Einladungscodes: registration_mode open|invite|closed, Admin-API /api/invites, App mit Code-Feld und Code-Verwaltung; v0.3.2

This commit is contained in:
OpenClaw Dev 2026-11-01 05:53:32 +01:00
parent d2658de099
commit cf5e0b1ca7
38 changed files with 665 additions and 25 deletions

View file

@ -26,12 +26,23 @@ func (u User) PasswordHash() string { return u.hash }
// CreateUser inserts a user. The first user ever created adopts all sessions
// that existed before accounts were introduced (user_id 0).
func (s *Store) CreateUser(ctx context.Context, username, passwordHash string) (User, error) {
return s.CreateUserWithInvite(ctx, username, passwordHash, "")
}
// CreateUserWithInvite creates a user and, if code is non-empty, consumes one
// use of that invite code in the same transaction (all or nothing).
func (s *Store) CreateUserWithInvite(ctx context.Context, username, passwordHash, code string) (User, error) {
now := time.Now().UTC()
tx, err := s.db.BeginTx(ctx, nil)
if err != nil {
return User{}, err
}
defer tx.Rollback()
if code != "" {
if err := consumeInvite(ctx, tx, code, now); err != nil {
return User{}, err
}
}
var n int
if err := tx.QueryRowContext(ctx, `SELECT COUNT(*) FROM users`).Scan(&n); err != nil {
return User{}, err
@ -44,6 +55,11 @@ func (s *Store) CreateUser(ctx context.Context, username, passwordHash string) (
return User{}, err
}
id, _ := res.LastInsertId()
if code != "" {
if _, err := tx.ExecContext(ctx, `INSERT INTO invite_uses(code,user_id,username,used_at) VALUES(?,?,?,?)`, code, id, username, now.UnixMilli()); err != nil {
return User{}, err
}
}
if n == 0 {
if _, err := tx.ExecContext(ctx, `UPDATE sessions SET user_id=? WHERE user_id=0`, id); err != nil {
return User{}, err