mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-08-20 11:56:23 +00:00
89 lines
3.2 KiB
Go
89 lines
3.2 KiB
Go
package usersignup
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/italypaleale/francis/host/local"
|
|
"gorm.io/gorm"
|
|
|
|
"github.com/pocket-id/pocket-id/backend/internal/appconfig"
|
|
"github.com/pocket-id/pocket-id/backend/internal/dto"
|
|
"github.com/pocket-id/pocket-id/backend/internal/httpserver"
|
|
"github.com/pocket-id/pocket-id/backend/internal/model"
|
|
)
|
|
|
|
type TokenService interface {
|
|
GenerateAccessToken(user model.User, authenticationMethod string, sessionDuration time.Duration) (string, error)
|
|
}
|
|
|
|
type AuditLogger interface {
|
|
Create(ctx context.Context, event model.AuditLogEvent, ipAddress, userAgent, userID string, data model.AuditLogData, tx *gorm.DB) (model.AuditLog, bool)
|
|
}
|
|
|
|
type UserCreator interface {
|
|
CreateUserInternal(ctx context.Context, dbConfig *appconfig.AppConfigModel, input dto.UserCreateDto, isLdapSync bool, tx *gorm.DB) (model.User, error)
|
|
}
|
|
|
|
// ScimSyncScheduler schedules SCIM after the signup transaction has committed
|
|
type ScimSyncScheduler interface {
|
|
ScheduleSync(ctx context.Context)
|
|
}
|
|
|
|
type Dependencies struct {
|
|
DB *gorm.DB
|
|
Actors *local.Host
|
|
|
|
Signer TokenService
|
|
AuditLog AuditLogger
|
|
UserCreator UserCreator
|
|
AppConfig appconfig.AppConfigResolver
|
|
ScimSync ScimSyncScheduler
|
|
}
|
|
|
|
type Module struct {
|
|
service *Service
|
|
handler *handler
|
|
}
|
|
|
|
func New(deps Dependencies) (*Module, error) {
|
|
// Register the actor that manages a signup token
|
|
// Each token is its own actor, whose actor ID is the token's value
|
|
err := deps.Actors.RegisterActor(SignupTokenActorType, NewSignupTokenActor)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error registering the %s actor: %w", SignupTokenActorType, err)
|
|
}
|
|
|
|
service := newService(deps, deps.Actors.Service())
|
|
return &Module{
|
|
service: service,
|
|
handler: newHandler(service, deps.AppConfig),
|
|
}, nil
|
|
}
|
|
|
|
// RunSignupTokenMigration performs the one-time migration of the pre-actor signup tokens, then blocks until the context is canceled.
|
|
// It's meant to be started as a background service gated on the actor host being ready, since the migration needs the actor state store.
|
|
// Note that it must not return before the context is canceled, as the service runner stops the application as soon as any of its services returns.
|
|
func (m *Module) RunSignupTokenMigration(ctx context.Context) error {
|
|
err := m.service.migrateSignupTokens(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to migrate signup tokens: %w", err)
|
|
}
|
|
|
|
<-ctx.Done()
|
|
return ctx.Err()
|
|
}
|
|
|
|
// RegisterRoutes mounts the signup and signup-token management endpoints
|
|
// adminAuth guards the admin token-management routes; signupRateLimit throttles public self-signup
|
|
func (m *Module) RegisterRoutes(apiGroup *gin.RouterGroup, adminAuth, signupRateLimit gin.HandlerFunc) {
|
|
apiGroup.POST("/signup-tokens", adminAuth, httpserver.Handle(m.handler.createSignupToken))
|
|
apiGroup.GET("/signup-tokens", adminAuth, httpserver.Handle(m.handler.listSignupTokens))
|
|
apiGroup.DELETE("/signup-tokens/:id", adminAuth, httpserver.Handle(m.handler.deleteSignupToken))
|
|
apiGroup.POST("/signup", signupRateLimit, httpserver.Handle(m.handler.signup))
|
|
apiGroup.GET("/signup/setup", httpserver.Handle(m.handler.checkInitialAdminSetupAvailable))
|
|
apiGroup.POST("/signup/setup", httpserver.Handle(m.handler.signUpInitialAdmin))
|
|
}
|