@bagelink/auth 1.1.41 → 1.1.43
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 +135 -201
- package/dist/index.d.cts +25 -29
- package/dist/index.d.mts +25 -29
- package/dist/index.d.ts +25 -29
- package/dist/index.mjs +135 -189
- package/package.json +13 -3
- package/src/api/auth.ts +81 -68
- package/src/composable/useAuth.ts +60 -126
- package/src/api/api.ts +0 -20
package/src/api/auth.ts
CHANGED
|
@@ -21,88 +21,101 @@ import type {
|
|
|
21
21
|
UpdatePasswordResponse,
|
|
22
22
|
SignupResponse
|
|
23
23
|
} from '../types'
|
|
24
|
-
import
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
import axios from 'axios'
|
|
25
|
+
|
|
26
|
+
export class AuthApi {
|
|
27
|
+
private api: ReturnType<typeof axios.create>
|
|
28
|
+
|
|
29
|
+
constructor(baseURL?: string) {
|
|
30
|
+
this.api = axios.create({
|
|
31
|
+
baseURL,
|
|
32
|
+
headers: {
|
|
33
|
+
'Content-Type': 'application/json',
|
|
34
|
+
},
|
|
35
|
+
})
|
|
36
|
+
this.setupInterceptors()
|
|
32
37
|
}
|
|
33
38
|
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
private setupInterceptors() {
|
|
40
|
+
this.api.interceptors.request.use((config: InternalAxiosRequestConfig) => {
|
|
41
|
+
const token = localStorage.getItem('access_token')
|
|
42
|
+
if (token !== null && config.headers) {
|
|
43
|
+
config.headers.Authorization = `Bearer ${token}`
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const urlParams = new URLSearchParams(window.location.search)
|
|
47
|
+
const resetToken = urlParams.get('token')
|
|
48
|
+
|
|
49
|
+
if (resetToken !== null && config.headers) {
|
|
50
|
+
config.headers.Authorization = `Bearer ${resetToken}`
|
|
51
|
+
}
|
|
52
|
+
return config
|
|
53
|
+
})
|
|
54
|
+
}
|
|
36
55
|
|
|
37
|
-
|
|
38
|
-
|
|
56
|
+
async login(username: string, password: string): Promise<LoginResponse> {
|
|
57
|
+
const { data } = await this.api.post<Token>('/auth/login', {
|
|
58
|
+
username: username.toLowerCase(),
|
|
59
|
+
password,
|
|
60
|
+
})
|
|
61
|
+
localStorage.setItem('access_token', data.access_token)
|
|
62
|
+
return { data } as LoginResponse
|
|
39
63
|
}
|
|
40
|
-
return config
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
export async function login(username: string, password: string): Promise<LoginResponse> {
|
|
44
|
-
const { data } = await ax.post<Token>('/auth/login', {
|
|
45
|
-
username: username.toLowerCase(),
|
|
46
|
-
password,
|
|
47
|
-
})
|
|
48
|
-
localStorage.setItem('access_token', data.access_token)
|
|
49
|
-
return { data } as LoginResponse
|
|
50
|
-
}
|
|
51
64
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
65
|
+
logout() {
|
|
66
|
+
localStorage.removeItem('access_token')
|
|
67
|
+
window.location.reload()
|
|
68
|
+
}
|
|
56
69
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
70
|
+
async passwordRecovery(email?: string): Promise<PasswordRecoveryResponse> {
|
|
71
|
+
return this.api.post('/auth/password-recovery', { email })
|
|
72
|
+
}
|
|
60
73
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
74
|
+
async resetPassword(newPassword: NewPassword['new_password']): Promise<ResetPasswordResponse> {
|
|
75
|
+
return this.api.post('/auth/reset-password', { new_password: newPassword })
|
|
76
|
+
}
|
|
64
77
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
78
|
+
async getCurrentUser(): Promise<GetMeResponse> {
|
|
79
|
+
return this.api.get<SanitizedUserOut>('/users/me')
|
|
80
|
+
}
|
|
69
81
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
82
|
+
async signup(user: NewUser): Promise<SignupResponse> {
|
|
83
|
+
return this.api.post<SanitizedUserOut>('/users/signup', {
|
|
84
|
+
email: user.email.toLowerCase(),
|
|
85
|
+
password: user.password,
|
|
86
|
+
first_name: user.first_name,
|
|
87
|
+
last_name: user.last_name,
|
|
88
|
+
})
|
|
89
|
+
}
|
|
78
90
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
91
|
+
async updatePassword(form: UpdatePasswordForm): Promise<UpdatePasswordResponse> {
|
|
92
|
+
return this.api.patch('/users/me/password', {
|
|
93
|
+
current_password: form.current_password,
|
|
94
|
+
new_password: form.new_password,
|
|
95
|
+
})
|
|
96
|
+
}
|
|
85
97
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
98
|
+
async updateUserProfile(user: Partial<User>): Promise<UpdateMeResponse> {
|
|
99
|
+
return this.api.patch<SanitizedUserOut>('/users/me', user)
|
|
100
|
+
}
|
|
89
101
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
102
|
+
async setUserStatus(userId: string, isActive: boolean): Promise<UpdateUserResponse> {
|
|
103
|
+
return this.api.patch<SanitizedUserOut>(`/users/${userId}`, { is_active: isActive })
|
|
104
|
+
}
|
|
93
105
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
106
|
+
async deleteUser(userId: string): Promise<DeleteUserResponse> {
|
|
107
|
+
return this.api.delete(`/users/${userId}`)
|
|
108
|
+
}
|
|
97
109
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
110
|
+
async getUsers(limit: number = 100, skip?: number): Promise<GetUsersResponse> {
|
|
111
|
+
return this.api.get<SanitizedUserList>('/users/', { params: { skip, limit } })
|
|
112
|
+
}
|
|
101
113
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
114
|
+
async createUser(user: UserCreate): Promise<CreateUserResponse> {
|
|
115
|
+
return this.api.post<SanitizedUserOut>('/users/', user)
|
|
116
|
+
}
|
|
105
117
|
|
|
106
|
-
|
|
107
|
-
|
|
118
|
+
async getUser(userId: string): Promise<GetUserResponse> {
|
|
119
|
+
return this.api.get<SanitizedUserOut>(`/users/${userId}`)
|
|
120
|
+
}
|
|
108
121
|
}
|
|
@@ -1,124 +1,72 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { User, NewUser, UpdatePasswordForm
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
let
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import type { App } from 'vue'
|
|
2
|
+
import type { User, NewUser, UpdatePasswordForm } from '../types'
|
|
3
|
+
import { AuthApi } from '../api/auth'
|
|
4
|
+
|
|
5
|
+
// Global state
|
|
6
|
+
let authApi: AuthApi | null = null
|
|
7
|
+
const currentUser = {
|
|
8
|
+
value: {
|
|
9
|
+
id: '',
|
|
10
|
+
email: '',
|
|
11
|
+
first_name: '',
|
|
12
|
+
last_name: '',
|
|
13
|
+
is_superuser: false,
|
|
14
|
+
is_active: false,
|
|
15
|
+
} as User,
|
|
16
|
+
set: (newValue: User) => {
|
|
17
|
+
currentUser.value = newValue
|
|
15
18
|
}
|
|
16
19
|
}
|
|
17
20
|
|
|
18
|
-
//
|
|
19
|
-
function
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return {
|
|
23
|
-
get value() { return refValue.value },
|
|
24
|
-
set: (v: T) => { refValue.value = v }
|
|
25
|
-
}
|
|
21
|
+
// Initialize auth
|
|
22
|
+
export function initAuth(baseURL?: string) {
|
|
23
|
+
if (!authApi) {
|
|
24
|
+
authApi = new AuthApi(baseURL)
|
|
26
25
|
}
|
|
27
|
-
}
|
|
28
26
|
|
|
29
|
-
// Create plugin instance
|
|
30
|
-
export function initAuth({
|
|
31
|
-
axios,
|
|
32
|
-
errorHandler,
|
|
33
|
-
reactive = defaultReactiveFactory,
|
|
34
|
-
baseURL
|
|
35
|
-
}: {
|
|
36
|
-
axios?: AxiosInstance
|
|
37
|
-
errorHandler?: (error: any) => void
|
|
38
|
-
reactive?: ReactiveFactory
|
|
39
|
-
baseURL?: string
|
|
40
|
-
} = {}) {
|
|
41
|
-
// Initialize API
|
|
42
|
-
api = axios || createDefaultApi(baseURL)
|
|
43
|
-
|
|
44
|
-
// Initialize error handler
|
|
45
|
-
if (errorHandler) onError = errorHandler
|
|
46
|
-
|
|
47
|
-
// Initialize reactive factory
|
|
48
|
-
createRef = reactive
|
|
49
|
-
|
|
50
|
-
// Return plugin interface
|
|
51
27
|
return {
|
|
52
|
-
install(app:
|
|
53
|
-
//
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
useAuth
|
|
28
|
+
install(app: App) {
|
|
29
|
+
// Make auth available globally
|
|
30
|
+
app.config.globalProperties.$auth = useAuth()
|
|
31
|
+
}
|
|
59
32
|
}
|
|
60
33
|
}
|
|
61
34
|
|
|
35
|
+
// Composable
|
|
62
36
|
export function useAuth() {
|
|
63
|
-
if (!
|
|
64
|
-
throw new Error('Auth
|
|
37
|
+
if (!authApi) {
|
|
38
|
+
throw new Error('Auth not initialized. Call initAuth first.')
|
|
65
39
|
}
|
|
66
40
|
|
|
67
|
-
// State
|
|
68
|
-
const currentUser = createRef<User>({
|
|
69
|
-
id: '',
|
|
70
|
-
email: '',
|
|
71
|
-
first_name: '',
|
|
72
|
-
last_name: '',
|
|
73
|
-
is_superuser: false,
|
|
74
|
-
is_active: false,
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
const passwordForm = createRef<UpdatePasswordForm>({
|
|
78
|
-
current_password: '',
|
|
79
|
-
new_password: '',
|
|
80
|
-
confirmNewPassword: '',
|
|
81
|
-
})
|
|
82
|
-
|
|
83
41
|
// Getters
|
|
84
42
|
const getFullName = () => `${currentUser.value.first_name} ${currentUser.value.last_name}`
|
|
85
43
|
const getIsLoggedIn = () => currentUser.value.id.length > 0
|
|
86
44
|
|
|
87
|
-
// Error handling
|
|
88
|
-
function handleError(error: any) {
|
|
89
|
-
if (onError) {
|
|
90
|
-
onError(error)
|
|
91
|
-
}
|
|
92
|
-
throw error
|
|
93
|
-
}
|
|
94
|
-
|
|
95
45
|
// Actions
|
|
96
46
|
async function logout() {
|
|
97
47
|
try {
|
|
98
|
-
await authApi
|
|
99
|
-
} catch (error
|
|
100
|
-
|
|
48
|
+
await authApi!.logout()
|
|
49
|
+
} catch (error) {
|
|
50
|
+
throw error
|
|
101
51
|
}
|
|
102
52
|
}
|
|
103
53
|
|
|
104
54
|
async function login(credentials: { email: string, password: string }) {
|
|
105
|
-
const email = credentials.email.toLowerCase()
|
|
106
|
-
const { password } = credentials
|
|
107
55
|
try {
|
|
108
|
-
await authApi
|
|
56
|
+
await authApi!.login(credentials.email.toLowerCase(), credentials.password)
|
|
109
57
|
await checkAuth()
|
|
110
|
-
} catch (error
|
|
111
|
-
|
|
58
|
+
} catch (error) {
|
|
59
|
+
throw error
|
|
112
60
|
}
|
|
113
61
|
}
|
|
114
62
|
|
|
115
63
|
async function checkAuth(): Promise<boolean> {
|
|
116
64
|
try {
|
|
117
65
|
if (!getIsLoggedIn()) {
|
|
118
|
-
const { data } = await authApi
|
|
66
|
+
const { data } = await authApi!.getCurrentUser()
|
|
119
67
|
currentUser.set(data)
|
|
120
68
|
}
|
|
121
|
-
} catch (error
|
|
69
|
+
} catch (error) {
|
|
122
70
|
return false
|
|
123
71
|
}
|
|
124
72
|
return getIsLoggedIn()
|
|
@@ -129,82 +77,68 @@ export function useAuth() {
|
|
|
129
77
|
if (user.password !== user.confirmPassword) {
|
|
130
78
|
throw new Error('Passwords do not match')
|
|
131
79
|
}
|
|
132
|
-
const { data } = await authApi
|
|
80
|
+
const { data } = await authApi!.signup(user)
|
|
133
81
|
currentUser.set(data)
|
|
134
|
-
} catch (error
|
|
135
|
-
|
|
82
|
+
} catch (error) {
|
|
83
|
+
throw error
|
|
136
84
|
}
|
|
137
85
|
}
|
|
138
86
|
|
|
139
87
|
async function recoverPassword(email: string) {
|
|
140
88
|
try {
|
|
141
|
-
await authApi
|
|
142
|
-
} catch (error
|
|
143
|
-
|
|
89
|
+
await authApi!.passwordRecovery(email)
|
|
90
|
+
} catch (error) {
|
|
91
|
+
throw error
|
|
144
92
|
}
|
|
145
93
|
}
|
|
146
94
|
|
|
147
|
-
async function resetPassword(
|
|
95
|
+
async function resetPassword(newPassword: string) {
|
|
148
96
|
try {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
await authApi.resetPassword(form.new_password)
|
|
153
|
-
form = {
|
|
154
|
-
current_password: '',
|
|
155
|
-
new_password: '',
|
|
156
|
-
confirmNewPassword: '',
|
|
157
|
-
}
|
|
158
|
-
} catch (error: any) {
|
|
159
|
-
handleError(error)
|
|
97
|
+
await authApi!.resetPassword(newPassword)
|
|
98
|
+
} catch (error) {
|
|
99
|
+
throw error
|
|
160
100
|
}
|
|
161
101
|
}
|
|
162
102
|
|
|
163
|
-
async function updatePassword() {
|
|
103
|
+
async function updatePassword(form: UpdatePasswordForm) {
|
|
164
104
|
try {
|
|
165
|
-
if (
|
|
105
|
+
if (form.new_password !== form.confirmNewPassword) {
|
|
166
106
|
throw new Error('Passwords do not match')
|
|
167
107
|
}
|
|
168
|
-
await authApi
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
new_password: '',
|
|
172
|
-
confirmNewPassword: '',
|
|
173
|
-
})
|
|
174
|
-
} catch (error: any) {
|
|
175
|
-
handleError(error)
|
|
108
|
+
await authApi!.updatePassword(form)
|
|
109
|
+
} catch (error) {
|
|
110
|
+
throw error
|
|
176
111
|
}
|
|
177
112
|
}
|
|
178
113
|
|
|
179
114
|
async function updateProfile(user: Partial<User>) {
|
|
180
115
|
try {
|
|
181
|
-
const { data } = await authApi
|
|
116
|
+
const { data } = await authApi!.updateUserProfile(user)
|
|
182
117
|
currentUser.set({ ...currentUser.value, ...data })
|
|
183
|
-
} catch (error
|
|
184
|
-
|
|
118
|
+
} catch (error) {
|
|
119
|
+
throw error
|
|
185
120
|
}
|
|
186
121
|
}
|
|
187
122
|
|
|
188
123
|
async function toggleUserStatus(userId: string, isActive: boolean) {
|
|
189
124
|
try {
|
|
190
|
-
await authApi
|
|
191
|
-
} catch (error
|
|
192
|
-
|
|
125
|
+
await authApi!.setUserStatus(userId, isActive)
|
|
126
|
+
} catch (error) {
|
|
127
|
+
throw error
|
|
193
128
|
}
|
|
194
129
|
}
|
|
195
130
|
|
|
196
131
|
async function deleteUser(userId: string) {
|
|
197
132
|
try {
|
|
198
|
-
await authApi
|
|
199
|
-
} catch (error
|
|
200
|
-
|
|
133
|
+
await authApi!.deleteUser(userId)
|
|
134
|
+
} catch (error) {
|
|
135
|
+
throw error
|
|
201
136
|
}
|
|
202
137
|
}
|
|
203
138
|
|
|
204
139
|
return {
|
|
205
140
|
// State
|
|
206
141
|
currentUser,
|
|
207
|
-
passwordForm,
|
|
208
142
|
|
|
209
143
|
// Getters
|
|
210
144
|
getFullName,
|
package/src/api/api.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { AxiosInstance } from 'axios'
|
|
2
|
-
import axios from 'axios'
|
|
3
|
-
|
|
4
|
-
const api: AxiosInstance | undefined = undefined
|
|
5
|
-
|
|
6
|
-
export function getApi(): AxiosInstance {
|
|
7
|
-
if (!api) {
|
|
8
|
-
throw new Error('API not initialized. Call initAuth first.')
|
|
9
|
-
}
|
|
10
|
-
return api
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function createDefaultApi(baseURL?: string) {
|
|
14
|
-
return axios.create({
|
|
15
|
-
baseURL,
|
|
16
|
-
headers: {
|
|
17
|
-
'Content-Type': 'application/json',
|
|
18
|
-
},
|
|
19
|
-
})
|
|
20
|
-
}
|