package repositoryservices import ( "context" "database/sql" "errors" "git.jamestombleson.com/jtom38/newsbot-api/internal/entity" "git.jamestombleson.com/jtom38/newsbot-api/internal/repository" "github.com/google/uuid" ) const ( ErrUnexpectedAmountOfRowsUpdated = "got a unexpected of rows updated" ) type RefreshToken interface { Create(ctx context.Context, username string) (string, error) GetByName(ctx context.Context, name string) (entity.RefreshTokenEntity, error) Delete(ctx context.Context, id int64) (int64, error) IsRequestValid(ctx context.Context, username, refreshToken string) error } // A new jwt token can be made if the user has the correct refresh token for the user. // It will also require the old JWT token so the expire time is pulled and part of the validation type RefreshTokenService struct { table repository.RefreshTokenRepository } func NewRefreshTokenService(conn *sql.DB) RefreshTokenService { return RefreshTokenService{ table: repository.NewRefreshTokenRepository(conn), } } func (rt RefreshTokenService) Create(ctx context.Context, username string) (string, error) { //if a refresh token already exists for a user, reuse existingToken, err := rt.GetByName(ctx, username) if err == nil { rowsRemoved, err := rt.Delete(ctx, existingToken.ID) if err != nil { return "", err } if rowsRemoved != 1 { return "", errors.New(ErrUnexpectedAmountOfRowsUpdated) } } token, err := uuid.NewV7() if err != nil { return "", err } rows, err := rt.table.Create(ctx, username, token.String()) if err != nil { return "", err } if rows != 1 { return "", errors.New("expected one row but got none") } return token.String(), nil } // Find the saved refresh token for a user and return it if it exists func (rt RefreshTokenService) GetByName(ctx context.Context, name string) (entity.RefreshTokenEntity, error) { return rt.table.GetByUsername(ctx, name) } // This will request that a object is removed from the database func (rt RefreshTokenService) Delete(ctx context.Context, id int64) (int64, error) { return rt.table.DeleteById(ctx, id) } func (rt RefreshTokenService) IsRequestValid(ctx context.Context, username, refreshToken string) error { token, err := rt.GetByName(ctx, username) if err != nil { return err } if token.Token != refreshToken { return errors.New("the refresh token given does not match") } return nil }