academe-kit 0.6.8 → 0.7.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.cjs CHANGED
@@ -5984,37 +5984,20 @@ exports.GLOBAL_ROLES = void 0;
5984
5984
  GLOBAL_ROLES["GUARDIAN"] = "guardian";
5985
5985
  })(exports.GLOBAL_ROLES || (exports.GLOBAL_ROLES = {}));
5986
5986
 
5987
- function detectMobileTokenSync() {
5988
- if (typeof window === "undefined") {
5989
- return { token: undefined, isMobile: false, decoded: null };
5990
- }
5991
- const keycloakConfig = window.keycloakConfig;
5992
- if (!keycloakConfig?.fromMobile || !keycloakConfig?.token) {
5993
- return { token: undefined, isMobile: false, decoded: null };
5994
- }
5995
- // Validar e decodificar o token mobile
5996
- try {
5997
- const decoded = jwtDecode(keycloakConfig.token);
5998
- if (!decoded) {
5999
- console.error("[SecurityProvider] Token mobile inválido - ignorando");
6000
- return { token: undefined, isMobile: false, decoded: null };
6001
- }
6002
- // Verificar se o token não está expirado
6003
- const now = Math.floor(Date.now() / 1000);
6004
- if (decoded.exp && decoded.exp < now) {
6005
- console.error("[SecurityProvider] Token mobile expirado - ignorando");
6006
- return { token: undefined, isMobile: false, decoded: null };
6007
- }
6008
- console.log("[SecurityProvider] ✅ Token mobile detectado síncronamente");
6009
- return { token: keycloakConfig.token, isMobile: true, decoded };
6010
- }
6011
- catch (error) {
6012
- console.error("[SecurityProvider] Erro ao decodificar token mobile:", error);
6013
- return { token: undefined, isMobile: false, decoded: null };
5987
+ const getCookie = (name) => {
5988
+ if (typeof window === "undefined")
5989
+ return null;
5990
+ const value = `; ${document.cookie}`;
5991
+ const parts = value.split(`; ${name}=`);
5992
+ if (parts.length === 2) {
5993
+ return parts.pop()?.split(";").shift() || null;
6014
5994
  }
6015
- }
6016
- // Detecta o token mobile UMA VEZ no carregamento do módulo
6017
- const initialMobileState = detectMobileTokenSync();
5995
+ return null;
5996
+ };
5997
+ const getAccessTokenFromCookies = () => {
5998
+ const token = getCookie("KC_FORCE_AUTH_TOKEN");
5999
+ return token || undefined;
6000
+ };
6018
6001
  const AcademeAuthProvider = ({ realm, hubUrl, children, clientId, keycloakUrl, apiBaseUrl, skipApiUserFetch, }) => {
6019
6002
  const oidcConfig = {
6020
6003
  authority: `${keycloakUrl}/realms/${realm}`,
@@ -6028,18 +6011,11 @@ const AcademeAuthProvider = ({ realm, hubUrl, children, clientId, keycloakUrl, a
6028
6011
  },
6029
6012
  automaticSilentRenew: true,
6030
6013
  };
6031
- // Se temos token mobile válido, NÃO monta o AuthProvider do OIDC
6032
- // Isso evita que ele tente fazer signinSilent() e cause erro CSP em iframes
6033
- if (initialMobileState.isMobile) {
6034
- console.log("[AcademeAuthProvider] 🖼️ Modo mobile/iframe - usando SecurityProviderMobileOnly");
6035
- return (jsxRuntime.jsx(SecurityProviderMobileOnly, { apiBaseUrl: apiBaseUrl, skipApiUserFetch: skipApiUserFetch, children: children }));
6036
- }
6037
6014
  return (jsxRuntime.jsx(AuthProvider, { ...oidcConfig, children: jsxRuntime.jsx(SecurityProvider, { hubUrl: hubUrl, apiBaseUrl: apiBaseUrl, skipApiUserFetch: skipApiUserFetch, children: children }) }));
6038
6015
  };
6039
6016
  const SecurityContext = React2.createContext({
6040
6017
  isInitialized: false,
6041
6018
  isTokenReady: false,
6042
- isMobileAuth: false,
6043
6019
  user: null,
6044
6020
  refreshUserData: async () => { },
6045
6021
  signOut: () => null,
@@ -6068,35 +6044,53 @@ const SecurityProvider = ({ apiBaseUrl = "https://stg-api.academe.com.br", skipA
6068
6044
  const auth = useAuth();
6069
6045
  const [currentUser, setCurrentUser] = React2.useState(null);
6070
6046
  const [isRefreshing, setIsRefreshing] = React2.useState(false);
6071
- // CRÍTICO: Inicializar estados com valores do token mobile detectado síncronamente
6072
- // Isso garante que no primeiro render já temos os valores corretos
6073
- const hasTriedSignInSilent = React2.useRef(initialMobileState.isMobile);
6074
- const [isTokenReady, setIsTokenReady] = React2.useState(initialMobileState.isMobile);
6075
- // --- Estado para autenticação mobile (inicializado com detecção síncrona) ---
6076
- const [isMobileAuth, setIsMobileAuth] = React2.useState(initialMobileState.isMobile);
6077
- const [mobileToken, setMobileToken] = React2.useState(initialMobileState.token);
6078
- // Ref para armazenar o resolver da Promise de token
6047
+ const hasTriedSignInSilent = React2.useRef(false);
6048
+ const [isTokenReady, setIsTokenReady] = React2.useState(false);
6079
6049
  const tokenReadyResolverRef = React2.useRef(null);
6080
6050
  const tokenReadyPromiseRef = React2.useRef(null);
6081
- // Extrair valores primitivos do auth para usar como dependências estáveis
6082
- const isAuthenticated = auth.isAuthenticated;
6051
+ const [accessToken, setAccessToken] = React2.useState(() => {
6052
+ const cookieToken = getAccessTokenFromCookies();
6053
+ return cookieToken || auth.user?.access_token;
6054
+ });
6055
+ const decodedAccessToken = React2.useMemo(() => {
6056
+ return accessToken ? decodeAccessToken(accessToken) : null;
6057
+ }, [accessToken]);
6058
+ const userProfileSub = auth.user?.profile?.sub || decodedAccessToken?.sub;
6059
+ const isAuthenticated = auth.isAuthenticated || !!accessToken;
6083
6060
  const isLoading = auth.isLoading;
6084
6061
  const activeNavigator = auth.activeNavigator;
6085
- const accessToken = auth.user?.access_token;
6086
6062
  const userProfile = auth.user?.profile;
6087
- const userProfileSub = auth.user?.profile?.sub;
6088
- // CRÍTICO: Inicializar currentTokenRef com o token mobile detectado síncronamente
6089
- // Isso garante que o middleware do apiClient já tenha o token no primeiro request
6090
- const currentTokenRef = React2.useRef(initialMobileState.token);
6091
- // Sincronizar window.accessToken se tivermos token mobile (executa síncronamente)
6092
- if (initialMobileState.token && typeof window !== "undefined" && !window.accessToken) {
6093
- window.accessToken = initialMobileState.token;
6094
- }
6095
- // --- 1. Silent Check Inicial (Check SSO) - Pulado se mobile ---
6063
+ console.log(">> isAuthenticated:", isAuthenticated);
6064
+ console.log(">> accessToken:", accessToken);
6065
+ const currentTokenRef = React2.useRef(undefined);
6066
+ // Efeito para sincronizar o token do auth com o state
6067
+ // e também verificar cookies periodicamente
6068
+ React2.useEffect(() => {
6069
+ const cookieToken = getAccessTokenFromCookies();
6070
+ const authToken = auth.user?.access_token;
6071
+ // Prioridade: Cookie > Auth token
6072
+ const newToken = cookieToken || authToken;
6073
+ if (newToken && newToken !== accessToken) {
6074
+ setAccessToken(newToken);
6075
+ }
6076
+ }, [auth.user?.access_token, accessToken]);
6077
+ // Efeito opcional: verificar cookies em intervalos (útil se o cookie pode mudar externamente)
6078
+ React2.useEffect(() => {
6079
+ const checkCookieToken = () => {
6080
+ const cookieToken = getAccessTokenFromCookies();
6081
+ if (cookieToken && cookieToken !== accessToken) {
6082
+ setAccessToken(cookieToken);
6083
+ }
6084
+ };
6085
+ // Verifica a cada 5 segundos (ajuste conforme necessário)
6086
+ const interval = setInterval(checkCookieToken, 5000);
6087
+ return () => clearInterval(interval);
6088
+ }, [accessToken]);
6089
+ // --- 1. Silent Check Inicial (Check SSO) ---
6096
6090
  React2.useEffect(() => {
6097
- // Pular SSO check se estamos em modo mobile
6098
- if (isMobileAuth) {
6099
- console.debug("[SecurityProvider] Modo mobile - pulando SSO check");
6091
+ // Se temos um token do cookie, não precisamos fazer silent check
6092
+ if (accessToken) {
6093
+ hasTriedSignInSilent.current = true;
6100
6094
  return;
6101
6095
  }
6102
6096
  if (!isAuthenticated &&
@@ -6109,31 +6103,19 @@ const SecurityProvider = ({ apiBaseUrl = "https://stg-api.academe.com.br", skipA
6109
6103
  });
6110
6104
  }
6111
6105
  // eslint-disable-next-line react-hooks/exhaustive-deps
6112
- }, [isAuthenticated, isLoading, activeNavigator, isMobileAuth]);
6106
+ }, [isAuthenticated, isLoading, activeNavigator, accessToken]);
6113
6107
  // --- 2. Configuração de API e Services ---
6114
6108
  const apiClient = React2.useMemo(() => {
6115
6109
  const client = createAcademeApiClient(apiBaseUrl);
6116
- // CRÍTICO: Se já temos token mobile, criar Promise resolvida
6117
- // Isso evita que o middleware aguarde uma Promise que nunca será resolvida
6118
- if (initialMobileState.token) {
6119
- tokenReadyPromiseRef.current = Promise.resolve();
6120
- tokenReadyResolverRef.current = () => { };
6121
- }
6122
- else {
6123
- // Inicializa a Promise de token ready para modo OIDC
6124
- tokenReadyPromiseRef.current = new Promise((resolve) => {
6125
- tokenReadyResolverRef.current = resolve;
6126
- });
6127
- }
6128
- // Middleware que aguarda o token estar disponível antes de fazer requests
6110
+ tokenReadyPromiseRef.current = new Promise((resolve) => {
6111
+ tokenReadyResolverRef.current = resolve;
6112
+ });
6129
6113
  client.use({
6130
6114
  async onRequest({ request }) {
6131
- // Se já tem token, usa imediatamente
6132
6115
  if (currentTokenRef.current) {
6133
6116
  request.headers.set("Authorization", `Bearer ${currentTokenRef.current}`);
6134
6117
  return request;
6135
6118
  }
6136
- // Se ainda está carregando a auth, aguarda o token ficar pronto
6137
6119
  if (tokenReadyPromiseRef.current) {
6138
6120
  await tokenReadyPromiseRef.current;
6139
6121
  if (currentTokenRef.current) {
@@ -6148,56 +6130,33 @@ const SecurityProvider = ({ apiBaseUrl = "https://stg-api.academe.com.br", skipA
6148
6130
  const services = React2.useMemo(() => {
6149
6131
  return createAcademeServices(apiClient);
6150
6132
  }, [apiClient]);
6151
- // Token efetivo: prioriza mobile, depois OIDC
6152
- const effectiveToken = mobileToken || accessToken;
6153
- const decodedAccessToken = React2.useMemo(() => {
6154
- return effectiveToken ? decodeAccessToken(effectiveToken) : null;
6155
- }, [effectiveToken]);
6156
- // Atualização do Token e resolução da Promise
6157
- // Não sobrescreve se estamos em modo mobile
6158
6133
  React2.useEffect(() => {
6159
- // Se estamos em modo mobile, o token já foi configurado
6160
- if (isMobileAuth) {
6161
- return;
6162
- }
6163
6134
  currentTokenRef.current = accessToken;
6164
6135
  if (typeof window !== "undefined") {
6165
6136
  window.accessToken = accessToken;
6166
6137
  }
6167
6138
  if (accessToken) {
6168
- // Resolve a promise indicando que o token está pronto
6169
6139
  if (tokenReadyResolverRef.current) {
6170
6140
  tokenReadyResolverRef.current();
6171
6141
  setIsTokenReady(true);
6172
6142
  }
6173
6143
  }
6174
6144
  else if (!isLoading && !isAuthenticated) {
6175
- // Usuário não autenticado - resolve a promise para não bloquear requests públicas
6176
6145
  if (tokenReadyResolverRef.current) {
6177
6146
  tokenReadyResolverRef.current();
6178
6147
  setIsTokenReady(true);
6179
6148
  }
6180
6149
  }
6181
- }, [accessToken, isLoading, isAuthenticated, isMobileAuth]);
6182
- // --- 3. Helpers de Usuário e Roles ---
6150
+ }, [accessToken, isLoading, isAuthenticated]);
6183
6151
  const getKeycloakUser = React2.useCallback(() => {
6184
- // Se estamos em modo mobile, extrair do token decodificado
6185
- if (isMobileAuth && decodedAccessToken) {
6186
- return {
6187
- email: decodedAccessToken.email || "",
6188
- name: decodedAccessToken.given_name || "",
6189
- lastName: decodedAccessToken.family_name || "",
6190
- };
6191
- }
6192
- // Modo OIDC normal
6193
6152
  const profile = userProfile;
6194
6153
  return {
6195
- email: profile?.email || "",
6196
- name: profile?.given_name || "",
6197
- lastName: profile?.family_name || "",
6198
- avatar_url: decodedAccessToken?.avatar_url
6154
+ email: profile?.email || decodedAccessToken?.email || "",
6155
+ name: profile?.given_name || decodedAccessToken?.given_name || "",
6156
+ lastName: profile?.family_name || decodedAccessToken?.family_name || "",
6157
+ avatar_url: decodedAccessToken?.avatar_url,
6199
6158
  };
6200
- }, [userProfile, isMobileAuth, decodedAccessToken]);
6159
+ }, [userProfile, decodedAccessToken]);
6201
6160
  const hasRealmRole = React2.useCallback((role) => {
6202
6161
  return decodedAccessToken?.realm_access?.roles?.includes(role) ?? false;
6203
6162
  }, [decodedAccessToken]);
@@ -6212,20 +6171,17 @@ const SecurityProvider = ({ apiBaseUrl = "https://stg-api.academe.com.br", skipA
6212
6171
  }
6213
6172
  return Object.values(decodedAccessToken.resource_access).some((resource) => resource.roles?.includes(role));
6214
6173
  }, [decodedAccessToken]);
6215
- // Autenticação efetiva: mobile ou OIDC
6216
- const effectiveIsAuthenticated = isMobileAuth || isAuthenticated;
6217
- const effectiveUserSub = isMobileAuth ? decodedAccessToken?.sub : userProfileSub;
6218
6174
  // --- 4. Fetch de Dados do Usuário (Backend) ---
6219
6175
  React2.useEffect(() => {
6220
6176
  let isMounted = true;
6221
6177
  const fetchUserData = async () => {
6222
- if (effectiveIsAuthenticated) {
6178
+ if (isAuthenticated) {
6223
6179
  if (skipApiUserFetch) {
6224
6180
  if (isMounted) {
6225
6181
  const academeUser = {
6226
6182
  keycloakUser: getKeycloakUser(),
6227
6183
  };
6228
- setCurrentUser({ ...academeUser, id: effectiveUserSub || "" });
6184
+ setCurrentUser({ ...academeUser, id: userProfileSub || "" });
6229
6185
  }
6230
6186
  return;
6231
6187
  }
@@ -6243,7 +6199,7 @@ const SecurityProvider = ({ apiBaseUrl = "https://stg-api.academe.com.br", skipA
6243
6199
  console.error("[SecurityProvider] Error fetching user data:", error);
6244
6200
  }
6245
6201
  }
6246
- else if (!effectiveIsAuthenticated && !isLoading && !isMobileAuth) {
6202
+ else if (!isAuthenticated && !isLoading) {
6247
6203
  if (isMounted) {
6248
6204
  setCurrentUser(null);
6249
6205
  }
@@ -6254,17 +6210,16 @@ const SecurityProvider = ({ apiBaseUrl = "https://stg-api.academe.com.br", skipA
6254
6210
  isMounted = false;
6255
6211
  };
6256
6212
  }, [
6257
- effectiveIsAuthenticated,
6213
+ isAuthenticated,
6258
6214
  isLoading,
6259
6215
  getKeycloakUser,
6260
6216
  services,
6261
6217
  skipApiUserFetch,
6262
- effectiveUserSub,
6263
- isMobileAuth,
6218
+ userProfileSub,
6264
6219
  ]);
6265
6220
  const refreshUserData = React2.useCallback(async () => {
6266
6221
  setIsRefreshing(true);
6267
- if (effectiveIsAuthenticated) {
6222
+ if (isAuthenticated) {
6268
6223
  if (skipApiUserFetch) {
6269
6224
  await auth.signinSilent();
6270
6225
  const academeUser = {
@@ -6288,11 +6243,10 @@ const SecurityProvider = ({ apiBaseUrl = "https://stg-api.academe.com.br", skipA
6288
6243
  }
6289
6244
  }
6290
6245
  setIsRefreshing(false);
6291
- }, [effectiveIsAuthenticated, getKeycloakUser, services, skipApiUserFetch]);
6246
+ }, [getKeycloakUser, services, skipApiUserFetch]);
6292
6247
  // --- 5. Ações de Auth ---
6293
- // SignOut para modo OIDC (web normal)
6294
- const signOutOidc = React2.useCallback(() => {
6295
- console.log("[KC LOGOUT - OIDC]");
6248
+ const signOut = React2.useCallback(() => {
6249
+ console.log("[KC LOGOUT!]");
6296
6250
  setCurrentUser(null);
6297
6251
  auth.removeUser();
6298
6252
  auth.signoutRedirect({
@@ -6300,32 +6254,6 @@ const SecurityProvider = ({ apiBaseUrl = "https://stg-api.academe.com.br", skipA
6300
6254
  });
6301
6255
  auth.clearStaleState();
6302
6256
  }, [auth]);
6303
- // SignOut para modo mobile
6304
- const signOutMobile = React2.useCallback(() => {
6305
- console.log("[KC LOGOUT - Mobile]");
6306
- setCurrentUser(null);
6307
- setMobileToken(undefined);
6308
- setIsMobileAuth(false);
6309
- // Limpar tokens globais
6310
- if (typeof window !== "undefined") {
6311
- window.accessToken = undefined;
6312
- window.keycloakConfig = undefined;
6313
- }
6314
- currentTokenRef.current = undefined;
6315
- // Notificar o app mobile para fazer logout
6316
- if (window.ReactNativeWebView) {
6317
- window.ReactNativeWebView.postMessage(JSON.stringify({ type: "LOGOUT_REQUESTED" }));
6318
- }
6319
- }, []);
6320
- // SignOut unificado: escolhe automaticamente baseado no modo
6321
- const signOut = React2.useCallback(() => {
6322
- if (isMobileAuth) {
6323
- signOutMobile();
6324
- }
6325
- else {
6326
- signOutOidc();
6327
- }
6328
- }, [isMobileAuth, signOutMobile, signOutOidc]);
6329
6257
  const hasSchool = React2.useCallback((schoolId) => {
6330
6258
  if (hasRealmRole(exports.GLOBAL_ROLES.ADMIN_ACADEME)) {
6331
6259
  return true;
@@ -6333,217 +6261,36 @@ const SecurityProvider = ({ apiBaseUrl = "https://stg-api.academe.com.br", skipA
6333
6261
  return (currentUser?.institutionRegistrations?.some((registration) => registration.institutionId === schoolId) ?? false);
6334
6262
  }, [hasRealmRole, currentUser?.institutionRegistrations]);
6335
6263
  const goToLogin = React2.useCallback(() => {
6336
- // Em modo mobile, notificar o app para fazer login
6337
- if (isMobileAuth && window.ReactNativeWebView) {
6338
- window.ReactNativeWebView.postMessage(JSON.stringify({ type: "LOGIN_REQUESTED" }));
6339
- return Promise.resolve();
6340
- }
6341
6264
  return auth.signinRedirect();
6342
6265
  // eslint-disable-next-line react-hooks/exhaustive-deps
6343
- }, [isMobileAuth]);
6266
+ }, []);
6344
6267
  // Memoizar o value do context para evitar re-renders desnecessários
6345
6268
  const contextValue = React2.useMemo(() => ({
6346
- isInitialized: isMobileAuth ? true : (!isLoading || isRefreshing),
6269
+ isInitialized: !isLoading || isRefreshing,
6347
6270
  isTokenReady,
6348
- isMobileAuth,
6349
6271
  user: currentUser,
6350
6272
  refreshUserData,
6351
6273
  signOut,
6352
- isAuthenticated: () => effectiveIsAuthenticated,
6274
+ isAuthenticated: () => isAuthenticated,
6353
6275
  hasSchool,
6354
6276
  goToLogin,
6355
6277
  hasRealmRole,
6356
6278
  hasClientRole,
6357
- accessToken: effectiveToken,
6279
+ accessToken,
6358
6280
  apiClient,
6359
6281
  services,
6360
6282
  }), [
6361
- isMobileAuth,
6362
6283
  isLoading,
6363
6284
  isTokenReady,
6364
6285
  currentUser,
6365
6286
  refreshUserData,
6366
6287
  signOut,
6367
- effectiveIsAuthenticated,
6368
- hasSchool,
6369
- goToLogin,
6370
- hasRealmRole,
6371
- hasClientRole,
6372
- effectiveToken,
6373
- apiClient,
6374
- services,
6375
- ]);
6376
- return (jsxRuntime.jsx(SecurityContext.Provider, { value: contextValue, children: children }));
6377
- };
6378
- /**
6379
- * SecurityProvider para modo mobile/iframe (sem OIDC)
6380
- * Usado quando já temos um token injetado pelo parent/mobile
6381
- * Evita montar o AuthProvider que tentaria fazer signinSilent
6382
- */
6383
- const SecurityProviderMobileOnly = ({ apiBaseUrl = "https://stg-api.academe.com.br", skipApiUserFetch = false, children, }) => {
6384
- const [currentUser, setCurrentUser] = React2.useState(null);
6385
- const mobileToken = initialMobileState.token;
6386
- const decodedToken = initialMobileState.decoded;
6387
- // Ref para armazenar o token atual
6388
- const currentTokenRef = React2.useRef(mobileToken);
6389
- // Configurar token global na inicialização
6390
- React2.useEffect(() => {
6391
- if (mobileToken) {
6392
- window.accessToken = mobileToken;
6393
- currentTokenRef.current = mobileToken;
6394
- }
6395
- }, [mobileToken]);
6396
- // API Client com token já configurado
6397
- const apiClient = React2.useMemo(() => {
6398
- const client = createAcademeApiClient(apiBaseUrl);
6399
- client.use({
6400
- async onRequest({ request }) {
6401
- if (currentTokenRef.current) {
6402
- request.headers.set("Authorization", `Bearer ${currentTokenRef.current}`);
6403
- }
6404
- return request;
6405
- },
6406
- });
6407
- return client;
6408
- }, [apiBaseUrl]);
6409
- const services = React2.useMemo(() => {
6410
- return createAcademeServices(apiClient);
6411
- }, [apiClient]);
6412
- const getKeycloakUser = React2.useCallback(() => {
6413
- if (decodedToken) {
6414
- return {
6415
- email: decodedToken.email || "",
6416
- name: decodedToken.given_name || "",
6417
- lastName: decodedToken.family_name || "",
6418
- avatar_url: decodedToken.avatar_url,
6419
- };
6420
- }
6421
- return { email: "", name: "", lastName: "" };
6422
- }, [decodedToken]);
6423
- const hasRealmRole = React2.useCallback((role) => {
6424
- return decodedToken?.realm_access?.roles?.includes(role) ?? false;
6425
- }, [decodedToken]);
6426
- const hasClientRole = React2.useCallback((role, clientId) => {
6427
- if (!decodedToken?.resource_access)
6428
- return false;
6429
- if (clientId) {
6430
- return (decodedToken.resource_access[clientId]?.roles?.includes(role) ?? false);
6431
- }
6432
- return Object.values(decodedToken.resource_access).some((resource) => resource.roles?.includes(role));
6433
- }, [decodedToken]);
6434
- // Fetch de dados do usuário
6435
- React2.useEffect(() => {
6436
- let isMounted = true;
6437
- const fetchUserData = async () => {
6438
- if (!mobileToken)
6439
- return;
6440
- if (skipApiUserFetch) {
6441
- if (isMounted) {
6442
- const academeUser = {
6443
- keycloakUser: getKeycloakUser(),
6444
- };
6445
- setCurrentUser({ ...academeUser, id: decodedToken?.sub || "" });
6446
- }
6447
- return;
6448
- }
6449
- try {
6450
- const response = await services.user.getMe();
6451
- if (isMounted && response?.data?.data) {
6452
- const academeUser = {
6453
- ...response.data.data,
6454
- keycloakUser: getKeycloakUser(),
6455
- };
6456
- setCurrentUser(academeUser);
6457
- }
6458
- }
6459
- catch (error) {
6460
- console.error("[SecurityProviderMobileOnly] Error fetching user data:", error);
6461
- }
6462
- };
6463
- fetchUserData();
6464
- return () => {
6465
- isMounted = false;
6466
- };
6467
- }, [mobileToken, getKeycloakUser, services, skipApiUserFetch, decodedToken?.sub]);
6468
- const refreshUserData = React2.useCallback(async () => {
6469
- if (!mobileToken)
6470
- return;
6471
- if (skipApiUserFetch) {
6472
- const academeUser = {
6473
- keycloakUser: getKeycloakUser(),
6474
- };
6475
- setCurrentUser(academeUser);
6476
- return;
6477
- }
6478
- try {
6479
- const response = await services.user.getMe();
6480
- if (response?.data?.data) {
6481
- const academeUser = {
6482
- ...response.data.data,
6483
- keycloakUser: getKeycloakUser(),
6484
- };
6485
- setCurrentUser(academeUser);
6486
- }
6487
- }
6488
- catch (error) {
6489
- console.error("[SecurityProviderMobileOnly] Error refreshing user data:", error);
6490
- }
6491
- }, [mobileToken, getKeycloakUser, services, skipApiUserFetch]);
6492
- const signOut = React2.useCallback(() => {
6493
- console.log("[SecurityProviderMobileOnly] Logout");
6494
- setCurrentUser(null);
6495
- if (typeof window !== "undefined") {
6496
- window.accessToken = undefined;
6497
- window.keycloakConfig = undefined;
6498
- }
6499
- currentTokenRef.current = undefined;
6500
- // Notificar o parent/app mobile para fazer logout
6501
- if (window.ReactNativeWebView) {
6502
- window.ReactNativeWebView.postMessage(JSON.stringify({ type: "LOGOUT_REQUESTED" }));
6503
- }
6504
- if (window.parent && window.parent !== window) {
6505
- window.parent.postMessage({ type: "LOGOUT_REQUESTED" }, "*");
6506
- }
6507
- }, []);
6508
- const hasSchool = React2.useCallback((schoolId) => {
6509
- if (hasRealmRole(exports.GLOBAL_ROLES.ADMIN_ACADEME)) {
6510
- return true;
6511
- }
6512
- return (currentUser?.institutionRegistrations?.some((registration) => registration.institutionId === schoolId) ?? false);
6513
- }, [hasRealmRole, currentUser?.institutionRegistrations]);
6514
- const goToLogin = React2.useCallback(() => {
6515
- if (window.ReactNativeWebView) {
6516
- window.ReactNativeWebView.postMessage(JSON.stringify({ type: "LOGIN_REQUESTED" }));
6517
- }
6518
- if (window.parent && window.parent !== window) {
6519
- window.parent.postMessage({ type: "LOGIN_REQUESTED" }, "*");
6520
- }
6521
- return Promise.resolve();
6522
- }, []);
6523
- const contextValue = React2.useMemo(() => ({
6524
- isInitialized: true,
6525
- isTokenReady: true,
6526
- isMobileAuth: true,
6527
- user: currentUser,
6528
- refreshUserData,
6529
- signOut,
6530
- isAuthenticated: () => !!mobileToken,
6531
- hasSchool,
6532
- goToLogin,
6533
- hasRealmRole,
6534
- hasClientRole,
6535
- accessToken: mobileToken,
6536
- apiClient,
6537
- services,
6538
- }), [
6539
- currentUser,
6540
- refreshUserData,
6541
- signOut,
6542
- mobileToken,
6288
+ isAuthenticated,
6543
6289
  hasSchool,
6544
6290
  goToLogin,
6545
6291
  hasRealmRole,
6546
6292
  hasClientRole,
6293
+ accessToken,
6547
6294
  apiClient,
6548
6295
  services,
6549
6296
  ]);