@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/src/api.ts CHANGED
@@ -1,25 +1,34 @@
1
1
  import type { AxiosInstance, InternalAxiosRequestConfig } from 'axios'
2
2
  import type {
3
- User,
4
- NewUser,
5
- UpdatePasswordForm,
6
- Token,
7
- NewPassword,
8
- UserCreate,
9
- SanitizedUserOut,
10
- SanitizedUserList,
3
+ RegisterRequest,
4
+ UpdateAccountRequest,
5
+ ChangePasswordRequest,
6
+ ResetPasswordRequest,
7
+ SendVerificationRequest,
8
+ AuthenticationAccount,
11
9
  LoginResponse,
12
- PasswordRecoveryResponse,
13
- ResetPasswordResponse,
14
- GetUserResponse,
15
- UpdateUserResponse,
16
- DeleteUserResponse,
17
- GetUsersResponse,
18
- CreateUserResponse,
10
+ RegisterResponse,
11
+ LogoutResponse,
19
12
  GetMeResponse,
20
13
  UpdateMeResponse,
21
- UpdatePasswordResponse,
22
- SignupResponse,
14
+ DeleteMeResponse,
15
+ GetAccountResponse,
16
+ UpdateAccountResponse,
17
+ DeleteAccountResponse,
18
+ ActivateAccountResponse,
19
+ DeactivateAccountResponse,
20
+ ChangePasswordResponse,
21
+ ForgotPasswordResponse,
22
+ ResetPasswordResponse,
23
+ VerifyResetTokenResponse,
24
+ SendVerificationResponse,
25
+ VerifyEmailResponse,
26
+ RefreshSessionResponse,
27
+ GetSessionsResponse,
28
+ DeleteSessionResponse,
29
+ DeleteAllSessionsResponse,
30
+ CleanupSessionsResponse,
31
+ GetMethodsResponse,
23
32
  } from './types'
24
33
  import { createAxiosInstance } from './utils'
25
34
 
@@ -33,98 +42,247 @@ export class AuthApi {
33
42
 
34
43
  private setupInterceptors() {
35
44
  this.api.interceptors.request.use((config: InternalAxiosRequestConfig) => {
36
- const token = localStorage.getItem('access_token')
37
- if (token !== null && config.headers) {
38
- config.headers.Authorization = `Bearer ${token}`
45
+ const sessionToken = localStorage.getItem('session_token')
46
+ if (sessionToken !== null && config.headers) {
47
+ config.headers.Authorization = `Bearer ${sessionToken}`
39
48
  }
40
49
 
50
+ // Handle password reset token from URL
41
51
  const urlParams = new URLSearchParams(window.location.search)
42
52
  const resetToken = urlParams.get('token')
43
-
44
53
  if (resetToken !== null && config.headers) {
45
- config.headers.Authorization = `Bearer ${resetToken}`
54
+ config.headers['X-Reset-Token'] = resetToken
46
55
  }
56
+
47
57
  return config
48
58
  })
49
59
  }
50
60
 
51
- async login(username: string, password: string): Promise<LoginResponse> {
52
- const { data } = await this.api.post<Token>('/auth/login', {
53
- username: username.toLowerCase(),
54
- password,
61
+ // ============================================
62
+ // Authentication Methods
63
+ // ============================================
64
+
65
+ /**
66
+ * Get available authentication methods
67
+ */
68
+ async getAuthMethods(): Promise<GetMethodsResponse> {
69
+ return this.api.get('/authentication/methods')
70
+ }
71
+
72
+ /**
73
+ * Register a new account
74
+ */
75
+ async register(data: RegisterRequest): Promise<RegisterResponse> {
76
+ const response = await this.api.post('/authentication/register', {
77
+ ...data,
78
+ email: data.email.toLowerCase(),
55
79
  })
56
- localStorage.setItem('access_token', data.access_token)
57
- return { data } as LoginResponse
80
+
81
+ // Store session token if provided
82
+ if (response.data.session_token) {
83
+ localStorage.setItem('session_token', response.data.session_token)
84
+ }
85
+
86
+ return response
58
87
  }
59
88
 
60
- logout() {
61
- localStorage.removeItem('access_token')
62
- window.location.reload()
89
+ /**
90
+ * Login with password
91
+ */
92
+ async login(email: string, password: string): Promise<LoginResponse> {
93
+ const response = await this.api.post('/authentication/login/password', {
94
+ email: email.toLowerCase(),
95
+ password,
96
+ })
97
+
98
+ // Store session token if provided
99
+ if (response.data.session_token) {
100
+ localStorage.setItem('session_token', response.data.session_token)
101
+ }
102
+
103
+ return response
63
104
  }
64
105
 
65
- async passwordRecovery(email?: string): Promise<PasswordRecoveryResponse> {
66
- return this.api.post('/auth/password-recovery', { email })
106
+ /**
107
+ * Logout and clear session
108
+ */
109
+ async logout(): Promise<LogoutResponse> {
110
+ const response = await this.api.post('/authentication/logout', {})
111
+ localStorage.removeItem('session_token')
112
+ return response
67
113
  }
68
114
 
69
- async resetPassword(
70
- newPassword: NewPassword['new_password']
71
- ): Promise<ResetPasswordResponse> {
72
- return this.api.post('/auth/reset-password', { new_password: newPassword })
115
+ /**
116
+ * Refresh current session
117
+ */
118
+ async refreshSession(): Promise<RefreshSessionResponse> {
119
+ const response = await this.api.post('/authentication/refresh', {})
120
+
121
+ // Update session token if provided
122
+ if (response.data.session_token) {
123
+ localStorage.setItem('session_token', response.data.session_token)
124
+ }
125
+
126
+ return response
73
127
  }
74
128
 
129
+ // ============================================
130
+ // Current User (Me) Methods
131
+ // ============================================
132
+
133
+ /**
134
+ * Get current user account info
135
+ */
75
136
  async getCurrentUser(): Promise<GetMeResponse> {
76
- return this.api.get<SanitizedUserOut>('/users/me')
137
+ return this.api.get('/authentication/me')
77
138
  }
78
139
 
79
- async signup(user: NewUser): Promise<SignupResponse> {
80
- return this.api.post<SanitizedUserOut>('/users/signup', {
81
- email: user.email.toLowerCase(),
82
- password: user.password,
83
- first_name: user.first_name,
84
- last_name: user.last_name,
85
- })
140
+ /**
141
+ * Update current user profile
142
+ */
143
+ async updateCurrentUser(data: UpdateAccountRequest): Promise<UpdateMeResponse> {
144
+ return this.api.patch('/authentication/me', data)
86
145
  }
87
146
 
88
- async updatePassword(
89
- form: UpdatePasswordForm
90
- ): Promise<UpdatePasswordResponse> {
91
- return this.api.patch('/users/me/password', {
92
- current_password: form.current_password,
93
- new_password: form.new_password,
94
- })
147
+ /**
148
+ * Delete current user account
149
+ */
150
+ async deleteCurrentUser(): Promise<DeleteMeResponse> {
151
+ const response = await this.api.delete('/authentication/me')
152
+ localStorage.removeItem('session_token')
153
+ return response
95
154
  }
96
155
 
97
- async updateUserProfile(user: Partial<User>): Promise<UpdateMeResponse> {
98
- return this.api.patch<SanitizedUserOut>('/users/me', user)
156
+ // ============================================
157
+ // Account Management (Admin)
158
+ // ============================================
159
+
160
+ /**
161
+ * Get account information by ID
162
+ */
163
+ async getAccount(accountId: string): Promise<GetAccountResponse> {
164
+ return this.api.get(`/authentication/account/${accountId}`)
99
165
  }
100
166
 
101
- async setUserStatus(
102
- userId: string,
103
- isActive: boolean
104
- ): Promise<UpdateUserResponse> {
105
- return this.api.patch<SanitizedUserOut>(`/users/${userId}`, {
106
- is_active: isActive,
167
+ /**
168
+ * Update account by ID
169
+ */
170
+ async updateAccount(
171
+ accountId: string,
172
+ data: UpdateAccountRequest
173
+ ): Promise<UpdateAccountResponse> {
174
+ return this.api.patch(`/authentication/account/${accountId}`, data)
175
+ }
176
+
177
+ /**
178
+ * Delete account by ID
179
+ */
180
+ async deleteAccount(accountId: string): Promise<DeleteAccountResponse> {
181
+ return this.api.delete(`/authentication/account/${accountId}`)
182
+ }
183
+
184
+ /**
185
+ * Activate account by ID
186
+ */
187
+ async activateAccount(accountId: string): Promise<ActivateAccountResponse> {
188
+ return this.api.post(`/authentication/account/${accountId}/activate`, {})
189
+ }
190
+
191
+ /**
192
+ * Deactivate account by ID
193
+ */
194
+ async deactivateAccount(
195
+ accountId: string
196
+ ): Promise<DeactivateAccountResponse> {
197
+ return this.api.post(`/authentication/account/${accountId}/deactivate`, {})
198
+ }
199
+
200
+ // ============================================
201
+ // Password Management
202
+ // ============================================
203
+
204
+ /**
205
+ * Change password (requires current password)
206
+ */
207
+ async changePassword(data: ChangePasswordRequest): Promise<ChangePasswordResponse> {
208
+ return this.api.post('/authentication/password/change', data)
209
+ }
210
+
211
+ /**
212
+ * Initiate forgot password flow
213
+ */
214
+ async forgotPassword(email: string): Promise<ForgotPasswordResponse> {
215
+ return this.api.post('/authentication/password/forgot', {
216
+ email: email.toLowerCase(),
107
217
  })
108
218
  }
109
219
 
110
- async deleteUser(userId: string): Promise<DeleteUserResponse> {
111
- return this.api.delete(`/users/${userId}`)
220
+ /**
221
+ * Verify password reset token
222
+ */
223
+ async verifyResetToken(token: string): Promise<VerifyResetTokenResponse> {
224
+ return this.api.get(`/authentication/password/verify-reset-token/${token}`)
112
225
  }
113
226
 
114
- async getUsers(
115
- limit: number = 100,
116
- skip?: number
117
- ): Promise<GetUsersResponse> {
118
- return this.api.get<SanitizedUserList>('/users/', {
119
- params: { skip, limit },
227
+ /**
228
+ * Reset password with token
229
+ */
230
+ async resetPassword(data: ResetPasswordRequest): Promise<ResetPasswordResponse> {
231
+ return this.api.post('/authentication/password/reset', data)
232
+ }
233
+
234
+ // ============================================
235
+ // Email Verification
236
+ // ============================================
237
+
238
+ /**
239
+ * Send email verification
240
+ */
241
+ async sendVerification(
242
+ data: SendVerificationRequest = {},
243
+ user?: AuthenticationAccount
244
+ ): Promise<SendVerificationResponse> {
245
+ return this.api.post('/authentication/verify/send', data, {
246
+ params: user ? { user } : undefined,
120
247
  })
121
248
  }
122
249
 
123
- async createUser(user: UserCreate): Promise<CreateUserResponse> {
124
- return this.api.post<SanitizedUserOut>('/users/', user)
250
+ /**
251
+ * Verify email with token
252
+ */
253
+ async verifyEmail(token: string): Promise<VerifyEmailResponse> {
254
+ return this.api.post('/authentication/verify/email', { token })
255
+ }
256
+
257
+ // ============================================
258
+ // Session Management
259
+ // ============================================
260
+
261
+ /**
262
+ * Get sessions for an account
263
+ */
264
+ async getSessions(accountId: string): Promise<GetSessionsResponse> {
265
+ return this.api.get(`/authentication/sessions/${accountId}`)
266
+ }
267
+
268
+ /**
269
+ * Revoke a specific session
270
+ */
271
+ async revokeSession(sessionToken: string): Promise<DeleteSessionResponse> {
272
+ return this.api.delete(`/authentication/sessions/${sessionToken}`)
273
+ }
274
+
275
+ /**
276
+ * Revoke all sessions for an account
277
+ */
278
+ async revokeAllSessions(accountId: string): Promise<DeleteAllSessionsResponse> {
279
+ return this.api.delete(`/authentication/sessions/account/${accountId}`)
125
280
  }
126
281
 
127
- async getUser(userId: string): Promise<GetUserResponse> {
128
- return this.api.get<SanitizedUserOut>(`/users/${userId}`)
282
+ /**
283
+ * Cleanup expired sessions (admin)
284
+ */
285
+ async cleanupSessions(): Promise<CleanupSessionsResponse> {
286
+ return this.api.post('/authentication/cleanup-sessions', {})
129
287
  }
130
288
  }
package/src/types.ts CHANGED
@@ -1,39 +1,20 @@
1
1
  /* eslint-disable no-unused-vars */
2
2
  import type { AxiosResponse } from 'axios'
3
3
 
4
- export interface User {
5
- id: string
6
- email: string
7
- first_name?: string
8
- last_name?: string
9
- is_superuser?: boolean
10
- is_active?: boolean
11
- }
12
-
13
- export interface UserRegister {
14
- email: string
15
- password: string
16
- first_name: string
17
- last_name: string
18
- }
19
-
20
- export interface NewUser extends UserRegister {
21
- confirmPassword: string
22
- }
23
-
24
- export interface UpdatePasswordForm {
25
- current_password: string
26
- new_password: string
27
- confirmNewPassword: string
28
- }
4
+ // ============================================
5
+ // Auth State & Events
6
+ // ============================================
29
7
 
30
8
  export enum AuthState {
31
9
  LOGIN = 'login',
32
10
  LOGOUT = 'logout',
33
11
  SIGNUP = 'signup',
34
12
  PASSWORD_RESET = 'password_reset',
13
+ PASSWORD_CHANGE = 'password_change',
35
14
  PROFILE_UPDATE = 'profile_update',
36
15
  AUTH_CHECK = 'auth_check',
16
+ EMAIL_VERIFIED = 'email_verified',
17
+ SESSION_REFRESH = 'session_refresh',
37
18
  }
38
19
 
39
20
  export type AuthEventHandler = () => void
@@ -42,75 +23,215 @@ export interface AuthEventMap {
42
23
  [AuthState.LOGOUT]: AuthEventHandler
43
24
  [AuthState.SIGNUP]: AuthEventHandler
44
25
  [AuthState.PASSWORD_RESET]: AuthEventHandler
26
+ [AuthState.PASSWORD_CHANGE]: AuthEventHandler
45
27
  [AuthState.PROFILE_UPDATE]: AuthEventHandler
46
28
  [AuthState.AUTH_CHECK]: AuthEventHandler
29
+ [AuthState.EMAIL_VERIFIED]: AuthEventHandler
30
+ [AuthState.SESSION_REFRESH]: AuthEventHandler
47
31
  }
48
32
 
49
- // API Response Types
50
- export interface Token {
51
- access_token: string
33
+ // ============================================
34
+ // Core Types
35
+ // ============================================
36
+
37
+ export type AuthenticationAccountType = 'person' | 'entity' | 'service'
38
+
39
+ export type AuthenticationMethodType =
40
+ | 'password'
41
+ | 'email_token'
42
+ | 'sso'
43
+ | 'otp'
44
+
45
+ export interface AuthenticationAccount {
46
+ created_at?: string
47
+ updated_at?: string
48
+ account_type?: AuthenticationAccountType
49
+ person_id?: string
50
+ entity_id?: string
51
+ display_name?: string
52
+ is_active?: boolean
53
+ is_verified?: boolean
54
+ account_metadata?: string
55
+ last_login_at?: string
56
+ failed_login_attempts?: number
57
+ locked_until?: string
58
+ id: string
52
59
  }
53
60
 
54
- export interface PasswordRecovery {
55
- email: string
61
+ export interface PersonInfo {
62
+ id: string
63
+ name: string
64
+ email?: string
65
+ roles: string[]
56
66
  }
57
67
 
58
- export interface NewPassword {
59
- new_password: string
68
+ export interface AuthMethodInfo {
69
+ id: string
70
+ type: string
71
+ identifier?: string
72
+ is_verified: boolean
73
+ last_used?: string
74
+ use_count: number
60
75
  }
61
76
 
62
- export interface UserUpdate {
63
- email?: string
64
- is_active?: boolean
65
- is_superuser?: boolean
66
- first_name?: string
67
- last_name?: string
77
+ export interface AccountInfo {
78
+ id: string
79
+ account_type: string
80
+ display_name: string
81
+ is_active: boolean
82
+ is_verified: boolean
83
+ last_login?: string
84
+ authentication_methods: AuthMethodInfo[]
85
+ person?: PersonInfo
68
86
  }
69
87
 
70
- export interface UserUpdateMe {
71
- email?: string
88
+ export interface SessionInfo {
89
+ id: string
90
+ created_at: string
91
+ expires_at: string
92
+ ip_address?: string
93
+ user_agent?: string
94
+ is_current?: boolean
95
+ }
96
+
97
+ // ============================================
98
+ // Request Types
99
+ // ============================================
100
+
101
+ export interface RegisterRequest {
102
+ email: string
103
+ first_name: string
104
+ last_name: string
105
+ phone_number?: string
106
+ password?: string
107
+ }
108
+
109
+ export interface UpdateAccountRequest {
72
110
  first_name?: string
73
111
  last_name?: string
112
+ email?: string
113
+ phone_number?: string
74
114
  }
75
115
 
76
- export interface UpdatePassword {
116
+ export interface PasswordLoginRequest {
117
+ email: string
118
+ password: string
119
+ }
120
+
121
+ export interface ChangePasswordRequest {
77
122
  current_password: string
78
123
  new_password: string
79
124
  }
80
125
 
81
- export interface UserCreate {
126
+ export interface ForgotPasswordRequest {
82
127
  email: string
83
- password: string
84
- first_name?: string
85
- last_name?: string
86
- is_active?: boolean
87
- is_superuser?: boolean
88
128
  }
89
129
 
90
- export interface SanitizedUserOut {
130
+ export interface ResetPasswordRequest {
131
+ token: string
132
+ new_password: string
133
+ }
134
+
135
+ export interface SendVerificationRequest {
136
+ email?: string
137
+ }
138
+
139
+ export interface VerifyEmailRequest {
140
+ token: string
141
+ }
142
+
143
+ // Client-side helper types
144
+ export interface NewUser extends RegisterRequest {
145
+ confirmPassword: string
146
+ }
147
+
148
+ export interface UpdatePasswordForm extends ChangePasswordRequest {
149
+ confirmNewPassword: string
150
+ }
151
+
152
+ // ============================================
153
+ // Response Types
154
+ // ============================================
155
+
156
+ export interface MessageResponse {
157
+ message: string
158
+ }
159
+
160
+ export interface AuthStatusResponse {
161
+ status: string
162
+ methods: string[]
163
+ }
164
+
165
+ export interface AvailableMethodsResponse {
166
+ available_methods: { [key: string]: any }[]
167
+ }
168
+
169
+ export interface OTPMetadata {
170
+ nonce: string
171
+ verification_hash: string
172
+ timestamp: number
173
+ expires_in_minutes: number
174
+ autofill: { [key: string]: any }
175
+ }
176
+
177
+ export interface SSOMetadata {
178
+ provider: string
179
+ sso_user_info: { [key: string]: any }
180
+ can_create_account?: boolean
181
+ }
182
+
183
+ export interface AuthenticationResponse {
184
+ success: boolean
185
+ account_id?: string
186
+ session_token?: string
187
+ requires_verification?: boolean
188
+ verification_method?: AuthenticationMethodType
189
+ message?: string
190
+ metadata?: OTPMetadata | SSOMetadata | { [key: string]: any }
191
+ }
192
+
193
+ export interface SessionListResponse {
194
+ account_id: string
195
+ sessions: SessionInfo[]
196
+ }
197
+
198
+ // ============================================
199
+ // Axios Response Types
200
+ // ============================================
201
+
202
+ export type LoginResponse = AxiosResponse<AuthenticationResponse>
203
+ export type RegisterResponse = AxiosResponse<AuthenticationResponse>
204
+ export type LogoutResponse = AxiosResponse<MessageResponse>
205
+ export type GetMeResponse = AxiosResponse<AccountInfo>
206
+ export type UpdateMeResponse = AxiosResponse<AccountInfo>
207
+ export type DeleteMeResponse = AxiosResponse<MessageResponse>
208
+ export type GetAccountResponse = AxiosResponse<AccountInfo>
209
+ export type UpdateAccountResponse = AxiosResponse<AccountInfo>
210
+ export type DeleteAccountResponse = AxiosResponse<MessageResponse>
211
+ export type ActivateAccountResponse = AxiosResponse<AccountInfo>
212
+ export type DeactivateAccountResponse = AxiosResponse<AccountInfo>
213
+ export type ChangePasswordResponse = AxiosResponse<MessageResponse>
214
+ export type ForgotPasswordResponse = AxiosResponse<MessageResponse>
215
+ export type ResetPasswordResponse = AxiosResponse<MessageResponse>
216
+ export type VerifyResetTokenResponse = AxiosResponse<MessageResponse>
217
+ export type SendVerificationResponse = AxiosResponse<MessageResponse>
218
+ export type VerifyEmailResponse = AxiosResponse<MessageResponse>
219
+ export type RefreshSessionResponse = AxiosResponse<AuthenticationResponse>
220
+ export type GetSessionsResponse = AxiosResponse<SessionListResponse>
221
+ export type DeleteSessionResponse = AxiosResponse<MessageResponse>
222
+ export type DeleteAllSessionsResponse = AxiosResponse<MessageResponse>
223
+ export type CleanupSessionsResponse = AxiosResponse<MessageResponse>
224
+ export type GetMethodsResponse = AxiosResponse<AvailableMethodsResponse>
225
+
226
+ // ============================================
227
+ // Legacy Type Aliases (for backward compatibility)
228
+ // ============================================
229
+
230
+ /** @deprecated Use AccountInfo instead */
231
+ export type User = AccountInfo & {
91
232
  email: string
92
- is_active?: boolean
93
- is_superuser?: boolean
94
233
  first_name?: string
95
234
  last_name?: string
96
- id: string
235
+ is_superuser?: boolean
236
+ is_active?: boolean
97
237
  }
98
-
99
- export interface SanitizedUserList {
100
- data: SanitizedUserOut[]
101
- count: number
102
- }
103
-
104
- // API Response Types
105
- export type LoginResponse = AxiosResponse<Token>
106
- export type PasswordRecoveryResponse = AxiosResponse
107
- export type ResetPasswordResponse = AxiosResponse
108
- export type GetUserResponse = AxiosResponse<SanitizedUserOut>
109
- export type UpdateUserResponse = AxiosResponse<SanitizedUserOut>
110
- export type DeleteUserResponse = AxiosResponse
111
- export type GetUsersResponse = AxiosResponse<SanitizedUserList>
112
- export type CreateUserResponse = AxiosResponse<SanitizedUserOut>
113
- export type GetMeResponse = AxiosResponse<SanitizedUserOut>
114
- export type UpdateMeResponse = AxiosResponse<SanitizedUserOut>
115
- export type UpdatePasswordResponse = AxiosResponse
116
- export type SignupResponse = AxiosResponse<SanitizedUserOut>