This commit is contained in:
@@ -28,6 +28,7 @@ var (
|
||||
ErrPersonalOrganization = errors.New("organizations: personal organization lifecycle is fixed")
|
||||
ErrLastOwner = errors.New("organizations: the last active direct owner must be preserved")
|
||||
ErrOwnerAuthority = errors.New("organizations: a current direct owner must manage owner access")
|
||||
ErrOwnedCreationUnsupported = errors.New("organizations: atomic owned organization creation is unsupported")
|
||||
slugPattern = regexp.MustCompile(`^[a-z0-9][a-z0-9-]{1,62}$`)
|
||||
idPattern = regexp.MustCompile(`^[A-Za-z0-9_-]{8,128}$`)
|
||||
)
|
||||
@@ -156,22 +157,11 @@ func New(repository Repository, options Options) (*Service, error) {
|
||||
type CreateOrganization struct {
|
||||
Slug, Name, OwnerUserID string
|
||||
Personal bool
|
||||
RequestID string
|
||||
}
|
||||
|
||||
func (service *Service) CreateOrganization(ctx context.Context, input CreateOrganization) (Organization, error) {
|
||||
input.Slug = strings.ToLower(strings.TrimSpace(input.Slug))
|
||||
input.Name = strings.TrimSpace(input.Name)
|
||||
if !slugPattern.MatchString(input.Slug) || !bounded(input.Name, 128) || !idPattern.MatchString(input.OwnerUserID) {
|
||||
return Organization{}, errors.New("organizations: invalid organization")
|
||||
}
|
||||
id, err := token(service.random, 18)
|
||||
if err != nil {
|
||||
return Organization{}, err
|
||||
}
|
||||
now := service.now().UTC()
|
||||
organization := Organization{ID: id, Slug: input.Slug, Name: input.Name, Status: "active", Personal: input.Personal, Revision: 1, CreatedAt: now, UpdatedAt: now}
|
||||
owner := Membership{OrganizationID: id, UserID: input.OwnerUserID, Status: "active", JoinedAt: now}
|
||||
audit, err := service.audit(input.OwnerUserID, id, "organization.create", "organization", id, "Organization created")
|
||||
organization, owner, audit, err := service.prepareOrganization(input)
|
||||
if err != nil {
|
||||
return Organization{}, err
|
||||
}
|
||||
@@ -181,6 +171,26 @@ func (service *Service) CreateOrganization(ctx context.Context, input CreateOrga
|
||||
return organization, nil
|
||||
}
|
||||
|
||||
func (service *Service) prepareOrganization(input CreateOrganization) (Organization, Membership, AuditEvent, error) {
|
||||
input.Slug = strings.ToLower(strings.TrimSpace(input.Slug))
|
||||
input.Name = strings.TrimSpace(input.Name)
|
||||
if !slugPattern.MatchString(input.Slug) || !bounded(input.Name, 128) || !idPattern.MatchString(input.OwnerUserID) || !boundedOptional(input.RequestID, 128) {
|
||||
return Organization{}, Membership{}, AuditEvent{}, errors.New("organizations: invalid organization")
|
||||
}
|
||||
id, err := token(service.random, 18)
|
||||
if err != nil {
|
||||
return Organization{}, Membership{}, AuditEvent{}, err
|
||||
}
|
||||
now := service.now().UTC()
|
||||
organization := Organization{ID: id, Slug: input.Slug, Name: input.Name, Status: "active", Personal: input.Personal, Revision: 1, CreatedAt: now, UpdatedAt: now}
|
||||
owner := Membership{OrganizationID: id, UserID: input.OwnerUserID, Status: "active", JoinedAt: now}
|
||||
audit, err := service.auditWithRequest(input.OwnerUserID, id, "organization.create", "organization", id, input.RequestID, "Organization created")
|
||||
if err != nil {
|
||||
return Organization{}, Membership{}, AuditEvent{}, err
|
||||
}
|
||||
return organization, owner, audit, nil
|
||||
}
|
||||
|
||||
func (service *Service) CreatePersonalOrganization(ctx context.Context, userID, displayName string) (Organization, error) {
|
||||
value := make([]byte, 6)
|
||||
if _, err := io.ReadFull(service.random, value); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user