@aglyn/plugins-marketing 1.0.0-beta.287 → 1.0.0-beta.289
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/package.json +16 -16
- package/src/lib/declarations.d.ts +25 -0
- package/src/lib/declarations.js +36 -0
- package/src/lib/declarations.js.map +1 -0
- package/src/lib/model/marketing-permissions.d.ts +26 -0
- package/src/lib/model/marketing-permissions.js +42 -0
- package/src/lib/model/marketing-permissions.js.map +1 -0
- package/src/lib/server/campaign-manage.d.ts +2 -4
- package/src/lib/server/campaign-manage.js +16 -21
- package/src/lib/server/campaign-manage.js.map +1 -1
- package/src/lib/server/campaign-recipients.js +7 -5
- package/src/lib/server/campaign-recipients.js.map +1 -1
- package/src/lib/server/campaign-send.js +7 -4
- package/src/lib/server/campaign-send.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aglyn/plugins-marketing",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.289",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://aglyn.com",
|
|
6
6
|
"repository": {
|
|
@@ -25,21 +25,21 @@
|
|
|
25
25
|
"./package.json": "./package.json"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@aglyn/aglyn": "1.0.0-beta.
|
|
29
|
-
"@aglyn/shared-data-enums": "1.0.0-beta.
|
|
30
|
-
"@aglyn/shared-data-mdi": "1.0.0-beta.
|
|
31
|
-
"@aglyn/shared-ui-email-campaigns": "1.0.0-beta.
|
|
32
|
-
"@aglyn/shared-ui-jsx": "1.0.0-beta.
|
|
33
|
-
"@aglyn/shared-ui-jsx-forms": "1.0.0-beta.
|
|
34
|
-
"@aglyn/shared-ui-next": "1.0.0-beta.
|
|
35
|
-
"@aglyn/shared-ui-snackstack": "1.0.0-beta.
|
|
36
|
-
"@aglyn/shared-util-email": "1.0.0-beta.
|
|
37
|
-
"@aglyn/shared-util-http": "1.0.0-beta.
|
|
38
|
-
"@aglyn/shared-util-timestamp": "1.0.0-beta.
|
|
39
|
-
"@aglyn/shared-util-tools": "1.0.0-beta.
|
|
40
|
-
"@aglyn/tenant-data-admin": "1.0.0-beta.
|
|
41
|
-
"@aglyn/tenant-feature-instance": "1.0.0-beta.
|
|
42
|
-
"@aglyn/tenant-runtime": "1.0.0-beta.
|
|
28
|
+
"@aglyn/aglyn": "1.0.0-beta.289",
|
|
29
|
+
"@aglyn/shared-data-enums": "1.0.0-beta.289",
|
|
30
|
+
"@aglyn/shared-data-mdi": "1.0.0-beta.289",
|
|
31
|
+
"@aglyn/shared-ui-email-campaigns": "1.0.0-beta.289",
|
|
32
|
+
"@aglyn/shared-ui-jsx": "1.0.0-beta.289",
|
|
33
|
+
"@aglyn/shared-ui-jsx-forms": "1.0.0-beta.289",
|
|
34
|
+
"@aglyn/shared-ui-next": "1.0.0-beta.289",
|
|
35
|
+
"@aglyn/shared-ui-snackstack": "1.0.0-beta.289",
|
|
36
|
+
"@aglyn/shared-util-email": "1.0.0-beta.289",
|
|
37
|
+
"@aglyn/shared-util-http": "1.0.0-beta.289",
|
|
38
|
+
"@aglyn/shared-util-timestamp": "1.0.0-beta.289",
|
|
39
|
+
"@aglyn/shared-util-tools": "1.0.0-beta.289",
|
|
40
|
+
"@aglyn/tenant-data-admin": "1.0.0-beta.289",
|
|
41
|
+
"@aglyn/tenant-feature-instance": "1.0.0-beta.289",
|
|
42
|
+
"@aglyn/tenant-runtime": "1.0.0-beta.289",
|
|
43
43
|
"@swc/helpers": "0.5.23"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* The plugin's DECLARATIONS (AGL-4047): "Run email campaigns", which the one
|
|
19
|
+
* permission catalog lists beside the core keys. Loaded eagerly by the
|
|
20
|
+
* console (client and server) and the tenant's server through the generated
|
|
21
|
+
* declarations manifest, so the role editor offers it, a custom role or a
|
|
22
|
+
* per-member override keeps it, and the site's stamp carries it. Light by
|
|
23
|
+
* construction: nothing here reaches a provider, Firestore or React.
|
|
24
|
+
*/
|
|
25
|
+
export declare function registerMarketingDeclarations(): void;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ import { registerPluginEntitlements } from "@aglyn/aglyn/plugin-manager/plugin-entitlements";
|
|
17
|
+
import { MARKETING_SITE_PERMISSIONS } from "./model/marketing-permissions.js";
|
|
18
|
+
let declared = false;
|
|
19
|
+
/**
|
|
20
|
+
* The plugin's DECLARATIONS (AGL-4047): "Run email campaigns", which the one
|
|
21
|
+
* permission catalog lists beside the core keys. Loaded eagerly by the
|
|
22
|
+
* console (client and server) and the tenant's server through the generated
|
|
23
|
+
* declarations manifest, so the role editor offers it, a custom role or a
|
|
24
|
+
* per-member override keeps it, and the site's stamp carries it. Light by
|
|
25
|
+
* construction: nothing here reaches a provider, Firestore or React.
|
|
26
|
+
*/ export function registerMarketingDeclarations() {
|
|
27
|
+
if (declared) return;
|
|
28
|
+
declared = true;
|
|
29
|
+
registerPluginEntitlements({
|
|
30
|
+
pluginId: 'marketing',
|
|
31
|
+
orgPermissions: MARKETING_SITE_PERMISSIONS
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
registerMarketingDeclarations();
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=declarations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/plugins/marketing/src/lib/declarations.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { registerPluginEntitlements } from '@aglyn/aglyn/plugin-manager/plugin-entitlements'\nimport { MARKETING_SITE_PERMISSIONS } from './model/marketing-permissions'\n\nlet declared = false\n\n/**\n * The plugin's DECLARATIONS (AGL-4047): \"Run email campaigns\", which the one\n * permission catalog lists beside the core keys. Loaded eagerly by the\n * console (client and server) and the tenant's server through the generated\n * declarations manifest, so the role editor offers it, a custom role or a\n * per-member override keeps it, and the site's stamp carries it. Light by\n * construction: nothing here reaches a provider, Firestore or React.\n */\nexport function registerMarketingDeclarations(): void {\n if (declared) return\n declared = true\n registerPluginEntitlements({ pluginId: 'marketing', orgPermissions: MARKETING_SITE_PERMISSIONS })\n}\n\nregisterMarketingDeclarations()\n"],"names":["registerPluginEntitlements","MARKETING_SITE_PERMISSIONS","declared","registerMarketingDeclarations","pluginId","orgPermissions"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,0BAA0B,QAAQ,kDAAiD;AAC5F,SAASC,0BAA0B,QAAQ,mCAA+B;AAE1E,IAAIC,WAAW;AAEf;;;;;;;CAOC,GACD,OAAO,SAASC;IACd,IAAID,UAAU;IACdA,WAAW;IACXF,2BAA2B;QAAEI,UAAU;QAAaC,gBAAgBJ;IAA2B;AACjG;AAEAE"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import type { HostAccessRole } from '@aglyn/aglyn/foundation/definitions/organization.types';
|
|
18
|
+
import type { PluginOrgPermissionDeclaration } from '@aglyn/aglyn/plugin-manager/plugin-entitlements';
|
|
19
|
+
/** Marketing's keys whose preset is the site role. */
|
|
20
|
+
export type MarketingSitePermission = 'marketing.campaigns';
|
|
21
|
+
/** Who ran a site's campaigns before it was a key: the site's Admin and Editor. */
|
|
22
|
+
export declare const MARKETING_CAMPAIGNS_SITE_ROLE_PRESET: Readonly<Record<HostAccessRole, boolean>>;
|
|
23
|
+
/** The key as the plugin declares it into the org permission catalog. */
|
|
24
|
+
export declare const MARKETING_SITE_PERMISSIONS: readonly PluginOrgPermissionDeclaration[];
|
|
25
|
+
/** The refusal a door answers without it: names the permission, never a role. */
|
|
26
|
+
export declare const MARKETING_CAMPAIGNS_REFUSAL = "Your role does not include \"Run email campaigns\" \u2014 ask an organization admin";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
17
|
+
/** Who ran a site's campaigns before it was a key: the site's Admin and Editor. */ export const MARKETING_CAMPAIGNS_SITE_ROLE_PRESET = {
|
|
18
|
+
admin: true,
|
|
19
|
+
editor: true,
|
|
20
|
+
author: false,
|
|
21
|
+
viewer: false
|
|
22
|
+
};
|
|
23
|
+
/** The key as the plugin declares it into the org permission catalog. */ export const MARKETING_SITE_PERMISSIONS = [
|
|
24
|
+
{
|
|
25
|
+
key: 'marketing.campaigns',
|
|
26
|
+
label: 'Run email campaigns',
|
|
27
|
+
description: 'Draft, send, duplicate and manage email campaigns, and see who a send reached. Follows the site role on a site, and the workspace role in the organization hub, unless a role or member sets it.',
|
|
28
|
+
roleDefaults: {
|
|
29
|
+
owner: true,
|
|
30
|
+
admin: true,
|
|
31
|
+
editor: true,
|
|
32
|
+
viewer: false
|
|
33
|
+
},
|
|
34
|
+
hostRoleDefaults: _extends({}, MARKETING_CAMPAIGNS_SITE_ROLE_PRESET),
|
|
35
|
+
group: 'marketing',
|
|
36
|
+
groupLabel: 'Marketing',
|
|
37
|
+
presetFromSiteRole: true
|
|
38
|
+
}
|
|
39
|
+
];
|
|
40
|
+
/** The refusal a door answers without it: names the permission, never a role. */ export const MARKETING_CAMPAIGNS_REFUSAL = 'Your role does not include "Run email campaigns" — ask an organization admin';
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=marketing-permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/marketing/src/lib/model/marketing-permissions.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { HostAccessRole } from '@aglyn/aglyn/foundation/definitions/organization.types'\nimport type { PluginOrgPermissionDeclaration } from '@aglyn/aglyn/plugin-manager/plugin-entitlements'\n\n/*\n * MARKETING'S KEY (AGL-4047).\n *\n * Composing, sending and managing email campaigns, and reading who a send\n * reached, was the site Admin's and Editor's on a site, and an owner's,\n * admin's or editor's of the whole workspace from the organization hub. That\n * is now \"Run email campaigns\", whose preset is the site role on a site\n * (`presetFromSiteRole`) and the workspace role with no site named\n * (`roleDefaults`), so every member keeps exactly the access they had, and a\n * custom role, a member's own permissions or a site's toggle can grant or\n * refuse it.\n */\n\n/** Marketing's keys whose preset is the site role. */\nexport type MarketingSitePermission = 'marketing.campaigns'\n\n/** Who ran a site's campaigns before it was a key: the site's Admin and Editor. */\nexport const MARKETING_CAMPAIGNS_SITE_ROLE_PRESET: Readonly<Record<HostAccessRole, boolean>> = {\n admin: true,\n editor: true,\n author: false,\n viewer: false,\n}\n\n/** The key as the plugin declares it into the org permission catalog. */\nexport const MARKETING_SITE_PERMISSIONS: readonly PluginOrgPermissionDeclaration[] = [\n {\n key: 'marketing.campaigns',\n label: 'Run email campaigns',\n description:\n 'Draft, send, duplicate and manage email campaigns, and see who a send reached. Follows the site role on a site, and the workspace role in the organization hub, unless a role or member sets it.',\n roleDefaults: { owner: true, admin: true, editor: true, viewer: false },\n hostRoleDefaults: { ...MARKETING_CAMPAIGNS_SITE_ROLE_PRESET },\n group: 'marketing',\n groupLabel: 'Marketing',\n presetFromSiteRole: true,\n },\n]\n\n/** The refusal a door answers without it: names the permission, never a role. */\nexport const MARKETING_CAMPAIGNS_REFUSAL = 'Your role does not include \"Run email campaigns\" — ask an organization admin'\n"],"names":["MARKETING_CAMPAIGNS_SITE_ROLE_PRESET","admin","editor","author","viewer","MARKETING_SITE_PERMISSIONS","key","label","description","roleDefaults","owner","hostRoleDefaults","group","groupLabel","presetFromSiteRole","MARKETING_CAMPAIGNS_REFUSAL"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;AAqBD,iFAAiF,GACjF,OAAO,MAAMA,uCAAkF;IAC7FC,OAAO;IACPC,QAAQ;IACRC,QAAQ;IACRC,QAAQ;AACV,EAAC;AAED,uEAAuE,GACvE,OAAO,MAAMC,6BAAwE;IACnF;QACEC,KAAK;QACLC,OAAO;QACPC,aACE;QACFC,cAAc;YAAEC,OAAO;YAAMT,OAAO;YAAMC,QAAQ;YAAME,QAAQ;QAAM;QACtEO,kBAAkB,aAAKX;QACvBY,OAAO;QACPC,YAAY;QACZC,oBAAoB;IACtB;CACD,CAAA;AAED,+EAA+E,GAC/E,OAAO,MAAMC,8BAA8B,+EAA8E"}
|
|
@@ -24,10 +24,8 @@ export declare const CAMPAIGN_DRAFT_DEFAULT_NAME = "Untitled campaign";
|
|
|
24
24
|
export declare const CAMPAIGN_DRAFT_HEADER_MAX_CHARS = 200;
|
|
25
25
|
/** The most alternative subject lines or preheaders a drafted email keeps. */
|
|
26
26
|
export declare const CAMPAIGN_DRAFT_MAX_VARIANTS = 10;
|
|
27
|
-
/** The
|
|
28
|
-
export declare const
|
|
29
|
-
/** The send route's refusal for a member who may not compose this site's mail. */
|
|
30
|
-
export declare const CAMPAIGN_DRAFT_ROLE_REFUSAL = "Not a site admin or editor";
|
|
27
|
+
/** The refusal for a member without "Run email campaigns" here (AGL-4047): names the permission. */
|
|
28
|
+
export declare const CAMPAIGN_DRAFT_ROLE_REFUSAL = "Your role does not include \"Run email campaigns\" \u2014 ask an organization admin";
|
|
31
29
|
/** The id of the one email inside a drafted campaign. */
|
|
32
30
|
export declare function campaignDraftEmailId(campaignId: string): string;
|
|
33
31
|
/** Every field a drafted email is written with, and so every field it can hold. */
|
|
@@ -96,7 +96,9 @@ import { claimAttempt, createResourceUid } from "@aglyn/aglyn/server";
|
|
|
96
96
|
* are what the contact pass and the organization door need, and taking them
|
|
97
97
|
* from `@aglyn/tenant-data-admin`'s index would pull the whole Next server
|
|
98
98
|
* pipeline back into this file's graph.
|
|
99
|
-
*/ import { getOrgDoc, resolveOrgIdForHost, resolveOrgMembership } from "@aglyn/tenant-data-admin/server/organizations";
|
|
99
|
+
*/ import { getOrgDoc, memberHasOrgPermission, resolveOrgIdForHost, resolveOrgMembership } from "@aglyn/tenant-data-admin/server/organizations";
|
|
100
|
+
import { holdsStampedSiteKey } from "@aglyn/aglyn/app-utils/host-permissions";
|
|
101
|
+
import { MARKETING_CAMPAIGNS_REFUSAL, MARKETING_CAMPAIGNS_SITE_ROLE_PRESET } from "../model/marketing-permissions.js";
|
|
100
102
|
import { isOrgWideMember } from "@aglyn/aglyn/server";
|
|
101
103
|
import { CAMPAIGN_SEND_CONTAINER_FIELD, CAMPAIGN_SEND_HOST_FIELD, campaignPlacedOnHost, campaignSiteIds, campaignVisibleTo } from "../model/campaign-container.js";
|
|
102
104
|
import { campaignSendSiteStamp, orgCampaignSends, orgEmailCampaigns, sendHostId, sendIsOnHost } from "./campaign-org-refs.js";
|
|
@@ -630,11 +632,7 @@ import { isPluginEnabled } from "@aglyn/aglyn/plugin-manager/enabled-plugins";
|
|
|
630
632
|
/** A drafted campaign's name when the caller asks for none. */ export const CAMPAIGN_DRAFT_DEFAULT_NAME = 'Untitled campaign';
|
|
631
633
|
/** The longest subject or preheader a drafted email stores: the send route's header cap. */ export const CAMPAIGN_DRAFT_HEADER_MAX_CHARS = 200;
|
|
632
634
|
/** The most alternative subject lines or preheaders a drafted email keeps. */ export const CAMPAIGN_DRAFT_MAX_VARIANTS = 10;
|
|
633
|
-
/** The
|
|
634
|
-
'admin',
|
|
635
|
-
'editor'
|
|
636
|
-
];
|
|
637
|
-
/** The send route's refusal for a member who may not compose this site's mail. */ export const CAMPAIGN_DRAFT_ROLE_REFUSAL = 'Not a site admin or editor';
|
|
635
|
+
/** The refusal for a member without "Run email campaigns" here (AGL-4047): names the permission. */ export const CAMPAIGN_DRAFT_ROLE_REFUSAL = MARKETING_CAMPAIGNS_REFUSAL;
|
|
638
636
|
/** The id of the one email inside a drafted campaign. */ export function campaignDraftEmailId(campaignId) {
|
|
639
637
|
return `${campaignId}-email`;
|
|
640
638
|
}
|
|
@@ -705,9 +703,9 @@ export function readCampaignDraftContent(content) {
|
|
|
705
703
|
};
|
|
706
704
|
}
|
|
707
705
|
function campaignDraftRoleRefusal(host, uid) {
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
return
|
|
706
|
+
// "Run email campaigns" (AGL-4047): the site's stamp, else the preset of
|
|
707
|
+
// the member's site role, the Admin and Editor this asked for before.
|
|
708
|
+
return holdsStampedSiteKey(host, uid, 'marketing.campaigns', MARKETING_CAMPAIGNS_SITE_ROLE_PRESET) ? null : {
|
|
711
709
|
status: 403,
|
|
712
710
|
error: CAMPAIGN_DRAFT_ROLE_REFUSAL
|
|
713
711
|
};
|
|
@@ -890,11 +888,6 @@ export const campaignDraftWriter = createCampaignDraftWriter();
|
|
|
890
888
|
pluginId: MARKETING_PLUGIN_ID
|
|
891
889
|
});
|
|
892
890
|
}
|
|
893
|
-
/** The org roles that may manage campaigns from the organization hub. */ const ORG_MANAGE_ROLES = [
|
|
894
|
-
'owner',
|
|
895
|
-
'admin',
|
|
896
|
-
'editor'
|
|
897
|
-
];
|
|
898
891
|
/**
|
|
899
892
|
* The organization a `campaigns/manage` request from the organization hub is
|
|
900
893
|
* for, read off its JSON body, so the dispatcher's release gate asks about the
|
|
@@ -974,7 +967,7 @@ export const campaignDraftWriter = createCampaignDraftWriter();
|
|
|
974
967
|
const firestore = firebaseAdmin.app().firestore();
|
|
975
968
|
let orgId;
|
|
976
969
|
if (hostId) {
|
|
977
|
-
var
|
|
970
|
+
var _ref4;
|
|
978
971
|
const hostRef = firestore.collection('hosts').doc(hostId);
|
|
979
972
|
const hostSnapshot = await hostRef.get();
|
|
980
973
|
if (!hostSnapshot.exists) {
|
|
@@ -982,10 +975,9 @@ export const campaignDraftWriter = createCampaignDraftWriter();
|
|
|
982
975
|
error: 'Unknown site'
|
|
983
976
|
});
|
|
984
977
|
}
|
|
985
|
-
|
|
986
|
-
if (memberRole !== 'admin' && memberRole !== 'editor') {
|
|
978
|
+
if (!holdsStampedSiteKey(hostSnapshot, decoded.uid, 'marketing.campaigns', MARKETING_CAMPAIGNS_SITE_ROLE_PRESET)) {
|
|
987
979
|
return res.status(403).json({
|
|
988
|
-
error:
|
|
980
|
+
error: MARKETING_CAMPAIGNS_REFUSAL
|
|
989
981
|
});
|
|
990
982
|
}
|
|
991
983
|
orgId = (_ref4 = await resolveOrgIdForHost(hostId)) != null ? _ref4 : '';
|
|
@@ -1004,12 +996,15 @@ export const campaignDraftWriter = createCampaignDraftWriter();
|
|
|
1004
996
|
});
|
|
1005
997
|
}
|
|
1006
998
|
} else {
|
|
1007
|
-
var _member_role;
|
|
1008
999
|
const membership = await resolveOrgMembership(decoded.uid, requestedOrgId);
|
|
1009
1000
|
const member = membership == null ? void 0 : membership.member;
|
|
1010
|
-
|
|
1001
|
+
// A member of the whole workspace holding "Run email campaigns" with
|
|
1002
|
+
// no site named (AGL-4047): its default is the owner, admins and
|
|
1003
|
+
// editors this asked for before, then their custom role and their own
|
|
1004
|
+
// permissions.
|
|
1005
|
+
if (!member || !isOrgWideMember(member) || !await memberHasOrgPermission(requestedOrgId, member, 'marketing.campaigns')) {
|
|
1011
1006
|
return res.status(403).json({
|
|
1012
|
-
error:
|
|
1007
|
+
error: MARKETING_CAMPAIGNS_REFUSAL
|
|
1013
1008
|
});
|
|
1014
1009
|
}
|
|
1015
1010
|
/*
|