@bagelink/auth 1.4.169 → 1.4.171

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/dist/index.cjs CHANGED
@@ -55,74 +55,199 @@ class AuthApi {
55
55
  }
56
56
  setupInterceptors() {
57
57
  this.api.interceptors.request.use((config) => {
58
- const token = localStorage.getItem("access_token");
59
- if (token !== null && config.headers) {
60
- config.headers.Authorization = `Bearer ${token}`;
58
+ const sessionToken = localStorage.getItem("session_token");
59
+ if (sessionToken !== null && config.headers) {
60
+ config.headers.Authorization = `Bearer ${sessionToken}`;
61
61
  }
62
62
  const urlParams = new URLSearchParams(window.location.search);
63
63
  const resetToken = urlParams.get("token");
64
64
  if (resetToken !== null && config.headers) {
65
- config.headers.Authorization = `Bearer ${resetToken}`;
65
+ config.headers["X-Reset-Token"] = resetToken;
66
66
  }
67
67
  return config;
68
68
  });
69
69
  }
70
- async login(username, password) {
71
- const { data } = await this.api.post("/auth/login", {
72
- username: username.toLowerCase(),
70
+ // ============================================
71
+ // Authentication Methods
72
+ // ============================================
73
+ /**
74
+ * Get available authentication methods
75
+ */
76
+ async getAuthMethods() {
77
+ return this.api.get("/authentication/methods");
78
+ }
79
+ /**
80
+ * Register a new account
81
+ */
82
+ async register(data) {
83
+ const response = await this.api.post("/authentication/register", {
84
+ ...data,
85
+ email: data.email.toLowerCase()
86
+ });
87
+ if (response.data.session_token) {
88
+ localStorage.setItem("session_token", response.data.session_token);
89
+ }
90
+ return response;
91
+ }
92
+ /**
93
+ * Login with password
94
+ */
95
+ async login(email, password) {
96
+ const response = await this.api.post("/authentication/login/password", {
97
+ email: email.toLowerCase(),
73
98
  password
74
99
  });
75
- localStorage.setItem("access_token", data.access_token);
76
- return { data };
77
- }
78
- logout() {
79
- localStorage.removeItem("access_token");
80
- window.location.reload();
81
- }
82
- async passwordRecovery(email) {
83
- return this.api.post("/auth/password-recovery", { email });
84
- }
85
- async resetPassword(newPassword) {
86
- return this.api.post("/auth/reset-password", { new_password: newPassword });
87
- }
100
+ if (response.data.session_token) {
101
+ localStorage.setItem("session_token", response.data.session_token);
102
+ }
103
+ return response;
104
+ }
105
+ /**
106
+ * Logout and clear session
107
+ */
108
+ async logout() {
109
+ const response = await this.api.post("/authentication/logout", {});
110
+ localStorage.removeItem("session_token");
111
+ return response;
112
+ }
113
+ /**
114
+ * Refresh current session
115
+ */
116
+ async refreshSession() {
117
+ const response = await this.api.post("/authentication/refresh", {});
118
+ if (response.data.session_token) {
119
+ localStorage.setItem("session_token", response.data.session_token);
120
+ }
121
+ return response;
122
+ }
123
+ // ============================================
124
+ // Current User (Me) Methods
125
+ // ============================================
126
+ /**
127
+ * Get current user account info
128
+ */
88
129
  async getCurrentUser() {
89
- return this.api.get("/users/me");
90
- }
91
- async signup(user) {
92
- return this.api.post("/users/signup", {
93
- email: user.email.toLowerCase(),
94
- password: user.password,
95
- first_name: user.first_name,
96
- last_name: user.last_name
97
- });
98
- }
99
- async updatePassword(form) {
100
- return this.api.patch("/users/me/password", {
101
- current_password: form.current_password,
102
- new_password: form.new_password
103
- });
104
- }
105
- async updateUserProfile(user) {
106
- return this.api.patch("/users/me", user);
107
- }
108
- async setUserStatus(userId, isActive) {
109
- return this.api.patch(`/users/${userId}`, {
110
- is_active: isActive
130
+ return this.api.get("/authentication/me");
131
+ }
132
+ /**
133
+ * Update current user profile
134
+ */
135
+ async updateCurrentUser(data) {
136
+ return this.api.patch("/authentication/me", data);
137
+ }
138
+ /**
139
+ * Delete current user account
140
+ */
141
+ async deleteCurrentUser() {
142
+ const response = await this.api.delete("/authentication/me");
143
+ localStorage.removeItem("session_token");
144
+ return response;
145
+ }
146
+ // ============================================
147
+ // Account Management (Admin)
148
+ // ============================================
149
+ /**
150
+ * Get account information by ID
151
+ */
152
+ async getAccount(accountId) {
153
+ return this.api.get(`/authentication/account/${accountId}`);
154
+ }
155
+ /**
156
+ * Update account by ID
157
+ */
158
+ async updateAccount(accountId, data) {
159
+ return this.api.patch(`/authentication/account/${accountId}`, data);
160
+ }
161
+ /**
162
+ * Delete account by ID
163
+ */
164
+ async deleteAccount(accountId) {
165
+ return this.api.delete(`/authentication/account/${accountId}`);
166
+ }
167
+ /**
168
+ * Activate account by ID
169
+ */
170
+ async activateAccount(accountId) {
171
+ return this.api.post(`/authentication/account/${accountId}/activate`, {});
172
+ }
173
+ /**
174
+ * Deactivate account by ID
175
+ */
176
+ async deactivateAccount(accountId) {
177
+ return this.api.post(`/authentication/account/${accountId}/deactivate`, {});
178
+ }
179
+ // ============================================
180
+ // Password Management
181
+ // ============================================
182
+ /**
183
+ * Change password (requires current password)
184
+ */
185
+ async changePassword(data) {
186
+ return this.api.post("/authentication/password/change", data);
187
+ }
188
+ /**
189
+ * Initiate forgot password flow
190
+ */
191
+ async forgotPassword(email) {
192
+ return this.api.post("/authentication/password/forgot", {
193
+ email: email.toLowerCase()
111
194
  });
112
195
  }
113
- async deleteUser(userId) {
114
- return this.api.delete(`/users/${userId}`);
115
- }
116
- async getUsers(limit = 100, skip) {
117
- return this.api.get("/users/", {
118
- params: { skip, limit }
196
+ /**
197
+ * Verify password reset token
198
+ */
199
+ async verifyResetToken(token) {
200
+ return this.api.get(`/authentication/password/verify-reset-token/${token}`);
201
+ }
202
+ /**
203
+ * Reset password with token
204
+ */
205
+ async resetPassword(data) {
206
+ return this.api.post("/authentication/password/reset", data);
207
+ }
208
+ // ============================================
209
+ // Email Verification
210
+ // ============================================
211
+ /**
212
+ * Send email verification
213
+ */
214
+ async sendVerification(data = {}, user) {
215
+ return this.api.post("/authentication/verify/send", data, {
216
+ params: user ? { user } : void 0
119
217
  });
120
218
  }
121
- async createUser(user) {
122
- return this.api.post("/users/", user);
123
- }
124
- async getUser(userId) {
125
- return this.api.get(`/users/${userId}`);
219
+ /**
220
+ * Verify email with token
221
+ */
222
+ async verifyEmail(token) {
223
+ return this.api.post("/authentication/verify/email", { token });
224
+ }
225
+ // ============================================
226
+ // Session Management
227
+ // ============================================
228
+ /**
229
+ * Get sessions for an account
230
+ */
231
+ async getSessions(accountId) {
232
+ return this.api.get(`/authentication/sessions/${accountId}`);
233
+ }
234
+ /**
235
+ * Revoke a specific session
236
+ */
237
+ async revokeSession(sessionToken) {
238
+ return this.api.delete(`/authentication/sessions/${sessionToken}`);
239
+ }
240
+ /**
241
+ * Revoke all sessions for an account
242
+ */
243
+ async revokeAllSessions(accountId) {
244
+ return this.api.delete(`/authentication/sessions/account/${accountId}`);
245
+ }
246
+ /**
247
+ * Cleanup expired sessions (admin)
248
+ */
249
+ async cleanupSessions() {
250
+ return this.api.post("/authentication/cleanup-sessions", {});
126
251
  }
127
252
  }
128
253
 
@@ -131,41 +256,43 @@ var AuthState = /* @__PURE__ */ ((AuthState2) => {
131
256
  AuthState2["LOGOUT"] = "logout";
132
257
  AuthState2["SIGNUP"] = "signup";
133
258
  AuthState2["PASSWORD_RESET"] = "password_reset";
259
+ AuthState2["PASSWORD_CHANGE"] = "password_change";
134
260
  AuthState2["PROFILE_UPDATE"] = "profile_update";
135
261
  AuthState2["AUTH_CHECK"] = "auth_check";
262
+ AuthState2["EMAIL_VERIFIED"] = "email_verified";
263
+ AuthState2["SESSION_REFRESH"] = "session_refresh";
136
264
  return AuthState2;
137
265
  })(AuthState || {});
138
266
 
139
267
  let authApi = null;
140
268
  let eventEmitter = null;
141
- const currentUser = vue.ref({
142
- id: "",
143
- email: "",
144
- first_name: "",
145
- last_name: "",
146
- is_superuser: false,
147
- is_active: false
148
- });
269
+ const currentUser = vue.ref(null);
149
270
  function initAuth({
150
271
  axios,
151
272
  baseURL
152
273
  }) {
153
- if (!authApi) {
274
+ if (authApi === null) {
154
275
  authApi = new AuthApi(axios, baseURL);
155
276
  }
156
- if (!eventEmitter) {
277
+ if (eventEmitter === null) {
157
278
  eventEmitter = new EventEmitter();
158
279
  }
159
280
  return {
160
281
  // Event listener methods
161
282
  on(event, handler) {
162
- eventEmitter.on(event, handler);
283
+ if (eventEmitter) {
284
+ eventEmitter.on(event, handler);
285
+ }
163
286
  },
164
287
  off(event, handler) {
165
- eventEmitter.off(event, handler);
288
+ if (eventEmitter) {
289
+ eventEmitter.off(event, handler);
290
+ }
166
291
  },
167
292
  removeAllListeners(event) {
168
- eventEmitter.removeAllListeners(event);
293
+ if (eventEmitter) {
294
+ eventEmitter.removeAllListeners(event);
295
+ }
169
296
  },
170
297
  install(app) {
171
298
  app.config.globalProperties.$auth = useAuth();
@@ -173,113 +300,149 @@ function initAuth({
173
300
  };
174
301
  }
175
302
  function useAuth() {
176
- if (!authApi) {
303
+ if (authApi === null) {
177
304
  throw new Error("Auth not initialized. Call initAuth first.");
178
305
  }
179
- const getFullName = () => `${currentUser.value.first_name} ${currentUser.value.last_name}`;
180
- const getIsLoggedIn = () => currentUser.value.id.length > 0;
181
- async function logout() {
182
- try {
183
- await authApi.logout();
184
- currentUser.value = {
185
- id: "",
186
- email: "",
187
- first_name: "",
188
- last_name: "",
189
- is_superuser: false,
190
- is_active: false
191
- };
192
- eventEmitter.emit(AuthState.LOGOUT);
193
- } catch (error) {
194
- throw error;
306
+ if (eventEmitter === null) {
307
+ throw new Error("Event emitter not initialized. Call initAuth first.");
308
+ }
309
+ const api = authApi;
310
+ const emitter = eventEmitter;
311
+ const getFullName = () => {
312
+ const user = currentUser.value;
313
+ if (user === null) return "";
314
+ if (user.person !== void 0) return user.person.name;
315
+ return user.display_name ?? "";
316
+ };
317
+ const getIsLoggedIn = () => {
318
+ const user = currentUser.value;
319
+ return user !== null && user.id.length > 0;
320
+ };
321
+ const getEmail = () => {
322
+ const user = currentUser.value;
323
+ if (user === null) return "";
324
+ if (user.person?.email !== void 0) {
325
+ return user.person.email;
195
326
  }
327
+ const emailMethod = user.authentication_methods?.find(
328
+ (m) => m.type === "password" || m.type === "email_token"
329
+ );
330
+ return emailMethod?.identifier ?? "";
331
+ };
332
+ async function logout() {
333
+ const logoutPromise = api.logout();
334
+ await logoutPromise.catch(() => {
335
+ });
336
+ currentUser.value = null;
337
+ emitter.emit(AuthState.LOGOUT);
196
338
  }
197
339
  async function login(credentials) {
198
- try {
199
- await authApi.login(
200
- credentials.email.toLowerCase(),
201
- credentials.password
202
- );
340
+ const { data } = await api.login(
341
+ credentials.email.toLowerCase(),
342
+ credentials.password
343
+ );
344
+ if (data.success === true && data.requires_verification !== true) {
203
345
  await checkAuth();
204
- eventEmitter.emit(AuthState.LOGIN);
205
- } catch (error) {
206
- throw error;
207
346
  }
347
+ emitter.emit(AuthState.LOGIN);
348
+ return data;
208
349
  }
209
350
  async function checkAuth() {
210
351
  try {
211
- if (!getIsLoggedIn()) {
212
- const { data } = await authApi.getCurrentUser();
213
- currentUser.value = data;
214
- if (getIsLoggedIn()) {
215
- eventEmitter.emit(AuthState.AUTH_CHECK);
216
- }
352
+ const { data } = await api.getCurrentUser();
353
+ currentUser.value = data;
354
+ if (getIsLoggedIn()) {
355
+ emitter.emit(AuthState.AUTH_CHECK);
217
356
  }
218
- } catch (error) {
357
+ return true;
358
+ } catch {
359
+ currentUser.value = null;
219
360
  return false;
220
361
  }
221
- return getIsLoggedIn();
222
362
  }
223
363
  async function signup(user) {
224
- try {
225
- if (user.password !== user.confirmPassword) {
226
- throw new Error("Passwords do not match");
227
- }
228
- const { data } = await authApi.signup(user);
229
- currentUser.value = data;
230
- eventEmitter.emit(AuthState.SIGNUP);
231
- } catch (error) {
232
- throw error;
364
+ if (user.password && user.password !== user.confirmPassword) {
365
+ throw new Error("Passwords do not match");
233
366
  }
234
- }
235
- async function recoverPassword(email) {
236
- try {
237
- await authApi.passwordRecovery(email);
238
- } catch (error) {
239
- throw error;
367
+ const { data } = await api.register({
368
+ email: user.email,
369
+ first_name: user.first_name,
370
+ last_name: user.last_name,
371
+ phone_number: user.phone_number,
372
+ password: user.password
373
+ });
374
+ if (data.success === true && data.requires_verification !== true) {
375
+ await checkAuth();
240
376
  }
377
+ emitter.emit(AuthState.SIGNUP);
378
+ return data;
241
379
  }
242
- async function resetPassword(newPassword) {
243
- try {
244
- await authApi.resetPassword(newPassword);
245
- eventEmitter.emit(AuthState.PASSWORD_RESET);
246
- } catch (error) {
247
- throw error;
248
- }
380
+ async function forgotPassword(email) {
381
+ await api.forgotPassword(email);
249
382
  }
250
- async function updatePassword(form) {
251
- try {
252
- if (form.new_password !== form.confirmNewPassword) {
253
- throw new Error("Passwords do not match");
254
- }
255
- await authApi.updatePassword(form);
256
- eventEmitter.emit(AuthState.PASSWORD_RESET);
257
- } catch (error) {
258
- throw error;
259
- }
383
+ async function verifyResetToken(token) {
384
+ await api.verifyResetToken(token);
260
385
  }
261
- async function updateProfile(user) {
262
- try {
263
- const { data } = await authApi.updateUserProfile(user);
264
- currentUser.value = { ...currentUser.value, ...data };
265
- eventEmitter.emit(AuthState.PROFILE_UPDATE);
266
- } catch (error) {
267
- throw error;
386
+ async function resetPassword(token, newPassword) {
387
+ await api.resetPassword({ token, new_password: newPassword });
388
+ emitter.emit(AuthState.PASSWORD_RESET);
389
+ }
390
+ async function changePassword(form) {
391
+ if (form.new_password !== form.confirmNewPassword) {
392
+ throw new Error("Passwords do not match");
268
393
  }
394
+ await api.changePassword({
395
+ current_password: form.current_password,
396
+ new_password: form.new_password
397
+ });
398
+ emitter.emit(AuthState.PASSWORD_CHANGE);
269
399
  }
270
- async function toggleUserStatus(userId, isActive) {
271
- try {
272
- await authApi.setUserStatus(userId, isActive);
273
- } catch (error) {
274
- throw error;
400
+ async function updateProfile(updates) {
401
+ const { data } = await api.updateCurrentUser(updates);
402
+ currentUser.value = data;
403
+ emitter.emit(AuthState.PROFILE_UPDATE);
404
+ }
405
+ async function activateAccount(accountId) {
406
+ await api.activateAccount(accountId);
407
+ }
408
+ async function deactivateAccount(accountId) {
409
+ await api.deactivateAccount(accountId);
410
+ }
411
+ async function deleteAccount(accountId) {
412
+ await api.deleteAccount(accountId);
413
+ }
414
+ async function deleteCurrentUser() {
415
+ await api.deleteCurrentUser();
416
+ currentUser.value = null;
417
+ }
418
+ async function sendVerification(email) {
419
+ await api.sendVerification({ email });
420
+ }
421
+ async function verifyEmail(token) {
422
+ await api.verifyEmail(token);
423
+ await checkAuth();
424
+ emitter.emit(AuthState.EMAIL_VERIFIED);
425
+ }
426
+ async function refreshSession() {
427
+ await api.refreshSession();
428
+ emitter.emit(AuthState.SESSION_REFRESH);
429
+ }
430
+ async function getSessions(accountId) {
431
+ const id = accountId ?? currentUser.value?.id;
432
+ if (id === void 0 || id === "") {
433
+ throw new Error("No account ID available");
275
434
  }
435
+ return api.getSessions(id);
276
436
  }
277
- async function deleteUser(userId) {
278
- try {
279
- await authApi.deleteUser(userId);
280
- } catch (error) {
281
- throw error;
437
+ async function revokeSession(sessionToken) {
438
+ await api.revokeSession(sessionToken);
439
+ }
440
+ async function revokeAllSessions(accountId) {
441
+ const id = accountId ?? currentUser.value?.id;
442
+ if (id === void 0 || id === "") {
443
+ throw new Error("No account ID available");
282
444
  }
445
+ await api.revokeAllSessions(id);
283
446
  }
284
447
  return {
285
448
  // State
@@ -287,17 +450,32 @@ function useAuth() {
287
450
  // Getters
288
451
  getFullName,
289
452
  getIsLoggedIn,
290
- // Actions
291
- logout,
453
+ getEmail,
454
+ // Authentication Actions
292
455
  login,
293
- checkAuth,
456
+ logout,
294
457
  signup,
295
- recoverPassword,
296
- resetPassword,
297
- updatePassword,
458
+ checkAuth,
459
+ refreshSession,
460
+ // Profile Actions
298
461
  updateProfile,
299
- toggleUserStatus,
300
- deleteUser
462
+ deleteCurrentUser,
463
+ // Password Actions
464
+ changePassword,
465
+ forgotPassword,
466
+ verifyResetToken,
467
+ resetPassword,
468
+ // Email Verification Actions
469
+ sendVerification,
470
+ verifyEmail,
471
+ // Admin Actions
472
+ activateAccount,
473
+ deactivateAccount,
474
+ deleteAccount,
475
+ // Session Management
476
+ getSessions,
477
+ revokeSession,
478
+ revokeAllSessions
301
479
  };
302
480
  }
303
481