84 lines
2.3 KiB
Go
84 lines
2.3 KiB
Go
package auth
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"errors"
|
||
|
|
"strings"
|
||
|
|
|
||
|
|
"github.com/google/uuid"
|
||
|
|
"github.com/jackc/pgx/v5"
|
||
|
|
)
|
||
|
|
|
||
|
|
// defaultOwnedCompanyName builds a workspace name when invite accept creates a personal company.
|
||
|
|
func defaultOwnedCompanyName(email, name string) string {
|
||
|
|
name = strings.TrimSpace(name)
|
||
|
|
if name != "" {
|
||
|
|
return name + "'s workspace"
|
||
|
|
}
|
||
|
|
email = strings.ToLower(strings.TrimSpace(email))
|
||
|
|
local := email
|
||
|
|
if at := strings.IndexByte(email, '@'); at > 0 {
|
||
|
|
local = email[:at]
|
||
|
|
}
|
||
|
|
local = strings.TrimSpace(local)
|
||
|
|
if local == "" {
|
||
|
|
return "My workspace"
|
||
|
|
}
|
||
|
|
return local + "'s workspace"
|
||
|
|
}
|
||
|
|
|
||
|
|
// ensureOwnedCompanyTx returns the user's owned company, creating one (admin membership +
|
||
|
|
// settings + credit wallet) when they do not already own a tenant.
|
||
|
|
func ensureOwnedCompanyTx(ctx context.Context, tx pgx.Tx, userID uuid.UUID, companyName string) (uuid.UUID, bool, error) {
|
||
|
|
var existing uuid.UUID
|
||
|
|
err := tx.QueryRow(ctx, `
|
||
|
|
SELECT id FROM companies WHERE owner_user_id = $1
|
||
|
|
ORDER BY created_at ASC
|
||
|
|
LIMIT 1`, userID).Scan(&existing)
|
||
|
|
if err == nil {
|
||
|
|
_, merr := tx.Exec(ctx, `
|
||
|
|
INSERT INTO memberships (company_id, user_id, role, status)
|
||
|
|
VALUES ($1, $2, 'admin', 'active')
|
||
|
|
ON CONFLICT (company_id, user_id) DO UPDATE
|
||
|
|
SET status = 'active',
|
||
|
|
role = 'admin',
|
||
|
|
updated_at = now()`, existing, userID)
|
||
|
|
return existing, false, merr
|
||
|
|
}
|
||
|
|
if !errors.Is(err, pgx.ErrNoRows) {
|
||
|
|
return uuid.Nil, false, err
|
||
|
|
}
|
||
|
|
|
||
|
|
companyName = strings.TrimSpace(companyName)
|
||
|
|
if companyName == "" {
|
||
|
|
companyName = "My workspace"
|
||
|
|
}
|
||
|
|
|
||
|
|
var companyID uuid.UUID
|
||
|
|
err = tx.QueryRow(ctx, `
|
||
|
|
INSERT INTO companies (name, owner_user_id) VALUES ($1, $2) RETURNING id`,
|
||
|
|
companyName, userID).Scan(&companyID)
|
||
|
|
if err != nil {
|
||
|
|
return uuid.Nil, false, err
|
||
|
|
}
|
||
|
|
_, err = tx.Exec(ctx, `
|
||
|
|
INSERT INTO memberships (company_id, user_id, role, status)
|
||
|
|
VALUES ($1, $2, 'admin', 'active')`, companyID, userID)
|
||
|
|
if err != nil {
|
||
|
|
return uuid.Nil, false, err
|
||
|
|
}
|
||
|
|
_, err = tx.Exec(ctx, `
|
||
|
|
INSERT INTO company_settings (company_id) VALUES ($1)
|
||
|
|
ON CONFLICT DO NOTHING`, companyID)
|
||
|
|
if err != nil {
|
||
|
|
return uuid.Nil, false, err
|
||
|
|
}
|
||
|
|
_, err = tx.Exec(ctx, `
|
||
|
|
INSERT INTO credit_balances (company_id) VALUES ($1)
|
||
|
|
ON CONFLICT DO NOTHING`, companyID)
|
||
|
|
if err != nil {
|
||
|
|
return uuid.Nil, false, err
|
||
|
|
}
|
||
|
|
return companyID, true, nil
|
||
|
|
}
|