@crowdin/app-project-module 0.103.0 → 0.104.1
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/index.js +2 -0
- package/out/modules/auth-guard/handlers/verify.d.ts +5 -0
- package/out/modules/auth-guard/handlers/verify.js +57 -0
- package/out/modules/auth-guard/index.d.ts +6 -0
- package/out/modules/auth-guard/index.js +36 -0
- package/out/modules/auth-guard/types.d.ts +101 -0
- package/out/modules/auth-guard/types.js +2 -0
- package/out/modules/manifest.js +29 -0
- package/out/types.d.ts +5 -0
- package/package.json +1 -1
package/out/index.js
CHANGED
|
@@ -88,6 +88,7 @@ const webhooks = __importStar(require("./modules/webhooks"));
|
|
|
88
88
|
const workflowStepType = __importStar(require("./modules/workflow-step-type"));
|
|
89
89
|
const aiRequestProcessors = __importStar(require("./modules/ai-request-processors"));
|
|
90
90
|
const automationAction = __importStar(require("./modules/automation-action"));
|
|
91
|
+
const authGuard = __importStar(require("./modules/auth-guard"));
|
|
91
92
|
const subscription_1 = require("./util/subscription");
|
|
92
93
|
var types_2 = require("./types");
|
|
93
94
|
Object.defineProperty(exports, "ProjectPermissions", { enumerable: true, get: function () { return types_2.ProjectPermissions; } });
|
|
@@ -222,6 +223,7 @@ function addCrowdinEndpoints(app, clientConfig) {
|
|
|
222
223
|
workflowStepType.register({ config, app });
|
|
223
224
|
aiRequestProcessors.register({ config, app });
|
|
224
225
|
automationAction.register({ config, app });
|
|
226
|
+
authGuard.register({ config, app });
|
|
225
227
|
addFormSchema({ config, app });
|
|
226
228
|
return Object.assign(Object.assign({}, exports.metadataStore), { storage: storage.getStorage(), establishCrowdinConnection: (authRequest, moduleKey) => {
|
|
227
229
|
let jwtToken = '';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/// <reference types="qs" />
|
|
2
|
+
import { Response } from 'express';
|
|
3
|
+
import { CrowdinClientRequest } from '../../../types';
|
|
4
|
+
import { AuthGuardModule } from '../types';
|
|
5
|
+
export default function verifyHandler(authGuardModules: AuthGuardModule[]): (req: CrowdinClientRequest | import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: Function) => void;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const util_1 = require("../../../util");
|
|
13
|
+
function verifyHandler(authGuardModules) {
|
|
14
|
+
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
15
|
+
const { userId, organizationId, ipAddress, moduleKey, code } = req.body;
|
|
16
|
+
req.logInfo(`Auth guard verification request for module: ${moduleKey}`);
|
|
17
|
+
// Find the auth-guard module by key
|
|
18
|
+
const module = authGuardModules.find((m) => m.key === moduleKey);
|
|
19
|
+
if (!module) {
|
|
20
|
+
req.logError(`Auth guard module not found: ${moduleKey}`);
|
|
21
|
+
return res.status(404).json({
|
|
22
|
+
error: `Auth guard module not found: ${moduleKey}`,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
// Call the user-provided verification logic
|
|
27
|
+
const result = yield module.verify({
|
|
28
|
+
client: req.crowdinApiClient,
|
|
29
|
+
context: req.crowdinContext,
|
|
30
|
+
userId,
|
|
31
|
+
organizationId,
|
|
32
|
+
ipAddress,
|
|
33
|
+
moduleKey,
|
|
34
|
+
code,
|
|
35
|
+
});
|
|
36
|
+
if (!result || typeof result.success !== 'boolean') {
|
|
37
|
+
req.logError('Invalid response from auth guard verification function');
|
|
38
|
+
return res.status(500).json({
|
|
39
|
+
success: false,
|
|
40
|
+
message: 'Invalid response from verification function',
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
// Return the result (always HTTP 200, success field indicates verification result)
|
|
44
|
+
req.logInfo(`Auth guard verification ${result.success ? 'succeeded' : 'failed'} for module: ${moduleKey}`);
|
|
45
|
+
return res.status(200).json(result);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
req.logError(`Auth guard verification error: ${error.message || error}`);
|
|
49
|
+
// Return HTTP 500 for internal errors
|
|
50
|
+
return res.status(500).json({
|
|
51
|
+
success: false,
|
|
52
|
+
message: 'Internal server error during verification',
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
exports.default = verifyHandler;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.register = void 0;
|
|
7
|
+
const crowdin_client_1 = __importDefault(require("../../middlewares/crowdin-client"));
|
|
8
|
+
const json_response_1 = __importDefault(require("../../middlewares/json-response"));
|
|
9
|
+
const render_ui_module_1 = __importDefault(require("../../middlewares/render-ui-module"));
|
|
10
|
+
const ui_module_1 = __importDefault(require("../../middlewares/ui-module"));
|
|
11
|
+
const verify_1 = __importDefault(require("./handlers/verify"));
|
|
12
|
+
function register({ config, app }) {
|
|
13
|
+
if (!config.authGuard) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
// Normalize to array
|
|
17
|
+
const authGuardModules = Array.isArray(config.authGuard) ? config.authGuard : [config.authGuard];
|
|
18
|
+
if (!authGuardModules.length) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
// Register settings UI modules if provided
|
|
22
|
+
authGuardModules.forEach((module, index) => {
|
|
23
|
+
if (module.settingsUiModule) {
|
|
24
|
+
const moduleKey = module.key || `${config.identifier}-auth-guard-${index}`;
|
|
25
|
+
app.use(`/auth-guard/${moduleKey}/settings`, (0, ui_module_1.default)({ config, moduleType: moduleKey }), (0, render_ui_module_1.default)(module.settingsUiModule));
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
// Register verification endpoint
|
|
29
|
+
app.post('/auth-guard/verify', json_response_1.default, (0, crowdin_client_1.default)({
|
|
30
|
+
config,
|
|
31
|
+
optional: false,
|
|
32
|
+
checkSubscriptionExpiration: false,
|
|
33
|
+
moduleKey: authGuardModules.map((m, i) => m.key || `${config.identifier}-auth-guard-${i}`),
|
|
34
|
+
}), (0, verify_1.default)(authGuardModules));
|
|
35
|
+
}
|
|
36
|
+
exports.register = register;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import Crowdin from '@crowdin/crowdin-api-client';
|
|
2
|
+
import { CrowdinContextInfo, Environments, ModuleKey, UiModule } from '../../types';
|
|
3
|
+
/**
|
|
4
|
+
* Auth Guard verification type
|
|
5
|
+
*/
|
|
6
|
+
export type AuthGuardVerificationType = 'direct' | 'redirect' | 'iframe';
|
|
7
|
+
/**
|
|
8
|
+
* Auth Guard module options
|
|
9
|
+
*/
|
|
10
|
+
export interface AuthGuardOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Verification type: direct (backend-only), redirect (external page), or iframe (embedded iframe)
|
|
13
|
+
* @default 'direct'
|
|
14
|
+
*/
|
|
15
|
+
type?: AuthGuardVerificationType;
|
|
16
|
+
/**
|
|
17
|
+
* Whether to apply this check to organization administrators
|
|
18
|
+
* @default false
|
|
19
|
+
*/
|
|
20
|
+
applyToAdmin?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* User-facing URL for redirect and iframe types
|
|
23
|
+
* Required if type is not 'direct'
|
|
24
|
+
*/
|
|
25
|
+
url?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Request body for auth guard verification
|
|
29
|
+
*/
|
|
30
|
+
export interface AuthGuardVerifyRequest {
|
|
31
|
+
/**
|
|
32
|
+
* User ID
|
|
33
|
+
*/
|
|
34
|
+
userId: number;
|
|
35
|
+
/**
|
|
36
|
+
* Organization ID
|
|
37
|
+
*/
|
|
38
|
+
organizationId: number;
|
|
39
|
+
/**
|
|
40
|
+
* User's IP address
|
|
41
|
+
*/
|
|
42
|
+
ipAddress: string;
|
|
43
|
+
/**
|
|
44
|
+
* Module key to identify which auth-guard module to invoke
|
|
45
|
+
*/
|
|
46
|
+
moduleKey: string;
|
|
47
|
+
/**
|
|
48
|
+
* Verification code (provided for redirect/iframe types after user interaction)
|
|
49
|
+
*/
|
|
50
|
+
code?: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Response for auth guard verification
|
|
54
|
+
*/
|
|
55
|
+
export interface AuthGuardVerifyResponse {
|
|
56
|
+
/**
|
|
57
|
+
* Whether verification was successful
|
|
58
|
+
*/
|
|
59
|
+
success: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Optional error or informational message
|
|
62
|
+
*/
|
|
63
|
+
message?: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Auth Guard module configuration
|
|
67
|
+
*/
|
|
68
|
+
export interface AuthGuardModule extends ModuleKey, Environments {
|
|
69
|
+
/**
|
|
70
|
+
* Module name displayed to users during verification
|
|
71
|
+
*/
|
|
72
|
+
name?: string;
|
|
73
|
+
/**
|
|
74
|
+
* Module description (primarily for iframe type)
|
|
75
|
+
*/
|
|
76
|
+
description?: string;
|
|
77
|
+
/**
|
|
78
|
+
* Endpoint URL for verification (relative to baseUrl or absolute)
|
|
79
|
+
*/
|
|
80
|
+
url?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Module configuration options
|
|
83
|
+
*/
|
|
84
|
+
options?: AuthGuardOptions;
|
|
85
|
+
/**
|
|
86
|
+
* Settings UI module for configuration
|
|
87
|
+
*/
|
|
88
|
+
settingsUiModule?: UiModule;
|
|
89
|
+
/**
|
|
90
|
+
* Verification logic function
|
|
91
|
+
*/
|
|
92
|
+
verify: (params: {
|
|
93
|
+
client?: Crowdin;
|
|
94
|
+
context?: CrowdinContextInfo;
|
|
95
|
+
userId: number;
|
|
96
|
+
organizationId: number;
|
|
97
|
+
ipAddress: string;
|
|
98
|
+
moduleKey: string;
|
|
99
|
+
code?: string;
|
|
100
|
+
}) => Promise<AuthGuardVerifyResponse>;
|
|
101
|
+
}
|
package/out/modules/manifest.js
CHANGED
|
@@ -411,6 +411,35 @@ function handle(config) {
|
|
|
411
411
|
: {})), { validateSettingsUrl: (0, index_1.getAutomationActionUrl)('/automation-action/validate-settings', automationAction), executeUrl: (0, index_1.getAutomationActionUrl)('/automation-action/execute', automationAction), invocationWaitMode: automationAction.invocationWaitMode || 'sync' }), (uiModule ? { url: (0, index_1.getAutomationActionUrl)('/automation-action', automationAction) } : {})));
|
|
412
412
|
}
|
|
413
413
|
}
|
|
414
|
+
if (config.authGuard) {
|
|
415
|
+
// prevent possible overrides of the other modules
|
|
416
|
+
if (Array.isArray(config.authGuard)) {
|
|
417
|
+
config.authGuard = config.authGuard.map((authGuard) => (Object.assign({}, authGuard)));
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
config.authGuard = Object.assign({}, config.authGuard);
|
|
421
|
+
}
|
|
422
|
+
const authGuards = Array.isArray(config.authGuard) ? config.authGuard : [config.authGuard];
|
|
423
|
+
modules['auth-guard'] = [];
|
|
424
|
+
for (let i = 0; i < authGuards.length; i++) {
|
|
425
|
+
if (!authGuards[i].key) {
|
|
426
|
+
authGuards[i].key = config.identifier + '-auth-guard-' + i;
|
|
427
|
+
}
|
|
428
|
+
const options = authGuards[i].options || {};
|
|
429
|
+
const manifestEntry = {
|
|
430
|
+
key: authGuards[i].key,
|
|
431
|
+
name: authGuards[i].name || config.name,
|
|
432
|
+
url: '/auth-guard/verify',
|
|
433
|
+
};
|
|
434
|
+
if (authGuards[i].description) {
|
|
435
|
+
manifestEntry.description = authGuards[i].description;
|
|
436
|
+
}
|
|
437
|
+
if (options.type || options.applyToAdmin !== undefined || options.url) {
|
|
438
|
+
manifestEntry.options = Object.assign(Object.assign(Object.assign({}, (options.type && { type: options.type })), (options.applyToAdmin !== undefined && { applyToAdmin: options.applyToAdmin })), (options.url && { url: options.url }));
|
|
439
|
+
}
|
|
440
|
+
modules['auth-guard'].push(manifestEntry);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
414
443
|
const events = {
|
|
415
444
|
installed: '/installed',
|
|
416
445
|
uninstall: '/uninstall',
|
package/out/types.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ import { Webhook } from './modules/webhooks/types';
|
|
|
20
20
|
import { WorkflowStepTypeModule } from './modules/workflow-step-type/types';
|
|
21
21
|
import { AiRequestProcessorModule, AiStreamProcessorModule } from './modules/ai-request-processors/types';
|
|
22
22
|
import { AutomationActionModule } from './modules/automation-action/types';
|
|
23
|
+
import { AuthGuardModule } from './modules/auth-guard/types';
|
|
23
24
|
export interface ClientConfig extends ImagePath {
|
|
24
25
|
/**
|
|
25
26
|
* Authentication Crowdin App type: "authorization_code", "crowdin_app", "crowdin_agent". Default: "crowdin_app"
|
|
@@ -272,6 +273,10 @@ export interface ClientConfig extends ImagePath {
|
|
|
272
273
|
* Automation action module
|
|
273
274
|
*/
|
|
274
275
|
automationAction?: AutomationActionModule | AutomationActionModule[];
|
|
276
|
+
/**
|
|
277
|
+
* Auth guard module for custom authentication/authorization checks
|
|
278
|
+
*/
|
|
279
|
+
authGuard?: AuthGuardModule | AuthGuardModule[];
|
|
275
280
|
}
|
|
276
281
|
export interface Environments {
|
|
277
282
|
environments?: Environment | Environment[];
|
package/package.json
CHANGED