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