main
ts 134 lines 3.53 KB
Raw
1 import type { LoginPayload } from "@/api/endpoints/auth"
2 import type { AuthResponse, AuthUser, AuthUserRole, JWTPayload, RouteMetaAuthRole } from "@/types/auth"
3 import type { ApiError } from "@/types/common"
4 import * as jose from "jose"
5 import _capitalize from "lodash/capitalize"
6 import _castArray from "lodash/castArray"
7 import { acceptHMRUpdate, defineStore } from "pinia"
8 import Api from "@/api"
9 import { useCustomerFilterStore } from "@/stores/customerFilter"
10 import { RouteRole } from "@/types/auth"
11 import { getAvatar } from "@/utils"
12 import { jwtRoleToUserRole } from "@/utils/auth"
13 import { getNameInitials, toNumber } from "@/utils/format"
14 import { piniaStorage, removePersistentSessionKey } from "@/utils/secure-storage"
15
16 export const useAuthStore = defineStore("auth", {
17 state: () => ({
18 user: null as AuthUser | null,
19 tokenDebounceTime: toNumber(import.meta.env.VITE_TOKEN_DEBOUNCE_TIME) || 10 // seconds
20 }),
21 actions: {
22 setLogged(payload: AuthResponse) {
23 const jwtPayload = jose.decodeJwt<JWTPayload>(payload.access_token)
24
25 this.user = {
26 access_token: payload.access_token,
27 refresh_token: payload.refresh_token,
28 username: jwtPayload.sub || "",
29 customer_code: jwtPayload.customer_codes?.[0] || null,
30 customer_codes: jwtPayload.customer_codes ?? [],
31 role: jwtRoleToUserRole(jwtPayload.scopes)
32 }
33 },
34 setTokens(payload: AuthResponse) {
35 if (this.user) {
36 this.user.access_token = payload.access_token
37 this.user.refresh_token = payload.refresh_token
38 }
39 },
40 setLogout() {
41 this.user = null
42
43 useCustomerFilterStore().clear()
44 removePersistentSessionKey()
45 },
46 async login(payload: LoginPayload) {
47 try {
48 const response = await Api.auth.login(payload)
49
50 if (response.data) {
51 this.setLogged(response.data)
52 }
53
54 return response.data
55 } catch (err) {
56 const error = err as ApiError
57 throw error.response?.data
58 }
59 },
60 refreshToken() {
61 return new Promise((resolve, reject) => {
62 const refreshToken = this.user?.refresh_token || ""
63
64 Api.auth
65 .refresh(refreshToken)
66 .then(res => {
67 if (res.data) {
68 this.setTokens(res.data)
69 resolve(res.data)
70 } else {
71 reject(res.data)
72 }
73 })
74 .catch(err => {
75 reject(err.response?.data || err)
76 })
77 })
78 }
79 },
80 getters: {
81 isLogged(state): boolean {
82 return !!state.user?.access_token
83 },
84 userToken(state): string | null {
85 return state.user?.access_token || null
86 },
87 userCustomerCode(state): string | null {
88 return state.user?.customer_code || null
89 },
90 accessibleCustomerCodes(state): string[] {
91 return state.user?.customer_codes ?? []
92 },
93 userName(state): string | null {
94 return state.user?.username || null
95 },
96 userRole(state): AuthUserRole | string | null {
97 return state.user?.role || null
98 },
99 userRoleName(state): string | null {
100 return _capitalize(state.user?.role ?? "")
101 },
102 userPic(): string {
103 const initial = getNameInitials(this.userName || "")
104
105 return getAvatar({ seed: initial, text: initial, size: 64 })
106 },
107 isRoleGranted() {
108 return (roles?: RouteMetaAuthRole | RouteMetaAuthRole[]) => {
109 if (!roles) {
110 return true
111 }
112 if (!this.userRole) {
113 return false
114 }
115
116 const arrRoles: RouteMetaAuthRole[] = _castArray(roles)
117
118 if (arrRoles.includes(RouteRole.All)) {
119 return true
120 }
121
122 return arrRoles.includes(this.userRole)
123 }
124 }
125 },
126 persist: {
127 storage: piniaStorage({ session: true }),
128 pick: ["user"]
129 }
130 })
131
132 if (import.meta.hot) {
133 import.meta.hot.accept(acceptHMRUpdate(useAuthStore, import.meta.hot))
134 }