package services import ( "database/sql" "errors" "git.jamestombleson.com/jtom38/go-cook/internal/domain" "git.jamestombleson.com/jtom38/go-cook/internal/repositories" "github.com/google/uuid" ) const ( ErrUnexpectedAmountOfRowsUpdated = "got a unexpected of rows updated" ) type RefreshToken interface { Create(username string) (string, error) GetByName(name string) (domain.RefreshTokenEntity, error) Delete(id int64) (int64, error) IsRequestValid(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 repositories.RefreshTokenTable } func NewRefreshTokenService(conn *sql.DB) RefreshTokenService { return RefreshTokenService{ table: repositories.NewRefreshTokenRepository(conn), } } func (rt RefreshTokenService) Create(username string) (string, error) { //if a refresh token already exists for a user, reuse existingToken, err := rt.GetByName(username) if err == nil { rowsRemoved, err := rt.Delete(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(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(name string) (domain.RefreshTokenEntity, error) { return rt.table.GetByUsername(name) } // This will request that a object is removed from the database func (rt RefreshTokenService) Delete(id int64) (int64, error) { return rt.table.DeleteById(id) } func (rt RefreshTokenService) IsRequestValid(username, refreshToken string) error { token, err := rt.GetByName(username) if err != nil { return err } if token.Token != refreshToken { return errors.New("the refresh token given does not match") } return nil }