feat: add data access layer (repositories)

- Add user repository with CRUD operations and authentication methods
- Add session repository for session management and validation
- Add API key repository for API key management
- Include proper error handling and database transaction support
- Implement search and filtering capabilities
This commit is contained in:
Björn Benouarets
2025-09-25 23:24:28 +02:00
parent 4ee00d0b97
commit 6f4e929959
3 changed files with 222 additions and 0 deletions

32
repositories/api-key.go Normal file
View File

@@ -0,0 +1,32 @@
package repositories
import (
"git.secnex.io/secnex/idp-api/models"
"gorm.io/gorm"
)
type ApiKeyRepository struct {
db *gorm.DB
}
func NewApiKeyRepository(db *gorm.DB) *ApiKeyRepository {
return &ApiKeyRepository{db: db}
}
func (r *ApiKeyRepository) GetApiKeyByID(id string) (*models.ApiKey, error) {
var apiKey models.ApiKey
err := r.db.First(&apiKey, "id = ?", id).Error
if err != nil {
return nil, err
}
return &apiKey, nil
}
func (r *ApiKeyRepository) CreateApiKey(apiKey *models.ApiKey) (*models.ApiKey, error) {
// Create and return the api key and return the database object
result := r.db.Create(apiKey)
if result.Error != nil {
return nil, result.Error
}
return apiKey, nil
}

124
repositories/session.go Normal file
View File

@@ -0,0 +1,124 @@
package repositories
import (
"time"
"git.secnex.io/secnex/idp-api/models"
"gorm.io/gorm"
)
type SessionRepository struct {
db *gorm.DB
}
func NewSessionRepository(db *gorm.DB) *SessionRepository {
return &SessionRepository{db: db}
}
// CreateSession creates a new session
func (r *SessionRepository) CreateSession(session *models.Session) error {
return r.db.Create(session).Error
}
func (r *SessionRepository) GetSessionCount(user *string) (int64, error) {
var count int64
query := r.db
if user != nil && *user != "" {
query = query.Where("user_id = ?", *user)
}
err := query.Model(&models.Session{}).Count(&count).Error
return count, err
}
// GetSessions retrieves all sessions from the database with pagination
func (r *SessionRepository) GetSessions(page, limit int, user *string) ([]models.Session, error) {
var sessions []models.Session
query := r.db.Offset((page - 1) * limit).Limit(limit)
if user != nil && *user != "" {
query = query.Where("user_id = ?", *user)
}
err := query.Find(&sessions).Error
return sessions, err
}
// GetSessionByID retrieves a session by ID with optional preloading
func (r *SessionRepository) GetSessionByID(id string, preloadUser bool, preloadUserRelations ...string) (*models.Session, error) {
var session models.Session
query := r.db.Where("id = ? AND revoked = ? AND expires_at > ? AND logged_out = ?", id, false, time.Now(), false)
if preloadUser {
query = query.Preload("User")
// Preload additional user relations if specified
for _, relation := range preloadUserRelations {
query = query.Preload("User." + relation)
}
}
err := query.First(&session).Error
if err != nil {
return nil, err
}
return &session, nil
}
// GetSessionByUserID retrieves sessions by user ID with optional preloading
func (r *SessionRepository) GetSessionByUserID(userID string, preloadUser bool, preloadUserRelations ...string) ([]models.Session, error) {
var sessions []models.Session
query := r.db.Where("user_id = ?", userID)
if preloadUser {
query = query.Preload("User")
// Preload additional user relations if specified
for _, relation := range preloadUserRelations {
query = query.Preload("User." + relation)
}
}
err := query.Find(&sessions).Error
return sessions, err
}
// UpdateSession updates an existing session
func (r *SessionRepository) UpdateSession(session *models.Session) error {
return r.db.Save(session).Error
}
// DeleteSession deletes a session by ID
func (r *SessionRepository) DeleteSession(id string) error {
return r.db.Delete(&models.Session{}, "id = ?", id).Error
}
// RevokeSession revokes a session
func (r *SessionRepository) RevokeSession(id string) error {
return r.db.Model(&models.Session{}).Where("id = ?", id).Update("revoked", true).Error
}
// RevokeAllSessions revokes all sessions
func (r *SessionRepository) RevokeAllSessions() error {
return r.db.Model(&models.Session{}).Where("revoked = ?", false).Update("revoked", true).Error
}
// RevokeAllSessionsByUserID revokes all sessions for a user
func (r *SessionRepository) RevokeAllSessionsByUserID(userID string) error {
return r.db.Model(&models.Session{}).Where("user_id = ?", userID).Update("revoked", true).Error
}
// GetActiveSessionsByUserID gets all active (non-revoked) sessions for a user
func (r *SessionRepository) GetActiveSessionsByUserID(userID string, preloadUser bool) ([]models.Session, error) {
var sessions []models.Session
query := r.db.Where("user_id = ? AND revoked = ?", userID, false)
if preloadUser {
query = query.Preload("User")
}
err := query.Find(&sessions).Error
return sessions, err
}
// LogoutSessionByID logs out a session by ID
func (r *SessionRepository) LogoutSessionByID(id string) error {
return r.db.Model(&models.Session{}).Where("id = ?", id).Update("logged_out", true).Error
}

66
repositories/user.go Normal file
View File

@@ -0,0 +1,66 @@
package repositories
import (
"git.secnex.io/secnex/idp-api/models"
"gorm.io/gorm"
)
type UserRepository struct {
db *gorm.DB
}
func NewUserRepository(db *gorm.DB) *UserRepository {
return &UserRepository{db: db}
}
// GetAllUsers retrieves all users from the database
func (r *UserRepository) GetAllUsers() ([]models.User, error) {
var users []models.User
err := r.db.Find(&users).Error
return users, err
}
// GetUserByID retrieves a user by ID
func (r *UserRepository) GetUserByID(id string) (*models.User, error) {
var user models.User
err := r.db.First(&user, "id = ?", id).Error
if err != nil {
return nil, err
}
return &user, nil
}
// CreateUser creates a new user
func (r *UserRepository) CreateUser(user *models.User) error {
return r.db.Create(user).Error
}
// UpdateUser updates an existing user
func (r *UserRepository) UpdateUser(user *models.User) error {
return r.db.Save(user).Error
}
// DeleteUser deletes a user by ID
func (r *UserRepository) DeleteUser(id string) error {
return r.db.Delete(&models.User{}, "id = ?", id).Error
}
// GetUserByEmail retrieves a user by email
func (r *UserRepository) GetUserByEmail(email string) (*models.User, error) {
var user models.User
err := r.db.First(&user, "email = ?", email).Error
if err != nil {
return nil, err
}
return &user, nil
}
// GetUserByUsername retrieves a user by username
func (r *UserRepository) GetUserByUsername(username string) (*models.User, error) {
var user models.User
err := r.db.First(&user, "username = ?", username).Error
if err != nil {
return nil, err
}
return &user, nil
}