Implement guard on empty full name before NDA is signed
Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<d32c91bec3630db95573556172f06d35>>
|
* @generated SignedSource<<35d27a50dd067775566c69dd0e555b25>>
|
||||||
* @lightSyntaxTransform
|
* @lightSyntaxTransform
|
||||||
* @nogrep
|
* @nogrep
|
||||||
*/
|
*/
|
||||||
@@ -17,7 +17,6 @@ export type CompliancePageAccessPageQuery$data = {
|
|||||||
readonly organization: {
|
readonly organization: {
|
||||||
readonly __typename: "Organization";
|
readonly __typename: "Organization";
|
||||||
readonly compliancePage: {
|
readonly compliancePage: {
|
||||||
readonly canCreateAccess: boolean;
|
|
||||||
readonly id: string;
|
readonly id: string;
|
||||||
readonly " $fragmentSpreads": FragmentRefs<"CompliancePageAccessListFragment">;
|
readonly " $fragmentSpreads": FragmentRefs<"CompliancePageAccessListFragment">;
|
||||||
};
|
};
|
||||||
@@ -61,20 +60,7 @@ v3 = {
|
|||||||
"name": "id",
|
"name": "id",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
v4 = {
|
v4 = [
|
||||||
"alias": "canCreateAccess",
|
|
||||||
"args": [
|
|
||||||
{
|
|
||||||
"kind": "Literal",
|
|
||||||
"name": "action",
|
|
||||||
"value": "core:trust-center-access:create"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"kind": "ScalarField",
|
|
||||||
"name": "permission",
|
|
||||||
"storageKey": "permission(action:\"core:trust-center-access:create\")"
|
|
||||||
},
|
|
||||||
v5 = [
|
|
||||||
{
|
{
|
||||||
"kind": "Literal",
|
"kind": "Literal",
|
||||||
"name": "first",
|
"name": "first",
|
||||||
@@ -119,7 +105,6 @@ return {
|
|||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v3/*: any*/),
|
(v3/*: any*/),
|
||||||
(v4/*: any*/),
|
|
||||||
{
|
{
|
||||||
"args": null,
|
"args": null,
|
||||||
"kind": "FragmentSpread",
|
"kind": "FragmentSpread",
|
||||||
@@ -168,10 +153,9 @@ return {
|
|||||||
"plural": false,
|
"plural": false,
|
||||||
"selections": [
|
"selections": [
|
||||||
(v3/*: any*/),
|
(v3/*: any*/),
|
||||||
(v4/*: any*/),
|
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v5/*: any*/),
|
"args": (v4/*: any*/),
|
||||||
"concreteType": "TrustCenterAccessConnection",
|
"concreteType": "TrustCenterAccessConnection",
|
||||||
"kind": "LinkedField",
|
"kind": "LinkedField",
|
||||||
"name": "accesses",
|
"name": "accesses",
|
||||||
@@ -350,7 +334,7 @@ return {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": (v5/*: any*/),
|
"args": (v4/*: any*/),
|
||||||
"filters": [
|
"filters": [
|
||||||
"orderBy"
|
"orderBy"
|
||||||
],
|
],
|
||||||
@@ -373,16 +357,16 @@ return {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
"cacheID": "c556c1f73c80950e432e5298b7aa1162",
|
"cacheID": "b4d6f7aa127d6ee60ec6344fb291ab4e",
|
||||||
"id": null,
|
"id": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"name": "CompliancePageAccessPageQuery",
|
"name": "CompliancePageAccessPageQuery",
|
||||||
"operationKind": "query",
|
"operationKind": "query",
|
||||||
"text": "query CompliancePageAccessPageQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n compliancePage: trustCenter {\n id\n canCreateAccess: permission(action: \"core:trust-center-access:create\")\n ...CompliancePageAccessListFragment\n }\n }\n id\n }\n}\n\nfragment CompliancePageAccessListFragment on TrustCenter {\n accesses(first: 10, orderBy: {field: CREATED_AT, direction: DESC}) {\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n edges {\n cursor\n node {\n id\n ...CompliancePageAccessListItemFragment\n __typename\n }\n }\n }\n id\n}\n\nfragment CompliancePageAccessListItemFragment on TrustCenterAccess {\n id\n createdAt\n profile {\n fullName\n emailAddress\n state\n id\n }\n activeCount\n pendingRequestCount\n ndaSignature {\n status\n id\n }\n canUpdate: permission(action: \"core:trust-center-access:update\")\n}\n"
|
"text": "query CompliancePageAccessPageQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n compliancePage: trustCenter {\n id\n ...CompliancePageAccessListFragment\n }\n }\n id\n }\n}\n\nfragment CompliancePageAccessListFragment on TrustCenter {\n accesses(first: 10, orderBy: {field: CREATED_AT, direction: DESC}) {\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n edges {\n cursor\n node {\n id\n ...CompliancePageAccessListItemFragment\n __typename\n }\n }\n }\n id\n}\n\nfragment CompliancePageAccessListItemFragment on TrustCenterAccess {\n id\n createdAt\n profile {\n fullName\n emailAddress\n state\n id\n }\n activeCount\n pendingRequestCount\n ndaSignature {\n status\n id\n }\n canUpdate: permission(action: \"core:trust-center-access:update\")\n}\n"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
(node as any).hash = "4cc473e91fd49ddd83b6cdb0c8da0abf";
|
(node as any).hash = "29f59aac000603a1d11c88a441fb595b";
|
||||||
|
|
||||||
export default node;
|
export default node;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { NDASignatureRequiredError, UnAuthenticatedError } from "@probo/relay";
|
import { FullNameRequiredError, NDASignatureRequiredError, UnAuthenticatedError } from "@probo/relay";
|
||||||
import { Navigate, useLocation, useRouteError } from "react-router";
|
import { Navigate, useLocation, useRouteError } from "react-router";
|
||||||
|
|
||||||
import { getPathPrefix } from "#/utils/pathPrefix";
|
import { getPathPrefix } from "#/utils/pathPrefix";
|
||||||
@@ -29,6 +29,18 @@ export function RootErrorBoundary() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (error instanceof FullNameRequiredError) {
|
||||||
|
return (
|
||||||
|
<Navigate
|
||||||
|
replace
|
||||||
|
to={{
|
||||||
|
pathname: "/full-name",
|
||||||
|
search: queryString ? "?" + queryString : "",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (error instanceof NDASignatureRequiredError) {
|
if (error instanceof NDASignatureRequiredError) {
|
||||||
return (
|
return (
|
||||||
<Navigate
|
<Navigate
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ const sendMagicLinkMutation = graphql`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
fullName: z.string().min(2),
|
|
||||||
email: z.string().email(),
|
email: z.string().email(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -104,7 +103,6 @@ export function ConnectPage(props: {
|
|||||||
} = useFormWithSchema(schema, {
|
} = useFormWithSchema(schema, {
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
email: "",
|
email: "",
|
||||||
fullName: "",
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -112,8 +110,8 @@ export function ConnectPage(props: {
|
|||||||
sendMagicLinkMutation,
|
sendMagicLinkMutation,
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSubmit = handleSubmitWrapper(({ email, fullName }: FormData) => {
|
const handleSubmit = handleSubmitWrapper(({ email }: FormData) => {
|
||||||
const input: SendMagicLinkInput = { email, fullName };
|
const input: SendMagicLinkInput = { email };
|
||||||
if (safeContinueUrl) {
|
if (safeContinueUrl) {
|
||||||
input.continue = safeContinueUrl;
|
input.continue = safeContinueUrl;
|
||||||
}
|
}
|
||||||
@@ -121,7 +119,6 @@ export function ConnectPage(props: {
|
|||||||
variables: {
|
variables: {
|
||||||
input: {
|
input: {
|
||||||
email,
|
email,
|
||||||
fullName,
|
|
||||||
continue: safeContinueUrl,
|
continue: safeContinueUrl,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -173,14 +170,6 @@ export function ConnectPage(props: {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form onSubmit={e => void handleSubmit(e)} className="space-y-6">
|
<form onSubmit={e => void handleSubmit(e)} className="space-y-6">
|
||||||
<Field
|
|
||||||
label={__("Full Name")}
|
|
||||||
placeholder="John Doe"
|
|
||||||
{...register("fullName")}
|
|
||||||
type="text"
|
|
||||||
required
|
|
||||||
error={formState.errors.fullName?.message}
|
|
||||||
/>
|
|
||||||
<Field
|
<Field
|
||||||
label={__("Email")}
|
label={__("Email")}
|
||||||
placeholder="john.doe@acme.com"
|
placeholder="john.doe@acme.com"
|
||||||
|
|||||||
135
apps/trust/src/pages/auth/FullNamePage.tsx
Normal file
135
apps/trust/src/pages/auth/FullNamePage.tsx
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
import type { GraphQLError } from "@probo/helpers";
|
||||||
|
import { useTranslate } from "@probo/i18n";
|
||||||
|
import { Button, Field, useToast } from "@probo/ui";
|
||||||
|
import {
|
||||||
|
useMutation,
|
||||||
|
} from "react-relay";
|
||||||
|
import { useSearchParams } from "react-router";
|
||||||
|
import { graphql } from "relay-runtime";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { useFormWithSchema } from "#/hooks/useFormWithSchema";
|
||||||
|
import { getPathPrefix } from "#/utils/pathPrefix";
|
||||||
|
|
||||||
|
import type { FullNamePageMutation } from "./__generated__/FullNamePageMutation.graphql";
|
||||||
|
|
||||||
|
const updateMutation = graphql`
|
||||||
|
mutation FullNamePageMutation($input: UpdateFullNameInput!) {
|
||||||
|
updateFullName(input: $input) {
|
||||||
|
success
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const schema = z.object({
|
||||||
|
fullName: z.string().min(2),
|
||||||
|
});
|
||||||
|
|
||||||
|
type FormData = z.infer<typeof schema>;
|
||||||
|
|
||||||
|
export default function FullNamePage() {
|
||||||
|
const { __ } = useTranslate();
|
||||||
|
const { toast } = useToast();
|
||||||
|
const [searchParams] = useSearchParams();
|
||||||
|
|
||||||
|
const continueUrlParam = searchParams.get("continue");
|
||||||
|
let safeContinueUrl: string;
|
||||||
|
if (continueUrlParam) {
|
||||||
|
try {
|
||||||
|
const continueUrl = new URL(continueUrlParam, window.location.origin);
|
||||||
|
if (continueUrl.origin === window.location.origin && continueUrl.pathname.startsWith(`${getPathPrefix()}/`)) {
|
||||||
|
safeContinueUrl = window.location.origin + continueUrl.pathname + continueUrl.search;
|
||||||
|
} else {
|
||||||
|
safeContinueUrl = window.location.origin + (getPathPrefix() || "/");
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
safeContinueUrl = window.location.origin + (getPathPrefix() || "/");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
safeContinueUrl = window.location.origin + (getPathPrefix() || "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
handleSubmit: handleSubmitWrapper,
|
||||||
|
register,
|
||||||
|
formState,
|
||||||
|
} = useFormWithSchema(schema, {
|
||||||
|
defaultValues: {
|
||||||
|
fullName: "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [update] = useMutation<FullNamePageMutation>(
|
||||||
|
updateMutation,
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSubmit = handleSubmitWrapper(({ fullName }: FormData) => {
|
||||||
|
update({
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
fullName,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
onCompleted: (_, errors: GraphQLError[] | null) => {
|
||||||
|
if (errors) {
|
||||||
|
for (const err of errors) {
|
||||||
|
if (err.extensions?.code === "ALREADY_AUTHENTICATED") {
|
||||||
|
window.location.href = getPathPrefix() || "/";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
toast({
|
||||||
|
title: __("Error"),
|
||||||
|
description: __("Cannot send magic link"),
|
||||||
|
variant: "error",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
toast({
|
||||||
|
title: __("Success"),
|
||||||
|
description: __("Full name updated!"),
|
||||||
|
variant: "success",
|
||||||
|
});
|
||||||
|
|
||||||
|
window.location.href = safeContinueUrl;
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
toast({
|
||||||
|
title: __("Error"),
|
||||||
|
description: error.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">
|
||||||
|
{__("Please set your profile's full name")}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form onSubmit={e => void handleSubmit(e)} className="space-y-6">
|
||||||
|
<Field
|
||||||
|
label={__("Full Name")}
|
||||||
|
placeholder="John Doe"
|
||||||
|
{...register("fullName")}
|
||||||
|
type="text"
|
||||||
|
required
|
||||||
|
error={formState.errors.fullName?.message}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
className="w-xs h-10 mx-auto"
|
||||||
|
disabled={formState.isSubmitting}
|
||||||
|
>
|
||||||
|
{__("Continue")}
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<f567da0a977d6ae788cdd5d6eff1d59f>>
|
* @generated SignedSource<<711ecaa392c23004a3bd1dfb24a5751f>>
|
||||||
* @lightSyntaxTransform
|
* @lightSyntaxTransform
|
||||||
* @nogrep
|
* @nogrep
|
||||||
*/
|
*/
|
||||||
@@ -12,7 +12,6 @@ import { ConcreteRequest } from 'relay-runtime';
|
|||||||
export type SendMagicLinkInput = {
|
export type SendMagicLinkInput = {
|
||||||
continue?: string | null | undefined;
|
continue?: string | null | undefined;
|
||||||
email: any;
|
email: any;
|
||||||
fullName: string;
|
|
||||||
};
|
};
|
||||||
export type ConnectPageMutation$variables = {
|
export type ConnectPageMutation$variables = {
|
||||||
input: SendMagicLinkInput;
|
input: SendMagicLinkInput;
|
||||||
|
|||||||
92
apps/trust/src/pages/auth/__generated__/FullNamePageMutation.graphql.ts
generated
Normal file
92
apps/trust/src/pages/auth/__generated__/FullNamePageMutation.graphql.ts
generated
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/**
|
||||||
|
* @generated SignedSource<<7861673355d6d647183c2a4425e9a5b9>>
|
||||||
|
* @lightSyntaxTransform
|
||||||
|
* @nogrep
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ConcreteRequest } from 'relay-runtime';
|
||||||
|
export type UpdateFullNameInput = {
|
||||||
|
fullName: string;
|
||||||
|
};
|
||||||
|
export type FullNamePageMutation$variables = {
|
||||||
|
input: UpdateFullNameInput;
|
||||||
|
};
|
||||||
|
export type FullNamePageMutation$data = {
|
||||||
|
readonly updateFullName: {
|
||||||
|
readonly success: boolean;
|
||||||
|
} | null | undefined;
|
||||||
|
};
|
||||||
|
export type FullNamePageMutation = {
|
||||||
|
response: FullNamePageMutation$data;
|
||||||
|
variables: FullNamePageMutation$variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
const node: ConcreteRequest = (function(){
|
||||||
|
var v0 = [
|
||||||
|
{
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "input"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v1 = [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "input",
|
||||||
|
"variableName": "input"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"concreteType": "UpdateFullNamePayload",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "updateFullName",
|
||||||
|
"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": "FullNamePageMutation",
|
||||||
|
"selections": (v1/*: any*/),
|
||||||
|
"type": "Mutation",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "FullNamePageMutation",
|
||||||
|
"selections": (v1/*: any*/)
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"cacheID": "502db67e5bab72aff71fec9a0be0eeaf",
|
||||||
|
"id": null,
|
||||||
|
"metadata": {},
|
||||||
|
"name": "FullNamePageMutation",
|
||||||
|
"operationKind": "mutation",
|
||||||
|
"text": "mutation FullNamePageMutation(\n $input: UpdateFullNameInput!\n) {\n updateFullName(input: $input) {\n success\n }\n}\n"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
(node as any).hash = "3d6352889babf98a37fe06a1bcaead15";
|
||||||
|
|
||||||
|
export default node;
|
||||||
@@ -10,32 +10,6 @@ import {
|
|||||||
|
|
||||||
import { getPathPrefix } from "#/utils/pathPrefix";
|
import { getPathPrefix } from "#/utils/pathPrefix";
|
||||||
|
|
||||||
export class UnAuthenticatedError extends Error {
|
|
||||||
constructor() {
|
|
||||||
super("UNAUTHENTICATED");
|
|
||||||
this.name = "UnAuthenticatedError";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class InvalidError extends Error {
|
|
||||||
field?: string;
|
|
||||||
cause?: string;
|
|
||||||
|
|
||||||
constructor(message?: string, field?: string, cause?: string) {
|
|
||||||
super(message || "INVALID");
|
|
||||||
this.name = "InvalidError";
|
|
||||||
this.field = field;
|
|
||||||
this.cause = cause;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class InternalServerError extends Error {
|
|
||||||
constructor() {
|
|
||||||
super("INTERNAL_SERVER_ERROR");
|
|
||||||
this.name = "InternalServerError";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function buildEndpoint(): string {
|
export function buildEndpoint(): string {
|
||||||
let host = import.meta.env.VITE_API_URL;
|
let host = import.meta.env.VITE_API_URL;
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ const routes = [
|
|||||||
path: "/verify-magic-link",
|
path: "/verify-magic-link",
|
||||||
Component: lazy(() => import("#/pages/auth/VerifyMagicLinkPage")),
|
Component: lazy(() => import("#/pages/auth/VerifyMagicLinkPage")),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/full-name",
|
||||||
|
Component: lazy(() => import("#/pages/auth/FullNamePage")),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,6 +6,14 @@ export class UnAuthenticatedError extends Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class FullNameRequiredError extends Error {
|
||||||
|
constructor(message?: string) {
|
||||||
|
super(message || "FULL_NAME_REQUIRED");
|
||||||
|
this.name = "FullNameRequiredError";
|
||||||
|
Object.setPrototypeOf(this, FullNameRequiredError.prototype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class NDASignatureRequiredError extends Error {
|
export class NDASignatureRequiredError extends Error {
|
||||||
constructor(message?: string) {
|
constructor(message?: string) {
|
||||||
super(message || "NDA_SIGNATURE_REQUIRED");
|
super(message || "NDA_SIGNATURE_REQUIRED");
|
||||||
|
|||||||
@@ -5,12 +5,16 @@ import {
|
|||||||
ForbiddenError,
|
ForbiddenError,
|
||||||
AssumptionRequiredError,
|
AssumptionRequiredError,
|
||||||
NDASignatureRequiredError,
|
NDASignatureRequiredError,
|
||||||
|
FullNameRequiredError,
|
||||||
} from "./errors";
|
} from "./errors";
|
||||||
import { GraphQLError } from "graphql";
|
import { GraphQLError } from "graphql";
|
||||||
|
|
||||||
const hasUnauthenticatedError = (error: GraphQLError) =>
|
const hasUnauthenticatedError = (error: GraphQLError) =>
|
||||||
error.extensions?.code == "UNAUTHENTICATED";
|
error.extensions?.code == "UNAUTHENTICATED";
|
||||||
|
|
||||||
|
const hasFullNameRequiredError = (error: GraphQLError) =>
|
||||||
|
error.extensions?.code == "FULL_NAME_REQUIRED";
|
||||||
|
|
||||||
const hasAssumptionRequiredError = (error: GraphQLError) =>
|
const hasAssumptionRequiredError = (error: GraphQLError) =>
|
||||||
error.extensions?.code == "ASSUMPTION_REQUIRED";
|
error.extensions?.code == "ASSUMPTION_REQUIRED";
|
||||||
|
|
||||||
@@ -83,6 +87,11 @@ export const makeFetchQuery = (endpoint: string): FetchFunction => {
|
|||||||
throw new UnAuthenticatedError(unauthenticatedError.message);
|
throw new UnAuthenticatedError(unauthenticatedError.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fullNameRequiredError = errors.find(hasFullNameRequiredError);
|
||||||
|
if (fullNameRequiredError) {
|
||||||
|
throw new FullNameRequiredError(fullNameRequiredError.message);
|
||||||
|
}
|
||||||
|
|
||||||
const assumptionRequiredError = errors.find(hasAssumptionRequiredError);
|
const assumptionRequiredError = errors.find(hasAssumptionRequiredError);
|
||||||
if (assumptionRequiredError) {
|
if (assumptionRequiredError) {
|
||||||
throw new AssumptionRequiredError(assumptionRequiredError.message)
|
throw new AssumptionRequiredError(assumptionRequiredError.message)
|
||||||
|
|||||||
@@ -47,6 +47,15 @@ type (
|
|||||||
IdentityID gid.GID `json:"uid"`
|
IdentityID gid.GID `json:"uid"`
|
||||||
Email mail.Addr `json:"email"`
|
Email mail.Addr `json:"email"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChangeEmailRequest struct {
|
||||||
|
NewEmail mail.Addr
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateIdentityRequest struct {
|
||||||
|
FullName string `json:"fullName"`
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -57,11 +66,6 @@ func NewAccountService(svc *Service) *AccountService {
|
|||||||
return &AccountService{Service: svc}
|
return &AccountService{Service: svc}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChangeEmailRequest struct {
|
|
||||||
NewEmail mail.Addr
|
|
||||||
Password string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (req ChangeEmailRequest) Validate() error {
|
func (req ChangeEmailRequest) Validate() error {
|
||||||
v := validator.New()
|
v := validator.New()
|
||||||
|
|
||||||
@@ -70,6 +74,14 @@ func (req ChangeEmailRequest) Validate() error {
|
|||||||
return v.Error()
|
return v.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (req UpdateIdentityRequest) Validate() error {
|
||||||
|
v := validator.New()
|
||||||
|
|
||||||
|
v.Check(req.FullName, "full_name", validator.NotEmpty(), validator.MinLen(2), validator.MaxLen(255))
|
||||||
|
|
||||||
|
return v.Error()
|
||||||
|
}
|
||||||
|
|
||||||
func (s AccountService) ChangeEmail(ctx context.Context, identityID gid.GID, req *ChangeEmailRequest) error {
|
func (s AccountService) ChangeEmail(ctx context.Context, identityID gid.GID, req *ChangeEmailRequest) error {
|
||||||
if err := req.Validate(); err != nil {
|
if err := req.Validate(); err != nil {
|
||||||
return fmt.Errorf("invalid request: %w", err)
|
return fmt.Errorf("invalid request: %w", err)
|
||||||
@@ -339,6 +351,42 @@ func (s AccountService) GetIdentity(ctx context.Context, identityID gid.GID) (*c
|
|||||||
return identity, nil
|
return identity, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s AccountService) UpdateIdentity(ctx context.Context, identityID gid.GID, req *UpdateIdentityRequest) (*coredata.Identity, error) {
|
||||||
|
if err := req.Validate(); err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
identity := &coredata.Identity{}
|
||||||
|
|
||||||
|
err := s.pg.WithTx(
|
||||||
|
ctx,
|
||||||
|
func(tx pg.Conn) error {
|
||||||
|
err := identity.LoadByID(ctx, tx, identityID)
|
||||||
|
if err != nil {
|
||||||
|
if err == coredata.ErrResourceNotFound {
|
||||||
|
return NewIdentityNotFoundError(identityID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("cannot load identity: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
identity.FullName = req.FullName
|
||||||
|
identity.UpdatedAt = time.Now()
|
||||||
|
|
||||||
|
if err := identity.Update(ctx, tx); err != nil {
|
||||||
|
return fmt.Errorf("cannot update identity: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return identity, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s AccountService) ListPersonalAPIKeys(
|
func (s AccountService) ListPersonalAPIKeys(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
identityID gid.GID,
|
identityID gid.GID,
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
SendMagicLinkRequest struct {
|
SendMagicLinkRequest struct {
|
||||||
FullName string
|
|
||||||
Email mail.Addr
|
Email mail.Addr
|
||||||
URLPath string
|
URLPath string
|
||||||
OrganizationID gid.GID
|
OrganizationID gid.GID
|
||||||
@@ -75,7 +74,6 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
MagicLinkData struct {
|
MagicLinkData struct {
|
||||||
FullName string `json:"fullName"`
|
|
||||||
Email mail.Addr `json:"email"`
|
Email mail.Addr `json:"email"`
|
||||||
Continue *string `json:"continue"`
|
Continue *string `json:"continue"`
|
||||||
}
|
}
|
||||||
@@ -552,7 +550,6 @@ func (s AuthService) SendMagicLink(ctx context.Context, req *SendMagicLinkReques
|
|||||||
TokenTypeMagicLink,
|
TokenTypeMagicLink,
|
||||||
s.magicLinkTokenValidity,
|
s.magicLinkTokenValidity,
|
||||||
MagicLinkData{
|
MagicLinkData{
|
||||||
FullName: req.FullName,
|
|
||||||
Email: req.Email,
|
Email: req.Email,
|
||||||
Continue: req.Continue,
|
Continue: req.Continue,
|
||||||
},
|
},
|
||||||
@@ -574,9 +571,20 @@ func (s AuthService) SendMagicLink(ctx context.Context, req *SendMagicLinkReques
|
|||||||
return fmt.Errorf("cannot insert token: %w", err)
|
return fmt.Errorf("cannot insert token: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fullName := req.FullName
|
fullName := req.Email.Username()
|
||||||
|
identity := &coredata.Identity{}
|
||||||
organization := &coredata.Organization{}
|
organization := &coredata.Organization{}
|
||||||
|
|
||||||
|
if err := identity.LoadByEmail(ctx, tx, req.Email); err == nil {
|
||||||
|
if identity.FullName != "" {
|
||||||
|
fullName = identity.FullName
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !errors.Is(err, coredata.ErrResourceNotFound) {
|
||||||
|
return fmt.Errorf("cannot load identity: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := organization.LoadByID(ctx, tx, coredata.NewNoScope(), req.OrganizationID); err != nil {
|
if err := organization.LoadByID(ctx, tx, coredata.NewNoScope(), req.OrganizationID); err != nil {
|
||||||
return fmt.Errorf("cannot load organization: %w", err)
|
return fmt.Errorf("cannot load organization: %w", err)
|
||||||
}
|
}
|
||||||
@@ -675,10 +683,6 @@ func (s AuthService) OpenSessionWithMagicLink(ctx context.Context, tokenString s
|
|||||||
UpdatedAt: now,
|
UpdatedAt: now,
|
||||||
}
|
}
|
||||||
|
|
||||||
if identity.FullName == "" {
|
|
||||||
identity.FullName = payload.Data.FullName
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := identity.Insert(ctx, tx); err != nil {
|
if err := identity.Insert(ctx, tx); err != nil {
|
||||||
return fmt.Errorf("cannot create identity: %w", err)
|
return fmt.Errorf("cannot create identity: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,11 @@ func newNDADirective(
|
|||||||
return nil, gqlutils.Internal(ctx)
|
return nil, gqlutils.Internal(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We need full name before user signs NDA
|
||||||
|
if identity.FullName == "" {
|
||||||
|
return nil, gqlutils.FullNameRequiredf(ctx, "full name is required")
|
||||||
|
}
|
||||||
|
|
||||||
if sig.Status != coredata.ElectronicSignatureStatusCompleted {
|
if sig.Status != coredata.ElectronicSignatureStatusCompleted {
|
||||||
return nil, gqlutils.NDASignatureRequiredf(ctx, "NDA signature required")
|
return nil, gqlutils.NDASignatureRequiredf(ctx, "NDA signature required")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -611,7 +611,6 @@ type DocumentAccess implements Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
input SendMagicLinkInput {
|
input SendMagicLinkInput {
|
||||||
fullName: String!
|
|
||||||
email: EmailAddr!
|
email: EmailAddr!
|
||||||
continue: String
|
continue: String
|
||||||
}
|
}
|
||||||
@@ -628,6 +627,14 @@ type VerifyMagicLinkPayload {
|
|||||||
continue: String
|
continue: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input UpdateFullNameInput {
|
||||||
|
fullName: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateFullNamePayload {
|
||||||
|
success: Boolean!
|
||||||
|
}
|
||||||
|
|
||||||
type RequestDocumentAccessPayload {
|
type RequestDocumentAccessPayload {
|
||||||
document: Document
|
document: Document
|
||||||
}
|
}
|
||||||
@@ -827,6 +834,8 @@ type Mutation {
|
|||||||
@session(required: OPTIONAL)
|
@session(required: OPTIONAL)
|
||||||
verifyMagicLink(input: VerifyMagicLinkInput!): VerifyMagicLinkPayload
|
verifyMagicLink(input: VerifyMagicLinkInput!): VerifyMagicLinkPayload
|
||||||
@session(required: OPTIONAL)
|
@session(required: OPTIONAL)
|
||||||
|
updateFullName(input: UpdateFullNameInput!): UpdateFullNamePayload
|
||||||
|
@session(required: PRESENT)
|
||||||
|
|
||||||
requestAllAccesses: RequestAccessesPayload! @session(required: PRESENT) @nda
|
requestAllAccesses: RequestAccessesPayload! @session(required: PRESENT) @nda
|
||||||
|
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ type ComplexityRoot struct {
|
|||||||
RequestReportAccess func(childComplexity int, input types.RequestReportAccessInput) int
|
RequestReportAccess func(childComplexity int, input types.RequestReportAccessInput) int
|
||||||
RequestTrustCenterFileAccess func(childComplexity int, input types.RequestTrustCenterFileAccessInput) int
|
RequestTrustCenterFileAccess func(childComplexity int, input types.RequestTrustCenterFileAccessInput) int
|
||||||
SendMagicLink func(childComplexity int, input types.SendMagicLinkInput) int
|
SendMagicLink func(childComplexity int, input types.SendMagicLinkInput) int
|
||||||
|
UpdateFullName func(childComplexity int, input types.UpdateFullNameInput) int
|
||||||
VerifyMagicLink func(childComplexity int, input types.VerifyMagicLinkInput) int
|
VerifyMagicLink func(childComplexity int, input types.VerifyMagicLinkInput) int
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,6 +290,10 @@ type ComplexityRoot struct {
|
|||||||
Node func(childComplexity int) int
|
Node func(childComplexity int) int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateFullNamePayload struct {
|
||||||
|
Success func(childComplexity int) int
|
||||||
|
}
|
||||||
|
|
||||||
Vendor struct {
|
Vendor struct {
|
||||||
Category func(childComplexity int) int
|
Category func(childComplexity int) int
|
||||||
Countries func(childComplexity int) int
|
Countries func(childComplexity int) int
|
||||||
@@ -333,6 +338,7 @@ type FrameworkResolver interface {
|
|||||||
type MutationResolver interface {
|
type MutationResolver interface {
|
||||||
SendMagicLink(ctx context.Context, input types.SendMagicLinkInput) (*types.SendMagicLinkPayload, error)
|
SendMagicLink(ctx context.Context, input types.SendMagicLinkInput) (*types.SendMagicLinkPayload, error)
|
||||||
VerifyMagicLink(ctx context.Context, input types.VerifyMagicLinkInput) (*types.VerifyMagicLinkPayload, error)
|
VerifyMagicLink(ctx context.Context, input types.VerifyMagicLinkInput) (*types.VerifyMagicLinkPayload, error)
|
||||||
|
UpdateFullName(ctx context.Context, input types.UpdateFullNameInput) (*types.UpdateFullNamePayload, error)
|
||||||
RequestAllAccesses(ctx context.Context) (*types.RequestAccessesPayload, error)
|
RequestAllAccesses(ctx context.Context) (*types.RequestAccessesPayload, error)
|
||||||
ExportDocumentPDF(ctx context.Context, input types.ExportDocumentPDFInput) (*types.ExportDocumentPDFPayload, error)
|
ExportDocumentPDF(ctx context.Context, input types.ExportDocumentPDFInput) (*types.ExportDocumentPDFPayload, error)
|
||||||
ExportReportPDF(ctx context.Context, input types.ExportReportPDFInput) (*types.ExportReportPDFPayload, error)
|
ExportReportPDF(ctx context.Context, input types.ExportReportPDFInput) (*types.ExportReportPDFPayload, error)
|
||||||
@@ -800,6 +806,17 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
return e.ComplexityRoot.Mutation.SendMagicLink(childComplexity, args["input"].(types.SendMagicLinkInput)), true
|
return e.ComplexityRoot.Mutation.SendMagicLink(childComplexity, args["input"].(types.SendMagicLinkInput)), true
|
||||||
|
case "Mutation.updateFullName":
|
||||||
|
if e.ComplexityRoot.Mutation.UpdateFullName == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
args, err := ec.field_Mutation_updateFullName_args(ctx, rawArgs)
|
||||||
|
if err != nil {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.ComplexityRoot.Mutation.UpdateFullName(childComplexity, args["input"].(types.UpdateFullNameInput)), true
|
||||||
case "Mutation.verifyMagicLink":
|
case "Mutation.verifyMagicLink":
|
||||||
if e.ComplexityRoot.Mutation.VerifyMagicLink == nil {
|
if e.ComplexityRoot.Mutation.VerifyMagicLink == nil {
|
||||||
break
|
break
|
||||||
@@ -1245,6 +1262,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
|||||||
|
|
||||||
return e.ComplexityRoot.TrustCenterReferenceEdge.Node(childComplexity), true
|
return e.ComplexityRoot.TrustCenterReferenceEdge.Node(childComplexity), true
|
||||||
|
|
||||||
|
case "UpdateFullNamePayload.success":
|
||||||
|
if e.ComplexityRoot.UpdateFullNamePayload.Success == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.ComplexityRoot.UpdateFullNamePayload.Success(childComplexity), true
|
||||||
|
|
||||||
case "Vendor.category":
|
case "Vendor.category":
|
||||||
if e.ComplexityRoot.Vendor.Category == nil {
|
if e.ComplexityRoot.Vendor.Category == nil {
|
||||||
break
|
break
|
||||||
@@ -1344,6 +1368,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
|
|||||||
ec.unmarshalInputRequestReportAccessInput,
|
ec.unmarshalInputRequestReportAccessInput,
|
||||||
ec.unmarshalInputRequestTrustCenterFileAccessInput,
|
ec.unmarshalInputRequestTrustCenterFileAccessInput,
|
||||||
ec.unmarshalInputSendMagicLinkInput,
|
ec.unmarshalInputSendMagicLinkInput,
|
||||||
|
ec.unmarshalInputUpdateFullNameInput,
|
||||||
ec.unmarshalInputVerifyMagicLinkInput,
|
ec.unmarshalInputVerifyMagicLinkInput,
|
||||||
)
|
)
|
||||||
first := true
|
first := true
|
||||||
@@ -2033,7 +2058,6 @@ type DocumentAccess implements Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
input SendMagicLinkInput {
|
input SendMagicLinkInput {
|
||||||
fullName: String!
|
|
||||||
email: EmailAddr!
|
email: EmailAddr!
|
||||||
continue: String
|
continue: String
|
||||||
}
|
}
|
||||||
@@ -2050,6 +2074,14 @@ type VerifyMagicLinkPayload {
|
|||||||
continue: String
|
continue: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input UpdateFullNameInput {
|
||||||
|
fullName: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateFullNamePayload {
|
||||||
|
success: Boolean!
|
||||||
|
}
|
||||||
|
|
||||||
type RequestDocumentAccessPayload {
|
type RequestDocumentAccessPayload {
|
||||||
document: Document
|
document: Document
|
||||||
}
|
}
|
||||||
@@ -2249,6 +2281,8 @@ type Mutation {
|
|||||||
@session(required: OPTIONAL)
|
@session(required: OPTIONAL)
|
||||||
verifyMagicLink(input: VerifyMagicLinkInput!): VerifyMagicLinkPayload
|
verifyMagicLink(input: VerifyMagicLinkInput!): VerifyMagicLinkPayload
|
||||||
@session(required: OPTIONAL)
|
@session(required: OPTIONAL)
|
||||||
|
updateFullName(input: UpdateFullNameInput!): UpdateFullNamePayload
|
||||||
|
@session(required: PRESENT)
|
||||||
|
|
||||||
requestAllAccesses: RequestAccessesPayload! @session(required: PRESENT) @nda
|
requestAllAccesses: RequestAccessesPayload! @session(required: PRESENT) @nda
|
||||||
|
|
||||||
@@ -2439,6 +2473,17 @@ func (ec *executionContext) field_Mutation_sendMagicLink_args(ctx context.Contex
|
|||||||
return args, nil
|
return args, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) field_Mutation_updateFullName_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||||
|
var err error
|
||||||
|
args := map[string]any{}
|
||||||
|
arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", ec.unmarshalNUpdateFullNameInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐUpdateFullNameInput)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
args["input"] = arg0
|
||||||
|
return args, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) field_Mutation_verifyMagicLink_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
func (ec *executionContext) field_Mutation_verifyMagicLink_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||||
var err error
|
var err error
|
||||||
args := map[string]any{}
|
args := map[string]any{}
|
||||||
@@ -4390,6 +4435,69 @@ func (ec *executionContext) fieldContext_Mutation_verifyMagicLink(ctx context.Co
|
|||||||
return fc, nil
|
return fc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Mutation_updateFullName(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||||
|
return graphql.ResolveField(
|
||||||
|
ctx,
|
||||||
|
ec.OperationContext,
|
||||||
|
field,
|
||||||
|
ec.fieldContext_Mutation_updateFullName,
|
||||||
|
func(ctx context.Context) (any, error) {
|
||||||
|
fc := graphql.GetFieldContext(ctx)
|
||||||
|
return ec.Resolvers.Mutation().UpdateFullName(ctx, fc.Args["input"].(types.UpdateFullNameInput))
|
||||||
|
},
|
||||||
|
func(ctx context.Context, next graphql.Resolver) graphql.Resolver {
|
||||||
|
directive0 := next
|
||||||
|
|
||||||
|
directive1 := func(ctx context.Context) (any, error) {
|
||||||
|
required, err := ec.unmarshalNSessionRequirement2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋgqlutilsᚋdirectivesᚋsessionᚐSessionRequirement(ctx, "PRESENT")
|
||||||
|
if err != nil {
|
||||||
|
var zeroVal *types.UpdateFullNamePayload
|
||||||
|
return zeroVal, err
|
||||||
|
}
|
||||||
|
if ec.Directives.Session == nil {
|
||||||
|
var zeroVal *types.UpdateFullNamePayload
|
||||||
|
return zeroVal, errors.New("directive session is not implemented")
|
||||||
|
}
|
||||||
|
return ec.Directives.Session(ctx, nil, directive0, required)
|
||||||
|
}
|
||||||
|
|
||||||
|
next = directive1
|
||||||
|
return next
|
||||||
|
},
|
||||||
|
ec.marshalOUpdateFullNamePayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐUpdateFullNamePayload,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) fieldContext_Mutation_updateFullName(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||||
|
fc = &graphql.FieldContext{
|
||||||
|
Object: "Mutation",
|
||||||
|
Field: field,
|
||||||
|
IsMethod: true,
|
||||||
|
IsResolver: true,
|
||||||
|
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||||
|
switch field.Name {
|
||||||
|
case "success":
|
||||||
|
return ec.fieldContext_UpdateFullNamePayload_success(ctx, field)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("no field named %q was found under type UpdateFullNamePayload", field.Name)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
err = ec.Recover(ctx, r)
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
if fc.Args, err = ec.field_Mutation_updateFullName_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return fc, err
|
||||||
|
}
|
||||||
|
return fc, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Mutation_requestAllAccesses(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Mutation_requestAllAccesses(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||||
return graphql.ResolveField(
|
return graphql.ResolveField(
|
||||||
ctx,
|
ctx,
|
||||||
@@ -7405,6 +7513,35 @@ func (ec *executionContext) fieldContext_TrustCenterReferenceEdge_node(_ context
|
|||||||
return fc, nil
|
return fc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _UpdateFullNamePayload_success(ctx context.Context, field graphql.CollectedField, obj *types.UpdateFullNamePayload) (ret graphql.Marshaler) {
|
||||||
|
return graphql.ResolveField(
|
||||||
|
ctx,
|
||||||
|
ec.OperationContext,
|
||||||
|
field,
|
||||||
|
ec.fieldContext_UpdateFullNamePayload_success,
|
||||||
|
func(ctx context.Context) (any, error) {
|
||||||
|
return obj.Success, nil
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
ec.marshalNBoolean2bool,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) fieldContext_UpdateFullNamePayload_success(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||||
|
fc = &graphql.FieldContext{
|
||||||
|
Object: "UpdateFullNamePayload",
|
||||||
|
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) _Vendor_id(ctx context.Context, field graphql.CollectedField, obj *types.Vendor) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Vendor_id(ctx context.Context, field graphql.CollectedField, obj *types.Vendor) (ret graphql.Marshaler) {
|
||||||
return graphql.ResolveField(
|
return graphql.ResolveField(
|
||||||
ctx,
|
ctx,
|
||||||
@@ -9508,20 +9645,13 @@ func (ec *executionContext) unmarshalInputSendMagicLinkInput(ctx context.Context
|
|||||||
asMap[k] = v
|
asMap[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldsInOrder := [...]string{"fullName", "email", "continue"}
|
fieldsInOrder := [...]string{"email", "continue"}
|
||||||
for _, k := range fieldsInOrder {
|
for _, k := range fieldsInOrder {
|
||||||
v, ok := asMap[k]
|
v, ok := asMap[k]
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
switch k {
|
switch k {
|
||||||
case "fullName":
|
|
||||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("fullName"))
|
|
||||||
data, err := ec.unmarshalNString2string(ctx, v)
|
|
||||||
if err != nil {
|
|
||||||
return it, err
|
|
||||||
}
|
|
||||||
it.FullName = data
|
|
||||||
case "email":
|
case "email":
|
||||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email"))
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email"))
|
||||||
data, err := ec.unmarshalNEmailAddr2goᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, v)
|
data, err := ec.unmarshalNEmailAddr2goᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, v)
|
||||||
@@ -9541,6 +9671,32 @@ func (ec *executionContext) unmarshalInputSendMagicLinkInput(ctx context.Context
|
|||||||
return it, nil
|
return it, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) unmarshalInputUpdateFullNameInput(ctx context.Context, obj any) (types.UpdateFullNameInput, error) {
|
||||||
|
var it types.UpdateFullNameInput
|
||||||
|
asMap := map[string]any{}
|
||||||
|
for k, v := range obj.(map[string]any) {
|
||||||
|
asMap[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldsInOrder := [...]string{"fullName"}
|
||||||
|
for _, k := range fieldsInOrder {
|
||||||
|
v, ok := asMap[k]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch k {
|
||||||
|
case "fullName":
|
||||||
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("fullName"))
|
||||||
|
data, err := ec.unmarshalNString2string(ctx, v)
|
||||||
|
if err != nil {
|
||||||
|
return it, err
|
||||||
|
}
|
||||||
|
it.FullName = data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return it, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) unmarshalInputVerifyMagicLinkInput(ctx context.Context, obj any) (types.VerifyMagicLinkInput, error) {
|
func (ec *executionContext) unmarshalInputVerifyMagicLinkInput(ctx context.Context, obj any) (types.VerifyMagicLinkInput, error) {
|
||||||
var it types.VerifyMagicLinkInput
|
var it types.VerifyMagicLinkInput
|
||||||
asMap := map[string]any{}
|
asMap := map[string]any{}
|
||||||
@@ -10722,6 +10878,10 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
|
|||||||
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||||
return ec._Mutation_verifyMagicLink(ctx, field)
|
return ec._Mutation_verifyMagicLink(ctx, field)
|
||||||
})
|
})
|
||||||
|
case "updateFullName":
|
||||||
|
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||||
|
return ec._Mutation_updateFullName(ctx, field)
|
||||||
|
})
|
||||||
case "requestAllAccesses":
|
case "requestAllAccesses":
|
||||||
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||||
return ec._Mutation_requestAllAccesses(ctx, field)
|
return ec._Mutation_requestAllAccesses(ctx, field)
|
||||||
@@ -12331,6 +12491,45 @@ func (ec *executionContext) _TrustCenterReferenceEdge(ctx context.Context, sel a
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var updateFullNamePayloadImplementors = []string{"UpdateFullNamePayload"}
|
||||||
|
|
||||||
|
func (ec *executionContext) _UpdateFullNamePayload(ctx context.Context, sel ast.SelectionSet, obj *types.UpdateFullNamePayload) graphql.Marshaler {
|
||||||
|
fields := graphql.CollectFields(ec.OperationContext, sel, updateFullNamePayloadImplementors)
|
||||||
|
|
||||||
|
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("UpdateFullNamePayload")
|
||||||
|
case "success":
|
||||||
|
out.Values[i] = ec._UpdateFullNamePayload_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 vendorImplementors = []string{"Vendor", "Node"}
|
var vendorImplementors = []string{"Vendor", "Node"}
|
||||||
|
|
||||||
func (ec *executionContext) _Vendor(ctx context.Context, sel ast.SelectionSet, obj *types.Vendor) graphql.Marshaler {
|
func (ec *executionContext) _Vendor(ctx context.Context, sel ast.SelectionSet, obj *types.Vendor) graphql.Marshaler {
|
||||||
@@ -14226,6 +14425,11 @@ func (ec *executionContext) marshalNTrustCenterReferenceEdge2ᚖgoᚗproboᚗinc
|
|||||||
return ec._TrustCenterReferenceEdge(ctx, sel, v)
|
return ec._TrustCenterReferenceEdge(ctx, sel, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) unmarshalNUpdateFullNameInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐUpdateFullNameInput(ctx context.Context, v any) (types.UpdateFullNameInput, error) {
|
||||||
|
res, err := ec.unmarshalInputUpdateFullNameInput(ctx, v)
|
||||||
|
return res, graphql.ErrorOnPath(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) marshalNVendor2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐVendor(ctx context.Context, sel ast.SelectionSet, v *types.Vendor) graphql.Marshaler {
|
func (ec *executionContext) marshalNVendor2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐVendor(ctx context.Context, sel ast.SelectionSet, v *types.Vendor) graphql.Marshaler {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||||
@@ -14712,6 +14916,13 @@ func (ec *executionContext) marshalOTrustCenterFile2ᚖgoᚗproboᚗincᚋprobo
|
|||||||
return ec._TrustCenterFile(ctx, sel, v)
|
return ec._TrustCenterFile(ctx, sel, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) marshalOUpdateFullNamePayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐUpdateFullNamePayload(ctx context.Context, sel ast.SelectionSet, v *types.UpdateFullNamePayload) graphql.Marshaler {
|
||||||
|
if v == nil {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
return ec._UpdateFullNamePayload(ctx, sel, v)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) marshalOVerifyMagicLinkPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐVerifyMagicLinkPayload(ctx context.Context, sel ast.SelectionSet, v *types.VerifyMagicLinkPayload) graphql.Marshaler {
|
func (ec *executionContext) marshalOVerifyMagicLinkPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐVerifyMagicLinkPayload(ctx context.Context, sel ast.SelectionSet, v *types.VerifyMagicLinkPayload) graphql.Marshaler {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return graphql.Null
|
return graphql.Null
|
||||||
|
|||||||
@@ -213,7 +213,6 @@ type RequestTrustCenterFileAccessInput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SendMagicLinkInput struct {
|
type SendMagicLinkInput struct {
|
||||||
FullName string `json:"fullName"`
|
|
||||||
Email mail.Addr `json:"email"`
|
Email mail.Addr `json:"email"`
|
||||||
Continue *string `json:"continue,omitempty"`
|
Continue *string `json:"continue,omitempty"`
|
||||||
}
|
}
|
||||||
@@ -294,6 +293,14 @@ type TrustCenterReferenceEdge struct {
|
|||||||
Node *TrustCenterReference `json:"node"`
|
Node *TrustCenterReference `json:"node"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UpdateFullNameInput struct {
|
||||||
|
FullName string `json:"fullName"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateFullNamePayload struct {
|
||||||
|
Success bool `json:"success"`
|
||||||
|
}
|
||||||
|
|
||||||
type Vendor struct {
|
type Vendor struct {
|
||||||
ID gid.GID `json:"id"`
|
ID gid.GID `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
|||||||
@@ -192,7 +192,6 @@ func (r *mutationResolver) SendMagicLink(ctx context.Context, input types.SendMa
|
|||||||
}
|
}
|
||||||
|
|
||||||
req := &iam.SendMagicLinkRequest{
|
req := &iam.SendMagicLinkRequest{
|
||||||
FullName: input.FullName,
|
|
||||||
Email: input.Email,
|
Email: input.Email,
|
||||||
CompliancePageID: &trustCenter.ID,
|
CompliancePageID: &trustCenter.ID,
|
||||||
OrganizationID: trustCenter.OrganizationID,
|
OrganizationID: trustCenter.OrganizationID,
|
||||||
@@ -273,6 +272,49 @@ func (r *mutationResolver) VerifyMagicLink(ctx context.Context, input types.Veri
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateFullName is the resolver for the updateFullName field.
|
||||||
|
func (r *mutationResolver) UpdateFullName(ctx context.Context, input types.UpdateFullNameInput) (*types.UpdateFullNamePayload, error) {
|
||||||
|
identity := authn.IdentityFromContext(ctx)
|
||||||
|
if identity == nil {
|
||||||
|
return nil, gqlutils.Unauthenticatedf(ctx, "authentication is required to request access")
|
||||||
|
}
|
||||||
|
|
||||||
|
identity, err := r.iam.AccountService.UpdateIdentity(ctx, identity.ID, &iam.UpdateIdentityRequest{
|
||||||
|
FullName: input.FullName,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot update identity", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
compliancePage := compliancepage.CompliancePageFromContext(ctx)
|
||||||
|
|
||||||
|
profile, err := r.iam.OrganizationService.GetProfileForIdentityAndOrganization(ctx, identity.ID, compliancePage.OrganizationID)
|
||||||
|
if err != nil {
|
||||||
|
if _, ok := errors.AsType[*iam.ErrProfileNotFound](err); !ok {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot get profile", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if profile.Source == coredata.ProfileSourceManual {
|
||||||
|
if _, err := r.iam.OrganizationService.UpdateUser(ctx, &iam.UpdateUserRequest{
|
||||||
|
ID: profile.ID,
|
||||||
|
FullName: identity.FullName,
|
||||||
|
AdditionalEmailAddresses: profile.AdditionalEmailAddresses,
|
||||||
|
Kind: profile.Kind,
|
||||||
|
Position: profile.Position,
|
||||||
|
ContractStartDate: &profile.ContractStartDate,
|
||||||
|
ContractEndDate: &profile.ContractEndDate,
|
||||||
|
}); err != nil {
|
||||||
|
r.logger.ErrorCtx(ctx, "cannot update profile", log.Error(err))
|
||||||
|
return nil, gqlutils.Internal(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.UpdateFullNamePayload{Success: true}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// RequestAllAccesses is the resolver for the requestAllAccesses field.
|
// RequestAllAccesses is the resolver for the requestAllAccesses field.
|
||||||
func (r *mutationResolver) RequestAllAccesses(ctx context.Context) (*types.RequestAccessesPayload, error) {
|
func (r *mutationResolver) RequestAllAccesses(ctx context.Context) (*types.RequestAccessesPayload, error) {
|
||||||
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
||||||
|
|||||||
@@ -66,6 +66,20 @@ func AssumptionRequiredf(ctx context.Context, format string, a ...any) *gqlerror
|
|||||||
return AssumptionRequired(ctx, fmt.Errorf(format, a...))
|
return AssumptionRequired(ctx, fmt.Errorf(format, a...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FullNameRequired(ctx context.Context, err error) *gqlerror.Error {
|
||||||
|
return &gqlerror.Error{
|
||||||
|
Message: err.Error(),
|
||||||
|
Path: graphql.GetPath(ctx),
|
||||||
|
Extensions: map[string]any{
|
||||||
|
"code": "FULL_NAME_REQUIRED",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func FullNameRequiredf(ctx context.Context, format string, a ...any) *gqlerror.Error {
|
||||||
|
return FullNameRequired(ctx, fmt.Errorf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
func NDASignatureRequired(ctx context.Context, err error) *gqlerror.Error {
|
func NDASignatureRequired(ctx context.Context, err error) *gqlerror.Error {
|
||||||
return &gqlerror.Error{
|
return &gqlerror.Error{
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ func (s TrustCenterAccessService) Request(
|
|||||||
return fmt.Errorf("cannot load trust center: %w", err)
|
return fmt.Errorf("cannot load trust center: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
access := &coredata.TrustCenterAccess{}
|
access = &coredata.TrustCenterAccess{}
|
||||||
if err := access.LoadByTrustCenterIDAndIdentityID(ctx, tx, s.svc.scope, req.TrustCenterID, req.IdentityID); err != nil {
|
if err := access.LoadByTrustCenterIDAndIdentityID(ctx, tx, s.svc.scope, req.TrustCenterID, req.IdentityID); err != nil {
|
||||||
return fmt.Errorf("cannot load compliance page membership: %w", err)
|
return fmt.Errorf("cannot load compliance page membership: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user