remove preact and create setup wizard
This commit is contained in:
@@ -55,7 +55,34 @@ func NewService(repo *Repository, publicOrigin string) (*Service, error) {
|
||||
return &Service{repo: repo, webauthn: web, publicOrigin: publicOrigin}, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetInstanceSettings(ctx context.Context) (InstanceSettings, error) {
|
||||
return s.repo.GetInstanceSettings(ctx)
|
||||
}
|
||||
|
||||
func (s *Service) CompleteInitialSetup(ctx context.Context, email, displayName, password string, signupsEnabled bool) (User, error) {
|
||||
email = normalizeEmail(email)
|
||||
if email == "" {
|
||||
return User{}, fmt.Errorf("email is required")
|
||||
}
|
||||
if len(password) < 12 {
|
||||
return User{}, fmt.Errorf("password must be at least 12 characters")
|
||||
}
|
||||
passwordHash, err := hashPassword(password)
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
return s.repo.CompleteInitialSetup(ctx, User{
|
||||
Email: email,
|
||||
DisplayName: strings.TrimSpace(displayName),
|
||||
PasswordHash: passwordHash,
|
||||
Role: RoleAdmin,
|
||||
}, signupsEnabled)
|
||||
}
|
||||
|
||||
func (s *Service) RegisterPasswordUser(ctx context.Context, email, displayName, password, role string) (User, error) {
|
||||
if err := s.requirePublicSignups(ctx); err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
email = normalizeEmail(email)
|
||||
if email == "" {
|
||||
return User{}, fmt.Errorf("email is required")
|
||||
@@ -72,21 +99,11 @@ func (s *Service) RegisterPasswordUser(ctx context.Context, email, displayName,
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
userCount, err := s.repo.CountUsers(ctx)
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
normalizedRole := RoleViewer
|
||||
if userCount == 0 {
|
||||
normalizedRole = RoleAdmin
|
||||
} else if strings.EqualFold(role, string(RoleViewer)) {
|
||||
normalizedRole = RoleViewer
|
||||
}
|
||||
return s.repo.UpsertUser(ctx, User{
|
||||
Email: email,
|
||||
DisplayName: strings.TrimSpace(displayName),
|
||||
PasswordHash: passwordHash,
|
||||
Role: normalizedRole,
|
||||
Role: RoleViewer,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -113,23 +130,18 @@ func (s *Service) LoginPassword(ctx context.Context, email, password, ip, userAg
|
||||
}
|
||||
|
||||
func (s *Service) BeginPasskeyRegistration(ctx context.Context, email, displayName, role string) (any, string, error) {
|
||||
if err := s.requirePublicSignups(ctx); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
user, err := s.repo.GetUserByEmail(ctx, normalizeEmail(email))
|
||||
if err != nil {
|
||||
if !isNoRows(err) {
|
||||
return nil, "", err
|
||||
}
|
||||
userCount, err := s.repo.CountUsers(ctx)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
normalizedRole := RoleViewer
|
||||
if userCount == 0 {
|
||||
normalizedRole = RoleAdmin
|
||||
}
|
||||
user, err = s.repo.UpsertUser(ctx, User{
|
||||
Email: normalizeEmail(email),
|
||||
DisplayName: strings.TrimSpace(displayName),
|
||||
Role: normalizedRole,
|
||||
Role: RoleViewer,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
@@ -278,6 +290,43 @@ func (s *Service) ListUsers(ctx context.Context) ([]User, error) {
|
||||
return s.repo.ListUsers(ctx)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateSignupsEnabled(ctx context.Context, actor Principal, enabled bool) (InstanceSettings, error) {
|
||||
if !Allows(actor, ScopeAdmin) {
|
||||
return InstanceSettings{}, fmt.Errorf("admin role required")
|
||||
}
|
||||
if err := s.repo.UpdateSignupsEnabled(ctx, enabled); err != nil {
|
||||
return InstanceSettings{}, err
|
||||
}
|
||||
return s.repo.GetInstanceSettings(ctx)
|
||||
}
|
||||
|
||||
func (s *Service) EnsureDevUser(ctx context.Context) (User, error) {
|
||||
const email = "dev@localhost"
|
||||
settings, err := s.repo.GetInstanceSettings(ctx)
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
if !settings.SetupComplete {
|
||||
return s.CompleteInitialSetup(ctx, email, "Development Admin", "development-only-password", true)
|
||||
}
|
||||
user, err := s.repo.GetUserByEmail(ctx, email)
|
||||
if err == nil {
|
||||
return user, nil
|
||||
}
|
||||
if !isNoRows(err) {
|
||||
return User{}, err
|
||||
}
|
||||
return s.repo.UpsertUser(ctx, User{Email: email, DisplayName: "Development Admin", Role: RoleAdmin})
|
||||
}
|
||||
|
||||
func (s *Service) PrincipalForUser(ctx context.Context, userID string) (Principal, error) {
|
||||
user, err := s.repo.GetUserByID(ctx, userID)
|
||||
if err != nil {
|
||||
return Principal{}, err
|
||||
}
|
||||
return principalFromUser(user, "dev", "", "", nil, time.Time{}), nil
|
||||
}
|
||||
|
||||
func (s *Service) UpdateUserRole(ctx context.Context, actor Principal, userID, role string) (User, error) {
|
||||
if !Allows(actor, ScopeAdmin) {
|
||||
return User{}, fmt.Errorf("admin role required")
|
||||
@@ -453,6 +502,20 @@ func (s *Service) createSession(ctx context.Context, user User, ip, userAgent st
|
||||
return principalFromUser(user, "session", session.ID, "", nil, session.ExpiresAt), token, nil
|
||||
}
|
||||
|
||||
func (s *Service) requirePublicSignups(ctx context.Context) error {
|
||||
settings, err := s.repo.GetInstanceSettings(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !settings.SetupComplete {
|
||||
return fmt.Errorf("initial setup is required")
|
||||
}
|
||||
if !settings.SignupsEnabled {
|
||||
return fmt.Errorf("signups are disabled")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func principalFromUser(user User, method, sessionID, apiKeyID string, scopes []Scope, expiresAt time.Time) Principal {
|
||||
return Principal{
|
||||
UserID: user.ID,
|
||||
|
||||
Reference in New Issue
Block a user