@riligar/auth-react 1.22.0 → 1.24.0

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.js CHANGED
@@ -8,7 +8,6 @@ var reactRouterDom = require('react-router-dom');
8
8
  var core = require('@mantine/core');
9
9
  var form = require('@mantine/form');
10
10
  var iconsReact = require('@tabler/icons-react');
11
- var notifications = require('@mantine/notifications');
12
11
 
13
12
  // Config - API Base URL fixa para o serviço de autenticação
14
13
  let API_BASE = 'https://manager.myauth.click';
@@ -752,32 +751,39 @@ const useAuthStore = zustand.create((set, get) => ({
752
751
  if (isAuthenticated()) {
753
752
  const token = window.localStorage.getItem('auth:token');
754
753
  if (token) {
755
- // Decodifica o token para verificar tempo de expiração
756
- const base64Url = token.split('.')[1];
757
- const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
758
- const jsonPayload = window.atob(base64);
759
- const payload = JSON.parse(jsonPayload);
754
+ // Usa o decoder oficial do SDK que é mais seguro
755
+ const payload = decodeJWT(token);
756
+
757
+ // Se não for um JWT ou não tiver expiração, não fazemos refresh em background
758
+ // O backend cuidará da expiração da sessão opaca via 401 nas requisições normais
759
+ if (!payload || !payload.exp) return;
760
760
  const now = Date.now() / 1000;
761
761
  const timeUntilExpiry = payload.exp - now;
762
762
 
763
- // Se o token expira em menos de 5 minutos, faz refresh
763
+ // Se o token expira em menos de 5 minutos, tenta o refresh
764
764
  if (timeUntilExpiry < 300) {
765
- // 5 minutos
766
- await refreshToken();
767
- const user = getCurrentUser();
768
- set({
769
- user
770
- });
765
+ try {
766
+ await refreshToken();
767
+ const user = getCurrentUser();
768
+ set({
769
+ user
770
+ });
771
+ } catch (refreshErr) {
772
+ console.warn('[AuthStore] Falha ao renovar token:', refreshErr);
773
+ // Só desloga se for um erro de autenticação explícito (401)
774
+ if (refreshErr.res?.status === 401) {
775
+ set({
776
+ user: null
777
+ });
778
+ window.localStorage.removeItem('auth:token');
779
+ }
780
+ }
771
781
  }
772
782
  }
773
783
  }
774
784
  } catch (error) {
775
- console.error('Erro no refresh automático:', error);
776
- // Em caso de erro, faz logout
777
- set({
778
- user: null
779
- });
780
- window.localStorage.removeItem('auth:token');
785
+ // Erros de processamento interno não devem deslogar o usuário
786
+ console.error('[AuthStore] Erro no ciclo de refresh automático:', error);
781
787
  }
782
788
  }, 4 * 60 * 1000); // Verifica a cada 4 minutos
783
789
 
@@ -2068,6 +2074,8 @@ function UserProfile({
2068
2074
  onProfileUpdate,
2069
2075
  onPasswordChange,
2070
2076
  onEmailChange,
2077
+ onSessionRevoked,
2078
+ onOtherSessionsRevoked,
2071
2079
  onError,
2072
2080
  // Features toggle
2073
2081
  showAvatar = true,
@@ -2154,7 +2162,9 @@ function UserProfile({
2154
2162
  if (isCurrentSession) {
2155
2163
  try {
2156
2164
  await revokeSession(sessionId);
2165
+ onSessionRevoked?.(sessionId);
2157
2166
  } catch (error) {
2167
+ onError?.(error);
2158
2168
  // Even if it fails, we're revoking our own session, so just logout
2159
2169
  // The server already revoked our session
2160
2170
  }
@@ -2168,11 +2178,7 @@ function UserProfile({
2168
2178
  // Revoking another session
2169
2179
  try {
2170
2180
  await revokeSession(sessionId);
2171
- notifications.notifications.show({
2172
- title: labels.successTitle || 'Sucesso',
2173
- message: labels.sessionRevoked || 'Sessão encerrada com sucesso',
2174
- color: 'green'
2175
- });
2181
+ onSessionRevoked?.(sessionId);
2176
2182
  } catch (error) {
2177
2183
  // Check for 401 error (our SDK uses error.res, axios uses error.response)
2178
2184
  const status = error.res?.status || error.response?.status;
@@ -2183,28 +2189,14 @@ function UserProfile({
2183
2189
  if (variant === 'modal') onClose?.();
2184
2190
  return;
2185
2191
  }
2186
- notifications.notifications.show({
2187
- title: labels.errorTitle || 'Erro',
2188
- message: error.message || labels.sessionRevokeFailed || 'Falha ao encerrar sessão',
2189
- color: 'red'
2190
- });
2191
2192
  onError?.(error);
2192
2193
  }
2193
2194
  };
2194
2195
  const handleRevokeOtherSessions = async () => {
2195
2196
  try {
2196
2197
  await revokeOtherSessions();
2197
- notifications.notifications.show({
2198
- title: labels.successTitle || 'Sucesso',
2199
- message: labels.otherSessionsRevoked || 'Todas as outras sessões foram encerradas',
2200
- color: 'green'
2201
- });
2198
+ onOtherSessionsRevoked?.();
2202
2199
  } catch (error) {
2203
- notifications.notifications.show({
2204
- title: labels.errorTitle || 'Erro',
2205
- message: error.message || labels.otherSessionsRevokeFailed || 'Falha ao encerrar sessões',
2206
- color: 'red'
2207
- });
2208
2200
  onError?.(error);
2209
2201
  }
2210
2202
  };
@@ -2265,21 +2257,13 @@ function UserProfile({
2265
2257
 
2266
2258
  // Validate file type
2267
2259
  if (!file.type.startsWith('image/')) {
2268
- notifications.notifications.show({
2269
- title: labels.errorTitle || 'Erro',
2270
- message: labels.avatarInvalidType || 'Por favor, selecione uma imagem válida',
2271
- color: 'red'
2272
- });
2260
+ onError?.(new Error(labels.avatarInvalidType || 'Por favor, selecione uma imagem válida'));
2273
2261
  return;
2274
2262
  }
2275
2263
 
2276
2264
  // Validate file size
2277
2265
  if (file.size > maxAvatarSize) {
2278
- notifications.notifications.show({
2279
- title: labels.errorTitle || 'Erro',
2280
- message: labels.avatarTooLarge || `Imagem muito grande. Máximo ${Math.round(maxAvatarSize / 1024)}KB.`,
2281
- color: 'red'
2282
- });
2266
+ onError?.(new Error(labels.avatarTooLarge || `Imagem muito grande. Máximo ${Math.round(maxAvatarSize / 1024)}KB.`));
2283
2267
  return;
2284
2268
  }
2285
2269
  setAvatarFile(file);
@@ -2318,40 +2302,20 @@ function UserProfile({
2318
2302
  const handleChangePassword = async values => {
2319
2303
  try {
2320
2304
  await changePassword(values.currentPassword, values.newPassword);
2321
- notifications.notifications.show({
2322
- title: labels.successTitle || 'Sucesso',
2323
- message: labels.passwordChanged || 'Senha alterada com sucesso',
2324
- color: 'green'
2325
- });
2326
2305
  passwordForm.reset();
2327
2306
  setEditingSection(null);
2328
2307
  onPasswordChange?.();
2329
2308
  } catch (error) {
2330
- notifications.notifications.show({
2331
- title: labels.errorTitle || 'Erro',
2332
- message: error.message || labels.passwordChangeFailed || 'Falha ao alterar senha',
2333
- color: 'red'
2334
- });
2335
2309
  onError?.(error);
2336
2310
  }
2337
2311
  };
2338
2312
  const handleChangeEmail = async values => {
2339
2313
  try {
2340
2314
  await changeEmail(values.newEmail);
2341
- notifications.notifications.show({
2342
- title: labels.successTitle || 'Sucesso',
2343
- message: labels.emailVerificationSent || 'Verifique seu novo email para confirmar a alteração',
2344
- color: 'green'
2345
- });
2346
2315
  emailForm.reset();
2347
2316
  setEditingSection(null);
2348
2317
  onEmailChange?.(values.newEmail);
2349
2318
  } catch (error) {
2350
- notifications.notifications.show({
2351
- title: labels.errorTitle || 'Erro',
2352
- message: error.message || labels.emailChangeFailed || 'Falha ao alterar email',
2353
- color: 'red'
2354
- });
2355
2319
  onError?.(error);
2356
2320
  }
2357
2321
  };
@@ -2360,43 +2324,29 @@ function UserProfile({
2360
2324
  await updateProfile({
2361
2325
  name: values.name
2362
2326
  });
2363
- notifications.notifications.show({
2364
- title: labels.successTitle || 'Sucesso',
2365
- message: labels.nameUpdated || 'Nome atualizado com sucesso',
2366
- color: 'green'
2367
- });
2368
2327
  nameForm.reset();
2369
2328
  setEditingSection(null);
2370
2329
  onProfileUpdate?.({
2371
2330
  name: values.name
2372
2331
  });
2373
2332
  } catch (error) {
2374
- notifications.notifications.show({
2375
- title: labels.errorTitle || 'Erro',
2376
- message: error.message || labels.nameUpdateFailed || 'Falha ao atualizar nome',
2377
- color: 'red'
2378
- });
2379
2333
  onError?.(error);
2380
2334
  }
2381
2335
  };
2382
2336
  const handleChangeAvatar = async () => {
2383
2337
  if (!avatarPreview) {
2384
- notifications.notifications.show({
2385
- title: labels.errorTitle || 'Erro',
2386
- message: labels.avatarRequired || 'Selecione uma imagem',
2387
- color: 'red'
2388
- });
2338
+ // Optionally handle this validation error via callback or just return?
2339
+ // Since it's a validation error before async call, we might want to expose it too?
2340
+ // The original code used notifications. Let's send to onError for consistency or just return if it's UI state.
2341
+ // Actually, for validation within the component, maybe we can just let it be silent or use form error if applicable?
2342
+ // But this is outside form context. Let's use onError with a custom error object.
2343
+ onError?.(new Error(labels.avatarRequired || 'Selecione uma imagem'));
2389
2344
  return;
2390
2345
  }
2391
2346
  try {
2392
2347
  await updateProfile({
2393
2348
  image: avatarPreview
2394
2349
  });
2395
- notifications.notifications.show({
2396
- title: labels.successTitle || 'Sucesso',
2397
- message: labels.avatarUpdated || 'Foto de perfil atualizada com sucesso',
2398
- color: 'green'
2399
- });
2400
2350
  setAvatarPreview(null);
2401
2351
  setAvatarFile(null);
2402
2352
  setEditingSection(null);
@@ -2404,11 +2354,6 @@ function UserProfile({
2404
2354
  image: avatarPreview
2405
2355
  });
2406
2356
  } catch (error) {
2407
- notifications.notifications.show({
2408
- title: labels.errorTitle || 'Erro',
2409
- message: error.message || labels.avatarUpdateFailed || 'Falha ao atualizar foto',
2410
- color: 'red'
2411
- });
2412
2357
  onError?.(error);
2413
2358
  }
2414
2359
  };
@@ -2417,11 +2362,6 @@ function UserProfile({
2417
2362
  await updateProfile({
2418
2363
  image: ''
2419
2364
  });
2420
- notifications.notifications.show({
2421
- title: labels.successTitle || 'Sucesso',
2422
- message: labels.avatarRemoved || 'Foto de perfil removida',
2423
- color: 'green'
2424
- });
2425
2365
  setAvatarPreview(null);
2426
2366
  setAvatarFile(null);
2427
2367
  setEditingSection(null);
@@ -2429,11 +2369,6 @@ function UserProfile({
2429
2369
  image: ''
2430
2370
  });
2431
2371
  } catch (error) {
2432
- notifications.notifications.show({
2433
- title: labels.errorTitle || 'Erro',
2434
- message: error.message || labels.avatarRemoveFailed || 'Falha ao remover foto',
2435
- color: 'red'
2436
- });
2437
2372
  onError?.(error);
2438
2373
  }
2439
2374
  };