Add ssoLoginURL in activate account outputs
Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<852ecee082c322aba273f04575353fbd>>
|
* @generated SignedSource<<e2bdaf924ff82d11f3c2ef4a8353c8e8>>
|
||||||
* @lightSyntaxTransform
|
* @lightSyntaxTransform
|
||||||
* @nogrep
|
* @nogrep
|
||||||
*/
|
*/
|
||||||
@@ -18,6 +18,7 @@ export type ActivateAccountPageMutation$variables = {
|
|||||||
export type ActivateAccountPageMutation$data = {
|
export type ActivateAccountPageMutation$data = {
|
||||||
readonly activateAccount: {
|
readonly activateAccount: {
|
||||||
readonly createPasswordToken: string | null | undefined;
|
readonly createPasswordToken: string | null | undefined;
|
||||||
|
readonly ssoLoginUrl: string | null | undefined;
|
||||||
} | null | undefined;
|
} | null | undefined;
|
||||||
};
|
};
|
||||||
export type ActivateAccountPageMutation = {
|
export type ActivateAccountPageMutation = {
|
||||||
@@ -54,6 +55,13 @@ v1 = [
|
|||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "createPasswordToken",
|
"name": "createPasswordToken",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "ssoLoginUrl",
|
||||||
|
"storageKey": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
@@ -77,16 +85,16 @@ return {
|
|||||||
"selections": (v1/*: any*/)
|
"selections": (v1/*: any*/)
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
"cacheID": "388c90522ecf3a3365e171a623fb2d2e",
|
"cacheID": "ab62d7332fce4af79b46c8627e551370",
|
||||||
"id": null,
|
"id": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"name": "ActivateAccountPageMutation",
|
"name": "ActivateAccountPageMutation",
|
||||||
"operationKind": "mutation",
|
"operationKind": "mutation",
|
||||||
"text": "mutation ActivateAccountPageMutation(\n $input: ActivateAccountInput!\n) {\n activateAccount(input: $input) {\n createPasswordToken\n }\n}\n"
|
"text": "mutation ActivateAccountPageMutation(\n $input: ActivateAccountInput!\n) {\n activateAccount(input: $input) {\n createPasswordToken\n ssoLoginUrl\n }\n}\n"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
(node as any).hash = "c27b723383934423bf92926820426653";
|
(node as any).hash = "fd91da524bb46256a9d8e1ae31590dc2";
|
||||||
|
|
||||||
export default node;
|
export default node;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ const activateAccountMutation = graphql`
|
|||||||
) {
|
) {
|
||||||
activateAccount(input: $input) {
|
activateAccount(input: $input) {
|
||||||
createPasswordToken
|
createPasswordToken
|
||||||
|
ssoLoginUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@@ -73,6 +74,14 @@ export default function ActivateAccountPage() {
|
|||||||
throw new Error("mutation data missing");
|
throw new Error("mutation data missing");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (activateAccount.ssoLoginUrl) {
|
||||||
|
const url = new URL(activateAccount.ssoLoginUrl);
|
||||||
|
url.search = searchParams.toString();
|
||||||
|
|
||||||
|
window.location.href = url.toString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (activateAccount.createPasswordToken) {
|
if (activateAccount.createPasswordToken) {
|
||||||
const search = new URLSearchParams([
|
const search = new URLSearchParams([
|
||||||
["token", activateAccount.createPasswordToken],
|
["token", activateAccount.createPasswordToken],
|
||||||
@@ -85,12 +94,14 @@ export default function ActivateAccountPage() {
|
|||||||
},
|
},
|
||||||
{ replace: true },
|
{ replace: true },
|
||||||
);
|
);
|
||||||
} else {
|
return;
|
||||||
void navigate({
|
|
||||||
pathname: safeContinueUrl.pathname,
|
|
||||||
search: safeContinueUrl.search,
|
|
||||||
}, { replace: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const search = new URLSearchParams([["continue", safeContinueUrl.toString()]]);
|
||||||
|
void navigate({
|
||||||
|
pathname: "/auth/password-login",
|
||||||
|
search: "?" + search.toString(),
|
||||||
|
}, { replace: true });
|
||||||
},
|
},
|
||||||
onError: (e) => {
|
onError: (e) => {
|
||||||
toast({
|
toast({
|
||||||
@@ -100,7 +111,7 @@ export default function ActivateAccountPage() {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}, [__, toast, activateAccount, navigate, safeContinueUrl]);
|
}, [__, toast, activateAccount, navigate, safeContinueUrl, searchParams]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const token = searchParams.get("token");
|
const token = searchParams.get("token");
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ func (req CreateIdentityWithPasswordRequest) Validate() error {
|
|||||||
func (s *AuthService) ActivateAccount(
|
func (s *AuthService) ActivateAccount(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req *ActivateAccountRequest,
|
req *ActivateAccountRequest,
|
||||||
) (*coredata.MembershipProfile, *string, error) {
|
) (*coredata.Identity, *coredata.MembershipProfile, error) {
|
||||||
if err := req.Validate(); err != nil {
|
if err := req.Validate(); err != nil {
|
||||||
return nil, nil, fmt.Errorf("invalid request: %w", err)
|
return nil, nil, fmt.Errorf("invalid request: %w", err)
|
||||||
}
|
}
|
||||||
@@ -146,15 +146,14 @@ func (s *AuthService) ActivateAccount(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
scope = coredata.NewScopeFromObjectID(payload.Data.InvitationID)
|
scope = coredata.NewScopeFromObjectID(payload.Data.InvitationID)
|
||||||
invitation = &coredata.Invitation{}
|
invitation = &coredata.Invitation{}
|
||||||
profile *coredata.MembershipProfile
|
profile *coredata.MembershipProfile
|
||||||
identity *coredata.Identity
|
identity *coredata.Identity
|
||||||
now = time.Now()
|
now = time.Now()
|
||||||
createPasswordToken *string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
err = s.pg.WithTx(
|
if err = s.pg.WithTx(
|
||||||
ctx,
|
ctx,
|
||||||
func(tx pg.Conn) error {
|
func(tx pg.Conn) error {
|
||||||
err := invitation.LoadByID(ctx, tx, scope, payload.Data.InvitationID)
|
err := invitation.LoadByID(ctx, tx, scope, payload.Data.InvitationID)
|
||||||
@@ -229,36 +228,25 @@ func (s *AuthService) ActivateAccount(
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
)
|
); err != nil {
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
count, err := s.AccountService.CountSAMLConfigurationsForEmail(ctx, identity.EmailAddress)
|
return identity, profile, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s AuthService) GetResetPasswordToken(ctx context.Context, email mail.Addr) (string, error) {
|
||||||
|
token, err := statelesstoken.NewToken(
|
||||||
|
s.tokenSecret,
|
||||||
|
TokenTypePasswordReset,
|
||||||
|
s.passwordResetTokenValidity,
|
||||||
|
PasswordResetData{Email: email},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("cannot count SAML configurations: %w", err)
|
return "", fmt.Errorf("cannot generate password create token: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if count > 0 {
|
return token, nil
|
||||||
return profile, nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if identity.HashedPassword == nil {
|
|
||||||
token, err := statelesstoken.NewToken(
|
|
||||||
s.tokenSecret,
|
|
||||||
TokenTypePasswordReset,
|
|
||||||
s.passwordResetTokenValidity,
|
|
||||||
PasswordResetData{Email: identity.EmailAddress},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("cannot generate password create token: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
createPasswordToken = &token
|
|
||||||
}
|
|
||||||
|
|
||||||
return profile, createPasswordToken, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s AuthService) ResetPassword(
|
func (s AuthService) ResetPassword(
|
||||||
@@ -313,12 +301,7 @@ func (s AuthService) SendPasswordResetInstructionByEmail(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
email mail.Addr,
|
email mail.Addr,
|
||||||
) error {
|
) error {
|
||||||
token, err := statelesstoken.NewToken(
|
token, err := s.GetResetPasswordToken(ctx, email)
|
||||||
s.tokenSecret,
|
|
||||||
TokenTypePasswordReset,
|
|
||||||
s.passwordResetTokenValidity,
|
|
||||||
PasswordResetData{Email: email},
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot generate password reset token: %w", err)
|
return fmt.Errorf("cannot generate password reset token: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -788,6 +788,7 @@ type SignOutPayload {
|
|||||||
|
|
||||||
type ActivateAccountPayload {
|
type ActivateAccountPayload {
|
||||||
createPasswordToken: String
|
createPasswordToken: String
|
||||||
|
ssoLoginUrl: String
|
||||||
profile: Profile
|
profile: Profile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ type ComplexityRoot struct {
|
|||||||
ActivateAccountPayload struct {
|
ActivateAccountPayload struct {
|
||||||
CreatePasswordToken func(childComplexity int) int
|
CreatePasswordToken func(childComplexity int) int
|
||||||
Profile func(childComplexity int) int
|
Profile func(childComplexity int) int
|
||||||
|
SsoLoginURL func(childComplexity int) int
|
||||||
}
|
}
|
||||||
|
|
||||||
AssumeOrganizationSessionPayload struct {
|
AssumeOrganizationSessionPayload struct {
|
||||||
@@ -623,6 +624,12 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
return e.ComplexityRoot.ActivateAccountPayload.Profile(childComplexity), true
|
return e.ComplexityRoot.ActivateAccountPayload.Profile(childComplexity), true
|
||||||
|
case "ActivateAccountPayload.ssoLoginUrl":
|
||||||
|
if e.ComplexityRoot.ActivateAccountPayload.SsoLoginURL == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.ComplexityRoot.ActivateAccountPayload.SsoLoginURL(childComplexity), true
|
||||||
|
|
||||||
case "AssumeOrganizationSessionPayload.result":
|
case "AssumeOrganizationSessionPayload.result":
|
||||||
if e.ComplexityRoot.AssumeOrganizationSessionPayload.Result == nil {
|
if e.ComplexityRoot.AssumeOrganizationSessionPayload.Result == nil {
|
||||||
@@ -3206,6 +3213,7 @@ type SignOutPayload {
|
|||||||
|
|
||||||
type ActivateAccountPayload {
|
type ActivateAccountPayload {
|
||||||
createPasswordToken: String
|
createPasswordToken: String
|
||||||
|
ssoLoginUrl: String
|
||||||
profile: Profile
|
profile: Profile
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4195,6 +4203,35 @@ func (ec *executionContext) fieldContext_ActivateAccountPayload_createPasswordTo
|
|||||||
return fc, nil
|
return fc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _ActivateAccountPayload_ssoLoginUrl(ctx context.Context, field graphql.CollectedField, obj *types.ActivateAccountPayload) (ret graphql.Marshaler) {
|
||||||
|
return graphql.ResolveField(
|
||||||
|
ctx,
|
||||||
|
ec.OperationContext,
|
||||||
|
field,
|
||||||
|
ec.fieldContext_ActivateAccountPayload_ssoLoginUrl,
|
||||||
|
func(ctx context.Context) (any, error) {
|
||||||
|
return obj.SsoLoginURL, nil
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
ec.marshalOString2ᚖstring,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) fieldContext_ActivateAccountPayload_ssoLoginUrl(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||||
|
fc = &graphql.FieldContext{
|
||||||
|
Object: "ActivateAccountPayload",
|
||||||
|
Field: field,
|
||||||
|
IsMethod: false,
|
||||||
|
IsResolver: false,
|
||||||
|
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||||
|
return nil, errors.New("field of type String does not have child fields")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return fc, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _ActivateAccountPayload_profile(ctx context.Context, field graphql.CollectedField, obj *types.ActivateAccountPayload) (ret graphql.Marshaler) {
|
func (ec *executionContext) _ActivateAccountPayload_profile(ctx context.Context, field graphql.CollectedField, obj *types.ActivateAccountPayload) (ret graphql.Marshaler) {
|
||||||
return graphql.ResolveField(
|
return graphql.ResolveField(
|
||||||
ctx,
|
ctx,
|
||||||
@@ -6342,6 +6379,8 @@ func (ec *executionContext) fieldContext_Mutation_activateAccount(ctx context.Co
|
|||||||
switch field.Name {
|
switch field.Name {
|
||||||
case "createPasswordToken":
|
case "createPasswordToken":
|
||||||
return ec.fieldContext_ActivateAccountPayload_createPasswordToken(ctx, field)
|
return ec.fieldContext_ActivateAccountPayload_createPasswordToken(ctx, field)
|
||||||
|
case "ssoLoginUrl":
|
||||||
|
return ec.fieldContext_ActivateAccountPayload_ssoLoginUrl(ctx, field)
|
||||||
case "profile":
|
case "profile":
|
||||||
return ec.fieldContext_ActivateAccountPayload_profile(ctx, field)
|
return ec.fieldContext_ActivateAccountPayload_profile(ctx, field)
|
||||||
}
|
}
|
||||||
@@ -16444,6 +16483,8 @@ func (ec *executionContext) _ActivateAccountPayload(ctx context.Context, sel ast
|
|||||||
out.Values[i] = graphql.MarshalString("ActivateAccountPayload")
|
out.Values[i] = graphql.MarshalString("ActivateAccountPayload")
|
||||||
case "createPasswordToken":
|
case "createPasswordToken":
|
||||||
out.Values[i] = ec._ActivateAccountPayload_createPasswordToken(ctx, field, obj)
|
out.Values[i] = ec._ActivateAccountPayload_createPasswordToken(ctx, field, obj)
|
||||||
|
case "ssoLoginUrl":
|
||||||
|
out.Values[i] = ec._ActivateAccountPayload_ssoLoginUrl(ctx, field, obj)
|
||||||
case "profile":
|
case "profile":
|
||||||
out.Values[i] = ec._ActivateAccountPayload_profile(ctx, field, obj)
|
out.Values[i] = ec._ActivateAccountPayload_profile(ctx, field, obj)
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ type ActivateAccountInput struct {
|
|||||||
|
|
||||||
type ActivateAccountPayload struct {
|
type ActivateAccountPayload struct {
|
||||||
CreatePasswordToken *string `json:"createPasswordToken,omitempty"`
|
CreatePasswordToken *string `json:"createPasswordToken,omitempty"`
|
||||||
|
SsoLoginURL *string `json:"ssoLoginUrl,omitempty"`
|
||||||
Profile *Profile `json:"profile,omitempty"`
|
Profile *Profile `json:"profile,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ func (r *mutationResolver) ActivateAccount(ctx context.Context, input types.Acti
|
|||||||
r.sessionCookie.Clear(w)
|
r.sessionCookie.Clear(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
user, createPasswordToken, err := r.iam.AuthService.ActivateAccount(
|
identity, user, err := r.iam.AuthService.ActivateAccount(
|
||||||
ctx,
|
ctx,
|
||||||
&iam.ActivateAccountRequest{
|
&iam.ActivateAccountRequest{
|
||||||
InvitationToken: input.Token,
|
InvitationToken: input.Token,
|
||||||
@@ -400,8 +400,42 @@ func (r *mutationResolver) ActivateAccount(ctx context.Context, input types.Acti
|
|||||||
return nil, gqlutils.Internal(ctx)
|
return nil, gqlutils.Internal(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ssoLoginURL *string
|
||||||
|
samlConfigs, err := r.iam.AccountService.ListSAMLConfigurationsForEmail(ctx, user.EmailAddress)
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot list saml configurations", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, samlConfig := range samlConfigs {
|
||||||
|
if samlConfig.OrganizationID != user.OrganizationID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ssoLoginURL = new(r.SSOLoginURL(samlConfig.ID))
|
||||||
|
}
|
||||||
|
|
||||||
|
if ssoLoginURL != nil {
|
||||||
|
return &types.ActivateAccountPayload{
|
||||||
|
CreatePasswordToken: nil,
|
||||||
|
SsoLoginURL: ssoLoginURL,
|
||||||
|
Profile: types.NewProfile(user),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var createPasswordToken *string
|
||||||
|
if identity.HashedPassword == nil {
|
||||||
|
token, err := r.iam.AuthService.GetResetPasswordToken(ctx, identity.EmailAddress)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot generate password create token: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
createPasswordToken = &token
|
||||||
|
}
|
||||||
|
|
||||||
return &types.ActivateAccountPayload{
|
return &types.ActivateAccountPayload{
|
||||||
CreatePasswordToken: createPasswordToken,
|
CreatePasswordToken: createPasswordToken,
|
||||||
|
SsoLoginURL: nil,
|
||||||
Profile: types.NewProfile(user),
|
Profile: types.NewProfile(user),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user