@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<31b0b8ac2c59ccf3addd4508d56bd166>>
|
||||
* @generated SignedSource<<b1826b0f39e35064b4f2c8bc9691f63a>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -12,7 +12,7 @@ import { ConcreteRequest } from 'relay-runtime';
|
||||
export type MembershipRole = "ADMIN" | "AUDITOR" | "EMPLOYEE" | "OWNER" | "VIEWER";
|
||||
export type InviteUserInput = {
|
||||
createPeople: boolean;
|
||||
email: string;
|
||||
email: any;
|
||||
fullName: string;
|
||||
organizationId: string;
|
||||
role: MembershipRole;
|
||||
@@ -27,7 +27,7 @@ export type InviteUserDialogMutation$data = {
|
||||
readonly node: {
|
||||
readonly acceptedAt: any | null | undefined;
|
||||
readonly createdAt: any;
|
||||
readonly email: string;
|
||||
readonly email: any;
|
||||
readonly expiresAt: any;
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<9b84adc0253186c6f0a5f47837d83d7f>>
|
||||
* @generated SignedSource<<f9018169cee4d71768fca395e5dd59a9>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -11,7 +11,7 @@
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type BulkExportDocumentsInput = {
|
||||
documentIds: ReadonlyArray<string>;
|
||||
watermarkEmail?: string | null | undefined;
|
||||
watermarkEmail?: any | null | undefined;
|
||||
withSignatures: boolean;
|
||||
withWatermark: boolean;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<e263259b92f7b1fe14bca5fca49b20bf>>
|
||||
* @generated SignedSource<<5175c19e84ee71ec4a3e9e35e515991e>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -15,14 +15,14 @@ export type PeopleGraphNodeQuery$variables = {
|
||||
};
|
||||
export type PeopleGraphNodeQuery$data = {
|
||||
readonly node: {
|
||||
readonly additionalEmailAddresses?: ReadonlyArray<string>;
|
||||
readonly additionalEmailAddresses?: ReadonlyArray<any>;
|
||||
readonly contractEndDate?: any | null | undefined;
|
||||
readonly contractStartDate?: any | null | undefined;
|
||||
readonly fullName?: string;
|
||||
readonly id?: string;
|
||||
readonly kind?: PeopleKind;
|
||||
readonly position?: string | null | undefined;
|
||||
readonly primaryEmailAddress?: string;
|
||||
readonly primaryEmailAddress?: any;
|
||||
};
|
||||
};
|
||||
export type PeopleGraphNodeQuery = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<940911e0b7ae1ffe53a31f98216dcfe6>>
|
||||
* @generated SignedSource<<336b3e8036d321c95981b2d15c0b41b9>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -17,14 +17,14 @@ export type PeopleGraphPaginatedFragment$data = {
|
||||
readonly __id: string;
|
||||
readonly edges: ReadonlyArray<{
|
||||
readonly node: {
|
||||
readonly additionalEmailAddresses: ReadonlyArray<string>;
|
||||
readonly additionalEmailAddresses: ReadonlyArray<any>;
|
||||
readonly contractEndDate: any | null | undefined;
|
||||
readonly contractStartDate: any | null | undefined;
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
readonly kind: PeopleKind;
|
||||
readonly position: string | null | undefined;
|
||||
readonly primaryEmailAddress: string;
|
||||
readonly primaryEmailAddress: any;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<3b196ff5779051fcd1ed9cca6b7be112>>
|
||||
* @generated SignedSource<<8d8fcf4db72f5417db8a4f32129a687a>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -23,7 +23,7 @@ export type PeopleGraphQuery$data = {
|
||||
readonly node: {
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
readonly primaryEmailAddress: string;
|
||||
readonly primaryEmailAddress: any;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<a91a49863ad5c692ae869d3bcc0584cb>>
|
||||
* @generated SignedSource<<904f3388abab4e5e84dddf0528530a46>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -11,14 +11,14 @@
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type PeopleKind = "CONTRACTOR" | "EMPLOYEE" | "SERVICE_ACCOUNT";
|
||||
export type UpdatePeopleInput = {
|
||||
additionalEmailAddresses?: ReadonlyArray<string> | null | undefined;
|
||||
additionalEmailAddresses?: ReadonlyArray<any> | null | undefined;
|
||||
contractEndDate?: any | null | undefined;
|
||||
contractStartDate?: any | null | undefined;
|
||||
fullName?: string | null | undefined;
|
||||
id: string;
|
||||
kind?: PeopleKind | null | undefined;
|
||||
position?: string | null | undefined;
|
||||
primaryEmailAddress?: string | null | undefined;
|
||||
primaryEmailAddress?: any | null | undefined;
|
||||
};
|
||||
export type PeopleGraphUpdateMutation$variables = {
|
||||
input: UpdatePeopleInput;
|
||||
@@ -26,14 +26,14 @@ export type PeopleGraphUpdateMutation$variables = {
|
||||
export type PeopleGraphUpdateMutation$data = {
|
||||
readonly updatePeople: {
|
||||
readonly people: {
|
||||
readonly additionalEmailAddresses: ReadonlyArray<string>;
|
||||
readonly additionalEmailAddresses: ReadonlyArray<any>;
|
||||
readonly contractEndDate: any | null | undefined;
|
||||
readonly contractStartDate: any | null | undefined;
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
readonly kind: PeopleKind;
|
||||
readonly position: string | null | undefined;
|
||||
readonly primaryEmailAddress: string;
|
||||
readonly primaryEmailAddress: any;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<271260153dc611541b234266fbdd0c74>>
|
||||
* @generated SignedSource<<213636cdb170859b30c372b29ddbf752>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -11,7 +11,7 @@
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type CreateTrustCenterAccessInput = {
|
||||
active: boolean;
|
||||
email: string;
|
||||
email: any;
|
||||
name: string;
|
||||
trustCenterId: string;
|
||||
};
|
||||
@@ -27,7 +27,7 @@ export type TrustCenterAccessGraphCreateMutation$data = {
|
||||
readonly active: boolean;
|
||||
readonly activeCount: number;
|
||||
readonly createdAt: any;
|
||||
readonly email: string;
|
||||
readonly email: any;
|
||||
readonly hasAcceptedNonDisclosureAgreement: boolean;
|
||||
readonly id: string;
|
||||
readonly lastTokenExpiresAt: any | null | undefined;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<4d6afeeeed479773202c8516eeb63620>>
|
||||
* @generated SignedSource<<3c70b46fb46bf10a48eb06a5e76c1d75>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -31,7 +31,7 @@ export type TrustCenterAccessGraphUpdateMutation$data = {
|
||||
readonly active: boolean;
|
||||
readonly activeCount: number;
|
||||
readonly createdAt: any;
|
||||
readonly email: string;
|
||||
readonly email: any;
|
||||
readonly hasAcceptedNonDisclosureAgreement: boolean;
|
||||
readonly id: string;
|
||||
readonly lastTokenExpiresAt: any | null | undefined;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<a3da155281753945ab0645a04f0b74fb>>
|
||||
* @generated SignedSource<<5b0e12ba40232dd4328c0fd766513fb2>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -19,7 +19,7 @@ export type TrustCenterAccessGraph_accesses$data = {
|
||||
readonly active: boolean;
|
||||
readonly activeCount: number;
|
||||
readonly createdAt: any;
|
||||
readonly email: string;
|
||||
readonly email: any;
|
||||
readonly hasAcceptedNonDisclosureAgreement: boolean;
|
||||
readonly id: string;
|
||||
readonly lastTokenExpiresAt: any | null | undefined;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<626f9dd0bec23ddd103042d53539363a>>
|
||||
* @generated SignedSource<<abb20ee18aca56681898a0390db03bfc>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -21,7 +21,7 @@ export type EmployeeLayoutQuery$data = {
|
||||
readonly viewer: {
|
||||
readonly id: string;
|
||||
readonly user: {
|
||||
readonly email: string;
|
||||
readonly email: any;
|
||||
readonly fullName: string;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<b7983d3d3c089aa0efebaab639de76fb>>
|
||||
* @generated SignedSource<<5e4ec3cfaeb52bc478d496e37349880c>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -21,7 +21,7 @@ export type MainLayoutQuery$data = {
|
||||
readonly viewer: {
|
||||
readonly id: string;
|
||||
readonly user: {
|
||||
readonly email: string;
|
||||
readonly email: any;
|
||||
readonly fullName: string;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<f860e097afe4111c629ecf78d873a84e>>
|
||||
* @generated SignedSource<<3a082179d9ea9d47824b7ee925418b95>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -11,7 +11,7 @@
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type ExportDocumentVersionPDFInput = {
|
||||
documentVersionId: string;
|
||||
watermarkEmail?: string | null | undefined;
|
||||
watermarkEmail?: any | null | undefined;
|
||||
withSignatures: boolean;
|
||||
withWatermark: boolean;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<c1a6e41382db3951401d70c039c49f01>>
|
||||
* @generated SignedSource<<b5ef7f2a5ceb3688743c82362f625a55>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -13,7 +13,7 @@ export type DocumentDetailPageUserEmailQuery$variables = Record<PropertyKey, nev
|
||||
export type DocumentDetailPageUserEmailQuery$data = {
|
||||
readonly viewer: {
|
||||
readonly user: {
|
||||
readonly email: string;
|
||||
readonly email: any;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<7ff59bf602dca8eafe0a671cb7e95aad>>
|
||||
* @generated SignedSource<<959a59c16a4d27856820501f80379429>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -13,7 +13,7 @@ export type DocumentsPageUserEmailQuery$variables = Record<PropertyKey, never>;
|
||||
export type DocumentsPageUserEmailQuery$data = {
|
||||
readonly viewer: {
|
||||
readonly user: {
|
||||
readonly email: string;
|
||||
readonly email: any;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<e3ddbde4beb849447cb819f8991245a7>>
|
||||
* @generated SignedSource<<7d45f232043aa77c8e1e4ae7f8f330db>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -17,7 +17,7 @@ export type DocumentSignaturesTab_signature$data = {
|
||||
readonly signedAt: any | null | undefined;
|
||||
readonly signedBy: {
|
||||
readonly fullName: string;
|
||||
readonly primaryEmailAddress: string;
|
||||
readonly primaryEmailAddress: any;
|
||||
};
|
||||
readonly state: DocumentVersionSignatureState;
|
||||
readonly " $fragmentType": "DocumentSignaturesTab_signature";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<328e9d55b6661d3330cb961426393d6f>>
|
||||
* @generated SignedSource<<807a8f8c5c320dadd6b9672ef48583f2>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -22,7 +22,7 @@ export type DocumentSignaturesTab_version$data = {
|
||||
readonly signedBy: {
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
readonly primaryEmailAddress: string;
|
||||
readonly primaryEmailAddress: any;
|
||||
};
|
||||
readonly state: DocumentVersionSignatureState;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"DocumentSignaturesTab_signature">;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<cf446d4f8991b5ff332b3d81174c3247>>
|
||||
* @generated SignedSource<<22054346a606e1ce4a26b02218f87af9>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -11,14 +11,14 @@
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type PeopleKind = "CONTRACTOR" | "EMPLOYEE" | "SERVICE_ACCOUNT";
|
||||
export type CreatePeopleInput = {
|
||||
additionalEmailAddresses?: ReadonlyArray<string> | null | undefined;
|
||||
additionalEmailAddresses?: ReadonlyArray<any> | null | undefined;
|
||||
contractEndDate?: any | null | undefined;
|
||||
contractStartDate?: any | null | undefined;
|
||||
fullName: string;
|
||||
kind: PeopleKind;
|
||||
organizationId: string;
|
||||
position?: string | null | undefined;
|
||||
primaryEmailAddress: string;
|
||||
primaryEmailAddress: any;
|
||||
};
|
||||
export type CreatePeopleDialogMutation$variables = {
|
||||
connections: ReadonlyArray<string>;
|
||||
@@ -28,12 +28,12 @@ export type CreatePeopleDialogMutation$data = {
|
||||
readonly createPeople: {
|
||||
readonly peopleEdge: {
|
||||
readonly node: {
|
||||
readonly additionalEmailAddresses: ReadonlyArray<string>;
|
||||
readonly additionalEmailAddresses: ReadonlyArray<any>;
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
readonly kind: PeopleKind;
|
||||
readonly position: string | null | undefined;
|
||||
readonly primaryEmailAddress: string;
|
||||
readonly primaryEmailAddress: any;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<dd7d5d34935f87fcfb658ca6cfc5e794>>
|
||||
* @generated SignedSource<<e3763975ef1132c3e2f909019b6cd98c>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -20,7 +20,7 @@ export type MembersSettingsTabInvitationsFragment$data = {
|
||||
readonly node: {
|
||||
readonly acceptedAt: any | null | undefined;
|
||||
readonly createdAt: any;
|
||||
readonly email: string;
|
||||
readonly email: any;
|
||||
readonly expiresAt: any;
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<c3bf3676d3f8688315fc342efcf54547>>
|
||||
* @generated SignedSource<<21ae595420b0098920e8d7f28834c7af>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -20,7 +20,7 @@ export type MembersSettingsTabMembershipsFragment$data = {
|
||||
readonly node: {
|
||||
readonly authMethod: UserAuthMethod;
|
||||
readonly createdAt: any;
|
||||
readonly emailAddress: string;
|
||||
readonly emailAddress: any;
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
readonly role: MembershipRole;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<843a80b3503ff276081e69b558dcce81>>
|
||||
* @generated SignedSource<<ac1551146f55ada33ee647ca3985d467>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -11,7 +11,7 @@
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type CreateVendorContactInput = {
|
||||
email?: string | null | undefined;
|
||||
email?: any | null | undefined;
|
||||
fullName?: string | null | undefined;
|
||||
phone?: string | null | undefined;
|
||||
role?: string | null | undefined;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<d22f20fafedcdddc50cd21917a8a5c28>>
|
||||
* @generated SignedSource<<00c307339357baa16c237c563b8f32bd>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -11,7 +11,7 @@
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type UpdateVendorContactInput = {
|
||||
email?: string | null | undefined;
|
||||
email?: any | null | undefined;
|
||||
fullName?: string | null | undefined;
|
||||
id: string;
|
||||
phone?: string | null | undefined;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<28eef433ba6749a95468492e8ac9d1a6>>
|
||||
* @generated SignedSource<<8020981cbf1e1b2b59c3ae9027973b17>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -12,7 +12,7 @@ import { ReaderFragment } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type VendorContactsTabFragment_contact$data = {
|
||||
readonly createdAt: any;
|
||||
readonly email: string | null | undefined;
|
||||
readonly email: any | null | undefined;
|
||||
readonly fullName: string | null | undefined;
|
||||
readonly id: string;
|
||||
readonly phone: string | null | undefined;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<446953c5eafa3b9a465d245da3bea1af>>
|
||||
* @generated SignedSource<<5344ac5d6a506485d45e399361b92299>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -11,7 +11,7 @@
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type RequestDocumentAccessInput = {
|
||||
documentId: string;
|
||||
email?: string | null | undefined;
|
||||
email?: any | null | undefined;
|
||||
name?: string | null | undefined;
|
||||
trustCenterId: string;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<898167474e2680273ad8b588a63a47c5>>
|
||||
* @generated SignedSource<<19ada29ea9b8f557b4fcc39f57bc3aec>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type RequestAllAccessesInput = {
|
||||
email?: string | null | undefined;
|
||||
email?: any | null | undefined;
|
||||
name?: string | null | undefined;
|
||||
trustCenterId: string;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<74bc40a8998c962930b3f0b63dc6acd9>>
|
||||
* @generated SignedSource<<858effd78b88a123430edcf6fcb100ed>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type RequestReportAccessInput = {
|
||||
email?: string | null | undefined;
|
||||
email?: any | null | undefined;
|
||||
name?: string | null | undefined;
|
||||
reportId: string;
|
||||
trustCenterId: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<4c07d5c8e345a8e3015f512403927890>>
|
||||
* @generated SignedSource<<32242c5e0b4dc9c9368c0e2f4034d95e>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type RequestTrustCenterFileAccessInput = {
|
||||
email?: string | null | undefined;
|
||||
email?: any | null | undefined;
|
||||
name?: string | null | undefined;
|
||||
trustCenterFileId: string;
|
||||
trustCenterId: string;
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
|
||||
"github.com/crewjam/saml"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
)
|
||||
|
||||
func ExtractAttributeValue(assertion *saml.Assertion, attributeName string) (string, error) {
|
||||
@@ -98,25 +99,32 @@ func isValidRole(role string) bool {
|
||||
func ExtractUserAttributes(
|
||||
assertion *saml.Assertion,
|
||||
attributeEmail, attributeFirstname, attributeLastname, attributeRole string,
|
||||
) (email, fullname, role string, err error) {
|
||||
) (email mail.Addr, fullname, role string, err error) {
|
||||
if len(assertion.AttributeStatements) == 0 {
|
||||
if assertion.Subject != nil && assertion.Subject.NameID != nil {
|
||||
email = assertion.Subject.NameID.Value
|
||||
fullname = email
|
||||
email, err = mail.ParseAddr(assertion.Subject.NameID.Value)
|
||||
if err != nil {
|
||||
return mail.Nil, "", "", fmt.Errorf("invalid nameID as email address")
|
||||
}
|
||||
fullname = email.String()
|
||||
role = ""
|
||||
return email, fullname, role, nil
|
||||
}
|
||||
return "", "", "", fmt.Errorf("no attribute statement and no NameID in assertion")
|
||||
return mail.Nil, "", "", fmt.Errorf("no attribute statement and no NameID in assertion")
|
||||
}
|
||||
|
||||
email, err = ExtractAttributeValue(assertion, attributeEmail)
|
||||
emailString, err := ExtractAttributeValue(assertion, attributeEmail)
|
||||
if err != nil {
|
||||
if assertion.Subject != nil && assertion.Subject.NameID != nil {
|
||||
email = assertion.Subject.NameID.Value
|
||||
emailString = assertion.Subject.NameID.Value
|
||||
} else {
|
||||
return "", "", "", fmt.Errorf("cannot extract email: %w", err)
|
||||
return mail.Nil, "", "", fmt.Errorf("cannot extract email: %w", err)
|
||||
}
|
||||
}
|
||||
email, err = mail.ParseAddr(emailString)
|
||||
if err != nil {
|
||||
return mail.Nil, "", "", fmt.Errorf("invalid attribute email")
|
||||
}
|
||||
|
||||
firstname, err := ExtractAttributeValue(assertion, attributeFirstname)
|
||||
if err != nil {
|
||||
@@ -135,7 +143,7 @@ func ExtractUserAttributes(
|
||||
} else if lastname != "" {
|
||||
fullname = lastname
|
||||
} else {
|
||||
fullname = email
|
||||
fullname = email.String()
|
||||
}
|
||||
|
||||
role, err = ExtractAttributeValue(assertion, attributeRole)
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/crypto/cipher"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -372,7 +373,7 @@ func (s *SAMLService) InitiateSAMLLogin(
|
||||
}
|
||||
|
||||
type SAMLUserInfo struct {
|
||||
Email string
|
||||
Email mail.Addr
|
||||
FullName string
|
||||
Role *coredata.MembershipRole
|
||||
SAMLSubject string
|
||||
@@ -516,13 +517,8 @@ func (s *SAMLService) HandleSAMLAssertion(
|
||||
return nil, ErrCannotExtractUserAttributes{Err: err}
|
||||
}
|
||||
|
||||
actualEmailDomain, err := ExtractEmailDomain(email)
|
||||
if err != nil {
|
||||
return nil, ErrCannotExtractUserAttributes{Err: fmt.Errorf("cannot extract domain from email: %w", err)}
|
||||
}
|
||||
|
||||
if actualEmailDomain != config.EmailDomain {
|
||||
return nil, fmt.Errorf("email domain mismatch: assertion contains email with domain %s but SAML config is for domain %s", actualEmailDomain, config.EmailDomain)
|
||||
if email.Domain() != config.EmailDomain {
|
||||
return nil, fmt.Errorf("email domain mismatch: assertion contains email with domain %s but SAML config is for domain %s", email.Domain(), config.EmailDomain)
|
||||
}
|
||||
|
||||
systemRole := MapSAMLRoleToSystemRole(samlRole)
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/mail"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
@@ -32,6 +31,7 @@ import (
|
||||
"go.probo.inc/probo/pkg/crypto/cipher"
|
||||
"go.probo.inc/probo/pkg/crypto/passwdhash"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/statelesstoken"
|
||||
)
|
||||
|
||||
@@ -102,8 +102,8 @@ type (
|
||||
ErrSAMLAutoSignupDisabled struct{}
|
||||
|
||||
EmailConfirmationData struct {
|
||||
UserID gid.GID `json:"uid"`
|
||||
Email string `json:"email"`
|
||||
UserID gid.GID `json:"uid"`
|
||||
Email mail.Addr `json:"email"`
|
||||
}
|
||||
|
||||
InvitationData struct {
|
||||
@@ -113,7 +113,7 @@ type (
|
||||
CreatePeople bool `json:"create_people"`
|
||||
}
|
||||
PasswordResetData struct {
|
||||
Email string `json:"email"`
|
||||
Email mail.Addr `json:"email"`
|
||||
}
|
||||
|
||||
ErrSAMLAuthRequired struct {
|
||||
@@ -262,7 +262,7 @@ func (s Service) CanCreateOrganization(ctx context.Context, userID gid.GID) erro
|
||||
|
||||
func (s Service) ForgetPassword(
|
||||
ctx context.Context,
|
||||
email string,
|
||||
email mail.Addr,
|
||||
) error {
|
||||
// Always generate a new token to avoid timing attacks and leaking information
|
||||
// about existing emails
|
||||
@@ -329,7 +329,7 @@ func (s Service) ForgetPassword(
|
||||
|
||||
func (s Service) SignUp(
|
||||
ctx context.Context,
|
||||
emailAddress string,
|
||||
emailAddress mail.Addr,
|
||||
password string,
|
||||
fullName string,
|
||||
) (*coredata.User, *coredata.Session, error) {
|
||||
@@ -337,11 +337,6 @@ func (s Service) SignUp(
|
||||
return nil, nil, &ErrSignupDisabled{}
|
||||
}
|
||||
|
||||
emailAddress2, err := mail.ParseAddress(emailAddress)
|
||||
if err != nil {
|
||||
return nil, nil, &ErrInvalidEmail{emailAddress}
|
||||
}
|
||||
|
||||
if len(password) < 8 || len(password) > 128 {
|
||||
return nil, nil, &ErrInvalidPassword{minLength: 8, maxLength: 128}
|
||||
}
|
||||
@@ -358,7 +353,7 @@ func (s Service) SignUp(
|
||||
now := time.Now()
|
||||
user := &coredata.User{
|
||||
ID: gid.New(gid.NilTenant, coredata.UserEntityType),
|
||||
EmailAddress: emailAddress2.Address,
|
||||
EmailAddress: emailAddress,
|
||||
HashedPassword: hashedPassword,
|
||||
EmailAddressVerified: false,
|
||||
FullName: fullName,
|
||||
@@ -453,16 +448,12 @@ func (s Service) ProvisionSAMLUser(
|
||||
ctx context.Context,
|
||||
samlConfigID gid.GID,
|
||||
organizationID gid.GID,
|
||||
emailAddress string,
|
||||
emailAddress mail.Addr,
|
||||
fullName string,
|
||||
samlSubject string,
|
||||
existingSession *coredata.Session,
|
||||
sessionDuration time.Duration,
|
||||
) (*coredata.Session, *coredata.User, error) {
|
||||
if _, err := mail.ParseAddress(emailAddress); err != nil {
|
||||
return nil, nil, &ErrInvalidEmail{emailAddress}
|
||||
}
|
||||
|
||||
if fullName == "" {
|
||||
return nil, nil, &ErrInvalidFullName{fullName}
|
||||
}
|
||||
@@ -566,14 +557,10 @@ func (s Service) ProvisionSAMLUser(
|
||||
|
||||
func (s Service) SignIn(
|
||||
ctx context.Context,
|
||||
emailAddress string,
|
||||
emailAddress mail.Addr,
|
||||
password string,
|
||||
existingSession *coredata.Session,
|
||||
) (*coredata.Session, *coredata.User, error) {
|
||||
if _, err := mail.ParseAddress(emailAddress); err != nil {
|
||||
return nil, nil, &ErrInvalidCredentials{"invalid email or password"}
|
||||
}
|
||||
|
||||
user := &coredata.User{}
|
||||
session := &coredata.Session{}
|
||||
|
||||
@@ -868,10 +855,6 @@ func (s Service) SignupFromInvitation(
|
||||
return nil, nil, &ErrInvalidPassword{minLength: 8, maxLength: 128}
|
||||
}
|
||||
|
||||
if _, err := mail.ParseAddress(payload.Data.Email); err != nil {
|
||||
return nil, nil, &ErrInvalidEmail{payload.Data.Email}
|
||||
}
|
||||
|
||||
if fullName == "" {
|
||||
fullName = payload.Data.FullName
|
||||
}
|
||||
@@ -980,7 +963,7 @@ func (s *TenantAuthService) GetUserAuthMethod(
|
||||
}
|
||||
|
||||
// User has SAML subject - check if there's SAML config for this org + user's domain
|
||||
domain := extractDomain(user.EmailAddress)
|
||||
domain := user.EmailAddress.Domain()
|
||||
if domain == "" {
|
||||
authMethod = coredata.UserAuthMethodPassword
|
||||
return nil
|
||||
@@ -1005,20 +988,6 @@ func (s *TenantAuthService) GetUserAuthMethod(
|
||||
return authMethod, err
|
||||
}
|
||||
|
||||
func extractDomain(email string) string {
|
||||
atIndex := -1
|
||||
for i := 0; i < len(email); i++ {
|
||||
if email[i] == '@' {
|
||||
atIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if atIndex == -1 || atIndex == len(email)-1 {
|
||||
return ""
|
||||
}
|
||||
return email[atIndex+1:]
|
||||
}
|
||||
|
||||
// CheckOrganizationAccess checks access to multiple organizations in a single database query
|
||||
// Always uses batch processing to avoid N+1 query problems
|
||||
func (s Service) CheckOrganizationAccess(
|
||||
@@ -1029,7 +998,7 @@ func (s Service) CheckOrganizationAccess(
|
||||
) (map[gid.GID]AccessResult, error) {
|
||||
results := make(map[gid.GID]AccessResult, len(organizationIDs))
|
||||
|
||||
domain := extractDomain(user.EmailAddress)
|
||||
domain := user.EmailAddress.Domain()
|
||||
if domain == "" {
|
||||
// All organizations fail with invalid email
|
||||
for _, orgID := range organizationIDs {
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"go.probo.inc/probo/packages/emails"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"go.probo.inc/probo/pkg/statelesstoken"
|
||||
)
|
||||
@@ -242,7 +243,7 @@ func (s *Service) AcceptInvitationByID(
|
||||
|
||||
type UserInvitation struct {
|
||||
ID gid.GID
|
||||
Email string
|
||||
Email mail.Addr
|
||||
FullName string
|
||||
Role coredata.MembershipRole
|
||||
ExpiresAt time.Time
|
||||
@@ -259,7 +260,7 @@ type OrganizationSummary struct {
|
||||
|
||||
func (s *Service) GetUserPendingInvitations(
|
||||
ctx context.Context,
|
||||
email string,
|
||||
email mail.Addr,
|
||||
) ([]*UserInvitation, error) {
|
||||
userInvitations := []*UserInvitation{}
|
||||
|
||||
@@ -679,7 +680,7 @@ func (s *TenantAuthzService) UpdateMembershipRole(
|
||||
func (s *TenantAuthzService) InviteUserToOrganization(
|
||||
ctx context.Context,
|
||||
organizationID gid.GID,
|
||||
emailAddress string,
|
||||
emailAddress mail.Addr,
|
||||
fullName string,
|
||||
role coredata.MembershipRole,
|
||||
) (*coredata.Invitation, error) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
)
|
||||
|
||||
@@ -701,7 +702,7 @@ func (p *Document) IsLastSignableVersionSignedByUserEmail(
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
documentID gid.GID,
|
||||
userEmail string,
|
||||
userEmail mail.Addr,
|
||||
) (bool, error) {
|
||||
q := `
|
||||
WITH last_signable_version AS (
|
||||
|
||||
@@ -16,6 +16,7 @@ package coredata
|
||||
|
||||
import (
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -23,7 +24,7 @@ type (
|
||||
query *string
|
||||
trustCenterVisibilities []TrustCenterVisibility
|
||||
published *bool
|
||||
userEmail *string
|
||||
userEmail *mail.Addr
|
||||
}
|
||||
)
|
||||
|
||||
@@ -47,7 +48,7 @@ func (f *DocumentFilter) WithPublished(published *bool) *DocumentFilter {
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *DocumentFilter) WithUserEmail(userEmail *string) *DocumentFilter {
|
||||
func (f *DocumentFilter) WithUserEmail(userEmail *mail.Addr) *DocumentFilter {
|
||||
f.userEmail = userEmail
|
||||
return f
|
||||
}
|
||||
|
||||
@@ -16,11 +16,12 @@ package coredata
|
||||
|
||||
import (
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
)
|
||||
|
||||
type (
|
||||
DocumentVersionFilter struct {
|
||||
userEmail *string
|
||||
userEmail *mail.Addr
|
||||
}
|
||||
)
|
||||
|
||||
@@ -28,7 +29,7 @@ func NewDocumentVersionFilter() *DocumentVersionFilter {
|
||||
return &DocumentVersionFilter{}
|
||||
}
|
||||
|
||||
func (f *DocumentVersionFilter) WithUserEmail(userEmail *string) *DocumentVersionFilter {
|
||||
func (f *DocumentVersionFilter) WithUserEmail(userEmail *mail.Addr) *DocumentVersionFilter {
|
||||
f.userEmail = userEmail
|
||||
return f
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
)
|
||||
|
||||
@@ -424,7 +425,7 @@ func (pvs *DocumentVersionSignature) IsSignedByUserEmail(
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
documentVersionID gid.GID,
|
||||
userEmail string,
|
||||
userEmail mail.Addr,
|
||||
) (bool, error) {
|
||||
q := `
|
||||
SELECT EXISTS (
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -45,7 +46,7 @@ var (
|
||||
|
||||
func NewEmail(
|
||||
recipientName string,
|
||||
recipientEmail string,
|
||||
recipientEmail mail.Addr,
|
||||
subject string,
|
||||
textBody string,
|
||||
htmlBody *string,
|
||||
@@ -54,7 +55,7 @@ func NewEmail(
|
||||
return &Email{
|
||||
ID: gid.New(gid.NilTenant, EmailEntityType),
|
||||
RecipientName: recipientName,
|
||||
RecipientEmail: recipientEmail,
|
||||
RecipientEmail: recipientEmail.String(),
|
||||
Subject: subject,
|
||||
TextBody: textBody,
|
||||
HtmlBody: htmlBody,
|
||||
|
||||
@@ -11,31 +11,32 @@ import (
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
)
|
||||
|
||||
type (
|
||||
ExportJob struct {
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
Type ExportJobType `db:"type"`
|
||||
Arguments json.RawMessage `db:"arguments"`
|
||||
Error *string `db:"error"`
|
||||
Status ExportJobStatus `db:"status"`
|
||||
FileID *gid.GID `db:"file_id"`
|
||||
RecipientEmail string `db:"recipient_email"`
|
||||
RecipientName string `db:"recipient_name"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
StartedAt *time.Time `db:"started_at"`
|
||||
CompletedAt *time.Time `db:"completed_at"`
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
Type ExportJobType `db:"type"`
|
||||
Arguments json.RawMessage `db:"arguments"`
|
||||
Error *string `db:"error"`
|
||||
Status ExportJobStatus `db:"status"`
|
||||
FileID *gid.GID `db:"file_id"`
|
||||
RecipientEmail mail.Addr `db:"recipient_email"`
|
||||
RecipientName string `db:"recipient_name"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
StartedAt *time.Time `db:"started_at"`
|
||||
CompletedAt *time.Time `db:"completed_at"`
|
||||
}
|
||||
|
||||
ExportJobs []*ExportJob
|
||||
|
||||
DocumentExportArguments struct {
|
||||
DocumentIDs []gid.GID `json:"document_ids"`
|
||||
WithWatermark bool `json:"with_watermark"`
|
||||
WatermarkEmail *string `json:"watermark_email"`
|
||||
WithSignatures bool `json:"with_signatures"`
|
||||
DocumentIDs []gid.GID `json:"document_ids"`
|
||||
WithWatermark bool `json:"with_watermark"`
|
||||
WatermarkEmail *mail.Addr `json:"watermark_email"`
|
||||
WithSignatures bool `json:"with_signatures"`
|
||||
}
|
||||
|
||||
FrameworkExportArguments struct {
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
)
|
||||
|
||||
@@ -31,9 +32,9 @@ type (
|
||||
Invitation struct {
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
Email string `db:"email"`
|
||||
Email mail.Addr `db:"email"`
|
||||
FullName string `db:"full_name"`
|
||||
Role MembershipRole `db:"role"`
|
||||
Role MembershipRole `db:"role"`
|
||||
Status InvitationStatus `db:"status"`
|
||||
ExpiresAt time.Time `db:"expires_at"`
|
||||
AcceptedAt *time.Time `db:"accepted_at"`
|
||||
@@ -43,10 +44,10 @@ type (
|
||||
Invitations []*Invitation
|
||||
|
||||
InvitationData struct {
|
||||
InvitationID gid.GID `json:"invitation_id"`
|
||||
OrganizationID gid.GID `json:"organization_id"`
|
||||
Email string `json:"email"`
|
||||
FullName string `json:"full_name"`
|
||||
InvitationID gid.GID `json:"invitation_id"`
|
||||
OrganizationID gid.GID `json:"organization_id"`
|
||||
Email mail.Addr `json:"email"`
|
||||
FullName string `json:"full_name"`
|
||||
Role MembershipRole `json:"role"`
|
||||
}
|
||||
|
||||
@@ -241,7 +242,7 @@ func (i *Invitations) LoadByEmail(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
email string,
|
||||
email mail.Addr,
|
||||
cursor *page.Cursor[InvitationOrderField],
|
||||
filter *InvitationFilter,
|
||||
) error {
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
)
|
||||
|
||||
@@ -36,7 +37,7 @@ type (
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
Role MembershipRole `db:"role"`
|
||||
FullName string `db:"full_name"`
|
||||
EmailAddress string `db:"email_address"`
|
||||
EmailAddress mail.Addr `db:"email_address"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
@@ -24,22 +24,23 @@ import (
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
)
|
||||
|
||||
type (
|
||||
People struct {
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
Kind PeopleKind `db:"kind"`
|
||||
FullName string `db:"full_name"`
|
||||
PrimaryEmailAddress string `db:"primary_email_address"`
|
||||
AdditionalEmailAddresses []string `db:"additional_email_addresses"`
|
||||
Position *string `db:"position"`
|
||||
ContractStartDate *time.Time `db:"contract_start_date"`
|
||||
ContractEndDate *time.Time `db:"contract_end_date"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
Kind PeopleKind `db:"kind"`
|
||||
FullName string `db:"full_name"`
|
||||
PrimaryEmailAddress mail.Addr `db:"primary_email_address"`
|
||||
AdditionalEmailAddresses []mail.Addr `db:"additional_email_addresses"`
|
||||
Position *string `db:"position"`
|
||||
ContractStartDate *time.Time `db:"contract_start_date"`
|
||||
ContractEndDate *time.Time `db:"contract_end_date"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
Peoples []*People
|
||||
@@ -180,7 +181,7 @@ func (p *People) LoadByEmailAndOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
primaryEmailAddress string,
|
||||
primaryEmailAddress mail.Addr,
|
||||
organizationID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
@@ -221,7 +222,7 @@ LIMIT 1;
|
||||
people, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[People])
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return &ErrPeopleNotFound{Identifier: primaryEmailAddress}
|
||||
return &ErrPeopleNotFound{Identifier: primaryEmailAddress.String()}
|
||||
}
|
||||
|
||||
return fmt.Errorf("cannot collect people: %w", err)
|
||||
|
||||
@@ -20,9 +20,9 @@ import (
|
||||
"maps"
|
||||
"time"
|
||||
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
)
|
||||
|
||||
type SAMLConfiguration struct {
|
||||
|
||||
@@ -24,23 +24,24 @@ import (
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
)
|
||||
|
||||
type (
|
||||
SlackMessage struct {
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
Type SlackMessageType `db:"type"`
|
||||
Body map[string]any `db:"body"`
|
||||
MessageTS *string `db:"message_ts"`
|
||||
ChannelID *string `db:"channel_id"`
|
||||
RequesterEmail *string `db:"requester_email"`
|
||||
Metadata map[string]any `db:"metadata"`
|
||||
InitialSlackMessageID gid.GID `db:"initial_slack_message_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
SentAt *time.Time `db:"sent_at"`
|
||||
Error *string `db:"error"`
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
Type SlackMessageType `db:"type"`
|
||||
Body map[string]any `db:"body"`
|
||||
MessageTS *string `db:"message_ts"`
|
||||
ChannelID *string `db:"channel_id"`
|
||||
RequesterEmail *mail.Addr `db:"requester_email"`
|
||||
Metadata map[string]any `db:"metadata"`
|
||||
InitialSlackMessageID gid.GID `db:"initial_slack_message_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
SentAt *time.Time `db:"sent_at"`
|
||||
Error *string `db:"error"`
|
||||
}
|
||||
|
||||
ErrNoUnsentSlackMessage struct{}
|
||||
@@ -61,7 +62,6 @@ func NewSlackMessage(
|
||||
organizationID gid.GID,
|
||||
messageType SlackMessageType,
|
||||
body map[string]any,
|
||||
requesterEmail *string,
|
||||
) *SlackMessage {
|
||||
now := time.Now()
|
||||
id := gid.New(scope.GetTenantID(), SlackMessageEntityType)
|
||||
@@ -70,7 +70,6 @@ func NewSlackMessage(
|
||||
OrganizationID: organizationID,
|
||||
Type: messageType,
|
||||
Body: body,
|
||||
RequesterEmail: requesterEmail,
|
||||
InitialSlackMessageID: id,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
@@ -438,7 +437,7 @@ func (s *SlackMessage) LoadLatestByRequesterEmailAndType(
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
requesterEmail string,
|
||||
requesterEmail mail.Addr,
|
||||
messageType SlackMessageType,
|
||||
since time.Time,
|
||||
) error {
|
||||
|
||||
@@ -26,24 +26,25 @@ import (
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
)
|
||||
|
||||
type (
|
||||
TrustCenterAccess struct {
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
TenantID gid.TenantID `db:"tenant_id"`
|
||||
TrustCenterID gid.GID `db:"trust_center_id"`
|
||||
Email string `db:"email"`
|
||||
Name string `db:"name"`
|
||||
Active bool `db:"active"`
|
||||
HasAcceptedNonDisclosureAgreement bool `db:"has_accepted_non_disclosure_agreement"`
|
||||
HasAcceptedNonDisclosureAgreementMetadata json.RawMessage `db:"has_accepted_non_disclosure_agreement_metadata"`
|
||||
NDAFileID *gid.GID `db:"nda_file_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
LastTokenExpiresAt *time.Time `db:"last_token_expires_at"`
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
TenantID gid.TenantID `db:"tenant_id"`
|
||||
TrustCenterID gid.GID `db:"trust_center_id"`
|
||||
Email mail.Addr `db:"email"`
|
||||
Name string `db:"name"`
|
||||
Active bool `db:"active"`
|
||||
HasAcceptedNonDisclosureAgreement bool `db:"has_accepted_non_disclosure_agreement"`
|
||||
HasAcceptedNonDisclosureAgreementMetadata json.RawMessage `db:"has_accepted_non_disclosure_agreement_metadata"`
|
||||
NDAFileID *gid.GID `db:"nda_file_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
LastTokenExpiresAt *time.Time `db:"last_token_expires_at"`
|
||||
}
|
||||
|
||||
TrustCenterAccesses []*TrustCenterAccess
|
||||
@@ -132,7 +133,7 @@ func (tca *TrustCenterAccess) LoadByTrustCenterIDAndEmail(
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
trustCenterID gid.GID,
|
||||
email string,
|
||||
email mail.Addr,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
|
||||
@@ -22,23 +22,24 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
)
|
||||
|
||||
type (
|
||||
User struct {
|
||||
ID gid.GID `db:"id"`
|
||||
EmailAddress string `db:"email_address"`
|
||||
HashedPassword []byte `db:"hashed_password"`
|
||||
FullName string `db:"fullname"`
|
||||
EmailAddressVerified bool `db:"email_address_verified"`
|
||||
SAMLSubject *string `db:"saml_subject"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
EmailAddress mail.Addr `db:"email_address"`
|
||||
HashedPassword []byte `db:"hashed_password"`
|
||||
FullName string `db:"fullname"`
|
||||
EmailAddressVerified bool `db:"email_address_verified"`
|
||||
SAMLSubject *string `db:"saml_subject"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
Users []*User
|
||||
@@ -150,7 +151,7 @@ WHERE
|
||||
func (u *User) LoadByEmail(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
email string,
|
||||
email mail.Addr,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
@@ -179,7 +180,7 @@ LIMIT 1;
|
||||
user, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[User])
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return &ErrUserNotFound{Identifier: email}
|
||||
return &ErrUserNotFound{Identifier: email.String()}
|
||||
}
|
||||
|
||||
return fmt.Errorf("cannot collect user: %w", err)
|
||||
@@ -362,11 +363,11 @@ WHERE
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"user_id": u.ID,
|
||||
"email_address": u.EmailAddress,
|
||||
"email_address_verified": u.EmailAddressVerified,
|
||||
"saml_subject": u.SAMLSubject,
|
||||
"updated_at": u.UpdatedAt,
|
||||
"user_id": u.ID,
|
||||
"email_address": u.EmailAddress,
|
||||
"email_address_verified": u.EmailAddressVerified,
|
||||
"saml_subject": u.SAMLSubject,
|
||||
"updated_at": u.UpdatedAt,
|
||||
}
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
|
||||
@@ -24,22 +24,23 @@ import (
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
)
|
||||
|
||||
type (
|
||||
VendorContact struct {
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
VendorID gid.GID `db:"vendor_id"`
|
||||
FullName *string `db:"full_name"`
|
||||
Email *string `db:"email"`
|
||||
Phone *string `db:"phone"`
|
||||
Role *string `db:"role"`
|
||||
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||
SourceID *gid.GID `db:"source_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
VendorID gid.GID `db:"vendor_id"`
|
||||
FullName *string `db:"full_name"`
|
||||
Email *mail.Addr `db:"email"`
|
||||
Phone *string `db:"phone"`
|
||||
Role *string `db:"role"`
|
||||
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||
SourceID *gid.GID `db:"source_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
VendorContacts []*VendorContact
|
||||
|
||||
74
pkg/mail/addr.go
Normal file
74
pkg/mail/addr.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package mail
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/mail"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Addr string
|
||||
|
||||
var Nil Addr
|
||||
|
||||
func (a Addr) String() string {
|
||||
return string(a)
|
||||
}
|
||||
|
||||
func (a *Addr) Domain() string {
|
||||
return strings.Split(a.String(), "@")[1]
|
||||
}
|
||||
|
||||
func ParseAddr(s string) (Addr, error) {
|
||||
netMailAddr, err := mail.ParseAddress(s)
|
||||
if err != nil {
|
||||
return Nil, fmt.Errorf("cannot parse address %s: %w", s, err)
|
||||
}
|
||||
|
||||
parts := strings.Split(netMailAddr.Address, "@")
|
||||
if len(parts) != 2 {
|
||||
return Nil, fmt.Errorf("invalid email address format")
|
||||
}
|
||||
|
||||
return Addr(netMailAddr.Address), nil
|
||||
}
|
||||
|
||||
func (a Addr) Value() (driver.Value, error) {
|
||||
return a.String(), nil
|
||||
}
|
||||
|
||||
func (a *Addr) Scan(value any) error {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
parsed, err := ParseAddr(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*a = parsed
|
||||
default:
|
||||
return fmt.Errorf("invalid type for mail.Addr: expected string, got %T", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Addr) UnmarshalJSON(data []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err != nil {
|
||||
return fmt.Errorf("cannot unmarshal email string from JSON")
|
||||
}
|
||||
|
||||
parsed, err := ParseAddr(s)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot parse email address")
|
||||
}
|
||||
|
||||
*a = parsed
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a Addr) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(a.String())
|
||||
}
|
||||
@@ -148,7 +148,7 @@ func (s *ConnectorService) Create(
|
||||
return fmt.Errorf("cannot parse template JSON: %w", err)
|
||||
}
|
||||
|
||||
slackMessage := coredata.NewSlackMessage(s.svc.scope, req.OrganizationID, coredata.SlackMessageTypeWelcome, body, nil)
|
||||
slackMessage := coredata.NewSlackMessage(s.svc.scope, req.OrganizationID, coredata.SlackMessageTypeWelcome, body)
|
||||
if err := slackMessage.Insert(ctx, conn, s.svc.scope); err != nil {
|
||||
return fmt.Errorf("cannot insert slack message: %w", err)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/mail"
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
@@ -24,6 +23,7 @@ import (
|
||||
"go.probo.inc/probo/pkg/docgen"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/html2pdf"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"go.probo.inc/probo/pkg/statelesstoken"
|
||||
"go.probo.inc/probo/pkg/validator"
|
||||
@@ -608,7 +608,7 @@ func (s *DocumentService) SignDocumentVersion(
|
||||
func (s *DocumentService) SignDocumentVersionByEmail(
|
||||
ctx context.Context,
|
||||
documentVersionID gid.GID,
|
||||
userEmail string,
|
||||
userEmail mail.Addr,
|
||||
) (*coredata.DocumentVersionSignature, error) {
|
||||
var documentVersionSignature *coredata.DocumentVersionSignature
|
||||
|
||||
@@ -887,7 +887,7 @@ func (s *DocumentService) ListSignatures(
|
||||
func (s *DocumentService) IsVersionSignedByUserEmail(
|
||||
ctx context.Context,
|
||||
documentVersionID gid.GID,
|
||||
userEmail string,
|
||||
userEmail mail.Addr,
|
||||
) (bool, error) {
|
||||
documentVersionSignature := &coredata.DocumentVersionSignature{}
|
||||
|
||||
@@ -1032,7 +1032,7 @@ func (s *DocumentService) BulkSoftDelete(
|
||||
func (s *DocumentService) RequestExport(
|
||||
ctx context.Context,
|
||||
documentIDs []gid.GID,
|
||||
recipientEmail string,
|
||||
recipientEmail mail.Addr,
|
||||
recipientName string,
|
||||
options ExportPDFOptions,
|
||||
) (*coredata.ExportJob, error) {
|
||||
@@ -1043,9 +1043,6 @@ func (s *DocumentService) RequestExport(
|
||||
if options.WatermarkEmail == nil {
|
||||
return nil, fmt.Errorf("watermark email is required when with watermark is true")
|
||||
}
|
||||
if _, err := mail.ParseAddress(*options.WatermarkEmail); err != nil {
|
||||
return nil, fmt.Errorf("invalid email address")
|
||||
}
|
||||
}
|
||||
|
||||
err := s.svc.pg.WithTx(ctx, func(conn pg.Conn) error {
|
||||
@@ -1149,7 +1146,7 @@ func (s *DocumentService) GetVersion(
|
||||
func (s *DocumentService) IsSigned(
|
||||
ctx context.Context,
|
||||
documentID gid.GID,
|
||||
userEmail string,
|
||||
userEmail mail.Addr,
|
||||
) (bool, error) {
|
||||
document := &coredata.Document{}
|
||||
|
||||
@@ -1438,7 +1435,7 @@ func (s *DocumentService) CancelSignatureRequest(
|
||||
|
||||
type ExportPDFOptions struct {
|
||||
WithWatermark bool
|
||||
WatermarkEmail *string
|
||||
WatermarkEmail *mail.Addr
|
||||
WithSignatures bool
|
||||
}
|
||||
|
||||
@@ -1695,9 +1692,6 @@ func exportDocumentPDF(
|
||||
if options.WatermarkEmail == nil {
|
||||
return nil, fmt.Errorf("watermark email is required with watermark enabled")
|
||||
}
|
||||
if _, err := mail.ParseAddress(*options.WatermarkEmail); err != nil {
|
||||
return nil, fmt.Errorf("invalid email address")
|
||||
}
|
||||
|
||||
watermarkedPDF, err := watermarkpdf.AddConfidentialWithTimestamp(pdfData, *options.WatermarkEmail)
|
||||
if err != nil {
|
||||
@@ -1770,7 +1764,7 @@ func (s *DocumentService) SendExportEmail(
|
||||
ctx context.Context,
|
||||
fileID gid.GID,
|
||||
recipientName string,
|
||||
recipientEmail string,
|
||||
recipientEmail mail.Addr,
|
||||
) error {
|
||||
return s.svc.pg.WithTx(
|
||||
ctx,
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/html2pdf"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"go.probo.inc/probo/pkg/slug"
|
||||
"go.probo.inc/probo/pkg/soagen"
|
||||
@@ -97,7 +98,7 @@ func (ufr *UpdateFrameworkRequest) Validate() error {
|
||||
func (s FrameworkService) RequestExport(
|
||||
ctx context.Context,
|
||||
frameworkID gid.GID,
|
||||
recipientEmail string,
|
||||
recipientEmail mail.Addr,
|
||||
recipientName string,
|
||||
) (error, *coredata.ExportJob) {
|
||||
var exportJobID gid.GID
|
||||
@@ -725,7 +726,7 @@ func (s FrameworkService) SendExportEmail(
|
||||
ctx context.Context,
|
||||
fileID gid.GID,
|
||||
recipientName string,
|
||||
recipientEmail string,
|
||||
recipientEmail mail.Addr,
|
||||
) error {
|
||||
return s.svc.pg.WithTx(
|
||||
ctx,
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"go.probo.inc/probo/pkg/validator"
|
||||
)
|
||||
@@ -34,8 +35,8 @@ type (
|
||||
CreatePeopleRequest struct {
|
||||
OrganizationID gid.GID
|
||||
FullName string
|
||||
PrimaryEmailAddress string
|
||||
AdditionalEmailAddresses []string
|
||||
PrimaryEmailAddress mail.Addr
|
||||
AdditionalEmailAddresses []mail.Addr
|
||||
Kind coredata.PeopleKind
|
||||
Position *string
|
||||
ContractStartDate *time.Time
|
||||
@@ -46,8 +47,8 @@ type (
|
||||
ID gid.GID
|
||||
Kind *coredata.PeopleKind
|
||||
FullName *string
|
||||
PrimaryEmailAddress *string
|
||||
AdditionalEmailAddresses *[]string
|
||||
PrimaryEmailAddress *mail.Addr
|
||||
AdditionalEmailAddresses *[]mail.Addr
|
||||
Position **string
|
||||
ContractStartDate **time.Time
|
||||
ContractEndDate **time.Time
|
||||
@@ -59,9 +60,9 @@ func (cpr *CreatePeopleRequest) Validate() error {
|
||||
|
||||
v.Check(cpr.OrganizationID, "organization_id", validator.Required(), validator.GID(coredata.OrganizationEntityType))
|
||||
v.Check(cpr.FullName, "full_name", validator.SafeTextNoNewLine(NameMaxLength))
|
||||
v.Check(cpr.PrimaryEmailAddress, "primary_email_address", validator.Required(), validator.NotEmpty(), validator.Email())
|
||||
v.Check(cpr.PrimaryEmailAddress, "primary_email_address", validator.Required(), validator.NotEmpty())
|
||||
v.CheckEach(cpr.AdditionalEmailAddresses, "additional_email_addresses", func(index int, item any) {
|
||||
v.Check(item, fmt.Sprintf("additional_email_addresses[%d]", index), validator.Required(), validator.NotEmpty(), validator.Email())
|
||||
v.Check(item, fmt.Sprintf("additional_email_addresses[%d]", index), validator.Required(), validator.NotEmpty())
|
||||
})
|
||||
v.Check(cpr.Kind, "kind", validator.Required(), validator.OneOfSlice(coredata.PeopleKinds()))
|
||||
v.Check(cpr.Position, "position", validator.SafeText(TitleMaxLength))
|
||||
@@ -77,9 +78,9 @@ func (upr *UpdatePeopleRequest) Validate() error {
|
||||
v.Check(upr.ID, "id", validator.Required(), validator.GID(coredata.PeopleEntityType))
|
||||
v.Check(upr.Kind, "kind", validator.OneOfSlice(coredata.PeopleKinds()))
|
||||
v.Check(upr.FullName, "full_name", validator.SafeTextNoNewLine(NameMaxLength))
|
||||
v.Check(upr.PrimaryEmailAddress, "primary_email_address", validator.NotEmpty(), validator.Email())
|
||||
v.Check(upr.PrimaryEmailAddress, "primary_email_address", validator.NotEmpty())
|
||||
v.CheckEach(upr.AdditionalEmailAddresses, "additional_email_addresses", func(index int, item any) {
|
||||
v.Check(item, fmt.Sprintf("additional_email_addresses[%d]", index), validator.Required(), validator.NotEmpty(), validator.Email())
|
||||
v.Check(item, fmt.Sprintf("additional_email_addresses[%d]", index), validator.Required(), validator.NotEmpty())
|
||||
})
|
||||
v.Check(upr.Position, "position", validator.SafeText(TitleMaxLength))
|
||||
v.Check(upr.ContractStartDate, "contract_start_date", validator.Before(upr.ContractEndDate))
|
||||
@@ -110,7 +111,7 @@ func (s PeopleService) Get(
|
||||
|
||||
func (s PeopleService) GetByEmailAndOrganizationID(
|
||||
ctx context.Context,
|
||||
primaryEmailAddress string,
|
||||
primaryEmailAddress mail.Addr,
|
||||
organizationID gid.GID,
|
||||
) (*coredata.People, error) {
|
||||
people := &coredata.People{}
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
"go.probo.inc/probo/pkg/crypto/cipher"
|
||||
"go.probo.inc/probo/pkg/filemanager"
|
||||
"go.probo.inc/probo/pkg/filevalidation"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/html2pdf"
|
||||
"go.probo.inc/probo/pkg/slack"
|
||||
@@ -44,7 +45,7 @@ const (
|
||||
|
||||
type ExportService interface {
|
||||
BuildAndUploadExport(ctx context.Context, exportJobID gid.GID) (*coredata.ExportJob, error)
|
||||
SendExportEmail(ctx context.Context, fileID gid.GID, recipientName, recipientEmail string) error
|
||||
SendExportEmail(ctx context.Context, fileID gid.GID, recipientName string, recipientEmail mail.Addr) error
|
||||
}
|
||||
|
||||
type (
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"go.probo.inc/probo/packages/emails"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"go.probo.inc/probo/pkg/statelesstoken"
|
||||
"go.probo.inc/probo/pkg/validator"
|
||||
@@ -36,7 +37,7 @@ type (
|
||||
|
||||
CreateTrustCenterAccessRequest struct {
|
||||
TrustCenterID gid.GID
|
||||
Email string
|
||||
Email mail.Addr
|
||||
Name string
|
||||
}
|
||||
|
||||
@@ -55,8 +56,8 @@ type (
|
||||
}
|
||||
|
||||
TrustCenterAccessData struct {
|
||||
TrustCenterID gid.GID `json:"trust_center_id"`
|
||||
Email string `json:"email"`
|
||||
TrustCenterID gid.GID `json:"trust_center_id"`
|
||||
Email mail.Addr `json:"email"`
|
||||
}
|
||||
)
|
||||
|
||||
@@ -64,7 +65,7 @@ func (ctcar *CreateTrustCenterAccessRequest) Validate() error {
|
||||
v := validator.New()
|
||||
|
||||
v.Check(ctcar.TrustCenterID, "trust_center_id", validator.Required(), validator.GID(coredata.TrustCenterEntityType))
|
||||
v.Check(ctcar.Email, "email", validator.Required(), validator.Email())
|
||||
v.Check(ctcar.Email, "email", validator.Required(), validator.NotEmpty())
|
||||
v.Check(ctcar.Name, "name", validator.SafeTextNoNewLine(TitleMaxLength))
|
||||
|
||||
return v.Error()
|
||||
@@ -469,7 +470,7 @@ func (s TrustCenterAccessService) sendTrustCenterAccessEmail(
|
||||
ctx context.Context,
|
||||
tx pg.Conn,
|
||||
name string,
|
||||
email string,
|
||||
email mail.Addr,
|
||||
companyName string,
|
||||
accessURL string,
|
||||
) error {
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"go.probo.inc/probo/pkg/validator"
|
||||
)
|
||||
@@ -34,7 +35,7 @@ type (
|
||||
CreateVendorContactRequest struct {
|
||||
VendorID gid.GID
|
||||
FullName *string
|
||||
Email *string
|
||||
Email *mail.Addr
|
||||
Phone *string
|
||||
Role *string
|
||||
}
|
||||
@@ -42,7 +43,7 @@ type (
|
||||
UpdateVendorContactRequest struct {
|
||||
ID gid.GID
|
||||
FullName **string
|
||||
Email **string
|
||||
Email **mail.Addr
|
||||
Phone **string
|
||||
Role **string
|
||||
}
|
||||
@@ -53,7 +54,6 @@ func (cvcr *CreateVendorContactRequest) Validate() error {
|
||||
|
||||
v.Check(cvcr.VendorID, "vendor_id", validator.Required(), validator.GID(coredata.VendorEntityType))
|
||||
v.Check(cvcr.FullName, "fullName", validator.SafeTextNoNewLine(TitleMaxLength))
|
||||
v.Check(cvcr.Email, "email", validator.Email())
|
||||
v.Check(cvcr.Phone, "phone", validator.SafeText(NameMaxLength))
|
||||
v.Check(cvcr.Role, "role", validator.SafeText(TitleMaxLength))
|
||||
|
||||
@@ -65,7 +65,6 @@ func (uvcr *UpdateVendorContactRequest) Validate() error {
|
||||
|
||||
v.Check(uvcr.ID, "id", validator.Required(), validator.GID(coredata.VendorContactEntityType))
|
||||
v.Check(uvcr.FullName, "fullName", validator.SafeTextNoNewLine(TitleMaxLength))
|
||||
v.Check(uvcr.Email, "email", validator.Email())
|
||||
v.Check(uvcr.Phone, "phone", validator.SafeText(NameMaxLength))
|
||||
v.Check(uvcr.Role, "role", validator.SafeText(TitleMaxLength))
|
||||
|
||||
|
||||
@@ -37,3 +37,6 @@ models:
|
||||
BigInt:
|
||||
model:
|
||||
- "go.probo.inc/probo/pkg/server/gqlutils/types/bigint.BigIntScalar"
|
||||
EmailAddr:
|
||||
model:
|
||||
- "go.probo.inc/probo/pkg/server/gqlutils/types/mail.AddrScalar"
|
||||
|
||||
@@ -19,6 +19,7 @@ scalar Datetime
|
||||
scalar Upload
|
||||
scalar Duration
|
||||
scalar BigInt
|
||||
scalar EmailAddr
|
||||
|
||||
# Interfaces
|
||||
interface Node {
|
||||
@@ -99,7 +100,8 @@ enum MembershipRole
|
||||
EMPLOYEE
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleEmployee")
|
||||
VIEWER @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleViewer")
|
||||
AUDITOR @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleAuditor")
|
||||
AUDITOR
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleAuditor")
|
||||
}
|
||||
|
||||
enum APIRole @goModel(model: "go.probo.inc/probo/pkg/coredata.APIRole") {
|
||||
@@ -1687,7 +1689,7 @@ type Organization implements Node {
|
||||
type User implements Node {
|
||||
id: ID!
|
||||
fullName: String!
|
||||
email: String!
|
||||
email: EmailAddr!
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
}
|
||||
@@ -1698,7 +1700,7 @@ type Membership implements Node {
|
||||
organizationID: ID!
|
||||
role: MembershipRole!
|
||||
fullName: String!
|
||||
emailAddress: String!
|
||||
emailAddress: EmailAddr!
|
||||
authMethod: UserAuthMethod! @goField(forceResolver: true)
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
@@ -1706,7 +1708,7 @@ type Membership implements Node {
|
||||
|
||||
type Invitation implements Node {
|
||||
id: ID!
|
||||
email: String!
|
||||
email: EmailAddr!
|
||||
fullName: String!
|
||||
role: MembershipRole!
|
||||
status: InvitationStatus!
|
||||
@@ -1737,8 +1739,8 @@ type SlackConnectionEdge {
|
||||
type People implements Node {
|
||||
id: ID!
|
||||
fullName: String!
|
||||
primaryEmailAddress: String!
|
||||
additionalEmailAddresses: [String!]!
|
||||
primaryEmailAddress: EmailAddr!
|
||||
additionalEmailAddresses: [EmailAddr!]!
|
||||
kind: PeopleKind!
|
||||
position: String
|
||||
contractStartDate: Datetime
|
||||
@@ -1841,7 +1843,7 @@ type VendorContact implements Node {
|
||||
id: ID!
|
||||
vendor: Vendor! @goField(forceResolver: true)
|
||||
fullName: String
|
||||
email: String
|
||||
email: EmailAddr
|
||||
phone: String
|
||||
role: String
|
||||
createdAt: Datetime!
|
||||
@@ -2342,7 +2344,7 @@ type TrustCenterEdge {
|
||||
|
||||
type TrustCenterAccess implements Node {
|
||||
id: ID!
|
||||
email: String!
|
||||
email: EmailAddr!
|
||||
name: String!
|
||||
active: Boolean!
|
||||
hasAcceptedNonDisclosureAgreement: Boolean!
|
||||
@@ -3185,7 +3187,7 @@ input DeleteTrustCenterNDAInput {
|
||||
|
||||
input CreateTrustCenterAccessInput {
|
||||
trustCenterId: ID!
|
||||
email: String!
|
||||
email: EmailAddr!
|
||||
name: String!
|
||||
active: Boolean!
|
||||
}
|
||||
@@ -3306,7 +3308,7 @@ input DeleteVendorInput {
|
||||
input CreateVendorContactInput {
|
||||
vendorId: ID!
|
||||
fullName: String
|
||||
email: String
|
||||
email: EmailAddr
|
||||
phone: String
|
||||
role: String
|
||||
}
|
||||
@@ -3314,7 +3316,7 @@ input CreateVendorContactInput {
|
||||
input UpdateVendorContactInput {
|
||||
id: ID!
|
||||
fullName: String @goField(omittable: true)
|
||||
email: String @goField(omittable: true)
|
||||
email: EmailAddr @goField(omittable: true)
|
||||
phone: String @goField(omittable: true)
|
||||
role: String @goField(omittable: true)
|
||||
}
|
||||
@@ -3346,8 +3348,8 @@ input DeleteVendorServiceInput {
|
||||
input CreatePeopleInput {
|
||||
organizationId: ID!
|
||||
fullName: String!
|
||||
primaryEmailAddress: String!
|
||||
additionalEmailAddresses: [String!]
|
||||
primaryEmailAddress: EmailAddr!
|
||||
additionalEmailAddresses: [EmailAddr!]
|
||||
kind: PeopleKind!
|
||||
position: String
|
||||
contractStartDate: Datetime
|
||||
@@ -3357,8 +3359,8 @@ input CreatePeopleInput {
|
||||
input UpdatePeopleInput {
|
||||
id: ID!
|
||||
fullName: String
|
||||
primaryEmailAddress: String
|
||||
additionalEmailAddresses: [String!]
|
||||
primaryEmailAddress: EmailAddr
|
||||
additionalEmailAddresses: [EmailAddr!]
|
||||
kind: PeopleKind
|
||||
position: String @goField(omittable: true)
|
||||
contractStartDate: Datetime @goField(omittable: true)
|
||||
@@ -3646,7 +3648,7 @@ input UpdateDocumentInput {
|
||||
input ExportDocumentVersionPDFInput {
|
||||
documentVersionId: ID!
|
||||
withWatermark: Boolean!
|
||||
watermarkEmail: String
|
||||
watermarkEmail: EmailAddr
|
||||
withSignatures: Boolean!
|
||||
}
|
||||
|
||||
@@ -3684,7 +3686,7 @@ input ConfirmEmailInput {
|
||||
|
||||
input InviteUserInput {
|
||||
organizationId: ID!
|
||||
email: String!
|
||||
email: EmailAddr!
|
||||
fullName: String!
|
||||
role: MembershipRole!
|
||||
createPeople: Boolean!
|
||||
@@ -4459,7 +4461,7 @@ input BulkDeleteDocumentsInput {
|
||||
input BulkExportDocumentsInput {
|
||||
documentIds: [ID!]!
|
||||
withWatermark: Boolean!
|
||||
watermarkEmail: String
|
||||
watermarkEmail: EmailAddr
|
||||
withSignatures: Boolean!
|
||||
}
|
||||
|
||||
|
||||
@@ -18,11 +18,13 @@ import (
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"go.probo.inc/probo/pkg/server/api/console/v1/types"
|
||||
"go.probo.inc/probo/pkg/server/gqlutils/types/bigint"
|
||||
"go.probo.inc/probo/pkg/server/gqlutils/types/cursor"
|
||||
gid1 "go.probo.inc/probo/pkg/server/gqlutils/types/gid"
|
||||
mail1 "go.probo.inc/probo/pkg/server/gqlutils/types/mail"
|
||||
)
|
||||
|
||||
// region ************************** generated!.gotpl **************************
|
||||
@@ -9573,6 +9575,7 @@ scalar Datetime
|
||||
scalar Upload
|
||||
scalar Duration
|
||||
scalar BigInt
|
||||
scalar EmailAddr
|
||||
|
||||
# Interfaces
|
||||
interface Node {
|
||||
@@ -9653,7 +9656,8 @@ enum MembershipRole
|
||||
EMPLOYEE
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleEmployee")
|
||||
VIEWER @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleViewer")
|
||||
AUDITOR @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleAuditor")
|
||||
AUDITOR
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleAuditor")
|
||||
}
|
||||
|
||||
enum APIRole @goModel(model: "go.probo.inc/probo/pkg/coredata.APIRole") {
|
||||
@@ -11241,7 +11245,7 @@ type Organization implements Node {
|
||||
type User implements Node {
|
||||
id: ID!
|
||||
fullName: String!
|
||||
email: String!
|
||||
email: EmailAddr!
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
}
|
||||
@@ -11252,7 +11256,7 @@ type Membership implements Node {
|
||||
organizationID: ID!
|
||||
role: MembershipRole!
|
||||
fullName: String!
|
||||
emailAddress: String!
|
||||
emailAddress: EmailAddr!
|
||||
authMethod: UserAuthMethod! @goField(forceResolver: true)
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
@@ -11260,7 +11264,7 @@ type Membership implements Node {
|
||||
|
||||
type Invitation implements Node {
|
||||
id: ID!
|
||||
email: String!
|
||||
email: EmailAddr!
|
||||
fullName: String!
|
||||
role: MembershipRole!
|
||||
status: InvitationStatus!
|
||||
@@ -11291,8 +11295,8 @@ type SlackConnectionEdge {
|
||||
type People implements Node {
|
||||
id: ID!
|
||||
fullName: String!
|
||||
primaryEmailAddress: String!
|
||||
additionalEmailAddresses: [String!]!
|
||||
primaryEmailAddress: EmailAddr!
|
||||
additionalEmailAddresses: [EmailAddr!]!
|
||||
kind: PeopleKind!
|
||||
position: String
|
||||
contractStartDate: Datetime
|
||||
@@ -11395,7 +11399,7 @@ type VendorContact implements Node {
|
||||
id: ID!
|
||||
vendor: Vendor! @goField(forceResolver: true)
|
||||
fullName: String
|
||||
email: String
|
||||
email: EmailAddr
|
||||
phone: String
|
||||
role: String
|
||||
createdAt: Datetime!
|
||||
@@ -11896,7 +11900,7 @@ type TrustCenterEdge {
|
||||
|
||||
type TrustCenterAccess implements Node {
|
||||
id: ID!
|
||||
email: String!
|
||||
email: EmailAddr!
|
||||
name: String!
|
||||
active: Boolean!
|
||||
hasAcceptedNonDisclosureAgreement: Boolean!
|
||||
@@ -12739,7 +12743,7 @@ input DeleteTrustCenterNDAInput {
|
||||
|
||||
input CreateTrustCenterAccessInput {
|
||||
trustCenterId: ID!
|
||||
email: String!
|
||||
email: EmailAddr!
|
||||
name: String!
|
||||
active: Boolean!
|
||||
}
|
||||
@@ -12860,7 +12864,7 @@ input DeleteVendorInput {
|
||||
input CreateVendorContactInput {
|
||||
vendorId: ID!
|
||||
fullName: String
|
||||
email: String
|
||||
email: EmailAddr
|
||||
phone: String
|
||||
role: String
|
||||
}
|
||||
@@ -12868,7 +12872,7 @@ input CreateVendorContactInput {
|
||||
input UpdateVendorContactInput {
|
||||
id: ID!
|
||||
fullName: String @goField(omittable: true)
|
||||
email: String @goField(omittable: true)
|
||||
email: EmailAddr @goField(omittable: true)
|
||||
phone: String @goField(omittable: true)
|
||||
role: String @goField(omittable: true)
|
||||
}
|
||||
@@ -12900,8 +12904,8 @@ input DeleteVendorServiceInput {
|
||||
input CreatePeopleInput {
|
||||
organizationId: ID!
|
||||
fullName: String!
|
||||
primaryEmailAddress: String!
|
||||
additionalEmailAddresses: [String!]
|
||||
primaryEmailAddress: EmailAddr!
|
||||
additionalEmailAddresses: [EmailAddr!]
|
||||
kind: PeopleKind!
|
||||
position: String
|
||||
contractStartDate: Datetime
|
||||
@@ -12911,8 +12915,8 @@ input CreatePeopleInput {
|
||||
input UpdatePeopleInput {
|
||||
id: ID!
|
||||
fullName: String
|
||||
primaryEmailAddress: String
|
||||
additionalEmailAddresses: [String!]
|
||||
primaryEmailAddress: EmailAddr
|
||||
additionalEmailAddresses: [EmailAddr!]
|
||||
kind: PeopleKind
|
||||
position: String @goField(omittable: true)
|
||||
contractStartDate: Datetime @goField(omittable: true)
|
||||
@@ -13200,7 +13204,7 @@ input UpdateDocumentInput {
|
||||
input ExportDocumentVersionPDFInput {
|
||||
documentVersionId: ID!
|
||||
withWatermark: Boolean!
|
||||
watermarkEmail: String
|
||||
watermarkEmail: EmailAddr
|
||||
withSignatures: Boolean!
|
||||
}
|
||||
|
||||
@@ -13238,7 +13242,7 @@ input ConfirmEmailInput {
|
||||
|
||||
input InviteUserInput {
|
||||
organizationId: ID!
|
||||
email: String!
|
||||
email: EmailAddr!
|
||||
fullName: String!
|
||||
role: MembershipRole!
|
||||
createPeople: Boolean!
|
||||
@@ -14013,7 +14017,7 @@ input BulkDeleteDocumentsInput {
|
||||
input BulkExportDocumentsInput {
|
||||
documentIds: [ID!]!
|
||||
withWatermark: Boolean!
|
||||
watermarkEmail: String
|
||||
watermarkEmail: EmailAddr
|
||||
withSignatures: Boolean!
|
||||
}
|
||||
|
||||
@@ -28689,7 +28693,7 @@ func (ec *executionContext) _Invitation_email(ctx context.Context, field graphql
|
||||
return obj.Email, nil
|
||||
},
|
||||
nil,
|
||||
ec.marshalNString2string,
|
||||
ec.marshalNEmailAddr2goᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
@@ -28702,7 +28706,7 @@ func (ec *executionContext) fieldContext_Invitation_email(_ context.Context, fie
|
||||
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 nil, errors.New("field of type EmailAddr does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
@@ -30443,7 +30447,7 @@ func (ec *executionContext) _Membership_emailAddress(ctx context.Context, field
|
||||
return obj.EmailAddress, nil
|
||||
},
|
||||
nil,
|
||||
ec.marshalNString2string,
|
||||
ec.marshalNEmailAddr2goᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
@@ -30456,7 +30460,7 @@ func (ec *executionContext) fieldContext_Membership_emailAddress(_ context.Conte
|
||||
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 nil, errors.New("field of type EmailAddr does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
@@ -40421,7 +40425,7 @@ func (ec *executionContext) _People_primaryEmailAddress(ctx context.Context, fie
|
||||
return obj.PrimaryEmailAddress, nil
|
||||
},
|
||||
nil,
|
||||
ec.marshalNString2string,
|
||||
ec.marshalNEmailAddr2goᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
@@ -40434,7 +40438,7 @@ func (ec *executionContext) fieldContext_People_primaryEmailAddress(_ context.Co
|
||||
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 nil, errors.New("field of type EmailAddr does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
@@ -40450,7 +40454,7 @@ func (ec *executionContext) _People_additionalEmailAddresses(ctx context.Context
|
||||
return obj.AdditionalEmailAddresses, nil
|
||||
},
|
||||
nil,
|
||||
ec.marshalNString2ᚕstringᚄ,
|
||||
ec.marshalNEmailAddr2ᚕᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddrᚄ,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
@@ -40463,7 +40467,7 @@ func (ec *executionContext) fieldContext_People_additionalEmailAddresses(_ conte
|
||||
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 nil, errors.New("field of type EmailAddr does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
@@ -46593,7 +46597,7 @@ func (ec *executionContext) _TrustCenterAccess_email(ctx context.Context, field
|
||||
return obj.Email, nil
|
||||
},
|
||||
nil,
|
||||
ec.marshalNString2string,
|
||||
ec.marshalNEmailAddr2goᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
@@ -46606,7 +46610,7 @@ func (ec *executionContext) fieldContext_TrustCenterAccess_email(_ context.Conte
|
||||
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 nil, errors.New("field of type EmailAddr does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
@@ -50525,7 +50529,7 @@ func (ec *executionContext) _User_email(ctx context.Context, field graphql.Colle
|
||||
return obj.Email, nil
|
||||
},
|
||||
nil,
|
||||
ec.marshalNString2string,
|
||||
ec.marshalNEmailAddr2goᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
@@ -50538,7 +50542,7 @@ func (ec *executionContext) fieldContext_User_email(_ context.Context, field gra
|
||||
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 nil, errors.New("field of type EmailAddr does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
@@ -52953,7 +52957,7 @@ func (ec *executionContext) _VendorContact_email(ctx context.Context, field grap
|
||||
return obj.Email, nil
|
||||
},
|
||||
nil,
|
||||
ec.marshalOString2ᚖstring,
|
||||
ec.marshalOEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr,
|
||||
true,
|
||||
false,
|
||||
)
|
||||
@@ -52966,7 +52970,7 @@ func (ec *executionContext) fieldContext_VendorContact_email(_ context.Context,
|
||||
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 nil, errors.New("field of type EmailAddr does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
@@ -56539,7 +56543,7 @@ func (ec *executionContext) unmarshalInputBulkExportDocumentsInput(ctx context.C
|
||||
it.WithWatermark = data
|
||||
case "watermarkEmail":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("watermarkEmail"))
|
||||
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
data, err := ec.unmarshalOEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -57848,14 +57852,14 @@ func (ec *executionContext) unmarshalInputCreatePeopleInput(ctx context.Context,
|
||||
it.FullName = data
|
||||
case "primaryEmailAddress":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("primaryEmailAddress"))
|
||||
data, err := ec.unmarshalNString2string(ctx, v)
|
||||
data, err := ec.unmarshalNEmailAddr2goᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.PrimaryEmailAddress = data
|
||||
case "additionalEmailAddresses":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("additionalEmailAddresses"))
|
||||
data, err := ec.unmarshalOString2ᚕstringᚄ(ctx, v)
|
||||
data, err := ec.unmarshalOEmailAddr2ᚕᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddrᚄ(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -58497,7 +58501,7 @@ func (ec *executionContext) unmarshalInputCreateTrustCenterAccessInput(ctx conte
|
||||
it.TrustCenterID = data
|
||||
case "email":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email"))
|
||||
data, err := ec.unmarshalNString2string(ctx, v)
|
||||
data, err := ec.unmarshalNEmailAddr2goᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -58662,7 +58666,7 @@ func (ec *executionContext) unmarshalInputCreateVendorContactInput(ctx context.C
|
||||
it.FullName = data
|
||||
case "email":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email"))
|
||||
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
data, err := ec.unmarshalOEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -60475,7 +60479,7 @@ func (ec *executionContext) unmarshalInputExportDocumentVersionPDFInput(ctx cont
|
||||
it.WithWatermark = data
|
||||
case "watermarkEmail":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("watermarkEmail"))
|
||||
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
data, err := ec.unmarshalOEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -60896,7 +60900,7 @@ func (ec *executionContext) unmarshalInputInviteUserInput(ctx context.Context, o
|
||||
it.OrganizationID = data
|
||||
case "email":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email"))
|
||||
data, err := ec.unmarshalNString2string(ctx, v)
|
||||
data, err := ec.unmarshalNEmailAddr2goᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -62825,14 +62829,14 @@ func (ec *executionContext) unmarshalInputUpdatePeopleInput(ctx context.Context,
|
||||
it.FullName = data
|
||||
case "primaryEmailAddress":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("primaryEmailAddress"))
|
||||
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
data, err := ec.unmarshalOEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.PrimaryEmailAddress = data
|
||||
case "additionalEmailAddresses":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("additionalEmailAddresses"))
|
||||
data, err := ec.unmarshalOString2ᚕstringᚄ(ctx, v)
|
||||
data, err := ec.unmarshalOEmailAddr2ᚕᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddrᚄ(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -63564,7 +63568,7 @@ func (ec *executionContext) unmarshalInputUpdateVendorContactInput(ctx context.C
|
||||
it.FullName = graphql.OmittableOf(data)
|
||||
case "email":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email"))
|
||||
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
data, err := ec.unmarshalOEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -86860,6 +86864,74 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func (ec *executionContext) unmarshalNEmailAddr2goᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx context.Context, v any) (mail.Addr, error) {
|
||||
res, err := mail1.UnmarshalAddrScalar(v)
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNEmailAddr2goᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx context.Context, sel ast.SelectionSet, v mail.Addr) graphql.Marshaler {
|
||||
_ = sel
|
||||
res := mail1.MarshalAddrScalar(v)
|
||||
if res == graphql.Null {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNEmailAddr2ᚕᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddrᚄ(ctx context.Context, v any) ([]*mail.Addr, error) {
|
||||
var vSlice []any
|
||||
vSlice = graphql.CoerceList(v)
|
||||
var err error
|
||||
res := make([]*mail.Addr, len(vSlice))
|
||||
for i := range vSlice {
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i))
|
||||
res[i], err = ec.unmarshalNEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, vSlice[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNEmailAddr2ᚕᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddrᚄ(ctx context.Context, sel ast.SelectionSet, v []*mail.Addr) graphql.Marshaler {
|
||||
ret := make(graphql.Array, len(v))
|
||||
for i := range v {
|
||||
ret[i] = ec.marshalNEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, sel, v[i])
|
||||
}
|
||||
|
||||
for _, e := range ret {
|
||||
if e == graphql.Null {
|
||||
return graphql.Null
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx context.Context, v any) (*mail.Addr, error) {
|
||||
res, err := mail1.UnmarshalAddrScalar(v)
|
||||
return &res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx context.Context, sel ast.SelectionSet, v *mail.Addr) graphql.Marshaler {
|
||||
if v == nil {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
_ = sel
|
||||
res := mail1.MarshalAddrScalar(*v)
|
||||
if res == graphql.Null {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNEnableSAMLInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐEnableSAMLInput(ctx context.Context, v any) (types.EnableSAMLInput, error) {
|
||||
res, err := ec.unmarshalInputEnableSAMLInput(ctx, v)
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
@@ -92570,6 +92642,60 @@ func (ec *executionContext) marshalODuration2ᚖtimeᚐDuration(ctx context.Cont
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalOEmailAddr2ᚕᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddrᚄ(ctx context.Context, v any) ([]*mail.Addr, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
var vSlice []any
|
||||
vSlice = graphql.CoerceList(v)
|
||||
var err error
|
||||
res := make([]*mail.Addr, len(vSlice))
|
||||
for i := range vSlice {
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i))
|
||||
res[i], err = ec.unmarshalNEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, vSlice[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOEmailAddr2ᚕᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddrᚄ(ctx context.Context, sel ast.SelectionSet, v []*mail.Addr) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
ret := make(graphql.Array, len(v))
|
||||
for i := range v {
|
||||
ret[i] = ec.marshalNEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, sel, v[i])
|
||||
}
|
||||
|
||||
for _, e := range ret {
|
||||
if e == graphql.Null {
|
||||
return graphql.Null
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalOEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx context.Context, v any) (*mail.Addr, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
res, err := mail1.UnmarshalAddrScalar(v)
|
||||
return &res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx context.Context, sel ast.SelectionSet, v *mail.Addr) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
_ = sel
|
||||
_ = ctx
|
||||
res := mail1.MarshalAddrScalar(*v)
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalOEvidenceOrder2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐEvidenceOrderBy(ctx context.Context, v any) (*types.EvidenceOrderBy, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
|
||||
@@ -17,6 +17,7 @@ package types
|
||||
import (
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
)
|
||||
|
||||
@@ -64,11 +65,16 @@ func NewPeopleEdge(p *coredata.People, orderBy coredata.PeopleOrderField) *Peopl
|
||||
}
|
||||
|
||||
func NewPeople(p *coredata.People) *People {
|
||||
var emailAddresses []*mail.Addr
|
||||
for _, emailAddress := range p.AdditionalEmailAddresses {
|
||||
emailAddresses = append(emailAddresses, &emailAddress)
|
||||
}
|
||||
|
||||
return &People{
|
||||
ID: p.ID,
|
||||
FullName: p.FullName,
|
||||
PrimaryEmailAddress: p.PrimaryEmailAddress,
|
||||
AdditionalEmailAddresses: p.AdditionalEmailAddresses,
|
||||
AdditionalEmailAddresses: emailAddresses,
|
||||
Kind: p.Kind,
|
||||
Position: p.Position,
|
||||
ContractStartDate: p.ContractStartDate,
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
)
|
||||
|
||||
@@ -105,10 +106,10 @@ type BulkDeleteDocumentsPayload struct {
|
||||
}
|
||||
|
||||
type BulkExportDocumentsInput struct {
|
||||
DocumentIds []gid.GID `json:"documentIds"`
|
||||
WithWatermark bool `json:"withWatermark"`
|
||||
WatermarkEmail *string `json:"watermarkEmail,omitempty"`
|
||||
WithSignatures bool `json:"withSignatures"`
|
||||
DocumentIds []gid.GID `json:"documentIds"`
|
||||
WithWatermark bool `json:"withWatermark"`
|
||||
WatermarkEmail *mail.Addr `json:"watermarkEmail,omitempty"`
|
||||
WithSignatures bool `json:"withSignatures"`
|
||||
}
|
||||
|
||||
type BulkExportDocumentsPayload struct {
|
||||
@@ -419,8 +420,8 @@ type CreateOrganizationPayload struct {
|
||||
type CreatePeopleInput struct {
|
||||
OrganizationID gid.GID `json:"organizationId"`
|
||||
FullName string `json:"fullName"`
|
||||
PrimaryEmailAddress string `json:"primaryEmailAddress"`
|
||||
AdditionalEmailAddresses []string `json:"additionalEmailAddresses,omitempty"`
|
||||
PrimaryEmailAddress mail.Addr `json:"primaryEmailAddress"`
|
||||
AdditionalEmailAddresses []*mail.Addr `json:"additionalEmailAddresses,omitempty"`
|
||||
Kind coredata.PeopleKind `json:"kind"`
|
||||
Position *string `json:"position,omitempty"`
|
||||
ContractStartDate *time.Time `json:"contractStartDate,omitempty"`
|
||||
@@ -551,10 +552,10 @@ type CreateTaskPayload struct {
|
||||
}
|
||||
|
||||
type CreateTrustCenterAccessInput struct {
|
||||
TrustCenterID gid.GID `json:"trustCenterId"`
|
||||
Email string `json:"email"`
|
||||
Name string `json:"name"`
|
||||
Active bool `json:"active"`
|
||||
TrustCenterID gid.GID `json:"trustCenterId"`
|
||||
Email mail.Addr `json:"email"`
|
||||
Name string `json:"name"`
|
||||
Active bool `json:"active"`
|
||||
}
|
||||
|
||||
type CreateTrustCenterAccessPayload struct {
|
||||
@@ -586,11 +587,11 @@ type CreateTrustCenterReferencePayload struct {
|
||||
}
|
||||
|
||||
type CreateVendorContactInput struct {
|
||||
VendorID gid.GID `json:"vendorId"`
|
||||
FullName *string `json:"fullName,omitempty"`
|
||||
Email *string `json:"email,omitempty"`
|
||||
Phone *string `json:"phone,omitempty"`
|
||||
Role *string `json:"role,omitempty"`
|
||||
VendorID gid.GID `json:"vendorId"`
|
||||
FullName *string `json:"fullName,omitempty"`
|
||||
Email *mail.Addr `json:"email,omitempty"`
|
||||
Phone *string `json:"phone,omitempty"`
|
||||
Role *string `json:"role,omitempty"`
|
||||
}
|
||||
|
||||
type CreateVendorContactPayload struct {
|
||||
@@ -1135,10 +1136,10 @@ type EvidenceEdge struct {
|
||||
}
|
||||
|
||||
type ExportDocumentVersionPDFInput struct {
|
||||
DocumentVersionID gid.GID `json:"documentVersionId"`
|
||||
WithWatermark bool `json:"withWatermark"`
|
||||
WatermarkEmail *string `json:"watermarkEmail,omitempty"`
|
||||
WithSignatures bool `json:"withSignatures"`
|
||||
DocumentVersionID gid.GID `json:"documentVersionId"`
|
||||
WithWatermark bool `json:"withWatermark"`
|
||||
WatermarkEmail *mail.Addr `json:"watermarkEmail,omitempty"`
|
||||
WithSignatures bool `json:"withSignatures"`
|
||||
}
|
||||
|
||||
type ExportDocumentVersionPDFPayload struct {
|
||||
@@ -1254,7 +1255,7 @@ type InitiateDomainVerificationPayload struct {
|
||||
|
||||
type Invitation struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Email string `json:"email"`
|
||||
Email mail.Addr `json:"email"`
|
||||
FullName string `json:"fullName"`
|
||||
Role coredata.MembershipRole `json:"role"`
|
||||
Status coredata.InvitationStatus `json:"status"`
|
||||
@@ -1283,7 +1284,7 @@ type InvitationOrder struct {
|
||||
|
||||
type InviteUserInput struct {
|
||||
OrganizationID gid.GID `json:"organizationId"`
|
||||
Email string `json:"email"`
|
||||
Email mail.Addr `json:"email"`
|
||||
FullName string `json:"fullName"`
|
||||
Role coredata.MembershipRole `json:"role"`
|
||||
CreatePeople bool `json:"createPeople"`
|
||||
@@ -1345,7 +1346,7 @@ type Membership struct {
|
||||
OrganizationID gid.GID `json:"organizationID"`
|
||||
Role coredata.MembershipRole `json:"role"`
|
||||
FullName string `json:"fullName"`
|
||||
EmailAddress string `json:"emailAddress"`
|
||||
EmailAddress mail.Addr `json:"emailAddress"`
|
||||
AuthMethod coredata.UserAuthMethod `json:"authMethod"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
@@ -1493,8 +1494,8 @@ type PageInfo struct {
|
||||
type People struct {
|
||||
ID gid.GID `json:"id"`
|
||||
FullName string `json:"fullName"`
|
||||
PrimaryEmailAddress string `json:"primaryEmailAddress"`
|
||||
AdditionalEmailAddresses []string `json:"additionalEmailAddresses"`
|
||||
PrimaryEmailAddress mail.Addr `json:"primaryEmailAddress"`
|
||||
AdditionalEmailAddresses []*mail.Addr `json:"additionalEmailAddresses"`
|
||||
Kind coredata.PeopleKind `json:"kind"`
|
||||
Position *string `json:"position,omitempty"`
|
||||
ContractStartDate *time.Time `json:"contractStartDate,omitempty"`
|
||||
@@ -1772,7 +1773,7 @@ func (this TrustCenter) GetID() gid.GID { return this.ID }
|
||||
|
||||
type TrustCenterAccess struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Email string `json:"email"`
|
||||
Email mail.Addr `json:"email"`
|
||||
Name string `json:"name"`
|
||||
Active bool `json:"active"`
|
||||
HasAcceptedNonDisclosureAgreement bool `json:"hasAcceptedNonDisclosureAgreement"`
|
||||
@@ -2056,8 +2057,8 @@ type UpdateOrganizationPayload struct {
|
||||
type UpdatePeopleInput struct {
|
||||
ID gid.GID `json:"id"`
|
||||
FullName *string `json:"fullName,omitempty"`
|
||||
PrimaryEmailAddress *string `json:"primaryEmailAddress,omitempty"`
|
||||
AdditionalEmailAddresses []string `json:"additionalEmailAddresses,omitempty"`
|
||||
PrimaryEmailAddress *mail.Addr `json:"primaryEmailAddress,omitempty"`
|
||||
AdditionalEmailAddresses []*mail.Addr `json:"additionalEmailAddresses,omitempty"`
|
||||
Kind *coredata.PeopleKind `json:"kind,omitempty"`
|
||||
Position graphql.Omittable[*string] `json:"position,omitempty"`
|
||||
ContractStartDate graphql.Omittable[*time.Time] `json:"contractStartDate,omitempty"`
|
||||
@@ -2201,11 +2202,11 @@ type UpdateVendorBusinessAssociateAgreementPayload struct {
|
||||
}
|
||||
|
||||
type UpdateVendorContactInput struct {
|
||||
ID gid.GID `json:"id"`
|
||||
FullName graphql.Omittable[*string] `json:"fullName,omitempty"`
|
||||
Email graphql.Omittable[*string] `json:"email,omitempty"`
|
||||
Phone graphql.Omittable[*string] `json:"phone,omitempty"`
|
||||
Role graphql.Omittable[*string] `json:"role,omitempty"`
|
||||
ID gid.GID `json:"id"`
|
||||
FullName graphql.Omittable[*string] `json:"fullName,omitempty"`
|
||||
Email graphql.Omittable[*mail.Addr] `json:"email,omitempty"`
|
||||
Phone graphql.Omittable[*string] `json:"phone,omitempty"`
|
||||
Role graphql.Omittable[*string] `json:"role,omitempty"`
|
||||
}
|
||||
|
||||
type UpdateVendorContactPayload struct {
|
||||
@@ -2329,7 +2330,7 @@ type UploadVendorDataPrivacyAgreementPayload struct {
|
||||
type User struct {
|
||||
ID gid.GID `json:"id"`
|
||||
FullName string `json:"fullName"`
|
||||
Email string `json:"email"`
|
||||
Email mail.Addr `json:"email"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
@@ -2419,14 +2420,14 @@ type VendorComplianceReportEdge struct {
|
||||
}
|
||||
|
||||
type VendorContact struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Vendor *Vendor `json:"vendor"`
|
||||
FullName *string `json:"fullName,omitempty"`
|
||||
Email *string `json:"email,omitempty"`
|
||||
Phone *string `json:"phone,omitempty"`
|
||||
Role *string `json:"role,omitempty"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
ID gid.GID `json:"id"`
|
||||
Vendor *Vendor `json:"vendor"`
|
||||
FullName *string `json:"fullName,omitempty"`
|
||||
Email *mail.Addr `json:"email,omitempty"`
|
||||
Phone *string `json:"phone,omitempty"`
|
||||
Role *string `json:"role,omitempty"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
func (VendorContact) IsNode() {}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"go.probo.inc/probo/pkg/authz"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"go.probo.inc/probo/pkg/probo"
|
||||
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
|
||||
@@ -1458,7 +1459,7 @@ func (r *mutationResolver) CreateOrganization(ctx context.Context, input types.C
|
||||
OrganizationID: organization.ID,
|
||||
FullName: currentUser.FullName,
|
||||
PrimaryEmailAddress: currentUser.EmailAddress,
|
||||
AdditionalEmailAddresses: []string{},
|
||||
AdditionalEmailAddresses: []mail.Addr{},
|
||||
Kind: coredata.PeopleKindEmployee,
|
||||
},
|
||||
)
|
||||
@@ -1903,7 +1904,7 @@ func (r *mutationResolver) InviteUser(ctx context.Context, input types.InviteUse
|
||||
OrganizationID: input.OrganizationID,
|
||||
FullName: input.FullName,
|
||||
PrimaryEmailAddress: input.Email,
|
||||
AdditionalEmailAddresses: []string{},
|
||||
AdditionalEmailAddresses: []mail.Addr{},
|
||||
Kind: coredata.PeopleKindEmployee,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -1993,7 +1994,7 @@ func (r *mutationResolver) CreatePeople(ctx context.Context, input types.CreateP
|
||||
OrganizationID: input.OrganizationID,
|
||||
FullName: input.FullName,
|
||||
PrimaryEmailAddress: input.PrimaryEmailAddress,
|
||||
AdditionalEmailAddresses: []string{},
|
||||
AdditionalEmailAddresses: []mail.Addr{},
|
||||
Kind: input.Kind,
|
||||
Position: input.Position,
|
||||
ContractStartDate: input.ContractStartDate,
|
||||
@@ -2019,11 +2020,15 @@ func (r *mutationResolver) UpdatePeople(ctx context.Context, input types.UpdateP
|
||||
|
||||
prb := r.ProboService(ctx, input.ID.TenantID())
|
||||
|
||||
var emailAddresses []mail.Addr
|
||||
for _, emailAddress := range input.AdditionalEmailAddresses {
|
||||
emailAddresses = append(emailAddresses, *emailAddress)
|
||||
}
|
||||
people, err := prb.Peoples.Update(ctx, probo.UpdatePeopleRequest{
|
||||
ID: input.ID,
|
||||
FullName: input.FullName,
|
||||
PrimaryEmailAddress: input.PrimaryEmailAddress,
|
||||
AdditionalEmailAddresses: &input.AdditionalEmailAddresses,
|
||||
AdditionalEmailAddresses: &emailAddresses,
|
||||
Kind: input.Kind,
|
||||
Position: UnwrapOmittable(input.Position),
|
||||
ContractStartDate: UnwrapOmittable(input.ContractStartDate),
|
||||
|
||||
@@ -5,6 +5,11 @@ info:
|
||||
|
||||
components:
|
||||
schemas:
|
||||
EmailAddress:
|
||||
type: string
|
||||
format: string
|
||||
go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/mail.Addr
|
||||
|
||||
Duration:
|
||||
type: string
|
||||
description: A duration
|
||||
@@ -89,12 +94,12 @@ components:
|
||||
type: string
|
||||
description: Full name
|
||||
primary_email_address:
|
||||
type: string
|
||||
$ref: "#/components/schemas/EmailAddress"
|
||||
description: Primary email address
|
||||
additional_email_addresses:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
$ref: "#/components/schemas/EmailAddress"
|
||||
description: Additional email addresses
|
||||
kind:
|
||||
$ref: "#/components/schemas/PeopleKind"
|
||||
@@ -372,12 +377,12 @@ components:
|
||||
type: string
|
||||
description: Full name
|
||||
primary_email_address:
|
||||
type: string
|
||||
$ref: "#/components/schemas/EmailAddress"
|
||||
description: Primary email address
|
||||
additional_email_addresses:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
$ref: "#/components/schemas/EmailAddress"
|
||||
description: Additional email addresses
|
||||
kind:
|
||||
$ref: "#/components/schemas/PeopleKind"
|
||||
@@ -414,13 +419,13 @@ components:
|
||||
type: string
|
||||
description: Full name
|
||||
primary_email_address:
|
||||
type: string
|
||||
$ref: "#/components/schemas/EmailAddress"
|
||||
description: Primary email address
|
||||
additional_email_addresses:
|
||||
anyOf:
|
||||
- type: array
|
||||
items:
|
||||
type: string
|
||||
$ref: "#/components/schemas/EmailAddress"
|
||||
- type: "null"
|
||||
description: No additional email addresses
|
||||
description: Additional email addresses
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"go.probo.inc/mcpgen/mcp"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"time"
|
||||
)
|
||||
@@ -32,8 +33,8 @@ var (
|
||||
AddNonconformityToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["nonconformity"],"properties":{"nonconformity":{"type":"object","required":["id","organization_id","reference_id","root_cause","owner_id","status","created_at","updated_at"],"properties":{"audit_id":{"description":"Audit ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No audit"}]},"corrective_action":{"description":"Corrective action"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"date_identified":{"description":"Date identified","format":"date-time"},"description":{"description":"Description"},"due_date":{"description":"Due date","format":"date-time"},"effectiveness_check":{"description":"Effectiveness check"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"reference_id":{"type":"string","description":"Reference ID"},"root_cause":{"type":"string","description":"Root cause"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`)
|
||||
AddObligationToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id","owner_id","status"],"properties":{"actions_to_be_implemented":{"type":"string","description":"Actions to be implemented"},"area":{"type":"string","description":"Area"},"due_date":{"type":"string","description":"Due date","format":"date-time"},"last_review_date":{"type":"string","description":"Last review date","format":"date-time"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"regulator":{"type":"string","description":"Regulator"},"requirement":{"type":"string","description":"Requirement"},"source":{"type":"string","description":"Source"},"status":{"description":"Status","anyOf":[{"type":"string","enum":["NON_COMPLIANT","PARTIALLY_COMPLIANT","COMPLIANT"]},{"type":"null","description":"No status"}]}}}`)
|
||||
AddObligationToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["obligation"],"properties":{"obligation":{"type":"object","required":["id","organization_id","owner_id","status","created_at","updated_at"],"properties":{"actions_to_be_implemented":{"description":"Actions to be implemented"},"area":{"description":"Area"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"due_date":{"description":"Due date","format":"date-time"},"id":{"type":"string","format":"string"},"last_review_date":{"description":"Last review date","format":"date-time"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"regulator":{"description":"Regulator"},"requirement":{"description":"Requirement"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"source":{"description":"Source"},"source_id":{"description":"Source ID"},"status":{"type":"string","enum":["NON_COMPLIANT","PARTIALLY_COMPLIANT","COMPLIANT"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`)
|
||||
AddPeopleToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id","full_name","primary_email_address","kind"],"properties":{"additional_email_addresses":{"type":"array","description":"Additional email addresses","items":{"type":"string"}},"contract_end_date":{"type":"string","description":"Contract end date","format":"date-time"},"contract_start_date":{"type":"string","description":"Contract start date","format":"date-time"},"full_name":{"type":"string","description":"Full name"},"kind":{"type":"string","enum":["EMPLOYEE","CONTRACTOR","SERVICE_ACCOUNT"]},"organization_id":{"type":"string","format":"string"},"position":{"type":"string","description":"Position"},"primary_email_address":{"type":"string","description":"Primary email address"}}}`)
|
||||
AddPeopleToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["people"],"properties":{"people":{"type":"object","required":["id","organization_id","full_name","primary_email_address","additional_email_addresses","kind","created_at","updated_at"],"properties":{"additional_email_addresses":{"type":"array","description":"Additional email addresses","items":{"type":"string"}},"contract_end_date":{"description":"Contract end date","format":"date-time"},"contract_start_date":{"description":"Contract start date","format":"date-time"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"full_name":{"type":"string","description":"Full name"},"id":{"type":"string","format":"string"},"kind":{"type":"string","enum":["EMPLOYEE","CONTRACTOR","SERVICE_ACCOUNT"]},"organization_id":{"type":"string","format":"string"},"position":{"description":"Position"},"primary_email_address":{"type":"string","description":"Primary email address"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`)
|
||||
AddPeopleToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id","full_name","primary_email_address","kind"],"properties":{"additional_email_addresses":{"type":"array","description":"Additional email addresses","items":{"type":"string","format":"string"}},"contract_end_date":{"type":"string","description":"Contract end date","format":"date-time"},"contract_start_date":{"type":"string","description":"Contract start date","format":"date-time"},"full_name":{"type":"string","description":"Full name"},"kind":{"type":"string","enum":["EMPLOYEE","CONTRACTOR","SERVICE_ACCOUNT"]},"organization_id":{"type":"string","format":"string"},"position":{"type":"string","description":"Position"},"primary_email_address":{"type":"string","format":"string"}}}`)
|
||||
AddPeopleToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["people"],"properties":{"people":{"type":"object","required":["id","organization_id","full_name","primary_email_address","additional_email_addresses","kind","created_at","updated_at"],"properties":{"additional_email_addresses":{"type":"array","description":"Additional email addresses","items":{"type":"string","format":"string"}},"contract_end_date":{"description":"Contract end date","format":"date-time"},"contract_start_date":{"description":"Contract start date","format":"date-time"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"full_name":{"type":"string","description":"Full name"},"id":{"type":"string","format":"string"},"kind":{"type":"string","enum":["EMPLOYEE","CONTRACTOR","SERVICE_ACCOUNT"]},"organization_id":{"type":"string","format":"string"},"position":{"description":"Position"},"primary_email_address":{"type":"string","format":"string"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`)
|
||||
AddRiskToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id","name","category","treatment","inherent_likelihood","inherent_impact"],"properties":{"category":{"type":"string","description":"Risk category"},"description":{"type":"string","description":"Risk description"},"inherent_impact":{"type":"integer","description":"Inherent impact"},"inherent_likelihood":{"type":"integer","description":"Inherent likelihood"},"name":{"type":"string","description":"Risk name"},"note":{"type":"string","description":"Risk note"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"residual_impact":{"type":"integer","description":"Residual impact"},"residual_likelihood":{"type":"integer","description":"Residual likelihood"},"treatment":{"type":"string","enum":["MITIGATED","ACCEPTED","AVOIDED","TRANSFERRED"]}}}`)
|
||||
AddRiskToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["risk"],"properties":{"risk":{"type":"object","required":["id","organization_id","name","category","treatment","inherent_likelihood","inherent_impact","inherent_risk_score","residual_likelihood","residual_impact","residual_risk_score","note","created_at","updated_at"],"properties":{"category":{"type":"string","description":"Risk category"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Risk description"},"id":{"type":"string","format":"string"},"inherent_impact":{"type":"integer","description":"Inherent impact"},"inherent_likelihood":{"type":"integer","description":"Inherent likelihood"},"inherent_risk_score":{"type":"integer","description":"Inherent risk score"},"name":{"type":"string","description":"Risk name"},"note":{"type":"string","description":"Risk note"},"organization_id":{"type":"string","format":"string"},"owner_id":{"anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No owner"}]},"residual_impact":{"type":"integer","description":"Residual impact"},"residual_likelihood":{"type":"integer","description":"Residual likelihood"},"residual_risk_score":{"type":"integer","description":"Residual risk score"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"treatment":{"type":"string","enum":["MITIGATED","ACCEPTED","AVOIDED","TRANSFERRED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`)
|
||||
AddTaskToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id","name"],"properties":{"assigned_to_id":{"description":"Assigned to person ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"Not assigned"}]},"deadline":{"type":"string","description":"Deadline","format":"date-time"},"description":{"type":"string","description":"Task description"},"measure_id":{"description":"Measure ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No measure"}]},"name":{"type":"string","description":"Task name"},"organization_id":{"type":"string","format":"string"},"time_estimate":{"type":"string","description":"A duration"}}}`)
|
||||
@@ -75,7 +76,7 @@ var (
|
||||
GetObligationToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"string"}}}`)
|
||||
GetObligationToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["obligation"],"properties":{"obligation":{"type":"object","required":["id","organization_id","owner_id","status","created_at","updated_at"],"properties":{"actions_to_be_implemented":{"description":"Actions to be implemented"},"area":{"description":"Area"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"due_date":{"description":"Due date","format":"date-time"},"id":{"type":"string","format":"string"},"last_review_date":{"description":"Last review date","format":"date-time"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"regulator":{"description":"Regulator"},"requirement":{"description":"Requirement"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"source":{"description":"Source"},"source_id":{"description":"Source ID"},"status":{"type":"string","enum":["NON_COMPLIANT","PARTIALLY_COMPLIANT","COMPLIANT"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`)
|
||||
GetPeopleToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"string"}}}`)
|
||||
GetPeopleToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["people"],"properties":{"people":{"type":"object","required":["id","organization_id","full_name","primary_email_address","additional_email_addresses","kind","created_at","updated_at"],"properties":{"additional_email_addresses":{"type":"array","description":"Additional email addresses","items":{"type":"string"}},"contract_end_date":{"description":"Contract end date","format":"date-time"},"contract_start_date":{"description":"Contract start date","format":"date-time"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"full_name":{"type":"string","description":"Full name"},"id":{"type":"string","format":"string"},"kind":{"type":"string","enum":["EMPLOYEE","CONTRACTOR","SERVICE_ACCOUNT"]},"organization_id":{"type":"string","format":"string"},"position":{"description":"Position"},"primary_email_address":{"type":"string","description":"Primary email address"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`)
|
||||
GetPeopleToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["people"],"properties":{"people":{"type":"object","required":["id","organization_id","full_name","primary_email_address","additional_email_addresses","kind","created_at","updated_at"],"properties":{"additional_email_addresses":{"type":"array","description":"Additional email addresses","items":{"type":"string","format":"string"}},"contract_end_date":{"description":"Contract end date","format":"date-time"},"contract_start_date":{"description":"Contract start date","format":"date-time"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"full_name":{"type":"string","description":"Full name"},"id":{"type":"string","format":"string"},"kind":{"type":"string","enum":["EMPLOYEE","CONTRACTOR","SERVICE_ACCOUNT"]},"organization_id":{"type":"string","format":"string"},"position":{"description":"Position"},"primary_email_address":{"type":"string","format":"string"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`)
|
||||
GetRiskToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"string"}}}`)
|
||||
GetRiskToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["risk"],"properties":{"risk":{"type":"object","required":["id","organization_id","name","category","treatment","inherent_likelihood","inherent_impact","inherent_risk_score","residual_likelihood","residual_impact","residual_risk_score","note","created_at","updated_at"],"properties":{"category":{"type":"string","description":"Risk category"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Risk description"},"id":{"type":"string","format":"string"},"inherent_impact":{"type":"integer","description":"Inherent impact"},"inherent_likelihood":{"type":"integer","description":"Inherent likelihood"},"inherent_risk_score":{"type":"integer","description":"Inherent risk score"},"name":{"type":"string","description":"Risk name"},"note":{"type":"string","description":"Risk note"},"organization_id":{"type":"string","format":"string"},"owner_id":{"anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No owner"}]},"residual_impact":{"type":"integer","description":"Residual impact"},"residual_likelihood":{"type":"integer","description":"Residual likelihood"},"residual_risk_score":{"type":"integer","description":"Residual risk score"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"treatment":{"type":"string","enum":["MITIGATED","ACCEPTED","AVOIDED","TRANSFERRED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`)
|
||||
GetSnapshotToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"string"}}}`)
|
||||
@@ -117,7 +118,7 @@ var (
|
||||
ListOrganizationsToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"organization_id":{"type":"string","format":"string"}}}`)
|
||||
ListOrganizationsToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","properties":{"organizations":{"type":"array","items":{"type":"object","required":["id","name","description","created_at","updated_at"],"properties":{"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Organization description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Organization name"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}}`)
|
||||
ListPeopleToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id"],"properties":{"cursor":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"exclude_contract_ended":{"type":"boolean","description":"Exclude people with ended contracts"}}},"order_by":{"type":"object","required":["field","direction"],"properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","FULL_NAME","KIND"]}}},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}}}`)
|
||||
ListPeopleToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["people"],"properties":{"next_cursor":{"type":"string","format":"string"},"people":{"type":"array","items":{"type":"object","required":["id","organization_id","full_name","primary_email_address","additional_email_addresses","kind","created_at","updated_at"],"properties":{"additional_email_addresses":{"type":"array","description":"Additional email addresses","items":{"type":"string"}},"contract_end_date":{"description":"Contract end date","format":"date-time"},"contract_start_date":{"description":"Contract start date","format":"date-time"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"full_name":{"type":"string","description":"Full name"},"id":{"type":"string","format":"string"},"kind":{"type":"string","enum":["EMPLOYEE","CONTRACTOR","SERVICE_ACCOUNT"]},"organization_id":{"type":"string","format":"string"},"position":{"description":"Position"},"primary_email_address":{"type":"string","description":"Primary email address"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}}`)
|
||||
ListPeopleToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["people"],"properties":{"next_cursor":{"type":"string","format":"string"},"people":{"type":"array","items":{"type":"object","required":["id","organization_id","full_name","primary_email_address","additional_email_addresses","kind","created_at","updated_at"],"properties":{"additional_email_addresses":{"type":"array","description":"Additional email addresses","items":{"type":"string","format":"string"}},"contract_end_date":{"description":"Contract end date","format":"date-time"},"contract_start_date":{"description":"Contract start date","format":"date-time"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"full_name":{"type":"string","description":"Full name"},"id":{"type":"string","format":"string"},"kind":{"type":"string","enum":["EMPLOYEE","CONTRACTOR","SERVICE_ACCOUNT"]},"organization_id":{"type":"string","format":"string"},"position":{"description":"Position"},"primary_email_address":{"type":"string","format":"string"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}}`)
|
||||
ListRisksToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id"],"properties":{"cursor":{"type":"string","format":"string"},"filter":{"type":"object","properties":{"query":{"type":"string","description":"Search query"},"snapshot_id":{"type":"string","format":"string"}}},"order_by":{"type":"object","required":["field","direction"],"properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","UPDATED_AT","NAME","CATEGORY","TREATMENT","INHERENT_RISK_SCORE","RESIDUAL_RISK_SCORE","OWNER_FULL_NAME"]}}},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}}}`)
|
||||
ListRisksToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["risks"],"properties":{"next_cursor":{"type":"string","format":"string"},"risks":{"type":"array","items":{"type":"object","required":["id","organization_id","name","category","treatment","inherent_likelihood","inherent_impact","inherent_risk_score","residual_likelihood","residual_impact","residual_risk_score","note","created_at","updated_at"],"properties":{"category":{"type":"string","description":"Risk category"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Risk description"},"id":{"type":"string","format":"string"},"inherent_impact":{"type":"integer","description":"Inherent impact"},"inherent_likelihood":{"type":"integer","description":"Inherent likelihood"},"inherent_risk_score":{"type":"integer","description":"Inherent risk score"},"name":{"type":"string","description":"Risk name"},"note":{"type":"string","description":"Risk note"},"organization_id":{"type":"string","format":"string"},"owner_id":{"anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No owner"}]},"residual_impact":{"type":"integer","description":"Residual impact"},"residual_likelihood":{"type":"integer","description":"Residual likelihood"},"residual_risk_score":{"type":"integer","description":"Residual risk score"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"treatment":{"type":"string","enum":["MITIGATED","ACCEPTED","AVOIDED","TRANSFERRED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}}`)
|
||||
ListSnapshotsToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["organization_id"],"properties":{"cursor":{"type":"string","format":"string"},"order_by":{"type":"object","required":["field","direction"],"properties":{"direction":{"type":"string","enum":["ASC","DESC"]},"field":{"type":"string","enum":["CREATED_AT","NAME","TYPE"]}}},"organization_id":{"type":"string","format":"string"},"size":{"type":"integer","description":"Page size"}}}`)
|
||||
@@ -164,8 +165,8 @@ var (
|
||||
UpdateNonconformityToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["nonconformity"],"properties":{"nonconformity":{"type":"object","required":["id","organization_id","reference_id","root_cause","owner_id","status","created_at","updated_at"],"properties":{"audit_id":{"description":"Audit ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No audit"}]},"corrective_action":{"description":"Corrective action"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"date_identified":{"description":"Date identified","format":"date-time"},"description":{"description":"Description"},"due_date":{"description":"Due date","format":"date-time"},"effectiveness_check":{"description":"Effectiveness check"},"id":{"type":"string","format":"string"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"reference_id":{"type":"string","description":"Reference ID"},"root_cause":{"type":"string","description":"Root cause"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","CLOSED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`)
|
||||
UpdateObligationToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"actions_to_be_implemented":{"description":"Actions to be implemented"},"area":{"description":"Area"},"due_date":{"description":"Due date","format":"date-time"},"id":{"type":"string","format":"string"},"last_review_date":{"description":"Last review date","format":"date-time"},"owner_id":{"description":"Owner ID","anyOf":[{"type":"string","format":"string"},{"type":"null"}]},"regulator":{"description":"Regulator"},"requirement":{"description":"Requirement"},"source":{"description":"Source"},"status":{"description":"Status","anyOf":[{"type":"string","enum":["NON_COMPLIANT","PARTIALLY_COMPLIANT","COMPLIANT"]},{"type":"null","description":"No status"}]}}}`)
|
||||
UpdateObligationToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["obligation"],"properties":{"obligation":{"type":"object","required":["id","organization_id","owner_id","status","created_at","updated_at"],"properties":{"actions_to_be_implemented":{"description":"Actions to be implemented"},"area":{"description":"Area"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"due_date":{"description":"Due date","format":"date-time"},"id":{"type":"string","format":"string"},"last_review_date":{"description":"Last review date","format":"date-time"},"organization_id":{"type":"string","format":"string"},"owner_id":{"type":"string","format":"string"},"regulator":{"description":"Regulator"},"requirement":{"description":"Requirement"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"source":{"description":"Source"},"source_id":{"description":"Source ID"},"status":{"type":"string","enum":["NON_COMPLIANT","PARTIALLY_COMPLIANT","COMPLIANT"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`)
|
||||
UpdatePeopleToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"additional_email_addresses":{"description":"Additional email addresses","anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null","description":"No additional email addresses"}]},"contract_end_date":{"description":"Contract end date","format":"date-time"},"contract_start_date":{"description":"Contract start date","format":"date-time"},"full_name":{"type":"string","description":"Full name"},"id":{"type":"string","format":"string"},"kind":{"type":"string","enum":["EMPLOYEE","CONTRACTOR","SERVICE_ACCOUNT"]},"position":{"description":"Position"},"primary_email_address":{"type":"string","description":"Primary email address"}}}`)
|
||||
UpdatePeopleToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["people"],"properties":{"people":{"type":"object","required":["id","organization_id","full_name","primary_email_address","additional_email_addresses","kind","created_at","updated_at"],"properties":{"additional_email_addresses":{"type":"array","description":"Additional email addresses","items":{"type":"string"}},"contract_end_date":{"description":"Contract end date","format":"date-time"},"contract_start_date":{"description":"Contract start date","format":"date-time"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"full_name":{"type":"string","description":"Full name"},"id":{"type":"string","format":"string"},"kind":{"type":"string","enum":["EMPLOYEE","CONTRACTOR","SERVICE_ACCOUNT"]},"organization_id":{"type":"string","format":"string"},"position":{"description":"Position"},"primary_email_address":{"type":"string","description":"Primary email address"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`)
|
||||
UpdatePeopleToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"additional_email_addresses":{"description":"Additional email addresses","anyOf":[{"type":"array","items":{"type":"string","format":"string"}},{"type":"null","description":"No additional email addresses"}]},"contract_end_date":{"description":"Contract end date","format":"date-time"},"contract_start_date":{"description":"Contract start date","format":"date-time"},"full_name":{"type":"string","description":"Full name"},"id":{"type":"string","format":"string"},"kind":{"type":"string","enum":["EMPLOYEE","CONTRACTOR","SERVICE_ACCOUNT"]},"position":{"description":"Position"},"primary_email_address":{"type":"string","format":"string"}}}`)
|
||||
UpdatePeopleToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["people"],"properties":{"people":{"type":"object","required":["id","organization_id","full_name","primary_email_address","additional_email_addresses","kind","created_at","updated_at"],"properties":{"additional_email_addresses":{"type":"array","description":"Additional email addresses","items":{"type":"string","format":"string"}},"contract_end_date":{"description":"Contract end date","format":"date-time"},"contract_start_date":{"description":"Contract start date","format":"date-time"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"full_name":{"type":"string","description":"Full name"},"id":{"type":"string","format":"string"},"kind":{"type":"string","enum":["EMPLOYEE","CONTRACTOR","SERVICE_ACCOUNT"]},"organization_id":{"type":"string","format":"string"},"position":{"description":"Position"},"primary_email_address":{"type":"string","format":"string"},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`)
|
||||
UpdateRiskToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"category":{"type":"string","description":"Risk category"},"description":{"description":"Risk description"},"id":{"type":"string","format":"string"},"inherent_impact":{"type":"integer","description":"Inherent impact"},"inherent_likelihood":{"type":"integer","description":"Inherent likelihood"},"name":{"type":"string","description":"Risk name"},"note":{"type":"string","description":"Risk note"},"owner_id":{"description":"Owner ID","anyOf":[{"type":"string","format":"string"},{"type":"null"}]},"residual_impact":{"type":"integer","description":"Residual impact"},"residual_likelihood":{"type":"integer","description":"Residual likelihood"},"treatment":{"type":"string","enum":["MITIGATED","ACCEPTED","AVOIDED","TRANSFERRED"]}}}`)
|
||||
UpdateRiskToolOutputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["risk"],"properties":{"risk":{"type":"object","required":["id","organization_id","name","category","treatment","inherent_likelihood","inherent_impact","inherent_risk_score","residual_likelihood","residual_impact","residual_risk_score","note","created_at","updated_at"],"properties":{"category":{"type":"string","description":"Risk category"},"created_at":{"type":"string","description":"Creation timestamp","format":"date-time"},"description":{"description":"Risk description"},"id":{"type":"string","format":"string"},"inherent_impact":{"type":"integer","description":"Inherent impact"},"inherent_likelihood":{"type":"integer","description":"Inherent likelihood"},"inherent_risk_score":{"type":"integer","description":"Inherent risk score"},"name":{"type":"string","description":"Risk name"},"note":{"type":"string","description":"Risk note"},"organization_id":{"type":"string","format":"string"},"owner_id":{"anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No owner"}]},"residual_impact":{"type":"integer","description":"Residual impact"},"residual_likelihood":{"type":"integer","description":"Residual likelihood"},"residual_risk_score":{"type":"integer","description":"Residual risk score"},"snapshot_id":{"description":"Snapshot ID","anyOf":[{"type":"string","format":"string"},{"type":"null","description":"No snapshot"}]},"treatment":{"type":"string","enum":["MITIGATED","ACCEPTED","AVOIDED","TRANSFERRED"]},"updated_at":{"type":"string","description":"Update timestamp","format":"date-time"}}}}}`)
|
||||
UpdateTaskToolInputSchema = mcp.MustUnmarshalSchema(`{"type":"object","required":["id"],"properties":{"deadline":{"description":"Deadline","anyOf":[{"type":"string","description":"Deadline","format":"date-time"},{"type":"null","description":"No deadline"}]},"description":{"description":"Task description"},"id":{"type":"string","format":"string"},"name":{"type":"string","description":"Task name"},"state":{"description":"Task state","anyOf":[{"type":"string","enum":["TODO","DONE"]},{"type":"null","description":"No state"}]},"time_estimate":{"description":"Time estimate","anyOf":[{"type":"string","description":"A duration"},{"type":"null","description":"No time estimate"}]}}}`)
|
||||
@@ -404,7 +405,7 @@ type AddObligationOutput struct {
|
||||
// AddPeopleInput represents the schema
|
||||
type AddPeopleInput struct {
|
||||
// Additional email addresses
|
||||
AdditionalEmailAddresses []string `json:"additional_email_addresses,omitempty"`
|
||||
AdditionalEmailAddresses []mail.Addr `json:"additional_email_addresses,omitempty"`
|
||||
// Contract end date
|
||||
ContractEndDate *time.Time `json:"contract_end_date,omitempty"`
|
||||
// Contract start date
|
||||
@@ -418,7 +419,7 @@ type AddPeopleInput struct {
|
||||
// Position
|
||||
Position *string `json:"position,omitempty"`
|
||||
// Primary email address
|
||||
PrimaryEmailAddress string `json:"primary_email_address"`
|
||||
PrimaryEmailAddress mail.Addr `json:"primary_email_address"`
|
||||
}
|
||||
|
||||
// AddPeopleOutput represents the schema
|
||||
@@ -1548,7 +1549,7 @@ type Organization struct {
|
||||
// People represents the schema
|
||||
type People struct {
|
||||
// Additional email addresses
|
||||
AdditionalEmailAddresses []string `json:"additional_email_addresses"`
|
||||
AdditionalEmailAddresses []mail.Addr `json:"additional_email_addresses"`
|
||||
// Contract end date
|
||||
ContractEndDate *time.Time `json:"contract_end_date,omitempty"`
|
||||
// Contract start date
|
||||
@@ -1566,7 +1567,7 @@ type People struct {
|
||||
// Position
|
||||
Position *string `json:"position,omitempty"`
|
||||
// Primary email address
|
||||
PrimaryEmailAddress string `json:"primary_email_address"`
|
||||
PrimaryEmailAddress mail.Addr `json:"primary_email_address"`
|
||||
// Update timestamp
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
@@ -2025,7 +2026,7 @@ type UpdateObligationOutput struct {
|
||||
// UpdatePeopleInput represents the schema
|
||||
type UpdatePeopleInput struct {
|
||||
// Additional email addresses
|
||||
AdditionalEmailAddresses *[]string `json:"additional_email_addresses,omitempty"`
|
||||
AdditionalEmailAddresses *[]mail.Addr `json:"additional_email_addresses,omitempty"`
|
||||
// Contract end date
|
||||
ContractEndDate mcp.Omittable[*time.Time] `json:"contract_end_date,omitempty"`
|
||||
// Contract start date
|
||||
@@ -2039,7 +2040,7 @@ type UpdatePeopleInput struct {
|
||||
// Position
|
||||
Position mcp.Omittable[*string] `json:"position,omitempty"`
|
||||
// Primary email address
|
||||
PrimaryEmailAddress *string `json:"primary_email_address,omitempty"`
|
||||
PrimaryEmailAddress *mail.Addr `json:"primary_email_address,omitempty"`
|
||||
}
|
||||
|
||||
// UpdatePeopleOutput represents the schema
|
||||
|
||||
@@ -146,7 +146,7 @@ func SlackHandler(slackSvc *slack.Service, slackSigningSecret string, logger *lo
|
||||
return
|
||||
}
|
||||
|
||||
if initialSlackMessage.RequesterEmail == nil || *initialSlackMessage.RequesterEmail == "" {
|
||||
if initialSlackMessage.RequesterEmail == nil {
|
||||
logger.ErrorCtx(ctx, "missing requester email", log.String("slack_message_id", initialSlackMessage.ID.String()))
|
||||
httpserver.RenderJSON(w, http.StatusInternalServerError, SlackInteractiveResponse{Success: false, Message: "internal server error"})
|
||||
return
|
||||
|
||||
@@ -27,3 +27,6 @@ models:
|
||||
CursorKey:
|
||||
model:
|
||||
- "go.probo.inc/probo/pkg/server/gqlutils/types/cursor.CursorKeyScalar"
|
||||
EmailAddr:
|
||||
model:
|
||||
- "go.probo.inc/probo/pkg/server/gqlutils/types/mail.AddrScalar"
|
||||
|
||||
@@ -19,8 +19,9 @@ enum Role {
|
||||
USER
|
||||
}
|
||||
|
||||
scalar Datetime
|
||||
scalar CursorKey
|
||||
scalar Datetime
|
||||
scalar EmailAddr
|
||||
|
||||
interface Node {
|
||||
id: ID!
|
||||
@@ -46,11 +47,9 @@ type Organization implements Node {
|
||||
|
||||
enum DocumentType
|
||||
@goModel(model: "go.probo.inc/probo/pkg/coredata.DocumentType") {
|
||||
OTHER
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeOther")
|
||||
OTHER @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeOther")
|
||||
ISMS @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeISMS")
|
||||
POLICY
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypePolicy")
|
||||
POLICY @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypePolicy")
|
||||
PROCEDURE
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeProcedure")
|
||||
}
|
||||
@@ -357,9 +356,7 @@ enum CountryCode
|
||||
enum VendorCategory
|
||||
@goModel(model: "go.probo.inc/probo/pkg/coredata.VendorCategory") {
|
||||
ANALYTICS
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryAnalytics"
|
||||
)
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryAnalytics")
|
||||
CLOUD_MONITORING
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryCloudMonitoring"
|
||||
@@ -389,28 +386,21 @@ enum VendorCategory
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryEmployeeManagement"
|
||||
)
|
||||
ENGINEERING
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryEngineering"
|
||||
)
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryEngineering")
|
||||
FINANCE
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryFinance"
|
||||
)
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryFinance")
|
||||
IDENTITY_PROVIDER
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryIdentityProvider"
|
||||
)
|
||||
IT @goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryIT")
|
||||
MARKETING
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryMarketing"
|
||||
)
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryMarketing")
|
||||
OFFICE_OPERATIONS
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryOfficeOperations"
|
||||
)
|
||||
OTHER
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryOther")
|
||||
OTHER @goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryOther")
|
||||
PASSWORD_MANAGEMENT
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryPasswordManagement"
|
||||
@@ -424,15 +414,10 @@ enum VendorCategory
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryProfessionalServices"
|
||||
)
|
||||
RECRUITING
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryRecruiting"
|
||||
)
|
||||
SALES
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategorySales")
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryRecruiting")
|
||||
SALES @goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategorySales")
|
||||
SECURITY
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategorySecurity"
|
||||
)
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategorySecurity")
|
||||
VERSION_CONTROL
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryVersionControl"
|
||||
@@ -542,7 +527,7 @@ type TrustCenter implements Node {
|
||||
|
||||
type TrustCenterAccess implements Node {
|
||||
id: ID!
|
||||
email: String!
|
||||
email: EmailAddr!
|
||||
name: String!
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
@@ -550,7 +535,7 @@ type TrustCenterAccess implements Node {
|
||||
|
||||
input RequestAllAccessesInput {
|
||||
trustCenterId: ID!
|
||||
email: String
|
||||
email: EmailAddr
|
||||
name: String
|
||||
}
|
||||
|
||||
@@ -573,21 +558,21 @@ input AcceptNonDisclosureAgreementInput {
|
||||
input RequestDocumentAccessInput {
|
||||
trustCenterId: ID!
|
||||
documentId: ID!
|
||||
email: String
|
||||
email: EmailAddr
|
||||
name: String
|
||||
}
|
||||
|
||||
input RequestReportAccessInput {
|
||||
trustCenterId: ID!
|
||||
reportId: ID!
|
||||
email: String
|
||||
email: EmailAddr
|
||||
name: String
|
||||
}
|
||||
|
||||
input RequestTrustCenterFileAccessInput {
|
||||
trustCenterId: ID!
|
||||
trustCenterFileId: ID!
|
||||
email: String
|
||||
email: EmailAddr
|
||||
name: String
|
||||
}
|
||||
|
||||
|
||||
@@ -18,10 +18,12 @@ import (
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"go.probo.inc/probo/pkg/server/api/trust/v1/types"
|
||||
"go.probo.inc/probo/pkg/server/gqlutils/types/cursor"
|
||||
gid1 "go.probo.inc/probo/pkg/server/gqlutils/types/gid"
|
||||
mail1 "go.probo.inc/probo/pkg/server/gqlutils/types/mail"
|
||||
)
|
||||
|
||||
// region ************************** generated!.gotpl **************************
|
||||
@@ -1115,8 +1117,9 @@ enum Role {
|
||||
USER
|
||||
}
|
||||
|
||||
scalar Datetime
|
||||
scalar CursorKey
|
||||
scalar Datetime
|
||||
scalar EmailAddr
|
||||
|
||||
interface Node {
|
||||
id: ID!
|
||||
@@ -1142,11 +1145,9 @@ type Organization implements Node {
|
||||
|
||||
enum DocumentType
|
||||
@goModel(model: "go.probo.inc/probo/pkg/coredata.DocumentType") {
|
||||
OTHER
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeOther")
|
||||
OTHER @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeOther")
|
||||
ISMS @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeISMS")
|
||||
POLICY
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypePolicy")
|
||||
POLICY @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypePolicy")
|
||||
PROCEDURE
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeProcedure")
|
||||
}
|
||||
@@ -1453,9 +1454,7 @@ enum CountryCode
|
||||
enum VendorCategory
|
||||
@goModel(model: "go.probo.inc/probo/pkg/coredata.VendorCategory") {
|
||||
ANALYTICS
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryAnalytics"
|
||||
)
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryAnalytics")
|
||||
CLOUD_MONITORING
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryCloudMonitoring"
|
||||
@@ -1485,28 +1484,21 @@ enum VendorCategory
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryEmployeeManagement"
|
||||
)
|
||||
ENGINEERING
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryEngineering"
|
||||
)
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryEngineering")
|
||||
FINANCE
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryFinance"
|
||||
)
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryFinance")
|
||||
IDENTITY_PROVIDER
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryIdentityProvider"
|
||||
)
|
||||
IT @goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryIT")
|
||||
MARKETING
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryMarketing"
|
||||
)
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryMarketing")
|
||||
OFFICE_OPERATIONS
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryOfficeOperations"
|
||||
)
|
||||
OTHER
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryOther")
|
||||
OTHER @goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryOther")
|
||||
PASSWORD_MANAGEMENT
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryPasswordManagement"
|
||||
@@ -1520,15 +1512,10 @@ enum VendorCategory
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryProfessionalServices"
|
||||
)
|
||||
RECRUITING
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryRecruiting"
|
||||
)
|
||||
SALES
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategorySales")
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategoryRecruiting")
|
||||
SALES @goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategorySales")
|
||||
SECURITY
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategorySecurity"
|
||||
)
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.VendorCategorySecurity")
|
||||
VERSION_CONTROL
|
||||
@goEnum(
|
||||
value: "go.probo.inc/probo/pkg/coredata.VendorCategoryVersionControl"
|
||||
@@ -1638,7 +1625,7 @@ type TrustCenter implements Node {
|
||||
|
||||
type TrustCenterAccess implements Node {
|
||||
id: ID!
|
||||
email: String!
|
||||
email: EmailAddr!
|
||||
name: String!
|
||||
createdAt: Datetime!
|
||||
updatedAt: Datetime!
|
||||
@@ -1646,7 +1633,7 @@ type TrustCenterAccess implements Node {
|
||||
|
||||
input RequestAllAccessesInput {
|
||||
trustCenterId: ID!
|
||||
email: String
|
||||
email: EmailAddr
|
||||
name: String
|
||||
}
|
||||
|
||||
@@ -1669,21 +1656,21 @@ input AcceptNonDisclosureAgreementInput {
|
||||
input RequestDocumentAccessInput {
|
||||
trustCenterId: ID!
|
||||
documentId: ID!
|
||||
email: String
|
||||
email: EmailAddr
|
||||
name: String
|
||||
}
|
||||
|
||||
input RequestReportAccessInput {
|
||||
trustCenterId: ID!
|
||||
reportId: ID!
|
||||
email: String
|
||||
email: EmailAddr
|
||||
name: String
|
||||
}
|
||||
|
||||
input RequestTrustCenterFileAccessInput {
|
||||
trustCenterId: ID!
|
||||
trustCenterFileId: ID!
|
||||
email: String
|
||||
email: EmailAddr
|
||||
name: String
|
||||
}
|
||||
|
||||
@@ -4584,7 +4571,7 @@ func (ec *executionContext) _TrustCenterAccess_email(ctx context.Context, field
|
||||
return obj.Email, nil
|
||||
},
|
||||
nil,
|
||||
ec.marshalNString2string,
|
||||
ec.marshalNEmailAddr2goᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
@@ -4597,7 +4584,7 @@ func (ec *executionContext) fieldContext_TrustCenterAccess_email(_ context.Conte
|
||||
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 nil, errors.New("field of type EmailAddr does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
@@ -7165,7 +7152,7 @@ func (ec *executionContext) unmarshalInputRequestAllAccessesInput(ctx context.Co
|
||||
it.TrustCenterID = data
|
||||
case "email":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email"))
|
||||
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
data, err := ec.unmarshalOEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -7213,7 +7200,7 @@ func (ec *executionContext) unmarshalInputRequestDocumentAccessInput(ctx context
|
||||
it.DocumentID = data
|
||||
case "email":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email"))
|
||||
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
data, err := ec.unmarshalOEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -7261,7 +7248,7 @@ func (ec *executionContext) unmarshalInputRequestReportAccessInput(ctx context.C
|
||||
it.ReportID = data
|
||||
case "email":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email"))
|
||||
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
data, err := ec.unmarshalOEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -7309,7 +7296,7 @@ func (ec *executionContext) unmarshalInputRequestTrustCenterFileAccessInput(ctx
|
||||
it.TrustCenterFileID = data
|
||||
case "email":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("email"))
|
||||
data, err := ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
data, err := ec.unmarshalOEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -10647,6 +10634,22 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func (ec *executionContext) unmarshalNEmailAddr2goᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx context.Context, v any) (mail.Addr, error) {
|
||||
res, err := mail1.UnmarshalAddrScalar(v)
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNEmailAddr2goᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx context.Context, sel ast.SelectionSet, v mail.Addr) graphql.Marshaler {
|
||||
_ = sel
|
||||
res := mail1.MarshalAddrScalar(v)
|
||||
if res == graphql.Null {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNExportDocumentPDFInput2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐExportDocumentPDFInput(ctx context.Context, v any) (types.ExportDocumentPDFInput, error) {
|
||||
res, err := ec.unmarshalInputExportDocumentPDFInput(ctx, v)
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
@@ -11431,6 +11434,24 @@ func (ec *executionContext) marshalOCursorKey2ᚖgoᚗproboᚗincᚋproboᚋpkg
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalOEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx context.Context, v any) (*mail.Addr, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
res, err := mail1.UnmarshalAddrScalar(v)
|
||||
return &res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOEmailAddr2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋmailᚐAddr(ctx context.Context, sel ast.SelectionSet, v *mail.Addr) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
_ = sel
|
||||
_ = ctx
|
||||
res := mail1.MarshalAddrScalar(*v)
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalOInt2ᚖint(ctx context.Context, v any) (*int, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
|
||||
@@ -21,20 +21,17 @@ import (
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/server/api/trust/v1/types"
|
||||
)
|
||||
|
||||
type TokenAccessData struct {
|
||||
TrustCenterID gid.GID
|
||||
Email string
|
||||
Email mail.Addr
|
||||
TenantID gid.TenantID
|
||||
Scope string
|
||||
}
|
||||
|
||||
func (t *TokenAccessData) GetEmail() string {
|
||||
return t.Email
|
||||
}
|
||||
|
||||
type ContextAccessor interface {
|
||||
UserFromContext(ctx context.Context) *coredata.User
|
||||
TokenAccessFromContext(ctx context.Context) *TokenAccessData
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
)
|
||||
|
||||
@@ -140,30 +141,30 @@ type RequestAccessesPayload struct {
|
||||
}
|
||||
|
||||
type RequestAllAccessesInput struct {
|
||||
TrustCenterID gid.GID `json:"trustCenterId"`
|
||||
Email *string `json:"email,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
TrustCenterID gid.GID `json:"trustCenterId"`
|
||||
Email *mail.Addr `json:"email,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
type RequestDocumentAccessInput struct {
|
||||
TrustCenterID gid.GID `json:"trustCenterId"`
|
||||
DocumentID gid.GID `json:"documentId"`
|
||||
Email *string `json:"email,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
TrustCenterID gid.GID `json:"trustCenterId"`
|
||||
DocumentID gid.GID `json:"documentId"`
|
||||
Email *mail.Addr `json:"email,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
type RequestReportAccessInput struct {
|
||||
TrustCenterID gid.GID `json:"trustCenterId"`
|
||||
ReportID gid.GID `json:"reportId"`
|
||||
Email *string `json:"email,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
TrustCenterID gid.GID `json:"trustCenterId"`
|
||||
ReportID gid.GID `json:"reportId"`
|
||||
Email *mail.Addr `json:"email,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
type RequestTrustCenterFileAccessInput struct {
|
||||
TrustCenterID gid.GID `json:"trustCenterId"`
|
||||
TrustCenterFileID gid.GID `json:"trustCenterFileId"`
|
||||
Email *string `json:"email,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
TrustCenterID gid.GID `json:"trustCenterId"`
|
||||
TrustCenterFileID gid.GID `json:"trustCenterFileId"`
|
||||
Email *mail.Addr `json:"email,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
type TrustCenter struct {
|
||||
@@ -187,7 +188,7 @@ func (this TrustCenter) GetID() gid.GID { return this.ID }
|
||||
|
||||
type TrustCenterAccess struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Email string `json:"email"`
|
||||
Email mail.Addr `json:"email"`
|
||||
Name string `json:"name"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/vektah/gqlparser/v2/gqlerror"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"go.probo.inc/probo/pkg/server/api/trust/v1/schema"
|
||||
"go.probo.inc/probo/pkg/server/api/trust/v1/types"
|
||||
@@ -82,7 +83,7 @@ func (r *documentResolver) IsUserAuthorized(ctx context.Context, obj *types.Docu
|
||||
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
if tokenData != nil {
|
||||
documentAccess, err := privateTrustService.TrustCenterAccesses.LoadDocumentAccess(ctx, tokenData.TrustCenterID, tokenData.GetEmail(), obj.ID)
|
||||
documentAccess, err := privateTrustService.TrustCenterAccesses.LoadDocumentAccess(ctx, tokenData.TrustCenterID, tokenData.Email, obj.ID)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
@@ -108,7 +109,7 @@ func (r *documentResolver) HasUserRequestedAccess(ctx context.Context, obj *type
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
if tokenData != nil {
|
||||
// Try to load document access - if it exists (regardless of active status), user has requested it
|
||||
_, err := privateTrustService.TrustCenterAccesses.LoadDocumentAccess(ctx, tokenData.TrustCenterID, tokenData.GetEmail(), obj.ID)
|
||||
_, err := privateTrustService.TrustCenterAccesses.LoadDocumentAccess(ctx, tokenData.TrustCenterID, tokenData.Email, obj.ID)
|
||||
if err != nil {
|
||||
return false, nil // No access requested or error
|
||||
}
|
||||
@@ -133,8 +134,8 @@ func (r *mutationResolver) RequestAllAccesses(ctx context.Context, input types.R
|
||||
if email != nil || input.Name != nil {
|
||||
return nil, fmt.Errorf("email and name are not allowed for authenticated users")
|
||||
}
|
||||
emailValue := tokenData.GetEmail()
|
||||
email = &emailValue
|
||||
|
||||
*email = tokenData.Email
|
||||
}
|
||||
if email == nil {
|
||||
return nil, fmt.Errorf("email is required for unauthenticated users")
|
||||
@@ -202,13 +203,13 @@ func (r *mutationResolver) ExportDocumentPDF(ctx context.Context, input types.Ex
|
||||
|
||||
if ndaExists {
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
hasAcceptedNDA, err = privateTrustService.TrustCenterAccesses.HasAcceptedNonDisclosureAgreement(ctx, tokenData.TrustCenterID, tokenData.GetEmail())
|
||||
hasAcceptedNDA, err = privateTrustService.TrustCenterAccesses.HasAcceptedNonDisclosureAgreement(ctx, tokenData.TrustCenterID, tokenData.Email)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot check if user has accepted NDA: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
documentAccess, err := privateTrustService.TrustCenterAccesses.LoadDocumentAccess(ctx, tokenData.TrustCenterID, tokenData.GetEmail(), input.DocumentID)
|
||||
documentAccess, err := privateTrustService.TrustCenterAccesses.LoadDocumentAccess(ctx, tokenData.TrustCenterID, tokenData.Email, input.DocumentID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot check document access: %w", err))
|
||||
}
|
||||
@@ -223,12 +224,12 @@ func (r *mutationResolver) ExportDocumentPDF(ctx context.Context, input types.Ex
|
||||
}
|
||||
|
||||
userData := UserFromContext(ctx)
|
||||
userEmail := ""
|
||||
var userEmail mail.Addr
|
||||
if userData != nil {
|
||||
userEmail = userData.EmailAddress
|
||||
}
|
||||
if tokenData != nil {
|
||||
userEmail = tokenData.GetEmail()
|
||||
userEmail = tokenData.Email
|
||||
}
|
||||
|
||||
pdf, err := privateTrustService.Documents.ExportPDF(ctx, input.DocumentID, userEmail)
|
||||
@@ -280,13 +281,13 @@ func (r *mutationResolver) ExportReportPDF(ctx context.Context, input types.Expo
|
||||
}
|
||||
|
||||
if ndaExists {
|
||||
hasAcceptedNDA, err = privateTrustService.TrustCenterAccesses.HasAcceptedNonDisclosureAgreement(ctx, tokenData.TrustCenterID, tokenData.GetEmail())
|
||||
hasAcceptedNDA, err = privateTrustService.TrustCenterAccesses.HasAcceptedNonDisclosureAgreement(ctx, tokenData.TrustCenterID, tokenData.Email)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot check if user has accepted NDA: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
reportAccess, err := privateTrustService.TrustCenterAccesses.LoadReportAccess(ctx, tokenData.TrustCenterID, tokenData.GetEmail(), input.ReportID)
|
||||
reportAccess, err := privateTrustService.TrustCenterAccesses.LoadReportAccess(ctx, tokenData.TrustCenterID, tokenData.Email, input.ReportID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot check report access: %w", err))
|
||||
}
|
||||
@@ -301,12 +302,12 @@ func (r *mutationResolver) ExportReportPDF(ctx context.Context, input types.Expo
|
||||
}
|
||||
|
||||
userData := UserFromContext(ctx)
|
||||
userEmail := ""
|
||||
var userEmail mail.Addr
|
||||
if userData != nil {
|
||||
userEmail = userData.EmailAddress
|
||||
}
|
||||
if tokenData != nil {
|
||||
userEmail = tokenData.GetEmail()
|
||||
userEmail = tokenData.Email
|
||||
}
|
||||
|
||||
pdf, err := privateTrustService.Reports.ExportPDF(ctx, input.ReportID, userEmail)
|
||||
@@ -331,7 +332,7 @@ func (r *mutationResolver) AcceptNonDisclosureAgreement(ctx context.Context, inp
|
||||
return nil, fmt.Errorf("token not found")
|
||||
}
|
||||
|
||||
err = privateTrustService.TrustCenterAccesses.AcceptNonDisclosureAgreement(ctx, input.TrustCenterID, tokenData.GetEmail())
|
||||
err = privateTrustService.TrustCenterAccesses.AcceptNonDisclosureAgreement(ctx, input.TrustCenterID, tokenData.Email)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot accept NDA: %w", err)
|
||||
}
|
||||
@@ -360,11 +361,7 @@ func (r *mutationResolver) RequestDocumentAccess(ctx context.Context, input type
|
||||
email := input.Email
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
if tokenData != nil {
|
||||
if email != nil || input.Name != nil {
|
||||
return nil, fmt.Errorf("email and name are not allowed for authenticated users")
|
||||
}
|
||||
emailValue := tokenData.GetEmail()
|
||||
email = &emailValue
|
||||
*email = tokenData.Email
|
||||
}
|
||||
if email == nil {
|
||||
return nil, fmt.Errorf("email is required for unauthenticated users")
|
||||
@@ -413,11 +410,7 @@ func (r *mutationResolver) RequestReportAccess(ctx context.Context, input types.
|
||||
email := input.Email
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
if tokenData != nil {
|
||||
if email != nil || input.Name != nil {
|
||||
return nil, fmt.Errorf("email and name are not allowed for authenticated users")
|
||||
}
|
||||
emailValue := tokenData.GetEmail()
|
||||
email = &emailValue
|
||||
*email = tokenData.Email
|
||||
}
|
||||
if email == nil {
|
||||
return nil, fmt.Errorf("email is required for unauthenticated users")
|
||||
@@ -466,11 +459,7 @@ func (r *mutationResolver) RequestTrustCenterFileAccess(ctx context.Context, inp
|
||||
email := input.Email
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
if tokenData != nil {
|
||||
if email != nil || input.Name != nil {
|
||||
return nil, fmt.Errorf("email and name are not allowed for authenticated users")
|
||||
}
|
||||
emailValue := tokenData.GetEmail()
|
||||
email = &emailValue
|
||||
*email = tokenData.Email
|
||||
}
|
||||
if email == nil {
|
||||
return nil, fmt.Errorf("email is required for unauthenticated users")
|
||||
@@ -538,13 +527,13 @@ func (r *mutationResolver) ExportTrustCenterFile(ctx context.Context, input type
|
||||
}
|
||||
|
||||
if ndaExists {
|
||||
hasAcceptedNDA, err = privateTrustService.TrustCenterAccesses.HasAcceptedNonDisclosureAgreement(ctx, tokenData.TrustCenterID, tokenData.GetEmail())
|
||||
hasAcceptedNDA, err = privateTrustService.TrustCenterAccesses.HasAcceptedNonDisclosureAgreement(ctx, tokenData.TrustCenterID, tokenData.Email)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot check if user has accepted NDA: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
fileAccess, err := privateTrustService.TrustCenterAccesses.LoadTrustCenterFileAccess(ctx, tokenData.TrustCenterID, tokenData.GetEmail(), input.TrustCenterFileID)
|
||||
fileAccess, err := privateTrustService.TrustCenterAccesses.LoadTrustCenterFileAccess(ctx, tokenData.TrustCenterID, tokenData.Email, input.TrustCenterFileID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot check trust center file access: %w", err))
|
||||
}
|
||||
@@ -559,12 +548,12 @@ func (r *mutationResolver) ExportTrustCenterFile(ctx context.Context, input type
|
||||
}
|
||||
|
||||
userData := UserFromContext(ctx)
|
||||
userEmail := ""
|
||||
var userEmail mail.Addr
|
||||
if userData != nil {
|
||||
userEmail = userData.EmailAddress
|
||||
}
|
||||
if tokenData != nil {
|
||||
userEmail = tokenData.GetEmail()
|
||||
userEmail = tokenData.Email
|
||||
}
|
||||
|
||||
fileData, err := privateTrustService.TrustCenterFiles.ExportFile(ctx, input.TrustCenterFileID, userEmail)
|
||||
@@ -743,7 +732,7 @@ func (r *reportResolver) IsUserAuthorized(ctx context.Context, obj *types.Report
|
||||
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
if tokenData != nil {
|
||||
reportAccess, err := privateTrustService.TrustCenterAccesses.LoadReportAccess(ctx, tokenData.TrustCenterID, tokenData.GetEmail(), obj.ID)
|
||||
reportAccess, err := privateTrustService.TrustCenterAccesses.LoadReportAccess(ctx, tokenData.TrustCenterID, tokenData.Email, obj.ID)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
@@ -768,7 +757,7 @@ func (r *reportResolver) HasUserRequestedAccess(ctx context.Context, obj *types.
|
||||
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
if tokenData != nil {
|
||||
_, err := privateTrustService.TrustCenterAccesses.LoadReportAccess(ctx, tokenData.TrustCenterID, tokenData.GetEmail(), obj.ID)
|
||||
_, err := privateTrustService.TrustCenterAccesses.LoadReportAccess(ctx, tokenData.TrustCenterID, tokenData.Email, obj.ID)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
@@ -822,7 +811,7 @@ func (r *trustCenterResolver) HasAcceptedNonDisclosureAgreement(ctx context.Cont
|
||||
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
if tokenData != nil {
|
||||
hasAcceptedNDA, err := privateTrustService.TrustCenterAccesses.HasAcceptedNonDisclosureAgreement(ctx, obj.ID, tokenData.GetEmail())
|
||||
hasAcceptedNDA, err := privateTrustService.TrustCenterAccesses.HasAcceptedNonDisclosureAgreement(ctx, obj.ID, tokenData.Email)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot check if user has accepted NDA: %w", err))
|
||||
}
|
||||
@@ -947,7 +936,7 @@ func (r *trustCenterFileResolver) IsUserAuthorized(ctx context.Context, obj *typ
|
||||
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
if tokenData != nil {
|
||||
fileAccess, err := privateTrustService.TrustCenterAccesses.LoadTrustCenterFileAccess(ctx, tokenData.TrustCenterID, tokenData.GetEmail(), obj.ID)
|
||||
fileAccess, err := privateTrustService.TrustCenterAccesses.LoadTrustCenterFileAccess(ctx, tokenData.TrustCenterID, tokenData.Email, obj.ID)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
@@ -972,7 +961,7 @@ func (r *trustCenterFileResolver) HasUserRequestedAccess(ctx context.Context, ob
|
||||
|
||||
tokenData := TokenAccessFromContext(ctx)
|
||||
if tokenData != nil {
|
||||
_, err := privateTrustService.TrustCenterAccesses.LoadTrustCenterFileAccess(ctx, tokenData.TrustCenterID, tokenData.GetEmail(), obj.ID)
|
||||
_, err := privateTrustService.TrustCenterAccesses.LoadTrustCenterFileAccess(ctx, tokenData.TrustCenterID, tokenData.Email, obj.ID)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -87,9 +87,7 @@ func AcceptInvitationHandler(authSvc *authsvc.Service, authzSvc *authz.Service,
|
||||
return
|
||||
}
|
||||
|
||||
response := AcceptInvitationResponse{
|
||||
InvitationID: req.InvitationID,
|
||||
}
|
||||
response := AcceptInvitationResponse(req)
|
||||
|
||||
httpserver.RenderJSON(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
@@ -75,9 +75,7 @@ func DeleteUserAPIKeyHandler(authSvc *authsvc.Service) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
response := DeleteUserAPIKeyResponse{
|
||||
ID: req.ID,
|
||||
}
|
||||
response := DeleteUserAPIKeyResponse(req)
|
||||
|
||||
httpserver.RenderJSON(w, http.StatusOK, response)
|
||||
}
|
||||
|
||||
@@ -19,13 +19,14 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
authsvc "go.probo.inc/probo/pkg/auth"
|
||||
"go.gearno.de/kit/httpserver"
|
||||
authsvc "go.probo.inc/probo/pkg/auth"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
)
|
||||
|
||||
type (
|
||||
ForgetPasswordRequest struct {
|
||||
Email string `json:"email"`
|
||||
Email mail.Addr `json:"email"`
|
||||
}
|
||||
|
||||
ForgetPasswordResponse struct {
|
||||
|
||||
@@ -18,9 +18,10 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"go.gearno.de/kit/httpserver"
|
||||
"go.probo.inc/probo/pkg/authz"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.gearno.de/kit/httpserver"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -30,7 +31,7 @@ type (
|
||||
|
||||
InvitationResponse struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Email string `json:"email"`
|
||||
Email mail.Addr `json:"email"`
|
||||
FullName string `json:"fullName"`
|
||||
Role string `json:"role"`
|
||||
ExpiresAt string `json:"expiresAt"`
|
||||
|
||||
@@ -25,13 +25,14 @@ import (
|
||||
authsvc "go.probo.inc/probo/pkg/auth"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/securecookie"
|
||||
)
|
||||
|
||||
type (
|
||||
SignInRequest struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
Email mail.Addr `json:"email"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
SignInResponse struct {
|
||||
@@ -40,7 +41,7 @@ type (
|
||||
|
||||
UserResponse struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Email string `json:"email"`
|
||||
Email mail.Addr `json:"email"`
|
||||
FullName string `json:"fullName"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
|
||||
@@ -22,14 +22,15 @@ import (
|
||||
|
||||
"go.gearno.de/kit/httpserver"
|
||||
authsvc "go.probo.inc/probo/pkg/auth"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/securecookie"
|
||||
)
|
||||
|
||||
type (
|
||||
SignUpRequest struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
FullName string `json:"fullName"`
|
||||
Email mail.Addr `json:"email"`
|
||||
Password string `json:"password"`
|
||||
FullName string `json:"fullName"`
|
||||
}
|
||||
|
||||
SignUpResponse struct {
|
||||
|
||||
46
pkg/server/gqlutils/types/mail/addr.go
Normal file
46
pkg/server/gqlutils/types/mail/addr.go
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package mail
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
)
|
||||
|
||||
type AddrScalar = mail.Addr
|
||||
|
||||
func MarshalAddrScalar(a mail.Addr) graphql.Marshaler {
|
||||
return graphql.WriterFunc(func(w io.Writer) {
|
||||
w.Write([]byte(strconv.Quote(a.String())))
|
||||
})
|
||||
}
|
||||
|
||||
func UnmarshalAddrScalar(v interface{}) (mail.Addr, error) {
|
||||
s, ok := v.(string)
|
||||
if !ok {
|
||||
return mail.Nil, errors.New("must be a string")
|
||||
}
|
||||
|
||||
a, err := mail.ParseAddr(s)
|
||||
if err != nil {
|
||||
return mail.Nil, err
|
||||
}
|
||||
|
||||
return a, nil
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"go.probo.inc/probo/pkg/baseurl"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -101,7 +102,7 @@ func (s *SlackMessageService) UpdateSlackAccessMessage(
|
||||
ctx context.Context,
|
||||
slackMessageID gid.GID,
|
||||
responseURL string,
|
||||
requesterEmail string,
|
||||
requesterEmail mail.Addr,
|
||||
) error {
|
||||
return s.svc.pg.WithTx(ctx, func(tx pg.Conn) error {
|
||||
var slackMessage coredata.SlackMessage
|
||||
@@ -174,7 +175,7 @@ func (s *SlackMessageService) UpdateSlackAccessMessage(
|
||||
|
||||
func (s *SlackMessageService) QueueSlackNotification(
|
||||
ctx context.Context,
|
||||
requesterEmail string,
|
||||
requesterEmail mail.Addr,
|
||||
trustCenterID gid.GID,
|
||||
) error {
|
||||
return s.svc.pg.WithTx(ctx, func(tx pg.Conn) error {
|
||||
@@ -287,7 +288,7 @@ func (s *SlackMessageService) QueueSlackNotification(
|
||||
|
||||
func (s *SlackMessageService) QueueSlackAccessMessageUpdate(
|
||||
ctx context.Context,
|
||||
requesterEmail string,
|
||||
requesterEmail mail.Addr,
|
||||
trustCenterID gid.GID,
|
||||
) error {
|
||||
return s.svc.pg.WithTx(ctx, func(tx pg.Conn) error {
|
||||
@@ -461,7 +462,7 @@ func (s *SlackMessageService) loadDocumentsReportsAndFilesFromAccesses(
|
||||
func (s *SlackMessageService) buildAccessRequestMessage(
|
||||
slackMessageID gid.GID,
|
||||
requesterName string,
|
||||
requesterEmail string,
|
||||
requesterEmail mail.Addr,
|
||||
organizationID gid.GID,
|
||||
documents []SlackMessageDocument,
|
||||
reports []SlackMessageReport,
|
||||
@@ -483,7 +484,7 @@ func (s *SlackMessageService) buildAccessRequestMessage(
|
||||
Files []SlackMessageFile
|
||||
}{
|
||||
RequesterName: requesterName,
|
||||
RequesterEmail: requesterEmail,
|
||||
RequesterEmail: requesterEmail.String(),
|
||||
OrganizationID: organizationID.String(),
|
||||
Domain: base.Host(),
|
||||
SlackMessageID: slackMessageID.String(),
|
||||
|
||||
@@ -19,13 +19,14 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/docgen"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/html2pdf"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"go.probo.inc/probo/pkg/watermarkpdf"
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -88,7 +89,7 @@ func (s *DocumentService) ListForOrganizationId(
|
||||
func (s *DocumentService) ExportPDF(
|
||||
ctx context.Context,
|
||||
documentID gid.GID,
|
||||
email string,
|
||||
email mail.Addr,
|
||||
) ([]byte, error) {
|
||||
pdfData, err := s.exportPDFData(ctx, documentID)
|
||||
if err != nil {
|
||||
|
||||
@@ -22,10 +22,11 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/watermarkpdf"
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
|
||||
type ReportService struct {
|
||||
@@ -88,7 +89,7 @@ func (s ReportService) GenerateDownloadURL(
|
||||
func (s ReportService) ExportPDF(
|
||||
ctx context.Context,
|
||||
reportID gid.GID,
|
||||
email string,
|
||||
email mail.Addr,
|
||||
) ([]byte, error) {
|
||||
pdfData, err := s.exportPDFData(ctx, reportID)
|
||||
if err != nil {
|
||||
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/mail"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
@@ -29,6 +28,7 @@ import (
|
||||
"go.probo.inc/probo/pkg/auth"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/probo"
|
||||
"go.probo.inc/probo/pkg/statelesstoken"
|
||||
"go.probo.inc/probo/pkg/validator"
|
||||
@@ -43,7 +43,7 @@ type (
|
||||
|
||||
TrustCenterAccessRequest struct {
|
||||
TrustCenterID gid.GID
|
||||
Email string
|
||||
Email mail.Addr
|
||||
Name *string
|
||||
DocumentIDs []gid.GID
|
||||
ReportIDs []gid.GID
|
||||
@@ -66,7 +66,7 @@ func (tcar *TrustCenterAccessRequest) Validate() error {
|
||||
func (s TrustCenterAccessService) ValidateToken(
|
||||
ctx context.Context,
|
||||
trustCenterID gid.GID,
|
||||
email string,
|
||||
email mail.Addr,
|
||||
) error {
|
||||
return s.svc.pg.WithConn(ctx, func(conn pg.Conn) error {
|
||||
access := &coredata.TrustCenterAccess{}
|
||||
@@ -87,6 +87,10 @@ func (s TrustCenterAccessService) Request(
|
||||
ctx context.Context,
|
||||
req *TrustCenterAccessRequest,
|
||||
) (*coredata.TrustCenterAccess, error) {
|
||||
if err := req.Validate(); err != nil {
|
||||
return nil, fmt.Errorf("invalid request arguments")
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
|
||||
var access *coredata.TrustCenterAccess
|
||||
@@ -161,10 +165,6 @@ func (s TrustCenterAccessService) Request(
|
||||
return fmt.Errorf("name is required for new access requests")
|
||||
}
|
||||
|
||||
if _, err := mail.ParseAddress(req.Email); err != nil {
|
||||
return fmt.Errorf("invalid email address")
|
||||
}
|
||||
|
||||
access = &coredata.TrustCenterAccess{
|
||||
ID: gid.New(s.svc.scope.GetTenantID(), coredata.TrustCenterAccessEntityType),
|
||||
OrganizationID: organizationID,
|
||||
@@ -248,7 +248,7 @@ func (s TrustCenterAccessService) Request(
|
||||
return access, nil
|
||||
}
|
||||
|
||||
func (s TrustCenterAccessService) HasAcceptedNonDisclosureAgreement(ctx context.Context, trustCenterID gid.GID, email string) (bool, error) {
|
||||
func (s TrustCenterAccessService) HasAcceptedNonDisclosureAgreement(ctx context.Context, trustCenterID gid.GID, email mail.Addr) (bool, error) {
|
||||
access := &coredata.TrustCenterAccess{}
|
||||
err := s.svc.pg.WithConn(ctx, func(conn pg.Conn) error {
|
||||
err := access.LoadByTrustCenterIDAndEmail(ctx, conn, s.svc.scope, trustCenterID, email)
|
||||
@@ -266,7 +266,7 @@ func (s TrustCenterAccessService) HasAcceptedNonDisclosureAgreement(ctx context.
|
||||
return access.HasAcceptedNonDisclosureAgreement, nil
|
||||
}
|
||||
|
||||
func (s TrustCenterAccessService) AcceptNonDisclosureAgreement(ctx context.Context, trustCenterID gid.GID, email string) error {
|
||||
func (s TrustCenterAccessService) AcceptNonDisclosureAgreement(ctx context.Context, trustCenterID gid.GID, email mail.Addr) error {
|
||||
return s.svc.pg.WithTx(ctx, func(tx pg.Conn) error {
|
||||
access := &coredata.TrustCenterAccess{}
|
||||
if err := access.LoadByTrustCenterIDAndEmail(ctx, tx, s.svc.scope, trustCenterID, email); err != nil {
|
||||
@@ -279,7 +279,7 @@ func (s TrustCenterAccessService) AcceptNonDisclosureAgreement(ctx context.Conte
|
||||
}
|
||||
|
||||
acceptationLogs, err := json.Marshal(map[string]string{
|
||||
"email": email,
|
||||
"email": email.String(),
|
||||
"timestamp": time.Now().Format(time.RFC3339),
|
||||
"ip": ctx.Value(coredata.ContextKeyIPAddress).(string),
|
||||
})
|
||||
@@ -302,7 +302,7 @@ func (s TrustCenterAccessService) AcceptNonDisclosureAgreement(ctx context.Conte
|
||||
func (s TrustCenterAccessService) LoadDocumentAccess(
|
||||
ctx context.Context,
|
||||
trustCenterID gid.GID,
|
||||
email string,
|
||||
email mail.Addr,
|
||||
documentID gid.GID,
|
||||
) (*coredata.TrustCenterDocumentAccess, error) {
|
||||
var documentAccess *coredata.TrustCenterDocumentAccess
|
||||
@@ -337,7 +337,7 @@ func (s TrustCenterAccessService) LoadDocumentAccess(
|
||||
func (s TrustCenterAccessService) LoadReportAccess(
|
||||
ctx context.Context,
|
||||
trustCenterID gid.GID,
|
||||
email string,
|
||||
email mail.Addr,
|
||||
reportID gid.GID,
|
||||
) (*coredata.TrustCenterDocumentAccess, error) {
|
||||
var reportAccess *coredata.TrustCenterDocumentAccess
|
||||
@@ -372,7 +372,7 @@ func (s TrustCenterAccessService) LoadReportAccess(
|
||||
func (s TrustCenterAccessService) LoadTrustCenterFileAccess(
|
||||
ctx context.Context,
|
||||
trustCenterID gid.GID,
|
||||
email string,
|
||||
email mail.Addr,
|
||||
trustCenterFileID gid.GID,
|
||||
) (*coredata.TrustCenterDocumentAccess, error) {
|
||||
var fileAccess *coredata.TrustCenterDocumentAccess
|
||||
@@ -407,7 +407,7 @@ func (s TrustCenterAccessService) LoadTrustCenterFileAccess(
|
||||
func (s *TrustCenterAccessService) GrantByIDs(
|
||||
ctx context.Context,
|
||||
organizationID gid.GID,
|
||||
email string,
|
||||
email mail.Addr,
|
||||
documentIDs []gid.GID,
|
||||
reportIDs []gid.GID,
|
||||
fileIDs []gid.GID,
|
||||
@@ -533,7 +533,7 @@ func (s *TrustCenterAccessService) sendTrustCenterAccessEmail(
|
||||
ctx context.Context,
|
||||
tx pg.Conn,
|
||||
name string,
|
||||
email string,
|
||||
email mail.Addr,
|
||||
companyName string,
|
||||
accessURL string,
|
||||
) error {
|
||||
@@ -565,7 +565,7 @@ func (s *TrustCenterAccessService) sendTrustCenterAccessEmail(
|
||||
func (s *TrustCenterAccessService) RejectOrRevokeByIDs(
|
||||
ctx context.Context,
|
||||
organizationID gid.GID,
|
||||
email string,
|
||||
email mail.Addr,
|
||||
documentIDs []gid.GID,
|
||||
reportIDs []gid.GID,
|
||||
fileIDs []gid.GID,
|
||||
|
||||
@@ -21,11 +21,12 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"go.gearno.de/kit/pg"
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
"go.probo.inc/probo/pkg/watermarkpdf"
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
|
||||
type TrustCenterFileService struct {
|
||||
@@ -86,7 +87,7 @@ func (s *TrustCenterFileService) ListForOrganizationId(
|
||||
func (s *TrustCenterFileService) ExportFile(
|
||||
ctx context.Context,
|
||||
trustCenterFileID gid.GID,
|
||||
email string,
|
||||
email mail.Addr,
|
||||
) ([]byte, error) {
|
||||
pdfData, err := s.exportFileData(ctx, trustCenterFileID)
|
||||
if err != nil {
|
||||
|
||||
@@ -25,7 +25,7 @@ func BenchmarkValidate_SingleField(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v := New()
|
||||
v.Check(&email, "email", Required(), Email())
|
||||
v.Check(&email, "email", Required(), NotEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ func BenchmarkValidate_MultipleFields(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v := New()
|
||||
v.Check(&email, "email", Required(), Email())
|
||||
v.Check(&email, "email", Required(), NotEmpty())
|
||||
v.Check(&password, "password", Required(), MinLen(8))
|
||||
v.Check(&age, "age", Min(18), Max(120))
|
||||
}
|
||||
@@ -108,16 +108,6 @@ func BenchmarkValidate_ArrayValidation(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEmail(b *testing.B) {
|
||||
email := "test@example.com"
|
||||
validator := Email()
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = validator(&email)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkURL(b *testing.B) {
|
||||
urlStr := "https://example.com"
|
||||
validator := URL()
|
||||
@@ -214,7 +204,7 @@ func BenchmarkValidate_WithErrors(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v := New()
|
||||
v.Check(&email, "email", Required(), Email())
|
||||
v.Check(&email, "email", Required(), NotEmpty())
|
||||
if !v.HasErrors() {
|
||||
b.Fatal("expected validation error")
|
||||
}
|
||||
@@ -256,7 +246,7 @@ func BenchmarkValidate_ComplexForm(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v := New()
|
||||
v.Check(&user.Email, "email", Required(), Email())
|
||||
v.Check(&user.Email, "email", Required(), NotEmpty())
|
||||
v.Check(&user.Name, "name", Required(), MinLen(2))
|
||||
v.Check(&user.Age, "age", Min(18), Max(120))
|
||||
v.Check(user.Website, "website", URL())
|
||||
|
||||
@@ -19,13 +19,15 @@ import (
|
||||
"testing"
|
||||
|
||||
"go.gearno.de/x/ref"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
)
|
||||
|
||||
func TestValidator_Validate(t *testing.T) {
|
||||
t.Run("single field validation", func(t *testing.T) {
|
||||
v := New()
|
||||
email := "test@example.com"
|
||||
v.Check(&email, "email", Required(), Email())
|
||||
email := mail.Addr("test@example.com")
|
||||
|
||||
v.Check(&email, "email", Required(), NotEmpty())
|
||||
|
||||
if v.HasErrors() {
|
||||
t.Errorf("expected no errors, got: %v", v.Errors())
|
||||
@@ -34,10 +36,10 @@ func TestValidator_Validate(t *testing.T) {
|
||||
|
||||
t.Run("multiple field validations", func(t *testing.T) {
|
||||
v := New()
|
||||
email := ""
|
||||
email := mail.Nil
|
||||
password := "123"
|
||||
|
||||
v.Check(&email, "email", Required(), Email())
|
||||
v.Check(email, "email", NotEmpty())
|
||||
v.Check(&password, "password", Required(), MinLen(8))
|
||||
|
||||
if !v.HasErrors() {
|
||||
@@ -69,8 +71,8 @@ func TestValidator_CheckNested(t *testing.T) {
|
||||
v := New()
|
||||
|
||||
v.CheckNested("user", func(nv *Validator) {
|
||||
email := "invalid"
|
||||
nv.Check(&email, "email", Email())
|
||||
email := mail.Nil
|
||||
nv.Check(&email, "email", NotEmpty())
|
||||
|
||||
nv.CheckNested("address", func(av *Validator) {
|
||||
city := ""
|
||||
@@ -186,7 +188,7 @@ func TestOptionalFieldExample(t *testing.T) {
|
||||
|
||||
v := New()
|
||||
|
||||
v.Check(&req.Email, "email", Required(), Email())
|
||||
v.Check(&req.Email, "email", Required(), NotEmpty())
|
||||
v.Check(&req.Name, "name", Required(), MinLen(2))
|
||||
v.Check(req.Website, "website", URL())
|
||||
v.Check(req.PhoneNumber, "phoneNumber", MinLen(10))
|
||||
@@ -232,7 +234,7 @@ func TestRealWorldExample(t *testing.T) {
|
||||
}
|
||||
|
||||
user := User{
|
||||
Email: "invalid-email",
|
||||
Email: "",
|
||||
Password: "123",
|
||||
Age: 15,
|
||||
Website: ref.Ref("not-a-url"),
|
||||
@@ -245,7 +247,7 @@ func TestRealWorldExample(t *testing.T) {
|
||||
v := New()
|
||||
|
||||
// Validate user fields
|
||||
v.Check(&user.Email, "email", Required(), Email())
|
||||
v.Check(&user.Email, "email", Required(), NotEmpty())
|
||||
v.Check(&user.Password, "password", Required(), MinLen(8))
|
||||
v.Check(&user.Age, "age", Min(18), Max(120))
|
||||
v.Check(user.Website, "website", URL())
|
||||
@@ -262,7 +264,7 @@ func TestRealWorldExample(t *testing.T) {
|
||||
|
||||
errors := v.Errors()
|
||||
expectedErrors := map[string]ErrorCode{
|
||||
"email": ErrorCodeInvalidEmail,
|
||||
"email": ErrorCodeRequired,
|
||||
"password": ErrorCodeTooShort,
|
||||
"age": ErrorCodeOutOfRange,
|
||||
"website": ErrorCodeInvalidURL,
|
||||
@@ -373,10 +375,10 @@ func TestDuplicateValidators(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("duplicate Email creates two errors", func(t *testing.T) {
|
||||
t.Run("duplicate NotEmpty creates two errors", func(t *testing.T) {
|
||||
v := New()
|
||||
email := "invalid"
|
||||
v.Check(&email, "email", Email(), Email())
|
||||
email := mail.Nil
|
||||
v.Check(&email, "email", NotEmpty(), NotEmpty())
|
||||
|
||||
errors := v.Errors()
|
||||
if len(errors) != 2 {
|
||||
@@ -405,22 +407,23 @@ func TestDuplicateValidators(t *testing.T) {
|
||||
|
||||
func TestStandardErrorPattern(t *testing.T) {
|
||||
// Simulates a typical validation function
|
||||
validateUser := func(email, password string) error {
|
||||
validateUser := func(email mail.Addr, password string) error {
|
||||
v := New()
|
||||
v.Check(&email, "email", Required(), Email())
|
||||
v.Check(&email, "email", Required(), NotEmpty())
|
||||
v.Check(&password, "password", Required(), MinLen(8))
|
||||
return v.Error()
|
||||
}
|
||||
|
||||
t.Run("valid data returns nil", func(t *testing.T) {
|
||||
err := validateUser("user@example.com", "password123")
|
||||
if err != nil {
|
||||
email := mail.Addr("user@example.com")
|
||||
|
||||
if err := validateUser(email, "password123"); err != nil {
|
||||
t.Errorf("expected nil, got: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("invalid data returns ValidationErrors as error", func(t *testing.T) {
|
||||
err := validateUser("", "123")
|
||||
err := validateUser(mail.Nil, "123")
|
||||
if err == nil {
|
||||
t.Fatal("expected validation errors")
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ package validator
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
)
|
||||
|
||||
// Required validates that a field has a value.
|
||||
@@ -59,6 +61,10 @@ func NotEmpty() ValidatorFunc {
|
||||
if strings.TrimSpace(v) == "" {
|
||||
return newValidationError(ErrorCodeRequired, "field cannot be empty")
|
||||
}
|
||||
case mail.Addr:
|
||||
if v == mail.Nil {
|
||||
return newValidationError(ErrorCodeRequired, "field cannot be empty")
|
||||
}
|
||||
default:
|
||||
rv := reflect.ValueOf(actualValue)
|
||||
if rv.Kind() == reflect.Slice && rv.Len() == 0 {
|
||||
|
||||
@@ -23,36 +23,10 @@ import (
|
||||
|
||||
var (
|
||||
emailRegex = regexp.MustCompile(`^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$`)
|
||||
gidRegex = regexp.MustCompile(`^gid://[a-zA-Z0-9\-_]+/[a-zA-Z0-9\-_]+/[a-zA-Z0-9\-_]+$`)
|
||||
uuidRegex = regexp.MustCompile(`^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$`)
|
||||
domainRegex = regexp.MustCompile(`^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)*[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$`)
|
||||
)
|
||||
|
||||
// Email validates that a string is a valid email address.
|
||||
func Email() ValidatorFunc {
|
||||
return func(value any) *ValidationError {
|
||||
actualValue, isNil := dereferenceValue(value)
|
||||
if isNil {
|
||||
return nil
|
||||
}
|
||||
|
||||
str, ok := actualValue.(string)
|
||||
if !ok {
|
||||
return newValidationError(ErrorCodeInvalidEmail, "value must be a string")
|
||||
}
|
||||
|
||||
if str == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !emailRegex.MatchString(str) {
|
||||
return newValidationError(ErrorCodeInvalidEmail, "invalid email address")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// URL validates that a string is a valid URL with http or https scheme.
|
||||
func URL() ValidatorFunc {
|
||||
return func(value any) *ValidationError {
|
||||
|
||||
@@ -21,35 +21,6 @@ import (
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
)
|
||||
|
||||
func TestEmail(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
value any
|
||||
wantError bool
|
||||
}{
|
||||
{"valid email", "test@example.com", false},
|
||||
{"valid email with plus", "test+tag@example.com", false},
|
||||
{"invalid email no @", "testexample.com", true},
|
||||
{"invalid email no domain", "test@", true},
|
||||
{"invalid email no TLD", "test@example", true},
|
||||
{"empty string", "", false}, // Empty is allowed, use Required() to enforce
|
||||
{"nil pointer", (*string)(nil), false}, // Skip validation
|
||||
{"non-string", 123, true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := Email()(tt.value)
|
||||
if (err != nil) != tt.wantError {
|
||||
t.Errorf("Email() error = %v, wantError %v", err, tt.wantError)
|
||||
}
|
||||
if err != nil && err.Code != ErrorCodeInvalidEmail {
|
||||
t.Errorf("Expected error code %s, got %s", ErrorCodeInvalidEmail, err.Code)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestURL(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
|
||||
"github.com/pdfcpu/pdfcpu/pkg/api"
|
||||
"github.com/pdfcpu/pdfcpu/pkg/pdfcpu/types"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"golang.org/x/image/font"
|
||||
"golang.org/x/image/font/gofont/goregular"
|
||||
"golang.org/x/image/font/opentype"
|
||||
@@ -46,12 +47,12 @@ var (
|
||||
fontColor = color.RGBA{0, 0, 0, 255}
|
||||
)
|
||||
|
||||
func AddConfidentialWithTimestamp(pdfData []byte, email string) ([]byte, error) {
|
||||
func AddConfidentialWithTimestamp(pdfData []byte, email mail.Addr) ([]byte, error) {
|
||||
reader := bytes.NewReader(pdfData)
|
||||
|
||||
watermarkLines := []string{
|
||||
"Confidential",
|
||||
email,
|
||||
email.String(),
|
||||
time.Now().Format("2006-01-02"),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user