Rewrite permission system

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2025-12-17 18:46:55 +01:00
parent 2baf8f0413
commit e61d72f15d
26 changed files with 3123 additions and 64 deletions

View File

@@ -819,14 +819,15 @@ func (r *personalAPIKeyConnectionResolver) TotalCount(ctx context.Context, obj *
// Node is the resolver for the node field.
func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error) {
var loadNode func(ctx context.Context, id gid.GID) (types.Node, error)
user := UserFromContext(ctx)
r.iam.AccessManagementService.Authorize(ctx, user.ID, nil, id, iam.ActionGet)
var (
loadNode func(ctx context.Context, id gid.GID) (types.Node, error)
user = UserFromContext(ctx)
action string
)
switch id.EntityType() {
case coredata.OrganizationEntityType:
action = iam.ActionIAMOrganizationGet
loadNode = func(ctx context.Context, id gid.GID) (types.Node, error) {
organization, err := r.iam.OrganizationService.GetOrganization(ctx, id)
if err != nil {
@@ -835,6 +836,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
return types.NewOrganization(organization), nil
}
case coredata.UserEntityType:
action = iam.ActionIAMIdentityGet
loadNode = func(ctx context.Context, id gid.GID) (types.Node, error) {
identity, err := r.iam.AccountService.GetIdentity(ctx, id)
if err != nil {
@@ -844,6 +846,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
return types.NewIdentity(identity), nil
}
case coredata.SessionEntityType:
action = iam.ActionIAMSessionGet
loadNode = func(ctx context.Context, id gid.GID) (types.Node, error) {
session, err := r.iam.GetSession(ctx, id)
if err != nil {
@@ -853,6 +856,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
return types.NewSession(session), nil
}
case coredata.MembershipEntityType:
action = iam.ActionIAMMembershipGet
loadNode = func(ctx context.Context, id gid.GID) (types.Node, error) {
membership, err := r.iam.GetMembership(ctx, id)
if err != nil {
@@ -862,6 +866,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
return types.NewMembership(membership), nil
}
case coredata.InvitationEntityType:
action = iam.ActionIAMInvitationGet
loadNode = func(ctx context.Context, id gid.GID) (types.Node, error) {
invitation, err := r.iam.GetInvitation(ctx, id)
if err != nil {
@@ -874,6 +879,24 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
return nil, fmt.Errorf("unsupported entity type: %d", id.EntityType())
}
err := r.iam.Authorizer.Authorize(
ctx,
iam.AuthorizeParams{
Principal: user.ID,
Resource: id,
Action: action,
ResourceAttributes: map[string]string{},
},
)
if err != nil {
var errInsufficientPermissions *iam.ErrInsufficientPermissions
if errors.As(err, &errInsufficientPermissions) {
return nil, gqlutils.Forbidden(err)
}
panic(fmt.Errorf("cannot authorize: %w", err))
}
node, err := loadNode(ctx, id)
if err != nil {
var (
@@ -882,13 +905,15 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
errSessionNotFound *iam.ErrSessionNotFound
errMembershipNotFound *iam.ErrMembershipNotFound
errInvitationNotFound *iam.ErrInvitationNotFound
isNotFoundErr = errors.As(err, &errOrganizationNotFound) ||
errors.As(err, &errIdentityNotFound) ||
errors.As(err, &errSessionNotFound) ||
errors.As(err, &errMembershipNotFound) ||
errors.As(err, &errInvitationNotFound)
)
if errors.As(err, &errOrganizationNotFound) ||
errors.As(err, &errIdentityNotFound) ||
errors.As(err, &errSessionNotFound) ||
errors.As(err, &errMembershipNotFound) ||
errors.As(err, &errInvitationNotFound) {
if isNotFoundErr {
return nil, gqlutils.NotFound(err)
}

View File

@@ -241,7 +241,7 @@ func NewMux(
}
// Ensure the actor (and optional API key) can access this organization.
if err := iamSvc.AccessManagementService.Authorize(r.Context(), identity.ID, credentialID, organizationID, iam.ActionGet); err != nil {
if err := iamSvc.LegacyAccessManagementService.Authorize(r.Context(), identity.ID, credentialID, organizationID, iam.ActionGet); err != nil {
httpserver.RenderError(w, http.StatusForbidden, err)
return
}
@@ -336,7 +336,7 @@ func (r *Resolver) MustBeAuthorized(ctx context.Context, entityID gid.GID, actio
credentialID = &apiKey.ID
}
err := r.iam.AccessManagementService.Authorize(ctx, user.ID, credentialID, entityID, action)
err := r.iam.LegacyAccessManagementService.Authorize(ctx, user.ID, credentialID, entityID, action)
if err != nil {
panic(err)
}

View File

@@ -1758,7 +1758,13 @@ func (r *mutationResolver) DeleteTrustCenterFile(ctx context.Context, input type
// CreatePeople is the resolver for the createPeople field.
func (r *mutationResolver) CreatePeople(ctx context.Context, input types.CreatePeopleInput) (*types.CreatePeoplePayload, error) {
r.MustBeAuthorized(ctx, input.OrganizationID, iam.ActionCreatePeople)
user := connect_v1.UserFromContext(ctx)
r.iam.Authorizer.Authorize(ctx, iam.AuthorizeParams{
Principal: user.ID,
Resource: input.OrganizationID,
Action: iam.ActionCreatePeople,
})
prb := r.ProboService(ctx, input.OrganizationID.TenantID())

View File

@@ -30,7 +30,7 @@ func (r *Resolver) MustBeAuthorized(ctx context.Context, entityID gid.GID, actio
credentialID = &apiKey.ID
}
err := r.iamSvc.AccessManagementService.Authorize(ctx, user.ID, credentialID, entityID, action)
err := r.iamSvc.LegacyAccessManagementService.Authorize(ctx, user.ID, credentialID, entityID, action)
if err != nil {
panic(err)
}

View File

@@ -430,7 +430,7 @@ func (r *mutationResolver) RequestReportAccess(ctx context.Context, input types.
// email := input.Email
// tokenData := TokenAccessFromContext(ctx)
// if tokenData != nil {
// *email = tokenData.Email
// email = &tokenData.Email
// }
// if email == nil {
// return nil, fmt.Errorf("email is required for unauthenticated users")