@symbo.ls/sdk 2.34.34 → 3.1.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/README.md +13 -315
- package/dist/cjs/config/environment.js +50 -124
- package/dist/cjs/index.js +22 -169
- package/dist/cjs/services/AIService.js +155 -0
- package/dist/cjs/services/AuthService.js +277 -751
- package/dist/cjs/services/BaseService.js +6 -158
- package/dist/cjs/services/BasedService.js +679 -0
- package/dist/cjs/services/SocketIOService.js +309 -0
- package/dist/cjs/services/SocketService.js +161 -0
- package/dist/cjs/services/SymstoryService.js +485 -0
- package/dist/cjs/services/index.js +16 -64
- package/dist/cjs/utils/basedQuerys.js +61 -0
- package/dist/cjs/utils/permission.js +4 -4
- package/dist/cjs/utils/services.js +80 -301
- package/dist/cjs/utils/symstoryClient.js +228 -0
- package/dist/cjs/utils/validation.js +3 -0
- package/dist/esm/config/environment.js +50 -124
- package/dist/esm/index.js +11282 -49789
- package/dist/esm/services/AIService.js +185 -0
- package/dist/esm/services/AuthService.js +358 -1506
- package/dist/esm/services/BaseService.js +6 -757
- package/dist/esm/services/BasedService.js +4651 -0
- package/dist/esm/services/SocketIOService.js +467 -0
- package/dist/esm/services/SocketService.js +191 -0
- package/dist/esm/services/SymstoryService.js +6849 -0
- package/dist/esm/services/index.js +11188 -49352
- package/dist/esm/utils/basedQuerys.js +43 -0
- package/dist/esm/utils/permission.js +4 -4
- package/dist/esm/utils/services.js +80 -301
- package/dist/esm/utils/symstoryClient.js +334 -0
- package/dist/esm/utils/validation.js +26 -93
- package/dist/node/config/environment.js +50 -124
- package/dist/node/index.js +26 -202
- package/dist/node/services/AIService.js +136 -0
- package/dist/node/services/AuthService.js +278 -751
- package/dist/node/services/BaseService.js +6 -148
- package/dist/node/services/BasedService.js +650 -0
- package/dist/node/services/SocketIOService.js +280 -0
- package/dist/node/services/SocketService.js +142 -0
- package/dist/node/services/SymstoryService.js +456 -0
- package/dist/node/services/index.js +16 -64
- package/dist/node/utils/basedQuerys.js +42 -0
- package/dist/node/utils/permission.js +4 -4
- package/dist/node/utils/services.js +80 -301
- package/dist/node/utils/symstoryClient.js +199 -0
- package/dist/node/utils/validation.js +3 -0
- package/package.json +21 -43
- package/src/config/environment.js +50 -126
- package/src/index.js +24 -208
- package/src/services/AIService.js +150 -0
- package/src/services/AuthService.js +298 -893
- package/src/services/BaseService.js +6 -166
- package/src/services/BasedService.js +722 -0
- package/src/services/SocketIOService.js +356 -0
- package/src/services/SocketService.js +168 -0
- package/src/services/SymstoryService.js +563 -0
- package/src/services/index.js +13 -80
- package/src/utils/basedQuerys.js +41 -0
- package/src/utils/permission.js +4 -4
- package/src/utils/services.js +83 -325
- package/src/utils/symstoryClient.js +218 -0
- package/src/utils/validation.js +3 -0
- package/dist/cjs/services/AdminService.js +0 -351
- package/dist/cjs/services/BranchService.js +0 -484
- package/dist/cjs/services/CollabService.js +0 -743
- package/dist/cjs/services/DnsService.js +0 -340
- package/dist/cjs/services/FeatureFlagService.js +0 -175
- package/dist/cjs/services/FileService.js +0 -201
- package/dist/cjs/services/IntegrationService.js +0 -538
- package/dist/cjs/services/MetricsService.js +0 -62
- package/dist/cjs/services/PaymentService.js +0 -271
- package/dist/cjs/services/PlanService.js +0 -426
- package/dist/cjs/services/ProjectService.js +0 -1207
- package/dist/cjs/services/PullRequestService.js +0 -503
- package/dist/cjs/services/ScreenshotService.js +0 -304
- package/dist/cjs/services/SubscriptionService.js +0 -396
- package/dist/cjs/services/TrackingService.js +0 -661
- package/dist/cjs/services/WaitlistService.js +0 -148
- package/dist/cjs/state/RootStateManager.js +0 -65
- package/dist/cjs/state/rootEventBus.js +0 -74
- package/dist/cjs/utils/CollabClient.js +0 -223
- package/dist/cjs/utils/TokenManager.js +0 -422
- package/dist/cjs/utils/changePreprocessor.js +0 -199
- package/dist/cjs/utils/jsonDiff.js +0 -145
- package/dist/cjs/utils/ordering.js +0 -309
- package/dist/esm/services/AdminService.js +0 -1132
- package/dist/esm/services/BranchService.js +0 -1265
- package/dist/esm/services/CollabService.js +0 -26838
- package/dist/esm/services/DnsService.js +0 -1121
- package/dist/esm/services/FeatureFlagService.js +0 -956
- package/dist/esm/services/FileService.js +0 -982
- package/dist/esm/services/IntegrationService.js +0 -1319
- package/dist/esm/services/MetricsService.js +0 -843
- package/dist/esm/services/PaymentService.js +0 -1052
- package/dist/esm/services/PlanService.js +0 -1207
- package/dist/esm/services/ProjectService.js +0 -2526
- package/dist/esm/services/PullRequestService.js +0 -1284
- package/dist/esm/services/ScreenshotService.js +0 -1085
- package/dist/esm/services/SubscriptionService.js +0 -1177
- package/dist/esm/services/TrackingService.js +0 -18343
- package/dist/esm/services/WaitlistService.js +0 -929
- package/dist/esm/state/RootStateManager.js +0 -90
- package/dist/esm/state/rootEventBus.js +0 -56
- package/dist/esm/utils/CollabClient.js +0 -18901
- package/dist/esm/utils/TokenManager.js +0 -408
- package/dist/esm/utils/changePreprocessor.js +0 -542
- package/dist/esm/utils/jsonDiff.js +0 -7011
- package/dist/esm/utils/ordering.js +0 -291
- package/dist/node/services/AdminService.js +0 -332
- package/dist/node/services/BranchService.js +0 -465
- package/dist/node/services/CollabService.js +0 -724
- package/dist/node/services/DnsService.js +0 -321
- package/dist/node/services/FeatureFlagService.js +0 -156
- package/dist/node/services/FileService.js +0 -182
- package/dist/node/services/IntegrationService.js +0 -519
- package/dist/node/services/MetricsService.js +0 -43
- package/dist/node/services/PaymentService.js +0 -252
- package/dist/node/services/PlanService.js +0 -407
- package/dist/node/services/ProjectService.js +0 -1188
- package/dist/node/services/PullRequestService.js +0 -484
- package/dist/node/services/ScreenshotService.js +0 -285
- package/dist/node/services/SubscriptionService.js +0 -377
- package/dist/node/services/TrackingService.js +0 -632
- package/dist/node/services/WaitlistService.js +0 -129
- package/dist/node/state/RootStateManager.js +0 -36
- package/dist/node/state/rootEventBus.js +0 -55
- package/dist/node/utils/CollabClient.js +0 -194
- package/dist/node/utils/TokenManager.js +0 -403
- package/dist/node/utils/changePreprocessor.js +0 -180
- package/dist/node/utils/jsonDiff.js +0 -116
- package/dist/node/utils/ordering.js +0 -290
- package/src/services/AdminService.js +0 -374
- package/src/services/BranchService.js +0 -536
- package/src/services/CollabService.js +0 -900
- package/src/services/DnsService.js +0 -366
- package/src/services/FeatureFlagService.js +0 -174
- package/src/services/FileService.js +0 -213
- package/src/services/IntegrationService.js +0 -548
- package/src/services/MetricsService.js +0 -40
- package/src/services/PaymentService.js +0 -287
- package/src/services/PlanService.js +0 -468
- package/src/services/ProjectService.js +0 -1366
- package/src/services/PullRequestService.js +0 -537
- package/src/services/ScreenshotService.js +0 -258
- package/src/services/SubscriptionService.js +0 -425
- package/src/services/TrackingService.js +0 -853
- package/src/services/WaitlistService.js +0 -130
- package/src/services/tests/BranchService/createBranch.test.js +0 -153
- package/src/services/tests/BranchService/deleteBranch.test.js +0 -173
- package/src/services/tests/BranchService/getBranchChanges.test.js +0 -146
- package/src/services/tests/BranchService/listBranches.test.js +0 -87
- package/src/services/tests/BranchService/mergeBranch.test.js +0 -210
- package/src/services/tests/BranchService/publishVersion.test.js +0 -183
- package/src/services/tests/BranchService/renameBranch.test.js +0 -240
- package/src/services/tests/BranchService/resetBranch.test.js +0 -152
- package/src/services/tests/FeatureFlagService/adminFeatureFlags.test.js +0 -67
- package/src/services/tests/FeatureFlagService/getFeatureFlags.test.js +0 -75
- package/src/services/tests/FileService/createFileFormData.test.js +0 -74
- package/src/services/tests/FileService/getFileUrl.test.js +0 -69
- package/src/services/tests/FileService/updateProjectIcon.test.js +0 -109
- package/src/services/tests/FileService/uploadDocument.test.js +0 -36
- package/src/services/tests/FileService/uploadFile.test.js +0 -78
- package/src/services/tests/FileService/uploadFileWithValidation.test.js +0 -114
- package/src/services/tests/FileService/uploadImage.test.js +0 -36
- package/src/services/tests/FileService/uploadMultipleFiles.test.js +0 -111
- package/src/services/tests/FileService/validateFile.test.js +0 -63
- package/src/services/tests/PlanService/createPlan.test.js +0 -104
- package/src/services/tests/PlanService/createPlanWithValidation.test.js +0 -523
- package/src/services/tests/PlanService/deletePlan.test.js +0 -92
- package/src/services/tests/PlanService/getActivePlans.test.js +0 -123
- package/src/services/tests/PlanService/getAdminPlans.test.js +0 -84
- package/src/services/tests/PlanService/getPlan.test.js +0 -50
- package/src/services/tests/PlanService/getPlanByKey.test.js +0 -109
- package/src/services/tests/PlanService/getPlanWithValidation.test.js +0 -85
- package/src/services/tests/PlanService/getPlans.test.js +0 -53
- package/src/services/tests/PlanService/getPlansByPriceRange.test.js +0 -109
- package/src/services/tests/PlanService/getPlansWithValidation.test.js +0 -48
- package/src/services/tests/PlanService/initializePlans.test.js +0 -75
- package/src/services/tests/PlanService/updatePlan.test.js +0 -111
- package/src/services/tests/PlanService/updatePlanWithValidation.test.js +0 -556
- package/src/state/RootStateManager.js +0 -76
- package/src/state/rootEventBus.js +0 -67
- package/src/utils/CollabClient.js +0 -248
- package/src/utils/TokenManager.js +0 -479
- package/src/utils/changePreprocessor.js +0 -239
- package/src/utils/jsonDiff.js +0 -144
- package/src/utils/ordering.js +0 -271
|
@@ -1,745 +1,153 @@
|
|
|
1
1
|
import { BaseService } from "./BaseService.js";
|
|
2
2
|
import {
|
|
3
|
+
PERMISSION_MAP,
|
|
3
4
|
ROLE_PERMISSIONS,
|
|
4
5
|
TIER_FEATURES,
|
|
5
6
|
PROJECT_ROLE_PERMISSIONS
|
|
6
7
|
} from "../utils/permission.js";
|
|
7
|
-
const PLUGIN_SESSION_STORAGE_KEY = "plugin_auth_session";
|
|
8
8
|
class AuthService extends BaseService {
|
|
9
9
|
constructor(config) {
|
|
10
|
-
var _a, _b;
|
|
11
10
|
super(config);
|
|
12
11
|
this._userRoles = /* @__PURE__ */ new Set(["guest", "editor", "admin", "owner"]);
|
|
13
12
|
this._projectTiers = /* @__PURE__ */ new Set([
|
|
14
13
|
"ready",
|
|
15
|
-
"
|
|
14
|
+
"free",
|
|
16
15
|
"pro1",
|
|
17
16
|
"pro2",
|
|
18
17
|
"enterprise"
|
|
19
18
|
]);
|
|
20
|
-
this.
|
|
21
|
-
this._roleCacheExpiry = 5 * 60 * 1e3;
|
|
22
|
-
this._pluginSession = null;
|
|
23
|
-
this._resolvePluginSession(
|
|
24
|
-
(config == null ? void 0 : config.session) || (config == null ? void 0 : config.pluginSession) || ((_a = config == null ? void 0 : config.options) == null ? void 0 : _a.pluginSession) || ((_b = config == null ? void 0 : config.context) == null ? void 0 : _b.pluginSession) || null
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
// Use BaseService.init/_request/_requireReady implementations
|
|
28
|
-
// ==================== AUTH METHODS ====================
|
|
29
|
-
async register(userData, options = {}) {
|
|
30
|
-
try {
|
|
31
|
-
const { payload, session } = this._preparePluginPayload(
|
|
32
|
-
{ ...userData || {} },
|
|
33
|
-
options.session
|
|
34
|
-
);
|
|
35
|
-
const response = await this._request("/auth/register", {
|
|
36
|
-
method: "POST",
|
|
37
|
-
body: JSON.stringify(payload),
|
|
38
|
-
methodName: "register"
|
|
39
|
-
});
|
|
40
|
-
if (response.success) {
|
|
41
|
-
if (session) {
|
|
42
|
-
this._clearPluginSession(session);
|
|
43
|
-
}
|
|
44
|
-
return response.data;
|
|
45
|
-
}
|
|
46
|
-
throw new Error(response.message);
|
|
47
|
-
} catch (error) {
|
|
48
|
-
throw new Error(`Registration failed: ${error.message}`, { cause: error });
|
|
49
|
-
}
|
|
19
|
+
this._initialized = false;
|
|
50
20
|
}
|
|
51
|
-
|
|
52
|
-
|
|
21
|
+
// eslint-disable-next-line no-empty-pattern
|
|
22
|
+
init({}) {
|
|
53
23
|
try {
|
|
54
|
-
const {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
);
|
|
61
|
-
const response = await this._request("/auth/login", {
|
|
62
|
-
method: "POST",
|
|
63
|
-
body: JSON.stringify(payload),
|
|
64
|
-
methodName: "login"
|
|
65
|
-
});
|
|
66
|
-
if (response.success && response.data && response.data.tokens) {
|
|
67
|
-
const { tokens } = response.data;
|
|
68
|
-
const tokenData = {
|
|
69
|
-
access_token: tokens.accessToken,
|
|
70
|
-
refresh_token: tokens.refreshToken,
|
|
71
|
-
expires_in: (_a = tokens.accessTokenExp) == null ? void 0 : _a.expiresIn,
|
|
72
|
-
token_type: "Bearer"
|
|
73
|
-
};
|
|
74
|
-
if (this._tokenManager) {
|
|
75
|
-
this._tokenManager.setTokens(tokenData);
|
|
24
|
+
const { authToken, appKey } = this._context || {};
|
|
25
|
+
this._info = {
|
|
26
|
+
config: {
|
|
27
|
+
appKey: appKey ? `${appKey.substr(0, 4)}...${appKey.substr(-4)}` : void 0,
|
|
28
|
+
// eslint-disable-line no-undefined
|
|
29
|
+
hasToken: Boolean(authToken)
|
|
76
30
|
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
this._clearPluginSession(session);
|
|
81
|
-
}
|
|
82
|
-
return response.data;
|
|
83
|
-
}
|
|
84
|
-
throw new Error(response.message);
|
|
85
|
-
} catch (error) {
|
|
86
|
-
throw new Error(`Login failed: ${error.message}`, { cause: error });
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
async logout() {
|
|
90
|
-
this._requireReady("logout");
|
|
91
|
-
try {
|
|
92
|
-
await this._request("/auth/logout", {
|
|
93
|
-
method: "POST",
|
|
94
|
-
methodName: "logout"
|
|
95
|
-
});
|
|
96
|
-
if (this._tokenManager) {
|
|
97
|
-
this._tokenManager.clearTokens();
|
|
98
|
-
}
|
|
99
|
-
} catch (error) {
|
|
100
|
-
if (this._tokenManager) {
|
|
101
|
-
this._tokenManager.clearTokens();
|
|
102
|
-
}
|
|
103
|
-
throw new Error(`Logout failed: ${error.message}`, { cause: error });
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
async refreshToken(refreshToken) {
|
|
107
|
-
try {
|
|
108
|
-
const response = await this._request("/auth/refresh", {
|
|
109
|
-
method: "POST",
|
|
110
|
-
body: JSON.stringify({ refreshToken }),
|
|
111
|
-
methodName: "refreshToken"
|
|
112
|
-
});
|
|
113
|
-
if (response.success) {
|
|
114
|
-
return response.data;
|
|
115
|
-
}
|
|
116
|
-
throw new Error(response.message);
|
|
31
|
+
};
|
|
32
|
+
this._initialized = true;
|
|
33
|
+
this._setReady();
|
|
117
34
|
} catch (error) {
|
|
118
|
-
|
|
119
|
-
|
|
35
|
+
this._setError(error);
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
_requiresInit(methodName) {
|
|
40
|
+
const noInitMethods = /* @__PURE__ */ new Set([
|
|
41
|
+
"users:login",
|
|
42
|
+
"users:register",
|
|
43
|
+
"users:request-password-reset",
|
|
44
|
+
"users:reset-password",
|
|
45
|
+
"users:reset-password-confirm",
|
|
46
|
+
"users:register-confirmation",
|
|
47
|
+
"users:google-auth",
|
|
48
|
+
"users:github-auth"
|
|
49
|
+
]);
|
|
50
|
+
return !noInitMethods.has(methodName);
|
|
120
51
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const { payload, session } = this._preparePluginPayload({ idToken }, options.session);
|
|
125
|
-
if (inviteToken) {
|
|
126
|
-
payload.inviteToken = inviteToken;
|
|
127
|
-
}
|
|
128
|
-
const response = await this._request("/auth/google", {
|
|
129
|
-
method: "POST",
|
|
130
|
-
body: JSON.stringify(payload),
|
|
131
|
-
methodName: "googleAuth"
|
|
132
|
-
});
|
|
133
|
-
if (response.success && response.data && response.data.tokens) {
|
|
134
|
-
const { tokens } = response.data;
|
|
135
|
-
const tokenData = {
|
|
136
|
-
access_token: tokens.accessToken,
|
|
137
|
-
refresh_token: tokens.refreshToken,
|
|
138
|
-
expires_in: (_a = tokens.accessTokenExp) == null ? void 0 : _a.expiresIn,
|
|
139
|
-
token_type: "Bearer"
|
|
140
|
-
};
|
|
141
|
-
if (this._tokenManager) {
|
|
142
|
-
this._tokenManager.setTokens(tokenData);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
if (response.success) {
|
|
146
|
-
if (session) {
|
|
147
|
-
this._clearPluginSession(session);
|
|
148
|
-
}
|
|
149
|
-
return response.data;
|
|
150
|
-
}
|
|
151
|
-
throw new Error(response.message);
|
|
152
|
-
} catch (error) {
|
|
153
|
-
throw new Error(`Google auth failed: ${error.message}`, { cause: error });
|
|
52
|
+
_requireReady(methodName) {
|
|
53
|
+
if (this._requiresInit(methodName) && !this._initialized) {
|
|
54
|
+
throw new Error("Service not initialized");
|
|
154
55
|
}
|
|
155
56
|
}
|
|
156
|
-
|
|
57
|
+
_getBasedService(methodName) {
|
|
157
58
|
var _a;
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
payload.inviteToken = inviteToken;
|
|
162
|
-
}
|
|
163
|
-
const response = await this._request("/auth/github", {
|
|
164
|
-
method: "POST",
|
|
165
|
-
body: JSON.stringify(payload),
|
|
166
|
-
methodName: "githubAuth"
|
|
167
|
-
});
|
|
168
|
-
if (response.success && response.data && response.data.tokens) {
|
|
169
|
-
const { tokens } = response.data;
|
|
170
|
-
const tokenData = {
|
|
171
|
-
access_token: tokens.accessToken,
|
|
172
|
-
refresh_token: tokens.refreshToken,
|
|
173
|
-
expires_in: (_a = tokens.accessTokenExp) == null ? void 0 : _a.expiresIn,
|
|
174
|
-
token_type: "Bearer"
|
|
175
|
-
};
|
|
176
|
-
if (this._tokenManager) {
|
|
177
|
-
this._tokenManager.setTokens(tokenData);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
if (response.success) {
|
|
181
|
-
if (session) {
|
|
182
|
-
this._clearPluginSession(session);
|
|
183
|
-
}
|
|
184
|
-
return response.data;
|
|
185
|
-
}
|
|
186
|
-
throw new Error(response.message);
|
|
187
|
-
} catch (error) {
|
|
188
|
-
throw new Error(`GitHub auth failed: ${error.message}`, { cause: error });
|
|
59
|
+
const based = (_a = this._context.services) == null ? void 0 : _a.based;
|
|
60
|
+
if (this._requiresInit(methodName) && !based) {
|
|
61
|
+
throw new Error("Based service not available");
|
|
189
62
|
}
|
|
63
|
+
return based._client;
|
|
190
64
|
}
|
|
191
|
-
async
|
|
192
|
-
var _a;
|
|
65
|
+
async login(identifier, password) {
|
|
193
66
|
try {
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
67
|
+
const based = this._getBasedService("login");
|
|
68
|
+
const response = await based.call("users:login", { identifier, password });
|
|
69
|
+
if (this._initialized) {
|
|
70
|
+
this.updateContext({ authToken: response.token });
|
|
71
|
+
}
|
|
72
|
+
based.setAuthState({
|
|
73
|
+
token: response.token,
|
|
74
|
+
userId: response.userId,
|
|
75
|
+
projectRoles: response.projectRoles,
|
|
76
|
+
globalRole: response.globalRole,
|
|
77
|
+
persistent: true
|
|
205
78
|
});
|
|
206
|
-
|
|
207
|
-
const { tokens } = response.data;
|
|
208
|
-
const tokenData = {
|
|
209
|
-
access_token: tokens.accessToken,
|
|
210
|
-
refresh_token: tokens.refreshToken,
|
|
211
|
-
expires_in: (_a = tokens.accessTokenExp) == null ? void 0 : _a.expiresIn,
|
|
212
|
-
token_type: "Bearer"
|
|
213
|
-
};
|
|
214
|
-
if (this._tokenManager) {
|
|
215
|
-
this._tokenManager.setTokens(tokenData);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
if (response.success) {
|
|
219
|
-
if (session) {
|
|
220
|
-
this._clearPluginSession(session);
|
|
221
|
-
}
|
|
222
|
-
return response.data;
|
|
223
|
-
}
|
|
224
|
-
throw new Error(response.message);
|
|
79
|
+
return response;
|
|
225
80
|
} catch (error) {
|
|
226
|
-
throw new Error(`
|
|
81
|
+
throw new Error(`Login failed: ${error.message}`);
|
|
227
82
|
}
|
|
228
83
|
}
|
|
229
|
-
async
|
|
84
|
+
async register(userData) {
|
|
230
85
|
try {
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
body: JSON.stringify({ email }),
|
|
234
|
-
methodName: "requestPasswordReset"
|
|
235
|
-
});
|
|
236
|
-
if (response.success) {
|
|
237
|
-
return response.data;
|
|
238
|
-
}
|
|
239
|
-
throw new Error(response.message);
|
|
86
|
+
const based = this._getBasedService("register");
|
|
87
|
+
return await based.call("users:register", userData);
|
|
240
88
|
} catch (error) {
|
|
241
|
-
throw new Error(`
|
|
89
|
+
throw new Error(`Registration failed: ${error.message}`);
|
|
242
90
|
}
|
|
243
91
|
}
|
|
244
|
-
async
|
|
92
|
+
async googleAuth(idToken) {
|
|
245
93
|
try {
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
body: JSON.stringify({ token, password }),
|
|
249
|
-
methodName: "confirmPasswordReset"
|
|
250
|
-
});
|
|
251
|
-
if (response.success) {
|
|
252
|
-
return response.data;
|
|
253
|
-
}
|
|
254
|
-
throw new Error(response.message);
|
|
94
|
+
const based = this._getBasedService("googleAuth");
|
|
95
|
+
return await based.call("users:google-auth", { idToken });
|
|
255
96
|
} catch (error) {
|
|
256
|
-
throw new Error(`
|
|
97
|
+
throw new Error(`Google auth failed: ${error.message}`);
|
|
257
98
|
}
|
|
258
99
|
}
|
|
259
|
-
async
|
|
100
|
+
async githubAuth(code) {
|
|
260
101
|
try {
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
body: JSON.stringify({ token }),
|
|
264
|
-
methodName: "confirmRegistration"
|
|
265
|
-
});
|
|
266
|
-
if (response.success) {
|
|
267
|
-
return response.data;
|
|
268
|
-
}
|
|
269
|
-
throw new Error(response.message);
|
|
102
|
+
const based = this._getBasedService("githubAuth");
|
|
103
|
+
return await based.call("users:github-auth", { code });
|
|
270
104
|
} catch (error) {
|
|
271
|
-
throw new Error(`
|
|
105
|
+
throw new Error(`GitHub auth failed: ${error.message}`);
|
|
272
106
|
}
|
|
273
107
|
}
|
|
274
|
-
async
|
|
275
|
-
this._requireReady("
|
|
276
|
-
try {
|
|
277
|
-
const response = await this._request("/auth/request-password-change", {
|
|
278
|
-
method: "POST",
|
|
279
|
-
methodName: "requestPasswordChange"
|
|
280
|
-
});
|
|
281
|
-
if (response.success) {
|
|
282
|
-
return response.data;
|
|
283
|
-
}
|
|
284
|
-
throw new Error(response.message);
|
|
285
|
-
} catch (error) {
|
|
286
|
-
throw new Error(`Password change request failed: ${error.message}`, { cause: error });
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
async confirmPasswordChange(currentPassword, newPassword, code) {
|
|
290
|
-
this._requireReady("confirmPasswordChange");
|
|
291
|
-
try {
|
|
292
|
-
const response = await this._request("/auth/confirm-password-change", {
|
|
293
|
-
method: "POST",
|
|
294
|
-
body: JSON.stringify({ currentPassword, newPassword, code }),
|
|
295
|
-
methodName: "confirmPasswordChange"
|
|
296
|
-
});
|
|
297
|
-
if (response.success) {
|
|
298
|
-
return response.data;
|
|
299
|
-
}
|
|
300
|
-
throw new Error(response.message);
|
|
301
|
-
} catch (error) {
|
|
302
|
-
throw new Error(`Password change confirmation failed: ${error.message}`, { cause: error });
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
async getMe(options = {}) {
|
|
306
|
-
this._requireReady("getMe");
|
|
307
|
-
try {
|
|
308
|
-
const session = this._resolvePluginSession(options.session);
|
|
309
|
-
const endpoint = session ? `/auth/me?session=${encodeURIComponent(session)}` : "/auth/me";
|
|
310
|
-
const response = await this._request(endpoint, {
|
|
311
|
-
method: "GET",
|
|
312
|
-
methodName: "getMe"
|
|
313
|
-
});
|
|
314
|
-
if (response.success) {
|
|
315
|
-
return response.data;
|
|
316
|
-
}
|
|
317
|
-
throw new Error(response.message);
|
|
318
|
-
} catch (error) {
|
|
319
|
-
throw new Error(`Failed to get user profile: ${error.message}`, { cause: error });
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
getAuthToken() {
|
|
323
|
-
if (!this._tokenManager) {
|
|
324
|
-
return null;
|
|
325
|
-
}
|
|
326
|
-
return this._tokenManager.getAccessToken();
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* Get stored authentication state (backward compatibility method)
|
|
330
|
-
* Replaces AuthService.getStoredAuthState()
|
|
331
|
-
*/
|
|
332
|
-
async getStoredAuthState() {
|
|
333
|
-
try {
|
|
334
|
-
if (!this._tokenManager) {
|
|
335
|
-
return {
|
|
336
|
-
userId: false,
|
|
337
|
-
authToken: false
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
|
-
const tokenStatus = this._tokenManager.getTokenStatus();
|
|
341
|
-
if (!tokenStatus.hasTokens) {
|
|
342
|
-
return {
|
|
343
|
-
userId: false,
|
|
344
|
-
authToken: false
|
|
345
|
-
};
|
|
346
|
-
}
|
|
347
|
-
if (!tokenStatus.isValid && tokenStatus.hasRefreshToken) {
|
|
348
|
-
try {
|
|
349
|
-
await this._tokenManager.ensureValidToken();
|
|
350
|
-
} catch (error) {
|
|
351
|
-
console.warn("[AuthService] Token refresh failed:", error.message);
|
|
352
|
-
if (error.message.includes("401") || error.message.includes("403") || error.message.includes("invalid") || error.message.includes("expired")) {
|
|
353
|
-
this._tokenManager.clearTokens();
|
|
354
|
-
return {
|
|
355
|
-
userId: false,
|
|
356
|
-
authToken: false,
|
|
357
|
-
error: `Authentication failed: ${error.message}`
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
return {
|
|
361
|
-
userId: false,
|
|
362
|
-
authToken: this._tokenManager.getAccessToken(),
|
|
363
|
-
error: `Network error during token refresh: ${error.message}`,
|
|
364
|
-
hasTokens: true
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
const currentAccessToken = this._tokenManager.getAccessToken();
|
|
369
|
-
if (!currentAccessToken) {
|
|
370
|
-
return {
|
|
371
|
-
userId: false,
|
|
372
|
-
authToken: false
|
|
373
|
-
};
|
|
374
|
-
}
|
|
375
|
-
try {
|
|
376
|
-
const currentUser = await this.getMe();
|
|
377
|
-
return {
|
|
378
|
-
userId: currentUser.user.id,
|
|
379
|
-
authToken: currentAccessToken,
|
|
380
|
-
...currentUser,
|
|
381
|
-
error: null
|
|
382
|
-
};
|
|
383
|
-
} catch (error) {
|
|
384
|
-
console.warn("[AuthService] Failed to get user data:", error.message);
|
|
385
|
-
if (error.message.includes("401") || error.message.includes("403")) {
|
|
386
|
-
this._tokenManager.clearTokens();
|
|
387
|
-
return {
|
|
388
|
-
userId: false,
|
|
389
|
-
authToken: false,
|
|
390
|
-
error: `Authentication failed: ${error.message}`
|
|
391
|
-
};
|
|
392
|
-
}
|
|
393
|
-
return {
|
|
394
|
-
userId: false,
|
|
395
|
-
authToken: currentAccessToken,
|
|
396
|
-
error: `Failed to get user data: ${error.message}`,
|
|
397
|
-
hasTokens: true
|
|
398
|
-
};
|
|
399
|
-
}
|
|
400
|
-
} catch (error) {
|
|
401
|
-
console.error(
|
|
402
|
-
"[AuthService] Unexpected error in getStoredAuthState:",
|
|
403
|
-
error
|
|
404
|
-
);
|
|
405
|
-
return {
|
|
406
|
-
userId: false,
|
|
407
|
-
authToken: false,
|
|
408
|
-
error: `Failed to get stored auth state: ${error.message}`
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
// ==================== USER METHODS ====================
|
|
413
|
-
async getUserProfile() {
|
|
414
|
-
this._requireReady("getUserProfile");
|
|
415
|
-
try {
|
|
416
|
-
const response = await this._request("/users/profile", {
|
|
417
|
-
method: "GET",
|
|
418
|
-
methodName: "getUserProfile"
|
|
419
|
-
});
|
|
420
|
-
if (response.success) {
|
|
421
|
-
return response.data;
|
|
422
|
-
}
|
|
423
|
-
throw new Error(response.message);
|
|
424
|
-
} catch (error) {
|
|
425
|
-
throw new Error(`Failed to get user profile: ${error.message}`, { cause: error });
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
async updateUserProfile(profileData) {
|
|
429
|
-
this._requireReady("updateUserProfile");
|
|
430
|
-
try {
|
|
431
|
-
const response = await this._request("/users/profile", {
|
|
432
|
-
method: "PATCH",
|
|
433
|
-
body: JSON.stringify(profileData),
|
|
434
|
-
methodName: "updateUserProfile"
|
|
435
|
-
});
|
|
436
|
-
if (response.success) {
|
|
437
|
-
return response.data;
|
|
438
|
-
}
|
|
439
|
-
throw new Error(response.message);
|
|
440
|
-
} catch (error) {
|
|
441
|
-
throw new Error(`Failed to update user profile: ${error.message}`, { cause: error });
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
async getUserProjects() {
|
|
445
|
-
this._requireReady("getUserProjects");
|
|
108
|
+
async logout() {
|
|
109
|
+
this._requireReady("logout");
|
|
446
110
|
try {
|
|
447
|
-
const
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
});
|
|
451
|
-
if (response.success) {
|
|
452
|
-
return response.data.map((project) => ({
|
|
453
|
-
...project,
|
|
454
|
-
...project.icon && {
|
|
455
|
-
icon: {
|
|
456
|
-
src: `${this._apiUrl}/core/files/public/${project.icon.id}/download`,
|
|
457
|
-
...project.icon
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
}));
|
|
461
|
-
}
|
|
462
|
-
throw new Error(response.message);
|
|
111
|
+
const based = this._getBasedService("logout");
|
|
112
|
+
await based.call("logout");
|
|
113
|
+
this.updateContext({ authToken: null });
|
|
463
114
|
} catch (error) {
|
|
464
|
-
throw new Error(`
|
|
115
|
+
throw new Error(`Logout failed: ${error.message}`);
|
|
465
116
|
}
|
|
466
117
|
}
|
|
467
|
-
async
|
|
468
|
-
this._requireReady("
|
|
118
|
+
async updateUserRole(userId, newRole) {
|
|
119
|
+
this._requireReady("updateUserRole");
|
|
469
120
|
if (!userId) {
|
|
470
121
|
throw new Error("User ID is required");
|
|
471
122
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
method: "GET",
|
|
475
|
-
methodName: "getUser"
|
|
476
|
-
});
|
|
477
|
-
if (response.success) {
|
|
478
|
-
return response.data;
|
|
479
|
-
}
|
|
480
|
-
throw new Error(response.message);
|
|
481
|
-
} catch (error) {
|
|
482
|
-
throw new Error(`Failed to get user: ${error.message}`, { cause: error });
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
async getUserByEmail(email) {
|
|
486
|
-
this._requireReady("getUserByEmail");
|
|
487
|
-
if (!email) {
|
|
488
|
-
throw new Error("Email is required");
|
|
123
|
+
if (!this._userRoles.has(newRole)) {
|
|
124
|
+
throw new Error(`Invalid role: ${newRole}`);
|
|
489
125
|
}
|
|
490
126
|
try {
|
|
491
|
-
const
|
|
492
|
-
|
|
493
|
-
methodName: "getUserByEmail"
|
|
494
|
-
});
|
|
495
|
-
if (response.success) {
|
|
496
|
-
return response.data.user;
|
|
497
|
-
}
|
|
498
|
-
throw new Error(response.message);
|
|
127
|
+
const based = this._getBasedService("updateUserRole");
|
|
128
|
+
return await based.call("users:update-role", { userId, role: newRole });
|
|
499
129
|
} catch (error) {
|
|
500
|
-
throw new Error(`Failed to
|
|
130
|
+
throw new Error(`Failed to update user role: ${error.message}`);
|
|
501
131
|
}
|
|
502
132
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
* Get the current user's role for a specific project by project ID
|
|
506
|
-
* Uses caching to avoid repeated API calls
|
|
507
|
-
*/
|
|
508
|
-
async getMyProjectRole(projectId) {
|
|
509
|
-
this._requireReady("getMyProjectRole");
|
|
133
|
+
async updateProjectTier(projectId, newTier) {
|
|
134
|
+
this._requireReady("updateProjectTier");
|
|
510
135
|
if (!projectId) {
|
|
511
136
|
throw new Error("Project ID is required");
|
|
512
137
|
}
|
|
513
|
-
if (!this.
|
|
514
|
-
|
|
515
|
-
}
|
|
516
|
-
const cacheKey = `role_${projectId}`;
|
|
517
|
-
const cached = this._projectRoleCache.get(cacheKey);
|
|
518
|
-
if (cached && Date.now() - cached.timestamp < this._roleCacheExpiry) {
|
|
519
|
-
return cached.role;
|
|
520
|
-
}
|
|
521
|
-
try {
|
|
522
|
-
const response = await this._request(`/projects/${projectId}/role`, {
|
|
523
|
-
method: "GET",
|
|
524
|
-
methodName: "getMyProjectRole"
|
|
525
|
-
});
|
|
526
|
-
if (response.success) {
|
|
527
|
-
const { role } = response.data;
|
|
528
|
-
this._projectRoleCache.set(cacheKey, {
|
|
529
|
-
role,
|
|
530
|
-
timestamp: Date.now()
|
|
531
|
-
});
|
|
532
|
-
return role;
|
|
533
|
-
}
|
|
534
|
-
throw new Error(response.message);
|
|
535
|
-
} catch (error) {
|
|
536
|
-
const message = (error == null ? void 0 : error.message) || "";
|
|
537
|
-
if (/401|403|unauthorized|no token|invalid token/iu.test(message)) {
|
|
538
|
-
return "guest";
|
|
539
|
-
}
|
|
540
|
-
throw new Error(`Failed to get project role: ${message}`, { cause: error });
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
/**
|
|
544
|
-
* Get the current user's role for a specific project by project key
|
|
545
|
-
* Uses caching to avoid repeated API calls
|
|
546
|
-
*/
|
|
547
|
-
async getMyProjectRoleByKey(projectKey) {
|
|
548
|
-
this._requireReady("getMyProjectRoleByKey");
|
|
549
|
-
if (!projectKey) {
|
|
550
|
-
throw new Error("Project key is required");
|
|
551
|
-
}
|
|
552
|
-
if (!this.hasValidTokens()) {
|
|
553
|
-
return "guest";
|
|
554
|
-
}
|
|
555
|
-
const cacheKey = `role_key_${projectKey}`;
|
|
556
|
-
const cached = this._projectRoleCache.get(cacheKey);
|
|
557
|
-
if (cached && Date.now() - cached.timestamp < this._roleCacheExpiry) {
|
|
558
|
-
return cached.role;
|
|
138
|
+
if (!this._projectTiers.has(newTier)) {
|
|
139
|
+
throw new Error(`Invalid project tier: ${newTier}`);
|
|
559
140
|
}
|
|
560
141
|
try {
|
|
561
|
-
const
|
|
562
|
-
|
|
563
|
-
|
|
142
|
+
const based = this._getBasedService("updateProjectTier");
|
|
143
|
+
return await based.call("projects:update-tier", {
|
|
144
|
+
projectId,
|
|
145
|
+
tier: newTier
|
|
564
146
|
});
|
|
565
|
-
if (response.success) {
|
|
566
|
-
const { role } = response.data;
|
|
567
|
-
this._projectRoleCache.set(cacheKey, {
|
|
568
|
-
role,
|
|
569
|
-
timestamp: Date.now()
|
|
570
|
-
});
|
|
571
|
-
return role;
|
|
572
|
-
}
|
|
573
|
-
throw new Error(response.message);
|
|
574
|
-
} catch (error) {
|
|
575
|
-
const message = (error == null ? void 0 : error.message) || "";
|
|
576
|
-
if (/401|403|unauthorized|no token|invalid token/iu.test(message)) {
|
|
577
|
-
return "guest";
|
|
578
|
-
}
|
|
579
|
-
throw new Error(`Failed to get project role by key: ${message}`, { cause: error });
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
/**
|
|
583
|
-
* Clear the project role cache for a specific project or all projects
|
|
584
|
-
*/
|
|
585
|
-
clearProjectRoleCache(projectId = null) {
|
|
586
|
-
if (projectId) {
|
|
587
|
-
this._projectRoleCache.delete(`role_${projectId}`);
|
|
588
|
-
for (const [key] of this._projectRoleCache) {
|
|
589
|
-
if (key.startsWith("role_key_")) {
|
|
590
|
-
this._projectRoleCache.delete(key);
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
} else {
|
|
594
|
-
this._projectRoleCache.clear();
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
/**
|
|
598
|
-
* Get project role with fallback to user projects list
|
|
599
|
-
* This method tries to get the role from user projects first,
|
|
600
|
-
* then falls back to API call if not found
|
|
601
|
-
*/
|
|
602
|
-
async getProjectRoleWithFallback(projectId, userProjects = null) {
|
|
603
|
-
this._requireReady("getProjectRoleWithFallback");
|
|
604
|
-
if (!projectId) {
|
|
605
|
-
throw new Error("Project ID is required");
|
|
606
|
-
}
|
|
607
|
-
if (userProjects && Array.isArray(userProjects)) {
|
|
608
|
-
const userProject = userProjects.find((p) => p.id === projectId);
|
|
609
|
-
if (userProject && userProject.role) {
|
|
610
|
-
return userProject.role;
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
return await this.getMyProjectRole(projectId);
|
|
614
|
-
}
|
|
615
|
-
/**
|
|
616
|
-
* Get project role with fallback to user projects list (by project key)
|
|
617
|
-
* This method tries to get the role from user projects first,
|
|
618
|
-
* then falls back to API call if not found
|
|
619
|
-
*/
|
|
620
|
-
async getProjectRoleByKeyWithFallback(projectKey, userProjects = null) {
|
|
621
|
-
this._requireReady("getProjectRoleByKeyWithFallback");
|
|
622
|
-
if (!projectKey) {
|
|
623
|
-
throw new Error("Project key is required");
|
|
624
|
-
}
|
|
625
|
-
if (userProjects && Array.isArray(userProjects)) {
|
|
626
|
-
const userProject = userProjects.find((p) => p.key === projectKey);
|
|
627
|
-
if (userProject && userProject.role) {
|
|
628
|
-
return userProject.role;
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
return await this.getMyProjectRoleByKey(projectKey);
|
|
632
|
-
}
|
|
633
|
-
// ==================== AUTH HELPER METHODS ====================
|
|
634
|
-
/**
|
|
635
|
-
* Debug method to check token status
|
|
636
|
-
*/
|
|
637
|
-
getTokenDebugInfo() {
|
|
638
|
-
if (!this._tokenManager) {
|
|
639
|
-
return {
|
|
640
|
-
tokenManagerExists: false,
|
|
641
|
-
error: "TokenManager not initialized"
|
|
642
|
-
};
|
|
643
|
-
}
|
|
644
|
-
const tokenStatus = this._tokenManager.getTokenStatus();
|
|
645
|
-
const { tokens } = this._tokenManager;
|
|
646
|
-
return {
|
|
647
|
-
tokenManagerExists: true,
|
|
648
|
-
tokenStatus,
|
|
649
|
-
hasAccessToken: Boolean(tokens.accessToken),
|
|
650
|
-
hasRefreshToken: Boolean(tokens.refreshToken),
|
|
651
|
-
accessTokenPreview: tokens.accessToken ? `${tokens.accessToken.substring(0, 20)}...` : null,
|
|
652
|
-
expiresAt: tokens.expiresAt,
|
|
653
|
-
timeToExpiry: tokenStatus.timeToExpiry,
|
|
654
|
-
authHeader: this._tokenManager.getAuthHeader()
|
|
655
|
-
};
|
|
656
|
-
}
|
|
657
|
-
/**
|
|
658
|
-
* Helper method to check if user is authenticated
|
|
659
|
-
*/
|
|
660
|
-
isAuthenticated() {
|
|
661
|
-
if (!this._tokenManager) {
|
|
662
|
-
return false;
|
|
663
|
-
}
|
|
664
|
-
return this._tokenManager.hasTokens();
|
|
665
|
-
}
|
|
666
|
-
/**
|
|
667
|
-
* Helper method to check if user has valid tokens
|
|
668
|
-
*/
|
|
669
|
-
hasValidTokens() {
|
|
670
|
-
if (!this._tokenManager) {
|
|
671
|
-
return false;
|
|
672
|
-
}
|
|
673
|
-
return this._tokenManager.hasTokens() && this._tokenManager.isAccessTokenValid();
|
|
674
|
-
}
|
|
675
|
-
/**
|
|
676
|
-
* Helper method to get current user info
|
|
677
|
-
*/
|
|
678
|
-
async getCurrentUser() {
|
|
679
|
-
try {
|
|
680
|
-
return await this.getMe();
|
|
681
147
|
} catch (error) {
|
|
682
|
-
throw new Error(`Failed to
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
/**
|
|
686
|
-
* Helper method to validate user data for registration
|
|
687
|
-
*/
|
|
688
|
-
validateRegistrationData(userData) {
|
|
689
|
-
const errors = [];
|
|
690
|
-
if (!userData.email || typeof userData.email !== "string") {
|
|
691
|
-
errors.push("Email is required and must be a string");
|
|
692
|
-
} else if (!this._isValidEmail(userData.email)) {
|
|
693
|
-
errors.push("Email must be a valid email address");
|
|
694
|
-
}
|
|
695
|
-
if (!userData.password || typeof userData.password !== "string") {
|
|
696
|
-
errors.push("Password is required and must be a string");
|
|
697
|
-
} else if (userData.password.length < 8) {
|
|
698
|
-
errors.push("Password must be at least 8 characters long");
|
|
699
|
-
}
|
|
700
|
-
if (userData.username && typeof userData.username !== "string") {
|
|
701
|
-
errors.push("Username must be a string");
|
|
702
|
-
} else if (userData.username && userData.username.length < 3) {
|
|
703
|
-
errors.push("Username must be at least 3 characters long");
|
|
148
|
+
throw new Error(`Failed to update project tier: ${error.message}`);
|
|
704
149
|
}
|
|
705
|
-
return {
|
|
706
|
-
isValid: errors.length === 0,
|
|
707
|
-
errors
|
|
708
|
-
};
|
|
709
|
-
}
|
|
710
|
-
/**
|
|
711
|
-
* Helper method to register with validation
|
|
712
|
-
*/
|
|
713
|
-
async registerWithValidation(userData, options = {}) {
|
|
714
|
-
const validation = this.validateRegistrationData(userData);
|
|
715
|
-
if (!validation.isValid) {
|
|
716
|
-
throw new Error(`Validation failed: ${validation.errors.join(", ")}`);
|
|
717
|
-
}
|
|
718
|
-
return await this.register(userData, options);
|
|
719
|
-
}
|
|
720
|
-
/**
|
|
721
|
-
* Helper method to login with validation
|
|
722
|
-
*/
|
|
723
|
-
async loginWithValidation(email, password, options = {}) {
|
|
724
|
-
if (!email || typeof email !== "string") {
|
|
725
|
-
throw new Error("Email is required and must be a string");
|
|
726
|
-
}
|
|
727
|
-
if (!password || typeof password !== "string") {
|
|
728
|
-
throw new Error("Password is required and must be a string");
|
|
729
|
-
}
|
|
730
|
-
if (!this._isValidEmail(email)) {
|
|
731
|
-
throw new Error("Email must be a valid email address");
|
|
732
|
-
}
|
|
733
|
-
return await this.login(email, password, options);
|
|
734
|
-
}
|
|
735
|
-
/**
|
|
736
|
-
* Private helper to validate email format
|
|
737
|
-
*/
|
|
738
|
-
_isValidEmail(email) {
|
|
739
|
-
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/u;
|
|
740
|
-
return emailRegex.test(email);
|
|
741
150
|
}
|
|
742
|
-
// ==================== PERMISSION METHODS (Existing) ====================
|
|
743
151
|
hasPermission(requiredPermission) {
|
|
744
152
|
var _a;
|
|
745
153
|
const authState = (_a = this._context) == null ? void 0 : _a.state;
|
|
@@ -788,17 +196,23 @@ class AuthService extends BaseService {
|
|
|
788
196
|
if (!operationConfig) {
|
|
789
197
|
return false;
|
|
790
198
|
}
|
|
199
|
+
if (!operationConfig) {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
791
202
|
const { permissions = [], features = [] } = operationConfig;
|
|
792
203
|
try {
|
|
793
204
|
const permissionResults = await Promise.all(
|
|
794
205
|
permissions.map(
|
|
795
|
-
(permission) => this.
|
|
206
|
+
(permission) => this.hasProjectPermission(projectId, permission)
|
|
796
207
|
)
|
|
797
208
|
);
|
|
798
209
|
const hasPermissions = requireAll ? permissionResults.every(Boolean) : permissionResults.some(Boolean);
|
|
799
210
|
if (!hasPermissions) {
|
|
800
211
|
return false;
|
|
801
212
|
}
|
|
213
|
+
if (!hasPermissions) {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
802
216
|
if (checkFeatures && features.length > 0) {
|
|
803
217
|
const featureResults = features.map((feature) => {
|
|
804
218
|
const result = this.hasProjectFeature(projectId, feature);
|
|
@@ -808,6 +222,9 @@ class AuthService extends BaseService {
|
|
|
808
222
|
if (!hasFeatures) {
|
|
809
223
|
return false;
|
|
810
224
|
}
|
|
225
|
+
if (!hasFeatures) {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
811
228
|
}
|
|
812
229
|
return true;
|
|
813
230
|
} catch (error) {
|
|
@@ -829,92 +246,202 @@ class AuthService extends BaseService {
|
|
|
829
246
|
}
|
|
830
247
|
return action();
|
|
831
248
|
}
|
|
832
|
-
//
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
|
|
249
|
+
// Project access information
|
|
250
|
+
async getProjectAccess(projectId) {
|
|
251
|
+
this._requireReady();
|
|
252
|
+
if (!projectId) {
|
|
253
|
+
throw new Error("Project ID is required");
|
|
254
|
+
}
|
|
255
|
+
const operations = Object.keys(PERMISSION_MAP);
|
|
256
|
+
const access = await Promise.all(
|
|
257
|
+
operations.map(async (operation) => {
|
|
258
|
+
const allowed = await this.canPerformOperation(projectId, operation);
|
|
259
|
+
const config = PERMISSION_MAP[operation];
|
|
260
|
+
return {
|
|
261
|
+
operation,
|
|
262
|
+
allowed,
|
|
263
|
+
permissions: config.permissions,
|
|
264
|
+
features: config.features,
|
|
265
|
+
aiTokens: operation.startsWith("ai") ? this._getAITokens(projectId, operation.replace("ai", "")) : null
|
|
266
|
+
};
|
|
267
|
+
})
|
|
268
|
+
);
|
|
269
|
+
return {
|
|
270
|
+
projectId,
|
|
271
|
+
permissions: access.reduce(
|
|
272
|
+
(acc, { operation, ...details }) => ({
|
|
273
|
+
...acc,
|
|
274
|
+
[operation]: details
|
|
275
|
+
}),
|
|
276
|
+
{}
|
|
277
|
+
),
|
|
278
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
279
|
+
};
|
|
840
280
|
}
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
const
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
return
|
|
281
|
+
// AI token management
|
|
282
|
+
_getAITokens(projectId, featureType) {
|
|
283
|
+
const tokenFeatures = [
|
|
284
|
+
`ai${featureType}:3`,
|
|
285
|
+
`ai${featureType}:5`,
|
|
286
|
+
`ai${featureType}:15`
|
|
287
|
+
];
|
|
288
|
+
return tokenFeatures.reduce((total, feature) => {
|
|
289
|
+
const tokens = this.hasProjectFeature(projectId, feature);
|
|
290
|
+
return total + (typeof tokens === "number" ? tokens : 0);
|
|
291
|
+
}, 0);
|
|
292
|
+
}
|
|
293
|
+
async getProjectMembers(projectId) {
|
|
294
|
+
this._requireReady("getProjectMembers");
|
|
295
|
+
if (!projectId) {
|
|
296
|
+
throw new Error("Project ID is required");
|
|
297
|
+
}
|
|
298
|
+
try {
|
|
299
|
+
const based = this._getBasedService("getProjectMembers");
|
|
300
|
+
return await based.call("projects:get-members", { projectId });
|
|
301
|
+
} catch (error) {
|
|
302
|
+
throw new Error(`Failed to get project members: ${error.message}`);
|
|
303
|
+
}
|
|
849
304
|
}
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
if (
|
|
853
|
-
|
|
305
|
+
async inviteMember(projectId, email, role, name, callbackUrl) {
|
|
306
|
+
this._requireReady("inviteMember");
|
|
307
|
+
if (!projectId) {
|
|
308
|
+
throw new Error("Project ID is required");
|
|
854
309
|
}
|
|
855
|
-
if (
|
|
856
|
-
|
|
310
|
+
if (!email) {
|
|
311
|
+
throw new Error("Email is required");
|
|
857
312
|
}
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
return this._cachePluginSession(optionSession);
|
|
313
|
+
if (!callbackUrl || Object.keys(callbackUrl).length === 0) {
|
|
314
|
+
throw new Error("Callback Url is required");
|
|
861
315
|
}
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
return this._cachePluginSession(contextSession);
|
|
316
|
+
if (!role || !this._userRoles.has(role)) {
|
|
317
|
+
throw new Error(`Invalid role: ${role}`);
|
|
865
318
|
}
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
if (stored) {
|
|
878
|
-
this._pluginSession = stored;
|
|
879
|
-
return stored;
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
} catch {
|
|
883
|
-
}
|
|
319
|
+
try {
|
|
320
|
+
const based = this._getBasedService("inviteMember");
|
|
321
|
+
return await based.call("projects:invite-member", {
|
|
322
|
+
projectId,
|
|
323
|
+
email,
|
|
324
|
+
role,
|
|
325
|
+
name,
|
|
326
|
+
callbackUrl
|
|
327
|
+
});
|
|
328
|
+
} catch (error) {
|
|
329
|
+
throw new Error(`Failed to invite member: ${error.message}`);
|
|
884
330
|
}
|
|
885
|
-
return null;
|
|
886
331
|
}
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
if (window.localStorage) {
|
|
895
|
-
window.localStorage.setItem(PLUGIN_SESSION_STORAGE_KEY, session);
|
|
896
|
-
}
|
|
897
|
-
} catch {
|
|
898
|
-
}
|
|
332
|
+
async acceptInvite(token) {
|
|
333
|
+
this._requireReady("acceptInvite");
|
|
334
|
+
try {
|
|
335
|
+
const based = this._getBasedService("acceptInvite");
|
|
336
|
+
return await based.call("projects:accept-invite", { token });
|
|
337
|
+
} catch (error) {
|
|
338
|
+
throw new Error(`Failed to accept invite: ${error.message}`);
|
|
899
339
|
}
|
|
900
|
-
return session;
|
|
901
340
|
}
|
|
902
|
-
|
|
903
|
-
this.
|
|
341
|
+
async updateMemberRole(projectId, userId, role) {
|
|
342
|
+
this._requireReady("updateMemberRole");
|
|
343
|
+
if (!projectId) {
|
|
344
|
+
throw new Error("Project ID is required");
|
|
345
|
+
}
|
|
346
|
+
if (!userId) {
|
|
347
|
+
throw new Error("User ID is required");
|
|
348
|
+
}
|
|
349
|
+
if (!this._userRoles.has(role)) {
|
|
350
|
+
throw new Error(`Invalid role: ${role}`);
|
|
351
|
+
}
|
|
352
|
+
try {
|
|
353
|
+
const based = this._getBasedService("updateMemberRole");
|
|
354
|
+
return await based.call("projects:update-member-role", {
|
|
355
|
+
projectId,
|
|
356
|
+
userId,
|
|
357
|
+
role
|
|
358
|
+
});
|
|
359
|
+
} catch (error) {
|
|
360
|
+
throw new Error(`Failed to update member role: ${error.message}`);
|
|
361
|
+
}
|
|
904
362
|
}
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
363
|
+
async removeMember(projectId, userId) {
|
|
364
|
+
this._requireReady("removeMember");
|
|
365
|
+
if (!projectId || !userId) {
|
|
366
|
+
throw new Error("Project ID and user ID are required");
|
|
367
|
+
}
|
|
368
|
+
try {
|
|
369
|
+
const based = this._getBasedService("removeMember");
|
|
370
|
+
return await based.call("projects:remove-member", { projectId, userId });
|
|
371
|
+
} catch (error) {
|
|
372
|
+
throw new Error(`Failed to remove member: ${error.message}`);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
async confirmRegistration(token) {
|
|
376
|
+
try {
|
|
377
|
+
const based = this._getBasedService("confirmRegistration");
|
|
378
|
+
return await based.call("users:register-confirmation", { token });
|
|
379
|
+
} catch (error) {
|
|
380
|
+
throw new Error(`Registration confirmation failed: ${error.message}`);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
async requestPasswordReset(email, callbackUrl) {
|
|
384
|
+
try {
|
|
385
|
+
const based = this._getBasedService("requestPasswordReset");
|
|
386
|
+
return await based.call("users:reset-password", { email, callbackUrl });
|
|
387
|
+
} catch (error) {
|
|
388
|
+
throw new Error(`Password reset request failed: ${error.message}`);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
async confirmPasswordReset(token, newPassword) {
|
|
392
|
+
try {
|
|
393
|
+
const based = this._getBasedService("confirmPasswordReset");
|
|
394
|
+
return await based.call("users:reset-password-confirm", {
|
|
395
|
+
token,
|
|
396
|
+
newPassword
|
|
397
|
+
});
|
|
398
|
+
} catch (error) {
|
|
399
|
+
throw new Error(`Password reset confirmation failed: ${error.message}`);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
async getStoredAuthState() {
|
|
403
|
+
try {
|
|
404
|
+
const based = this._getBasedService("getStoredAuthState");
|
|
405
|
+
const { authState } = based;
|
|
406
|
+
if (authState == null ? void 0 : authState.token) {
|
|
407
|
+
return {
|
|
408
|
+
userId: authState.userId,
|
|
409
|
+
authToken: authState.token,
|
|
410
|
+
projectRoles: authState.projectRoles,
|
|
411
|
+
globalRole: authState.globalRole,
|
|
412
|
+
error: null
|
|
413
|
+
};
|
|
915
414
|
}
|
|
415
|
+
return {
|
|
416
|
+
userId: false,
|
|
417
|
+
authToken: false
|
|
418
|
+
};
|
|
419
|
+
} catch (error) {
|
|
420
|
+
this._setError(error);
|
|
421
|
+
return {
|
|
422
|
+
userId: false,
|
|
423
|
+
authToken: false,
|
|
424
|
+
error: `Failed to get stored auth state: ${error.message}`
|
|
425
|
+
};
|
|
916
426
|
}
|
|
917
427
|
}
|
|
428
|
+
async subscribeToAuthChanges(callback) {
|
|
429
|
+
const based = this._getBasedService("subscribeToAuthChanges");
|
|
430
|
+
based.on("authstate-change", async (authState) => {
|
|
431
|
+
const formattedState = (authState == null ? void 0 : authState.token) ? {
|
|
432
|
+
userId: authState.userId,
|
|
433
|
+
authToken: authState.token,
|
|
434
|
+
projectRoles: authState.projectRoles,
|
|
435
|
+
globalRole: authState.globalRole,
|
|
436
|
+
error: null
|
|
437
|
+
} : {
|
|
438
|
+
userId: false,
|
|
439
|
+
authToken: false
|
|
440
|
+
};
|
|
441
|
+
await callback(formattedState);
|
|
442
|
+
});
|
|
443
|
+
return () => based.off("authstate-change");
|
|
444
|
+
}
|
|
918
445
|
}
|
|
919
446
|
export {
|
|
920
447
|
AuthService
|