// Copyright 2022 Harness Inc. All rights reserved. // Use of this source code is governed by the Polyform Free Trial License // that can be found in the LICENSE.md file for this repository. package space import ( "context" "fmt" "time" apiauth "github.com/harness/gitness/internal/api/auth" "github.com/harness/gitness/internal/api/usererror" "github.com/harness/gitness/internal/auth" "github.com/harness/gitness/internal/paths" "github.com/harness/gitness/types" "github.com/harness/gitness/types/check" "github.com/harness/gitness/types/enum" ) type CreateInput struct { ParentID int64 `json:"parentId"` UID string `json:"uid"` Description string `json:"description"` IsPublic bool `json:"isPublic"` } /* * Create creates a new space. */ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *CreateInput) (*types.Space, error) { // Collect parent path along the way - needed for duplicate error message parentPath := "" /* * AUTHORIZATION * Can only be done once we know the parent space */ if in.ParentID <= 0 { // TODO: Restrict top level space creation. if session == nil { return nil, usererror.ErrUnauthorized } } else { // Create is a special case - we need the parent path var parent *types.Space parent, err := c.spaceStore.Find(ctx, in.ParentID) if err != nil { return nil, fmt.Errorf("failed to get parent space: %w", err) } scope := &types.Scope{SpacePath: parent.Path} resource := &types.Resource{ Type: enum.ResourceTypeSpace, Name: "", } if err = apiauth.Check(ctx, c.authorizer, session, scope, resource, enum.PermissionSpaceCreate); err != nil { return nil, err } parentPath = parent.Path } // create new space object space := &types.Space{ ParentID: in.ParentID, UID: in.UID, Description: in.Description, IsPublic: in.IsPublic, CreatedBy: session.Principal.ID, Created: time.Now().UnixMilli(), Updated: time.Now().UnixMilli(), } // validate space if err := c.spaceCheck(space); err != nil { return nil, err } // Validate path depth (Due to racing conditions we can't be 100% sure on the path here only best effort // to have a quick failure) path := paths.Concatinate(parentPath, space.UID) if err := check.PathDepth(path, true); err != nil { return nil, err } // create in store err := c.spaceStore.Create(ctx, space) if err != nil { return nil, fmt.Errorf("space creation failed: %w", err) } return space, nil }