Skip to content

Commit e14cce4

Browse files
committed
feat: update user and team service response handling and cache management
1 parent cd5177a commit e14cce4

File tree

3 files changed

+56
-42
lines changed

3 files changed

+56
-42
lines changed

services/frontend/src/router/index.ts

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ const routes = [
6969
},
7070
{
7171
path: '/admin',
72-
meta: {
72+
meta: {
7373
requiresSetup: true,
7474
requiresRole: 'global_admin'
7575
},
@@ -101,19 +101,37 @@ const router = createRouter({
101101
// Navigation guard to check database setup
102102
router.beforeEach(async (to, from, next) => {
103103
const databaseStore = useDatabaseStore()
104-
104+
105105
// Define public routes that don't need user authentication checks
106106
const publicRoutes = ['Setup', 'Login', 'Register']
107107
const isPublicRoute = publicRoutes.includes(to.name as string)
108-
108+
109+
// Attempt to get current user status early
110+
let currentUser: any = null;
111+
try {
112+
// Avoid force refreshing cache here unless necessary, to use existing session info
113+
currentUser = await UserService.getCurrentUser();
114+
} catch (error) {
115+
console.error('Failed to get current user in guard:', error);
116+
// currentUser remains null, proceed as unauthenticated for safety
117+
}
118+
119+
// If user is logged in and trying to access Login or Register, redirect to Dashboard
120+
if (currentUser && (to.name === 'Login' || to.name === 'Register')) {
121+
next('/dashboard');
122+
return;
123+
}
124+
109125
// Skip setup check for the setup route itself
110126
if (to.name === 'Setup') {
111127
next()
112128
return
113129
}
114130

115-
// For public routes (Login/Register), only check database setup, skip user checks
131+
// For public routes (Login/Register) that are NOT being accessed by an already logged-in user
116132
if (isPublicRoute) {
133+
// This block is now for genuinely unauthenticated users accessing Login/Register
134+
// or for the Setup page (though Setup is handled above, this keeps structure)
117135
// Check if route requires setup
118136
if (to.meta.requiresSetup !== false) {
119137
try {
@@ -132,27 +150,20 @@ router.beforeEach(async (to, from, next) => {
132150
return
133151
}
134152
}
135-
136-
// For public routes, proceed without user checks
153+
154+
// For public routes, proceed without further user checks if not already redirected
137155
next()
138156
return
139157
}
140158

141-
// For protected routes, check user authentication (single call)
142-
let currentUser: any = null
143-
try {
144-
currentUser = await UserService.getCurrentUser()
145-
} catch (error) {
146-
console.error('Failed to get current user:', error)
147-
}
148-
149-
// If user is logged in and trying to access Login or Register, redirect to Dashboard
150-
if (currentUser && (to.name === 'Login' || to.name === 'Register')) {
151-
next('/dashboard')
152-
return
159+
// For protected routes (user is not null or trying to access login/register when logged in)
160+
// If not logged in and trying to access a protected route, redirect to login
161+
if (!currentUser && !isPublicRoute && to.name !== 'Setup') {
162+
next('/login');
163+
return;
153164
}
154165

155-
// Check if route requires setup
166+
// Check if route requires setup (for protected routes, currentUser should exist here)
156167
if (to.meta.requiresSetup !== false) {
157168
try {
158169
// Check database status (use cache for performance)
@@ -173,8 +184,9 @@ router.beforeEach(async (to, from, next) => {
173184

174185
// Check role requirements (reuse the currentUser from above)
175186
if (to.meta.requiresRole) {
187+
// currentUser should be valid here due to the redirect above if null
176188
if (!currentUser || currentUser.role_id !== to.meta.requiresRole) {
177-
next({ name: 'NotFound' })
189+
next({ name: 'NotFound' }) // Or redirect to an 'Unauthorized' page
178190
return
179191
}
180192
}

services/frontend/src/services/teamService.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ export interface Team {
1111
}
1212

1313
export interface TeamResponse {
14-
success: boolean
15-
data: Team[]
14+
success: boolean;
15+
teams: Team[]; // Changed 'data' to 'teams'
1616
}
1717

1818
interface TeamCacheEntry {
@@ -71,16 +71,16 @@ export class TeamService {
7171

7272
// Make the API call
7373
this.pendingUserTeamsRequest = this.fetchUserTeams();
74-
74+
7575
try {
7676
const result = await this.pendingUserTeamsRequest;
77-
77+
7878
// Cache the result
7979
this.userTeamsCache = {
8080
data: result,
8181
timestamp: Date.now()
8282
};
83-
83+
8484
return result;
8585
} finally {
8686
// Clear pending request
@@ -112,8 +112,8 @@ export class TeamService {
112112

113113
const data: TeamResponse = await response.json()
114114

115-
if (data.success && Array.isArray(data.data)) {
116-
return data.data
115+
if (data.success && Array.isArray(data.teams)) { // Changed 'data.data' to 'data.teams'
116+
return data.teams // Changed 'data.data' to 'data.teams'
117117
} else {
118118
throw new Error('Invalid response format')
119119
}
@@ -129,7 +129,7 @@ export class TeamService {
129129
static async createTeam(teamData: Partial<Team>): Promise<Team> {
130130
try {
131131
const apiUrl = this.getApiUrl();
132-
132+
133133
const response = await fetch(`${apiUrl}/api/teams`, {
134134
method: 'POST',
135135
headers: {
@@ -144,10 +144,10 @@ export class TeamService {
144144
}
145145

146146
const data = await response.json();
147-
147+
148148
// Clear cache on successful team creation
149149
this.clearUserTeamsCache();
150-
150+
151151
return data.data;
152152
} catch (error) {
153153
console.error('Error creating team:', error);
@@ -161,7 +161,7 @@ export class TeamService {
161161
static async updateTeam(teamId: string, teamData: Partial<Team>): Promise<Team> {
162162
try {
163163
const apiUrl = this.getApiUrl();
164-
164+
165165
const response = await fetch(`${apiUrl}/api/teams/${teamId}`, {
166166
method: 'PUT',
167167
headers: {
@@ -176,10 +176,10 @@ export class TeamService {
176176
}
177177

178178
const data = await response.json();
179-
179+
180180
// Clear cache on successful team update
181181
this.clearUserTeamsCache();
182-
182+
183183
return data.data;
184184
} catch (error) {
185185
console.error('Error updating team:', error);
@@ -193,7 +193,7 @@ export class TeamService {
193193
static async deleteTeam(teamId: string): Promise<void> {
194194
try {
195195
const apiUrl = this.getApiUrl();
196-
196+
197197
const response = await fetch(`${apiUrl}/api/teams/${teamId}`, {
198198
method: 'DELETE',
199199
headers: {
@@ -205,7 +205,7 @@ export class TeamService {
205205
if (!response.ok) {
206206
throw new Error(`Failed to delete team: ${response.status}`);
207207
}
208-
208+
209209
// Clear cache on successful team deletion
210210
this.clearUserTeamsCache();
211211
} catch (error) {

services/frontend/src/services/userService.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,16 @@ export class UserService {
7070

7171
// Make the API call
7272
this.pendingRequest = this.fetchCurrentUser();
73-
73+
7474
try {
7575
const result = await this.pendingRequest;
76-
76+
7777
// Cache the result
7878
this.cache = {
7979
data: result,
8080
timestamp: Date.now()
8181
};
82-
82+
8383
return result;
8484
} finally {
8585
// Clear pending request
@@ -102,11 +102,13 @@ export class UserService {
102102
});
103103

104104
if (response.ok) {
105-
const data = await response.json();
106-
if (data.success && data.data) {
107-
return data.data as User;
105+
const userData = await response.json();
106+
// The /api/users/me endpoint returns the user object directly
107+
// Ensure it's not an error structure like { success: false, error: '...' }
108+
if (userData && typeof userData.id === 'string') {
109+
return userData as User;
108110
}
109-
// If success is false or data is missing, treat as not logged in for this check
111+
// If it's not a valid user object (e.g., an error response still got 200 OK somehow, or empty)
110112
return null;
111113
}
112114

0 commit comments

Comments
 (0)