@bagelink/auth 1.4.171 → 1.4.176

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/types.ts CHANGED
@@ -83,6 +83,14 @@ export interface AccountInfo {
83
83
  last_login?: string
84
84
  authentication_methods: AuthMethodInfo[]
85
85
  person?: PersonInfo
86
+ entity?: EntityInfo
87
+ }
88
+
89
+ export interface EntityInfo {
90
+ id: string
91
+ name: string
92
+ type?: string
93
+ metadata?: Record<string, any>
86
94
  }
87
95
 
88
96
  export interface SessionInfo {
@@ -94,6 +102,39 @@ export interface SessionInfo {
94
102
  is_current?: boolean
95
103
  }
96
104
 
105
+ // ============================================
106
+ // Unified User Type (Person or Entity)
107
+ // ============================================
108
+
109
+ /**
110
+ * Unified user representation that works for both person and entity accounts
111
+ * This is the primary interface for accessing user data in the application
112
+ */
113
+ export interface User {
114
+ /** Unique identifier (person_id or entity_id) */
115
+ id: string
116
+ /** Account ID */
117
+ accountId: string
118
+ /** Display name */
119
+ name: string
120
+ /** Email address (from person or authentication methods) */
121
+ email?: string
122
+ /** Account type: 'person', 'entity', or 'service' */
123
+ type: AuthenticationAccountType
124
+ /** User roles (only for person accounts) */
125
+ roles?: string[]
126
+ /** Is the account active */
127
+ isActive: boolean
128
+ /** Is the account verified */
129
+ isVerified: boolean
130
+ /** Last login timestamp */
131
+ lastLogin?: string
132
+ /** Entity-specific info (only for entity accounts) */
133
+ entityType?: string
134
+ /** Additional metadata */
135
+ metadata?: Record<string, any>
136
+ }
137
+
97
138
  // ============================================
98
139
  // Request Types
99
140
  // ============================================
@@ -224,14 +265,59 @@ export type CleanupSessionsResponse = AxiosResponse<MessageResponse>
224
265
  export type GetMethodsResponse = AxiosResponse<AvailableMethodsResponse>
225
266
 
226
267
  // ============================================
227
- // Legacy Type Aliases (for backward compatibility)
268
+ // Helper Functions (exported for convenience)
228
269
  // ============================================
229
270
 
230
- /** @deprecated Use AccountInfo instead */
231
- export type User = AccountInfo & {
232
- email: string
233
- first_name?: string
234
- last_name?: string
235
- is_superuser?: boolean
236
- is_active?: boolean
271
+ /**
272
+ * Extract unified user from account info
273
+ */
274
+ export function accountToUser(account: AccountInfo | null): User | null {
275
+ if (account === null) return null
276
+
277
+ // Person account - most common case
278
+ if (account.person !== undefined) {
279
+ return {
280
+ id: account.person.id,
281
+ accountId: account.id,
282
+ name: account.person.name,
283
+ email: account.person.email,
284
+ type: account.account_type as AuthenticationAccountType,
285
+ roles: account.person.roles,
286
+ isActive: account.is_active,
287
+ isVerified: account.is_verified,
288
+ lastLogin: account.last_login,
289
+ }
290
+ }
291
+
292
+ // Entity account
293
+ if (account.entity !== undefined) {
294
+ return {
295
+ id: account.entity.id,
296
+ accountId: account.id,
297
+ name: account.entity.name,
298
+ type: account.account_type as AuthenticationAccountType,
299
+ isActive: account.is_active,
300
+ isVerified: account.is_verified,
301
+ lastLogin: account.last_login,
302
+ entityType: account.entity.type,
303
+ metadata: account.entity.metadata,
304
+ }
305
+ }
306
+
307
+ // Fallback - use account info directly
308
+ // Extract email from authentication methods
309
+ const emailMethod = account.authentication_methods?.find(
310
+ m => m.type === 'password' || m.type === 'email_token',
311
+ )
312
+
313
+ return {
314
+ id: account.id,
315
+ accountId: account.id,
316
+ name: account.display_name,
317
+ email: emailMethod?.identifier,
318
+ type: account.account_type as AuthenticationAccountType,
319
+ isActive: account.is_active,
320
+ isVerified: account.is_verified,
321
+ lastLogin: account.last_login,
322
+ }
237
323
  }
package/src/useAuth.ts CHANGED
@@ -2,20 +2,21 @@ import type { AxiosInstance } from 'axios'
2
2
  import type { App } from 'vue'
3
3
  import type {
4
4
  AccountInfo,
5
+ User,
5
6
  NewUser,
6
7
  UpdatePasswordForm,
7
8
  UpdateAccountRequest,
8
9
  AuthEventMap,
9
10
  } from './types'
10
- import { ref } from 'vue'
11
+ import { ref, computed } from 'vue'
11
12
  import { AuthApi } from './api'
12
- import { AuthState } from './types'
13
+ import { AuthState, accountToUser } from './types'
13
14
  import { EventEmitter } from './utils'
14
15
 
15
16
  // Global state
16
17
  let authApi: AuthApi | null = null
17
18
  let eventEmitter: EventEmitter | null = null
18
- const currentUser = ref<AccountInfo | null>(null)
19
+ const accountInfo = ref<AccountInfo | null>(null)
19
20
 
20
21
  // Initialize auth
21
22
  export function initAuth({
@@ -73,33 +74,36 @@ export function useAuth() {
73
74
  const api = authApi
74
75
  const emitter = eventEmitter
75
76
 
77
+ // Computed user - the primary interface for accessing user data
78
+ const user = computed<User | null>(() => accountToUser(accountInfo.value))
79
+
76
80
  // Getters
77
81
  const getFullName = () => {
78
- const user = currentUser.value
79
- if (user === null) return ''
80
- if (user.person !== undefined) return user.person.name
81
- return user.display_name ?? ''
82
+ return user.value?.name ?? ''
82
83
  }
83
84
 
84
85
  const getIsLoggedIn = () => {
85
- const user = currentUser.value
86
- return user !== null && user.id.length > 0
86
+ return user.value !== null
87
87
  }
88
88
 
89
89
  const getEmail = () => {
90
- const user = currentUser.value
91
- if (user === null) return ''
90
+ return user.value?.email ?? ''
91
+ }
92
92
 
93
- // Try to get email from person info first
94
- if (user.person?.email !== undefined) {
95
- return user.person.email
96
- }
93
+ const getRoles = () => {
94
+ return user.value?.roles ?? []
95
+ }
97
96
 
98
- // Otherwise look for email in authentication methods
99
- const emailMethod = user.authentication_methods?.find(
100
- m => m.type === 'password' || m.type === 'email_token'
101
- )
102
- return emailMethod?.identifier ?? ''
97
+ const getAccountType = () => {
98
+ return user.value?.type ?? 'person'
99
+ }
100
+
101
+ const isPersonAccount = () => {
102
+ return user.value?.type === 'person'
103
+ }
104
+
105
+ const isEntityAccount = () => {
106
+ return user.value?.type === 'entity'
103
107
  }
104
108
 
105
109
  // Actions
@@ -110,7 +114,7 @@ export function useAuth() {
110
114
  // Ignore logout errors
111
115
  })
112
116
  // Clear local state regardless of API result
113
- currentUser.value = null
117
+ accountInfo.value = null
114
118
  // Emit logout event
115
119
  emitter.emit(AuthState.LOGOUT)
116
120
  }
@@ -133,29 +137,30 @@ export function useAuth() {
133
137
  async function checkAuth(): Promise<boolean> {
134
138
  try {
135
139
  const { data } = await api.getCurrentUser()
136
- currentUser.value = data
140
+ accountInfo.value = data
137
141
  if (getIsLoggedIn()) {
138
142
  emitter.emit(AuthState.AUTH_CHECK)
139
143
  }
140
144
  return true
141
145
  } catch {
142
- currentUser.value = null
146
+ accountInfo.value = null
143
147
  return false
144
148
  }
145
149
  }
146
150
 
147
- async function signup(user: NewUser) {
151
+ async function signup(newUser: NewUser) {
148
152
  // Check password match if password is provided
149
- if (user.password && user.password !== user.confirmPassword) {
153
+ const hasPassword = newUser.password !== undefined && newUser.password.length > 0
154
+ if (hasPassword && newUser.password !== newUser.confirmPassword) {
150
155
  throw new Error('Passwords do not match')
151
156
  }
152
157
 
153
158
  const { data } = await api.register({
154
- email: user.email,
155
- first_name: user.first_name,
156
- last_name: user.last_name,
157
- phone_number: user.phone_number,
158
- password: user.password,
159
+ email: newUser.email,
160
+ first_name: newUser.first_name,
161
+ last_name: newUser.last_name,
162
+ phone_number: newUser.phone_number,
163
+ password: newUser.password,
159
164
  })
160
165
 
161
166
  // If successful and not requiring verification, fetch user data
@@ -193,7 +198,7 @@ export function useAuth() {
193
198
 
194
199
  async function updateProfile(updates: UpdateAccountRequest) {
195
200
  const { data } = await api.updateCurrentUser(updates)
196
- currentUser.value = data
201
+ accountInfo.value = data
197
202
  emitter.emit(AuthState.PROFILE_UPDATE)
198
203
  }
199
204
 
@@ -211,7 +216,7 @@ export function useAuth() {
211
216
 
212
217
  async function deleteCurrentUser() {
213
218
  await api.deleteCurrentUser()
214
- currentUser.value = null
219
+ accountInfo.value = null
215
220
  }
216
221
 
217
222
  async function sendVerification(email?: string) {
@@ -231,7 +236,7 @@ export function useAuth() {
231
236
  }
232
237
 
233
238
  async function getSessions(accountId?: string) {
234
- const id = accountId ?? currentUser.value?.id
239
+ const id = accountId ?? user.value?.accountId
235
240
  if (id === undefined || id === '') {
236
241
  throw new Error('No account ID available')
237
242
  }
@@ -243,7 +248,7 @@ export function useAuth() {
243
248
  }
244
249
 
245
250
  async function revokeAllSessions(accountId?: string) {
246
- const id = accountId ?? currentUser.value?.id
251
+ const id = accountId ?? user.value?.accountId
247
252
  if (id === undefined || id === '') {
248
253
  throw new Error('No account ID available')
249
254
  }
@@ -251,13 +256,20 @@ export function useAuth() {
251
256
  }
252
257
 
253
258
  return {
254
- // State
255
- currentUser,
259
+ // Primary State (use this!)
260
+ user,
261
+
262
+ // Full account info (for advanced use cases)
263
+ accountInfo,
256
264
 
257
265
  // Getters
258
266
  getFullName,
259
267
  getIsLoggedIn,
260
268
  getEmail,
269
+ getRoles,
270
+ getAccountType,
271
+ isPersonAccount,
272
+ isEntityAccount,
261
273
 
262
274
  // Authentication Actions
263
275
  login,