@greatapps/common 1.1.271 → 1.1.274

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.
@@ -11,8 +11,7 @@ function AppNavBar({
11
11
  showExpandButton = false,
12
12
  onExpandClick,
13
13
  menuItems = [],
14
- onNotificationsViewAll,
15
- logoutRedirect
14
+ onNotificationsViewAll
16
15
  }) {
17
16
  const router = useRouter();
18
17
  const handleLogoClick = onLogoClick ?? (() => router.push("/"));
@@ -27,13 +26,7 @@ function AppNavBar({
27
26
  onExpandClick,
28
27
  children: [
29
28
  /* @__PURE__ */ jsx(NotificationsPopover, { onViewAll: onNotificationsViewAll }),
30
- /* @__PURE__ */ jsx(
31
- ProfilePopover,
32
- {
33
- menuItems,
34
- logoutRedirect
35
- }
36
- )
29
+ /* @__PURE__ */ jsx(ProfilePopover, { menuItems })
37
30
  ]
38
31
  }
39
32
  );
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/layouts/AppNavBar.tsx"],"sourcesContent":["\"use client\";\n\nimport { useRouter } from \"next/navigation\";\nimport { NavBar } from \"./NavBar\";\nimport { ProfilePopover } from \"./ProfilePopover\";\nimport { NotificationsPopover } from \"./NotificationsPopover\";\nimport type { ProfileMenuItem } from \"./ProfilePopover\";\n\nexport interface AppNavBarProps {\n onLogoClick?: () => void;\n /** Which app is currently active — controls which icon gets the indicator */\n activeApp?: \"gapps\" | \"gpages\";\n appIconHref?: string;\n showExpandButton?: boolean;\n onExpandClick?: () => void;\n menuItems?: ProfileMenuItem[];\n onNotificationsViewAll?: () => void;\n logoutRedirect?: string;\n}\n\nexport function AppNavBar({\n onLogoClick,\n activeApp,\n appIconHref = \"/\",\n showExpandButton = false,\n onExpandClick,\n menuItems = [],\n onNotificationsViewAll,\n logoutRedirect,\n}: AppNavBarProps) {\n const router = useRouter();\n\n const handleLogoClick = onLogoClick ?? (() => router.push(\"/\"));\n const handleAppIconClick = () => router.push(appIconHref);\n\n return (\n <NavBar\n onLogoClick={handleLogoClick}\n onAppIconClick={handleAppIconClick}\n activeApp={activeApp}\n showExpandButton={showExpandButton}\n onExpandClick={onExpandClick}\n >\n <NotificationsPopover onViewAll={onNotificationsViewAll} />\n <ProfilePopover\n menuItems={menuItems}\n logoutRedirect={logoutRedirect}\n />\n </NavBar>\n );\n}\n"],"mappings":";AAoCI,SAOE,KAPF;AAlCJ,SAAS,iBAAiB;AAC1B,SAAS,cAAc;AACvB,SAAS,sBAAsB;AAC/B,SAAS,4BAA4B;AAe9B,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB;AAAA,EACA,YAAY,CAAC;AAAA,EACb;AAAA,EACA;AACF,GAAmB;AACjB,QAAM,SAAS,UAAU;AAEzB,QAAM,kBAAkB,gBAAgB,MAAM,OAAO,KAAK,GAAG;AAC7D,QAAM,qBAAqB,MAAM,OAAO,KAAK,WAAW;AAExD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MAEA;AAAA,4BAAC,wBAAqB,WAAW,wBAAwB;AAAA,QACzD;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/layouts/AppNavBar.tsx"],"sourcesContent":["\"use client\";\n\nimport { useRouter } from \"next/navigation\";\nimport { NavBar } from \"./NavBar\";\nimport { ProfilePopover } from \"./ProfilePopover\";\nimport { NotificationsPopover } from \"./NotificationsPopover\";\nimport type { ProfileMenuItem } from \"./ProfilePopover\";\n\nexport interface AppNavBarProps {\n onLogoClick?: () => void;\n /** Which app is currently active — controls which icon gets the indicator */\n activeApp?: \"gapps\" | \"gpages\";\n appIconHref?: string;\n showExpandButton?: boolean;\n onExpandClick?: () => void;\n menuItems?: ProfileMenuItem[];\n onNotificationsViewAll?: () => void;\n}\n\nexport function AppNavBar({\n onLogoClick,\n activeApp,\n appIconHref = \"/\",\n showExpandButton = false,\n onExpandClick,\n menuItems = [],\n onNotificationsViewAll,\n}: AppNavBarProps) {\n const router = useRouter();\n\n const handleLogoClick = onLogoClick ?? (() => router.push(\"/\"));\n const handleAppIconClick = () => router.push(appIconHref);\n\n return (\n <NavBar\n onLogoClick={handleLogoClick}\n onAppIconClick={handleAppIconClick}\n activeApp={activeApp}\n showExpandButton={showExpandButton}\n onExpandClick={onExpandClick}\n >\n <NotificationsPopover onViewAll={onNotificationsViewAll} />\n <ProfilePopover menuItems={menuItems} />\n </NavBar>\n );\n}\n"],"mappings":";AAkCI,SAOE,KAPF;AAhCJ,SAAS,iBAAiB;AAC1B,SAAS,cAAc;AACvB,SAAS,sBAAsB;AAC/B,SAAS,4BAA4B;AAc9B,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB;AAAA,EACA,YAAY,CAAC;AAAA,EACb;AACF,GAAmB;AACjB,QAAM,SAAS,UAAU;AAEzB,QAAM,kBAAkB,gBAAgB,MAAM,OAAO,KAAK,GAAG;AAC7D,QAAM,qBAAqB,MAAM,OAAO,KAAK,WAAW;AAExD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MAEA;AAAA,4BAAC,wBAAqB,WAAW,wBAAwB;AAAA,QACzD,oBAAC,kBAAe,WAAsB;AAAA;AAAA;AAAA,EACxC;AAEJ;","names":[]}
@@ -1,7 +1,6 @@
1
1
  "use client";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
- import { useRouter } from "next/navigation";
5
4
  import * as PopoverPrimitive from "@radix-ui/react-popover";
6
5
  import { Popover } from "../ui/overlay/Popover";
7
6
  import { Progress } from "../ui/feedback/Progress";
@@ -17,10 +16,8 @@ function ProfilePopover({
17
16
  side = "top",
18
17
  align = "start",
19
18
  contentClassName = "absolute bottom-2 left-[26px]",
20
- menuItems = [],
21
- logoutRedirect = "/login"
19
+ menuItems = []
22
20
  }) {
23
- const router = useRouter();
24
21
  const { user, logout } = useAuth();
25
22
  const [isLoggingOut, setIsLoggingOut] = useState(false);
26
23
  const { summary, subscription, isSubscriptionLoading, isCreditsLoading } = useIaCredits();
@@ -31,9 +28,6 @@ function ProfilePopover({
31
28
  await logout();
32
29
  } finally {
33
30
  setIsLoggingOut(false);
34
- if (logoutRedirect !== "/login") {
35
- router.push(logoutRedirect);
36
- }
37
31
  }
38
32
  };
39
33
  const hasSubscription = !isSubscriptionLoading && subscription !== null;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/layouts/ProfilePopover.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { useRouter } from \"next/navigation\";\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport { Popover } from \"../ui/overlay/Popover\";\nimport { Progress } from \"../ui/feedback/Progress\";\nimport { Separator } from \"../ui/data-display/Separator\";\nimport { NavBarItem } from \"./NavBarItem\";\nimport { UserAvatar } from \"../ui/data-display/UserAvatar\";\nimport { LoadingOverlay } from \"../ui/feedback/LoadingOverlay\";\nimport { useAuth } from \"../../providers/auth.provider\";\nimport { cn } from \"../../infra/utils/clsx\";\nimport { useIaCredits } from \"../../modules/ia-credits/hooks/ia-credits.hook\";\nimport { useBuyCreditsModal } from \"../../store/useBuyCreditsModal\";\n\nexport interface ProfileMenuItem {\n icon?: React.ReactNode;\n label: string;\n onClick: () => void;\n}\n\nexport interface ProfilePopoverProps {\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n align?: \"start\" | \"center\" | \"end\";\n contentClassName?: string;\n menuItems?: ProfileMenuItem[];\n logoutRedirect?: string;\n}\n\nfunction ProfilePopover({\n side = \"top\",\n align = \"start\",\n contentClassName = \"absolute bottom-2 left-[26px]\",\n menuItems = [],\n logoutRedirect = \"/login\",\n}: ProfilePopoverProps) {\n const router = useRouter();\n const { user, logout } = useAuth();\n const [isLoggingOut, setIsLoggingOut] = useState(false);\n\n const { summary, subscription, isSubscriptionLoading, isCreditsLoading } =\n useIaCredits();\n const { openModal: openBuyCreditsModal } = useBuyCreditsModal();\n\n const handleLogout = async () => {\n try {\n setIsLoggingOut(true);\n await logout();\n } finally {\n setIsLoggingOut(false);\n if (logoutRedirect !== \"/login\") {\n router.push(logoutRedirect);\n }\n }\n };\n\n const hasSubscription = !isSubscriptionLoading && subscription !== null;\n\n const shouldShowCredits = hasSubscription && subscription.id_wl === 1;\n const creditsPercentage =\n shouldShowCredits && summary.totalCredits > 0\n ? (summary.usedCredits / summary.totalCredits) * 100\n : 0;\n\n return (\n <>\n <LoadingOverlay\n isLoading={isLoggingOut}\n message=\"Saindo da sua conta...\"\n />\n <Popover>\n <PopoverPrimitive.Trigger className=\"cursor-pointer\">\n {user && (\n <UserAvatar\n key={user.id}\n photo={user.photo}\n name={user.name}\n size={40}\n />\n )}\n </PopoverPrimitive.Trigger>\n\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n className={cn(\n \"w-64.75 p-0 bg-white rounded-2xl shadow-md border border-gray-200 z-99\",\n contentClassName,\n )}\n side={side}\n align={align}\n sideOffset={8}\n >\n <div className=\"grid grid-cols-[32px_1fr] items-center gap-3 p-3 w-full\">\n {user && (\n <UserAvatar\n key={user.id}\n photo={user.photo}\n name={user.name}\n size={32}\n />\n )}\n\n <div className=\"flex flex-col gap-0.5 min-w-0\">\n <span className=\"paragraph-small-semibold text-gray-950 truncate\">\n {user?.name || \"\"}\n </span>\n <span className=\"paragraph-xsmall-medium text-gray-500 truncate\">\n {user?.email || \"\"}\n </span>\n </div>\n </div>\n\n <div className=\"flex flex-col gap-2 border-t border-gray-200 rounded-2xl p-1.5\">\n {shouldShowCredits && (\n <div\n className={cn(\n \"flex flex-col bg-gray-950 rounded-lg gap-4 w-full p-4 transition-colors\",\n \"cursor-pointer hover:bg-gray-900\",\n )}\n onClick={() => openBuyCreditsModal()}\n >\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"paragraph-xsmall-semibold text-white truncate\">\n Créditos usados\n </span>\n <span className=\"paragraph-xsmall-medium text-white/50\">\n {summary.usedCredits.toLocaleString(\"pt-BR\")}/\n {summary.totalCredits.toLocaleString(\"pt-BR\")}\n </span>\n </div>\n <Progress\n className=\"bg-white/10\"\n indicatorColor=\"bg-white\"\n value={creditsPercentage}\n />\n </div>\n )}\n\n <div className=\"flex flex-col gap-2\">\n {menuItems.length > 0 && (\n <div className=\"flex flex-col\">\n {menuItems.map((item, index) => (\n <NavBarItem\n key={index}\n icon={item.icon}\n label={item.label}\n onClick={item.onClick}\n />\n ))}\n </div>\n )}\n <Separator />\n <NavBarItem label=\"Sair\" onClick={handleLogout} />\n </div>\n </div>\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </Popover>\n </>\n );\n}\n\nexport { ProfilePopover };\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/layouts/ProfilePopover.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport { Popover } from \"../ui/overlay/Popover\";\nimport { Progress } from \"../ui/feedback/Progress\";\nimport { Separator } from \"../ui/data-display/Separator\";\nimport { NavBarItem } from \"./NavBarItem\";\nimport { UserAvatar } from \"../ui/data-display/UserAvatar\";\nimport { LoadingOverlay } from \"../ui/feedback/LoadingOverlay\";\nimport { useAuth } from \"../../providers/auth.provider\";\nimport { cn } from \"../../infra/utils/clsx\";\nimport { useIaCredits } from \"../../modules/ia-credits/hooks/ia-credits.hook\";\nimport { useBuyCreditsModal } from \"../../store/useBuyCreditsModal\";\n\nexport interface ProfileMenuItem {\n icon?: React.ReactNode;\n label: string;\n onClick: () => void;\n}\n\nexport interface ProfilePopoverProps {\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n align?: \"start\" | \"center\" | \"end\";\n contentClassName?: string;\n menuItems?: ProfileMenuItem[];\n}\n\nfunction ProfilePopover({\n side = \"top\",\n align = \"start\",\n contentClassName = \"absolute bottom-2 left-[26px]\",\n menuItems = [],\n}: ProfilePopoverProps) {\n const { user, logout } = useAuth();\n const [isLoggingOut, setIsLoggingOut] = useState(false);\n\n const { summary, subscription, isSubscriptionLoading, isCreditsLoading } =\n useIaCredits();\n const { openModal: openBuyCreditsModal } = useBuyCreditsModal();\n\n const handleLogout = async () => {\n try {\n setIsLoggingOut(true);\n await logout();\n } finally {\n setIsLoggingOut(false);\n }\n };\n\n const hasSubscription = !isSubscriptionLoading && subscription !== null;\n\n const shouldShowCredits = hasSubscription && subscription.id_wl === 1;\n const creditsPercentage =\n shouldShowCredits && summary.totalCredits > 0\n ? (summary.usedCredits / summary.totalCredits) * 100\n : 0;\n\n return (\n <>\n <LoadingOverlay\n isLoading={isLoggingOut}\n message=\"Saindo da sua conta...\"\n />\n <Popover>\n <PopoverPrimitive.Trigger className=\"cursor-pointer\">\n {user && (\n <UserAvatar\n key={user.id}\n photo={user.photo}\n name={user.name}\n size={40}\n />\n )}\n </PopoverPrimitive.Trigger>\n\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n className={cn(\n \"w-64.75 p-0 bg-white rounded-2xl shadow-md border border-gray-200 z-99\",\n contentClassName,\n )}\n side={side}\n align={align}\n sideOffset={8}\n >\n <div className=\"grid grid-cols-[32px_1fr] items-center gap-3 p-3 w-full\">\n {user && (\n <UserAvatar\n key={user.id}\n photo={user.photo}\n name={user.name}\n size={32}\n />\n )}\n\n <div className=\"flex flex-col gap-0.5 min-w-0\">\n <span className=\"paragraph-small-semibold text-gray-950 truncate\">\n {user?.name || \"\"}\n </span>\n <span className=\"paragraph-xsmall-medium text-gray-500 truncate\">\n {user?.email || \"\"}\n </span>\n </div>\n </div>\n\n <div className=\"flex flex-col gap-2 border-t border-gray-200 rounded-2xl p-1.5\">\n {shouldShowCredits && (\n <div\n className={cn(\n \"flex flex-col bg-gray-950 rounded-lg gap-4 w-full p-4 transition-colors\",\n \"cursor-pointer hover:bg-gray-900\",\n )}\n onClick={() => openBuyCreditsModal()}\n >\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"paragraph-xsmall-semibold text-white truncate\">\n Créditos usados\n </span>\n <span className=\"paragraph-xsmall-medium text-white/50\">\n {summary.usedCredits.toLocaleString(\"pt-BR\")}/\n {summary.totalCredits.toLocaleString(\"pt-BR\")}\n </span>\n </div>\n <Progress\n className=\"bg-white/10\"\n indicatorColor=\"bg-white\"\n value={creditsPercentage}\n />\n </div>\n )}\n\n <div className=\"flex flex-col gap-2\">\n {menuItems.length > 0 && (\n <div className=\"flex flex-col\">\n {menuItems.map((item, index) => (\n <NavBarItem\n key={index}\n icon={item.icon}\n label={item.label}\n onClick={item.onClick}\n />\n ))}\n </div>\n )}\n <Separator />\n <NavBarItem label=\"Sair\" onClick={handleLogout} />\n </div>\n </div>\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </Popover>\n </>\n );\n}\n\nexport { ProfilePopover };\n"],"mappings":"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","names":[]}
@@ -1,7 +1,8 @@
1
1
  import { cookies } from "next/headers";
2
2
  import { api } from "../../../infra/api/client";
3
3
  import { ApiError } from "../../../infra/api/types";
4
- import { findWhitelabel } from "../../whitelabel/actions/find-whitelabel.action";
4
+ import { whitelabelService } from "../../whitelabel/services/whitelabel.service";
5
+ import { findWhitelabel } from "../../../server";
5
6
  const AUTH_COOKIE_NAME = "greatapps";
6
7
  const COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
7
8
  const COOKIE_OPTIONS = {
@@ -12,21 +13,10 @@ const COOKIE_OPTIONS = {
12
13
  domain: process.env.DOMAIN_COOKIE
13
14
  };
14
15
  class AuthService {
15
- async getWhitelabelToken(idWl) {
16
- const response = await api.apps.get(`/tokens?limit=1&page=1&sort=id:desc`, { whiteLabelId: idWl });
17
- if (response.status === 0 || !response.data?.[0]?.token) {
18
- throw new ApiError(
19
- "Token do whitelabel n\xE3o encontrado",
20
- "WL_TOKEN_NOT_FOUND",
21
- 404
22
- );
23
- }
24
- return response.data[0].token;
25
- }
26
16
  async login(credentials, clientInfo) {
27
17
  let requestConfig;
28
18
  if (credentials.id_wl) {
29
- const wlToken = await this.getWhitelabelToken(credentials.id_wl);
19
+ const wlToken = await whitelabelService.getTokenByWhitelabelId(credentials.id_wl);
30
20
  requestConfig = { whiteLabelId: credentials.id_wl, authToken: wlToken };
31
21
  }
32
22
  const response = await api.apps.post("/auth/login", {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/modules/auth/services/auth.service.ts"],"sourcesContent":["import { cookies } from \"next/headers\";\r\n\r\nimport { api } from \"../../../infra/api/client\";\r\nimport { ApiError } from \"../../../infra/api/types\";\r\nimport { findWhitelabel } from \"../../whitelabel/actions/find-whitelabel.action\";\r\nimport {\r\n ClientInfo,\r\n ForgotPasswordRequest,\r\n ForgotPasswordResponse,\r\n GeoLocation,\r\n LoginApiResponse,\r\n LoginRequest,\r\n LoginResponse,\r\n LogoutApiResponse,\r\n LogoutRequest,\r\n LogoutResponse,\r\n RegisterApiRequest,\r\n RegisterApiResponse,\r\n RegisterRequest,\r\n RegisterResponse,\r\n ResendVerificationRequest,\r\n ResendVerificationResponse,\r\n ResetPasswordRequest,\r\n ResetPasswordResponse,\r\n SearchPlansApiResponse,\r\n SessionKeepRequest,\r\n SessionKeepResponse,\r\n TwoFactorApiResponse,\r\n TwoFactorRequest,\r\n TwoFactorResponse,\r\n VerifyEmailRequest,\r\n VerifyEmailResponse,\r\n} from \"../schema\";\r\n\r\nconst AUTH_COOKIE_NAME = \"greatapps\";\r\nconst COOKIE_MAX_AGE = 60 * 60 * 24 * 30;\r\n\r\nconst COOKIE_OPTIONS = {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === \"production\",\r\n sameSite: \"lax\" as const,\r\n path: \"/\",\r\n domain: process.env.DOMAIN_COOKIE,\r\n};\r\n\r\nclass AuthService {\r\n private async getWhitelabelToken(idWl: number): Promise<string> {\r\n const response = await api.apps.get<{\r\n status: 0 | 1;\r\n data: Array<{ token: string }>;\r\n }>(`/tokens?limit=1&page=1&sort=id:desc`, { whiteLabelId: idWl });\r\n\r\n if (response.status === 0 || !response.data?.[0]?.token) {\r\n throw new ApiError(\r\n \"Token do whitelabel não encontrado\",\r\n \"WL_TOKEN_NOT_FOUND\",\r\n 404\r\n );\r\n }\r\n\r\n return response.data[0].token;\r\n }\r\n\r\n async login(\r\n credentials: LoginRequest,\r\n clientInfo: ClientInfo\r\n ): Promise<LoginResponse> {\r\n let requestConfig: import(\"../../../infra/api/client\").RequestConfig | undefined;\r\n\r\n if (credentials.id_wl) {\r\n const wlToken = await this.getWhitelabelToken(credentials.id_wl);\r\n requestConfig = { whiteLabelId: credentials.id_wl, authToken: wlToken };\r\n }\r\n\r\n const response = await api.apps.post<LoginApiResponse>(\"/auth/login\", {\r\n email: credentials.email,\r\n password: credentials.password,\r\n source: credentials?.source,\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n }, requestConfig);\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || \"E-mail ou senha incorretos\",\r\n response.code || \"LOGIN_FAILED\",\r\n 401\r\n );\r\n }\r\n\r\n if (!response.cookie) {\r\n throw new ApiError(\r\n \"Resposta de autenticação inválida\",\r\n \"INVALID_RESPONSE\",\r\n 500\r\n );\r\n }\r\n\r\n if (response.two_factor_required) {\r\n return { result: 'two_factor_required', cookie: response.cookie };\r\n }\r\n\r\n await this.setAuthCookie(response.cookie);\r\n\r\n const [{ userService }, { accountService }] = await Promise.all([\r\n import('../../users/services/user.service'),\r\n import('../../accounts/services/account.service'),\r\n ]);\r\n const [user, account] = await Promise.all([\r\n userService.findById(),\r\n accountService.findCurrentAccount(),\r\n ]);\r\n\r\n return {\r\n result: 'success',\r\n user,\r\n account,\r\n accessToken: response.cookie,\r\n refreshToken: \"\",\r\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\r\n };\r\n }\r\n\r\n async verifyTwoFactor(\r\n cookie: string,\r\n code: string,\r\n clientInfo: ClientInfo\r\n ): Promise<TwoFactorResponse> {\r\n const payload: TwoFactorRequest = {\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n cookie,\r\n code,\r\n };\r\n\r\n const response = await api.apps.post<TwoFactorApiResponse>(\r\n \"/auth/code\",\r\n payload\r\n );\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\"Código 2FA inválido\", \"TWO_FACTOR_FAILED\", 401);\r\n }\r\n\r\n if (!response?.data?.cookie) {\r\n throw new ApiError(\r\n \"Resposta de autenticação inválida após 2FA\",\r\n \"INVALID_RESPONSE\",\r\n 500\r\n );\r\n }\r\n\r\n await this.setAuthCookie(response.data.cookie);\r\n\r\n return { status: 1 };\r\n }\r\n async register(data: RegisterRequest, clientInfo: ClientInfo): Promise<RegisterResponse> {\r\n const today = new Date();\r\n const trialEndDate = new Date(today);\r\n trialEndDate.setDate(today.getDate() + 7); // 7 dias de trial\r\n\r\n const idPlan = await this.resolvePlanId(data.idPlan);\r\n\r\n const payload: RegisterApiRequest = {\r\n name: data.accountName,\r\n bussiness_type: data.businessType ?? 0,\r\n language: \"pt-br\",\r\n timezone: \"America/Sao_Paulo\",\r\n currency: \"BRL\",\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n agent: clientInfo.agent,\r\n user: {\r\n id_api: \"\",\r\n name: data.name,\r\n last_name: data.lastName || \"\",\r\n rg: data.rg || \"\",\r\n cpf: data.cpf || \"\",\r\n gender: data.gender,\r\n email: data.email,\r\n phone: data.phone,\r\n password: data.password,\r\n profile: \"owner\",\r\n language: \"pt-br\",\r\n },\r\n subscription: {\r\n type: \"trial\",\r\n id_cupom: data.couponCode || \"\",\r\n id_plan: idPlan,\r\n due_date: trialEndDate.toISOString().split(\"T\")[0],\r\n id_product: 1,\r\n },\r\n };\r\n\r\n const response = await api.apps.post<RegisterApiResponse>(\r\n \"/accounts\",\r\n payload\r\n );\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || \"Erro ao criar conta\",\r\n \"REGISTER_FAILED\",\r\n 400\r\n );\r\n }\r\n\r\n if (!response.data || response.data.length === 0) {\r\n throw new ApiError(\r\n \"Resposta de registro inválida\",\r\n \"INVALID_RESPONSE\",\r\n 500\r\n );\r\n }\r\n\r\n if (!response.cookie) {\r\n throw new ApiError(\r\n \"Resposta de autenticação inválida\",\r\n \"INVALID_RESPONSE\",\r\n 500\r\n );\r\n }\r\n\r\n const accountData = response.data[0];\r\n\r\n await this.setAuthCookie(response.cookie);\r\n\r\n const [{ userService }, { accountService }] = await Promise.all([\r\n import('../../users/services/user.service'),\r\n import('../../accounts/services/account.service'),\r\n ]);\r\n const [user, account] = await Promise.all([\r\n userService.findById(),\r\n accountService.findCurrentAccount(),\r\n ]);\r\n\r\n return {\r\n user,\r\n account,\r\n accessToken: response.cookie,\r\n refreshToken: \"\",\r\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\r\n requiresEmailVerification: !accountData.verified,\r\n };\r\n }\r\n\r\n async logout(clientInfo: ClientInfo): Promise<LogoutResponse> {\r\n const cookie = await this.getToken();\r\n\r\n if (!cookie) {\r\n throw new ApiError(\r\n \"Usuário não autenticado\",\r\n \"NOT_AUTHENTICATED_LOGOUT\",\r\n 401\r\n );\r\n }\r\n\r\n const payload: LogoutRequest = {\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n cookie,\r\n };\r\n\r\n try {\r\n const response = await api.apps.post<LogoutApiResponse>(\r\n \"/auth/logout\",\r\n payload\r\n );\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || \"Erro ao realizar logout\",\r\n response.code || \"LOGOUT_FAILED\",\r\n 400\r\n );\r\n }\r\n } finally {\r\n await this.removeAuthCookie();\r\n }\r\n\r\n return {\r\n success: true,\r\n };\r\n }\r\n\r\n async forgotPassword(\r\n _data: ForgotPasswordRequest\r\n ): Promise<ForgotPasswordResponse> {\r\n throw new ApiError(\r\n \"Recuperação de senha não implementada\",\r\n \"NOT_IMPLEMENTED\",\r\n 501\r\n );\r\n }\r\n\r\n async resetPassword(\r\n _data: ResetPasswordRequest\r\n ): Promise<ResetPasswordResponse> {\r\n throw new ApiError(\r\n \"Redefinição de senha não implementada\",\r\n \"NOT_IMPLEMENTED\",\r\n 501\r\n );\r\n }\r\n\r\n async verifyEmail(_data: VerifyEmailRequest): Promise<VerifyEmailResponse> {\r\n throw new ApiError(\r\n \"Verificação de email não implementada\",\r\n \"NOT_IMPLEMENTED\",\r\n 501\r\n );\r\n }\r\n\r\n async resendVerification(\r\n _data: ResendVerificationRequest\r\n ): Promise<ResendVerificationResponse> {\r\n throw new ApiError(\r\n \"Reenvio de verificação não implementado\",\r\n \"NOT_IMPLEMENTED\",\r\n 501\r\n );\r\n }\r\n\r\n async validateSession(clientInfo: ClientInfo): Promise<boolean> {\r\n const cookie = await this.getToken();\r\n\r\n if (!cookie) {\r\n return false;\r\n }\r\n\r\n try {\r\n const payload: SessionKeepRequest = {\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n cookie,\r\n };\r\n\r\n const response = await api.apps.post<SessionKeepResponse>(\r\n \"/auth/keep\",\r\n payload\r\n );\r\n\r\n return response.status === 1;\r\n } catch (error) {\r\n console.error(\"[AuthService] validateSession error\", error);\r\n return false;\r\n }\r\n }\r\n\r\n async isAuthenticated(): Promise<boolean> {\r\n const token = await this.getToken();\r\n return !!token;\r\n }\r\n\r\n async getToken(): Promise<string | undefined> {\r\n if (process.env.DUMMY_AUTH_TOKEN) return process.env.DUMMY_AUTH_TOKEN;\r\n const cookieStore = await cookies();\r\n return cookieStore.get(AUTH_COOKIE_NAME)?.value;\r\n }\r\n\r\n private async resolvePlanId(idPlan?: number | string): Promise<number> {\r\n if (idPlan === undefined || idPlan === null) return 1;\r\n if (typeof idPlan === 'number') return idPlan;\r\n\r\n const response = await api.apps.get<SearchPlansApiResponse>(\r\n `/plans?search=${encodeURIComponent(idPlan)}`\r\n );\r\n\r\n if (response.status === 0 || !response.data || response.data.length === 0) {\r\n throw new ApiError(\r\n `Plano \"${idPlan}\" não encontrado`,\r\n \"PLAN_NOT_FOUND\",\r\n 404\r\n );\r\n }\r\n\r\n return response.data[0].id;\r\n }\r\n\r\n private async setAuthCookie(token: string): Promise<void> {\r\n const cookieStore = await cookies();\r\n const whitelabel = await findWhitelabel().catch(() => null);\r\n const cookieDomain =\r\n this.normalizeCookieDomain(whitelabel?.domain) ??\r\n this.normalizeCookieDomain(process.env.DOMAIN_COOKIE);\r\n\r\n cookieStore.set(AUTH_COOKIE_NAME, token, {\r\n ...COOKIE_OPTIONS,\r\n ...(cookieDomain ? { domain: cookieDomain } : {}),\r\n maxAge: COOKIE_MAX_AGE,\r\n });\r\n }\r\n\r\n async removeAuthCookie(): Promise<void> {\r\n const cookieStore = await cookies();\r\n const whitelabel = await findWhitelabel().catch(() => null);\r\n const cookieDomain =\r\n this.normalizeCookieDomain(whitelabel?.domain) ??\r\n this.normalizeCookieDomain(process.env.DOMAIN_COOKIE);\r\n\r\n cookieStore.delete({\r\n name: AUTH_COOKIE_NAME,\r\n ...COOKIE_OPTIONS,\r\n ...(cookieDomain ? { domain: cookieDomain } : {}),\r\n });\r\n }\r\n\r\n private normalizeCookieDomain(domain?: string | null): string | undefined {\r\n if (!domain) return undefined;\r\n\r\n const normalized = domain.trim();\r\n if (!normalized) return undefined;\r\n\r\n const rawHost = (() => {\r\n try {\r\n return new URL(normalized).hostname;\r\n } catch {\r\n return normalized\r\n .replace(/^https?:\\/\\//i, \"\")\r\n .replace(/^www\\./i, \"\")\r\n .split(\"/\")[0]\r\n .split(\":\")[0];\r\n }\r\n })();\r\n\r\n if (!rawHost || rawHost === \"localhost\") {\r\n return undefined;\r\n }\r\n\r\n return rawHost.startsWith(\".\") ? rawHost : `.${rawHost}`;\r\n }\r\n}\r\n\r\nexport const authService = new AuthService();\r\n\r\nexport type { ClientInfo, GeoLocation };\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/modules/auth/services/auth.service.ts"],"sourcesContent":["import { cookies } from \"next/headers\";\r\n\r\nimport { api } from \"../../../infra/api/client\";\r\nimport { ApiError } from \"../../../infra/api/types\";\r\nimport { whitelabelService } from \"../../whitelabel/services/whitelabel.service\";\r\nimport {\r\n ClientInfo,\r\n ForgotPasswordRequest,\r\n ForgotPasswordResponse,\r\n GeoLocation,\r\n LoginApiResponse,\r\n LoginRequest,\r\n LoginResponse,\r\n LogoutApiResponse,\r\n LogoutRequest,\r\n LogoutResponse,\r\n RegisterApiRequest,\r\n RegisterApiResponse,\r\n RegisterRequest,\r\n RegisterResponse,\r\n ResendVerificationRequest,\r\n ResendVerificationResponse,\r\n ResetPasswordRequest,\r\n ResetPasswordResponse,\r\n SearchPlansApiResponse,\r\n SessionKeepRequest,\r\n SessionKeepResponse,\r\n TwoFactorApiResponse,\r\n TwoFactorRequest,\r\n TwoFactorResponse,\r\n VerifyEmailRequest,\r\n VerifyEmailResponse,\r\n} from \"../schema\";\r\nimport { findWhitelabel } from \"../../../server\";\r\n\r\nconst AUTH_COOKIE_NAME = \"greatapps\";\r\nconst COOKIE_MAX_AGE = 60 * 60 * 24 * 30;\r\n\r\nconst COOKIE_OPTIONS = {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === \"production\",\r\n sameSite: \"lax\" as const,\r\n path: \"/\",\r\n domain: process.env.DOMAIN_COOKIE,\r\n};\r\n\r\nclass AuthService {\r\n async login(\r\n credentials: LoginRequest,\r\n clientInfo: ClientInfo\r\n ): Promise<LoginResponse> {\r\n let requestConfig: import(\"../../../infra/api/client\").RequestConfig | undefined;\r\n\r\n if (credentials.id_wl) {\r\n const wlToken = await whitelabelService.getTokenByWhitelabelId(credentials.id_wl);\r\n requestConfig = { whiteLabelId: credentials.id_wl, authToken: wlToken };\r\n }\r\n\r\n const response = await api.apps.post<LoginApiResponse>(\"/auth/login\", {\r\n email: credentials.email,\r\n password: credentials.password,\r\n source: credentials?.source,\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n }, requestConfig);\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || \"E-mail ou senha incorretos\",\r\n response.code || \"LOGIN_FAILED\",\r\n 401\r\n );\r\n }\r\n\r\n if (!response.cookie) {\r\n throw new ApiError(\r\n \"Resposta de autenticação inválida\",\r\n \"INVALID_RESPONSE\",\r\n 500\r\n );\r\n }\r\n\r\n if (response.two_factor_required) {\r\n return { result: 'two_factor_required', cookie: response.cookie };\r\n }\r\n\r\n await this.setAuthCookie(response.cookie);\r\n\r\n const [{ userService }, { accountService }] = await Promise.all([\r\n import('../../users/services/user.service'),\r\n import('../../accounts/services/account.service'),\r\n ]);\r\n const [user, account] = await Promise.all([\r\n userService.findById(),\r\n accountService.findCurrentAccount(),\r\n ]);\r\n\r\n return {\r\n result: 'success',\r\n user,\r\n account,\r\n accessToken: response.cookie,\r\n refreshToken: \"\",\r\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\r\n };\r\n }\r\n\r\n async verifyTwoFactor(\r\n cookie: string,\r\n code: string,\r\n clientInfo: ClientInfo\r\n ): Promise<TwoFactorResponse> {\r\n const payload: TwoFactorRequest = {\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n cookie,\r\n code,\r\n };\r\n\r\n const response = await api.apps.post<TwoFactorApiResponse>(\r\n \"/auth/code\",\r\n payload\r\n );\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\"Código 2FA inválido\", \"TWO_FACTOR_FAILED\", 401);\r\n }\r\n\r\n if (!response?.data?.cookie) {\r\n throw new ApiError(\r\n \"Resposta de autenticação inválida após 2FA\",\r\n \"INVALID_RESPONSE\",\r\n 500\r\n );\r\n }\r\n\r\n await this.setAuthCookie(response.data.cookie);\r\n\r\n return { status: 1 };\r\n }\r\n async register(data: RegisterRequest, clientInfo: ClientInfo): Promise<RegisterResponse> {\r\n const today = new Date();\r\n const trialEndDate = new Date(today);\r\n trialEndDate.setDate(today.getDate() + 7); // 7 dias de trial\r\n\r\n const idPlan = await this.resolvePlanId(data.idPlan);\r\n\r\n const payload: RegisterApiRequest = {\r\n name: data.accountName,\r\n bussiness_type: data.businessType ?? 0,\r\n language: \"pt-br\",\r\n timezone: \"America/Sao_Paulo\",\r\n currency: \"BRL\",\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n agent: clientInfo.agent,\r\n user: {\r\n id_api: \"\",\r\n name: data.name,\r\n last_name: data.lastName || \"\",\r\n rg: data.rg || \"\",\r\n cpf: data.cpf || \"\",\r\n gender: data.gender,\r\n email: data.email,\r\n phone: data.phone,\r\n password: data.password,\r\n profile: \"owner\",\r\n language: \"pt-br\",\r\n },\r\n subscription: {\r\n type: \"trial\",\r\n id_cupom: data.couponCode || \"\",\r\n id_plan: idPlan,\r\n due_date: trialEndDate.toISOString().split(\"T\")[0],\r\n id_product: 1,\r\n },\r\n };\r\n\r\n const response = await api.apps.post<RegisterApiResponse>(\r\n \"/accounts\",\r\n payload\r\n );\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || \"Erro ao criar conta\",\r\n \"REGISTER_FAILED\",\r\n 400\r\n );\r\n }\r\n\r\n if (!response.data || response.data.length === 0) {\r\n throw new ApiError(\r\n \"Resposta de registro inválida\",\r\n \"INVALID_RESPONSE\",\r\n 500\r\n );\r\n }\r\n\r\n if (!response.cookie) {\r\n throw new ApiError(\r\n \"Resposta de autenticação inválida\",\r\n \"INVALID_RESPONSE\",\r\n 500\r\n );\r\n }\r\n\r\n const accountData = response.data[0];\r\n\r\n await this.setAuthCookie(response.cookie);\r\n\r\n const [{ userService }, { accountService }] = await Promise.all([\r\n import('../../users/services/user.service'),\r\n import('../../accounts/services/account.service'),\r\n ]);\r\n const [user, account] = await Promise.all([\r\n userService.findById(),\r\n accountService.findCurrentAccount(),\r\n ]);\r\n\r\n return {\r\n user,\r\n account,\r\n accessToken: response.cookie,\r\n refreshToken: \"\",\r\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\r\n requiresEmailVerification: !accountData.verified,\r\n };\r\n }\r\n\r\n async logout(clientInfo: ClientInfo): Promise<LogoutResponse> {\r\n const cookie = await this.getToken();\r\n\r\n if (!cookie) {\r\n throw new ApiError(\r\n \"Usuário não autenticado\",\r\n \"NOT_AUTHENTICATED_LOGOUT\",\r\n 401\r\n );\r\n }\r\n\r\n const payload: LogoutRequest = {\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n cookie,\r\n };\r\n\r\n try {\r\n const response = await api.apps.post<LogoutApiResponse>(\r\n \"/auth/logout\",\r\n payload\r\n );\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || \"Erro ao realizar logout\",\r\n response.code || \"LOGOUT_FAILED\",\r\n 400\r\n );\r\n }\r\n } finally {\r\n await this.removeAuthCookie();\r\n }\r\n\r\n return {\r\n success: true,\r\n };\r\n }\r\n\r\n async forgotPassword(\r\n _data: ForgotPasswordRequest\r\n ): Promise<ForgotPasswordResponse> {\r\n throw new ApiError(\r\n \"Recuperação de senha não implementada\",\r\n \"NOT_IMPLEMENTED\",\r\n 501\r\n );\r\n }\r\n\r\n async resetPassword(\r\n _data: ResetPasswordRequest\r\n ): Promise<ResetPasswordResponse> {\r\n throw new ApiError(\r\n \"Redefinição de senha não implementada\",\r\n \"NOT_IMPLEMENTED\",\r\n 501\r\n );\r\n }\r\n\r\n async verifyEmail(_data: VerifyEmailRequest): Promise<VerifyEmailResponse> {\r\n throw new ApiError(\r\n \"Verificação de email não implementada\",\r\n \"NOT_IMPLEMENTED\",\r\n 501\r\n );\r\n }\r\n\r\n async resendVerification(\r\n _data: ResendVerificationRequest\r\n ): Promise<ResendVerificationResponse> {\r\n throw new ApiError(\r\n \"Reenvio de verificação não implementado\",\r\n \"NOT_IMPLEMENTED\",\r\n 501\r\n );\r\n }\r\n\r\n async validateSession(clientInfo: ClientInfo): Promise<boolean> {\r\n const cookie = await this.getToken();\r\n\r\n if (!cookie) {\r\n return false;\r\n }\r\n\r\n try {\r\n const payload: SessionKeepRequest = {\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n cookie,\r\n };\r\n\r\n const response = await api.apps.post<SessionKeepResponse>(\r\n \"/auth/keep\",\r\n payload\r\n );\r\n\r\n return response.status === 1;\r\n } catch (error) {\r\n console.error(\"[AuthService] validateSession error\", error);\r\n return false;\r\n }\r\n }\r\n\r\n async isAuthenticated(): Promise<boolean> {\r\n const token = await this.getToken();\r\n return !!token;\r\n }\r\n\r\n async getToken(): Promise<string | undefined> {\r\n if (process.env.DUMMY_AUTH_TOKEN) return process.env.DUMMY_AUTH_TOKEN;\r\n const cookieStore = await cookies();\r\n return cookieStore.get(AUTH_COOKIE_NAME)?.value;\r\n }\r\n\r\n private async resolvePlanId(idPlan?: number | string): Promise<number> {\r\n if (idPlan === undefined || idPlan === null) return 1;\r\n if (typeof idPlan === 'number') return idPlan;\r\n\r\n const response = await api.apps.get<SearchPlansApiResponse>(\r\n `/plans?search=${encodeURIComponent(idPlan)}`\r\n );\r\n\r\n if (response.status === 0 || !response.data || response.data.length === 0) {\r\n throw new ApiError(\r\n `Plano \"${idPlan}\" não encontrado`,\r\n \"PLAN_NOT_FOUND\",\r\n 404\r\n );\r\n }\r\n\r\n return response.data[0].id;\r\n }\r\n\r\n private async setAuthCookie(token: string): Promise<void> {\r\n const cookieStore = await cookies();\r\n const whitelabel = await findWhitelabel().catch(() => null);\r\n const cookieDomain =\r\n this.normalizeCookieDomain(whitelabel?.domain) ??\r\n this.normalizeCookieDomain(process.env.DOMAIN_COOKIE);\r\n\r\n cookieStore.set(AUTH_COOKIE_NAME, token, {\r\n ...COOKIE_OPTIONS,\r\n ...(cookieDomain ? { domain: cookieDomain } : {}),\r\n maxAge: COOKIE_MAX_AGE,\r\n });\r\n }\r\n\r\n async removeAuthCookie(): Promise<void> {\r\n const cookieStore = await cookies();\r\n const whitelabel = await findWhitelabel().catch(() => null);\r\n const cookieDomain =\r\n this.normalizeCookieDomain(whitelabel?.domain) ??\r\n this.normalizeCookieDomain(process.env.DOMAIN_COOKIE);\r\n\r\n cookieStore.delete({\r\n name: AUTH_COOKIE_NAME,\r\n ...COOKIE_OPTIONS,\r\n ...(cookieDomain ? { domain: cookieDomain } : {}),\r\n });\r\n }\r\n\r\n private normalizeCookieDomain(domain?: string | null): string | undefined {\r\n if (!domain) return undefined;\r\n\r\n const normalized = domain.trim();\r\n if (!normalized) return undefined;\r\n\r\n const rawHost = (() => {\r\n try {\r\n return new URL(normalized).hostname;\r\n } catch {\r\n return normalized\r\n .replace(/^https?:\\/\\//i, \"\")\r\n .replace(/^www\\./i, \"\")\r\n .split(\"/\")[0]\r\n .split(\":\")[0];\r\n }\r\n })();\r\n\r\n if (!rawHost || rawHost === \"localhost\") {\r\n return undefined;\r\n }\r\n\r\n return rawHost.startsWith(\".\") ? rawHost : `.${rawHost}`;\r\n }\r\n}\r\n\r\nexport const authService = new AuthService();\r\n\r\nexport type { ClientInfo, GeoLocation };\r\n"],"mappings":"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","names":[]}
@@ -4,14 +4,22 @@ class WhitelabelService {
4
4
  getApiUrl() {
5
5
  const apiUrl = process.env.GAPPS_R3_API_URL;
6
6
  if (!apiUrl) {
7
- throw new ApiError("GAPPS_R3_API_URL not configured", "CONFIG_ERROR", 500);
7
+ throw new ApiError(
8
+ "GAPPS_R3_API_URL not configured",
9
+ "CONFIG_ERROR",
10
+ 500
11
+ );
8
12
  }
9
13
  return apiUrl;
10
14
  }
11
15
  getToken() {
12
16
  const token = process.env.WHITELABEL_TOKEN_MASTER;
13
17
  if (!token) {
14
- throw new ApiError("WHITELABEL_TOKEN_MASTER not configured", "CONFIG_ERROR", 500);
18
+ throw new ApiError(
19
+ "WHITELABEL_TOKEN_MASTER not configured",
20
+ "CONFIG_ERROR",
21
+ 500
22
+ );
15
23
  }
16
24
  return token;
17
25
  }
@@ -38,7 +46,9 @@ class WhitelabelService {
38
46
  }
39
47
  });
40
48
  if (!response.ok) {
41
- console.error("[WhitelabelService] Failed to fetch whitelabel token", { response });
49
+ console.error("[WhitelabelService] Failed to fetch whitelabel token", {
50
+ response
51
+ });
42
52
  throw new ApiError(
43
53
  `Failed to fetch whitelabel token: ${response.status}`,
44
54
  "FETCH_ERROR",
@@ -64,15 +74,51 @@ class WhitelabelService {
64
74
  await cache.insert(cacheKey, JSON.stringify(data), 604800);
65
75
  return data;
66
76
  }
77
+ async getTokenByWhitelabelId(idWl) {
78
+ const apiUrl = this.getApiUrl();
79
+ const masterToken = this.getToken();
80
+ const url = `${apiUrl}/v1/pt-br/${idWl}/tokens?limit=1&page=1&sort=id:desc`;
81
+ const response = await fetch(url, {
82
+ method: "GET",
83
+ headers: { authorization: masterToken }
84
+ });
85
+ console.debug("[WhitelabelService] Fetching token by whitelabel ID", {
86
+ url,
87
+ config: {
88
+ method: "GET",
89
+ headers: { authorization: masterToken }
90
+ }
91
+ });
92
+ if (!response.ok) {
93
+ throw new ApiError(
94
+ `Failed to fetch whitelabel token: ${response.status}`,
95
+ "WL_TOKEN_NOT_FOUND",
96
+ response.status
97
+ );
98
+ }
99
+ const result = await response.json();
100
+ if (result.status !== 1 || !result.data?.length) {
101
+ throw new ApiError(
102
+ "Token do whitelabel n\xE3o encontrado",
103
+ "WL_TOKEN_NOT_FOUND",
104
+ 404
105
+ );
106
+ }
107
+ return result.data[0].token;
108
+ }
67
109
  async revalidateByDomain(hostname) {
68
110
  hostname = process.env.WHITELABEL_DOMAIN || hostname;
69
111
  const cache = this.createCache();
70
112
  const cacheKey = this.getCacheKey(hostname);
71
- console.log("[WhitelabelService] Revalidating cache for domain", { hostname });
113
+ console.log("[WhitelabelService] Revalidating cache for domain", {
114
+ hostname
115
+ });
72
116
  await cache.delete(cacheKey);
73
117
  const data = await this.fetchFromApi(hostname);
74
118
  await cache.insert(cacheKey, JSON.stringify(data), 604800);
75
- console.log("[WhitelabelService] Cache revalidated for domain", { hostname });
119
+ console.log("[WhitelabelService] Cache revalidated for domain", {
120
+ hostname
121
+ });
76
122
  return data;
77
123
  }
78
124
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/modules/whitelabel/services/whitelabel.service.ts"],"sourcesContent":["\r\nimport greatCache from '@greatapps/cache';\r\nimport { ApiError } from '../../../infra/api/types';\r\nimport { WhitelabelTokenApiResponse, WhitelabelTokenData } from '../schema';\r\n\r\nclass WhitelabelService {\r\n private getApiUrl(): string {\r\n const apiUrl = process.env.GAPPS_R3_API_URL;\r\n if (!apiUrl) {\r\n throw new ApiError('GAPPS_R3_API_URL not configured', 'CONFIG_ERROR', 500);\r\n }\r\n return apiUrl;\r\n }\r\n\r\n private getToken(): string {\r\n const token = process.env.WHITELABEL_TOKEN_MASTER;\r\n if (!token) {\r\n throw new ApiError('WHITELABEL_TOKEN_MASTER not configured', 'CONFIG_ERROR', 500);\r\n }\r\n return token;\r\n }\r\n\r\n private createCache() {\r\n return new greatCache({\r\n service: 'whitelabel-service',\r\n version: '1.0',\r\n domain: 'whitelabel-cache.greatapps.com.br',\r\n ambient: process.env.NODE_ENV || 'development',\r\n });\r\n }\r\n\r\n private getCacheKey(hostname: string): string {\r\n return `whitelabel-token-${hostname}`;\r\n }\r\n\r\n private async fetchFromApi(hostname: string): Promise<WhitelabelTokenData> {\r\n const apiUrl = this.getApiUrl();\r\n const whitelabelMasterToken = this.getToken();\r\n const url = `${apiUrl}/v1/pt-br/1/whitelabel/${hostname}/token`;\r\n\r\n console.log('[WhitelabelService] Fetching token for domain', { url });\r\n\r\n const response = await fetch(url, {\r\n method: 'GET',\r\n headers: {\r\n authorization: whitelabelMasterToken,\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n console.error('[WhitelabelService] Failed to fetch whitelabel token', { response });\r\n throw new ApiError(\r\n `Failed to fetch whitelabel token: ${response.status}`,\r\n 'FETCH_ERROR',\r\n response.status\r\n );\r\n }\r\n\r\n const result: WhitelabelTokenApiResponse = await response.json();\r\n\r\n if (result.status !== 1 || !result.data?.length) {\r\n throw new ApiError('Whitelabel token not found', 'TOKEN_NOT_FOUND', 404);\r\n }\r\n\r\n return result.data[0];\r\n }\r\n\r\n async getTokenByDomain(hostname: string): Promise<WhitelabelTokenData> {\r\n hostname = process.env.WHITELABEL_DOMAIN || hostname;\r\n\r\n const cache = this.createCache();\r\n const cacheKey = this.getCacheKey(hostname);\r\n\r\n const cachedData = await cache.select(cacheKey);\r\n\r\n if (cachedData.status == 1 && 'data' in cachedData && cachedData.data) {\r\n console.log('[WhitelabelService] Cache hit for domain', { hostname });\r\n return JSON.parse(cachedData.data) as WhitelabelTokenData;\r\n }\r\n\r\n const data = await this.fetchFromApi(hostname);\r\n\r\n await cache.insert(cacheKey, JSON.stringify(data), 604800);\r\n\r\n return data;\r\n }\r\n\r\n async revalidateByDomain(hostname: string): Promise<WhitelabelTokenData> {\r\n hostname = process.env.WHITELABEL_DOMAIN || hostname;\r\n\r\n const cache = this.createCache();\r\n const cacheKey = this.getCacheKey(hostname);\r\n\r\n console.log('[WhitelabelService] Revalidating cache for domain', { hostname });\r\n\r\n await cache.delete(cacheKey);\r\n\r\n const data = await this.fetchFromApi(hostname);\r\n\r\n await cache.insert(cacheKey, JSON.stringify(data), 604800);\r\n\r\n console.log('[WhitelabelService] Cache revalidated for domain', { hostname });\r\n\r\n return data;\r\n }\r\n}\r\n\r\nexport const whitelabelService = new WhitelabelService();\r\n"],"mappings":"AACA,OAAO,gBAAgB;AACvB,SAAS,gBAAgB;AAGzB,MAAM,kBAAkB;AAAA,EACd,YAAoB;AAC1B,UAAM,SAAS,QAAQ,IAAI;AAC3B,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,SAAS,mCAAmC,gBAAgB,GAAG;AAAA,IAC3E;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,WAAmB;AACzB,UAAM,QAAQ,QAAQ,IAAI;AAC1B,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,SAAS,0CAA0C,gBAAgB,GAAG;AAAA,IAClF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,cAAc;AACpB,WAAO,IAAI,WAAW;AAAA,MACpB,SAAS;AAAA,MACT,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,SAAS,QAAQ,IAAI,YAAY;AAAA,IACnC,CAAC;AAAA,EACH;AAAA,EAEQ,YAAY,UAA0B;AAC5C,WAAO,oBAAoB,QAAQ;AAAA,EACrC;AAAA,EAEA,MAAc,aAAa,UAAgD;AACzE,UAAM,SAAS,KAAK,UAAU;AAC9B,UAAM,wBAAwB,KAAK,SAAS;AAC5C,UAAM,MAAM,GAAG,MAAM,0BAA0B,QAAQ;AAEvD,YAAQ,IAAI,iDAAiD,EAAE,IAAI,CAAC;AAEpE,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe;AAAA,MACjB;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,cAAQ,MAAM,wDAAwD,EAAE,SAAS,CAAC;AAClF,YAAM,IAAI;AAAA,QACR,qCAAqC,SAAS,MAAM;AAAA,QACpD;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,SAAqC,MAAM,SAAS,KAAK;AAE/D,QAAI,OAAO,WAAW,KAAK,CAAC,OAAO,MAAM,QAAQ;AAC/C,YAAM,IAAI,SAAS,8BAA8B,mBAAmB,GAAG;AAAA,IACzE;AAEA,WAAO,OAAO,KAAK,CAAC;AAAA,EACtB;AAAA,EAEA,MAAM,iBAAiB,UAAgD;AACrE,eAAW,QAAQ,IAAI,qBAAqB;AAE5C,UAAM,QAAQ,KAAK,YAAY;AAC/B,UAAM,WAAW,KAAK,YAAY,QAAQ;AAE1C,UAAM,aAAa,MAAM,MAAM,OAAO,QAAQ;AAE9C,QAAI,WAAW,UAAU,KAAK,UAAU,cAAc,WAAW,MAAM;AACrE,cAAQ,IAAI,4CAA4C,EAAE,SAAS,CAAC;AACpE,aAAO,KAAK,MAAM,WAAW,IAAI;AAAA,IACnC;AAEA,UAAM,OAAO,MAAM,KAAK,aAAa,QAAQ;AAE7C,UAAM,MAAM,OAAO,UAAU,KAAK,UAAU,IAAI,GAAG,MAAM;AAEzD,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,mBAAmB,UAAgD;AACvE,eAAW,QAAQ,IAAI,qBAAqB;AAE5C,UAAM,QAAQ,KAAK,YAAY;AAC/B,UAAM,WAAW,KAAK,YAAY,QAAQ;AAE1C,YAAQ,IAAI,qDAAqD,EAAE,SAAS,CAAC;AAE7E,UAAM,MAAM,OAAO,QAAQ;AAE3B,UAAM,OAAO,MAAM,KAAK,aAAa,QAAQ;AAE7C,UAAM,MAAM,OAAO,UAAU,KAAK,UAAU,IAAI,GAAG,MAAM;AAEzD,YAAQ,IAAI,oDAAoD,EAAE,SAAS,CAAC;AAE5E,WAAO;AAAA,EACT;AACF;AAEO,MAAM,oBAAoB,IAAI,kBAAkB;","names":[]}
1
+ {"version":3,"sources":["../../../../src/modules/whitelabel/services/whitelabel.service.ts"],"sourcesContent":["import greatCache from \"@greatapps/cache\";\r\nimport { ApiError } from \"../../../infra/api/types\";\r\nimport { WhitelabelTokenApiResponse, WhitelabelTokenData } from \"../schema\";\r\n\r\nclass WhitelabelService {\r\n private getApiUrl(): string {\r\n const apiUrl = process.env.GAPPS_R3_API_URL;\r\n if (!apiUrl) {\r\n throw new ApiError(\r\n \"GAPPS_R3_API_URL not configured\",\r\n \"CONFIG_ERROR\",\r\n 500,\r\n );\r\n }\r\n return apiUrl;\r\n }\r\n\r\n private getToken(): string {\r\n const token = process.env.WHITELABEL_TOKEN_MASTER;\r\n if (!token) {\r\n throw new ApiError(\r\n \"WHITELABEL_TOKEN_MASTER not configured\",\r\n \"CONFIG_ERROR\",\r\n 500,\r\n );\r\n }\r\n return token;\r\n }\r\n\r\n private createCache() {\r\n return new greatCache({\r\n service: \"whitelabel-service\",\r\n version: \"1.0\",\r\n domain: \"whitelabel-cache.greatapps.com.br\",\r\n ambient: process.env.NODE_ENV || \"development\",\r\n });\r\n }\r\n\r\n private getCacheKey(hostname: string): string {\r\n return `whitelabel-token-${hostname}`;\r\n }\r\n\r\n private async fetchFromApi(hostname: string): Promise<WhitelabelTokenData> {\r\n const apiUrl = this.getApiUrl();\r\n const whitelabelMasterToken = this.getToken();\r\n const url = `${apiUrl}/v1/pt-br/1/whitelabel/${hostname}/token`;\r\n\r\n console.log(\"[WhitelabelService] Fetching token for domain\", { url });\r\n\r\n const response = await fetch(url, {\r\n method: \"GET\",\r\n headers: {\r\n authorization: whitelabelMasterToken,\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n console.error(\"[WhitelabelService] Failed to fetch whitelabel token\", {\r\n response,\r\n });\r\n throw new ApiError(\r\n `Failed to fetch whitelabel token: ${response.status}`,\r\n \"FETCH_ERROR\",\r\n response.status,\r\n );\r\n }\r\n\r\n const result: WhitelabelTokenApiResponse = await response.json();\r\n\r\n if (result.status !== 1 || !result.data?.length) {\r\n throw new ApiError(\"Whitelabel token not found\", \"TOKEN_NOT_FOUND\", 404);\r\n }\r\n\r\n return result.data[0];\r\n }\r\n\r\n async getTokenByDomain(hostname: string): Promise<WhitelabelTokenData> {\r\n hostname = process.env.WHITELABEL_DOMAIN || hostname;\r\n\r\n const cache = this.createCache();\r\n const cacheKey = this.getCacheKey(hostname);\r\n\r\n const cachedData = await cache.select(cacheKey);\r\n\r\n if (cachedData.status == 1 && \"data\" in cachedData && cachedData.data) {\r\n console.log(\"[WhitelabelService] Cache hit for domain\", { hostname });\r\n return JSON.parse(cachedData.data) as WhitelabelTokenData;\r\n }\r\n\r\n const data = await this.fetchFromApi(hostname);\r\n\r\n await cache.insert(cacheKey, JSON.stringify(data), 604800);\r\n\r\n return data;\r\n }\r\n\r\n async getTokenByWhitelabelId(idWl: number): Promise<string> {\r\n const apiUrl = this.getApiUrl();\r\n const masterToken = this.getToken();\r\n const url = `${apiUrl}/v1/pt-br/${idWl}/tokens?limit=1&page=1&sort=id:desc`;\r\n\r\n const response = await fetch(url, {\r\n method: \"GET\",\r\n headers: { authorization: masterToken },\r\n });\r\n\r\n console.debug(\"[WhitelabelService] Fetching token by whitelabel ID\", {\r\n url,\r\n config: {\r\n method: \"GET\",\r\n headers: { authorization: masterToken },\r\n },\r\n });\r\n\r\n \r\n\r\n if (!response.ok) {\r\n throw new ApiError(\r\n `Failed to fetch whitelabel token: ${response.status}`,\r\n \"WL_TOKEN_NOT_FOUND\",\r\n response.status,\r\n );\r\n }\r\n\r\n const result: WhitelabelTokenApiResponse = await response.json();\r\n\r\n if (result.status !== 1 || !result.data?.length) {\r\n throw new ApiError(\r\n \"Token do whitelabel não encontrado\",\r\n \"WL_TOKEN_NOT_FOUND\",\r\n 404,\r\n );\r\n }\r\n\r\n return result.data[0].token;\r\n }\r\n\r\n async revalidateByDomain(hostname: string): Promise<WhitelabelTokenData> {\r\n hostname = process.env.WHITELABEL_DOMAIN || hostname;\r\n\r\n const cache = this.createCache();\r\n const cacheKey = this.getCacheKey(hostname);\r\n\r\n console.log(\"[WhitelabelService] Revalidating cache for domain\", {\r\n hostname,\r\n });\r\n\r\n await cache.delete(cacheKey);\r\n\r\n const data = await this.fetchFromApi(hostname);\r\n\r\n await cache.insert(cacheKey, JSON.stringify(data), 604800);\r\n\r\n console.log(\"[WhitelabelService] Cache revalidated for domain\", {\r\n hostname,\r\n });\r\n\r\n return data;\r\n }\r\n}\r\n\r\nexport const whitelabelService = new WhitelabelService();\r\n"],"mappings":"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","names":[]}
@@ -16,7 +16,7 @@ import { useLogin } from "../modules/auth/hooks/login.hook";
16
16
  import { useRegister } from "../modules/auth/hooks/register.hook";
17
17
  import { useLogout } from "../modules/auth/hooks/logout.hook";
18
18
  import { useCurrentAccount, ACCOUNT_QUERY_KEY } from "../modules/accounts/hooks/current-account.hook";
19
- import { useRouter } from "next/navigation";
19
+ import { useWhitelabelUrls } from "./whitelabel.provider";
20
20
  const AuthContext = createContext(
21
21
  void 0
22
22
  );
@@ -26,7 +26,7 @@ function AuthProvider({ children }) {
26
26
  const { isLoading: isSessionLoading } = useUserValidateSession();
27
27
  const queryClient = useQueryClient();
28
28
  const setUserData = useSetUserData();
29
- const router = useRouter();
29
+ const { accountsUrl, pagesUrl } = useWhitelabelUrls();
30
30
  const { mutateAsync: loginMutate, isPending: isLogging } = useLogin();
31
31
  const { mutateAsync: registerMutate, isPending: isRegistering } = useRegister();
32
32
  const { mutateAsync: logoutMutate, isPending: isLoggingOut } = useLogout();
@@ -62,15 +62,29 @@ function AuthProvider({ children }) {
62
62
  },
63
63
  [queryClient, setUserData]
64
64
  );
65
+ const resolveLogoutRedirect = useCallback(() => {
66
+ if (typeof window === "undefined") {
67
+ return "/login";
68
+ }
69
+ try {
70
+ const currentOrigin = window.location.origin;
71
+ const pagesOrigin = pagesUrl ? new URL(pagesUrl).origin : "";
72
+ if (pagesOrigin && currentOrigin === pagesOrigin) {
73
+ return accountsUrl || "/login";
74
+ }
75
+ } catch {
76
+ }
77
+ return "/login";
78
+ }, [accountsUrl, pagesUrl]);
65
79
  const logout = useCallback(async () => {
66
80
  try {
67
81
  await logoutMutate(void 0);
68
82
  } catch {
69
83
  } finally {
70
84
  queryClient.clear();
71
- router.push("/login");
85
+ window.location.assign(resolveLogoutRedirect());
72
86
  }
73
- }, [queryClient, router]);
87
+ }, [queryClient, logoutMutate, resolveLogoutRedirect]);
74
88
  const value = useMemo(
75
89
  () => ({
76
90
  user: user ?? null,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/providers/auth.provider.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport {\r\n createContext,\r\n ReactNode,\r\n useCallback,\r\n useContext,\r\n useMemo,\r\n} from \"react\";\r\nimport { useQueryClient } from \"@tanstack/react-query\";\r\nimport {\r\n useUserQuery,\r\n useSetUserData,\r\n useUserValidateSession,\r\n} from \"../modules/auth/hooks/useUserQuery\";\r\nimport { useLogin } from \"../modules/auth/hooks/login.hook\";\r\nimport { useRegister } from \"../modules/auth/hooks/register.hook\";\r\nimport { useLogout } from \"../modules/auth/hooks/logout.hook\";\r\nimport {\r\n AuthState,\r\n LoginRequest,\r\n RegisterRequest,\r\n} from \"../modules/auth/schema\";\r\n\r\nexport type LoginResult =\r\n | { result: \"success\" }\r\n | { result: \"two_factor_required\"; cookie: string }\r\n | { result: \"error\"; message: string };\r\nimport { useCurrentAccount, ACCOUNT_QUERY_KEY } from \"../modules/accounts/hooks/current-account.hook\";\r\nimport { useRouter } from \"next/navigation\";\r\n\r\ninterface AuthContextProps extends AuthState {\r\n login: (credentials: LoginRequest) => Promise<LoginResult>;\r\n register: (data: RegisterRequest) => Promise<void>;\r\n logout: () => Promise<void>;\r\n}\r\n\r\nexport const AuthContext = createContext<AuthContextProps | undefined>(\r\n undefined\r\n);\r\n\r\ninterface AuthProviderProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function AuthProvider({ children }: AuthProviderProps) {\r\n const { data: user, isLoading: isQueryLoading } = useUserQuery();\r\n const { data: account, isLoading: isAccountLoading } = useCurrentAccount();\r\n const { isLoading: isSessionLoading } = useUserValidateSession();\r\n\r\n const queryClient = useQueryClient();\r\n const setUserData = useSetUserData();\r\n\r\n const router = useRouter();\r\n\r\n const { mutateAsync: loginMutate, isPending: isLogging } = useLogin();\r\n const { mutateAsync: registerMutate, isPending: isRegistering } =\r\n useRegister();\r\n const { mutateAsync: logoutMutate, isPending: isLoggingOut } = useLogout();\r\n\r\n const isAuthenticated = !!user;\r\n const isLoading =\r\n isLogging ||\r\n isRegistering ||\r\n isLoggingOut ||\r\n isQueryLoading ||\r\n isAccountLoading ||\r\n isSessionLoading;\r\n\r\n const login = useCallback(\r\n async (credentials: LoginRequest): Promise<LoginResult> => {\r\n try {\r\n const data = await loginMutate(credentials);\r\n\r\n if (data.result === \"two_factor_required\") {\r\n return { result: \"two_factor_required\", cookie: data.cookie };\r\n }\r\n\r\n queryClient.clear();\r\n setUserData(data.user);\r\n queryClient.setQueryData(ACCOUNT_QUERY_KEY, data.account);\r\n\r\n return { result: \"success\" };\r\n } catch (error) {\r\n const message =\r\n error instanceof Error ? error.message : \"Ocorreu um erro ao fazer login. Tente novamente.\";\r\n return { result: \"error\", message };\r\n }\r\n },\r\n [queryClient, setUserData]\r\n );\r\n\r\n const register = useCallback(\r\n async (data: RegisterRequest): Promise<void> => {\r\n await registerMutate(data, {\r\n onSuccess: (data) => {\r\n queryClient.clear();\r\n setUserData(data.user);\r\n queryClient.setQueryData(ACCOUNT_QUERY_KEY, data.account);\r\n },\r\n });\r\n },\r\n [queryClient, setUserData]\r\n );\r\n\r\n const logout = useCallback(async (): Promise<void> => {\r\n try {\r\n await logoutMutate(undefined);\r\n } catch {\r\n // cookie já removido no servidor mesmo se a API falhou\r\n } finally {\r\n queryClient.clear();\r\n router.push(\"/login\");\r\n }\r\n }, [queryClient, router]);\r\n\r\n const value: AuthContextProps = useMemo(\r\n () => ({\r\n user: user ?? null,\r\n account: account ?? null,\r\n isAuthenticated,\r\n isLoading,\r\n login,\r\n register,\r\n logout,\r\n }),\r\n [user, account, isAuthenticated, isLoading, login, register, logout]\r\n );\r\n\r\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\r\n}\r\n\r\nexport function useAuth(): AuthContextProps {\r\n const context = useContext(AuthContext);\r\n\r\n if (context === undefined) {\r\n throw new Error(\"useAuth deve ser usado dentro de um AuthProvider\");\r\n }\r\n\r\n return context;\r\n}\r\n"],"mappings":";AAiIS;AA/HT;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,sBAAsB;AAC/B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB;AAW1B,SAAS,mBAAmB,yBAAyB;AACrD,SAAS,iBAAiB;AAQnB,MAAM,cAAc;AAAA,EACzB;AACF;AAMO,SAAS,aAAa,EAAE,SAAS,GAAsB;AAC5D,QAAM,EAAE,MAAM,MAAM,WAAW,eAAe,IAAI,aAAa;AAC/D,QAAM,EAAE,MAAM,SAAS,WAAW,iBAAiB,IAAI,kBAAkB;AACzE,QAAM,EAAE,WAAW,iBAAiB,IAAI,uBAAuB;AAE/D,QAAM,cAAc,eAAe;AACnC,QAAM,cAAc,eAAe;AAEnC,QAAM,SAAS,UAAU;AAEzB,QAAM,EAAE,aAAa,aAAa,WAAW,UAAU,IAAI,SAAS;AACpE,QAAM,EAAE,aAAa,gBAAgB,WAAW,cAAc,IAC5D,YAAY;AACd,QAAM,EAAE,aAAa,cAAc,WAAW,aAAa,IAAI,UAAU;AAEzE,QAAM,kBAAkB,CAAC,CAAC;AAC1B,QAAM,YACJ,aACA,iBACA,gBACA,kBACA,oBACA;AAEF,QAAM,QAAQ;AAAA,IACZ,OAAO,gBAAoD;AACzD,UAAI;AACF,cAAM,OAAO,MAAM,YAAY,WAAW;AAE1C,YAAI,KAAK,WAAW,uBAAuB;AACzC,iBAAO,EAAE,QAAQ,uBAAuB,QAAQ,KAAK,OAAO;AAAA,QAC9D;AAEA,oBAAY,MAAM;AAClB,oBAAY,KAAK,IAAI;AACrB,oBAAY,aAAa,mBAAmB,KAAK,OAAO;AAExD,eAAO,EAAE,QAAQ,UAAU;AAAA,MAC7B,SAAS,OAAO;AACd,cAAM,UACJ,iBAAiB,QAAQ,MAAM,UAAU;AAC3C,eAAO,EAAE,QAAQ,SAAS,QAAQ;AAAA,MACpC;AAAA,IACF;AAAA,IACA,CAAC,aAAa,WAAW;AAAA,EAC3B;AAEA,QAAM,WAAW;AAAA,IACf,OAAO,SAAyC;AAC9C,YAAM,eAAe,MAAM;AAAA,QACzB,WAAW,CAACA,UAAS;AACnB,sBAAY,MAAM;AAClB,sBAAYA,MAAK,IAAI;AACrB,sBAAY,aAAa,mBAAmBA,MAAK,OAAO;AAAA,QAC1D;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA,CAAC,aAAa,WAAW;AAAA,EAC3B;AAEA,QAAM,SAAS,YAAY,YAA2B;AACpD,QAAI;AACF,YAAM,aAAa,MAAS;AAAA,IAC9B,QAAQ;AAAA,IAER,UAAE;AACA,kBAAY,MAAM;AAClB,aAAO,KAAK,QAAQ;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,aAAa,MAAM,CAAC;AAExB,QAAM,QAA0B;AAAA,IAC9B,OAAO;AAAA,MACL,MAAM,QAAQ;AAAA,MACd,SAAS,WAAW;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,MAAM,SAAS,iBAAiB,WAAW,OAAO,UAAU,MAAM;AAAA,EACrE;AAEA,SAAO,oBAAC,YAAY,UAAZ,EAAqB,OAAe,UAAS;AACvD;AAEO,SAAS,UAA4B;AAC1C,QAAM,UAAU,WAAW,WAAW;AAEtC,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AAEA,SAAO;AACT;","names":["data"]}
1
+ {"version":3,"sources":["../../src/providers/auth.provider.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport {\r\n createContext,\r\n ReactNode,\r\n useCallback,\r\n useContext,\r\n useMemo,\r\n} from \"react\";\r\nimport { useQueryClient } from \"@tanstack/react-query\";\r\nimport {\n useUserQuery,\n useSetUserData,\n useUserValidateSession,\n} from \"../modules/auth/hooks/useUserQuery\";\nimport { useLogin } from \"../modules/auth/hooks/login.hook\";\r\nimport { useRegister } from \"../modules/auth/hooks/register.hook\";\r\nimport { useLogout } from \"../modules/auth/hooks/logout.hook\";\r\nimport {\n AuthState,\n LoginRequest,\n RegisterRequest,\n} from \"../modules/auth/schema\";\n\r\nexport type LoginResult =\n | { result: \"success\" }\n | { result: \"two_factor_required\"; cookie: string }\n | { result: \"error\"; message: string };\nimport { useCurrentAccount, ACCOUNT_QUERY_KEY } from \"../modules/accounts/hooks/current-account.hook\";\nimport { useWhitelabelUrls } from \"./whitelabel.provider\";\n\ninterface AuthContextProps extends AuthState {\n login: (credentials: LoginRequest) => Promise<LoginResult>;\n register: (data: RegisterRequest) => Promise<void>;\n logout: () => Promise<void>;\n}\n\r\nexport const AuthContext = createContext<AuthContextProps | undefined>(\r\n undefined\r\n);\r\n\r\ninterface AuthProviderProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function AuthProvider({ children }: AuthProviderProps) {\r\n const { data: user, isLoading: isQueryLoading } = useUserQuery();\r\n const { data: account, isLoading: isAccountLoading } = useCurrentAccount();\r\n const { isLoading: isSessionLoading } = useUserValidateSession();\r\n\r\n const queryClient = useQueryClient();\n const setUserData = useSetUserData();\n const { accountsUrl, pagesUrl } = useWhitelabelUrls();\n\r\n const { mutateAsync: loginMutate, isPending: isLogging } = useLogin();\n const { mutateAsync: registerMutate, isPending: isRegistering } =\r\n useRegister();\r\n const { mutateAsync: logoutMutate, isPending: isLoggingOut } = useLogout();\r\n\r\n const isAuthenticated = !!user;\r\n const isLoading =\r\n isLogging ||\r\n isRegistering ||\r\n isLoggingOut ||\r\n isQueryLoading ||\r\n isAccountLoading ||\r\n isSessionLoading;\r\n\r\n const login = useCallback(\r\n async (credentials: LoginRequest): Promise<LoginResult> => {\r\n try {\r\n const data = await loginMutate(credentials);\r\n\r\n if (data.result === \"two_factor_required\") {\r\n return { result: \"two_factor_required\", cookie: data.cookie };\r\n }\r\n\r\n queryClient.clear();\r\n setUserData(data.user);\r\n queryClient.setQueryData(ACCOUNT_QUERY_KEY, data.account);\r\n\r\n return { result: \"success\" };\r\n } catch (error) {\r\n const message =\r\n error instanceof Error ? error.message : \"Ocorreu um erro ao fazer login. Tente novamente.\";\r\n return { result: \"error\", message };\r\n }\r\n },\r\n [queryClient, setUserData]\r\n );\r\n\r\n const register = useCallback(\r\n async (data: RegisterRequest): Promise<void> => {\r\n await registerMutate(data, {\r\n onSuccess: (data) => {\r\n queryClient.clear();\r\n setUserData(data.user);\r\n queryClient.setQueryData(ACCOUNT_QUERY_KEY, data.account);\r\n },\r\n });\r\n },\r\n [queryClient, setUserData]\r\n );\r\n\r\n const resolveLogoutRedirect = useCallback(() => {\n if (typeof window === \"undefined\") {\n return \"/login\";\n }\n\n try {\n const currentOrigin = window.location.origin;\n const pagesOrigin = pagesUrl ? new URL(pagesUrl).origin : \"\";\n\n if (pagesOrigin && currentOrigin === pagesOrigin) {\n return accountsUrl || \"/login\";\n }\n } catch {\n // fallback below\n }\n\n return \"/login\";\n }, [accountsUrl, pagesUrl]);\n\n const logout = useCallback(async (): Promise<void> => {\n try {\n await logoutMutate(undefined);\n } catch {\n // cookie já removido no servidor mesmo se a API falhou\n } finally {\n queryClient.clear();\n window.location.assign(resolveLogoutRedirect());\n }\n }, [queryClient, logoutMutate, resolveLogoutRedirect]);\n\r\n const value: AuthContextProps = useMemo(\r\n () => ({\r\n user: user ?? null,\r\n account: account ?? null,\r\n isAuthenticated,\r\n isLoading,\r\n login,\r\n register,\r\n logout,\r\n }),\r\n [user, account, isAuthenticated, isLoading, login, register, logout]\r\n );\r\n\r\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\r\n}\r\n\r\nexport function useAuth(): AuthContextProps {\r\n const context = useContext(AuthContext);\r\n\r\n if (context === undefined) {\r\n throw new Error(\"useAuth deve ser usado dentro de um AuthProvider\");\r\n }\r\n\r\n return context;\r\n}\r\n"],"mappings":"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","names":["data"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greatapps/common",
3
- "version": "1.1.271",
3
+ "version": "1.1.274",
4
4
  "description": "Shared library for GreatApps frontend applications",
5
5
  "main": "./dist/index.mjs",
6
6
  "types": "./src/index.ts",
@@ -15,7 +15,6 @@ export interface AppNavBarProps {
15
15
  onExpandClick?: () => void;
16
16
  menuItems?: ProfileMenuItem[];
17
17
  onNotificationsViewAll?: () => void;
18
- logoutRedirect?: string;
19
18
  }
20
19
 
21
20
  export function AppNavBar({
@@ -26,7 +25,6 @@ export function AppNavBar({
26
25
  onExpandClick,
27
26
  menuItems = [],
28
27
  onNotificationsViewAll,
29
- logoutRedirect,
30
28
  }: AppNavBarProps) {
31
29
  const router = useRouter();
32
30
 
@@ -42,10 +40,7 @@ export function AppNavBar({
42
40
  onExpandClick={onExpandClick}
43
41
  >
44
42
  <NotificationsPopover onViewAll={onNotificationsViewAll} />
45
- <ProfilePopover
46
- menuItems={menuItems}
47
- logoutRedirect={logoutRedirect}
48
- />
43
+ <ProfilePopover menuItems={menuItems} />
49
44
  </NavBar>
50
45
  );
51
46
  }
@@ -1,7 +1,6 @@
1
1
  "use client";
2
2
 
3
3
  import { useState } from "react";
4
- import { useRouter } from "next/navigation";
5
4
  import * as PopoverPrimitive from "@radix-ui/react-popover";
6
5
  import { Popover } from "../ui/overlay/Popover";
7
6
  import { Progress } from "../ui/feedback/Progress";
@@ -25,7 +24,6 @@ export interface ProfilePopoverProps {
25
24
  align?: "start" | "center" | "end";
26
25
  contentClassName?: string;
27
26
  menuItems?: ProfileMenuItem[];
28
- logoutRedirect?: string;
29
27
  }
30
28
 
31
29
  function ProfilePopover({
@@ -33,9 +31,7 @@ function ProfilePopover({
33
31
  align = "start",
34
32
  contentClassName = "absolute bottom-2 left-[26px]",
35
33
  menuItems = [],
36
- logoutRedirect = "/login",
37
34
  }: ProfilePopoverProps) {
38
- const router = useRouter();
39
35
  const { user, logout } = useAuth();
40
36
  const [isLoggingOut, setIsLoggingOut] = useState(false);
41
37
 
@@ -49,9 +45,6 @@ function ProfilePopover({
49
45
  await logout();
50
46
  } finally {
51
47
  setIsLoggingOut(false);
52
- if (logoutRedirect !== "/login") {
53
- router.push(logoutRedirect);
54
- }
55
48
  }
56
49
  };
57
50
 
@@ -2,7 +2,7 @@ import { cookies } from "next/headers";
2
2
 
3
3
  import { api } from "../../../infra/api/client";
4
4
  import { ApiError } from "../../../infra/api/types";
5
- import { findWhitelabel } from "../../whitelabel/actions/find-whitelabel.action";
5
+ import { whitelabelService } from "../../whitelabel/services/whitelabel.service";
6
6
  import {
7
7
  ClientInfo,
8
8
  ForgotPasswordRequest,
@@ -31,6 +31,7 @@ import {
31
31
  VerifyEmailRequest,
32
32
  VerifyEmailResponse,
33
33
  } from "../schema";
34
+ import { findWhitelabel } from "../../../server";
34
35
 
35
36
  const AUTH_COOKIE_NAME = "greatapps";
36
37
  const COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
@@ -44,23 +45,6 @@ const COOKIE_OPTIONS = {
44
45
  };
45
46
 
46
47
  class AuthService {
47
- private async getWhitelabelToken(idWl: number): Promise<string> {
48
- const response = await api.apps.get<{
49
- status: 0 | 1;
50
- data: Array<{ token: string }>;
51
- }>(`/tokens?limit=1&page=1&sort=id:desc`, { whiteLabelId: idWl });
52
-
53
- if (response.status === 0 || !response.data?.[0]?.token) {
54
- throw new ApiError(
55
- "Token do whitelabel não encontrado",
56
- "WL_TOKEN_NOT_FOUND",
57
- 404
58
- );
59
- }
60
-
61
- return response.data[0].token;
62
- }
63
-
64
48
  async login(
65
49
  credentials: LoginRequest,
66
50
  clientInfo: ClientInfo
@@ -68,7 +52,7 @@ class AuthService {
68
52
  let requestConfig: import("../../../infra/api/client").RequestConfig | undefined;
69
53
 
70
54
  if (credentials.id_wl) {
71
- const wlToken = await this.getWhitelabelToken(credentials.id_wl);
55
+ const wlToken = await whitelabelService.getTokenByWhitelabelId(credentials.id_wl);
72
56
  requestConfig = { whiteLabelId: credentials.id_wl, authToken: wlToken };
73
57
  }
74
58
 
@@ -1,13 +1,16 @@
1
-
2
- import greatCache from '@greatapps/cache';
3
- import { ApiError } from '../../../infra/api/types';
4
- import { WhitelabelTokenApiResponse, WhitelabelTokenData } from '../schema';
1
+ import greatCache from "@greatapps/cache";
2
+ import { ApiError } from "../../../infra/api/types";
3
+ import { WhitelabelTokenApiResponse, WhitelabelTokenData } from "../schema";
5
4
 
6
5
  class WhitelabelService {
7
6
  private getApiUrl(): string {
8
7
  const apiUrl = process.env.GAPPS_R3_API_URL;
9
8
  if (!apiUrl) {
10
- throw new ApiError('GAPPS_R3_API_URL not configured', 'CONFIG_ERROR', 500);
9
+ throw new ApiError(
10
+ "GAPPS_R3_API_URL not configured",
11
+ "CONFIG_ERROR",
12
+ 500,
13
+ );
11
14
  }
12
15
  return apiUrl;
13
16
  }
@@ -15,17 +18,21 @@ class WhitelabelService {
15
18
  private getToken(): string {
16
19
  const token = process.env.WHITELABEL_TOKEN_MASTER;
17
20
  if (!token) {
18
- throw new ApiError('WHITELABEL_TOKEN_MASTER not configured', 'CONFIG_ERROR', 500);
21
+ throw new ApiError(
22
+ "WHITELABEL_TOKEN_MASTER not configured",
23
+ "CONFIG_ERROR",
24
+ 500,
25
+ );
19
26
  }
20
27
  return token;
21
28
  }
22
29
 
23
30
  private createCache() {
24
31
  return new greatCache({
25
- service: 'whitelabel-service',
26
- version: '1.0',
27
- domain: 'whitelabel-cache.greatapps.com.br',
28
- ambient: process.env.NODE_ENV || 'development',
32
+ service: "whitelabel-service",
33
+ version: "1.0",
34
+ domain: "whitelabel-cache.greatapps.com.br",
35
+ ambient: process.env.NODE_ENV || "development",
29
36
  });
30
37
  }
31
38
 
@@ -38,28 +45,30 @@ class WhitelabelService {
38
45
  const whitelabelMasterToken = this.getToken();
39
46
  const url = `${apiUrl}/v1/pt-br/1/whitelabel/${hostname}/token`;
40
47
 
41
- console.log('[WhitelabelService] Fetching token for domain', { url });
48
+ console.log("[WhitelabelService] Fetching token for domain", { url });
42
49
 
43
50
  const response = await fetch(url, {
44
- method: 'GET',
51
+ method: "GET",
45
52
  headers: {
46
53
  authorization: whitelabelMasterToken,
47
54
  },
48
55
  });
49
56
 
50
57
  if (!response.ok) {
51
- console.error('[WhitelabelService] Failed to fetch whitelabel token', { response });
58
+ console.error("[WhitelabelService] Failed to fetch whitelabel token", {
59
+ response,
60
+ });
52
61
  throw new ApiError(
53
62
  `Failed to fetch whitelabel token: ${response.status}`,
54
- 'FETCH_ERROR',
55
- response.status
63
+ "FETCH_ERROR",
64
+ response.status,
56
65
  );
57
66
  }
58
67
 
59
68
  const result: WhitelabelTokenApiResponse = await response.json();
60
69
 
61
70
  if (result.status !== 1 || !result.data?.length) {
62
- throw new ApiError('Whitelabel token not found', 'TOKEN_NOT_FOUND', 404);
71
+ throw new ApiError("Whitelabel token not found", "TOKEN_NOT_FOUND", 404);
63
72
  }
64
73
 
65
74
  return result.data[0];
@@ -73,8 +82,8 @@ class WhitelabelService {
73
82
 
74
83
  const cachedData = await cache.select(cacheKey);
75
84
 
76
- if (cachedData.status == 1 && 'data' in cachedData && cachedData.data) {
77
- console.log('[WhitelabelService] Cache hit for domain', { hostname });
85
+ if (cachedData.status == 1 && "data" in cachedData && cachedData.data) {
86
+ console.log("[WhitelabelService] Cache hit for domain", { hostname });
78
87
  return JSON.parse(cachedData.data) as WhitelabelTokenData;
79
88
  }
80
89
 
@@ -85,13 +94,56 @@ class WhitelabelService {
85
94
  return data;
86
95
  }
87
96
 
97
+ async getTokenByWhitelabelId(idWl: number): Promise<string> {
98
+ const apiUrl = this.getApiUrl();
99
+ const masterToken = this.getToken();
100
+ const url = `${apiUrl}/v1/pt-br/${idWl}/tokens?limit=1&page=1&sort=id:desc`;
101
+
102
+ const response = await fetch(url, {
103
+ method: "GET",
104
+ headers: { authorization: masterToken },
105
+ });
106
+
107
+ console.debug("[WhitelabelService] Fetching token by whitelabel ID", {
108
+ url,
109
+ config: {
110
+ method: "GET",
111
+ headers: { authorization: masterToken },
112
+ },
113
+ });
114
+
115
+
116
+
117
+ if (!response.ok) {
118
+ throw new ApiError(
119
+ `Failed to fetch whitelabel token: ${response.status}`,
120
+ "WL_TOKEN_NOT_FOUND",
121
+ response.status,
122
+ );
123
+ }
124
+
125
+ const result: WhitelabelTokenApiResponse = await response.json();
126
+
127
+ if (result.status !== 1 || !result.data?.length) {
128
+ throw new ApiError(
129
+ "Token do whitelabel não encontrado",
130
+ "WL_TOKEN_NOT_FOUND",
131
+ 404,
132
+ );
133
+ }
134
+
135
+ return result.data[0].token;
136
+ }
137
+
88
138
  async revalidateByDomain(hostname: string): Promise<WhitelabelTokenData> {
89
139
  hostname = process.env.WHITELABEL_DOMAIN || hostname;
90
140
 
91
141
  const cache = this.createCache();
92
142
  const cacheKey = this.getCacheKey(hostname);
93
143
 
94
- console.log('[WhitelabelService] Revalidating cache for domain', { hostname });
144
+ console.log("[WhitelabelService] Revalidating cache for domain", {
145
+ hostname,
146
+ });
95
147
 
96
148
  await cache.delete(cacheKey);
97
149
 
@@ -99,7 +151,9 @@ class WhitelabelService {
99
151
 
100
152
  await cache.insert(cacheKey, JSON.stringify(data), 604800);
101
153
 
102
- console.log('[WhitelabelService] Cache revalidated for domain', { hostname });
154
+ console.log("[WhitelabelService] Cache revalidated for domain", {
155
+ hostname,
156
+ });
103
157
 
104
158
  return data;
105
159
  }
@@ -8,32 +8,32 @@ import {
8
8
  useMemo,
9
9
  } from "react";
10
10
  import { useQueryClient } from "@tanstack/react-query";
11
- import {
12
- useUserQuery,
13
- useSetUserData,
14
- useUserValidateSession,
15
- } from "../modules/auth/hooks/useUserQuery";
11
+ import {
12
+ useUserQuery,
13
+ useSetUserData,
14
+ useUserValidateSession,
15
+ } from "../modules/auth/hooks/useUserQuery";
16
16
  import { useLogin } from "../modules/auth/hooks/login.hook";
17
17
  import { useRegister } from "../modules/auth/hooks/register.hook";
18
18
  import { useLogout } from "../modules/auth/hooks/logout.hook";
19
- import {
20
- AuthState,
21
- LoginRequest,
22
- RegisterRequest,
23
- } from "../modules/auth/schema";
24
-
25
- export type LoginResult =
26
- | { result: "success" }
27
- | { result: "two_factor_required"; cookie: string }
28
- | { result: "error"; message: string };
29
- import { useCurrentAccount, ACCOUNT_QUERY_KEY } from "../modules/accounts/hooks/current-account.hook";
30
- import { useRouter } from "next/navigation";
31
-
32
- interface AuthContextProps extends AuthState {
33
- login: (credentials: LoginRequest) => Promise<LoginResult>;
34
- register: (data: RegisterRequest) => Promise<void>;
35
- logout: () => Promise<void>;
36
- }
19
+ import {
20
+ AuthState,
21
+ LoginRequest,
22
+ RegisterRequest,
23
+ } from "../modules/auth/schema";
24
+
25
+ export type LoginResult =
26
+ | { result: "success" }
27
+ | { result: "two_factor_required"; cookie: string }
28
+ | { result: "error"; message: string };
29
+ import { useCurrentAccount, ACCOUNT_QUERY_KEY } from "../modules/accounts/hooks/current-account.hook";
30
+ import { useWhitelabelUrls } from "./whitelabel.provider";
31
+
32
+ interface AuthContextProps extends AuthState {
33
+ login: (credentials: LoginRequest) => Promise<LoginResult>;
34
+ register: (data: RegisterRequest) => Promise<void>;
35
+ logout: () => Promise<void>;
36
+ }
37
37
 
38
38
  export const AuthContext = createContext<AuthContextProps | undefined>(
39
39
  undefined
@@ -48,12 +48,11 @@ export function AuthProvider({ children }: AuthProviderProps) {
48
48
  const { data: account, isLoading: isAccountLoading } = useCurrentAccount();
49
49
  const { isLoading: isSessionLoading } = useUserValidateSession();
50
50
 
51
- const queryClient = useQueryClient();
52
- const setUserData = useSetUserData();
53
-
54
- const router = useRouter();
51
+ const queryClient = useQueryClient();
52
+ const setUserData = useSetUserData();
53
+ const { accountsUrl, pagesUrl } = useWhitelabelUrls();
55
54
 
56
- const { mutateAsync: loginMutate, isPending: isLogging } = useLogin();
55
+ const { mutateAsync: loginMutate, isPending: isLogging } = useLogin();
57
56
  const { mutateAsync: registerMutate, isPending: isRegistering } =
58
57
  useRegister();
59
58
  const { mutateAsync: logoutMutate, isPending: isLoggingOut } = useLogout();
@@ -103,16 +102,35 @@ export function AuthProvider({ children }: AuthProviderProps) {
103
102
  [queryClient, setUserData]
104
103
  );
105
104
 
106
- const logout = useCallback(async (): Promise<void> => {
107
- try {
108
- await logoutMutate(undefined);
109
- } catch {
110
- // cookie já removido no servidor mesmo se a API falhou
111
- } finally {
112
- queryClient.clear();
113
- router.push("/login");
114
- }
115
- }, [queryClient, router]);
105
+ const resolveLogoutRedirect = useCallback(() => {
106
+ if (typeof window === "undefined") {
107
+ return "/login";
108
+ }
109
+
110
+ try {
111
+ const currentOrigin = window.location.origin;
112
+ const pagesOrigin = pagesUrl ? new URL(pagesUrl).origin : "";
113
+
114
+ if (pagesOrigin && currentOrigin === pagesOrigin) {
115
+ return accountsUrl || "/login";
116
+ }
117
+ } catch {
118
+ // fallback below
119
+ }
120
+
121
+ return "/login";
122
+ }, [accountsUrl, pagesUrl]);
123
+
124
+ const logout = useCallback(async (): Promise<void> => {
125
+ try {
126
+ await logoutMutate(undefined);
127
+ } catch {
128
+ // cookie já removido no servidor mesmo se a API falhou
129
+ } finally {
130
+ queryClient.clear();
131
+ window.location.assign(resolveLogoutRedirect());
132
+ }
133
+ }, [queryClient, logoutMutate, resolveLogoutRedirect]);
116
134
 
117
135
  const value: AuthContextProps = useMemo(
118
136
  () => ({