Fix CustomerType and OwnerType enums: send int instead of string
Some checks failed
Build frontend / build (push) Failing after 45s
Some checks failed
Build frontend / build (push) Failing after 45s
- CustomerType: PERSONAL=0, FAMILY=1 (was 'Personal', 'Family') - OwnerType: PERSON=0, REAL_ESTATE_AGENCY=1 (was 'peerson', 'RealEstateAgency') - Backend Type column is int(11), sending strings caused 415 errors
This commit is contained in:
@ -36,6 +36,8 @@ import {
|
|||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useState, useEffect, useRef } from "react";
|
import { useState, useEffect, useRef } from "react";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
|
import AuthService from "../services/AuthService";
|
||||||
|
import { UserRole, UserRoleLabels } from "./enums/UserRole";
|
||||||
import "./i18n/config";
|
import "./i18n/config";
|
||||||
|
|
||||||
export default function ClientLayout({ children }) {
|
export default function ClientLayout({ children }) {
|
||||||
@ -55,11 +57,17 @@ export default function ClientLayout({ children }) {
|
|||||||
setCurrentLanguage(savedLanguage);
|
setCurrentLanguage(savedLanguage);
|
||||||
i18n.changeLanguage(savedLanguage);
|
i18n.changeLanguage(savedLanguage);
|
||||||
|
|
||||||
const storedUser = localStorage.getItem("user");
|
// Load user from JWT via AuthService
|
||||||
if (storedUser) {
|
const authUser = AuthService.getUser();
|
||||||
const userData = JSON.parse(storedUser);
|
if (authUser) {
|
||||||
console.log("User data loaded:", userData);
|
setUser({
|
||||||
setUser(userData);
|
name: authUser.name || authUser.email,
|
||||||
|
email: authUser.email,
|
||||||
|
phone: authUser.phone,
|
||||||
|
role: AuthService.isOwner() ? UserRole.OWNER : UserRole.CUSTOMER,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setUser(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (savedLanguage === "ar") {
|
if (savedLanguage === "ar") {
|
||||||
@ -104,7 +112,7 @@ export default function ClientLayout({ children }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const logout = () => {
|
const logout = () => {
|
||||||
localStorage.removeItem("user");
|
AuthService.deleteToken();
|
||||||
setUser(null);
|
setUser(null);
|
||||||
setShowUserMenu(false);
|
setShowUserMenu(false);
|
||||||
window.location.href = "/";
|
window.location.href = "/";
|
||||||
@ -119,11 +127,10 @@ export default function ClientLayout({ children }) {
|
|||||||
|
|
||||||
const isProfilePage = pathname === "/profile";
|
const isProfilePage = pathname === "/profile";
|
||||||
|
|
||||||
const isOwner = user?.role === "owner";
|
const isOwner = user?.role === UserRole.OWNER;
|
||||||
const isAdmin = user?.role === "admin";
|
const isAdmin = user?.role === UserRole.ADMIN;
|
||||||
|
const isCustomer = user?.role === UserRole.CUSTOMER;
|
||||||
console.log("User role:", user?.role);
|
const isAuthenticated = !!user;
|
||||||
console.log("Is Admin:", isAdmin);
|
|
||||||
|
|
||||||
const getUserInitial = () => {
|
const getUserInitial = () => {
|
||||||
if (user?.name) {
|
if (user?.name) {
|
||||||
@ -295,11 +302,7 @@ export default function ClientLayout({ children }) {
|
|||||||
{user?.email || ""}
|
{user?.email || ""}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs text-amber-100 mt-1">
|
<p className="text-xs text-amber-100 mt-1">
|
||||||
{isOwner
|
{UserRoleLabels[user?.role] || 'زائر'}
|
||||||
? "مالك عقار"
|
|
||||||
: isAdmin
|
|
||||||
? "مدير النظام"
|
|
||||||
: "مستأجر"}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -486,7 +489,7 @@ export default function ClientLayout({ children }) {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!isOwner && !isAdmin && user && (
|
{isCustomer && (
|
||||||
<>
|
<>
|
||||||
<div className="border-t border-gray-100 my-2"></div>
|
<div className="border-t border-gray-100 my-2"></div>
|
||||||
|
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
* Used in: Customer registration (Customer/Add)
|
* Used in: Customer registration (Customer/Add)
|
||||||
*/
|
*/
|
||||||
const CustomerType = Object.freeze({
|
const CustomerType = Object.freeze({
|
||||||
PERSONAL: 'Personal',
|
PERSONAL: 0,
|
||||||
FAMILY: 'Family',
|
FAMILY: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Map value → Arabic label
|
// Map value → Arabic label
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
* Used in: Owner registration (Owner/Add)
|
* Used in: Owner registration (Owner/Add)
|
||||||
*/
|
*/
|
||||||
const OwnerType = Object.freeze({
|
const OwnerType = Object.freeze({
|
||||||
PERSON: 'peerson',
|
PERSON: 0,
|
||||||
REAL_ESTATE_AGENCY: 'RealEstateAgency',
|
REAL_ESTATE_AGENCY: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Map value → Arabic label
|
// Map value → Arabic label
|
||||||
|
|||||||
@ -1,25 +1,26 @@
|
|||||||
/**
|
/**
|
||||||
* UserRole Enum
|
* UserRole Enum
|
||||||
* User account roles in the system
|
* User account roles in the system
|
||||||
* Used in: JWT payload, registration, routing
|
* Derived from JWT token claims
|
||||||
*/
|
*/
|
||||||
const UserRole = Object.freeze({
|
const UserRole = Object.freeze({
|
||||||
|
GUEST: 'guest',
|
||||||
|
CUSTOMER: 'customer',
|
||||||
OWNER: 'owner',
|
OWNER: 'owner',
|
||||||
TENANT: 'tenant',
|
|
||||||
ADMIN: 'admin',
|
ADMIN: 'admin',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Map role → Arabic label
|
|
||||||
const UserRoleLabels = Object.freeze({
|
const UserRoleLabels = Object.freeze({
|
||||||
|
[UserRole.GUEST]: 'زائر',
|
||||||
|
[UserRole.CUSTOMER]: 'مستأجر',
|
||||||
[UserRole.OWNER]: 'مالك عقار',
|
[UserRole.OWNER]: 'مالك عقار',
|
||||||
[UserRole.TENANT]: 'مستأجر',
|
|
||||||
[UserRole.ADMIN]: 'مدير النظام',
|
[UserRole.ADMIN]: 'مدير النظام',
|
||||||
});
|
});
|
||||||
|
|
||||||
// Map role → color theme (used in UI)
|
|
||||||
const UserRoleColors = Object.freeze({
|
const UserRoleColors = Object.freeze({
|
||||||
|
[UserRole.GUEST]: 'gray',
|
||||||
|
[UserRole.CUSTOMER]: 'blue',
|
||||||
[UserRole.OWNER]: 'amber',
|
[UserRole.OWNER]: 'amber',
|
||||||
[UserRole.TENANT]: 'blue',
|
|
||||||
[UserRole.ADMIN]: 'red',
|
[UserRole.ADMIN]: 'red',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -93,24 +93,12 @@ export default function LoginPage() {
|
|||||||
AuthService.addToken(token);
|
AuthService.addToken(token);
|
||||||
console.log('[Login] Token stored via AuthService');
|
console.log('[Login] Token stored via AuthService');
|
||||||
|
|
||||||
// Decode token to get user info (basic JWT decode)
|
// Decode token to get user info via AuthService
|
||||||
try {
|
const authUser = AuthService.getUser();
|
||||||
const payload = JSON.parse(atob(token.split('.')[1]));
|
const userRole = authUser?.roles?.includes('Owner') ? 'owner'
|
||||||
const user = {
|
: authUser?.roles?.includes('Admin') ? 'admin'
|
||||||
name: payload.name || payload.unique_name || formData.credential,
|
: 'customer';
|
||||||
email: payload.email || (loginMethod === 'email' ? formData.credential : ''),
|
console.log('[Login] User role:', userRole);
|
||||||
phone: payload.phone || (loginMethod === 'phone' ? formData.credential : ''),
|
|
||||||
role: payload.role || payload.Role || 'customer',
|
|
||||||
};
|
|
||||||
localStorage.setItem('user', JSON.stringify(user));
|
|
||||||
console.log('[Login] User stored:', user);
|
|
||||||
} catch (decodeErr) {
|
|
||||||
console.warn('[Login] Could not decode JWT, storing credential as user');
|
|
||||||
localStorage.setItem('user', JSON.stringify({
|
|
||||||
name: formData.credential,
|
|
||||||
role: 'customer',
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsSuccess(true);
|
setIsSuccess(true);
|
||||||
toast.success('تم تسجيل الدخول بنجاح!', {
|
toast.success('تم تسجيل الدخول بنجاح!', {
|
||||||
@ -118,9 +106,7 @@ export default function LoginPage() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const user = JSON.parse(localStorage.getItem('user') || '{}');
|
if (userRole === 'admin') {
|
||||||
console.log('[Login] Redirecting user:', user);
|
|
||||||
if (user.role === 'admin') {
|
|
||||||
router.push('/admin');
|
router.push('/admin');
|
||||||
} else {
|
} else {
|
||||||
router.push('/');
|
router.push('/');
|
||||||
@ -190,11 +176,6 @@ export default function LoginPage() {
|
|||||||
console.log('[OTP] Token stored via AuthService');
|
console.log('[OTP] Token stored via AuthService');
|
||||||
}
|
}
|
||||||
|
|
||||||
localStorage.setItem('user', JSON.stringify({
|
|
||||||
name: formData.credential,
|
|
||||||
role: 'customer',
|
|
||||||
}));
|
|
||||||
|
|
||||||
setIsSuccess(true);
|
setIsSuccess(true);
|
||||||
toast.success('تم التحقق بنجاح!', {
|
toast.success('تم التحقق بنجاح!', {
|
||||||
style: { background: '#dcfce7', color: '#166534' },
|
style: { background: '#dcfce7', color: '#166534' },
|
||||||
|
|||||||
@ -33,6 +33,7 @@ import {
|
|||||||
Building
|
Building
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import toast, { Toaster } from 'react-hot-toast';
|
import toast, { Toaster } from 'react-hot-toast';
|
||||||
|
import AuthService from '../../../services/AuthService';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
|
|
||||||
const OwnerBookingCalendar = ({ property, onDateSelect, selectedDates }) => {
|
const OwnerBookingCalendar = ({ property, onDateSelect, selectedDates }) => {
|
||||||
@ -425,8 +426,8 @@ export default function OwnerBookingsPage() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const storedUser = localStorage.getItem('user');
|
const storedUser = localStorage.getItem('user');
|
||||||
if (storedUser) {
|
// User loaded via AuthService
|
||||||
const userData = JSON.parse(storedUser);
|
// Handled above
|
||||||
if (userData.role !== 'owner') {
|
if (userData.role !== 'owner') {
|
||||||
router.push('/');
|
router.push('/');
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -36,6 +36,7 @@ import {
|
|||||||
Calendar as CalendarIcon
|
Calendar as CalendarIcon
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import toast, { Toaster } from 'react-hot-toast';
|
import toast, { Toaster } from 'react-hot-toast';
|
||||||
|
import AuthService from '../../../services/AuthService';
|
||||||
|
|
||||||
const MonthlyCalendar = ({ properties, selectedPropertyId, onDateClick, onPropertySelect }) => {
|
const MonthlyCalendar = ({ properties, selectedPropertyId, onDateClick, onPropertySelect }) => {
|
||||||
const [currentMonth, setCurrentMonth] = useState(new Date());
|
const [currentMonth, setCurrentMonth] = useState(new Date());
|
||||||
@ -484,8 +485,8 @@ export default function OwnerCalendarPage() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const storedUser = localStorage.getItem('user');
|
const storedUser = localStorage.getItem('user');
|
||||||
if (storedUser) {
|
// User loaded via AuthService
|
||||||
const userData = JSON.parse(storedUser);
|
// Handled above
|
||||||
if (userData.role !== 'owner') {
|
if (userData.role !== 'owner') {
|
||||||
router.push('/');
|
router.push('/');
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -28,6 +28,7 @@ import {
|
|||||||
XCircle
|
XCircle
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import toast, { Toaster } from 'react-hot-toast';
|
import toast, { Toaster } from 'react-hot-toast';
|
||||||
|
import AuthService from '../../../services/AuthService';
|
||||||
|
|
||||||
const StatCard = ({ title, value, change, icon: Icon, color, trend }) => {
|
const StatCard = ({ title, value, change, icon: Icon, color, trend }) => {
|
||||||
return (
|
return (
|
||||||
@ -237,8 +238,8 @@ export default function OwnerProfitsPage() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const storedUser = localStorage.getItem('user');
|
const storedUser = localStorage.getItem('user');
|
||||||
if (storedUser) {
|
// User loaded via AuthService
|
||||||
const userData = JSON.parse(storedUser);
|
// Handled above
|
||||||
if (userData.role !== 'owner') {
|
if (userData.role !== 'owner') {
|
||||||
router.push('/');
|
router.push('/');
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -45,6 +45,7 @@ import {
|
|||||||
X
|
X
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import toast, { Toaster } from 'react-hot-toast';
|
import toast, { Toaster } from 'react-hot-toast';
|
||||||
|
import AuthService from '../../../services/AuthService';
|
||||||
|
|
||||||
const DeleteConfirmationModal = ({ isOpen, onClose, onConfirm, propertyTitle }) => {
|
const DeleteConfirmationModal = ({ isOpen, onClose, onConfirm, propertyTitle }) => {
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null;
|
||||||
@ -693,8 +694,8 @@ export default function OwnerPropertiesPage() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const storedUser = localStorage.getItem('user');
|
const storedUser = localStorage.getItem('user');
|
||||||
if (storedUser) {
|
// User loaded via AuthService
|
||||||
const userData = JSON.parse(storedUser);
|
// Handled above
|
||||||
if (userData.role !== 'owner') {
|
if (userData.role !== 'owner') {
|
||||||
router.push('/');
|
router.push('/');
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
13
app/page.js
13
app/page.js
@ -30,6 +30,7 @@ import Link from 'next/link';
|
|||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { getRentProperties, getSaleProperties } from './utils/api';
|
import { getRentProperties, getSaleProperties } from './utils/api';
|
||||||
import { BuildingTypeKeys, PropertyStatusKeys, extractCity } from './enums';
|
import { BuildingTypeKeys, PropertyStatusKeys, extractCity } from './enums';
|
||||||
|
import AuthService from './services/AuthService';
|
||||||
|
|
||||||
// Map API property data to the format the UI expects
|
// Map API property data to the format the UI expects
|
||||||
// API returns { propertyInformationId, deposit, monthlyRent, dailyRent, rating, propertyInformation: {...}, ... }
|
// API returns { propertyInformationId, deposit, monthlyRent, dailyRent, rating, propertyInformation: {...}, ... }
|
||||||
@ -180,9 +181,13 @@ export default function HomePage() {
|
|||||||
|
|
||||||
// Fetch properties from API on mount
|
// Fetch properties from API on mount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const storedUser = localStorage.getItem('user');
|
const authUser = AuthService.getUser();
|
||||||
if (storedUser) {
|
if (authUser) {
|
||||||
setUser(JSON.parse(storedUser));
|
setUser({
|
||||||
|
name: authUser.name || authUser.email,
|
||||||
|
email: authUser.email,
|
||||||
|
role: AuthService.isOwner() ? 'owner' : 'customer',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchProperties() {
|
async function fetchProperties() {
|
||||||
@ -226,7 +231,7 @@ export default function HomePage() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const logout = () => {
|
const logout = () => {
|
||||||
localStorage.removeItem('user');
|
AuthService.deleteToken();
|
||||||
setUser(null);
|
setUser(null);
|
||||||
setShowUserMenu(false);
|
setShowUserMenu(false);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -27,6 +27,7 @@ import {
|
|||||||
Pencil
|
Pencil
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import toast, { Toaster } from 'react-hot-toast';
|
import toast, { Toaster } from 'react-hot-toast';
|
||||||
|
import AuthService from '../services/AuthService';
|
||||||
|
|
||||||
export default function ProfilePage() {
|
export default function ProfilePage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -62,9 +63,14 @@ export default function ProfilePage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const storedUser = localStorage.getItem('user');
|
const authUser = AuthService.getUser();
|
||||||
if (storedUser) {
|
if (authUser) {
|
||||||
const userData = JSON.parse(storedUser);
|
const userData = {
|
||||||
|
name: authUser.name || '',
|
||||||
|
email: authUser.email || '',
|
||||||
|
phone: authUser.phone || '',
|
||||||
|
role: AuthService.isOwner() ? 'owner' : 'customer',
|
||||||
|
};
|
||||||
setUser(userData);
|
setUser(userData);
|
||||||
|
|
||||||
const savedProfile = localStorage.getItem('userProfile');
|
const savedProfile = localStorage.getItem('userProfile');
|
||||||
@ -167,7 +173,6 @@ export default function ProfilePage() {
|
|||||||
|
|
||||||
if (field === 'name') {
|
if (field === 'name') {
|
||||||
const updatedUser = { ...user, name: value };
|
const updatedUser = { ...user, name: value };
|
||||||
localStorage.setItem('user', JSON.stringify(updatedUser));
|
|
||||||
setUser(updatedUser);
|
setUser(updatedUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,50 +1,117 @@
|
|||||||
/**
|
/**
|
||||||
* AuthService
|
* AuthService
|
||||||
* Manages authentication tokens securely using localStorage.
|
* Manages authentication tokens and user role detection via JWT decoding.
|
||||||
*
|
|
||||||
* Methods:
|
|
||||||
* addToken(token) — store JWT token
|
|
||||||
* getToken() — retrieve JWT token
|
|
||||||
* deleteToken() — remove JWT token
|
|
||||||
*
|
*
|
||||||
* Usage:
|
* Roles (from JWT claims):
|
||||||
* import AuthService from '@/app/services/AuthService';
|
* - Owner: roles array contains "Owner"
|
||||||
* AuthService.addToken(token);
|
* - Customer: authenticated but no "Owner" role
|
||||||
* const token = AuthService.getToken();
|
* - Guest: no token
|
||||||
* AuthService.deleteToken();
|
*
|
||||||
|
* 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 TOKEN_KEY = 'auth_token';
|
||||||
|
|
||||||
const AuthService = Object.freeze({
|
const AuthService = Object.freeze({
|
||||||
/**
|
|
||||||
* Store token in localStorage
|
|
||||||
* @param {string} token — JWT string
|
|
||||||
*/
|
|
||||||
addToken(token) {
|
addToken(token) {
|
||||||
if (!token || typeof token !== 'string') {
|
if (!token || typeof token !== 'string') return;
|
||||||
console.error('[AuthService] addToken: invalid token', token);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
localStorage.setItem(TOKEN_KEY, token);
|
localStorage.setItem(TOKEN_KEY, token);
|
||||||
console.log('[AuthService] Token stored');
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve token from localStorage
|
|
||||||
* @returns {string|null}
|
|
||||||
*/
|
|
||||||
getToken() {
|
getToken() {
|
||||||
const token = localStorage.getItem(TOKEN_KEY);
|
return localStorage.getItem(TOKEN_KEY);
|
||||||
console.log('[AuthService] getToken:', token ? '***exists***' : null);
|
|
||||||
return token;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove token from localStorage
|
|
||||||
*/
|
|
||||||
deleteToken() {
|
deleteToken() {
|
||||||
localStorage.removeItem(TOKEN_KEY);
|
localStorage.removeItem(TOKEN_KEY);
|
||||||
console.log('[AuthService] Token deleted');
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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() {
|
||||||
|
const roles = this.getRoles();
|
||||||
|
return roles.includes('Owner');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authenticated user without Owner role (i.e. customer)
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isCustomer() {
|
||||||
|
return this.isAuthenticated() && !this.isOwner();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No token — guest user
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isGuest() {
|
||||||
|
return !this.getToken();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Token exists
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isAuthenticated() {
|
||||||
|
return !!this.getToken();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user