Create flow to add password after account activation
Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<b79143becc90a4776f321d0e91db49bd>>
|
* @generated SignedSource<<852ecee082c322aba273f04575353fbd>>
|
||||||
* @lightSyntaxTransform
|
* @lightSyntaxTransform
|
||||||
* @nogrep
|
* @nogrep
|
||||||
*/
|
*/
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
import { ConcreteRequest } from 'relay-runtime';
|
import { ConcreteRequest } from 'relay-runtime';
|
||||||
export type ActivateAccountInput = {
|
export type ActivateAccountInput = {
|
||||||
password?: string | null | undefined;
|
|
||||||
token: string;
|
token: string;
|
||||||
};
|
};
|
||||||
export type ActivateAccountPageMutation$variables = {
|
export type ActivateAccountPageMutation$variables = {
|
||||||
@@ -18,9 +17,7 @@ export type ActivateAccountPageMutation$variables = {
|
|||||||
};
|
};
|
||||||
export type ActivateAccountPageMutation$data = {
|
export type ActivateAccountPageMutation$data = {
|
||||||
readonly activateAccount: {
|
readonly activateAccount: {
|
||||||
readonly profile: {
|
readonly createPasswordToken: string | null | undefined;
|
||||||
readonly id: string;
|
|
||||||
} | null | undefined;
|
|
||||||
} | null | undefined;
|
} | null | undefined;
|
||||||
};
|
};
|
||||||
export type ActivateAccountPageMutation = {
|
export type ActivateAccountPageMutation = {
|
||||||
@@ -54,19 +51,8 @@ v1 = [
|
|||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
"concreteType": "Profile",
|
"kind": "ScalarField",
|
||||||
"kind": "LinkedField",
|
"name": "createPasswordToken",
|
||||||
"name": "profile",
|
|
||||||
"plural": false,
|
|
||||||
"selections": [
|
|
||||||
{
|
|
||||||
"alias": null,
|
|
||||||
"args": null,
|
|
||||||
"kind": "ScalarField",
|
|
||||||
"name": "id",
|
|
||||||
"storageKey": null
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -91,16 +77,16 @@ return {
|
|||||||
"selections": (v1/*: any*/)
|
"selections": (v1/*: any*/)
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
"cacheID": "57d92d0ae2a6220af84fbd9fe27f7aa3",
|
"cacheID": "388c90522ecf3a3365e171a623fb2d2e",
|
||||||
"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 profile {\n id\n }\n }\n}\n"
|
"text": "mutation ActivateAccountPageMutation(\n $input: ActivateAccountInput!\n) {\n activateAccount(input: $input) {\n createPasswordToken\n }\n}\n"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
(node as any).hash = "0e073ce00eb7c435a875b5797f3e6db0";
|
(node as any).hash = "c27b723383934423bf92926820426653";
|
||||||
|
|
||||||
export default node;
|
export default node;
|
||||||
|
|||||||
93
apps/console/src/__generated__/iam/CreatePasswordPageMutation.graphql.ts
generated
Normal file
93
apps/console/src/__generated__/iam/CreatePasswordPageMutation.graphql.ts
generated
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/**
|
||||||
|
* @generated SignedSource<<cde2278cb4ed7c350f1c8727933cd92d>>
|
||||||
|
* @lightSyntaxTransform
|
||||||
|
* @nogrep
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ConcreteRequest } from 'relay-runtime';
|
||||||
|
export type ResetPasswordInput = {
|
||||||
|
password: string;
|
||||||
|
token: string;
|
||||||
|
};
|
||||||
|
export type CreatePasswordPageMutation$variables = {
|
||||||
|
input: ResetPasswordInput;
|
||||||
|
};
|
||||||
|
export type CreatePasswordPageMutation$data = {
|
||||||
|
readonly resetPassword: {
|
||||||
|
readonly success: boolean;
|
||||||
|
} | null | undefined;
|
||||||
|
};
|
||||||
|
export type CreatePasswordPageMutation = {
|
||||||
|
response: CreatePasswordPageMutation$data;
|
||||||
|
variables: CreatePasswordPageMutation$variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
const node: ConcreteRequest = (function(){
|
||||||
|
var v0 = [
|
||||||
|
{
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "input"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v1 = [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "input",
|
||||||
|
"variableName": "input"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"concreteType": "ResetPasswordPayload",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "resetPassword",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "success",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return {
|
||||||
|
"fragment": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": null,
|
||||||
|
"name": "CreatePasswordPageMutation",
|
||||||
|
"selections": (v1/*: any*/),
|
||||||
|
"type": "Mutation",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "CreatePasswordPageMutation",
|
||||||
|
"selections": (v1/*: any*/)
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"cacheID": "aedb0b874e2e55a106724665d51f840e",
|
||||||
|
"id": null,
|
||||||
|
"metadata": {},
|
||||||
|
"name": "CreatePasswordPageMutation",
|
||||||
|
"operationKind": "mutation",
|
||||||
|
"text": "mutation CreatePasswordPageMutation(\n $input: ResetPasswordInput!\n) {\n resetPassword(input: $input) {\n success\n }\n}\n"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
(node as any).hash = "d9bd91787098b9272f0046ad09554a1a";
|
||||||
|
|
||||||
|
export default node;
|
||||||
@@ -7,16 +7,14 @@ import { useMutation } from "react-relay";
|
|||||||
import { Link, useNavigate, useSearchParams } from "react-router";
|
import { Link, useNavigate, useSearchParams } from "react-router";
|
||||||
import { graphql } from "relay-runtime";
|
import { graphql } from "relay-runtime";
|
||||||
|
|
||||||
import type { ActivateAccountPageMutation } from "#/__generated__/iam/ActivateAccountPageMutation.graphql";
|
import type { ActivateAccountPageMutation$data, ActivateAccountPageMutation } from "#/__generated__/iam/ActivateAccountPageMutation.graphql";
|
||||||
|
|
||||||
const activateAccountMutation = graphql`
|
const activateAccountMutation = graphql`
|
||||||
mutation ActivateAccountPageMutation(
|
mutation ActivateAccountPageMutation(
|
||||||
$input: ActivateAccountInput!
|
$input: ActivateAccountInput!
|
||||||
) {
|
) {
|
||||||
activateAccount(input: $input) {
|
activateAccount(input: $input) {
|
||||||
profile {
|
createPasswordToken
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@@ -39,7 +37,7 @@ export default function ActivateAccountPage() {
|
|||||||
variables: {
|
variables: {
|
||||||
input: { token },
|
input: { token },
|
||||||
},
|
},
|
||||||
onCompleted: (_, errors: GraphQLError[] | null) => {
|
onCompleted: (response: ActivateAccountPageMutation$data, errors: GraphQLError[] | null) => {
|
||||||
if (errors) {
|
if (errors) {
|
||||||
for (const err of errors) {
|
for (const err of errors) {
|
||||||
if (err.extensions?.code === "ALREADY_AUTHENTICATED") {
|
if (err.extensions?.code === "ALREADY_AUTHENTICATED") {
|
||||||
@@ -63,7 +61,21 @@ export default function ActivateAccountPage() {
|
|||||||
),
|
),
|
||||||
variant: "success",
|
variant: "success",
|
||||||
});
|
});
|
||||||
void navigate("/", { replace: true });
|
|
||||||
|
const { activateAccount } = response;
|
||||||
|
|
||||||
|
if (!activateAccount) {
|
||||||
|
throw new Error("mutation data missing");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activateAccount.createPasswordToken) {
|
||||||
|
void navigate(
|
||||||
|
{ pathname: "/auth/create-password", search: `?token=${activateAccount.createPasswordToken}` },
|
||||||
|
{ replace: true },
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
void navigate("/", { replace: true });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onError: (e) => {
|
onError: (e) => {
|
||||||
toast({
|
toast({
|
||||||
|
|||||||
114
apps/console/src/pages/iam/auth/CreatePasswordPage.tsx
Normal file
114
apps/console/src/pages/iam/auth/CreatePasswordPage.tsx
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
import { formatError } from "@probo/helpers";
|
||||||
|
import { usePageTitle } from "@probo/hooks";
|
||||||
|
import { useTranslate } from "@probo/i18n";
|
||||||
|
import { Button, Field, useToast } from "@probo/ui";
|
||||||
|
import { useMutation } from "react-relay";
|
||||||
|
import { Link, useNavigate, useSearchParams } from "react-router";
|
||||||
|
import { graphql } from "relay-runtime";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import type { CreatePasswordPageMutation } from "#/__generated__/iam/CreatePasswordPageMutation.graphql";
|
||||||
|
import { useFormWithSchema } from "#/hooks/useFormWithSchema";
|
||||||
|
|
||||||
|
const createPasswordMutation = graphql`
|
||||||
|
mutation CreatePasswordPageMutation($input: ResetPasswordInput!) {
|
||||||
|
resetPassword(input: $input) {
|
||||||
|
success
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const schema = z.object({
|
||||||
|
password: z.string().min(8),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default function CreatePasswordPage() {
|
||||||
|
const { __ } = useTranslate();
|
||||||
|
const { toast } = useToast();
|
||||||
|
const [searchParams] = useSearchParams();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
usePageTitle(__("Create Password"));
|
||||||
|
|
||||||
|
const { register, handleSubmit, formState } = useFormWithSchema(schema, {
|
||||||
|
defaultValues: {
|
||||||
|
password: "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [createPassword, isCreatingPassword] = useMutation<CreatePasswordPageMutation>(createPasswordMutation);
|
||||||
|
|
||||||
|
const onSubmit = (data: z.infer<typeof schema>) => {
|
||||||
|
createPassword({
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
password: data.password,
|
||||||
|
token: searchParams.get("token") ?? "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
onCompleted: (_, e) => {
|
||||||
|
if (e) {
|
||||||
|
toast({
|
||||||
|
title: __("Password creation failed"),
|
||||||
|
description: formatError(__("Password creation failed"), e),
|
||||||
|
variant: "error",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
toast({
|
||||||
|
title: __("Success"),
|
||||||
|
description: __("Account created successfully"),
|
||||||
|
variant: "success",
|
||||||
|
});
|
||||||
|
void navigate("/auth/login", { replace: true });
|
||||||
|
},
|
||||||
|
onError: (e) => {
|
||||||
|
toast({
|
||||||
|
title: __("Password creation failed"),
|
||||||
|
description: e.message,
|
||||||
|
variant: "error",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-6 w-full max-w-md mx-auto pt-8">
|
||||||
|
<div className="space-y-2 text-center">
|
||||||
|
<h1 className="text-3xl font-bold">{__("Create a password")}</h1>
|
||||||
|
<p className="text-txt-tertiary">
|
||||||
|
{__("Set a password for your account, with at least 8 characters")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form onSubmit={e => void handleSubmit(onSubmit)(e)} className="space-y-4">
|
||||||
|
<Field
|
||||||
|
label={__("Password")}
|
||||||
|
type="password"
|
||||||
|
placeholder="••••••••"
|
||||||
|
{...register("password")}
|
||||||
|
required
|
||||||
|
error={formState.errors.password?.message}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Button type="submit" className="w-xs h-10 mx-auto mt-6" disabled={formState.isLoading || isCreatingPassword}>
|
||||||
|
{__("Save")}
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div className="text-center">
|
||||||
|
<p className="text-sm text-txt-tertiary">
|
||||||
|
{__("Already have an account?")}
|
||||||
|
{" "}
|
||||||
|
<Link
|
||||||
|
to="/auth/login"
|
||||||
|
className="underline text-txt-primary hover:text-txt-secondary"
|
||||||
|
>
|
||||||
|
{__("Log in here")}
|
||||||
|
</Link>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -68,6 +68,12 @@ const routes = [
|
|||||||
() => import("./pages/iam/auth/ActivateAccountPage"),
|
() => import("./pages/iam/auth/ActivateAccountPage"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "create-password",
|
||||||
|
Component: lazy(
|
||||||
|
() => import("./pages/iam/auth/CreatePasswordPage"),
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "forgot-password",
|
path: "forgot-password",
|
||||||
Component: lazy(() => import("./pages/iam/auth/ForgotPasswordPage")),
|
Component: lazy(() => import("./pages/iam/auth/ForgotPasswordPage")),
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ type (
|
|||||||
NewPassword string
|
NewPassword string
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateIdentityFromInvitationRequest struct {
|
ActivateAccountRequest struct {
|
||||||
InvitationToken string
|
InvitationToken string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ func NewAuthService(svc *Service) *AuthService {
|
|||||||
return &AuthService{Service: svc}
|
return &AuthService{Service: svc}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (req CreateIdentityFromInvitationRequest) Validate() error {
|
func (req ActivateAccountRequest) Validate() error {
|
||||||
v := validator.New()
|
v := validator.New()
|
||||||
|
|
||||||
v.Check(req.InvitationToken, "invitationToken", validator.NotEmpty())
|
v.Check(req.InvitationToken, "invitationToken", validator.NotEmpty())
|
||||||
@@ -132,8 +132,8 @@ func (req CreateIdentityWithPasswordRequest) Validate() error {
|
|||||||
|
|
||||||
func (s *AuthService) ActivateAccount(
|
func (s *AuthService) ActivateAccount(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req *CreateIdentityFromInvitationRequest,
|
req *ActivateAccountRequest,
|
||||||
) (*coredata.MembershipProfile, *coredata.Session, error) {
|
) (*coredata.MembershipProfile, *string, 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)
|
||||||
}
|
}
|
||||||
@@ -144,11 +144,12 @@ 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
|
||||||
session *coredata.Session
|
identity *coredata.Identity
|
||||||
now = time.Now()
|
now = time.Now()
|
||||||
|
createPasswordToken *string
|
||||||
)
|
)
|
||||||
|
|
||||||
err = s.pg.WithTx(
|
err = s.pg.WithTx(
|
||||||
@@ -185,7 +186,7 @@ func (s *AuthService) ActivateAccount(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
identity := &coredata.Identity{}
|
identity = &coredata.Identity{}
|
||||||
if err := identity.LoadByID(ctx, tx, profile.IdentityID); err != nil {
|
if err := identity.LoadByID(ctx, tx, profile.IdentityID); err != nil {
|
||||||
return fmt.Errorf("cannot load identity: %w", err)
|
return fmt.Errorf("cannot load identity: %w", err)
|
||||||
}
|
}
|
||||||
@@ -220,12 +221,6 @@ func (s *AuthService) ActivateAccount(
|
|||||||
return fmt.Errorf("cannot expire pending invitations: %w", err)
|
return fmt.Errorf("cannot expire pending invitations: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
session = coredata.NewRootSession(identity.ID, coredata.AuthMethodPassword, s.sessionDuration)
|
|
||||||
err = session.Insert(ctx, tx)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("cannot insert session: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -234,7 +229,21 @@ func (s *AuthService) ActivateAccount(
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return profile, session, 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(
|
||||||
|
|||||||
@@ -796,13 +796,10 @@ type SignOutPayload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ActivateAccountPayload {
|
type ActivateAccountPayload {
|
||||||
|
createPasswordToken: String
|
||||||
profile: Profile
|
profile: Profile
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreatePasswordPayload {
|
|
||||||
success: Boolean!
|
|
||||||
}
|
|
||||||
|
|
||||||
type ForgotPasswordPayload {
|
type ForgotPasswordPayload {
|
||||||
success: Boolean!
|
success: Boolean!
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,8 @@ type ComplexityRoot struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ActivateAccountPayload struct {
|
ActivateAccountPayload struct {
|
||||||
Profile func(childComplexity int) int
|
CreatePasswordToken func(childComplexity int) int
|
||||||
|
Profile func(childComplexity int) int
|
||||||
}
|
}
|
||||||
|
|
||||||
AssumeOrganizationSessionPayload struct {
|
AssumeOrganizationSessionPayload struct {
|
||||||
@@ -108,10 +109,6 @@ type ComplexityRoot struct {
|
|||||||
Organization func(childComplexity int) int
|
Organization func(childComplexity int) int
|
||||||
}
|
}
|
||||||
|
|
||||||
CreatePasswordPayload struct {
|
|
||||||
Success func(childComplexity int) int
|
|
||||||
}
|
|
||||||
|
|
||||||
CreatePersonalAPIKeyPayload struct {
|
CreatePersonalAPIKeyPayload struct {
|
||||||
PersonalAPIKeyEdge func(childComplexity int) int
|
PersonalAPIKeyEdge func(childComplexity int) int
|
||||||
Token func(childComplexity int) int
|
Token func(childComplexity int) int
|
||||||
@@ -654,6 +651,12 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
|||||||
|
|
||||||
return e.complexity.AcceptInvitationPayload.Membership(childComplexity), true
|
return e.complexity.AcceptInvitationPayload.Membership(childComplexity), true
|
||||||
|
|
||||||
|
case "ActivateAccountPayload.createPasswordToken":
|
||||||
|
if e.complexity.ActivateAccountPayload.CreatePasswordToken == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.ActivateAccountPayload.CreatePasswordToken(childComplexity), true
|
||||||
case "ActivateAccountPayload.profile":
|
case "ActivateAccountPayload.profile":
|
||||||
if e.complexity.ActivateAccountPayload.Profile == nil {
|
if e.complexity.ActivateAccountPayload.Profile == nil {
|
||||||
break
|
break
|
||||||
@@ -731,13 +734,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
|||||||
|
|
||||||
return e.complexity.CreateOrganizationPayload.Organization(childComplexity), true
|
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":
|
case "CreatePersonalAPIKeyPayload.personalAPIKeyEdge":
|
||||||
if e.complexity.CreatePersonalAPIKeyPayload.PersonalAPIKeyEdge == nil {
|
if e.complexity.CreatePersonalAPIKeyPayload.PersonalAPIKeyEdge == nil {
|
||||||
break
|
break
|
||||||
@@ -3281,13 +3277,10 @@ type SignOutPayload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ActivateAccountPayload {
|
type ActivateAccountPayload {
|
||||||
|
createPasswordToken: String
|
||||||
profile: Profile
|
profile: Profile
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreatePasswordPayload {
|
|
||||||
success: Boolean!
|
|
||||||
}
|
|
||||||
|
|
||||||
type ForgotPasswordPayload {
|
type ForgotPasswordPayload {
|
||||||
success: Boolean!
|
success: Boolean!
|
||||||
}
|
}
|
||||||
@@ -4327,6 +4320,35 @@ func (ec *executionContext) fieldContext_AcceptInvitationPayload_invitation(_ co
|
|||||||
return fc, nil
|
return fc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _ActivateAccountPayload_createPasswordToken(ctx context.Context, field graphql.CollectedField, obj *types.ActivateAccountPayload) (ret graphql.Marshaler) {
|
||||||
|
return graphql.ResolveField(
|
||||||
|
ctx,
|
||||||
|
ec.OperationContext,
|
||||||
|
field,
|
||||||
|
ec.fieldContext_ActivateAccountPayload_createPasswordToken,
|
||||||
|
func(ctx context.Context) (any, error) {
|
||||||
|
return obj.CreatePasswordToken, nil
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
ec.marshalOString2ᚖstring,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) fieldContext_ActivateAccountPayload_createPasswordToken(_ 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,
|
||||||
@@ -4756,35 +4778,6 @@ func (ec *executionContext) fieldContext_CreateOrganizationPayload_membership(_
|
|||||||
return fc, nil
|
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) {
|
func (ec *executionContext) _CreatePersonalAPIKeyPayload_personalAPIKeyEdge(ctx context.Context, field graphql.CollectedField, obj *types.CreatePersonalAPIKeyPayload) (ret graphql.Marshaler) {
|
||||||
return graphql.ResolveField(
|
return graphql.ResolveField(
|
||||||
ctx,
|
ctx,
|
||||||
@@ -6636,6 +6629,8 @@ func (ec *executionContext) fieldContext_Mutation_activateAccount(ctx context.Co
|
|||||||
IsResolver: true,
|
IsResolver: true,
|
||||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||||
switch field.Name {
|
switch field.Name {
|
||||||
|
case "createPasswordToken":
|
||||||
|
return ec.fieldContext_ActivateAccountPayload_createPasswordToken(ctx, field)
|
||||||
case "profile":
|
case "profile":
|
||||||
return ec.fieldContext_ActivateAccountPayload_profile(ctx, field)
|
return ec.fieldContext_ActivateAccountPayload_profile(ctx, field)
|
||||||
}
|
}
|
||||||
@@ -16764,6 +16759,8 @@ func (ec *executionContext) _ActivateAccountPayload(ctx context.Context, sel ast
|
|||||||
switch field.Name {
|
switch field.Name {
|
||||||
case "__typename":
|
case "__typename":
|
||||||
out.Values[i] = graphql.MarshalString("ActivateAccountPayload")
|
out.Values[i] = graphql.MarshalString("ActivateAccountPayload")
|
||||||
|
case "createPasswordToken":
|
||||||
|
out.Values[i] = ec._ActivateAccountPayload_createPasswordToken(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:
|
||||||
@@ -17037,45 +17034,6 @@ func (ec *executionContext) _CreateOrganizationPayload(ctx context.Context, sel
|
|||||||
return out
|
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"}
|
var createPersonalAPIKeyPayloadImplementors = []string{"CreatePersonalAPIKeyPayload"}
|
||||||
|
|
||||||
func (ec *executionContext) _CreatePersonalAPIKeyPayload(ctx context.Context, sel ast.SelectionSet, obj *types.CreatePersonalAPIKeyPayload) graphql.Marshaler {
|
func (ec *executionContext) _CreatePersonalAPIKeyPayload(ctx context.Context, sel ast.SelectionSet, obj *types.CreatePersonalAPIKeyPayload) graphql.Marshaler {
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ type ActivateAccountInput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ActivateAccountPayload struct {
|
type ActivateAccountPayload struct {
|
||||||
Profile *Profile `json:"profile,omitempty"`
|
CreatePasswordToken *string `json:"createPasswordToken,omitempty"`
|
||||||
|
Profile *Profile `json:"profile,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AssumeOrganizationSessionInput struct {
|
type AssumeOrganizationSessionInput struct {
|
||||||
@@ -91,10 +92,6 @@ type CreateOrganizationPayload struct {
|
|||||||
Membership *Membership `json:"membership"`
|
Membership *Membership `json:"membership"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreatePasswordPayload struct {
|
|
||||||
Success bool `json:"success"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreatePersonalAPIKeyInput struct {
|
type CreatePersonalAPIKeyInput struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
ExpiresAt time.Time `json:"expiresAt"`
|
ExpiresAt time.Time `json:"expiresAt"`
|
||||||
|
|||||||
@@ -384,9 +384,9 @@ func (r *mutationResolver) SignOut(ctx context.Context) (*types.SignOutPayload,
|
|||||||
|
|
||||||
// ActivateAccount is the resolver for the signUpFromInvitation field.
|
// ActivateAccount is the resolver for the signUpFromInvitation field.
|
||||||
func (r *mutationResolver) ActivateAccount(ctx context.Context, input types.ActivateAccountInput) (*types.ActivateAccountPayload, error) {
|
func (r *mutationResolver) ActivateAccount(ctx context.Context, input types.ActivateAccountInput) (*types.ActivateAccountPayload, error) {
|
||||||
user, session, err := r.iam.AuthService.ActivateAccount(
|
user, createPasswordToken, err := r.iam.AuthService.ActivateAccount(
|
||||||
ctx,
|
ctx,
|
||||||
&iam.CreateIdentityFromInvitationRequest{
|
&iam.ActivateAccountRequest{
|
||||||
InvitationToken: input.Token,
|
InvitationToken: input.Token,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -411,11 +411,9 @@ func (r *mutationResolver) ActivateAccount(ctx context.Context, input types.Acti
|
|||||||
return nil, gqlutils.Internal(ctx)
|
return nil, gqlutils.Internal(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
w := gqlutils.HTTPResponseWriterFromContext(ctx)
|
|
||||||
r.sessionCookie.Set(w, session)
|
|
||||||
|
|
||||||
return &types.ActivateAccountPayload{
|
return &types.ActivateAccountPayload{
|
||||||
Profile: types.NewProfile(user),
|
CreatePasswordToken: createPasswordToken,
|
||||||
|
Profile: types.NewProfile(user),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user