package apikeys import ( "context" "errors" "time" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" "gorm.io/gorm" ) type Repository interface { Create(ctx context.Context, record *entity.IntegrationAPIKey) error GetByEnvironmentAndPrefix(ctx context.Context, environment, prefix string) (*entity.IntegrationAPIKey, error) List(ctx context.Context, environment string) ([]entity.IntegrationAPIKey, error) Revoke(ctx context.Context, environment, prefix string, revokedAt time.Time) error TouchLastUsed(ctx context.Context, id uint, usedAt time.Time, usedFrom string) error } type repository struct { db *gorm.DB } func NewRepository(db *gorm.DB) Repository { return &repository{db: db} } func (r *repository) Create(ctx context.Context, record *entity.IntegrationAPIKey) error { if r.db == nil { return errors.New("database not configured") } return r.db.WithContext(ctx).Create(record).Error } func (r *repository) GetByEnvironmentAndPrefix(ctx context.Context, environment, prefix string) (*entity.IntegrationAPIKey, error) { if r.db == nil { return nil, errors.New("database not configured") } var record entity.IntegrationAPIKey if err := r.db.WithContext(ctx). Where("environment = ?", environment). Where("key_prefix = ?", prefix). First(&record).Error; err != nil { return nil, err } return &record, nil } func (r *repository) List(ctx context.Context, environment string) ([]entity.IntegrationAPIKey, error) { if r.db == nil { return nil, errors.New("database not configured") } query := r.db.WithContext(ctx).Model(&entity.IntegrationAPIKey{}) if environment != "" { query = query.Where("environment = ?", environment) } var records []entity.IntegrationAPIKey if err := query.Order("environment ASC").Order("name ASC").Find(&records).Error; err != nil { return nil, err } return records, nil } func (r *repository) Revoke(ctx context.Context, environment, prefix string, revokedAt time.Time) error { if r.db == nil { return errors.New("database not configured") } updates := map[string]any{ "status": entity.IntegrationAPIKeyStatusRevoked, "revoked_at": revokedAt, "updated_at": revokedAt, } result := r.db.WithContext(ctx). Model(&entity.IntegrationAPIKey{}). Where("environment = ?", environment). Where("key_prefix = ?", prefix). Updates(updates) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return gorm.ErrRecordNotFound } return nil } func (r *repository) TouchLastUsed(ctx context.Context, id uint, usedAt time.Time, usedFrom string) error { if r.db == nil { return errors.New("database not configured") } return r.db.WithContext(ctx). Model(&entity.IntegrationAPIKey{}). Where("id = ?", id). Updates(map[string]any{ "last_used_at": usedAt, "last_used_from": usedFrom, "updated_at": usedAt, }).Error }