Implement activate account page
Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
@@ -293,7 +293,6 @@ func (i *Invitations) ExpireByUserID(
|
||||
expires_at = NOW()
|
||||
WHERE
|
||||
user_id = @user_id
|
||||
AND organization_id = @organization_id
|
||||
AND %s
|
||||
AND %s
|
||||
`
|
||||
|
||||
@@ -47,7 +47,6 @@ type (
|
||||
|
||||
CreateIdentityFromInvitationRequest struct {
|
||||
InvitationToken string
|
||||
Password string
|
||||
}
|
||||
|
||||
LoadOrCreateIdentityRequest struct {
|
||||
@@ -92,7 +91,6 @@ func (req CreateIdentityFromInvitationRequest) Validate() error {
|
||||
v := validator.New()
|
||||
|
||||
v.Check(req.InvitationToken, "invitationToken", validator.NotEmpty())
|
||||
v.Check(req.Password, "password", PasswordValidator())
|
||||
|
||||
return v.Error()
|
||||
}
|
||||
@@ -153,11 +151,6 @@ func (s *AuthService) ActivateAccount(
|
||||
now = time.Now()
|
||||
)
|
||||
|
||||
hashedPassword, err := s.hp.HashPassword([]byte(req.Password))
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("cannot hash password: %w", err)
|
||||
}
|
||||
|
||||
err = s.pg.WithTx(
|
||||
ctx,
|
||||
func(tx pg.Conn) error {
|
||||
@@ -197,7 +190,6 @@ func (s *AuthService) ActivateAccount(
|
||||
return fmt.Errorf("cannot load identity: %w", err)
|
||||
}
|
||||
|
||||
identity.HashedPassword = hashedPassword
|
||||
identity.EmailAddressVerified = true
|
||||
identity.UpdatedAt = now
|
||||
|
||||
|
||||
@@ -326,15 +326,15 @@ func (e ErrInvitationNotDeleted) Error() string {
|
||||
return fmt.Sprintf("cannot delete invitation %q in %q status", e.InvitationID, e.Status)
|
||||
}
|
||||
|
||||
type ErrPasswordRequired struct {
|
||||
type ErrPasswordAuthenticationRequired struct {
|
||||
Reason string
|
||||
}
|
||||
|
||||
func NewPasswordRequiredError(reason string) *ErrPasswordRequired {
|
||||
return &ErrPasswordRequired{Reason: reason}
|
||||
func NewPasswordAuthenticationRequiredError(reason string) *ErrPasswordAuthenticationRequired {
|
||||
return &ErrPasswordAuthenticationRequired{Reason: reason}
|
||||
}
|
||||
|
||||
func (e *ErrPasswordRequired) Error() string {
|
||||
func (e *ErrPasswordAuthenticationRequired) Error() string {
|
||||
return fmt.Sprintf("password authentication required: %s", e.Reason)
|
||||
}
|
||||
|
||||
|
||||
@@ -573,16 +573,23 @@ func (s SessionService) AssumeOrganizationSession(
|
||||
return fmt.Errorf("cannot load SAML configuration: %w", err)
|
||||
}
|
||||
|
||||
if err == nil && samlConfig.EnforcementPolicy == coredata.SAMLEnforcementPolicyRequired {
|
||||
if rootSession.AuthMethod != coredata.AuthMethodSAML {
|
||||
return NewSAMLAuthenticationRequiredError("policy_requirement")
|
||||
if err == nil {
|
||||
switch samlConfig.EnforcementPolicy {
|
||||
case coredata.SAMLEnforcementPolicyRequired:
|
||||
if rootSession.AuthMethod != coredata.AuthMethodSAML {
|
||||
return NewSAMLAuthenticationRequiredError("policy_requirement")
|
||||
}
|
||||
case coredata.SAMLEnforcementPolicyOptional:
|
||||
// SAML is optional: both PASSWORD and SAML root sessions are allowed.
|
||||
}
|
||||
} else {
|
||||
switch rootSession.AuthMethod {
|
||||
case coredata.AuthMethodPassword:
|
||||
case coredata.AuthMethodSAML:
|
||||
// No (or non-required) SAML configuration: require a password-authenticated or magic-link root session
|
||||
// (eg. when switching into a password-based org from a SAML login)
|
||||
return NewPasswordAuthenticationRequiredError("password_authentication_required")
|
||||
}
|
||||
} else if err == nil && samlConfig.EnforcementPolicy == coredata.SAMLEnforcementPolicyOptional {
|
||||
// SAML is optional: both PASSWORD and SAML root sessions are allowed.
|
||||
} else if rootSession.AuthMethod != coredata.AuthMethodPassword {
|
||||
// No (or non-required) SAML configuration: require a password-authenticated root session
|
||||
// (eg. when switching into a password-based org from a SAML login).
|
||||
return NewPasswordRequiredError("password_authentication_required")
|
||||
}
|
||||
|
||||
tenantID := scope.GetTenantID()
|
||||
|
||||
@@ -141,6 +141,7 @@ type Identity implements Node {
|
||||
last: Int
|
||||
before: CursorKey
|
||||
orderBy: ProfileOrder
|
||||
filter: ProfileFilter
|
||||
): ProfileConnection @goField(forceResolver: true)
|
||||
|
||||
sessions(
|
||||
@@ -512,6 +513,11 @@ enum ProfileOrderField
|
||||
)
|
||||
}
|
||||
|
||||
input ProfileFilter {
|
||||
excludeContractEnded: Boolean
|
||||
state: ProfileState
|
||||
}
|
||||
|
||||
input ProfileOrder
|
||||
@goModel(
|
||||
model: "go.probo.inc/probo/pkg/server/api/connect/v1/types.ProfileOrderBy"
|
||||
@@ -628,7 +634,6 @@ input SignUpInput {
|
||||
|
||||
input ActivateAccountInput {
|
||||
token: String!
|
||||
password: String!
|
||||
}
|
||||
|
||||
input ForgotPasswordInput {
|
||||
@@ -794,6 +799,10 @@ type ActivateAccountPayload {
|
||||
profile: Profile
|
||||
}
|
||||
|
||||
type CreatePasswordPayload {
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
type ForgotPasswordPayload {
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
@@ -108,6 +108,10 @@ type ComplexityRoot struct {
|
||||
Organization func(childComplexity int) int
|
||||
}
|
||||
|
||||
CreatePasswordPayload struct {
|
||||
Success func(childComplexity int) int
|
||||
}
|
||||
|
||||
CreatePersonalAPIKeyPayload struct {
|
||||
PersonalAPIKeyEdge func(childComplexity int) int
|
||||
Token func(childComplexity int) int
|
||||
@@ -159,7 +163,7 @@ type ComplexityRoot struct {
|
||||
ID func(childComplexity int) int
|
||||
Permission func(childComplexity int, action string) int
|
||||
PersonalAPIKeys func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int
|
||||
Profiles func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy) int
|
||||
Profiles func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy, filter *types.ProfileFilter) int
|
||||
Sessions func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.SessionOrder) int
|
||||
UpdatedAt func(childComplexity int) int
|
||||
}
|
||||
@@ -499,7 +503,7 @@ type ConnectorResolver interface {
|
||||
Permission(ctx context.Context, obj *types.Connector, action string) (bool, error)
|
||||
}
|
||||
type IdentityResolver interface {
|
||||
Profiles(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy) (*types.ProfileConnection, error)
|
||||
Profiles(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy, filter *types.ProfileFilter) (*types.ProfileConnection, error)
|
||||
Sessions(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.SessionOrder) (*types.SessionConnection, error)
|
||||
PersonalAPIKeys(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.PersonalAPIKeyConnection, error)
|
||||
SsoLoginURL(ctx context.Context, obj *types.Identity) (*string, error)
|
||||
@@ -727,6 +731,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
|
||||
return e.complexity.CreateOrganizationPayload.Organization(childComplexity), true
|
||||
|
||||
case "CreatePasswordPayload.success":
|
||||
if e.complexity.CreatePasswordPayload.Success == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.CreatePasswordPayload.Success(childComplexity), true
|
||||
|
||||
case "CreatePersonalAPIKeyPayload.personalAPIKeyEdge":
|
||||
if e.complexity.CreatePersonalAPIKeyPayload.PersonalAPIKeyEdge == nil {
|
||||
break
|
||||
@@ -877,7 +888,7 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Identity.Profiles(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.ProfileOrderBy)), true
|
||||
return e.complexity.Identity.Profiles(childComplexity, args["first"].(*int), args["after"].(*page.CursorKey), args["last"].(*int), args["before"].(*page.CursorKey), args["orderBy"].(*types.ProfileOrderBy), args["filter"].(*types.ProfileFilter)), true
|
||||
case "Identity.sessions":
|
||||
if e.complexity.Identity.Sessions == nil {
|
||||
break
|
||||
@@ -2357,6 +2368,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
|
||||
ec.unmarshalInputForgotPasswordInput,
|
||||
ec.unmarshalInputInvitationOrder,
|
||||
ec.unmarshalInputInviteUserInput,
|
||||
ec.unmarshalInputProfileFilter,
|
||||
ec.unmarshalInputProfileOrder,
|
||||
ec.unmarshalInputRegenerateSCIMTokenInput,
|
||||
ec.unmarshalInputRemoveUserInput,
|
||||
@@ -2614,6 +2626,7 @@ type Identity implements Node {
|
||||
last: Int
|
||||
before: CursorKey
|
||||
orderBy: ProfileOrder
|
||||
filter: ProfileFilter
|
||||
): ProfileConnection @goField(forceResolver: true)
|
||||
|
||||
sessions(
|
||||
@@ -2985,6 +2998,11 @@ enum ProfileOrderField
|
||||
)
|
||||
}
|
||||
|
||||
input ProfileFilter {
|
||||
excludeContractEnded: Boolean
|
||||
state: ProfileState
|
||||
}
|
||||
|
||||
input ProfileOrder
|
||||
@goModel(
|
||||
model: "go.probo.inc/probo/pkg/server/api/connect/v1/types.ProfileOrderBy"
|
||||
@@ -3101,7 +3119,6 @@ input SignUpInput {
|
||||
|
||||
input ActivateAccountInput {
|
||||
token: String!
|
||||
password: String!
|
||||
}
|
||||
|
||||
input ForgotPasswordInput {
|
||||
@@ -3267,6 +3284,10 @@ type ActivateAccountPayload {
|
||||
profile: Profile
|
||||
}
|
||||
|
||||
type CreatePasswordPayload {
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
type ForgotPasswordPayload {
|
||||
success: Boolean!
|
||||
}
|
||||
@@ -3557,6 +3578,11 @@ func (ec *executionContext) field_Identity_profiles_args(ctx context.Context, ra
|
||||
return nil, err
|
||||
}
|
||||
args["orderBy"] = arg4
|
||||
arg5, err := graphql.ProcessArgField(ctx, rawArgs, "filter", ec.unmarshalOProfileFilter2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconnectᚋv1ᚋtypesᚐProfileFilter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["filter"] = arg5
|
||||
return args, nil
|
||||
}
|
||||
|
||||
@@ -4730,6 +4756,35 @@ func (ec *executionContext) fieldContext_CreateOrganizationPayload_membership(_
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _CreatePasswordPayload_success(ctx context.Context, field graphql.CollectedField, obj *types.CreatePasswordPayload) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
ec.OperationContext,
|
||||
field,
|
||||
ec.fieldContext_CreatePasswordPayload_success,
|
||||
func(ctx context.Context) (any, error) {
|
||||
return obj.Success, nil
|
||||
},
|
||||
nil,
|
||||
ec.marshalNBoolean2bool,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_CreatePasswordPayload_success(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "CreatePasswordPayload",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type Boolean does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _CreatePersonalAPIKeyPayload_personalAPIKeyEdge(ctx context.Context, field graphql.CollectedField, obj *types.CreatePersonalAPIKeyPayload) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
@@ -5377,7 +5432,7 @@ func (ec *executionContext) _Identity_profiles(ctx context.Context, field graphq
|
||||
ec.fieldContext_Identity_profiles,
|
||||
func(ctx context.Context) (any, error) {
|
||||
fc := graphql.GetFieldContext(ctx)
|
||||
return ec.resolvers.Identity().Profiles(ctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*page.CursorKey), fc.Args["last"].(*int), fc.Args["before"].(*page.CursorKey), fc.Args["orderBy"].(*types.ProfileOrderBy))
|
||||
return ec.resolvers.Identity().Profiles(ctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*page.CursorKey), fc.Args["last"].(*int), fc.Args["before"].(*page.CursorKey), fc.Args["orderBy"].(*types.ProfileOrderBy), fc.Args["filter"].(*types.ProfileFilter))
|
||||
},
|
||||
nil,
|
||||
ec.marshalOProfileConnection2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconnectᚋv1ᚋtypesᚐProfileConnection,
|
||||
@@ -15129,7 +15184,7 @@ func (ec *executionContext) unmarshalInputActivateAccountInput(ctx context.Conte
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"token", "password"}
|
||||
fieldsInOrder := [...]string{"token"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
@@ -15143,13 +15198,6 @@ func (ec *executionContext) unmarshalInputActivateAccountInput(ctx context.Conte
|
||||
return it, err
|
||||
}
|
||||
it.Token = data
|
||||
case "password":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("password"))
|
||||
data, err := ec.unmarshalNString2string(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.Password = data
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15770,6 +15818,40 @@ func (ec *executionContext) unmarshalInputInviteUserInput(ctx context.Context, o
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalInputProfileFilter(ctx context.Context, obj any) (types.ProfileFilter, error) {
|
||||
var it types.ProfileFilter
|
||||
asMap := map[string]any{}
|
||||
for k, v := range obj.(map[string]any) {
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"excludeContractEnded", "state"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
switch k {
|
||||
case "excludeContractEnded":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("excludeContractEnded"))
|
||||
data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.ExcludeContractEnded = data
|
||||
case "state":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("state"))
|
||||
data, err := ec.unmarshalOProfileState2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐProfileState(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.State = data
|
||||
}
|
||||
}
|
||||
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalInputProfileOrder(ctx context.Context, obj any) (types.ProfileOrderBy, error) {
|
||||
var it types.ProfileOrderBy
|
||||
asMap := map[string]any{}
|
||||
@@ -16955,6 +17037,45 @@ func (ec *executionContext) _CreateOrganizationPayload(ctx context.Context, sel
|
||||
return out
|
||||
}
|
||||
|
||||
var createPasswordPayloadImplementors = []string{"CreatePasswordPayload"}
|
||||
|
||||
func (ec *executionContext) _CreatePasswordPayload(ctx context.Context, sel ast.SelectionSet, obj *types.CreatePasswordPayload) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, createPasswordPayloadImplementors)
|
||||
|
||||
out := graphql.NewFieldSet(fields)
|
||||
deferred := make(map[string]*graphql.FieldSet)
|
||||
for i, field := range fields {
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("CreatePasswordPayload")
|
||||
case "success":
|
||||
out.Values[i] = ec._CreatePasswordPayload_success(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
}
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
}
|
||||
out.Dispatch(ctx)
|
||||
if out.Invalids > 0 {
|
||||
return graphql.Null
|
||||
}
|
||||
|
||||
atomic.AddInt32(&ec.deferred, int32(len(deferred)))
|
||||
|
||||
for label, dfs := range deferred {
|
||||
ec.processDeferredGroup(graphql.DeferredGroup{
|
||||
Label: label,
|
||||
Path: graphql.GetPath(ctx),
|
||||
FieldSet: dfs,
|
||||
Context: ctx,
|
||||
})
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
var createPersonalAPIKeyPayloadImplementors = []string{"CreatePersonalAPIKeyPayload"}
|
||||
|
||||
func (ec *executionContext) _CreatePersonalAPIKeyPayload(ctx context.Context, sel ast.SelectionSet, obj *types.CreatePersonalAPIKeyPayload) graphql.Marshaler {
|
||||
@@ -23298,6 +23419,14 @@ func (ec *executionContext) marshalOProfileConnection2ᚖgoᚗproboᚗincᚋprob
|
||||
return ec._ProfileConnection(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalOProfileFilter2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconnectᚋv1ᚋtypesᚐProfileFilter(ctx context.Context, v any) (*types.ProfileFilter, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
res, err := ec.unmarshalInputProfileFilter(ctx, v)
|
||||
return &res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalOProfileOrder2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconnectᚋv1ᚋtypesᚐProfileOrderBy(ctx context.Context, v any) (*types.ProfileOrderBy, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
@@ -23306,6 +23435,36 @@ func (ec *executionContext) unmarshalOProfileOrder2ᚖgoᚗproboᚗincᚋprobo
|
||||
return &res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalOProfileState2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐProfileState(ctx context.Context, v any) (*coredata.ProfileState, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalOProfileState2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐProfileState[tmp]
|
||||
return &res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOProfileState2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐProfileState(ctx context.Context, sel ast.SelectionSet, v *coredata.ProfileState) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
_ = sel
|
||||
_ = ctx
|
||||
res := graphql.MarshalString(marshalOProfileState2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐProfileState[*v])
|
||||
return res
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalOProfileState2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐProfileState = map[string]coredata.ProfileState{
|
||||
"ACTIVE": coredata.ProfileStateActive,
|
||||
"INACTIVE": coredata.ProfileStateInactive,
|
||||
}
|
||||
marshalOProfileState2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐProfileState = map[coredata.ProfileState]string{
|
||||
coredata.ProfileStateActive: "ACTIVE",
|
||||
coredata.ProfileStateInactive: "INACTIVE",
|
||||
}
|
||||
)
|
||||
|
||||
func (ec *executionContext) marshalORegenerateSCIMTokenPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconnectᚋv1ᚋtypesᚐRegenerateSCIMTokenPayload(ctx context.Context, sel ast.SelectionSet, v *types.RegenerateSCIMTokenPayload) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
|
||||
@@ -30,6 +30,7 @@ type (
|
||||
|
||||
Resolver any
|
||||
ParentID gid.GID
|
||||
Filters *coredata.MembershipProfileFilter
|
||||
}
|
||||
)
|
||||
|
||||
@@ -37,6 +38,7 @@ func NewProfileConnection(
|
||||
p *page.Page[*coredata.MembershipProfile, coredata.MembershipProfileOrderField],
|
||||
resolver any,
|
||||
parentID gid.GID,
|
||||
filters *coredata.MembershipProfileFilter,
|
||||
) *ProfileConnection {
|
||||
edges := make([]*ProfileEdge, len(p.Data))
|
||||
for i, profile := range p.Data {
|
||||
@@ -49,6 +51,7 @@ func NewProfileConnection(
|
||||
|
||||
Resolver: resolver,
|
||||
ParentID: parentID,
|
||||
Filters: filters,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,7 @@ type AcceptInvitationPayload struct {
|
||||
}
|
||||
|
||||
type ActivateAccountInput struct {
|
||||
Token string `json:"token"`
|
||||
Password string `json:"password"`
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
type ActivateAccountPayload struct {
|
||||
@@ -92,6 +91,10 @@ type CreateOrganizationPayload struct {
|
||||
Membership *Membership `json:"membership"`
|
||||
}
|
||||
|
||||
type CreatePasswordPayload struct {
|
||||
Success bool `json:"success"`
|
||||
}
|
||||
|
||||
type CreatePersonalAPIKeyInput struct {
|
||||
Name string `json:"name"`
|
||||
ExpiresAt time.Time `json:"expiresAt"`
|
||||
@@ -339,6 +342,11 @@ type ProfileEdge struct {
|
||||
Node *Profile `json:"node"`
|
||||
}
|
||||
|
||||
type ProfileFilter struct {
|
||||
ExcludeContractEnded *bool `json:"excludeContractEnded,omitempty"`
|
||||
State *coredata.ProfileState `json:"state,omitempty"`
|
||||
}
|
||||
|
||||
type Query struct {
|
||||
}
|
||||
|
||||
|
||||
@@ -33,17 +33,24 @@ func (r *connectorResolver) Permission(ctx context.Context, obj *types.Connector
|
||||
}
|
||||
|
||||
// Profiles is the resolver for the profiles field.
|
||||
func (r *identityResolver) Profiles(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy) (*types.ProfileConnection, error) {
|
||||
func (r *identityResolver) Profiles(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy, filter *types.ProfileFilter) (*types.ProfileConnection, error) {
|
||||
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileList, authz.WithSkipAssumptionCheck()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
filter := coredata.NewMembershipProfileFilter(nil)
|
||||
filters := coredata.NewMembershipProfileFilter(nil)
|
||||
if filter != nil {
|
||||
filters = coredata.NewMembershipProfileFilter(filter.ExcludeContractEnded)
|
||||
if filter.State != nil {
|
||||
filters.WithState(*filter.State)
|
||||
}
|
||||
}
|
||||
|
||||
if gqlutils.OnlyTotalCountSelected(ctx) {
|
||||
return &types.ProfileConnection{
|
||||
Resolver: r,
|
||||
ParentID: obj.ID,
|
||||
Filters: filters,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -60,13 +67,13 @@ func (r *identityResolver) Profiles(ctx context.Context, obj *types.Identity, fi
|
||||
|
||||
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
|
||||
|
||||
page, err := r.iam.AccountService.ListProfilesForIdentity(ctx, obj.ID, cursor, filter)
|
||||
page, err := r.iam.AccountService.ListProfilesForIdentity(ctx, obj.ID, cursor, filters)
|
||||
if err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot list profiles", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return types.NewProfileConnection(page, r, obj.ID), nil
|
||||
return types.NewProfileConnection(page, r, obj.ID, filters), nil
|
||||
}
|
||||
|
||||
// Sessions is the resolver for the sessions field.
|
||||
@@ -381,7 +388,6 @@ func (r *mutationResolver) ActivateAccount(ctx context.Context, input types.Acti
|
||||
ctx,
|
||||
&iam.CreateIdentityFromInvitationRequest{
|
||||
InvitationToken: input.Token,
|
||||
Password: input.Password,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
@@ -565,19 +571,19 @@ func (r *mutationResolver) AssumeOrganizationSession(ctx context.Context, input
|
||||
childSession, membership, err := r.iam.SessionService.AssumeOrganizationSession(ctx, rootSession.ID, input.OrganizationID, input.Continue)
|
||||
if err != nil {
|
||||
var (
|
||||
errMembershipNotFound *iam.ErrMembershipNotFound
|
||||
errPasswordRequired *iam.ErrPasswordRequired
|
||||
errSAMLAuthenticationRequired *iam.ErrSAMLAuthenticationRequired
|
||||
errMembershipNotFound *iam.ErrMembershipNotFound
|
||||
errPasswordAuthenticationRequired *iam.ErrPasswordAuthenticationRequired
|
||||
errSAMLAuthenticationRequired *iam.ErrSAMLAuthenticationRequired
|
||||
)
|
||||
|
||||
switch {
|
||||
case errors.As(err, &errMembershipNotFound):
|
||||
return nil, gqlutils.NotFound(ctx, err)
|
||||
|
||||
case errors.As(err, &errPasswordRequired):
|
||||
case errors.As(err, &errPasswordAuthenticationRequired):
|
||||
return &types.AssumeOrganizationSessionPayload{
|
||||
Result: types.PasswordRequired{
|
||||
Reason: types.ReauthenticationReason(errPasswordRequired.Reason),
|
||||
Reason: types.ReauthenticationReason(errPasswordAuthenticationRequired.Reason),
|
||||
},
|
||||
}, nil
|
||||
|
||||
@@ -1199,7 +1205,7 @@ func (r *organizationResolver) Profiles(ctx context.Context, obj *types.Organiza
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
return types.NewProfileConnection(page, r, obj.ID), nil
|
||||
return types.NewProfileConnection(page, r, obj.ID, filter), nil
|
||||
}
|
||||
|
||||
// SamlConfigurations is the resolver for the samlConfigurations field.
|
||||
|
||||
Reference in New Issue
Block a user