@crowdin/app-project-module 0.80.0 → 0.81.0
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/out/modules/api/api.js
CHANGED
|
@@ -499,9 +499,9 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
499
499
|
checkSubscriptionExpiration: true,
|
|
500
500
|
moduleKey: config.projectIntegration.key,
|
|
501
501
|
}), (req, res) => {
|
|
502
|
-
var _a;
|
|
502
|
+
var _a, _b;
|
|
503
503
|
let fields = [];
|
|
504
|
-
if ((_a = config.projectIntegration) === null || _a === void 0 ? void 0 : _a.loginForm.fields) {
|
|
504
|
+
if ((_b = (_a = config.projectIntegration) === null || _a === void 0 ? void 0 : _a.loginForm) === null || _b === void 0 ? void 0 : _b.fields) {
|
|
505
505
|
fields = getFormFields(config === null || config === void 0 ? void 0 : config.projectIntegration.loginForm.fields);
|
|
506
506
|
}
|
|
507
507
|
res.send({ fields });
|
|
@@ -47,19 +47,25 @@ function handle() {
|
|
|
47
47
|
if (!hasManagerAccess) {
|
|
48
48
|
return res.status(403).send({ error: 'Access denied' });
|
|
49
49
|
}
|
|
50
|
+
const inviteRestricted = !isAdmin &&
|
|
51
|
+
'invite_restrict_enabled' in req.crowdinContext.jwtPayload.context &&
|
|
52
|
+
!!req.crowdinContext.jwtPayload.context.invite_restrict_enabled;
|
|
50
53
|
const usersWhoWillBeInvitedToOrganization = filterOrganizationUsers(usersToInvite);
|
|
51
54
|
const usersWhoWillBeInvitedToProject = filterProjectUsers({
|
|
55
|
+
inviteRestricted,
|
|
52
56
|
usersToInvite,
|
|
53
57
|
projectMembers,
|
|
54
58
|
organizationMembers,
|
|
55
59
|
});
|
|
56
60
|
const usersWhoNotIssetInApplicationInstallation = filterNotIssetApplicationUsers({
|
|
61
|
+
inviteRestricted,
|
|
57
62
|
usersToInvite,
|
|
58
63
|
applicationInstallation,
|
|
59
64
|
projectMembers,
|
|
60
65
|
organizationMembers,
|
|
61
66
|
});
|
|
62
67
|
const usersWhoNotIssetInIntegration = filterNotIssetIntegrationUsers({
|
|
68
|
+
inviteRestricted,
|
|
63
69
|
usersToInvite,
|
|
64
70
|
integrationCredentials,
|
|
65
71
|
projectMembers,
|
|
@@ -69,6 +75,7 @@ function handle() {
|
|
|
69
75
|
return res.send({
|
|
70
76
|
data: {
|
|
71
77
|
isAdmin,
|
|
78
|
+
inviteRestricted,
|
|
72
79
|
editApplicationAvailable: applicationInstallation !== null,
|
|
73
80
|
usersWhoWillBeInvitedToOrganization,
|
|
74
81
|
usersWhoWillBeInvitedToProject,
|
|
@@ -81,6 +88,7 @@ function handle() {
|
|
|
81
88
|
req,
|
|
82
89
|
projectId,
|
|
83
90
|
isAdmin,
|
|
91
|
+
inviteRestricted,
|
|
84
92
|
usersToInvite,
|
|
85
93
|
applicationInstallation,
|
|
86
94
|
usersWhoWillBeInvitedToOrganization,
|
|
@@ -94,10 +102,10 @@ exports.default = handle;
|
|
|
94
102
|
function filterOrganizationUsers(usersToInvite) {
|
|
95
103
|
return usersToInvite.filter((identifier) => (0, util_1.validateEmail)(identifier)).map((name) => ({ name: `${name}` }));
|
|
96
104
|
}
|
|
97
|
-
function filterProjectUsers({ usersToInvite, projectMembers, organizationMembers, }) {
|
|
105
|
+
function filterProjectUsers({ inviteRestricted, usersToInvite, projectMembers, organizationMembers, }) {
|
|
98
106
|
return usersToInvite
|
|
99
107
|
.map((identifier) => {
|
|
100
|
-
if ((0, util_1.validateEmail)(identifier)) {
|
|
108
|
+
if ((0, util_1.validateEmail)(identifier) && !inviteRestricted) {
|
|
101
109
|
return { name: `${identifier}` };
|
|
102
110
|
}
|
|
103
111
|
const user = projectMembers.find((member) => member.id === +identifier);
|
|
@@ -113,7 +121,7 @@ function filterProjectUsers({ usersToInvite, projectMembers, organizationMembers
|
|
|
113
121
|
})
|
|
114
122
|
.filter(Boolean);
|
|
115
123
|
}
|
|
116
|
-
function filterNotIssetApplicationUsers({ usersToInvite, applicationInstallation, projectMembers, organizationMembers, }) {
|
|
124
|
+
function filterNotIssetApplicationUsers({ inviteRestricted, usersToInvite, applicationInstallation, projectMembers, organizationMembers, }) {
|
|
117
125
|
let userIdentifiers = [];
|
|
118
126
|
if (!applicationInstallation) {
|
|
119
127
|
return [];
|
|
@@ -130,7 +138,7 @@ function filterNotIssetApplicationUsers({ usersToInvite, applicationInstallation
|
|
|
130
138
|
}
|
|
131
139
|
return userIdentifiers
|
|
132
140
|
.map((identifier) => {
|
|
133
|
-
if ((0, util_1.validateEmail)(identifier)) {
|
|
141
|
+
if ((0, util_1.validateEmail)(identifier) && !inviteRestricted) {
|
|
134
142
|
return { name: `${identifier}` };
|
|
135
143
|
}
|
|
136
144
|
let user;
|
|
@@ -142,7 +150,7 @@ function filterNotIssetApplicationUsers({ usersToInvite, applicationInstallation
|
|
|
142
150
|
})
|
|
143
151
|
.filter(Boolean);
|
|
144
152
|
}
|
|
145
|
-
function filterNotIssetIntegrationUsers({ usersToInvite, integrationCredentials, projectMembers, organizationMembers, }) {
|
|
153
|
+
function filterNotIssetIntegrationUsers({ inviteRestricted, usersToInvite, integrationCredentials, projectMembers, organizationMembers, }) {
|
|
146
154
|
let integrationManagers = [];
|
|
147
155
|
if (integrationCredentials === null || integrationCredentials === void 0 ? void 0 : integrationCredentials.managers) {
|
|
148
156
|
integrationManagers = JSON.parse(integrationCredentials.managers);
|
|
@@ -152,7 +160,7 @@ function filterNotIssetIntegrationUsers({ usersToInvite, integrationCredentials,
|
|
|
152
160
|
if (integrationManagers.includes(`${identifier}`)) {
|
|
153
161
|
return null;
|
|
154
162
|
}
|
|
155
|
-
if ((0, util_1.validateEmail)(identifier)) {
|
|
163
|
+
if ((0, util_1.validateEmail)(identifier) && !inviteRestricted) {
|
|
156
164
|
return { name: `${identifier}` };
|
|
157
165
|
}
|
|
158
166
|
let user;
|
|
@@ -164,9 +172,12 @@ function filterNotIssetIntegrationUsers({ usersToInvite, integrationCredentials,
|
|
|
164
172
|
})
|
|
165
173
|
.filter(Boolean);
|
|
166
174
|
}
|
|
167
|
-
function inviteUsers({ req, projectId, isAdmin, usersToInvite, applicationInstallation, usersWhoWillBeInvitedToOrganization, usersWhoWillBeInvitedToProject, usersWhoNotIssetInApplicationInstallation, }) {
|
|
175
|
+
function inviteUsers({ req, projectId, isAdmin, inviteRestricted, usersToInvite, applicationInstallation, usersWhoWillBeInvitedToOrganization, usersWhoWillBeInvitedToProject, usersWhoNotIssetInApplicationInstallation, }) {
|
|
168
176
|
return __awaiter(this, void 0, void 0, function* () {
|
|
169
177
|
const client = req.crowdinApiClient;
|
|
178
|
+
if (inviteRestricted) {
|
|
179
|
+
usersWhoWillBeInvitedToOrganization = [];
|
|
180
|
+
}
|
|
170
181
|
const alreadyAddedUserIds = yield inviteUsersToProject({
|
|
171
182
|
client,
|
|
172
183
|
projectId,
|
|
@@ -197,8 +197,10 @@ function register({ config, app }) {
|
|
|
197
197
|
}
|
|
198
198
|
// remove user errors
|
|
199
199
|
cron.schedule('0 0 * * *', () => __awaiter(this, void 0, void 0, function* () {
|
|
200
|
-
|
|
201
|
-
|
|
200
|
+
if (integrationLogic.userErrorLifetimeDays) {
|
|
201
|
+
const date = (0, util_1.getPreviousDate)(integrationLogic.userErrorLifetimeDays);
|
|
202
|
+
yield (0, storage_1.getStorage)().deleteAllUsersErrorsOlderThan(`${date.getTime()}`);
|
|
203
|
+
}
|
|
202
204
|
}));
|
|
203
205
|
if (integrationLogic.webhooks) {
|
|
204
206
|
app.post(`${integrationLogic.webhooks.crowdinWebhookUrl
|
|
@@ -6,7 +6,7 @@ export interface IntegrationLogic extends ModuleKey {
|
|
|
6
6
|
/**
|
|
7
7
|
* Customize your app login form
|
|
8
8
|
*/
|
|
9
|
-
loginForm
|
|
9
|
+
loginForm?: LoginForm;
|
|
10
10
|
/**
|
|
11
11
|
* Define login process via OAuth2 protocol
|
|
12
12
|
*/
|
|
@@ -162,7 +162,7 @@ export interface IntegrationLogic extends ModuleKey {
|
|
|
162
162
|
/**
|
|
163
163
|
* The duration for storing user errors, default is 30 days.
|
|
164
164
|
*/
|
|
165
|
-
userErrorLifetimeDays
|
|
165
|
+
userErrorLifetimeDays?: number;
|
|
166
166
|
/**
|
|
167
167
|
* When true, folder filtering during automatic translation sync is bypassed, and the file tree is returned unchanged.
|
|
168
168
|
*/
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
integration-one-level-fetching="true"
|
|
72
72
|
{{/if}}
|
|
73
73
|
{{#if integrationSearchListener}}
|
|
74
|
-
allow-filter-change-listener="true"
|
|
74
|
+
allow-integration-filter-change-listener="true"
|
|
75
75
|
{{/if}}
|
|
76
76
|
{{#if integrationPagination}}
|
|
77
77
|
integration-load-more-files="true"
|
|
@@ -166,6 +166,7 @@
|
|
|
166
166
|
<tr class="organization-invite">
|
|
167
167
|
<td>
|
|
168
168
|
<crowdin-p>Registration in Organization</crowdin-p>
|
|
169
|
+
<div class="permission-description"></div>
|
|
169
170
|
</td>
|
|
170
171
|
<td class="affected-users"></td>
|
|
171
172
|
<td class="status"></td>
|
|
@@ -1009,7 +1010,7 @@
|
|
|
1009
1010
|
if (organizationInvite) {
|
|
1010
1011
|
const organizationWillGrantElement = `<span class="badge badge-will-be-granted">Will Be Registered</span>`;
|
|
1011
1012
|
|
|
1012
|
-
|
|
1013
|
+
processUsersWhoWillBeInvitedToOrganization(organizationInvite, usersData, organizationWillGrantElement, grantedElement, notAvailableElement);
|
|
1013
1014
|
}
|
|
1014
1015
|
|
|
1015
1016
|
processUsersWhoWillBeInvited(projectInvite, usersData.usersWhoWillBeInvitedToProject, willGrantedElement, grantedElement);
|
|
@@ -1018,6 +1019,38 @@
|
|
|
1018
1019
|
processUsersWhoWillBeInvitedApplicationSettings(usersData, willGrantedElement, grantedElement, notAvailableElement);
|
|
1019
1020
|
}
|
|
1020
1021
|
|
|
1022
|
+
function processUsersWhoWillBeInvitedToOrganization(element, usersData, willGrantedElement, alreadyGrantedMessage, notAvailableElement) {
|
|
1023
|
+
const tooltip = element.querySelector('.status');
|
|
1024
|
+
const description = element.querySelector('.permission-description');
|
|
1025
|
+
const userList = element.querySelector('.affected-users');
|
|
1026
|
+
|
|
1027
|
+
description.classList.remove('text-warning');
|
|
1028
|
+
description.innerText = '';
|
|
1029
|
+
|
|
1030
|
+
const users = usersData.usersWhoWillBeInvitedToOrganization;
|
|
1031
|
+
|
|
1032
|
+
if (users.length) {
|
|
1033
|
+
if (usersData.inviteRestricted) {
|
|
1034
|
+
description.classList.add('text-warning');
|
|
1035
|
+
description.innerText = 'New user invitations are restricted to administrators.';
|
|
1036
|
+
|
|
1037
|
+
tooltip.innerHTML = notAvailableElement;
|
|
1038
|
+
} else {
|
|
1039
|
+
tooltip.innerHTML = willGrantedElement;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
let affectedUsers = '<ul>';
|
|
1043
|
+
for (const user of users) {
|
|
1044
|
+
affectedUsers += `<li><crowdin-p>${sanitizeHTML(user.name)}</crowdin-p></li>`;
|
|
1045
|
+
}
|
|
1046
|
+
affectedUsers += '</ul>';
|
|
1047
|
+
userList.innerHTML = affectedUsers;
|
|
1048
|
+
} else {
|
|
1049
|
+
tooltip.innerHTML = alreadyGrantedMessage;
|
|
1050
|
+
userList.innerHTML = alreadyGrantedMessage;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1021
1054
|
function processUsersWhoWillBeInvited(element, users, grantMessage, alreadyGrantedMessage) {
|
|
1022
1055
|
const tooltip = element.querySelector('.status');
|
|
1023
1056
|
const userList = element.querySelector('.affected-users');
|
package/package.json
CHANGED