Reimplement remove and invite user
Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
@@ -253,14 +253,14 @@ func (e ErrPersonalAPIKeyNotFound) Error() string {
|
|||||||
return fmt.Sprintf("personal API key %q not found", e.PersonalAPIKeyID)
|
return fmt.Sprintf("personal API key %q not found", e.PersonalAPIKeyID)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ErrProfileNotFound struct{ MembershipID gid.GID }
|
type ErrProfileNotFound struct{ ProfileID gid.GID }
|
||||||
|
|
||||||
func NewProfileNotFoundError(membershipID gid.GID) error {
|
func NewProfileNotFoundError(profileID gid.GID) error {
|
||||||
return &ErrProfileNotFound{MembershipID: membershipID}
|
return &ErrProfileNotFound{ProfileID: profileID}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e ErrProfileNotFound) Error() string {
|
func (e ErrProfileNotFound) Error() string {
|
||||||
return fmt.Sprintf("profile for membership %q not found", e.MembershipID)
|
return fmt.Sprintf("profile %q not found", e.ProfileID)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ErrPersonalAPIKeyExpired struct{ PersonalAPIKeyID gid.GID }
|
type ErrPersonalAPIKeyExpired struct{ PersonalAPIKeyID gid.GID }
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ const (
|
|||||||
ActionMembershipProfileList = "iam:membership-profile:list"
|
ActionMembershipProfileList = "iam:membership-profile:list"
|
||||||
ActionMembershipProfileCreate = "iam:membership-profile:create"
|
ActionMembershipProfileCreate = "iam:membership-profile:create"
|
||||||
ActionMembershipProfileUpdate = "iam:membership-profile:update"
|
ActionMembershipProfileUpdate = "iam:membership-profile:update"
|
||||||
|
ActionMembershipProfileDelete = "iam:membership-profile:delete"
|
||||||
|
|
||||||
// Personal API Key actions
|
// Personal API Key actions
|
||||||
ActionPersonalAPIKeyCreate = "iam:personal-api-key:create"
|
ActionPersonalAPIKeyCreate = "iam:personal-api-key:create"
|
||||||
|
|||||||
@@ -93,9 +93,8 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
CreateInvitationRequest struct {
|
CreateInvitationRequest struct {
|
||||||
Email mail.Addr
|
ProfileID gid.GID
|
||||||
FullName string
|
OrganizationID gid.GID
|
||||||
Role coredata.MembershipRole
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateUserRequest struct {
|
CreateUserRequest struct {
|
||||||
@@ -110,7 +109,7 @@ type (
|
|||||||
ContractEndDate **time.Time
|
ContractEndDate **time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateProfileRequest struct {
|
UpdateUserRequest struct {
|
||||||
ID gid.GID
|
ID gid.GID
|
||||||
FullName string
|
FullName string
|
||||||
AdditionalEmailAddresses mail.Addrs
|
AdditionalEmailAddresses mail.Addrs
|
||||||
@@ -220,7 +219,7 @@ func (cur *CreateUserRequest) Validate() error {
|
|||||||
return v.Error()
|
return v.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (upr *UpdateProfileRequest) Validate() error {
|
func (upr *UpdateUserRequest) Validate() error {
|
||||||
v := validator.New()
|
v := validator.New()
|
||||||
|
|
||||||
v.Check(upr.ID, "id", validator.Required(), validator.GID(coredata.MembershipProfileEntityType))
|
v.Check(upr.ID, "id", validator.Required(), validator.GID(coredata.MembershipProfileEntityType))
|
||||||
@@ -280,7 +279,7 @@ func (s *OrganizationService) UpdateMempership(
|
|||||||
return &membership, nil
|
return &membership, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OrganizationService) RemoveMember(
|
func (s *OrganizationService) RemoveUser(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
organizationID gid.GID,
|
organizationID gid.GID,
|
||||||
profileID gid.GID,
|
profileID gid.GID,
|
||||||
@@ -300,10 +299,6 @@ func (s *OrganizationService) RemoveMember(
|
|||||||
return fmt.Errorf("cannot load profile: %w", err)
|
return fmt.Errorf("cannot load profile: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if profile.OrganizationID != organizationID {
|
|
||||||
return NewMembershipNotFoundError(profile.ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
if profile.Source == coredata.ProfileSourceSCIM {
|
if profile.Source == coredata.ProfileSourceSCIM {
|
||||||
return NewUserManagedBySCIMError(profileID)
|
return NewUserManagedBySCIMError(profileID)
|
||||||
}
|
}
|
||||||
@@ -431,20 +426,16 @@ func (s *OrganizationService) CountInvitations(
|
|||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OrganizationService) InviteMember(
|
func (s *OrganizationService) InviteUser(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
organizationID gid.GID,
|
|
||||||
req *CreateInvitationRequest,
|
req *CreateInvitationRequest,
|
||||||
) (*coredata.Invitation, error) {
|
) (*coredata.Invitation, error) {
|
||||||
var (
|
var (
|
||||||
scope = coredata.NewScopeFromObjectID(organizationID)
|
scope = coredata.NewScopeFromObjectID(req.OrganizationID)
|
||||||
now = time.Now()
|
now = time.Now()
|
||||||
invitation = &coredata.Invitation{
|
invitation = &coredata.Invitation{
|
||||||
ID: gid.New(organizationID.TenantID(), coredata.InvitationEntityType),
|
ID: gid.New(req.OrganizationID.TenantID(), coredata.InvitationEntityType),
|
||||||
OrganizationID: organizationID,
|
OrganizationID: req.OrganizationID,
|
||||||
Email: req.Email,
|
|
||||||
FullName: req.FullName,
|
|
||||||
Role: req.Role,
|
|
||||||
Status: coredata.InvitationStatusPending,
|
Status: coredata.InvitationStatusPending,
|
||||||
ExpiresAt: now.Add(s.invitationTokenValidity),
|
ExpiresAt: now.Add(s.invitationTokenValidity),
|
||||||
CreatedAt: now,
|
CreatedAt: now,
|
||||||
@@ -455,32 +446,22 @@ func (s *OrganizationService) InviteMember(
|
|||||||
ctx,
|
ctx,
|
||||||
func(tx pg.Conn) error {
|
func(tx pg.Conn) error {
|
||||||
organization := coredata.Organization{}
|
organization := coredata.Organization{}
|
||||||
err := organization.LoadByID(ctx, tx, scope, organizationID)
|
err := organization.LoadByID(ctx, tx, scope, req.OrganizationID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == coredata.ErrResourceNotFound {
|
if err == coredata.ErrResourceNotFound {
|
||||||
return NewOrganizationNotFoundError(organizationID)
|
return NewOrganizationNotFoundError(req.OrganizationID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("cannot load organization: %w", err)
|
return fmt.Errorf("cannot load organization: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
identity := &coredata.Identity{}
|
profile := &coredata.MembershipProfile{}
|
||||||
err = identity.LoadByEmail(ctx, tx, invitation.Email)
|
if err := profile.LoadByID(ctx, tx, scope, req.ProfileID); err != nil {
|
||||||
if err != nil && err != coredata.ErrResourceNotFound {
|
if errors.Is(err, coredata.ErrResourceNotFound) {
|
||||||
return fmt.Errorf("cannot load identity: %w", err)
|
return NewProfileNotFoundError(req.ProfileID)
|
||||||
}
|
|
||||||
|
|
||||||
identityExists := identity.ID != gid.Nil
|
|
||||||
if identityExists {
|
|
||||||
profile := &coredata.MembershipProfile{}
|
|
||||||
err = profile.LoadByIdentityIDAndOrganizationID(ctx, tx, scope, identity.ID, organizationID)
|
|
||||||
if err != nil && err != coredata.ErrResourceNotFound {
|
|
||||||
return fmt.Errorf("cannot load profile: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if profile.ID != gid.Nil && profile.State == coredata.ProfileStateActive {
|
return fmt.Errorf("cannot load profile: %w", err)
|
||||||
return NewUserAlreadyExistsError(identity.ID, organizationID)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = invitation.Insert(ctx, tx, scope)
|
err = invitation.Insert(ctx, tx, scope)
|
||||||
@@ -498,7 +479,7 @@ func (s *OrganizationService) InviteMember(
|
|||||||
return fmt.Errorf("cannot generate invitation token: %w", err)
|
return fmt.Errorf("cannot generate invitation token: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
emailPresenter := emails.NewPresenter(s.fm, s.bucket, s.baseURL, identity.FullName)
|
emailPresenter := emails.NewPresenter(s.fm, s.bucket, s.baseURL, profile.FullName)
|
||||||
|
|
||||||
subject, textBody, htmlBody, err := emailPresenter.RenderInvitation(
|
subject, textBody, htmlBody, err := emailPresenter.RenderInvitation(
|
||||||
ctx,
|
ctx,
|
||||||
@@ -511,8 +492,8 @@ func (s *OrganizationService) InviteMember(
|
|||||||
}
|
}
|
||||||
|
|
||||||
email := coredata.NewEmail(
|
email := coredata.NewEmail(
|
||||||
invitation.FullName,
|
profile.FullName,
|
||||||
invitation.Email,
|
profile.EmailAddress,
|
||||||
subject,
|
subject,
|
||||||
textBody,
|
textBody,
|
||||||
htmlBody,
|
htmlBody,
|
||||||
@@ -1034,7 +1015,7 @@ func (s *OrganizationService) CreateUser(ctx context.Context, req *CreateUserReq
|
|||||||
return profile, nil
|
return profile, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OrganizationService) UpdateProfile(ctx context.Context, req *UpdateProfileRequest) (*coredata.MembershipProfile, error) {
|
func (s *OrganizationService) UpdateUser(ctx context.Context, req *UpdateUserRequest) (*coredata.MembershipProfile, error) {
|
||||||
if err := req.Validate(); err != nil {
|
if err := req.Validate(); err != nil {
|
||||||
return nil, fmt.Errorf("invalid request: %w", err)
|
return nil, fmt.Errorf("invalid request: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -357,7 +357,7 @@ func (s SessionService) OpenPasswordChildSessionForOrganization(
|
|||||||
err = profile.LoadByIdentityIDAndOrganizationID(ctx, tx, scope, rootSession.IdentityID, organizationID)
|
err = profile.LoadByIdentityIDAndOrganizationID(ctx, tx, scope, rootSession.IdentityID, organizationID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == coredata.ErrResourceNotFound {
|
if err == coredata.ErrResourceNotFound {
|
||||||
return NewProfileNotFoundError(organizationID)
|
return NewProfileNotFoundError(gid.Nil)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("cannot load profile: %w", err)
|
return fmt.Errorf("cannot load profile: %w", err)
|
||||||
}
|
}
|
||||||
@@ -459,7 +459,7 @@ func (s SessionService) OpenSAMLChildSessionForOrganization(
|
|||||||
err = profile.LoadByIdentityIDAndOrganizationID(ctx, tx, scope, rootSession.IdentityID, organizationID)
|
err = profile.LoadByIdentityIDAndOrganizationID(ctx, tx, scope, rootSession.IdentityID, organizationID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == coredata.ErrResourceNotFound {
|
if err == coredata.ErrResourceNotFound {
|
||||||
return NewProfileNotFoundError(organizationID)
|
return NewProfileNotFoundError(gid.Nil)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("cannot load profile: %w", err)
|
return fmt.Errorf("cannot load profile: %w", err)
|
||||||
}
|
}
|
||||||
@@ -545,7 +545,7 @@ func (s SessionService) AssumeOrganizationSession(
|
|||||||
|
|
||||||
if err := profile.LoadByIdentityIDAndOrganizationID(ctx, tx, scope, rootSession.IdentityID, organizationID); err != nil {
|
if err := profile.LoadByIdentityIDAndOrganizationID(ctx, tx, scope, rootSession.IdentityID, organizationID); err != nil {
|
||||||
if err == coredata.ErrResourceNotFound {
|
if err == coredata.ErrResourceNotFound {
|
||||||
return NewProfileNotFoundError(organizationID)
|
return NewProfileNotFoundError(gid.Nil)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("cannot load profile: %w", err)
|
return fmt.Errorf("cannot load profile: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,13 +96,13 @@ type Mutation {
|
|||||||
|
|
||||||
createUser(input: CreateUserInput!): CreateUserPayload
|
createUser(input: CreateUserInput!): CreateUserPayload
|
||||||
@session(required: PRESENT)
|
@session(required: PRESENT)
|
||||||
inviteMember(input: InviteMemberInput!): InviteMemberPayload
|
inviteUser(input: InviteUserInput!): InviteUserPayload
|
||||||
@session(required: PRESENT)
|
@session(required: PRESENT)
|
||||||
deleteInvitation(input: DeleteInvitationInput!): DeleteInvitationPayload
|
deleteInvitation(input: DeleteInvitationInput!): DeleteInvitationPayload
|
||||||
@session(required: PRESENT)
|
@session(required: PRESENT)
|
||||||
updateProfile(input: UpdateProfileInput!): UpdateProfilePayload!
|
updateUser(input: UpdateUserInput!): UpdateUserPayload!
|
||||||
updateMembership(input: UpdateMembershipInput!): UpdateMembershipPayload!
|
updateMembership(input: UpdateMembershipInput!): UpdateMembershipPayload!
|
||||||
removeMember(input: RemoveMemberInput!): RemoveMemberPayload
|
removeUser(input: RemoveUserInput!): RemoveUserPayload
|
||||||
@session(required: PRESENT)
|
@session(required: PRESENT)
|
||||||
|
|
||||||
acceptInvitation(input: AcceptInvitationInput!): AcceptInvitationPayload
|
acceptInvitation(input: AcceptInvitationInput!): AcceptInvitationPayload
|
||||||
@@ -741,14 +741,12 @@ input CreateUserInput {
|
|||||||
contractEndDate: Datetime @goField(omittable: true)
|
contractEndDate: Datetime @goField(omittable: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
input InviteMemberInput {
|
input InviteUserInput {
|
||||||
organizationId: ID!
|
organizationId: ID!
|
||||||
email: EmailAddr!
|
profileId: ID!
|
||||||
fullName: String!
|
|
||||||
role: MembershipRole!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input UpdateProfileInput {
|
input UpdateUserInput {
|
||||||
id: ID!
|
id: ID!
|
||||||
fullName: String!
|
fullName: String!
|
||||||
additionalEmailAddresses: [EmailAddr!]
|
additionalEmailAddresses: [EmailAddr!]
|
||||||
@@ -764,9 +762,9 @@ input UpdateMembershipInput {
|
|||||||
role: MembershipRole!
|
role: MembershipRole!
|
||||||
}
|
}
|
||||||
|
|
||||||
input RemoveMemberInput {
|
input RemoveUserInput {
|
||||||
organizationId: ID!
|
organizationId: ID!
|
||||||
membershipId: ID!
|
profileId: ID!
|
||||||
}
|
}
|
||||||
|
|
||||||
input AcceptInvitationInput {
|
input AcceptInvitationInput {
|
||||||
@@ -908,11 +906,11 @@ type CreateUserPayload {
|
|||||||
profileEdge: ProfileEdge!
|
profileEdge: ProfileEdge!
|
||||||
}
|
}
|
||||||
|
|
||||||
type InviteMemberPayload {
|
type InviteUserPayload {
|
||||||
invitationEdge: InvitationEdge!
|
invitationEdge: InvitationEdge!
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateProfilePayload {
|
type UpdateUserPayload {
|
||||||
profile: Profile!
|
profile: Profile!
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -920,8 +918,8 @@ type UpdateMembershipPayload {
|
|||||||
membership: Membership!
|
membership: Membership!
|
||||||
}
|
}
|
||||||
|
|
||||||
type RemoveMemberPayload {
|
type RemoveUserPayload {
|
||||||
deletedMembershipId: ID!
|
deletedProfileId: ID!
|
||||||
}
|
}
|
||||||
|
|
||||||
type AcceptInvitationPayload {
|
type AcceptInvitationPayload {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -224,14 +224,12 @@ type InvitationEdge struct {
|
|||||||
Cursor page.CursorKey `json:"cursor"`
|
Cursor page.CursorKey `json:"cursor"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type InviteMemberInput struct {
|
type InviteUserInput struct {
|
||||||
OrganizationID gid.GID `json:"organizationId"`
|
OrganizationID gid.GID `json:"organizationId"`
|
||||||
Email mail.Addr `json:"email"`
|
ProfileID gid.GID `json:"profileId"`
|
||||||
FullName string `json:"fullName"`
|
|
||||||
Role coredata.MembershipRole `json:"role"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type InviteMemberPayload struct {
|
type InviteUserPayload struct {
|
||||||
InvitationEdge *InvitationEdge `json:"invitationEdge"`
|
InvitationEdge *InvitationEdge `json:"invitationEdge"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,13 +346,13 @@ type RegenerateSCIMTokenPayload struct {
|
|||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RemoveMemberInput struct {
|
type RemoveUserInput struct {
|
||||||
OrganizationID gid.GID `json:"organizationId"`
|
OrganizationID gid.GID `json:"organizationId"`
|
||||||
MembershipID gid.GID `json:"membershipId"`
|
ProfileID gid.GID `json:"profileId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RemoveMemberPayload struct {
|
type RemoveUserPayload struct {
|
||||||
DeletedMembershipID gid.GID `json:"deletedMembershipId"`
|
DeletedProfileID gid.GID `json:"deletedProfileId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResetPasswordInput struct {
|
type ResetPasswordInput struct {
|
||||||
@@ -566,20 +564,6 @@ type UpdateOrganizationPayload struct {
|
|||||||
Organization *Organization `json:"organization,omitempty"`
|
Organization *Organization `json:"organization,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateProfileInput struct {
|
|
||||||
ID gid.GID `json:"id"`
|
|
||||||
FullName string `json:"fullName"`
|
|
||||||
AdditionalEmailAddresses []mail.Addr `json:"additionalEmailAddresses,omitempty"`
|
|
||||||
Kind coredata.MembershipProfileKind `json:"kind"`
|
|
||||||
Position *string `json:"position,omitempty"`
|
|
||||||
ContractStartDate graphql.Omittable[*time.Time] `json:"contractStartDate,omitempty"`
|
|
||||||
ContractEndDate graphql.Omittable[*time.Time] `json:"contractEndDate,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateProfilePayload struct {
|
|
||||||
Profile *Profile `json:"profile"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateSAMLConfigurationInput struct {
|
type UpdateSAMLConfigurationInput struct {
|
||||||
OrganizationID gid.GID `json:"organizationId"`
|
OrganizationID gid.GID `json:"organizationId"`
|
||||||
SamlConfigurationID gid.GID `json:"samlConfigurationId"`
|
SamlConfigurationID gid.GID `json:"samlConfigurationId"`
|
||||||
@@ -605,6 +589,20 @@ type UpdateSCIMBridgePayload struct {
|
|||||||
ScimBridge *SCIMBridge `json:"scimBridge"`
|
ScimBridge *SCIMBridge `json:"scimBridge"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UpdateUserInput struct {
|
||||||
|
ID gid.GID `json:"id"`
|
||||||
|
FullName string `json:"fullName"`
|
||||||
|
AdditionalEmailAddresses []mail.Addr `json:"additionalEmailAddresses,omitempty"`
|
||||||
|
Kind coredata.MembershipProfileKind `json:"kind"`
|
||||||
|
Position *string `json:"position,omitempty"`
|
||||||
|
ContractStartDate graphql.Omittable[*time.Time] `json:"contractStartDate,omitempty"`
|
||||||
|
ContractEndDate graphql.Omittable[*time.Time] `json:"contractEndDate,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateUserPayload struct {
|
||||||
|
Profile *Profile `json:"profile"`
|
||||||
|
}
|
||||||
|
|
||||||
type VerifyEmailInput struct {
|
type VerifyEmailInput struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -907,19 +907,17 @@ func (r *mutationResolver) CreateUser(ctx context.Context, input types.CreateUse
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// InviteMember is the resolver for the inviteMember field.
|
// InviteUser is the resolver for the inviteUser field.
|
||||||
func (r *mutationResolver) InviteMember(ctx context.Context, input types.InviteMemberInput) (*types.InviteMemberPayload, error) {
|
func (r *mutationResolver) InviteUser(ctx context.Context, input types.InviteUserInput) (*types.InviteUserPayload, error) {
|
||||||
if err := r.authorize(ctx, input.OrganizationID, iam.ActionInvitationCreate); err != nil {
|
if err := r.authorize(ctx, input.ProfileID, iam.ActionInvitationCreate); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
invitation, err := r.iam.OrganizationService.InviteMember(
|
invitation, err := r.iam.OrganizationService.InviteUser(
|
||||||
ctx,
|
ctx,
|
||||||
input.OrganizationID,
|
|
||||||
&iam.CreateInvitationRequest{
|
&iam.CreateInvitationRequest{
|
||||||
Email: input.Email,
|
OrganizationID: input.OrganizationID,
|
||||||
FullName: input.FullName,
|
ProfileID: input.ProfileID,
|
||||||
Role: input.Role,
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -934,11 +932,11 @@ func (r *mutationResolver) InviteMember(ctx context.Context, input types.InviteM
|
|||||||
return nil, gqlutils.Conflict(ctx, err)
|
return nil, gqlutils.Conflict(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot add member to organization", log.Error(err))
|
r.logger.ErrorCtx(ctx, "cannot invite user", log.Error(err))
|
||||||
return nil, gqlutils.Internal(ctx)
|
return nil, gqlutils.Internal(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &types.InviteMemberPayload{
|
return &types.InviteUserPayload{
|
||||||
InvitationEdge: types.NewInvitationEdge(invitation, coredata.InvitationOrderFieldCreatedAt),
|
InvitationEdge: types.NewInvitationEdge(invitation, coredata.InvitationOrderFieldCreatedAt),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@@ -969,15 +967,15 @@ func (r *mutationResolver) DeleteInvitation(ctx context.Context, input types.Del
|
|||||||
return &types.DeleteInvitationPayload{DeletedInvitationID: input.InvitationID}, nil
|
return &types.DeleteInvitationPayload{DeletedInvitationID: input.InvitationID}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateProfile is the resolver for the updateProfile field.
|
// UpdateUser is the resolver for the updateUser field.
|
||||||
func (r *mutationResolver) UpdateProfile(ctx context.Context, input types.UpdateProfileInput) (*types.UpdateProfilePayload, error) {
|
func (r *mutationResolver) UpdateUser(ctx context.Context, input types.UpdateUserInput) (*types.UpdateUserPayload, error) {
|
||||||
if err := r.authorize(ctx, input.ID, iam.ActionMembershipProfileUpdate); err != nil {
|
if err := r.authorize(ctx, input.ID, iam.ActionMembershipProfileUpdate); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
profile, err := r.iam.OrganizationService.UpdateProfile(
|
profile, err := r.iam.OrganizationService.UpdateUser(
|
||||||
ctx,
|
ctx,
|
||||||
&iam.UpdateProfileRequest{
|
&iam.UpdateUserRequest{
|
||||||
ID: input.ID,
|
ID: input.ID,
|
||||||
FullName: input.FullName,
|
FullName: input.FullName,
|
||||||
AdditionalEmailAddresses: input.AdditionalEmailAddresses,
|
AdditionalEmailAddresses: input.AdditionalEmailAddresses,
|
||||||
@@ -992,7 +990,7 @@ func (r *mutationResolver) UpdateProfile(ctx context.Context, input types.Update
|
|||||||
return nil, gqlutils.Internal(ctx)
|
return nil, gqlutils.Internal(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &types.UpdateProfilePayload{
|
return &types.UpdateUserPayload{
|
||||||
Profile: types.NewProfile(profile),
|
Profile: types.NewProfile(profile),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@@ -1020,13 +1018,13 @@ func (r *mutationResolver) UpdateMembership(ctx context.Context, input types.Upd
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveMember is the resolver for the removeMember field.
|
// RemoveUser is the resolver for the removeUser field.
|
||||||
func (r *mutationResolver) RemoveMember(ctx context.Context, input types.RemoveMemberInput) (*types.RemoveMemberPayload, error) {
|
func (r *mutationResolver) RemoveUser(ctx context.Context, input types.RemoveUserInput) (*types.RemoveUserPayload, error) {
|
||||||
if err := r.authorize(ctx, input.MembershipID, iam.ActionMembershipDelete); err != nil {
|
if err := r.authorize(ctx, input.ProfileID, iam.ActionMembershipProfileDelete); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err := r.iam.OrganizationService.RemoveMember(ctx, input.OrganizationID, input.MembershipID)
|
err := r.iam.OrganizationService.RemoveUser(ctx, input.OrganizationID, input.ProfileID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var errManagedBySCIM *iam.ErrUserManagedBySCIM
|
var errManagedBySCIM *iam.ErrUserManagedBySCIM
|
||||||
var errLastActiveOwner *iam.ErrLastActiveOwner
|
var errLastActiveOwner *iam.ErrLastActiveOwner
|
||||||
@@ -1039,11 +1037,11 @@ func (r *mutationResolver) RemoveMember(ctx context.Context, input types.RemoveM
|
|||||||
return nil, gqlutils.Conflict(ctx, err)
|
return nil, gqlutils.Conflict(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.logger.ErrorCtx(ctx, "cannot remove member from organization", log.Error(err))
|
r.logger.ErrorCtx(ctx, "cannot remove user from organization", log.Error(err))
|
||||||
return nil, gqlutils.Internal(ctx)
|
return nil, gqlutils.Internal(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &types.RemoveMemberPayload{DeletedMembershipID: input.MembershipID}, nil
|
return &types.RemoveUserPayload{DeletedProfileID: input.ProfileID}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AcceptInvitation is the resolver for the acceptInvitation field.
|
// AcceptInvitation is the resolver for the acceptInvitation field.
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ package mcp_v1
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||||
"go.probo.inc/probo/pkg/coredata"
|
"go.probo.inc/probo/pkg/coredata"
|
||||||
"go.probo.inc/probo/pkg/gid"
|
"go.probo.inc/probo/pkg/gid"
|
||||||
|
"go.probo.inc/probo/pkg/iam"
|
||||||
"go.probo.inc/probo/pkg/page"
|
"go.probo.inc/probo/pkg/page"
|
||||||
"go.probo.inc/probo/pkg/probo"
|
"go.probo.inc/probo/pkg/probo"
|
||||||
"go.probo.inc/probo/pkg/server/api/authn"
|
"go.probo.inc/probo/pkg/server/api/authn"
|
||||||
|
|||||||
Reference in New Issue
Block a user