fix
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotCompanyOwner = errors.New("company owner required")
|
||||
ErrCannotRemoveOwner = errors.New("transfer ownership before removing the company owner")
|
||||
ErrTransferSelf = errors.New("user is already the company owner")
|
||||
ErrOwnerRequired = errors.New("new owner must be an active company member")
|
||||
)
|
||||
|
||||
// CompanyOwnerID returns the billing representative for the company, if set.
|
||||
func (s *Service) CompanyOwnerID(ctx context.Context, companyID uuid.UUID) (uuid.UUID, bool, error) {
|
||||
var owner *uuid.UUID
|
||||
err := s.Pool.QueryRow(ctx, `SELECT owner_user_id FROM companies WHERE id = $1`, companyID).Scan(&owner)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return uuid.Nil, false, ErrCompanyNotFound
|
||||
}
|
||||
if err != nil {
|
||||
return uuid.Nil, false, err
|
||||
}
|
||||
if owner == nil || *owner == uuid.Nil {
|
||||
return uuid.Nil, false, nil
|
||||
}
|
||||
return *owner, true, nil
|
||||
}
|
||||
|
||||
// IsCompanyOwner reports whether userID is the company's owner_user_id.
|
||||
func (s *Service) IsCompanyOwner(ctx context.Context, companyID, userID uuid.UUID) (bool, error) {
|
||||
ownerID, ok, err := s.CompanyOwnerID(ctx, companyID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return ok && ownerID == userID, nil
|
||||
}
|
||||
|
||||
// TransferOwnership sets a new company owner. The target must be an active member.
|
||||
// The new owner is promoted to membership admin so they retain team powers.
|
||||
func (s *Service) TransferOwnership(ctx context.Context, companyID, newOwnerID uuid.UUID) error {
|
||||
tx, err := s.Pool.Begin(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback(ctx)
|
||||
|
||||
var current *uuid.UUID
|
||||
err = tx.QueryRow(ctx, `SELECT owner_user_id FROM companies WHERE id = $1 FOR UPDATE`, companyID).Scan(¤t)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return ErrCompanyNotFound
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if current != nil && *current == newOwnerID {
|
||||
return ErrTransferSelf
|
||||
}
|
||||
|
||||
var status string
|
||||
err = tx.QueryRow(ctx, `
|
||||
SELECT status FROM memberships
|
||||
WHERE company_id = $1 AND user_id = $2`, companyID, newOwnerID).Scan(&status)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return ErrOwnerRequired
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if status != "active" {
|
||||
return ErrOwnerRequired
|
||||
}
|
||||
|
||||
_, err = tx.Exec(ctx, `
|
||||
UPDATE memberships
|
||||
SET role = 'admin', status = 'active', updated_at = now()
|
||||
WHERE company_id = $1 AND user_id = $2`, companyID, newOwnerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tag, err := tx.Exec(ctx, `
|
||||
UPDATE companies SET owner_user_id = $2, updated_at = now() WHERE id = $1`, companyID, newOwnerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tag.RowsAffected() == 0 {
|
||||
return ErrCompanyNotFound
|
||||
}
|
||||
return tx.Commit(ctx)
|
||||
}
|
||||
Reference in New Issue
Block a user