|
|
|
|
@ -254,20 +254,19 @@ func (r *Repository) CreateAppToken(ctx context.Context, token *AppToken) (*AppT
|
|
|
|
|
// each inner slice contains items of the same type (appTokenPermissionGlobal, for example)
|
|
|
|
|
// to be batch inserted using CreateItems
|
|
|
|
|
var dbInserts []interface{}
|
|
|
|
|
var createdToken appTokenSubtype
|
|
|
|
|
switch {
|
|
|
|
|
case strings.HasPrefix(token.GetScopeId(), globals.GlobalPrefix):
|
|
|
|
|
createdToken, dbInserts, err = createAppTokenGlobal(ctx, token)
|
|
|
|
|
dbInserts, err = createAppTokenGlobal(ctx, token)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, errors.Wrap(ctx, err, op)
|
|
|
|
|
}
|
|
|
|
|
case strings.HasPrefix(token.GetScopeId(), globals.OrgPrefix):
|
|
|
|
|
createdToken, dbInserts, err = createAppTokenOrg(ctx, token)
|
|
|
|
|
dbInserts, err = createAppTokenOrg(ctx, token)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, errors.Wrap(ctx, err, op)
|
|
|
|
|
}
|
|
|
|
|
case strings.HasPrefix(token.GetScopeId(), globals.ProjectPrefix):
|
|
|
|
|
createdToken, dbInserts, err = createAppTokenProject(ctx, token)
|
|
|
|
|
dbInserts, err = createAppTokenProject(ctx, token)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, errors.Wrap(ctx, err, op)
|
|
|
|
|
}
|
|
|
|
|
@ -295,34 +294,33 @@ func (r *Repository) CreateAppToken(ctx context.Context, token *AppToken) (*AppT
|
|
|
|
|
dbInserts = append(dbInserts, []*appTokenCipher{atc})
|
|
|
|
|
|
|
|
|
|
// batch write all collected inserts
|
|
|
|
|
var newAppToken *AppToken
|
|
|
|
|
_, err = r.writer.DoTx(
|
|
|
|
|
ctx,
|
|
|
|
|
db.StdRetryCnt,
|
|
|
|
|
db.ExpBackoff{},
|
|
|
|
|
func(_ db.Reader, w db.Writer) error {
|
|
|
|
|
func(reader db.Reader, writer db.Writer) error {
|
|
|
|
|
for _, appTokenItems := range dbInserts {
|
|
|
|
|
if err := w.CreateItems(ctx, appTokenItems); err != nil {
|
|
|
|
|
if err := writer.CreateItems(ctx, appTokenItems); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Do a fresh lookup to get all return values
|
|
|
|
|
newAppToken, err = r.LookupAppToken(ctx, id, WithReaderWriter(reader, writer))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return errors.Wrap(ctx, err, op)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("creating app token in database"))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newAppToken := createdToken.toAppToken()
|
|
|
|
|
if newAppToken == nil {
|
|
|
|
|
return nil, errors.New(ctx, errors.Internal, op, "failed to convert created app token to domain object")
|
|
|
|
|
}
|
|
|
|
|
newAppToken.Token = cipherToken
|
|
|
|
|
newAppToken.Permissions = token.Permissions
|
|
|
|
|
|
|
|
|
|
return newAppToken, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func createAppTokenGlobal(ctx context.Context, token *AppToken) (*appTokenGlobal, []interface{}, error) {
|
|
|
|
|
func createAppTokenGlobal(ctx context.Context, token *AppToken) ([]interface{}, error) {
|
|
|
|
|
const op = "apptoken.(Repository).createAppTokenGlobal"
|
|
|
|
|
var globalInserts []interface{}
|
|
|
|
|
// we collect inserts in their own slices so that we can use w.CreateItems above
|
|
|
|
|
@ -350,25 +348,25 @@ func createAppTokenGlobal(ctx context.Context, token *AppToken) (*appTokenGlobal
|
|
|
|
|
// they're a composite key in the app_token_permission_grant table
|
|
|
|
|
for _, perm := range token.Permissions {
|
|
|
|
|
if slices.Contains(perm.GrantedScopes, globals.GrantScopeDescendants) && slices.Contains(perm.GrantedScopes, globals.GrantScopeChildren) {
|
|
|
|
|
return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "only one of descendants or children grant scope can be specified")
|
|
|
|
|
return nil, errors.New(ctx, errors.InvalidParameter, op, "only one of descendants or children grant scope can be specified")
|
|
|
|
|
}
|
|
|
|
|
// perm.GrantedScopes cannot contain globals.GrantScopeDescendants and also contain an individual project or org scope
|
|
|
|
|
if slices.Contains(perm.GrantedScopes, globals.GrantScopeDescendants) && slices.ContainsFunc(perm.GrantedScopes, func(s string) bool {
|
|
|
|
|
return strings.HasPrefix(s, globals.ProjectPrefix) || strings.HasPrefix(s, globals.OrgPrefix)
|
|
|
|
|
}) {
|
|
|
|
|
return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "descendants grant scope cannot be combined with individual project grant scopes")
|
|
|
|
|
return nil, errors.New(ctx, errors.InvalidParameter, op, "descendants grant scope cannot be combined with individual project grant scopes")
|
|
|
|
|
}
|
|
|
|
|
// perm.GrantedScopes cannot contain globals.GrantScopeChildren and also contain an individual org scope
|
|
|
|
|
if slices.Contains(perm.GrantedScopes, globals.GrantScopeChildren) && slices.ContainsFunc(perm.GrantedScopes, func(s string) bool {
|
|
|
|
|
return strings.HasPrefix(s, globals.OrgPrefix)
|
|
|
|
|
}) {
|
|
|
|
|
return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "children grant scope cannot be combined with individual org grant scopes")
|
|
|
|
|
return nil, errors.New(ctx, errors.InvalidParameter, op, "children grant scope cannot be combined with individual org grant scopes")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// generate new permission ID
|
|
|
|
|
permId, err := newAppTokenPermissionId(ctx)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, nil, errors.Wrap(ctx, err, op)
|
|
|
|
|
return nil, errors.Wrap(ctx, err, op)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
grantThisScope := slices.Contains(perm.GrantedScopes, globals.GrantScopeThis) || slices.Contains(perm.GrantedScopes, globals.GlobalPrefix)
|
|
|
|
|
@ -386,7 +384,7 @@ func createAppTokenGlobal(ctx context.Context, token *AppToken) (*appTokenGlobal
|
|
|
|
|
|
|
|
|
|
grantInserts, err := processPermissionGrants(ctx, permId, perm.Grants)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, nil, errors.Wrap(ctx, err, op)
|
|
|
|
|
return nil, errors.Wrap(ctx, err, op)
|
|
|
|
|
}
|
|
|
|
|
permissionGrantInserts = append(permissionGrantInserts, grantInserts...)
|
|
|
|
|
|
|
|
|
|
@ -420,7 +418,7 @@ func createAppTokenGlobal(ctx context.Context, token *AppToken) (*appTokenGlobal
|
|
|
|
|
}
|
|
|
|
|
individualProjInserts = append(individualProjInserts, individualProjGlobalPermToCreate)
|
|
|
|
|
default:
|
|
|
|
|
return nil, nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("invalid grant scope %s", gs))
|
|
|
|
|
return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("invalid grant scope %s", gs))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -438,10 +436,10 @@ func createAppTokenGlobal(ctx context.Context, token *AppToken) (*appTokenGlobal
|
|
|
|
|
globalInserts = append(globalInserts, individualProjInserts)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tokenToCreate, globalInserts, nil
|
|
|
|
|
return globalInserts, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func createAppTokenOrg(ctx context.Context, token *AppToken) (*appTokenOrg, []interface{}, error) {
|
|
|
|
|
func createAppTokenOrg(ctx context.Context, token *AppToken) ([]interface{}, error) {
|
|
|
|
|
const op = "apptoken.(Repository).createAppTokenOrg"
|
|
|
|
|
var orgInserts []interface{}
|
|
|
|
|
// we collect inserts in their own slices so that we can use w.CreateItems above
|
|
|
|
|
@ -467,20 +465,20 @@ func createAppTokenOrg(ctx context.Context, token *AppToken) (*appTokenOrg, []in
|
|
|
|
|
|
|
|
|
|
for _, perm := range token.Permissions {
|
|
|
|
|
if slices.Contains(perm.GrantedScopes, globals.GlobalPrefix) {
|
|
|
|
|
return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "org cannot have global grant scope")
|
|
|
|
|
return nil, errors.New(ctx, errors.InvalidParameter, op, "org cannot have global grant scope")
|
|
|
|
|
}
|
|
|
|
|
if slices.Contains(perm.GrantedScopes, globals.GrantScopeDescendants) {
|
|
|
|
|
return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "org cannot have descendants grant scope")
|
|
|
|
|
return nil, errors.New(ctx, errors.InvalidParameter, op, "org cannot have descendants grant scope")
|
|
|
|
|
}
|
|
|
|
|
if slices.Contains(perm.GrantedScopes, globals.GrantScopeChildren) && slices.ContainsFunc(perm.GrantedScopes, func(s string) bool {
|
|
|
|
|
return strings.HasPrefix(s, globals.ProjectPrefix)
|
|
|
|
|
}) {
|
|
|
|
|
return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "children grant scope cannot be combined with individual project grant scopes")
|
|
|
|
|
return nil, errors.New(ctx, errors.InvalidParameter, op, "children grant scope cannot be combined with individual project grant scopes")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
permId, err := newAppTokenPermissionId(ctx)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, nil, errors.Wrap(ctx, err, op)
|
|
|
|
|
return nil, errors.Wrap(ctx, err, op)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
grantThisScope := slices.Contains(perm.GrantedScopes, globals.GrantScopeThis) || slices.Contains(perm.GrantedScopes, token.GetScopeId())
|
|
|
|
|
@ -500,7 +498,7 @@ func createAppTokenOrg(ctx context.Context, token *AppToken) (*appTokenOrg, []in
|
|
|
|
|
|
|
|
|
|
grantInserts, err := processPermissionGrants(ctx, permId, perm.Grants)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, nil, errors.Wrap(ctx, err, op)
|
|
|
|
|
return nil, errors.Wrap(ctx, err, op)
|
|
|
|
|
}
|
|
|
|
|
permissionGrantInserts = append(permissionGrantInserts, grantInserts...)
|
|
|
|
|
|
|
|
|
|
@ -523,7 +521,7 @@ func createAppTokenOrg(ctx context.Context, token *AppToken) (*appTokenOrg, []in
|
|
|
|
|
}
|
|
|
|
|
individualProjInserts = append(individualProjInserts, individualProjOrgPermToCreate)
|
|
|
|
|
} else {
|
|
|
|
|
return nil, nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("invalid grant scope %s", gs))
|
|
|
|
|
return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("invalid grant scope %s", gs))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -538,10 +536,10 @@ func createAppTokenOrg(ctx context.Context, token *AppToken) (*appTokenOrg, []in
|
|
|
|
|
orgInserts = append(orgInserts, individualProjInserts)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tokenToCreate, orgInserts, nil
|
|
|
|
|
return orgInserts, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func createAppTokenProject(ctx context.Context, token *AppToken) (*appTokenProject, []interface{}, error) {
|
|
|
|
|
func createAppTokenProject(ctx context.Context, token *AppToken) ([]interface{}, error) {
|
|
|
|
|
const op = "apptoken.(Repository).createAppTokenProject"
|
|
|
|
|
var projectInserts []interface{}
|
|
|
|
|
// we collect inserts in their own slices so that we can use w.CreateItems above
|
|
|
|
|
@ -569,17 +567,17 @@ func createAppTokenProject(ctx context.Context, token *AppToken) (*appTokenProje
|
|
|
|
|
slices.Contains(perm.GrantedScopes, globals.GrantScopeChildren) ||
|
|
|
|
|
slices.Contains(perm.GrantedScopes, globals.GlobalPrefix) ||
|
|
|
|
|
slices.ContainsFunc(perm.GrantedScopes, func(s string) bool { return strings.HasPrefix(s, globals.OrgPrefix) }) {
|
|
|
|
|
return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "project can only contain individual project grant scopes")
|
|
|
|
|
return nil, errors.New(ctx, errors.InvalidParameter, op, "project can only contain individual project grant scopes")
|
|
|
|
|
}
|
|
|
|
|
if slices.ContainsFunc(perm.GrantedScopes, func(s string) bool {
|
|
|
|
|
return strings.HasPrefix(s, globals.ProjectPrefix) && s != token.GetScopeId()
|
|
|
|
|
}) {
|
|
|
|
|
return nil, nil, errors.New(ctx, errors.InvalidParameter, op, "project cannot contain individual grant scopes for other projects")
|
|
|
|
|
return nil, errors.New(ctx, errors.InvalidParameter, op, "project cannot contain individual grant scopes for other projects")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
permId, err := newAppTokenPermissionId(ctx)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, nil, errors.Wrap(ctx, err, op)
|
|
|
|
|
return nil, errors.Wrap(ctx, err, op)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// true if slices contains only the individual project scope that matches the token's scope ID or `this`
|
|
|
|
|
@ -598,7 +596,7 @@ func createAppTokenProject(ctx context.Context, token *AppToken) (*appTokenProje
|
|
|
|
|
|
|
|
|
|
grantInserts, err := processPermissionGrants(ctx, permId, perm.Grants)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, nil, errors.Wrap(ctx, err, op)
|
|
|
|
|
return nil, errors.Wrap(ctx, err, op)
|
|
|
|
|
}
|
|
|
|
|
permissionGrantInserts = append(permissionGrantInserts, grantInserts...)
|
|
|
|
|
}
|
|
|
|
|
@ -609,7 +607,7 @@ func createAppTokenProject(ctx context.Context, token *AppToken) (*appTokenProje
|
|
|
|
|
projectInserts = append(projectInserts, permissionGrantInserts)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tokenToCreate, projectInserts, nil
|
|
|
|
|
return projectInserts, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// processPermissionGrants validates grants and creates grant objects for insertion
|
|
|
|
|
|