/** * AuthService * Manages authentication tokens and user role detection via JWT decoding. * * Roles (from JWT claims): * - Owner: roles array contains "Owner" * - Customer: authenticated but no "Owner" role * - Guest: no token * * Methods: * addToken(token) — store JWT token * getToken() — retrieve JWT token * deleteToken() — remove JWT token * decodeToken() — decode JWT payload * getUser() — get decoded user info * getRoles() — get roles array from JWT * isOwner() — check if user has Owner role * isCustomer() — check if user is authenticated but not Owner * isGuest() — check if no token exists * isAuthenticated() — check if token exists */ const TOKEN_KEY = 'auth_token'; const AuthService = Object.freeze({ addToken(token) { if (!token || typeof token !== 'string') return; localStorage.setItem(TOKEN_KEY, token); }, getToken() { return localStorage.getItem(TOKEN_KEY); }, deleteToken() { localStorage.removeItem(TOKEN_KEY); }, /** * Decode JWT payload (base64) * @returns {object|null} */ decodeToken() { const token = this.getToken(); if (!token) return null; try { const payload = token.split('.')[1]; return JSON.parse(atob(payload)); } catch { return null; } }, /** * Extract user info from JWT * @returns {object|null} — { id, name, email, phone, roles } */ getUser() { const payload = this.decodeToken(); if (!payload) return null; return { id: payload['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier'] || payload.sub || null, name: payload['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name'] || null, email: payload['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'] || null, phone: payload['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone'] || null, roles: this.getRoles(), }; }, /** * Get roles array from JWT * @returns {string[]} */ getRoles() { const payload = this.decodeToken(); if (!payload) return []; const roles = payload['http://schemas.microsoft.com/ws/2008/06/identity/claims/role']; if (Array.isArray(roles)) return roles; if (typeof roles === 'string') return [roles]; return []; }, /** * User has Owner role * @returns {boolean} */ isOwner() { return this.getRoles().includes('Owner'); }, /** * User has Admin role * @returns {boolean} */ isAdmin() { return this.getRoles().includes('Admin'); }, /** * Authenticated user without Owner or Admin role (i.e. customer) * @returns {boolean} */ isCustomer() { return this.isAuthenticated() && !this.isOwner() && !this.isAdmin(); }, /** * No token — guest user * @returns {boolean} */ isGuest() { return !this.getToken(); }, /** * Token exists * @returns {boolean} */ isAuthenticated() { return !!this.getToken(); }, }); export default AuthService;