Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions apps/api/internal/service/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,9 @@ func (s *WorkspaceService) Create(ctx context.Context, name, slug, organizationS
CreatedByID: &ownerID,
OrganizationSize: orgSize,
}
if err := s.ws.Create(ctx, w); err != nil {
if err := s.ws.CreateWithOwner(ctx, w, ownerID); err != nil {
return nil, err
}
m := &model.WorkspaceMember{WorkspaceID: w.ID, MemberID: ownerID, Role: 20}
_ = s.ws.AddMember(ctx, m)
return w, nil
}

Expand Down
17 changes: 17 additions & 0 deletions apps/api/internal/store/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,23 @@ func (s *WorkspaceStore) Create(ctx context.Context, w *model.Workspace) error {
return s.db.WithContext(ctx).Create(w).Error
}

// CreateWithOwner inserts a workspace and its owner membership in one
// transaction. Without this, a failed membership insert would leave a workspace
// with no members, and since access is gated on membership the owner would be
// locked out of the workspace they just created.
func (s *WorkspaceStore) CreateWithOwner(ctx context.Context, w *model.Workspace, ownerID uuid.UUID) error {
return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
if err := tx.Create(w).Error; err != nil {
return err
}
return tx.Create(&model.WorkspaceMember{
WorkspaceID: w.ID,
MemberID: ownerID,
Role: model.RoleOwner,
}).Error
})
}

func (s *WorkspaceStore) GetByID(ctx context.Context, id uuid.UUID) (*model.Workspace, error) {
var w model.Workspace
err := s.db.WithContext(ctx).Where("id = ? AND deleted_at IS NULL", id).First(&w).Error
Expand Down
Loading