@greatapps/common 1.1.51 → 1.1.53
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.mjs +3 -1
- package/dist/index.mjs.map +1 -1
- package/dist/modules/auth/actions/is-two-factor-pending.action.mjs +9 -0
- package/dist/modules/auth/actions/is-two-factor-pending.action.mjs.map +1 -0
- package/dist/modules/auth/actions/validate-session.action.mjs +2 -2
- package/dist/modules/auth/actions/validate-session.action.mjs.map +1 -1
- package/dist/modules/auth/actions/verify-two-factor.action.mjs +16 -0
- package/dist/modules/auth/actions/verify-two-factor.action.mjs.map +1 -0
- package/dist/modules/auth/hooks/useUserQuery.mjs +27 -1
- package/dist/modules/auth/hooks/useUserQuery.mjs.map +1 -1
- package/dist/modules/auth/services/auth.service.mjs +68 -28
- package/dist/modules/auth/services/auth.service.mjs.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +1 -1
- package/src/modules/auth/actions/is-two-factor-pending.action.ts +7 -0
- package/src/modules/auth/actions/validate-session.action.ts +2 -2
- package/src/modules/auth/actions/verify-two-factor.action.ts +15 -0
- package/src/modules/auth/hooks/useUserQuery.ts +28 -1
- package/src/modules/auth/schema.ts +23 -7
- package/src/modules/auth/services/auth.service.ts +89 -29
package/dist/index.mjs
CHANGED
|
@@ -7,7 +7,7 @@ export * from "./providers/auth.provider";
|
|
|
7
7
|
export * from "./providers/whitelabel.provider";
|
|
8
8
|
import { useListProjectUsers, LIST_PROJECT_USERS_QUERY_KEY, LIST_PROJECT_USERS_BASE_KEY } from "./modules/projects/hooks/list-project-users.hook";
|
|
9
9
|
import { useListAvailableUsers, LIST_AVAILABLE_USERS_QUERY_KEY, LIST_AVAILABLE_USERS_BASE_KEY } from "./modules/projects/hooks/list-available-users.hook";
|
|
10
|
-
import { useUserQuery, useUserValidateSession, useInvalidateUser, useSetUserData, USER_QUERY_KEY } from "./modules/auth/hooks/useUserQuery";
|
|
10
|
+
import { useUserQuery, useUserValidateSession, useInvalidateUser, useSetUserData, useTwoFactorVerify, useTwoFactorPending, USER_QUERY_KEY } from "./modules/auth/hooks/useUserQuery";
|
|
11
11
|
import { useSubscriptions, SUBSCRIPTIONS_QUERY_KEY } from "./modules/subscriptions/hooks/list-subscriptions.hook";
|
|
12
12
|
import { useActiveSubscription } from "./modules/subscriptions/hooks/find-active-subscription.hook";
|
|
13
13
|
import { useIaCredits } from "./modules/ia-credits/hooks/ia-credits.hook";
|
|
@@ -294,6 +294,8 @@ export {
|
|
|
294
294
|
default5 as usePasswordVisibility,
|
|
295
295
|
useSetUserData,
|
|
296
296
|
useSubscriptions,
|
|
297
|
+
useTwoFactorPending,
|
|
298
|
+
useTwoFactorVerify,
|
|
297
299
|
useUpdateAccount,
|
|
298
300
|
useUpdateAccountUser,
|
|
299
301
|
useUpdateAccountUserById,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Types\nexport * from './modules/auth/schema';\nexport * from './modules/users/schema';\nexport * from './modules/whitelabel/schema';\nexport * from './infra/api/types';\n\n// Contexts\nexport * from './providers/query.provider';\nexport * from './providers/auth.provider';\nexport * from './providers/whitelabel.provider';\n\n// Hooks\nexport { useListProjectUsers, LIST_PROJECT_USERS_QUERY_KEY, LIST_PROJECT_USERS_BASE_KEY } from './modules/projects/hooks/list-project-users.hook';\nexport { useListAvailableUsers, LIST_AVAILABLE_USERS_QUERY_KEY, LIST_AVAILABLE_USERS_BASE_KEY } from './modules/projects/hooks/list-available-users.hook';\nexport type { ProjectUser, AccountUser, AddRemoveProjectUsersParams, ListUsersParams, UsersPage } from './modules/projects/types';\nexport { useUserQuery, useUserValidateSession, useInvalidateUser, useSetUserData, USER_QUERY_KEY } from './modules/auth/hooks/useUserQuery';\nexport { useSubscriptions, SUBSCRIPTIONS_QUERY_KEY } from './modules/subscriptions/hooks/list-subscriptions.hook';\nexport { useActiveSubscription } from './modules/subscriptions/hooks/find-active-subscription.hook';\nexport { useIaCredits } from './modules/ia-credits/hooks/ia-credits.hook';\nexport type { IaCreditsSummary, IaCreditOperation } from './modules/ia-credits/types';\nexport type { Subscription, SubscriptionItem, FindSubscriptionsParams } from './modules/subscriptions/types';\nexport { SubscriptionSchema, SubscriptionItemSchema } from './modules/subscriptions/types';\nexport { ADDON_IDS } from './modules/subscriptions/constants/addons.constants';\nexport type { AddonKindEnum } from './modules/subscriptions/constants/addons.constants';\n\n// Providers\nexport { QueryProvider } from './providers/query.provider';\n\n// Middleware\nexport { createAuthMiddleware } from './middlewares/create-auth-middleware';\nexport { createMiddlewareChain } from './middlewares/chain';\nexport { continueChain, stopChain } from './middlewares/types';\nexport type { MiddlewareFunction, MiddlewareConfig, MiddlewareResult } from './middlewares/types';\n\n// Utils\nexport { cn } from './infra/utils/clsx';\nexport { buildQueryParams } from './infra/utils/params';\nexport { parseSchema, parseResult } from './infra/utils/parser';\n\n// Layout\nexport { MainLayout, MainLayoutContent, MainLayoutSpacer, MainLayoutMain } from './components/layouts/MainLayout';\nexport { NavBar } from './components/layouts/NavBar';\nexport type { NavBarProps } from './components/layouts/NavBar';\nexport { AppNavBar } from './components/layouts/AppNavBar';\nexport type { AppNavBarProps } from './components/layouts/AppNavBar';\nexport { AppMobileNavBar } from './components/layouts/AppMobileNavBar';\nexport type { AppMobileNavBarProps } from './components/layouts/AppMobileNavBar';\nexport { SideBarNavigation } from './components/layouts/SideBarNavigation';\nexport { MdSideBarNavigation } from './components/layouts/MdSideBarNavigation';\nexport { NotificationItem } from './components/layouts/NotificationItem';\nexport type { NotificationItemProps } from './components/layouts/NotificationItem';\nexport { NotificationsPopover } from './components/layouts/NotificationsPopover';\nexport type { NotificationsPopoverProps, NotificationData } from './components/layouts/NotificationsPopover';\nexport { UsersSelectorPopover } from './components/layouts/UsersSelectorPopover';\nexport type { UsersSelectorPopoverProps } from './components/layouts/UsersSelectorPopover';\nexport { ProfilePopover } from './components/layouts/ProfilePopover';\nexport type { ProfilePopoverProps, ProfileMenuItem } from './components/layouts/ProfilePopover';\nexport { NavBarItem } from './components/layouts/NavBarItem';\nexport type { NavBarItemProps } from './components/layouts/NavBarItem';\n\n// UI - Buttons\nexport { Button, buttonVariants } from './components/ui/buttons/Button';\nexport { CopyButton } from './components/ui/buttons/CopyButton';\nexport { default as CancelButton } from './components/ui/buttons/CancelButton';\n\n// UI - Data Display\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from './components/ui/data-display/Accordion';\nexport { Badge, badgeVariants } from './components/ui/data-display/Badge';\nexport { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent } from './components/ui/data-display/Card';\nexport { Pagination, PaginationContent, PaginationLink, PaginationItem, PaginationPrevious, PaginationNext, PaginationEllipsis } from './components/ui/data-display/Pagination';\nexport { ScrollArea, ScrollBar } from './components/ui/data-display/ScrollArea';\nexport { Separator } from './components/ui/data-display/Separator';\nexport { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption } from './components/ui/data-display/Table';\nexport { Tabs, TabsList, TabsTrigger, TabsContent } from './components/ui/data-display/Tabs';\nexport { UserAvatar } from './components/ui/data-display/UserAvatar';\nexport type { UserAvatarProps } from './components/ui/data-display/UserAvatar';\n\n// UI - Feedback\nexport { default as CircularProgress } from './components/ui/feedback/CircularProgress';\nexport { default as DefaultCircularProgress } from './components/ui/feedback/DefaultCircularProgress';\nexport { Progress } from './components/ui/feedback/Progress';\nexport { LoadingOverlay } from './components/ui/feedback/LoadingOverlay';\nexport { Toast, toastVariants, toastIconContainerVariants } from './components/ui/feedback/Toast';\nexport type { ToastProps } from './components/ui/feedback/Toast';\n\n// UI - Form\nexport { Calendar, CalendarDayButton } from './components/ui/form/Calendar';\nexport { Checkbox } from './components/ui/form/Checkbox';\nexport { DatePicker } from './components/ui/form/DatePicker';\nexport { DateRangePicker } from './components/ui/form/DateRangePicker';\nexport { Input } from './components/ui/form/Input';\nexport { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } from './components/ui/form/InputOtp';\nexport { RadioGroup, RadioGroupItem } from './components/ui/form/RadioGroup';\nexport { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue } from './components/ui/form/Select';\nexport { Switch } from './components/ui/form/Switch';\nexport { Textarea } from './components/ui/form/Textarea';\n\n// UI - Overlay\nexport { Command, CommandDialog, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandShortcut, CommandSeparator } from './components/ui/overlay/Command';\nexport { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from './components/ui/overlay/Dialog';\nexport { Popover, PopoverTrigger, PopoverContent, PopoverAnchor } from './components/ui/overlay/Popover';\nexport { Sheet, SheetTrigger, SheetClose, SheetContent, SheetHeader, SheetFooter, SheetTitle, SheetDescription } from './components/ui/overlay/Sheet';\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from './components/ui/overlay/Tooltip';\n\n// Store\nexport { useMdSidebarStore } from './store/useMdSidebarStore';\nexport { useModalManager } from './store/useModalManager';\nexport type { ModalData } from './store/useModalManager';\n\n// Enums\nexport { AccountSectionType } from './enums/AccountSectionType';\n\n// Hooks\nexport { default as usePasswordVisibility } from './hooks/usePasswordVisibility';\nexport { default as useCountdownTimer } from './hooks/useCountdownTimer';\nexport { default as useIsMobile } from './hooks/useIsMobile';\n\n// Utils\nexport { formatPhone, formatTimer, formatFullName, formatCPF, formatCardNumber } from './utils/format/masks';\nexport { timezoneService } from './modules/accounts/services/timezone.service';\nexport type { TimezoneOption } from './modules/accounts/services/timezone.service';\nexport { buildLocaleOptions, LANGUAGE_OPTIONS as LOCALE_LANGUAGE_OPTIONS } from './utils/intl/locales';\nexport type { LocaleOption } from './utils/intl/locales';\nexport { copyToClipboard, readFromClipboard } from './utils/browser/clipboard';\n\n// UI - Form (new widgets)\nexport { FormField } from './components/ui/form/FormField';\nexport { SelectField } from './components/ui/form/SelectField';\nexport { ComboboxField } from './components/ui/form/ComboboxField';\nexport type { ComboboxOption } from './components/ui/form/ComboboxField';\nexport { default as PhoneInput } from './components/ui/form/PhoneInput';\nexport { default as SwitchOptionFieldWithIcon } from './components/ui/form/SwitchOptionFieldWithIcon';\nexport { TextAreaField } from './components/ui/form/TextAreaField';\n\n// Account Module - Hooks\nexport {\n useUpdateAccount,\n useUpdateAccountUser,\n useUpdateAccountUserById,\n useDeleteAccountUser,\n useDeleteAccount,\n} from './modules/accounts/hooks/useAccountManagement';\n\n// Account Types\nexport type {\n UpdateAccountRequest,\n UpdateAccountUserRequest,\n ChangePasswordRequest,\n DeleteAccountActionResult,\n DeleteUserActionResult,\n UpdateAccountActionResult,\n UpdateUserActionResult,\n TwoFactorGenerateResult,\n TwoFactorActionResult,\n ContactResetResult,\n} from './modules/accounts/types';\n\nexport { default as AccountModals } from './components/account/AccountModals';\nexport { useAccountModals } from './store/useAccountModals';\nexport type { AccountModalsConfig } from './store/useAccountModals';\n\nexport { ModalManager } from './components/modals/ModalManager';\nexport { Modals } from './components/modals/Modals';\n\nexport { default as TwoFactorAuthModal } from './components/account/TwoFactorAuthModal';\nexport { default as DisableTwoFactorAuthModal } from './components/account/DisableTwoFactorAuthModal';\nexport { default as ConfirmGlobalPreferencesModal } from './components/account/ConfirmGlobalPreferencesModal';\nexport { MyProfileSection } from './components/account/sections/MyProfileSection';\nexport { PreferencesSection } from './components/account/sections/PreferencesSection';\nexport { SecuritySection } from './components/account/sections/SecuritySection';\nexport { ChangePasswordSection } from './components/account/sections/ChangePasswordSection';\nexport { ChangeEmailModal } from './components/account/sections/ChangeEmailModal';\nexport { ChangePhoneModal } from './components/account/sections/ChangePhoneModal';\n\n// Account Constants\nexport {\n GENDER_OPTIONS,\n CURRENCY_OPTIONS,\n TIME_FORMAT_OPTIONS,\n NOTIFICATION_TYPES,\n LANGUAGE_OPTIONS,\n} from './components/account/constants';\n"],"mappings":"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","names":["default","LANGUAGE_OPTIONS"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Types\nexport * from './modules/auth/schema';\nexport * from './modules/users/schema';\nexport * from './modules/whitelabel/schema';\nexport * from './infra/api/types';\n\n// Contexts\nexport * from './providers/query.provider';\nexport * from './providers/auth.provider';\nexport * from './providers/whitelabel.provider';\n\n// Hooks\nexport { useListProjectUsers, LIST_PROJECT_USERS_QUERY_KEY, LIST_PROJECT_USERS_BASE_KEY } from './modules/projects/hooks/list-project-users.hook';\nexport { useListAvailableUsers, LIST_AVAILABLE_USERS_QUERY_KEY, LIST_AVAILABLE_USERS_BASE_KEY } from './modules/projects/hooks/list-available-users.hook';\nexport type { ProjectUser, AccountUser, AddRemoveProjectUsersParams, ListUsersParams, UsersPage } from './modules/projects/types';\nexport { useUserQuery, useUserValidateSession, useInvalidateUser, useSetUserData, useTwoFactorVerify, useTwoFactorPending, USER_QUERY_KEY } from './modules/auth/hooks/useUserQuery';\nexport { useSubscriptions, SUBSCRIPTIONS_QUERY_KEY } from './modules/subscriptions/hooks/list-subscriptions.hook';\nexport { useActiveSubscription } from './modules/subscriptions/hooks/find-active-subscription.hook';\nexport { useIaCredits } from './modules/ia-credits/hooks/ia-credits.hook';\nexport type { IaCreditsSummary, IaCreditOperation } from './modules/ia-credits/types';\nexport type { Subscription, SubscriptionItem, FindSubscriptionsParams } from './modules/subscriptions/types';\nexport { SubscriptionSchema, SubscriptionItemSchema } from './modules/subscriptions/types';\nexport { ADDON_IDS } from './modules/subscriptions/constants/addons.constants';\nexport type { AddonKindEnum } from './modules/subscriptions/constants/addons.constants';\n\n// Providers\nexport { QueryProvider } from './providers/query.provider';\n\n// Middleware\nexport { createAuthMiddleware } from './middlewares/create-auth-middleware';\nexport { createMiddlewareChain } from './middlewares/chain';\nexport { continueChain, stopChain } from './middlewares/types';\nexport type { MiddlewareFunction, MiddlewareConfig, MiddlewareResult } from './middlewares/types';\n\n// Utils\nexport { cn } from './infra/utils/clsx';\nexport { buildQueryParams } from './infra/utils/params';\nexport { parseSchema, parseResult } from './infra/utils/parser';\n\n// Layout\nexport { MainLayout, MainLayoutContent, MainLayoutSpacer, MainLayoutMain } from './components/layouts/MainLayout';\nexport { NavBar } from './components/layouts/NavBar';\nexport type { NavBarProps } from './components/layouts/NavBar';\nexport { AppNavBar } from './components/layouts/AppNavBar';\nexport type { AppNavBarProps } from './components/layouts/AppNavBar';\nexport { AppMobileNavBar } from './components/layouts/AppMobileNavBar';\nexport type { AppMobileNavBarProps } from './components/layouts/AppMobileNavBar';\nexport { SideBarNavigation } from './components/layouts/SideBarNavigation';\nexport { MdSideBarNavigation } from './components/layouts/MdSideBarNavigation';\nexport { NotificationItem } from './components/layouts/NotificationItem';\nexport type { NotificationItemProps } from './components/layouts/NotificationItem';\nexport { NotificationsPopover } from './components/layouts/NotificationsPopover';\nexport type { NotificationsPopoverProps, NotificationData } from './components/layouts/NotificationsPopover';\nexport { UsersSelectorPopover } from './components/layouts/UsersSelectorPopover';\nexport type { UsersSelectorPopoverProps } from './components/layouts/UsersSelectorPopover';\nexport { ProfilePopover } from './components/layouts/ProfilePopover';\nexport type { ProfilePopoverProps, ProfileMenuItem } from './components/layouts/ProfilePopover';\nexport { NavBarItem } from './components/layouts/NavBarItem';\nexport type { NavBarItemProps } from './components/layouts/NavBarItem';\n\n// UI - Buttons\nexport { Button, buttonVariants } from './components/ui/buttons/Button';\nexport { CopyButton } from './components/ui/buttons/CopyButton';\nexport { default as CancelButton } from './components/ui/buttons/CancelButton';\n\n// UI - Data Display\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from './components/ui/data-display/Accordion';\nexport { Badge, badgeVariants } from './components/ui/data-display/Badge';\nexport { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent } from './components/ui/data-display/Card';\nexport { Pagination, PaginationContent, PaginationLink, PaginationItem, PaginationPrevious, PaginationNext, PaginationEllipsis } from './components/ui/data-display/Pagination';\nexport { ScrollArea, ScrollBar } from './components/ui/data-display/ScrollArea';\nexport { Separator } from './components/ui/data-display/Separator';\nexport { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption } from './components/ui/data-display/Table';\nexport { Tabs, TabsList, TabsTrigger, TabsContent } from './components/ui/data-display/Tabs';\nexport { UserAvatar } from './components/ui/data-display/UserAvatar';\nexport type { UserAvatarProps } from './components/ui/data-display/UserAvatar';\n\n// UI - Feedback\nexport { default as CircularProgress } from './components/ui/feedback/CircularProgress';\nexport { default as DefaultCircularProgress } from './components/ui/feedback/DefaultCircularProgress';\nexport { Progress } from './components/ui/feedback/Progress';\nexport { LoadingOverlay } from './components/ui/feedback/LoadingOverlay';\nexport { Toast, toastVariants, toastIconContainerVariants } from './components/ui/feedback/Toast';\nexport type { ToastProps } from './components/ui/feedback/Toast';\n\n// UI - Form\nexport { Calendar, CalendarDayButton } from './components/ui/form/Calendar';\nexport { Checkbox } from './components/ui/form/Checkbox';\nexport { DatePicker } from './components/ui/form/DatePicker';\nexport { DateRangePicker } from './components/ui/form/DateRangePicker';\nexport { Input } from './components/ui/form/Input';\nexport { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } from './components/ui/form/InputOtp';\nexport { RadioGroup, RadioGroupItem } from './components/ui/form/RadioGroup';\nexport { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue } from './components/ui/form/Select';\nexport { Switch } from './components/ui/form/Switch';\nexport { Textarea } from './components/ui/form/Textarea';\n\n// UI - Overlay\nexport { Command, CommandDialog, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandShortcut, CommandSeparator } from './components/ui/overlay/Command';\nexport { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from './components/ui/overlay/Dialog';\nexport { Popover, PopoverTrigger, PopoverContent, PopoverAnchor } from './components/ui/overlay/Popover';\nexport { Sheet, SheetTrigger, SheetClose, SheetContent, SheetHeader, SheetFooter, SheetTitle, SheetDescription } from './components/ui/overlay/Sheet';\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from './components/ui/overlay/Tooltip';\n\n// Store\nexport { useMdSidebarStore } from './store/useMdSidebarStore';\nexport { useModalManager } from './store/useModalManager';\nexport type { ModalData } from './store/useModalManager';\n\n// Enums\nexport { AccountSectionType } from './enums/AccountSectionType';\n\n// Hooks\nexport { default as usePasswordVisibility } from './hooks/usePasswordVisibility';\nexport { default as useCountdownTimer } from './hooks/useCountdownTimer';\nexport { default as useIsMobile } from './hooks/useIsMobile';\n\n// Utils\nexport { formatPhone, formatTimer, formatFullName, formatCPF, formatCardNumber } from './utils/format/masks';\nexport { timezoneService } from './modules/accounts/services/timezone.service';\nexport type { TimezoneOption } from './modules/accounts/services/timezone.service';\nexport { buildLocaleOptions, LANGUAGE_OPTIONS as LOCALE_LANGUAGE_OPTIONS } from './utils/intl/locales';\nexport type { LocaleOption } from './utils/intl/locales';\nexport { copyToClipboard, readFromClipboard } from './utils/browser/clipboard';\n\n// UI - Form (new widgets)\nexport { FormField } from './components/ui/form/FormField';\nexport { SelectField } from './components/ui/form/SelectField';\nexport { ComboboxField } from './components/ui/form/ComboboxField';\nexport type { ComboboxOption } from './components/ui/form/ComboboxField';\nexport { default as PhoneInput } from './components/ui/form/PhoneInput';\nexport { default as SwitchOptionFieldWithIcon } from './components/ui/form/SwitchOptionFieldWithIcon';\nexport { TextAreaField } from './components/ui/form/TextAreaField';\n\n// Account Module - Hooks\nexport {\n useUpdateAccount,\n useUpdateAccountUser,\n useUpdateAccountUserById,\n useDeleteAccountUser,\n useDeleteAccount,\n} from './modules/accounts/hooks/useAccountManagement';\n\n// Account Types\nexport type {\n UpdateAccountRequest,\n UpdateAccountUserRequest,\n ChangePasswordRequest,\n DeleteAccountActionResult,\n DeleteUserActionResult,\n UpdateAccountActionResult,\n UpdateUserActionResult,\n TwoFactorGenerateResult,\n TwoFactorActionResult,\n ContactResetResult,\n} from './modules/accounts/types';\n\nexport { default as AccountModals } from './components/account/AccountModals';\nexport { useAccountModals } from './store/useAccountModals';\nexport type { AccountModalsConfig } from './store/useAccountModals';\n\nexport { ModalManager } from './components/modals/ModalManager';\nexport { Modals } from './components/modals/Modals';\n\nexport { default as TwoFactorAuthModal } from './components/account/TwoFactorAuthModal';\nexport { default as DisableTwoFactorAuthModal } from './components/account/DisableTwoFactorAuthModal';\nexport { default as ConfirmGlobalPreferencesModal } from './components/account/ConfirmGlobalPreferencesModal';\nexport { MyProfileSection } from './components/account/sections/MyProfileSection';\nexport { PreferencesSection } from './components/account/sections/PreferencesSection';\nexport { SecuritySection } from './components/account/sections/SecuritySection';\nexport { ChangePasswordSection } from './components/account/sections/ChangePasswordSection';\nexport { ChangeEmailModal } from './components/account/sections/ChangeEmailModal';\nexport { ChangePhoneModal } from './components/account/sections/ChangePhoneModal';\n\n// Account Constants\nexport {\n GENDER_OPTIONS,\n CURRENCY_OPTIONS,\n TIME_FORMAT_OPTIONS,\n NOTIFICATION_TYPES,\n LANGUAGE_OPTIONS,\n} from './components/account/constants';\n"],"mappings":"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","names":["default","LANGUAGE_OPTIONS"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { authService } from "../services/auth.service";
|
|
3
|
+
async function isTwoFactorPendingAction() {
|
|
4
|
+
return authService.isTwoFactorPending();
|
|
5
|
+
}
|
|
6
|
+
export {
|
|
7
|
+
isTwoFactorPendingAction
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=is-two-factor-pending.action.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/auth/actions/is-two-factor-pending.action.ts"],"sourcesContent":["'use server';\r\n\r\nimport { authService } from '../services/auth.service';\r\n\r\nexport async function isTwoFactorPendingAction(): Promise<boolean> {\r\n return authService.isTwoFactorPending();\r\n}\r\n"],"mappings":";AAEA,SAAS,mBAAmB;AAE5B,eAAsB,2BAA6C;AACjE,SAAO,YAAY,mBAAmB;AACxC;","names":[]}
|
|
@@ -28,14 +28,14 @@ async function validateSessionAction() {
|
|
|
28
28
|
const clientInfo = await getClientInfoFromRequest();
|
|
29
29
|
const isValid = await authService.validateSession(clientInfo);
|
|
30
30
|
if (!isValid) {
|
|
31
|
-
|
|
31
|
+
await authService.removeAuthCookie();
|
|
32
32
|
await redirectToLogin();
|
|
33
33
|
return false;
|
|
34
34
|
}
|
|
35
35
|
return true;
|
|
36
36
|
} catch (error) {
|
|
37
37
|
console.error("[validateSessionAction] Error:", error);
|
|
38
|
-
|
|
38
|
+
await authService.removeAuthCookie();
|
|
39
39
|
await redirectToLogin();
|
|
40
40
|
return false;
|
|
41
41
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/auth/actions/validate-session.action.ts"],"sourcesContent":["'use server';\r\n\r\nimport { redirect } from 'next/navigation';\r\nimport { cookies, headers } from 'next/headers';\r\nimport { authService } from '../services/auth.service';\r\nimport { getClientInfoFromRequest } from '../../../infra/utils/client-info';\r\n\r\nasync function redirectToLogin() {\r\n const h = await headers();\r\n const referer = h.get('referer') || '/';\r\n\r\n if (!referer) {\r\n redirect('/login');\r\n return;\r\n }\r\n\r\n const url = new URL(referer);\r\n\r\n if (['/login', '/register', '/forgot-password'].includes(url.pathname)) {\r\n return;\r\n }\r\n\r\n redirect('/login');\r\n}\r\n\r\nexport async function validateSessionAction(): Promise<boolean> {\r\n if (process.env.DUMMY_AUTH_TOKEN) return true;\r\n\r\n const cookieStore = await cookies();\r\n const cookie = cookieStore.get('greatapps')?.value;\r\n\r\n if (!cookie) {\r\n await redirectToLogin();\r\n return false;\r\n }\r\n\r\n try {\r\n const clientInfo = await getClientInfoFromRequest();\r\n const isValid = await authService.validateSession(clientInfo);\r\n\r\n if (!isValid) {\r\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/auth/actions/validate-session.action.ts"],"sourcesContent":["'use server';\r\n\r\nimport { redirect } from 'next/navigation';\r\nimport { cookies, headers } from 'next/headers';\r\nimport { authService } from '../services/auth.service';\r\nimport { getClientInfoFromRequest } from '../../../infra/utils/client-info';\r\n\r\nasync function redirectToLogin() {\r\n const h = await headers();\r\n const referer = h.get('referer') || '/';\r\n\r\n if (!referer) {\r\n redirect('/login');\r\n return;\r\n }\r\n\r\n const url = new URL(referer);\r\n\r\n if (['/login', '/register', '/forgot-password'].includes(url.pathname)) {\r\n return;\r\n }\r\n\r\n redirect('/login');\r\n}\r\n\r\nexport async function validateSessionAction(): Promise<boolean> {\r\n if (process.env.DUMMY_AUTH_TOKEN) return true;\r\n\r\n const cookieStore = await cookies();\r\n const cookie = cookieStore.get('greatapps')?.value;\r\n\r\n if (!cookie) {\r\n await redirectToLogin();\r\n return false;\r\n }\r\n\r\n try {\r\n const clientInfo = await getClientInfoFromRequest();\r\n const isValid = await authService.validateSession(clientInfo);\r\n\r\n if (!isValid) {\r\n await authService.removeAuthCookie();\r\n await redirectToLogin();\r\n return false;\r\n }\r\n\r\n return true;\r\n } catch (error) {\r\n console.error('[validateSessionAction] Error:', error);\r\n await authService.removeAuthCookie();\r\n await redirectToLogin();\r\n return false;\r\n }\r\n}\r\n"],"mappings":";AAEA,SAAS,gBAAgB;AACzB,SAAS,SAAS,eAAe;AACjC,SAAS,mBAAmB;AAC5B,SAAS,gCAAgC;AAEzC,eAAe,kBAAkB;AAC/B,QAAM,IAAI,MAAM,QAAQ;AACxB,QAAM,UAAU,EAAE,IAAI,SAAS,KAAK;AAEpC,MAAI,CAAC,SAAS;AACZ,aAAS,QAAQ;AACjB;AAAA,EACF;AAEA,QAAM,MAAM,IAAI,IAAI,OAAO;AAE3B,MAAI,CAAC,UAAU,aAAa,kBAAkB,EAAE,SAAS,IAAI,QAAQ,GAAG;AACtE;AAAA,EACF;AAEA,WAAS,QAAQ;AACnB;AAEA,eAAsB,wBAA0C;AAC9D,MAAI,QAAQ,IAAI,iBAAkB,QAAO;AAEzC,QAAM,cAAc,MAAM,QAAQ;AAClC,QAAM,SAAS,YAAY,IAAI,WAAW,GAAG;AAE7C,MAAI,CAAC,QAAQ;AACX,UAAM,gBAAgB;AACtB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,aAAa,MAAM,yBAAyB;AAClD,UAAM,UAAU,MAAM,YAAY,gBAAgB,UAAU;AAE5D,QAAI,CAAC,SAAS;AACZ,YAAM,YAAY,iBAAiB;AACnC,YAAM,gBAAgB;AACtB,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,kCAAkC,KAAK;AACrD,UAAM,YAAY,iBAAiB;AACnC,UAAM,gBAAgB;AACtB,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { authService } from "../services/auth.service";
|
|
3
|
+
import { ApiError } from "../../../infra/api/types";
|
|
4
|
+
import { getClientInfoFromRequest } from "../../../infra/utils/client-info";
|
|
5
|
+
async function verifyTwoFactorAction(code) {
|
|
6
|
+
if (!Number.isInteger(code) || code < 0 || code > 999999) {
|
|
7
|
+
throw new ApiError("C\xF3digo inv\xE1lido", "INVALID_CODE", 400);
|
|
8
|
+
}
|
|
9
|
+
const clientInfo = await getClientInfoFromRequest();
|
|
10
|
+
await authService.verifyTwoFactor(code, clientInfo);
|
|
11
|
+
return { success: true };
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
verifyTwoFactorAction
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=verify-two-factor.action.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/auth/actions/verify-two-factor.action.ts"],"sourcesContent":["'use server';\r\n\r\nimport { authService } from '../services/auth.service';\r\nimport { ApiError } from '../../../infra/api/types';\r\nimport { getClientInfoFromRequest } from '../../../infra/utils/client-info';\r\n\r\nexport async function verifyTwoFactorAction(code: number): Promise<{ success: boolean }> {\r\n if (!Number.isInteger(code) || code < 0 || code > 999999) {\r\n throw new ApiError('Código inválido', 'INVALID_CODE', 400);\r\n }\r\n\r\n const clientInfo = await getClientInfoFromRequest();\r\n await authService.verifyTwoFactor(code, clientInfo);\r\n return { success: true };\r\n}\r\n"],"mappings":";AAEA,SAAS,mBAAmB;AAC5B,SAAS,gBAAgB;AACzB,SAAS,gCAAgC;AAEzC,eAAsB,sBAAsB,MAA6C;AACvF,MAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,QAAQ;AACxD,UAAM,IAAI,SAAS,yBAAmB,gBAAgB,GAAG;AAAA,EAC3D;AAEA,QAAM,aAAa,MAAM,yBAAyB;AAClD,QAAM,YAAY,gBAAgB,MAAM,UAAU;AAClD,SAAO,EAAE,SAAS,KAAK;AACzB;","names":[]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
2
|
+
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
3
3
|
const USER_QUERY_KEY = ["user"];
|
|
4
4
|
async function fetchUser() {
|
|
5
5
|
const { findUserById: getUserDataAction } = await import("../../users/action/find-user-by-id.action");
|
|
@@ -30,6 +30,30 @@ function useUserValidateSession(options) {
|
|
|
30
30
|
refetchOnWindowFocus: true
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
|
+
function useTwoFactorVerify() {
|
|
34
|
+
const queryClient = useQueryClient();
|
|
35
|
+
return useMutation({
|
|
36
|
+
mutationFn: async (code) => {
|
|
37
|
+
const { verifyTwoFactorAction } = await import("../actions/verify-two-factor.action");
|
|
38
|
+
return verifyTwoFactorAction(code);
|
|
39
|
+
},
|
|
40
|
+
onSuccess: () => {
|
|
41
|
+
queryClient.invalidateQueries({ queryKey: USER_QUERY_KEY });
|
|
42
|
+
queryClient.invalidateQueries({ queryKey: ["two-factor-pending"] });
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function useTwoFactorPending() {
|
|
47
|
+
return useQuery({
|
|
48
|
+
queryKey: ["two-factor-pending"],
|
|
49
|
+
queryFn: async () => {
|
|
50
|
+
const { isTwoFactorPendingAction } = await import("../actions/is-two-factor-pending.action");
|
|
51
|
+
return isTwoFactorPendingAction();
|
|
52
|
+
},
|
|
53
|
+
staleTime: 10 * 1e3,
|
|
54
|
+
retry: false
|
|
55
|
+
});
|
|
56
|
+
}
|
|
33
57
|
function useInvalidateUser() {
|
|
34
58
|
const queryClient = useQueryClient();
|
|
35
59
|
return () => queryClient.invalidateQueries({ queryKey: USER_QUERY_KEY });
|
|
@@ -42,6 +66,8 @@ export {
|
|
|
42
66
|
USER_QUERY_KEY,
|
|
43
67
|
useInvalidateUser,
|
|
44
68
|
useSetUserData,
|
|
69
|
+
useTwoFactorPending,
|
|
70
|
+
useTwoFactorVerify,
|
|
45
71
|
useUserQuery,
|
|
46
72
|
useUserValidateSession
|
|
47
73
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/auth/hooks/useUserQuery.ts"],"sourcesContent":["'use client';\r\n\r\nimport { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query';\r\nimport { User } from '../../users/schema';\r\n\r\nexport const USER_QUERY_KEY = ['user'];\r\n\r\nasync function fetchUser(): Promise<User | null> {\r\n const { findUserById: getUserDataAction } = await import('../../users/action/find-user-by-id.action');\r\n const result = await getUserDataAction();\r\n return result.success && result.data ? result.data : null;\r\n}\r\n\r\nasync function validateUserSession(): Promise<boolean> {\r\n const { validateSessionAction } = await import('../actions/validate-session.action');\r\n return await validateSessionAction();\r\n}\r\n\r\nexport function useUserQuery() {\r\n return useQuery({\r\n queryKey: USER_QUERY_KEY,\r\n queryFn: fetchUser,\r\n staleTime: 5 * 60 * 1000,\r\n gcTime: 10 * 60 * 1000,\r\n retry: false,\r\n });\r\n}\r\n\r\nexport function useUserValidateSession(options?: UseQueryOptions) {\r\n return useQuery({\r\n queryKey: ['user-validate-session'],\r\n queryFn: validateUserSession,\r\n retry: false,\r\n staleTime: 5 * 60 * 1000,\r\n ...options,\r\n refetchOnMount: 'always',\r\n refetchOnWindowFocus: true,\r\n });\r\n}\r\n\r\nexport function useInvalidateUser() {\r\n const queryClient = useQueryClient();\r\n return () => queryClient.invalidateQueries({ queryKey: USER_QUERY_KEY });\r\n}\r\n\r\nexport function useSetUserData() {\r\n const queryClient = useQueryClient();\r\n return (user: User | null) => queryClient.setQueryData(USER_QUERY_KEY, user);\r\n}\r\n"],"mappings":";AAEA,SAAS,UAAU,sBAAuC;
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/auth/hooks/useUserQuery.ts"],"sourcesContent":["'use client';\r\n\r\nimport { useMutation, useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query';\r\nimport { User } from '../../users/schema';\r\n\r\nexport const USER_QUERY_KEY = ['user'];\r\n\r\nasync function fetchUser(): Promise<User | null> {\r\n const { findUserById: getUserDataAction } = await import('../../users/action/find-user-by-id.action');\r\n const result = await getUserDataAction();\r\n return result.success && result.data ? result.data : null;\r\n}\r\n\r\nasync function validateUserSession(): Promise<boolean> {\r\n const { validateSessionAction } = await import('../actions/validate-session.action');\r\n return await validateSessionAction();\r\n}\r\n\r\nexport function useUserQuery() {\r\n return useQuery({\r\n queryKey: USER_QUERY_KEY,\r\n queryFn: fetchUser,\r\n staleTime: 5 * 60 * 1000,\r\n gcTime: 10 * 60 * 1000,\r\n retry: false,\r\n });\r\n}\r\n\r\nexport function useUserValidateSession(options?: UseQueryOptions) {\r\n return useQuery({\r\n queryKey: ['user-validate-session'],\r\n queryFn: validateUserSession,\r\n retry: false,\r\n staleTime: 5 * 60 * 1000,\r\n ...options,\r\n refetchOnMount: 'always',\r\n refetchOnWindowFocus: true,\r\n });\r\n}\r\n\r\nexport function useTwoFactorVerify() {\r\n const queryClient = useQueryClient();\r\n\r\n return useMutation({\r\n mutationFn: async (code: number) => {\r\n const { verifyTwoFactorAction } = await import('../actions/verify-two-factor.action');\r\n return verifyTwoFactorAction(code);\r\n },\r\n onSuccess: () => {\r\n queryClient.invalidateQueries({ queryKey: USER_QUERY_KEY });\r\n queryClient.invalidateQueries({ queryKey: ['two-factor-pending'] });\r\n },\r\n });\r\n}\r\n\r\nexport function useTwoFactorPending() {\r\n return useQuery({\r\n queryKey: ['two-factor-pending'],\r\n queryFn: async () => {\r\n const { isTwoFactorPendingAction } = await import('../actions/is-two-factor-pending.action');\r\n return isTwoFactorPendingAction();\r\n },\r\n staleTime: 10 * 1000,\r\n retry: false,\r\n });\r\n}\r\n\r\nexport function useInvalidateUser() {\r\n const queryClient = useQueryClient();\r\n return () => queryClient.invalidateQueries({ queryKey: USER_QUERY_KEY });\r\n}\r\n\r\nexport function useSetUserData() {\r\n const queryClient = useQueryClient();\r\n return (user: User | null) => queryClient.setQueryData(USER_QUERY_KEY, user);\r\n}\r\n"],"mappings":";AAEA,SAAS,aAAa,UAAU,sBAAuC;AAGhE,MAAM,iBAAiB,CAAC,MAAM;AAErC,eAAe,YAAkC;AAC/C,QAAM,EAAE,cAAc,kBAAkB,IAAI,MAAM,OAAO,2CAA2C;AACpG,QAAM,SAAS,MAAM,kBAAkB;AACvC,SAAO,OAAO,WAAW,OAAO,OAAO,OAAO,OAAO;AACvD;AAEA,eAAe,sBAAwC;AACrD,QAAM,EAAE,sBAAsB,IAAI,MAAM,OAAO,oCAAoC;AACnF,SAAO,MAAM,sBAAsB;AACrC;AAEO,SAAS,eAAe;AAC7B,SAAO,SAAS;AAAA,IACd,UAAU;AAAA,IACV,SAAS;AAAA,IACT,WAAW,IAAI,KAAK;AAAA,IACpB,QAAQ,KAAK,KAAK;AAAA,IAClB,OAAO;AAAA,EACT,CAAC;AACH;AAEO,SAAS,uBAAuB,SAA2B;AAChE,SAAO,SAAS;AAAA,IACd,UAAU,CAAC,uBAAuB;AAAA,IAClC,SAAS;AAAA,IACT,OAAO;AAAA,IACP,WAAW,IAAI,KAAK;AAAA,IACpB,GAAG;AAAA,IACH,gBAAgB;AAAA,IAChB,sBAAsB;AAAA,EACxB,CAAC;AACH;AAEO,SAAS,qBAAqB;AACnC,QAAM,cAAc,eAAe;AAEnC,SAAO,YAAY;AAAA,IACjB,YAAY,OAAO,SAAiB;AAClC,YAAM,EAAE,sBAAsB,IAAI,MAAM,OAAO,qCAAqC;AACpF,aAAO,sBAAsB,IAAI;AAAA,IACnC;AAAA,IACA,WAAW,MAAM;AACf,kBAAY,kBAAkB,EAAE,UAAU,eAAe,CAAC;AAC1D,kBAAY,kBAAkB,EAAE,UAAU,CAAC,oBAAoB,EAAE,CAAC;AAAA,IACpE;AAAA,EACF,CAAC;AACH;AAEO,SAAS,sBAAsB;AACpC,SAAO,SAAS;AAAA,IACd,UAAU,CAAC,oBAAoB;AAAA,IAC/B,SAAS,YAAY;AACnB,YAAM,EAAE,yBAAyB,IAAI,MAAM,OAAO,yCAAyC;AAC3F,aAAO,yBAAyB;AAAA,IAClC;AAAA,IACA,WAAW,KAAK;AAAA,IAChB,OAAO;AAAA,EACT,CAAC;AACH;AAEO,SAAS,oBAAoB;AAClC,QAAM,cAAc,eAAe;AACnC,SAAO,MAAM,YAAY,kBAAkB,EAAE,UAAU,eAAe,CAAC;AACzE;AAEO,SAAS,iBAAiB;AAC/B,QAAM,cAAc,eAAe;AACnC,SAAO,CAAC,SAAsB,YAAY,aAAa,gBAAgB,IAAI;AAC7E;","names":[]}
|
|
@@ -2,32 +2,27 @@ import { cookies } from "next/headers";
|
|
|
2
2
|
import { apiClient } from "../../../infra/api/client";
|
|
3
3
|
import { ApiError } from "../../../infra/api/types";
|
|
4
4
|
const AUTH_COOKIE_NAME = "greatapps";
|
|
5
|
+
const PENDING_2FA_COOKIE_NAME = "greatapps_2fa_pending";
|
|
5
6
|
const COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
|
|
6
|
-
|
|
7
|
+
const PENDING_2FA_MAX_AGE = 60 * 10;
|
|
8
|
+
const COOKIE_OPTIONS = {
|
|
9
|
+
httpOnly: true,
|
|
10
|
+
secure: process.env.NODE_ENV === "production",
|
|
11
|
+
sameSite: "lax",
|
|
12
|
+
path: "/",
|
|
13
|
+
domain: process.env.DOMAIN_COOKIE
|
|
14
|
+
};
|
|
15
|
+
async function setPending2FACookie(token) {
|
|
7
16
|
const cookieStore = await cookies();
|
|
8
|
-
cookieStore.set(
|
|
9
|
-
httpOnly: true,
|
|
10
|
-
secure: process.env.NODE_ENV === "production",
|
|
11
|
-
sameSite: "lax",
|
|
12
|
-
maxAge: COOKIE_MAX_AGE,
|
|
13
|
-
path: "/",
|
|
14
|
-
domain: process.env.DOMAIN_COOKIE
|
|
15
|
-
});
|
|
17
|
+
cookieStore.set(PENDING_2FA_COOKIE_NAME, token, { ...COOKIE_OPTIONS, maxAge: PENDING_2FA_MAX_AGE });
|
|
16
18
|
}
|
|
17
|
-
async function
|
|
19
|
+
async function removePending2FACookie() {
|
|
18
20
|
const cookieStore = await cookies();
|
|
19
|
-
cookieStore.delete({
|
|
20
|
-
name: AUTH_COOKIE_NAME,
|
|
21
|
-
path: "/",
|
|
22
|
-
secure: process.env.NODE_ENV === "production",
|
|
23
|
-
sameSite: "lax",
|
|
24
|
-
domain: process.env.DOMAIN_COOKIE
|
|
25
|
-
});
|
|
21
|
+
cookieStore.delete({ name: PENDING_2FA_COOKIE_NAME, ...COOKIE_OPTIONS });
|
|
26
22
|
}
|
|
27
|
-
async function
|
|
28
|
-
if (process.env.DUMMY_AUTH_TOKEN) return process.env.DUMMY_AUTH_TOKEN;
|
|
23
|
+
async function getPending2FACookie() {
|
|
29
24
|
const cookieStore = await cookies();
|
|
30
|
-
return cookieStore.get(
|
|
25
|
+
return cookieStore.get(PENDING_2FA_COOKIE_NAME)?.value;
|
|
31
26
|
}
|
|
32
27
|
class AuthService {
|
|
33
28
|
async login(credentials, clientInfo) {
|
|
@@ -45,15 +40,45 @@ class AuthService {
|
|
|
45
40
|
if (!response.cookie) {
|
|
46
41
|
throw new ApiError("Resposta de autentica\xE7\xE3o inv\xE1lida", "INVALID_RESPONSE", 500);
|
|
47
42
|
}
|
|
48
|
-
|
|
43
|
+
if (response.two_factor_authentication) {
|
|
44
|
+
await setPending2FACookie(response.cookie);
|
|
45
|
+
return { twoFactorRequired: true };
|
|
46
|
+
}
|
|
47
|
+
await this.setAuthCookie(response.cookie);
|
|
49
48
|
return {
|
|
50
49
|
user: {},
|
|
51
|
-
// Placeholder, será preenchido pelo AuthProvider
|
|
52
50
|
accessToken: response.cookie,
|
|
53
51
|
refreshToken: "",
|
|
54
52
|
expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1e3).toISOString()
|
|
55
53
|
};
|
|
56
54
|
}
|
|
55
|
+
async verifyTwoFactor(code, clientInfo) {
|
|
56
|
+
const pendingCookie = await getPending2FACookie();
|
|
57
|
+
if (!pendingCookie) {
|
|
58
|
+
throw new ApiError("Nenhuma autentica\xE7\xE3o 2FA pendente", "NO_PENDING_2FA", 400);
|
|
59
|
+
}
|
|
60
|
+
const payload = {
|
|
61
|
+
location: clientInfo.location,
|
|
62
|
+
ip: clientInfo.ip,
|
|
63
|
+
timezone: clientInfo.timezone,
|
|
64
|
+
agent: clientInfo.agent,
|
|
65
|
+
cookie: pendingCookie,
|
|
66
|
+
code
|
|
67
|
+
};
|
|
68
|
+
const response = await apiClient.post("/auth/code", payload);
|
|
69
|
+
if (response.status === 0) {
|
|
70
|
+
throw new ApiError(response.message || "C\xF3digo 2FA inv\xE1lido", "TWO_FACTOR_FAILED", 401);
|
|
71
|
+
}
|
|
72
|
+
if (!response.cookie) {
|
|
73
|
+
throw new ApiError("Resposta de autentica\xE7\xE3o inv\xE1lida ap\xF3s 2FA", "INVALID_RESPONSE", 500);
|
|
74
|
+
}
|
|
75
|
+
await Promise.all([this.setAuthCookie(response.cookie), removePending2FACookie()]);
|
|
76
|
+
return { success: true };
|
|
77
|
+
}
|
|
78
|
+
async isTwoFactorPending() {
|
|
79
|
+
const pending = await getPending2FACookie();
|
|
80
|
+
return !!pending;
|
|
81
|
+
}
|
|
57
82
|
async register(data) {
|
|
58
83
|
const today = /* @__PURE__ */ new Date();
|
|
59
84
|
const trialEndDate = new Date(today);
|
|
@@ -103,7 +128,7 @@ class AuthService {
|
|
|
103
128
|
};
|
|
104
129
|
}
|
|
105
130
|
async logout(clientInfo) {
|
|
106
|
-
const cookie = await
|
|
131
|
+
const cookie = await this.getToken();
|
|
107
132
|
if (!cookie) {
|
|
108
133
|
throw new ApiError("Usu\xE1rio n\xE3o autenticado", "NOT_AUTHENTICATED", 401);
|
|
109
134
|
}
|
|
@@ -120,8 +145,7 @@ class AuthService {
|
|
|
120
145
|
throw new ApiError(response.message || "Erro ao realizar logout", "LOGOUT_FAILED", 400);
|
|
121
146
|
}
|
|
122
147
|
} finally {
|
|
123
|
-
|
|
124
|
-
await removeAuthCookie();
|
|
148
|
+
await Promise.all([this.removeAuthCookie(), removePending2FACookie()]);
|
|
125
149
|
}
|
|
126
150
|
return {
|
|
127
151
|
success: true
|
|
@@ -140,7 +164,7 @@ class AuthService {
|
|
|
140
164
|
throw new ApiError("Reenvio de verifica\xE7\xE3o n\xE3o implementado", "NOT_IMPLEMENTED", 501);
|
|
141
165
|
}
|
|
142
166
|
async validateSession(clientInfo) {
|
|
143
|
-
const cookie = await
|
|
167
|
+
const cookie = await this.getToken();
|
|
144
168
|
if (!cookie) {
|
|
145
169
|
return false;
|
|
146
170
|
}
|
|
@@ -160,11 +184,27 @@ class AuthService {
|
|
|
160
184
|
}
|
|
161
185
|
}
|
|
162
186
|
async isAuthenticated() {
|
|
163
|
-
const token = await
|
|
187
|
+
const token = await this.getToken();
|
|
164
188
|
return !!token;
|
|
165
189
|
}
|
|
166
190
|
async getToken() {
|
|
167
|
-
|
|
191
|
+
if (process.env.DUMMY_AUTH_TOKEN) return process.env.DUMMY_AUTH_TOKEN;
|
|
192
|
+
const cookieStore = await cookies();
|
|
193
|
+
return cookieStore.get(AUTH_COOKIE_NAME)?.value;
|
|
194
|
+
}
|
|
195
|
+
async setAuthCookie(token) {
|
|
196
|
+
const cookieStore = await cookies();
|
|
197
|
+
cookieStore.set(AUTH_COOKIE_NAME, token, {
|
|
198
|
+
...COOKIE_OPTIONS,
|
|
199
|
+
maxAge: COOKIE_MAX_AGE
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
async removeAuthCookie() {
|
|
203
|
+
const cookieStore = await cookies();
|
|
204
|
+
cookieStore.delete({
|
|
205
|
+
name: AUTH_COOKIE_NAME,
|
|
206
|
+
...COOKIE_OPTIONS
|
|
207
|
+
});
|
|
168
208
|
}
|
|
169
209
|
}
|
|
170
210
|
const authService = new AuthService();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/auth/services/auth.service.ts"],"sourcesContent":["\r\nimport { cookies } from 'next/headers';\r\n\r\nimport { apiClient } from '../../../infra/api/client';\r\nimport { ApiError } from '../../../infra/api/types';\r\nimport { User } from '../../users/schema';\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 SessionKeepRequest,\r\n SessionKeepResponse,\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\nasync function setAuthCookie(token: string): Promise<void> {\r\n const cookieStore = await cookies();\r\n cookieStore.set(AUTH_COOKIE_NAME, token, {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'lax',\r\n maxAge: COOKIE_MAX_AGE,\r\n path: '/',\r\n domain: process.env.DOMAIN_COOKIE\r\n });\r\n}\r\n\r\nasync function removeAuthCookie(): Promise<void> {\r\n const cookieStore = await cookies();\r\n cookieStore.delete({\r\n name: AUTH_COOKIE_NAME,\r\n path: \"/\",\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'lax',\r\n domain: process.env.DOMAIN_COOKIE,\r\n });\r\n}\r\n\r\nasync function getAuthCookie(): 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\nclass AuthService {\r\n async login(credentials: LoginRequest, clientInfo: ClientInfo): Promise<LoginResponse> {\r\n const response = await apiClient.post<LoginApiResponse>('/auth/login', {\r\n email: credentials.email,\r\n password: credentials.password,\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n });\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(response.message || 'E-mail ou senha incorretos', 'LOGIN_FAILED', 401);\r\n }\r\n\r\n if (!response.cookie) {\r\n throw new ApiError('Resposta de autenticação inválida', 'INVALID_RESPONSE', 500);\r\n }\r\n\r\n await setAuthCookie(response.cookie);\r\n\r\n // O usuário completo será carregado pelo AuthProvider via getUserDataAction\r\n return {\r\n user: {} as User, // Placeholder, será preenchido pelo AuthProvider\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 register(data: RegisterRequest): 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 payload: RegisterApiRequest = {\r\n name: data.accountName,\r\n bussiness_type: data.businessType,\r\n language: 'pt-br',\r\n timezone: 'America/Sao_Paulo',\r\n currency: 'BRL',\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: '',\r\n id_plan: 1,\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 apiClient.post<RegisterApiResponse>('/accounts', payload);\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(response.message || 'Erro ao criar conta', 'REGISTER_FAILED', 400);\r\n }\r\n\r\n if (!response.data || response.data.length === 0) {\r\n throw new ApiError('Resposta de registro inválida', 'INVALID_RESPONSE', 500);\r\n }\r\n\r\n const accountData = response.data[0];\r\n\r\n // Retornar sem token pois o registro não retorna cookie diretamente\r\n // O usuário precisará fazer login após o registro\r\n // O usuário completo será carregado após o login\r\n return {\r\n user: {} as User, // Placeholder, será preenchido após login\r\n accessToken: '',\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 getAuthCookie();\r\n\r\n if (!cookie) {\r\n throw new ApiError('Usuário não autenticado', 'NOT_AUTHENTICATED', 401);\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 apiClient.post<LogoutApiResponse>('/auth/logout', payload);\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(response.message || 'Erro ao realizar logout', 'LOGOUT_FAILED', 400);\r\n }\r\n } finally {\r\n console.log('[AuthService] Logout - removendo cookie localmente');\r\n await removeAuthCookie();\r\n }\r\n\r\n return {\r\n success: true,\r\n };\r\n }\r\n\r\n async forgotPassword(_data: ForgotPasswordRequest): Promise<ForgotPasswordResponse> {\r\n throw new ApiError('Recuperação de senha não implementada', 'NOT_IMPLEMENTED', 501);\r\n }\r\n\r\n async resetPassword(_data: ResetPasswordRequest): Promise<ResetPasswordResponse> {\r\n throw new ApiError('Redefinição de senha não implementada', 'NOT_IMPLEMENTED', 501);\r\n }\r\n\r\n async verifyEmail(_data: VerifyEmailRequest): Promise<VerifyEmailResponse> {\r\n throw new ApiError('Verificação de email não implementada', 'NOT_IMPLEMENTED', 501);\r\n }\r\n\r\n async resendVerification(_data: ResendVerificationRequest): Promise<ResendVerificationResponse> {\r\n throw new ApiError('Reenvio de verificação não implementado', 'NOT_IMPLEMENTED', 501);\r\n }\r\n\r\n async validateSession(clientInfo: ClientInfo): Promise<boolean> {\r\n const cookie = await getAuthCookie();\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 apiClient.post<SessionKeepResponse>('/auth/keep', payload);\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 getAuthCookie();\r\n return !!token;\r\n }\r\n\r\n async getToken(): Promise<string | undefined> {\r\n return getAuthCookie();\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":["\r\nimport { cookies } from 'next/headers';\r\n\r\nimport { apiClient } from '../../../infra/api/client';\r\nimport { ApiError } from '../../../infra/api/types';\r\nimport { User } from '../../users/schema';\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 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 PENDING_2FA_COOKIE_NAME = 'greatapps_2fa_pending';\r\nconst COOKIE_MAX_AGE = 60 * 60 * 24 * 30;\r\nconst PENDING_2FA_MAX_AGE = 60 * 10; // 10 minutos para completar o 2FA\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\nasync function setPending2FACookie(token: string): Promise<void> {\r\n const cookieStore = await cookies();\r\n cookieStore.set(PENDING_2FA_COOKIE_NAME, token, { ...COOKIE_OPTIONS, maxAge: PENDING_2FA_MAX_AGE });\r\n}\r\n\r\nasync function removePending2FACookie(): Promise<void> {\r\n const cookieStore = await cookies();\r\n cookieStore.delete({ name: PENDING_2FA_COOKIE_NAME, ...COOKIE_OPTIONS });\r\n}\r\n\r\nasync function getPending2FACookie(): Promise<string | undefined> {\r\n const cookieStore = await cookies();\r\n return cookieStore.get(PENDING_2FA_COOKIE_NAME)?.value;\r\n}\r\n\r\nclass AuthService {\r\n async login(credentials: LoginRequest, clientInfo: ClientInfo): Promise<LoginResponse> {\r\n const response = await apiClient.post<LoginApiResponse>('/auth/login', {\r\n email: credentials.email,\r\n password: credentials.password,\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n });\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(response.message || 'E-mail ou senha incorretos', 'LOGIN_FAILED', 401);\r\n }\r\n\r\n if (!response.cookie) {\r\n throw new ApiError('Resposta de autenticação inválida', 'INVALID_RESPONSE', 500);\r\n }\r\n\r\n if (response.two_factor_authentication) {\r\n // Armazena o cookie temporariamente até o 2FA ser concluído.\r\n // O cookie principal NÃO é setado aqui para evitar falso positivo em isAuthenticated().\r\n await setPending2FACookie(response.cookie);\r\n return { twoFactorRequired: true };\r\n }\r\n\r\n await this.setAuthCookie(response.cookie);\r\n\r\n return {\r\n user: {} as User,\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(code: number, clientInfo: ClientInfo): Promise<TwoFactorResponse> {\r\n const pendingCookie = await getPending2FACookie();\r\n\r\n if (!pendingCookie) {\r\n throw new ApiError('Nenhuma autenticação 2FA pendente', 'NO_PENDING_2FA', 400);\r\n }\r\n\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: pendingCookie,\r\n code,\r\n };\r\n\r\n const response = await apiClient.post<TwoFactorApiResponse>('/auth/code', payload);\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(response.message || 'Código 2FA inválido', 'TWO_FACTOR_FAILED', 401);\r\n }\r\n\r\n if (!response.cookie) {\r\n throw new ApiError('Resposta de autenticação inválida após 2FA', 'INVALID_RESPONSE', 500);\r\n }\r\n\r\n await Promise.all([this.setAuthCookie(response.cookie), removePending2FACookie()]);\r\n\r\n return { success: true };\r\n }\r\n\r\n async isTwoFactorPending(): Promise<boolean> {\r\n const pending = await getPending2FACookie();\r\n return !!pending;\r\n }\r\n\r\n async register(data: RegisterRequest): 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 payload: RegisterApiRequest = {\r\n name: data.accountName,\r\n bussiness_type: data.businessType,\r\n language: 'pt-br',\r\n timezone: 'America/Sao_Paulo',\r\n currency: 'BRL',\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: '',\r\n id_plan: 1,\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 apiClient.post<RegisterApiResponse>('/accounts', payload);\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(response.message || 'Erro ao criar conta', 'REGISTER_FAILED', 400);\r\n }\r\n\r\n if (!response.data || response.data.length === 0) {\r\n throw new ApiError('Resposta de registro inválida', 'INVALID_RESPONSE', 500);\r\n }\r\n\r\n const accountData = response.data[0];\r\n\r\n // Retornar sem token pois o registro não retorna cookie diretamente\r\n // O usuário precisará fazer login após o registro\r\n // O usuário completo será carregado após o login\r\n return {\r\n user: {} as User, // Placeholder, será preenchido após login\r\n accessToken: '',\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('Usuário não autenticado', 'NOT_AUTHENTICATED', 401);\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 apiClient.post<LogoutApiResponse>('/auth/logout', payload);\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(response.message || 'Erro ao realizar logout', 'LOGOUT_FAILED', 400);\r\n }\r\n } finally {\r\n await Promise.all([this.removeAuthCookie(), removePending2FACookie()]);\r\n }\r\n\r\n return {\r\n success: true,\r\n };\r\n }\r\n\r\n async forgotPassword(_data: ForgotPasswordRequest): Promise<ForgotPasswordResponse> {\r\n throw new ApiError('Recuperação de senha não implementada', 'NOT_IMPLEMENTED', 501);\r\n }\r\n\r\n async resetPassword(_data: ResetPasswordRequest): Promise<ResetPasswordResponse> {\r\n throw new ApiError('Redefinição de senha não implementada', 'NOT_IMPLEMENTED', 501);\r\n }\r\n\r\n async verifyEmail(_data: VerifyEmailRequest): Promise<VerifyEmailResponse> {\r\n throw new ApiError('Verificação de email não implementada', 'NOT_IMPLEMENTED', 501);\r\n }\r\n\r\n async resendVerification(_data: ResendVerificationRequest): Promise<ResendVerificationResponse> {\r\n throw new ApiError('Reenvio de verificação não implementado', 'NOT_IMPLEMENTED', 501);\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 apiClient.post<SessionKeepResponse>('/auth/keep', payload);\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\r\n private async setAuthCookie(token: string): Promise<void> {\r\n const cookieStore = await cookies();\r\n cookieStore.set(AUTH_COOKIE_NAME, token, {\r\n ...COOKIE_OPTIONS,\r\n maxAge: COOKIE_MAX_AGE,\r\n });\r\n }\r\n\r\n\r\n async removeAuthCookie(): Promise<void> {\r\n const cookieStore = await cookies();\r\n cookieStore.delete({\r\n name: AUTH_COOKIE_NAME,\r\n ...COOKIE_OPTIONS,\r\n });\r\n }\r\n}\r\n\r\nexport const authService = new AuthService();\r\n\r\nexport type { ClientInfo, GeoLocation };\r\n"],"mappings":"AACA,SAAS,eAAe;AAExB,SAAS,iBAAiB;AAC1B,SAAS,gBAAgB;AA8BzB,MAAM,mBAAmB;AACzB,MAAM,0BAA0B;AAChC,MAAM,iBAAiB,KAAK,KAAK,KAAK;AACtC,MAAM,sBAAsB,KAAK;AAEjC,MAAM,iBAAiB;AAAA,EACrB,UAAU;AAAA,EACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,EACjC,UAAU;AAAA,EACV,MAAM;AAAA,EACN,QAAQ,QAAQ,IAAI;AACtB;AAEA,eAAe,oBAAoB,OAA8B;AAC/D,QAAM,cAAc,MAAM,QAAQ;AAClC,cAAY,IAAI,yBAAyB,OAAO,EAAE,GAAG,gBAAgB,QAAQ,oBAAoB,CAAC;AACpG;AAEA,eAAe,yBAAwC;AACrD,QAAM,cAAc,MAAM,QAAQ;AAClC,cAAY,OAAO,EAAE,MAAM,yBAAyB,GAAG,eAAe,CAAC;AACzE;AAEA,eAAe,sBAAmD;AAChE,QAAM,cAAc,MAAM,QAAQ;AAClC,SAAO,YAAY,IAAI,uBAAuB,GAAG;AACnD;AAEA,MAAM,YAAY;AAAA,EAChB,MAAM,MAAM,aAA2B,YAAgD;AACrF,UAAM,WAAW,MAAM,UAAU,KAAuB,eAAe;AAAA,MACrE,OAAO,YAAY;AAAA,MACnB,UAAU,YAAY;AAAA,MACtB,UAAU,WAAW;AAAA,MACrB,IAAI,WAAW;AAAA,MACf,UAAU,WAAW;AAAA,MACrB,OAAO,WAAW;AAAA,IACpB,CAAC;AAED,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI,SAAS,SAAS,WAAW,8BAA8B,gBAAgB,GAAG;AAAA,IAC1F;AAEA,QAAI,CAAC,SAAS,QAAQ;AACpB,YAAM,IAAI,SAAS,8CAAqC,oBAAoB,GAAG;AAAA,IACjF;AAEA,QAAI,SAAS,2BAA2B;AAGtC,YAAM,oBAAoB,SAAS,MAAM;AACzC,aAAO,EAAE,mBAAmB,KAAK;AAAA,IACnC;AAEA,UAAM,KAAK,cAAc,SAAS,MAAM;AAExC,WAAO;AAAA,MACL,MAAM,CAAC;AAAA,MACP,aAAa,SAAS;AAAA,MACtB,cAAc;AAAA,MACd,WAAW,IAAI,KAAK,KAAK,IAAI,IAAI,iBAAiB,GAAI,EAAE,YAAY;AAAA,IACtE;AAAA,EACF;AAAA,EAEA,MAAM,gBAAgB,MAAc,YAAoD;AACtF,UAAM,gBAAgB,MAAM,oBAAoB;AAEhD,QAAI,CAAC,eAAe;AAClB,YAAM,IAAI,SAAS,2CAAqC,kBAAkB,GAAG;AAAA,IAC/E;AAEA,UAAM,UAA4B;AAAA,MAChC,UAAU,WAAW;AAAA,MACrB,IAAI,WAAW;AAAA,MACf,UAAU,WAAW;AAAA,MACrB,OAAO,WAAW;AAAA,MAClB,QAAQ;AAAA,MACR;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,UAAU,KAA2B,cAAc,OAAO;AAEjF,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI,SAAS,SAAS,WAAW,6BAAuB,qBAAqB,GAAG;AAAA,IACxF;AAEA,QAAI,CAAC,SAAS,QAAQ;AACpB,YAAM,IAAI,SAAS,0DAA8C,oBAAoB,GAAG;AAAA,IAC1F;AAEA,UAAM,QAAQ,IAAI,CAAC,KAAK,cAAc,SAAS,MAAM,GAAG,uBAAuB,CAAC,CAAC;AAEjF,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB;AAAA,EAEA,MAAM,qBAAuC;AAC3C,UAAM,UAAU,MAAM,oBAAoB;AAC1C,WAAO,CAAC,CAAC;AAAA,EACX;AAAA,EAEA,MAAM,SAAS,MAAkD;AAC/D,UAAM,QAAQ,oBAAI,KAAK;AACvB,UAAM,eAAe,IAAI,KAAK,KAAK;AACnC,iBAAa,QAAQ,MAAM,QAAQ,IAAI,CAAC;AAExC,UAAM,UAA8B;AAAA,MAClC,MAAM,KAAK;AAAA,MACX,gBAAgB,KAAK;AAAA,MACrB,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,MAAM;AAAA,QACJ,QAAQ;AAAA,QACR,MAAM,KAAK;AAAA,QACX,WAAW,KAAK,YAAY;AAAA,QAC5B,IAAI,KAAK,MAAM;AAAA,QACf,KAAK,KAAK,OAAO;AAAA,QACjB,QAAQ,KAAK;AAAA,QACb,OAAO,KAAK;AAAA,QACZ,OAAO,KAAK;AAAA,QACZ,UAAU,KAAK;AAAA,QACf,SAAS;AAAA,QACT,UAAU;AAAA,MACZ;AAAA,MACA,cAAc;AAAA,QACZ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAS;AAAA,QACT,UAAU,aAAa,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,QACjD,YAAY;AAAA,MACd;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,UAAU,KAA0B,aAAa,OAAO;AAE/E,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI,SAAS,SAAS,WAAW,uBAAuB,mBAAmB,GAAG;AAAA,IACtF;AAEA,QAAI,CAAC,SAAS,QAAQ,SAAS,KAAK,WAAW,GAAG;AAChD,YAAM,IAAI,SAAS,oCAAiC,oBAAoB,GAAG;AAAA,IAC7E;AAEA,UAAM,cAAc,SAAS,KAAK,CAAC;AAKnC,WAAO;AAAA,MACL,MAAM,CAAC;AAAA;AAAA,MACP,aAAa;AAAA,MACb,cAAc;AAAA,MACd,WAAW,IAAI,KAAK,KAAK,IAAI,IAAI,iBAAiB,GAAI,EAAE,YAAY;AAAA,MACpE,2BAA2B,CAAC,YAAY;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,YAAiD;AAC5D,UAAM,SAAS,MAAM,KAAK,SAAS;AAEnC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,SAAS,iCAA2B,qBAAqB,GAAG;AAAA,IACxE;AAEA,UAAM,UAAyB;AAAA,MAC7B,UAAU,WAAW;AAAA,MACrB,IAAI,WAAW;AAAA,MACf,UAAU,WAAW;AAAA,MACrB,OAAO,WAAW;AAAA,MAClB;AAAA,IACF;AAEA,QAAI;AACF,YAAM,WAAW,MAAM,UAAU,KAAwB,gBAAgB,OAAO;AAEhF,UAAI,SAAS,WAAW,GAAG;AACzB,cAAM,IAAI,SAAS,SAAS,WAAW,2BAA2B,iBAAiB,GAAG;AAAA,MACxF;AAAA,IACF,UAAE;AACA,YAAM,QAAQ,IAAI,CAAC,KAAK,iBAAiB,GAAG,uBAAuB,CAAC,CAAC;AAAA,IACvE;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EAEA,MAAM,eAAe,OAA+D;AAClF,UAAM,IAAI,SAAS,kDAAyC,mBAAmB,GAAG;AAAA,EACpF;AAAA,EAEA,MAAM,cAAc,OAA6D;AAC/E,UAAM,IAAI,SAAS,kDAAyC,mBAAmB,GAAG;AAAA,EACpF;AAAA,EAEA,MAAM,YAAY,OAAyD;AACzE,UAAM,IAAI,SAAS,kDAAyC,mBAAmB,GAAG;AAAA,EACpF;AAAA,EAEA,MAAM,mBAAmB,OAAuE;AAC9F,UAAM,IAAI,SAAS,oDAA2C,mBAAmB,GAAG;AAAA,EACtF;AAAA,EAEA,MAAM,gBAAgB,YAA0C;AAC9D,UAAM,SAAS,MAAM,KAAK,SAAS;AAEnC,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,IACT;AAEA,QAAI;AACF,YAAM,UAA8B;AAAA,QAClC,UAAU,WAAW;AAAA,QACrB,IAAI,WAAW;AAAA,QACf,UAAU,WAAW;AAAA,QACrB,OAAO,WAAW;AAAA,QAClB;AAAA,MACF;AAEA,YAAM,WAAW,MAAM,UAAU,KAA0B,cAAc,OAAO;AAEhF,aAAO,SAAS,WAAW;AAAA,IAC7B,SAAS,OAAO;AACd,cAAQ,MAAM,uCAAuC,KAAK;AAC1D,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,kBAAoC;AACxC,UAAM,QAAQ,MAAM,KAAK,SAAS;AAClC,WAAO,CAAC,CAAC;AAAA,EACX;AAAA,EAEA,MAAM,WAAwC;AAC5C,QAAI,QAAQ,IAAI,iBAAkB,QAAO,QAAQ,IAAI;AACrD,UAAM,cAAc,MAAM,QAAQ;AAClC,WAAO,YAAY,IAAI,gBAAgB,GAAG;AAAA,EAC5C;AAAA,EAGA,MAAc,cAAc,OAA8B;AACxD,UAAM,cAAc,MAAM,QAAQ;AAClC,gBAAY,IAAI,kBAAkB,OAAO;AAAA,MACvC,GAAG;AAAA,MACH,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAAA,EAGA,MAAM,mBAAkC;AACtC,UAAM,cAAc,MAAM,QAAQ;AAClC,gBAAY,OAAO;AAAA,MACjB,MAAM;AAAA,MACN,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AACF;AAEO,MAAM,cAAc,IAAI,YAAY;","names":[]}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -13,7 +13,7 @@ export * from './providers/whitelabel.provider';
|
|
|
13
13
|
export { useListProjectUsers, LIST_PROJECT_USERS_QUERY_KEY, LIST_PROJECT_USERS_BASE_KEY } from './modules/projects/hooks/list-project-users.hook';
|
|
14
14
|
export { useListAvailableUsers, LIST_AVAILABLE_USERS_QUERY_KEY, LIST_AVAILABLE_USERS_BASE_KEY } from './modules/projects/hooks/list-available-users.hook';
|
|
15
15
|
export type { ProjectUser, AccountUser, AddRemoveProjectUsersParams, ListUsersParams, UsersPage } from './modules/projects/types';
|
|
16
|
-
export { useUserQuery, useUserValidateSession, useInvalidateUser, useSetUserData, USER_QUERY_KEY } from './modules/auth/hooks/useUserQuery';
|
|
16
|
+
export { useUserQuery, useUserValidateSession, useInvalidateUser, useSetUserData, useTwoFactorVerify, useTwoFactorPending, USER_QUERY_KEY } from './modules/auth/hooks/useUserQuery';
|
|
17
17
|
export { useSubscriptions, SUBSCRIPTIONS_QUERY_KEY } from './modules/subscriptions/hooks/list-subscriptions.hook';
|
|
18
18
|
export { useActiveSubscription } from './modules/subscriptions/hooks/find-active-subscription.hook';
|
|
19
19
|
export { useIaCredits } from './modules/ia-credits/hooks/ia-credits.hook';
|
|
@@ -39,7 +39,7 @@ export async function validateSessionAction(): Promise<boolean> {
|
|
|
39
39
|
const isValid = await authService.validateSession(clientInfo);
|
|
40
40
|
|
|
41
41
|
if (!isValid) {
|
|
42
|
-
|
|
42
|
+
await authService.removeAuthCookie();
|
|
43
43
|
await redirectToLogin();
|
|
44
44
|
return false;
|
|
45
45
|
}
|
|
@@ -47,7 +47,7 @@ export async function validateSessionAction(): Promise<boolean> {
|
|
|
47
47
|
return true;
|
|
48
48
|
} catch (error) {
|
|
49
49
|
console.error('[validateSessionAction] Error:', error);
|
|
50
|
-
|
|
50
|
+
await authService.removeAuthCookie();
|
|
51
51
|
await redirectToLogin();
|
|
52
52
|
return false;
|
|
53
53
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { authService } from '../services/auth.service';
|
|
4
|
+
import { ApiError } from '../../../infra/api/types';
|
|
5
|
+
import { getClientInfoFromRequest } from '../../../infra/utils/client-info';
|
|
6
|
+
|
|
7
|
+
export async function verifyTwoFactorAction(code: number): Promise<{ success: boolean }> {
|
|
8
|
+
if (!Number.isInteger(code) || code < 0 || code > 999999) {
|
|
9
|
+
throw new ApiError('Código inválido', 'INVALID_CODE', 400);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const clientInfo = await getClientInfoFromRequest();
|
|
13
|
+
await authService.verifyTwoFactor(code, clientInfo);
|
|
14
|
+
return { success: true };
|
|
15
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query';
|
|
3
|
+
import { useMutation, useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query';
|
|
4
4
|
import { User } from '../../users/schema';
|
|
5
5
|
|
|
6
6
|
export const USER_QUERY_KEY = ['user'];
|
|
@@ -38,6 +38,33 @@ export function useUserValidateSession(options?: UseQueryOptions) {
|
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
export function useTwoFactorVerify() {
|
|
42
|
+
const queryClient = useQueryClient();
|
|
43
|
+
|
|
44
|
+
return useMutation({
|
|
45
|
+
mutationFn: async (code: number) => {
|
|
46
|
+
const { verifyTwoFactorAction } = await import('../actions/verify-two-factor.action');
|
|
47
|
+
return verifyTwoFactorAction(code);
|
|
48
|
+
},
|
|
49
|
+
onSuccess: () => {
|
|
50
|
+
queryClient.invalidateQueries({ queryKey: USER_QUERY_KEY });
|
|
51
|
+
queryClient.invalidateQueries({ queryKey: ['two-factor-pending'] });
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function useTwoFactorPending() {
|
|
57
|
+
return useQuery({
|
|
58
|
+
queryKey: ['two-factor-pending'],
|
|
59
|
+
queryFn: async () => {
|
|
60
|
+
const { isTwoFactorPendingAction } = await import('../actions/is-two-factor-pending.action');
|
|
61
|
+
return isTwoFactorPendingAction();
|
|
62
|
+
},
|
|
63
|
+
staleTime: 10 * 1000,
|
|
64
|
+
retry: false,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
41
68
|
export function useInvalidateUser() {
|
|
42
69
|
const queryClient = useQueryClient();
|
|
43
70
|
return () => queryClient.invalidateQueries({ queryKey: USER_QUERY_KEY });
|
|
@@ -15,6 +15,29 @@ export interface LoginApiResponse {
|
|
|
15
15
|
two_factor_authentication?: boolean;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
export type LoginResponse =
|
|
19
|
+
| { twoFactorRequired: true }
|
|
20
|
+
| { twoFactorRequired?: false; user: User; accessToken: string; refreshToken: string; expiresAt: string };
|
|
21
|
+
|
|
22
|
+
export interface TwoFactorRequest {
|
|
23
|
+
location: GeoLocation;
|
|
24
|
+
ip: string;
|
|
25
|
+
timezone: string;
|
|
26
|
+
agent: string;
|
|
27
|
+
cookie: string;
|
|
28
|
+
code: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface TwoFactorApiResponse {
|
|
32
|
+
status: 0 | 1;
|
|
33
|
+
message: string;
|
|
34
|
+
cookie?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface TwoFactorResponse {
|
|
38
|
+
success: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
18
41
|
export interface GeoLocation {
|
|
19
42
|
continent: string;
|
|
20
43
|
country: string;
|
|
@@ -37,13 +60,6 @@ export interface LoginRequest {
|
|
|
37
60
|
rememberMe?: boolean;
|
|
38
61
|
}
|
|
39
62
|
|
|
40
|
-
export interface LoginResponse {
|
|
41
|
-
user: User;
|
|
42
|
-
accessToken: string;
|
|
43
|
-
refreshToken: string;
|
|
44
|
-
expiresAt: string;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
63
|
export interface RegisterRequest {
|
|
48
64
|
accountName: string;
|
|
49
65
|
businessType: number;
|
|
@@ -25,40 +25,39 @@ import {
|
|
|
25
25
|
ResetPasswordResponse,
|
|
26
26
|
SessionKeepRequest,
|
|
27
27
|
SessionKeepResponse,
|
|
28
|
+
TwoFactorApiResponse,
|
|
29
|
+
TwoFactorRequest,
|
|
30
|
+
TwoFactorResponse,
|
|
28
31
|
VerifyEmailRequest,
|
|
29
32
|
VerifyEmailResponse,
|
|
30
33
|
} from '../schema';
|
|
31
34
|
|
|
32
35
|
const AUTH_COOKIE_NAME = 'greatapps';
|
|
36
|
+
const PENDING_2FA_COOKIE_NAME = 'greatapps_2fa_pending';
|
|
33
37
|
const COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
|
|
38
|
+
const PENDING_2FA_MAX_AGE = 60 * 10; // 10 minutos para completar o 2FA
|
|
34
39
|
|
|
35
|
-
|
|
40
|
+
const COOKIE_OPTIONS = {
|
|
41
|
+
httpOnly: true,
|
|
42
|
+
secure: process.env.NODE_ENV === 'production',
|
|
43
|
+
sameSite: 'lax' as const,
|
|
44
|
+
path: '/',
|
|
45
|
+
domain: process.env.DOMAIN_COOKIE,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
async function setPending2FACookie(token: string): Promise<void> {
|
|
36
49
|
const cookieStore = await cookies();
|
|
37
|
-
cookieStore.set(
|
|
38
|
-
httpOnly: true,
|
|
39
|
-
secure: process.env.NODE_ENV === 'production',
|
|
40
|
-
sameSite: 'lax',
|
|
41
|
-
maxAge: COOKIE_MAX_AGE,
|
|
42
|
-
path: '/',
|
|
43
|
-
domain: process.env.DOMAIN_COOKIE
|
|
44
|
-
});
|
|
50
|
+
cookieStore.set(PENDING_2FA_COOKIE_NAME, token, { ...COOKIE_OPTIONS, maxAge: PENDING_2FA_MAX_AGE });
|
|
45
51
|
}
|
|
46
52
|
|
|
47
|
-
async function
|
|
53
|
+
async function removePending2FACookie(): Promise<void> {
|
|
48
54
|
const cookieStore = await cookies();
|
|
49
|
-
cookieStore.delete({
|
|
50
|
-
name: AUTH_COOKIE_NAME,
|
|
51
|
-
path: "/",
|
|
52
|
-
secure: process.env.NODE_ENV === 'production',
|
|
53
|
-
sameSite: 'lax',
|
|
54
|
-
domain: process.env.DOMAIN_COOKIE,
|
|
55
|
-
});
|
|
55
|
+
cookieStore.delete({ name: PENDING_2FA_COOKIE_NAME, ...COOKIE_OPTIONS });
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
async function
|
|
59
|
-
if (process.env.DUMMY_AUTH_TOKEN) return process.env.DUMMY_AUTH_TOKEN;
|
|
58
|
+
async function getPending2FACookie(): Promise<string | undefined> {
|
|
60
59
|
const cookieStore = await cookies();
|
|
61
|
-
return cookieStore.get(
|
|
60
|
+
return cookieStore.get(PENDING_2FA_COOKIE_NAME)?.value;
|
|
62
61
|
}
|
|
63
62
|
|
|
64
63
|
class AuthService {
|
|
@@ -80,17 +79,59 @@ class AuthService {
|
|
|
80
79
|
throw new ApiError('Resposta de autenticação inválida', 'INVALID_RESPONSE', 500);
|
|
81
80
|
}
|
|
82
81
|
|
|
83
|
-
|
|
82
|
+
if (response.two_factor_authentication) {
|
|
83
|
+
// Armazena o cookie temporariamente até o 2FA ser concluído.
|
|
84
|
+
// O cookie principal NÃO é setado aqui para evitar falso positivo em isAuthenticated().
|
|
85
|
+
await setPending2FACookie(response.cookie);
|
|
86
|
+
return { twoFactorRequired: true };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
await this.setAuthCookie(response.cookie);
|
|
84
90
|
|
|
85
|
-
// O usuário completo será carregado pelo AuthProvider via getUserDataAction
|
|
86
91
|
return {
|
|
87
|
-
user: {} as User,
|
|
92
|
+
user: {} as User,
|
|
88
93
|
accessToken: response.cookie,
|
|
89
94
|
refreshToken: '',
|
|
90
95
|
expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),
|
|
91
96
|
};
|
|
92
97
|
}
|
|
93
98
|
|
|
99
|
+
async verifyTwoFactor(code: number, clientInfo: ClientInfo): Promise<TwoFactorResponse> {
|
|
100
|
+
const pendingCookie = await getPending2FACookie();
|
|
101
|
+
|
|
102
|
+
if (!pendingCookie) {
|
|
103
|
+
throw new ApiError('Nenhuma autenticação 2FA pendente', 'NO_PENDING_2FA', 400);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const payload: TwoFactorRequest = {
|
|
107
|
+
location: clientInfo.location,
|
|
108
|
+
ip: clientInfo.ip,
|
|
109
|
+
timezone: clientInfo.timezone,
|
|
110
|
+
agent: clientInfo.agent,
|
|
111
|
+
cookie: pendingCookie,
|
|
112
|
+
code,
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const response = await apiClient.post<TwoFactorApiResponse>('/auth/code', payload);
|
|
116
|
+
|
|
117
|
+
if (response.status === 0) {
|
|
118
|
+
throw new ApiError(response.message || 'Código 2FA inválido', 'TWO_FACTOR_FAILED', 401);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (!response.cookie) {
|
|
122
|
+
throw new ApiError('Resposta de autenticação inválida após 2FA', 'INVALID_RESPONSE', 500);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
await Promise.all([this.setAuthCookie(response.cookie), removePending2FACookie()]);
|
|
126
|
+
|
|
127
|
+
return { success: true };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async isTwoFactorPending(): Promise<boolean> {
|
|
131
|
+
const pending = await getPending2FACookie();
|
|
132
|
+
return !!pending;
|
|
133
|
+
}
|
|
134
|
+
|
|
94
135
|
async register(data: RegisterRequest): Promise<RegisterResponse> {
|
|
95
136
|
const today = new Date();
|
|
96
137
|
const trialEndDate = new Date(today);
|
|
@@ -149,7 +190,7 @@ class AuthService {
|
|
|
149
190
|
}
|
|
150
191
|
|
|
151
192
|
async logout(clientInfo: ClientInfo): Promise<LogoutResponse> {
|
|
152
|
-
const cookie = await
|
|
193
|
+
const cookie = await this.getToken();
|
|
153
194
|
|
|
154
195
|
if (!cookie) {
|
|
155
196
|
throw new ApiError('Usuário não autenticado', 'NOT_AUTHENTICATED', 401);
|
|
@@ -170,8 +211,7 @@ class AuthService {
|
|
|
170
211
|
throw new ApiError(response.message || 'Erro ao realizar logout', 'LOGOUT_FAILED', 400);
|
|
171
212
|
}
|
|
172
213
|
} finally {
|
|
173
|
-
|
|
174
|
-
await removeAuthCookie();
|
|
214
|
+
await Promise.all([this.removeAuthCookie(), removePending2FACookie()]);
|
|
175
215
|
}
|
|
176
216
|
|
|
177
217
|
return {
|
|
@@ -196,7 +236,7 @@ class AuthService {
|
|
|
196
236
|
}
|
|
197
237
|
|
|
198
238
|
async validateSession(clientInfo: ClientInfo): Promise<boolean> {
|
|
199
|
-
const cookie = await
|
|
239
|
+
const cookie = await this.getToken();
|
|
200
240
|
|
|
201
241
|
if (!cookie) {
|
|
202
242
|
return false;
|
|
@@ -221,12 +261,32 @@ class AuthService {
|
|
|
221
261
|
}
|
|
222
262
|
|
|
223
263
|
async isAuthenticated(): Promise<boolean> {
|
|
224
|
-
const token = await
|
|
264
|
+
const token = await this.getToken();
|
|
225
265
|
return !!token;
|
|
226
266
|
}
|
|
227
267
|
|
|
228
268
|
async getToken(): Promise<string | undefined> {
|
|
229
|
-
|
|
269
|
+
if (process.env.DUMMY_AUTH_TOKEN) return process.env.DUMMY_AUTH_TOKEN;
|
|
270
|
+
const cookieStore = await cookies();
|
|
271
|
+
return cookieStore.get(AUTH_COOKIE_NAME)?.value;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
private async setAuthCookie(token: string): Promise<void> {
|
|
276
|
+
const cookieStore = await cookies();
|
|
277
|
+
cookieStore.set(AUTH_COOKIE_NAME, token, {
|
|
278
|
+
...COOKIE_OPTIONS,
|
|
279
|
+
maxAge: COOKIE_MAX_AGE,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
async removeAuthCookie(): Promise<void> {
|
|
285
|
+
const cookieStore = await cookies();
|
|
286
|
+
cookieStore.delete({
|
|
287
|
+
name: AUTH_COOKIE_NAME,
|
|
288
|
+
...COOKIE_OPTIONS,
|
|
289
|
+
});
|
|
230
290
|
}
|
|
231
291
|
}
|
|
232
292
|
|