@contember/engine-tenant-api 2.0.2 → 2.1.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/development/index.cjs +1 -0
- package/dist/development/index.cjs.map +1 -1
- package/dist/development/index.js +2 -1
- package/dist/development/src/model/mailing/UserMailer.cjs +18 -12
- package/dist/development/src/model/mailing/UserMailer.cjs.map +1 -1
- package/dist/development/src/model/mailing/UserMailer.js +18 -12
- package/dist/development/src/model/mailing/UserMailer.js.map +1 -1
- package/dist/development/src/model/service/InviteManager.cjs +2 -2
- package/dist/development/src/model/service/InviteManager.cjs.map +1 -1
- package/dist/development/src/model/service/InviteManager.js +2 -2
- package/dist/development/src/model/service/InviteManager.js.map +1 -1
- package/dist/development/src/utils/Mailer.cjs +29 -1
- package/dist/development/src/utils/Mailer.cjs.map +1 -1
- package/dist/development/src/utils/Mailer.js +29 -1
- package/dist/development/src/utils/Mailer.js.map +1 -1
- package/dist/production/index.cjs +1 -0
- package/dist/production/index.cjs.map +1 -1
- package/dist/production/index.js +2 -1
- package/dist/production/src/model/mailing/UserMailer.cjs +18 -12
- package/dist/production/src/model/mailing/UserMailer.cjs.map +1 -1
- package/dist/production/src/model/mailing/UserMailer.js +18 -12
- package/dist/production/src/model/mailing/UserMailer.js.map +1 -1
- package/dist/production/src/model/service/InviteManager.cjs +2 -2
- package/dist/production/src/model/service/InviteManager.cjs.map +1 -1
- package/dist/production/src/model/service/InviteManager.js +2 -2
- package/dist/production/src/model/service/InviteManager.js.map +1 -1
- package/dist/production/src/utils/Mailer.cjs +29 -1
- package/dist/production/src/utils/Mailer.cjs.map +1 -1
- package/dist/production/src/utils/Mailer.js +29 -1
- package/dist/production/src/utils/Mailer.js.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/addProjectMember.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/changeMyPassword.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/changeMyProfile.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/changePassword.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/changeProfile.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/confirmOtp.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/createApiKey.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/createResetPasswordRequest.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/createSessionToken.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/invite.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/prepareOtp.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/resetPassword.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/signIn.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/signInIdp.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/signUp.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/unmanagedInvite.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/gql/updateProjectMember.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/createApiKeySql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/createIdentitySql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/createMembershipSql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/createMembershipVariableSql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/createPersonSql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/createPersonTokenSql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/createSessionKeySql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/disableApiKeySql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/disableOneOffKeySql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/getApiKeySql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/getIdentityProjectsSql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/getIdpBySlugSql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/getMailTemplateSql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/getPersonByEmailSql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/getPersonByIdSql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/getPersonByIdentity.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/getPersonByIdpSql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/getProjectBySlugSql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/getProjectMembershipSql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/patchVariablesSql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/selectMembershipsSql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/sqlTransaction.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/updatePesonNameSql.d.ts.map +1 -1
- package/dist/tests/cases/integration/mocked/sql/updatePesonPasswordSql.d.ts.map +1 -1
- package/dist/tests/src/dbUtils.d.ts.map +1 -1
- package/dist/tests/src/tags.d.ts.map +1 -1
- package/dist/tests/src/testGraphql.d.ts.map +1 -1
- package/dist/tests/src/testTenant.d.ts.map +1 -1
- package/dist/tests/src/testUuid.d.ts.map +1 -1
- package/dist/tests/tsconfig.tsbuildinfo +1 -1
- package/dist/types/bridges/system/IdentityFetcher.d.ts.map +1 -1
- package/dist/types/migrations/snapshot-factory.d.ts.map +1 -1
- package/dist/types/migrations/tenantCredentials.d.ts.map +1 -1
- package/dist/types/model/authorization/PermissionActions.d.ts.map +1 -1
- package/dist/types/model/mailing/UserMailer.d.ts +4 -1
- package/dist/types/model/mailing/UserMailer.d.ts.map +1 -1
- package/dist/types/model/mailing/templates/Layout.mustache.d.ts.map +1 -1
- package/dist/types/model/mailing/type.d.ts.map +1 -1
- package/dist/types/model/queries/idp/helpers.d.ts.map +1 -1
- package/dist/types/model/queries/membership/ProjectSlugSpecification.d.ts.map +1 -1
- package/dist/types/model/service/helpers/getPreferredProject.d.ts.map +1 -1
- package/dist/types/model/service/idp/providers/OIDCHelpers.d.ts.map +1 -1
- package/dist/types/model/service/idp/providers/helpers.d.ts.map +1 -1
- package/dist/types/model/service/membershipUtils.d.ts.map +1 -1
- package/dist/types/model/utils/email.d.ts.map +1 -1
- package/dist/types/model/utils/password.d.ts.map +1 -1
- package/dist/types/model/utils/time.d.ts.map +1 -1
- package/dist/types/model/utils/tokenUtils.d.ts.map +1 -1
- package/dist/types/model/utils/typeUtils.d.ts.map +1 -1
- package/dist/types/resolvers/TenantResolverContextFactory.d.ts.map +1 -1
- package/dist/types/resolvers/errorUtils.d.ts.map +1 -1
- package/dist/types/resolvers/membershipUtils.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dist/types/utils/Mailer.d.ts +24 -4
- package/dist/types/utils/Mailer.d.ts.map +1 -1
- package/dist/types/utils/array.d.ts.map +1 -1
- package/dist/types/utils/batchQuery.d.ts +1 -1
- package/dist/types/utils/batchQuery.d.ts.map +1 -1
- package/package.json +13 -13
- package/src/model/mailing/UserMailer.ts +23 -15
- package/src/model/service/InviteManager.ts +2 -2
- package/src/utils/Mailer.ts +56 -6
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { Transporter, TransportOptions } from 'nodemailer';
|
|
2
|
-
import { Options as MailMessage } from 'nodemailer/lib/mailer';
|
|
3
2
|
import * as SMTPTransport from 'nodemailer/lib/smtp-transport';
|
|
4
3
|
import * as SMTPPool from 'nodemailer/lib/smtp-pool';
|
|
5
4
|
import * as SendmailTransport from 'nodemailer/lib/sendmail-transport';
|
|
6
5
|
import * as SESTransport from 'nodemailer/lib/ses-transport';
|
|
7
|
-
|
|
6
|
+
import { MailTemplateIdentifier } from '../model';
|
|
7
|
+
export interface MailMessage {
|
|
8
|
+
to: string;
|
|
9
|
+
subject: string;
|
|
10
|
+
html: string;
|
|
11
|
+
from?: string;
|
|
12
|
+
replyTo?: string;
|
|
13
|
+
variables?: Record<string, any>;
|
|
14
|
+
template?: MailTemplateIdentifier;
|
|
15
|
+
}
|
|
8
16
|
export interface SentInfo {
|
|
9
17
|
error?: any;
|
|
10
18
|
messageId?: string;
|
|
@@ -13,9 +21,14 @@ export interface SentInfo {
|
|
|
13
21
|
rejected?: string[];
|
|
14
22
|
pending?: string[];
|
|
15
23
|
}
|
|
16
|
-
export type MailerOptions =
|
|
24
|
+
export type MailerOptions = (SMTPTransport.Options | SMTPPool.Options | SendmailTransport.Options | SESTransport.Options | TransportOptions | {
|
|
25
|
+
webhook: string | {
|
|
26
|
+
url: string;
|
|
27
|
+
headers?: Record<string, string>;
|
|
28
|
+
};
|
|
29
|
+
}) & {
|
|
17
30
|
from?: string;
|
|
18
|
-
}
|
|
31
|
+
};
|
|
19
32
|
export interface Mailer {
|
|
20
33
|
send(message: MailMessage): Promise<SentInfo>;
|
|
21
34
|
}
|
|
@@ -23,6 +36,13 @@ export declare class NodeMailer implements Mailer {
|
|
|
23
36
|
private readonly from;
|
|
24
37
|
private readonly transport;
|
|
25
38
|
constructor(from: string | undefined, transport: Transporter);
|
|
39
|
+
send({ variables, template, ...message }: MailMessage): Promise<SentInfo>;
|
|
40
|
+
}
|
|
41
|
+
export declare class WebhookMailer implements Mailer {
|
|
42
|
+
private readonly from;
|
|
43
|
+
private readonly url;
|
|
44
|
+
private readonly headers;
|
|
45
|
+
constructor(from: string | undefined, url: string, headers?: Record<string, string>);
|
|
26
46
|
send(message: MailMessage): Promise<SentInfo>;
|
|
27
47
|
}
|
|
28
48
|
export declare const createMailer: (options: MailerOptions) => Mailer;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Mailer.d.ts","sourceRoot":"","sources":["../../../src/utils/Mailer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC3E,OAAO,
|
|
1
|
+
{"version":3,"file":"Mailer.d.ts","sourceRoot":"","sources":["../../../src/utils/Mailer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC3E,OAAO,KAAK,aAAa,MAAM,+BAA+B,CAAA;AAC9D,OAAO,KAAK,QAAQ,MAAM,0BAA0B,CAAA;AACpD,OAAO,KAAK,iBAAiB,MAAM,mCAAmC,CAAA;AACtE,OAAO,KAAK,YAAY,MAAM,8BAA8B,CAAA;AAE5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAEjD,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC/B,QAAQ,CAAC,EAAE,sBAAsB,CAAA;CACjC;AAED,MAAM,WAAW,QAAQ;IACxB,KAAK,CAAC,EAAE,GAAG,CAAA;IACX,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,GAAG,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,MAAM,MAAM,aAAa,GACtB,CACD,aAAa,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,GAAG,iBAAiB,CAAC,OAAO,GAAG,YAAY,CAAC,OAAO,GAAG,gBAAgB,GAC5G;IACD,OAAO,EAAE,MAAM,GAAG;QACjB,GAAG,EAAE,MAAM,CAAA;QACX,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAChC,CAAA;CACD,CACD,GACC;IACD,IAAI,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAGF,MAAM,WAAW,MAAM;IACtB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CAC7C;AAED,qBAAa,UAAW,YAAW,MAAM;IAC5B,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAsB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAApD,IAAI,EAAE,MAAM,GAAG,SAAS,EAAmB,SAAS,EAAE,WAAW;IAEjF,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC;CAQtF;AAED,qBAAa,aAAc,YAAW,MAAM;IAG1C,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAFP,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;IAIzC,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC;CAgB1D;AAGD,eAAO,MAAM,YAAY,GAAI,SAAS,aAAa,KAAG,MAQrD,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../../src/utils/array.ts"],"names":[],"mappings":"AAAA,wBAAgB,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,IAAI,MAAM,CAElF;AAED,KAAK,UAAU,CAAC,CAAC,EAAE,CAAC,IAAI;KACtB,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,KAAK;CAC1C,CAAC,MAAM,CAAC,CAAC,CAAA;AAEV,eAAO,MAAM,WAAW,GAAI,IAAI,EAAE,GAAG,SAAS,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,KAAK,SAAS,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../../src/utils/array.ts"],"names":[],"mappings":"AAAA,wBAAgB,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,IAAI,MAAM,CAElF;AAED,KAAK,UAAU,CAAC,CAAC,EAAE,CAAC,IAAI;KACtB,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,KAAK;CAC1C,CAAC,MAAM,CAAC,CAAC,CAAA;AAEV,eAAO,MAAM,WAAW,GAAI,IAAI,EAAE,GAAG,SAAS,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,KAAK,SAAS,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,EACvG,OAAO,IAAI,EAAE,EACb,KAAK,GAAG,KACN,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,CAQtB,CAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DatabaseContext } from '../model';
|
|
2
2
|
export type ItemLoader<Arg, Item> = (args: Arg) => Promise<Item>;
|
|
3
3
|
export type BatchLoaderArgs<Arg, Result, Item> = [createResult: (args: Arg[], db: DatabaseContext) => Promise<Result>, getItem: (arg: Arg, result: Result) => Item];
|
|
4
|
-
export declare const batchLoader: <Arg, Result, Item>(
|
|
4
|
+
export declare const batchLoader: <Arg, Result, Item>(...args: BatchLoaderArgs<Arg, Result, Item>) => BatchLoaderArgs<Arg, Result, Item>;
|
|
5
5
|
export declare const initBatchLoader: <Arg, Result, Item>([createResult, getItem]: BatchLoaderArgs<Arg, Result, Item>, db: DatabaseContext) => ItemLoader<Arg, Item>;
|
|
6
6
|
//# sourceMappingURL=batchQuery.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batchQuery.d.ts","sourceRoot":"","sources":["../../../src/utils/batchQuery.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAE1C,MAAM,MAAM,UAAU,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAEhE,MAAM,MAAM,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,eAAe,KAAK,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC,CAAA;AACnK,eAAO,MAAM,WAAW,GAAI,GAAG,EAAE,MAAM,EAAE,IAAI,
|
|
1
|
+
{"version":3,"file":"batchQuery.d.ts","sourceRoot":"","sources":["../../../src/utils/batchQuery.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAE1C,MAAM,MAAM,UAAU,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAEhE,MAAM,MAAM,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,eAAe,KAAK,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC,CAAA;AACnK,eAAO,MAAM,WAAW,GAAI,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,uCAAS,CAAA;AAEnG,eAAO,MAAM,eAAe,GAAI,GAAG,EAAE,MAAM,EAAE,IAAI,EAChD,yBAAyB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAC3D,IAAI,eAAe,KACjB,UAAU,CAAC,GAAG,EAAE,IAAI,CAiBtB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contember/engine-tenant-api",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.1.0-alpha.10",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "./dist/production/index.js",
|
|
6
6
|
"typings": "./dist/types/index.d.ts",
|
|
@@ -26,16 +26,16 @@
|
|
|
26
26
|
"generate": "gql-gen --config graphql.codegen.yml"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@contember/authorization": "2.0.
|
|
30
|
-
"@contember/config-loader": "2.0.
|
|
31
|
-
"@contember/database": "2.0.
|
|
32
|
-
"@contember/database-migrations": "2.0.
|
|
33
|
-
"@contember/dic": "2.0.
|
|
34
|
-
"@contember/graphql-utils": "2.0.
|
|
35
|
-
"@contember/logger": "2.0.
|
|
36
|
-
"@contember/schema": "2.0.
|
|
37
|
-
"@contember/schema-utils": "2.0.
|
|
38
|
-
"@contember/typesafe": "2.0.
|
|
29
|
+
"@contember/authorization": "2.1.0-alpha.10",
|
|
30
|
+
"@contember/config-loader": "2.1.0-alpha.10",
|
|
31
|
+
"@contember/database": "2.1.0-alpha.10",
|
|
32
|
+
"@contember/database-migrations": "2.1.0-alpha.10",
|
|
33
|
+
"@contember/dic": "2.1.0-alpha.10",
|
|
34
|
+
"@contember/graphql-utils": "2.1.0-alpha.10",
|
|
35
|
+
"@contember/logger": "2.1.0-alpha.10",
|
|
36
|
+
"@contember/schema": "2.1.0-alpha.10",
|
|
37
|
+
"@contember/schema-utils": "2.1.0-alpha.10",
|
|
38
|
+
"@contember/typesafe": "2.1.0-alpha.10",
|
|
39
39
|
"@graphql-tools/utils": "^10.5.5",
|
|
40
40
|
"graphql-tag": "^2.12.6",
|
|
41
41
|
"jose": "^5.8.0",
|
|
@@ -45,10 +45,10 @@
|
|
|
45
45
|
"otpauth": "^9.3.4"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@contember/database-tester": "2.0.
|
|
48
|
+
"@contember/database-tester": "2.1.0-alpha.10",
|
|
49
49
|
"@graphql-tools/schema": "^10.0.7",
|
|
50
50
|
"@types/mustache": "^4.2.5",
|
|
51
|
-
"@types/node": "^20.
|
|
51
|
+
"@types/node": "^20.17.22",
|
|
52
52
|
"@types/nodemailer": "^6.4.16",
|
|
53
53
|
"graphql": "^16.9.0"
|
|
54
54
|
},
|
|
@@ -7,6 +7,7 @@ import { MailTemplateData, MailTemplateIdentifier, MailType } from './type'
|
|
|
7
7
|
import { MailTemplateQuery } from '../queries'
|
|
8
8
|
import Layout from './templates/Layout.mustache'
|
|
9
9
|
import { DatabaseContext } from '../utils'
|
|
10
|
+
import { Acl } from '@contember/schema'
|
|
10
11
|
|
|
11
12
|
export class UserMailer {
|
|
12
13
|
constructor(
|
|
@@ -16,28 +17,30 @@ export class UserMailer {
|
|
|
16
17
|
|
|
17
18
|
async sendNewUserInvitedMail(
|
|
18
19
|
dbContext: DatabaseContext,
|
|
19
|
-
mailArguments: { email: string; password: string | null; token: string | null; project: string; projectSlug: string },
|
|
20
|
+
mailArguments: { email: string; password: string | null; token: string | null; project: string; projectSlug: string; memberships: readonly Acl.Membership[]},
|
|
20
21
|
customMailOptions: { projectId: string; variant: string },
|
|
21
22
|
): Promise<void> {
|
|
22
|
-
const
|
|
23
|
+
const templateId = { type: MailType.newUserInvited, ...customMailOptions }
|
|
24
|
+
const template = (await this.getCustomTemplate(dbContext, templateId)) || {
|
|
23
25
|
subject: 'You have been invited to {{project}}',
|
|
24
26
|
content: NewUserInvited,
|
|
25
27
|
replyTo: null,
|
|
26
28
|
}
|
|
27
|
-
await this.
|
|
29
|
+
await this.sendMail(templateId, template, mailArguments)
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
async sendExistingUserInvitedEmail(
|
|
31
33
|
dbContext: DatabaseContext,
|
|
32
|
-
mailArguments: { email: string; project: string; projectSlug: string },
|
|
34
|
+
mailArguments: { email: string; project: string; projectSlug: string; memberships: readonly Acl.Membership[] },
|
|
33
35
|
customMailOptions: { projectId: string; variant: string },
|
|
34
36
|
): Promise<void> {
|
|
35
|
-
const
|
|
37
|
+
const templateId = { type: MailType.existingUserInvited, ...customMailOptions }
|
|
38
|
+
const template = (await this.getCustomTemplate(dbContext, templateId)) || {
|
|
36
39
|
subject: 'You have been invited to {{project}}',
|
|
37
40
|
content: ExistingUserInvited,
|
|
38
41
|
replyTo: null,
|
|
39
42
|
}
|
|
40
|
-
await this.
|
|
43
|
+
await this.sendMail(templateId, template, mailArguments)
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
async sendPasswordResetEmail(
|
|
@@ -45,12 +48,13 @@ export class UserMailer {
|
|
|
45
48
|
mailArguments: { email: string; token: string; project?: string; projectSlug?: string },
|
|
46
49
|
customMailOptions: { projectId: string | null; variant: string },
|
|
47
50
|
): Promise<void> {
|
|
48
|
-
const
|
|
51
|
+
const templateId = { type: MailType.passwordReset, ...customMailOptions }
|
|
52
|
+
const template = (await this.getCustomTemplate(dbContext, templateId)) || {
|
|
49
53
|
subject: 'Password reset',
|
|
50
54
|
content: PasswordReset,
|
|
51
55
|
replyTo: null,
|
|
52
56
|
}
|
|
53
|
-
await this.
|
|
57
|
+
await this.sendMail(templateId, template, mailArguments)
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
async sendPasswordlessEmail(
|
|
@@ -58,23 +62,27 @@ export class UserMailer {
|
|
|
58
62
|
mailArguments: { email: string; token: string; project?: string; projectSlug?: string; url?: string },
|
|
59
63
|
customMailOptions: { projectId: string | null; variant: string },
|
|
60
64
|
): Promise<void> {
|
|
61
|
-
const
|
|
65
|
+
const templateId = { type: MailType.passwordlessSignIn, ...customMailOptions }
|
|
66
|
+
const template = (await this.getCustomTemplate(dbContext, templateId)) || {
|
|
62
67
|
subject: 'Sign in here',
|
|
63
68
|
content: PasswordlessSignIn,
|
|
64
69
|
replyTo: null,
|
|
65
70
|
}
|
|
66
|
-
await this.
|
|
71
|
+
await this.sendMail(templateId, template, mailArguments)
|
|
67
72
|
}
|
|
68
73
|
|
|
69
|
-
private async
|
|
74
|
+
private async sendMail(
|
|
75
|
+
templateId: MailTemplateIdentifier,
|
|
70
76
|
template: Pick<MailTemplateData, 'subject' | 'content' | 'replyTo'>,
|
|
71
|
-
|
|
77
|
+
variables: Record<string, any>,
|
|
72
78
|
) {
|
|
73
|
-
const html = await this.templateRenderer.render(template.content,
|
|
79
|
+
const html = await this.templateRenderer.render(template.content, variables)
|
|
74
80
|
await this.mailer.send({
|
|
75
|
-
to:
|
|
76
|
-
subject: await this.templateRenderer.render(template.subject,
|
|
81
|
+
to: variables.email,
|
|
82
|
+
subject: await this.templateRenderer.render(template.subject, variables),
|
|
77
83
|
html,
|
|
84
|
+
variables,
|
|
85
|
+
template: templateId,
|
|
78
86
|
...(template.replyTo ? {
|
|
79
87
|
replyTo: template.replyTo,
|
|
80
88
|
} : {}),
|
|
@@ -93,11 +93,11 @@ export class InviteManager {
|
|
|
93
93
|
if (isNew) {
|
|
94
94
|
await this.mailer.sendNewUserInvitedMail(
|
|
95
95
|
trx,
|
|
96
|
-
{ email, project: project.name, projectSlug: project.slug, password: generatedPassword, token: resetToken },
|
|
96
|
+
{ email, project: project.name, projectSlug: project.slug, password: generatedPassword, token: resetToken, memberships },
|
|
97
97
|
customMailOptions,
|
|
98
98
|
)
|
|
99
99
|
} else {
|
|
100
|
-
await this.mailer.sendExistingUserInvitedEmail(trx, { email, project: project.name, projectSlug: project.slug }, customMailOptions)
|
|
100
|
+
await this.mailer.sendExistingUserInvitedEmail(trx, { email, project: project.name, projectSlug: project.slug, memberships }, customMailOptions)
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
return new ResponseOk(new InviteResult(person, isNew))
|
package/src/utils/Mailer.ts
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import { createTransport, Transporter, TransportOptions } from 'nodemailer'
|
|
2
|
-
import { Options as MailMessage } from 'nodemailer/lib/mailer'
|
|
3
2
|
import * as SMTPTransport from 'nodemailer/lib/smtp-transport'
|
|
4
3
|
import * as SMTPPool from 'nodemailer/lib/smtp-pool'
|
|
5
4
|
import * as SendmailTransport from 'nodemailer/lib/sendmail-transport'
|
|
6
5
|
import * as SESTransport from 'nodemailer/lib/ses-transport'
|
|
7
6
|
import { logger } from '@contember/logger'
|
|
7
|
+
import { MailTemplateIdentifier } from '../model'
|
|
8
8
|
|
|
9
|
-
export
|
|
9
|
+
export interface MailMessage {
|
|
10
|
+
to: string
|
|
11
|
+
subject: string
|
|
12
|
+
html: string
|
|
13
|
+
from?: string
|
|
14
|
+
replyTo?: string
|
|
15
|
+
variables?: Record<string, any>
|
|
16
|
+
template?: MailTemplateIdentifier
|
|
17
|
+
}
|
|
10
18
|
|
|
11
19
|
export interface SentInfo {
|
|
12
20
|
error?: any
|
|
@@ -17,11 +25,20 @@ export interface SentInfo {
|
|
|
17
25
|
pending?: string[]
|
|
18
26
|
}
|
|
19
27
|
|
|
20
|
-
export type MailerOptions =
|
|
21
|
-
|
|
28
|
+
export type MailerOptions =
|
|
29
|
+
& (
|
|
30
|
+
SMTPTransport.Options | SMTPPool.Options | SendmailTransport.Options | SESTransport.Options | TransportOptions
|
|
31
|
+
| {
|
|
32
|
+
webhook: string | {
|
|
33
|
+
url: string
|
|
34
|
+
headers?: Record<string, string>
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
& {
|
|
22
39
|
from?: string
|
|
23
40
|
}
|
|
24
|
-
|
|
41
|
+
|
|
25
42
|
|
|
26
43
|
export interface Mailer {
|
|
27
44
|
send(message: MailMessage): Promise<SentInfo>
|
|
@@ -30,7 +47,7 @@ export interface Mailer {
|
|
|
30
47
|
export class NodeMailer implements Mailer {
|
|
31
48
|
constructor(private readonly from: string | undefined, private readonly transport: Transporter) {}
|
|
32
49
|
|
|
33
|
-
public async send(message: MailMessage): Promise<SentInfo> {
|
|
50
|
+
public async send({ variables, template, ...message }: MailMessage): Promise<SentInfo> {
|
|
34
51
|
try {
|
|
35
52
|
return await this.transport.sendMail({ ...message, from: message.from || this.from })
|
|
36
53
|
} catch (e) {
|
|
@@ -40,7 +57,40 @@ export class NodeMailer implements Mailer {
|
|
|
40
57
|
}
|
|
41
58
|
}
|
|
42
59
|
|
|
60
|
+
export class WebhookMailer implements Mailer {
|
|
61
|
+
|
|
62
|
+
constructor(
|
|
63
|
+
private readonly from: string | undefined,
|
|
64
|
+
private readonly url: string,
|
|
65
|
+
private readonly headers: Record<string, string> = {},
|
|
66
|
+
) {
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public async send(message: MailMessage): Promise<SentInfo> {
|
|
70
|
+
const response = await fetch(this.url, {
|
|
71
|
+
method: 'POST',
|
|
72
|
+
body: JSON.stringify({ ...message, from: message.from || this.from }),
|
|
73
|
+
headers: {
|
|
74
|
+
...this.headers,
|
|
75
|
+
'Content-Type': 'application/json',
|
|
76
|
+
},
|
|
77
|
+
})
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
logger.error('Mail sending failed', { mail: message, response })
|
|
80
|
+
return { error: response.statusText }
|
|
81
|
+
}
|
|
82
|
+
await response.text()
|
|
83
|
+
return {}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
|
|
43
88
|
export const createMailer = (options: MailerOptions): Mailer => {
|
|
44
89
|
const { from, ...transportOptions } = options
|
|
90
|
+
if ('webhook' in transportOptions) {
|
|
91
|
+
const config = typeof transportOptions.webhook === 'string' ? { url: transportOptions.webhook } : transportOptions.webhook
|
|
92
|
+
return new WebhookMailer(from, config.url, config.headers)
|
|
93
|
+
}
|
|
94
|
+
|
|
45
95
|
return new NodeMailer(from, createTransport(transportOptions as any))
|
|
46
96
|
}
|