1
0
forked from baron/baron-sso

개발자 권한 신청 도메인 모델 및 서비스 레이어 구현

This commit is contained in:
2026-04-22 11:41:01 +09:00
parent b05700f7cc
commit 18e9a2aa4a
3 changed files with 99 additions and 0 deletions

View File

@@ -42,6 +42,7 @@ func migrateSchemas(db *gorm.DB) error {
&domain.ClientConsent{},
&domain.KetoOutbox{},
&domain.SharedLink{},
&domain.DeveloperRequest{},
// &domain.RelyingParty{}, // Removed: SSOT is Hydra + Keto
)
}

View File

@@ -0,0 +1,25 @@
package domain
import (
"time"
)
const (
DeveloperRequestStatusPending = "pending"
DeveloperRequestStatusApproved = "approved"
DeveloperRequestStatusRejected = "rejected"
)
// DeveloperRequest represents a user's application to become a developer.
type DeveloperRequest struct {
ID uint `gorm:"primaryKey" json:"id"`
UserID string `gorm:"index;not null" json:"userId"` // Kratos User ID
TenantID string `gorm:"index;not null" json:"tenantId"`
Name string `gorm:"not null" json:"name"`
Organization string `json:"organization"`
Reason string `json:"reason"`
Status string `gorm:"default:'pending';not null" json:"status"` // pending, approved, rejected
AdminNotes string `json:"adminNotes"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}

View File

@@ -0,0 +1,73 @@
package service
import (
"baron-sso-backend/internal/domain"
"context"
"errors"
"gorm.io/gorm"
)
type DeveloperService struct {
db *gorm.DB
}
func NewDeveloperService(db *gorm.DB) *DeveloperService {
return &DeveloperService{db: db}
}
func (s *DeveloperService) RequestAccess(ctx context.Context, req domain.DeveloperRequest) error {
// Check if there is already a pending request
var existing domain.DeveloperRequest
err := s.db.WithContext(ctx).Where("user_id = ? AND tenant_id = ? AND status = ?", req.UserID, req.TenantID, domain.DeveloperRequestStatusPending).First(&existing).Error
if err == nil {
return errors.New("already has a pending request")
}
return s.db.WithContext(ctx).Create(&req).Error
}
func (s *DeveloperService) GetRequestStatus(ctx context.Context, userID, tenantID string) (*domain.DeveloperRequest, error) {
var req domain.DeveloperRequest
err := s.db.WithContext(ctx).Where("user_id = ? AND tenant_id = ?", userID, tenantID).Order("created_at DESC").First(&req).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, err
}
return &req, nil
}
func (s *DeveloperService) GetRequestByID(ctx context.Context, id uint) (*domain.DeveloperRequest, error) {
var req domain.DeveloperRequest
err := s.db.WithContext(ctx).First(&req, id).Error
if err != nil {
return nil, err
}
return &req, nil
}
func (s *DeveloperService) ListRequests(ctx context.Context, status string) ([]domain.DeveloperRequest, error) {
var requests []domain.DeveloperRequest
query := s.db.WithContext(ctx)
if status != "" {
query = query.Where("status = ?", status)
}
err := query.Order("created_at DESC").Find(&requests).Error
return requests, err
}
func (s *DeveloperService) ApproveRequest(ctx context.Context, id uint, adminNotes string) error {
return s.db.WithContext(ctx).Model(&domain.DeveloperRequest{}).Where("id = ?", id).Updates(map[string]interface{}{
"status": domain.DeveloperRequestStatusApproved,
"admin_notes": adminNotes,
}).Error
}
func (s *DeveloperService) RejectRequest(ctx context.Context, id uint, adminNotes string) error {
return s.db.WithContext(ctx).Model(&domain.DeveloperRequest{}).Where("id = ?", id).Updates(map[string]interface{}{
"status": domain.DeveloperRequestStatusRejected,
"admin_notes": adminNotes,
}).Error
}