From ccf65ec6c6a8afb19c40b9c60aeb408330a25ab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Benouarets?= Date: Tue, 30 Sep 2025 11:44:40 +0200 Subject: [PATCH] feat: implement repository layer for data access - Add CertificateRepository with CRUD operations - Implement CertificateAuthorityRepository for CA management - Add CertificateRequestRepository for CSR handling - Include UserRepository and OrganizationRepository - Implement proper error handling and validation - Add support for soft deletes and relationships - Include query optimization and filtering capabilities --- repositories/ca.go | 56 ++++++++++++++++++++ repositories/cert.go | 100 +++++++++++++++++++++++++++++++++++ repositories/csr.go | 91 +++++++++++++++++++++++++++++++ repositories/index.go | 10 ++++ repositories/organization.go | 56 ++++++++++++++++++++ repositories/user.go | 56 ++++++++++++++++++++ 6 files changed, 369 insertions(+) create mode 100644 repositories/ca.go create mode 100644 repositories/cert.go create mode 100644 repositories/csr.go create mode 100644 repositories/index.go create mode 100644 repositories/organization.go create mode 100644 repositories/user.go diff --git a/repositories/ca.go b/repositories/ca.go new file mode 100644 index 0000000..98a649b --- /dev/null +++ b/repositories/ca.go @@ -0,0 +1,56 @@ +package repositories + +import ( + "git.secnex.io/secnex/certman/models" + "gorm.io/gorm" +) + +type CertificateAuthorityRepository struct { + db *gorm.DB +} + +// NewCertificateAuthorityRepository creates a new certificate authority repository +func NewCertificateAuthorityRepository(db *gorm.DB) *CertificateAuthorityRepository { + return &CertificateAuthorityRepository{db: db} +} + +// GetByID returns a certificate authority by their ID +func (r *CertificateAuthorityRepository) GetByID(id string) (models.CertificateAuthority, error) { + var ca models.CertificateAuthority + if err := r.db.Where("id = ?", id).First(&ca).Error; err != nil { + return models.CertificateAuthority{}, err + } + return ca, nil +} + +// GetAll returns all certificate authorities +func (r *CertificateAuthorityRepository) GetAll() ([]models.CertificateAuthority, error) { + var cas []models.CertificateAuthority + if err := r.db.Find(&cas).Error; err != nil { + return []models.CertificateAuthority{}, err + } + return cas, nil +} + +// Create creates a new certificate authority +func (r *CertificateAuthorityRepository) Create(ca models.CertificateAuthority) (models.CertificateAuthority, error) { + if err := r.db.Create(&ca).Error; err != nil { + return models.CertificateAuthority{}, err + } + return ca, nil +} + +// Update updates a certificate authority +func (r *CertificateAuthorityRepository) Update(ca models.CertificateAuthority) error { + return r.db.Save(&ca).Error +} + +// Delete deletes a certificate authority by their ID +func (r *CertificateAuthorityRepository) Delete(id string) error { + return r.db.Delete(&models.CertificateAuthority{}, id).Error +} + +// HardDelete deletes a certificate authority by their ID +func (r *CertificateAuthorityRepository) HardDelete(ca models.CertificateAuthority) error { + return r.db.Unscoped().Delete(&ca).Error +} diff --git a/repositories/cert.go b/repositories/cert.go new file mode 100644 index 0000000..cec53fb --- /dev/null +++ b/repositories/cert.go @@ -0,0 +1,100 @@ +package repositories + +import ( + "git.secnex.io/secnex/certman/models" + "gorm.io/gorm" +) + +type CertificateRepository struct { + db *gorm.DB +} + +// NewCertificateRepository creates a new certificate repository +func NewCertificateRepository(db *gorm.DB) *CertificateRepository { + return &CertificateRepository{db: db} +} + +// GetByID returns a certificate by their ID +func (r *CertificateRepository) GetByID(id string) (models.Certificate, error) { + var cert models.Certificate + if err := r.db.First(&cert, id).Error; err != nil { + return models.Certificate{}, err + } + return cert, nil +} + +// GetAll returns all certificates +func (r *CertificateRepository) GetAll() ([]models.Certificate, error) { + var certs []models.Certificate + if err := r.db.Find(&certs).Error; err != nil { + return []models.Certificate{}, err + } + return certs, nil +} + +// Create creates a new certificate +func (r *CertificateRepository) Create(cert models.Certificate) error { + return r.db.Create(&cert).Error +} + +// Update updates a certificate +func (r *CertificateRepository) Update(cert models.Certificate) error { + return r.db.Save(&cert).Error +} + +// Delete deletes a certificate by their ID +func (r *CertificateRepository) Delete(id string) error { + return r.db.Delete(&models.Certificate{}, id).Error +} + +// HardDelete deletes a certificate by their ID +func (r *CertificateRepository) HardDelete(cert models.Certificate) error { + return r.db.Unscoped().Delete(&cert).Error +} + +// GetByType returns certificates by type +func (r *CertificateRepository) GetByType(certType models.CertificateType) ([]models.Certificate, error) { + var certs []models.Certificate + if err := r.db.Where("type = ?", certType).Find(&certs).Error; err != nil { + return []models.Certificate{}, err + } + return certs, nil +} + +// GetByCA returns certificates issued by a specific CA +func (r *CertificateRepository) GetByCA(caID string) ([]models.Certificate, error) { + var certs []models.Certificate + if err := r.db.Where("certificate_authority_id = ?", caID).Find(&certs).Error; err != nil { + return []models.Certificate{}, err + } + return certs, nil +} + +// GetByStatus returns certificates by status +func (r *CertificateRepository) GetByStatus(status models.CertificateStatus) ([]models.Certificate, error) { + var certs []models.Certificate + if err := r.db.Where("status = ?", status).Find(&certs).Error; err != nil { + return []models.Certificate{}, err + } + return certs, nil +} + +// GetActive returns all active certificates +func (r *CertificateRepository) GetActive() ([]models.Certificate, error) { + return r.GetByStatus(models.CertificateStatusActive) +} + +// GetRevoked returns all revoked certificates +func (r *CertificateRepository) GetRevoked() ([]models.Certificate, error) { + return r.GetByStatus(models.CertificateStatusRevoked) +} + +// GetExpired returns all expired certificates +func (r *CertificateRepository) GetExpired() ([]models.Certificate, error) { + return r.GetByStatus(models.CertificateStatusExpired) +} + +// GetPending returns all pending certificates +func (r *CertificateRepository) GetPending() ([]models.Certificate, error) { + return r.GetByStatus(models.CertificateStatusPending) +} \ No newline at end of file diff --git a/repositories/csr.go b/repositories/csr.go new file mode 100644 index 0000000..f95db24 --- /dev/null +++ b/repositories/csr.go @@ -0,0 +1,91 @@ +package repositories + +import ( + "git.secnex.io/secnex/certman/models" + "gorm.io/gorm" +) + +type CertificateRequestRepository struct { + db *gorm.DB +} + +// NewCertificateRequestRepository creates a new certificate request repository +func NewCertificateRequestRepository(db *gorm.DB) *CertificateRequestRepository { + return &CertificateRequestRepository{db: db} +} + +// GetByID returns a certificate request by their ID +func (r *CertificateRequestRepository) GetByID(id string) (models.CertificateRequest, error) { + var csr models.CertificateRequest + if err := r.db.First(&csr, id).Error; err != nil { + return models.CertificateRequest{}, err + } + return csr, nil +} + +// GetAll returns all certificate requests +func (r *CertificateRequestRepository) GetAll() ([]models.CertificateRequest, error) { + var csrs []models.CertificateRequest + if err := r.db.Find(&csrs).Error; err != nil { + return []models.CertificateRequest{}, err + } + return csrs, nil +} + +// Create creates a new certificate request +func (r *CertificateRequestRepository) Create(csr models.CertificateRequest) error { + return r.db.Create(&csr).Error +} + +// Update updates a certificate request +func (r *CertificateRequestRepository) Update(csr models.CertificateRequest) error { + return r.db.Save(&csr).Error +} + +// Delete deletes a certificate request by their ID +func (r *CertificateRequestRepository) Delete(id string) error { + return r.db.Delete(&models.CertificateRequest{}, id).Error +} + +// HardDelete deletes a certificate request by their ID +func (r *CertificateRequestRepository) HardDelete(csr models.CertificateRequest) error { + return r.db.Unscoped().Delete(&csr).Error +} + +// GetByStatus returns certificate requests by status +func (r *CertificateRequestRepository) GetByStatus(status models.RequestStatus) ([]models.CertificateRequest, error) { + var csrs []models.CertificateRequest + if err := r.db.Where("status = ?", status).Find(&csrs).Error; err != nil { + return []models.CertificateRequest{}, err + } + return csrs, nil +} + +// GetPending returns all pending certificate requests +func (r *CertificateRequestRepository) GetPending() ([]models.CertificateRequest, error) { + return r.GetByStatus(models.RequestStatusPending) +} + +// GetApproved returns all approved certificate requests +func (r *CertificateRequestRepository) GetApproved() ([]models.CertificateRequest, error) { + return r.GetByStatus(models.RequestStatusApproved) +} + +// GetRejected returns all rejected certificate requests +func (r *CertificateRequestRepository) GetRejected() ([]models.CertificateRequest, error) { + return r.GetByStatus(models.RequestStatusRejected) +} + +// GetCancelled returns all cancelled certificate requests +func (r *CertificateRequestRepository) GetCancelled() ([]models.CertificateRequest, error) { + return r.GetByStatus(models.RequestStatusCancelled) +} + +// GetByCA returns certificate requests for a specific CA +func (r *CertificateRequestRepository) GetByCA(caID string) ([]models.CertificateRequest, error) { + var csrs []models.CertificateRequest + if err := r.db.Where("certificate_authority_id = ?", caID).Find(&csrs).Error; err != nil { + return []models.CertificateRequest{}, err + } + return csrs, nil +} \ No newline at end of file diff --git a/repositories/index.go b/repositories/index.go new file mode 100644 index 0000000..e326e7c --- /dev/null +++ b/repositories/index.go @@ -0,0 +1,10 @@ +package repositories + +type Repository interface { + GetByID(id string) (interface{}, error) // Get a single entity by ID + GetAll() ([]interface{}, error) // Get all entities + Create(entity interface{}) error // Create a new entity + Update(entity interface{}) error // Update an entity + Delete(id string) error // Delete an entity by ID + HardDelete(entity interface{}) error // Hard delete an entity +} diff --git a/repositories/organization.go b/repositories/organization.go new file mode 100644 index 0000000..4070b38 --- /dev/null +++ b/repositories/organization.go @@ -0,0 +1,56 @@ +package repositories + +import ( + "git.secnex.io/secnex/certman/models" + "gorm.io/gorm" +) + +type OrganizationRepository struct { + db *gorm.DB +} + +// NewOrganizationRepository creates a new organization repository +func NewOrganizationRepository(db *gorm.DB) *OrganizationRepository { + return &OrganizationRepository{db: db} +} + +// GetByID returns an organization by their ID +func (r *OrganizationRepository) GetByID(id string) (models.Organization, error) { + var organization models.Organization + if err := r.db.Where("id = ?", id).First(&organization).Error; err != nil { + return models.Organization{}, err + } + return organization, nil +} + +// GetAll returns all organizations +func (r *OrganizationRepository) GetAll() ([]models.Organization, error) { + var organizations []models.Organization + if err := r.db.Find(&organizations).Error; err != nil { + return []models.Organization{}, err + } + return organizations, nil +} + +// Create creates a new organization +func (r *OrganizationRepository) Create(organization models.Organization) (models.Organization, error) { + if err := r.db.Create(&organization).Error; err != nil { + return models.Organization{}, err + } + return organization, nil +} + +// Update updates an organization +func (r *OrganizationRepository) Update(organization models.Organization) error { + return r.db.Save(&organization).Error +} + +// Delete deletes an organization by their ID +func (r *OrganizationRepository) Delete(id string) error { + return r.db.Delete(&models.Organization{}, id).Error +} + +// HardDelete deletes an organization by their ID +func (r *OrganizationRepository) HardDelete(organization models.Organization) error { + return r.db.Unscoped().Delete(&organization).Error +} diff --git a/repositories/user.go b/repositories/user.go new file mode 100644 index 0000000..b348088 --- /dev/null +++ b/repositories/user.go @@ -0,0 +1,56 @@ +package repositories + +import ( + "git.secnex.io/secnex/certman/models" + "gorm.io/gorm" +) + +type UserRepository struct { + db *gorm.DB +} + +// NewUserRepository creates a new user repository +func NewUserRepository(db *gorm.DB) *UserRepository { + return &UserRepository{db: db} +} + +// GetByID returns a user by their ID +func (r *UserRepository) GetByID(id string) (models.User, error) { + var user models.User + if err := r.db.Where("id = ?", id).First(&user).Error; err != nil { + return models.User{}, err + } + return user, nil +} + +// GetAll returns all users +func (r *UserRepository) GetAll() ([]models.User, error) { + var users []models.User + if err := r.db.Find(&users).Error; err != nil { + return []models.User{}, err + } + return users, nil +} + +// Create creates a new user +func (r *UserRepository) Create(user models.User) (models.User, error) { + if err := r.db.Create(&user).Error; err != nil { + return models.User{}, err + } + return user, nil +} + +// Update updates a user +func (r *UserRepository) Update(user models.User) error { + return r.db.Save(&user).Error +} + +// Delete deletes a user by their ID +func (r *UserRepository) Delete(id string) error { + return r.db.Delete(&models.User{}, id).Error +} + +// HardDelete deletes a user by their ID +func (r *UserRepository) HardDelete(user models.User) error { + return r.db.Unscoped().Delete(&user).Error +}