edit: unique code shortlink ambil dari tabel shortcodes
This commit is contained in:
@@ -24,8 +24,8 @@ const (
|
||||
// DefaultMaxTries is the default number of login attempts allowed for a shortlink
|
||||
DefaultMaxTries = 5
|
||||
|
||||
// ShortTokenLength is the length of the generated short token
|
||||
ShortTokenLength = 8
|
||||
// ShortTokenLength is the length of the generated short token. 5 digit kapital semua
|
||||
ShortTokenLength = 5
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -36,6 +36,7 @@ var (
|
||||
ErrCreationFailed = errors.New("failed to create short link")
|
||||
ErrInvalidStudyUID = errors.New("invalid or missing StudyInstanceUID")
|
||||
ErrAdminRoleRequired = errors.New("admin role required to generate shortlinks")
|
||||
ErrNoShortcodes = errors.New("no unused shortcodes available")
|
||||
)
|
||||
|
||||
// ShortLinkService handles operations related to short links
|
||||
@@ -43,6 +44,7 @@ type ShortLinkService struct {
|
||||
jwtManager *auth.JWTManager
|
||||
logger *zap.Logger
|
||||
shortLinkRepo *repository.ShortLinkRepository
|
||||
shortCodeRepo *repository.ShortCodeRepository
|
||||
patientRepo *repository.PatientRepository
|
||||
// Configuration settings
|
||||
baseURL string
|
||||
@@ -69,6 +71,7 @@ func NewShortLinkService(jwtManager *auth.JWTManager, logger *zap.Logger, baseUR
|
||||
jwtManager: jwtManager,
|
||||
logger: logger,
|
||||
shortLinkRepo: repository.NewShortLinkRepository(),
|
||||
shortCodeRepo: repository.NewShortCodeRepository(),
|
||||
patientRepo: repository.NewPatientRepository(),
|
||||
baseURL: baseURL,
|
||||
defaultExpiryTime: time.Duration(defaultExpiryHours) * time.Hour,
|
||||
@@ -127,31 +130,10 @@ func (s *ShortLinkService) GenerateShortLink(req *models.GenerateShortLinkReques
|
||||
}
|
||||
expiresAt := time.Now().Add(expiresIn)
|
||||
|
||||
// Generate a secure random token
|
||||
token, err := generateSecureToken(ShortTokenLength)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to generate secure token", zap.Error(err))
|
||||
return nil, ErrCreationFailed
|
||||
}
|
||||
|
||||
// Hash the DOB for secure storage
|
||||
hashedDOB := hashDOB(dob)
|
||||
|
||||
// Create the short link record
|
||||
shortLink := &models.ShortLink{
|
||||
ID: generateID(),
|
||||
Token: token,
|
||||
PatientID: req.PatientID,
|
||||
StudyUID: req.StudyUID,
|
||||
HashedDOB: hashedDOB,
|
||||
ExpiresAt: expiresAt.Format(time.RFC3339),
|
||||
IsRevoked: false,
|
||||
CreatedAt: time.Now().Format(time.RFC3339),
|
||||
CreatedByID: creatorID,
|
||||
RemainingTries: s.maxAttempts,
|
||||
}
|
||||
|
||||
// Start a transaction for creating the shortlink
|
||||
// Start a transaction for creating the shortlink and updating the shortcode
|
||||
tx, err := database.DB.Beginx()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to start transaction", zap.Error(err))
|
||||
@@ -165,6 +147,31 @@ func (s *ShortLinkService) GenerateShortLink(req *models.GenerateShortLinkReques
|
||||
}
|
||||
}()
|
||||
|
||||
// Get an unused shortcode from the bank
|
||||
unusedShortcode, err := s.shortCodeRepo.GetUnusedShortCode()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get unused shortcode", zap.Error(err))
|
||||
return nil, ErrNoShortcodes
|
||||
}
|
||||
|
||||
if unusedShortcode == nil {
|
||||
s.logger.Error("No unused shortcodes available in the bank")
|
||||
return nil, ErrNoShortcodes
|
||||
}
|
||||
|
||||
// Create the short link record
|
||||
shortLink := &models.ShortLink{
|
||||
Token: *unusedShortcode,
|
||||
PatientID: req.PatientID,
|
||||
StudyUID: req.StudyUID,
|
||||
HashedDOB: hashedDOB,
|
||||
ExpiresAt: expiresAt.Format(time.RFC3339),
|
||||
IsRevoked: false,
|
||||
CreatedAt: time.Now().Format(time.RFC3339),
|
||||
CreatedByID: creatorID,
|
||||
RemainingTries: s.maxAttempts,
|
||||
}
|
||||
|
||||
// Store the short link in the database using transaction
|
||||
err = s.shortLinkRepo.CreateShortLinkTx(tx, shortLink)
|
||||
if err != nil {
|
||||
@@ -172,6 +179,21 @@ func (s *ShortLinkService) GenerateShortLink(req *models.GenerateShortLinkReques
|
||||
return nil, ErrCreationFailed
|
||||
}
|
||||
|
||||
// Get the ID of the created shortlink
|
||||
var shortlinkID int
|
||||
err = tx.Get(&shortlinkID, "SELECT ShortlinkID FROM shortlink WHERE ShortlinkCode = ?", shortLink.Token)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get shortlink ID", zap.Error(err))
|
||||
return nil, ErrCreationFailed
|
||||
}
|
||||
|
||||
// Mark the shortcode as used
|
||||
err = s.shortCodeRepo.MarkShortCodeAsUsed(tx, shortLink.Token, shortlinkID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to mark shortcode as used", zap.Error(err))
|
||||
return nil, ErrCreationFailed
|
||||
}
|
||||
|
||||
// Commit the transaction
|
||||
if err = tx.Commit(); err != nil {
|
||||
s.logger.Error("Failed to commit transaction", zap.Error(err))
|
||||
@@ -182,10 +204,10 @@ func (s *ShortLinkService) GenerateShortLink(req *models.GenerateShortLinkReques
|
||||
tx = nil
|
||||
|
||||
// Generate the full URL using the configured base URL
|
||||
fullURL := fmt.Sprintf("%s/short-auth?short=%s", s.baseURL, token)
|
||||
fullURL := fmt.Sprintf("%s/short-auth?short=%s", s.baseURL, shortLink.Token)
|
||||
|
||||
return &models.GenerateShortLinkResponse{
|
||||
ShortToken: token,
|
||||
ShortToken: shortLink.Token,
|
||||
FullURL: fullURL,
|
||||
ExpiresAt: shortLink.ExpiresAt,
|
||||
IsExisting: false,
|
||||
@@ -367,6 +389,21 @@ func (s *ShortLinkService) AuthenticateWithShortLink(req *models.ShortLinkAuthRe
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CleanupExpiredShortcodes checks for expired shortlinks and frees their shortcodes
|
||||
func (s *ShortLinkService) CleanupExpiredShortcodes() (int, error) {
|
||||
count, err := s.shortCodeRepo.MarkExpiredShortlinkShortcodesAsUnused()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to clean up expired shortcodes", zap.Error(err))
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
s.logger.Info("Freed shortcodes from expired shortlinks", zap.Int("count", count))
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
|
||||
// hashDOB creates a secure hash of a date of birth
|
||||
|
||||
Reference in New Issue
Block a user