@greatapps/common 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/handlers/SearchParamsHandler.mjs +23 -0
- package/dist/components/handlers/SearchParamsHandler.mjs.map +1 -0
- package/dist/components/layouts/MainLayout.mjs +60 -0
- package/dist/components/layouts/MainLayout.mjs.map +1 -0
- package/dist/components/layouts/MdSideBarNavigation.mjs +36 -0
- package/dist/components/layouts/MdSideBarNavigation.mjs.map +1 -0
- package/dist/components/layouts/NavBar.mjs +45 -0
- package/dist/components/layouts/NavBar.mjs.map +1 -0
- package/dist/components/layouts/NotificationItem.mjs +7 -0
- package/dist/components/layouts/NotificationItem.mjs.map +1 -0
- package/dist/components/layouts/SideBarNavigation.mjs +22 -0
- package/dist/components/layouts/SideBarNavigation.mjs.map +1 -0
- package/dist/components/ui/buttons/Button.mjs +51 -0
- package/dist/components/ui/buttons/Button.mjs.map +1 -0
- package/dist/components/ui/buttons/CancelButton.mjs +16 -0
- package/dist/components/ui/buttons/CancelButton.mjs.map +1 -0
- package/dist/components/ui/buttons/CopyButton.mjs +34 -0
- package/dist/components/ui/buttons/CopyButton.mjs.map +1 -0
- package/dist/components/ui/data-display/Accordion.mjs +73 -0
- package/dist/components/ui/data-display/Accordion.mjs.map +1 -0
- package/dist/components/ui/data-display/Badge.mjs +41 -0
- package/dist/components/ui/data-display/Badge.mjs.map +1 -0
- package/dist/components/ui/data-display/Card.mjs +91 -0
- package/dist/components/ui/data-display/Card.mjs.map +1 -0
- package/dist/components/ui/data-display/Pagination.mjs +115 -0
- package/dist/components/ui/data-display/Pagination.mjs.map +1 -0
- package/dist/components/ui/data-display/ScrollArea.mjs +60 -0
- package/dist/components/ui/data-display/ScrollArea.mjs.map +1 -0
- package/dist/components/ui/data-display/Separator.mjs +28 -0
- package/dist/components/ui/data-display/Separator.mjs.map +1 -0
- package/dist/components/ui/data-display/Table.mjs +116 -0
- package/dist/components/ui/data-display/Table.mjs.map +1 -0
- package/dist/components/ui/data-display/Tabs.mjs +69 -0
- package/dist/components/ui/data-display/Tabs.mjs.map +1 -0
- package/dist/components/ui/feedback/CircularProgress.mjs +61 -0
- package/dist/components/ui/feedback/CircularProgress.mjs.map +1 -0
- package/dist/components/ui/feedback/DefaultCircularProgress.mjs +49 -0
- package/dist/components/ui/feedback/DefaultCircularProgress.mjs.map +1 -0
- package/dist/components/ui/feedback/Progress.mjs +37 -0
- package/dist/components/ui/feedback/Progress.mjs.map +1 -0
- package/dist/components/ui/feedback/Toast.mjs +73 -0
- package/dist/components/ui/feedback/Toast.mjs.map +1 -0
- package/dist/components/ui/form/Calendar.mjs +203 -0
- package/dist/components/ui/form/Calendar.mjs.map +1 -0
- package/dist/components/ui/form/Checkbox.mjs +33 -0
- package/dist/components/ui/form/Checkbox.mjs.map +1 -0
- package/dist/components/ui/form/DatePicker.mjs +78 -0
- package/dist/components/ui/form/DatePicker.mjs.map +1 -0
- package/dist/components/ui/form/DateRangePicker.mjs +86 -0
- package/dist/components/ui/form/DateRangePicker.mjs.map +1 -0
- package/dist/components/ui/form/Input.mjs +20 -0
- package/dist/components/ui/form/Input.mjs.map +1 -0
- package/dist/components/ui/form/InputOtp.mjs +67 -0
- package/dist/components/ui/form/InputOtp.mjs.map +1 -0
- package/dist/components/ui/form/RadioGroup.mjs +36 -0
- package/dist/components/ui/form/RadioGroup.mjs.map +1 -0
- package/dist/components/ui/form/Select.mjs +172 -0
- package/dist/components/ui/form/Select.mjs.map +1 -0
- package/dist/components/ui/form/Switch.mjs +33 -0
- package/dist/components/ui/form/Switch.mjs.map +1 -0
- package/dist/components/ui/form/Textarea.mjs +19 -0
- package/dist/components/ui/form/Textarea.mjs.map +1 -0
- package/dist/components/ui/overlay/Command.mjs +170 -0
- package/dist/components/ui/overlay/Command.mjs.map +1 -0
- package/dist/components/ui/overlay/Dialog.mjs +131 -0
- package/dist/components/ui/overlay/Dialog.mjs.map +1 -0
- package/dist/components/ui/overlay/Popover.mjs +46 -0
- package/dist/components/ui/overlay/Popover.mjs.map +1 -0
- package/dist/components/ui/overlay/Sheet.mjs +129 -0
- package/dist/components/ui/overlay/Sheet.mjs.map +1 -0
- package/dist/components/ui/overlay/Tooltip.mjs +55 -0
- package/dist/components/ui/overlay/Tooltip.mjs.map +1 -0
- package/dist/hooks/copy-to-clipboard.hook.mjs +39 -0
- package/dist/hooks/copy-to-clipboard.hook.mjs.map +1 -0
- package/dist/index.mjs +57 -0
- package/dist/index.mjs.map +1 -0
- package/dist/infra/api/client.mjs +115 -0
- package/dist/infra/api/client.mjs.map +1 -0
- package/dist/infra/api/types.mjs +31 -0
- package/dist/infra/api/types.mjs.map +1 -0
- package/dist/infra/utils/client-info.mjs +27 -0
- package/dist/infra/utils/client-info.mjs.map +1 -0
- package/dist/infra/utils/clsx.mjs +9 -0
- package/dist/infra/utils/clsx.mjs.map +1 -0
- package/dist/infra/utils/params.mjs +21 -0
- package/dist/infra/utils/params.mjs.map +1 -0
- package/dist/infra/utils/percentage.mjs +20 -0
- package/dist/infra/utils/percentage.mjs.map +1 -0
- package/dist/middlewares/chain.mjs +37 -0
- package/dist/middlewares/chain.mjs.map +1 -0
- package/dist/middlewares/create-auth-middleware.mjs +28 -0
- package/dist/middlewares/create-auth-middleware.mjs.map +1 -0
- package/dist/middlewares/types.mjs +11 -0
- package/dist/middlewares/types.mjs.map +1 -0
- package/dist/middlewares/validate-session.mjs +92 -0
- package/dist/middlewares/validate-session.mjs.map +1 -0
- package/dist/modules/auth/actions/login.action.mjs +11 -0
- package/dist/modules/auth/actions/login.action.mjs.map +1 -0
- package/dist/modules/auth/actions/logout.action.mjs +11 -0
- package/dist/modules/auth/actions/logout.action.mjs.map +1 -0
- package/dist/modules/auth/actions/register.action.mjs +9 -0
- package/dist/modules/auth/actions/register.action.mjs.map +1 -0
- package/dist/modules/auth/actions/validate-session.action.mjs +44 -0
- package/dist/modules/auth/actions/validate-session.action.mjs.map +1 -0
- package/dist/modules/auth/hooks/login.hook.mjs +12 -0
- package/dist/modules/auth/hooks/login.hook.mjs.map +1 -0
- package/dist/modules/auth/hooks/logout.hook.mjs +12 -0
- package/dist/modules/auth/hooks/logout.hook.mjs.map +1 -0
- package/dist/modules/auth/hooks/register.hook.mjs +12 -0
- package/dist/modules/auth/hooks/register.hook.mjs.map +1 -0
- package/dist/modules/auth/hooks/useUserQuery.mjs +48 -0
- package/dist/modules/auth/hooks/useUserQuery.mjs.map +1 -0
- package/dist/modules/auth/schema.mjs +1 -0
- package/dist/modules/auth/schema.mjs.map +1 -0
- package/dist/modules/auth/services/auth.service.mjs +163 -0
- package/dist/modules/auth/services/auth.service.mjs.map +1 -0
- package/dist/modules/users/action/find-user-by-id.action.mjs +21 -0
- package/dist/modules/users/action/find-user-by-id.action.mjs.map +1 -0
- package/dist/modules/users/schema.mjs +11 -0
- package/dist/modules/users/schema.mjs.map +1 -0
- package/dist/modules/users/services/user.service.mjs +50 -0
- package/dist/modules/users/services/user.service.mjs.map +1 -0
- package/dist/modules/whitelabel/actions/find-whitelabel.action.mjs +19 -0
- package/dist/modules/whitelabel/actions/find-whitelabel.action.mjs.map +1 -0
- package/dist/modules/whitelabel/schema.mjs +1 -0
- package/dist/modules/whitelabel/schema.mjs.map +1 -0
- package/dist/modules/whitelabel/services/whitelabel.service.mjs +62 -0
- package/dist/modules/whitelabel/services/whitelabel.service.mjs.map +1 -0
- package/dist/providers/auth.provider.mjs +84 -0
- package/dist/providers/auth.provider.mjs.map +1 -0
- package/dist/providers/query.provider.mjs +37 -0
- package/dist/providers/query.provider.mjs.map +1 -0
- package/dist/providers/whitelabel.provider.mjs +33 -0
- package/dist/providers/whitelabel.provider.mjs.map +1 -0
- package/dist/store/useMdSidebarStore.mjs +11 -0
- package/dist/store/useMdSidebarStore.mjs.map +1 -0
- package/package.json +68 -0
- package/src/components/handlers/SearchParamsHandler.tsx +61 -0
- package/src/components/layouts/MainLayout.tsx +59 -0
- package/src/components/layouts/MdSideBarNavigation.tsx +39 -0
- package/src/components/layouts/NavBar.tsx +79 -0
- package/src/components/layouts/NotificationItem.tsx +26 -0
- package/src/components/layouts/SideBarNavigation.tsx +22 -0
- package/src/components/ui/buttons/Button.tsx +55 -0
- package/src/components/ui/buttons/CancelButton.tsx +12 -0
- package/src/components/ui/buttons/CopyButton.tsx +47 -0
- package/src/components/ui/data-display/Accordion.tsx +79 -0
- package/src/components/ui/data-display/Badge.tsx +45 -0
- package/src/components/ui/data-display/Card.tsx +91 -0
- package/src/components/ui/data-display/Pagination.tsx +124 -0
- package/src/components/ui/data-display/ScrollArea.tsx +57 -0
- package/src/components/ui/data-display/Separator.tsx +27 -0
- package/src/components/ui/data-display/Table.tsx +115 -0
- package/src/components/ui/data-display/Tabs.tsx +65 -0
- package/src/components/ui/feedback/CircularProgress.tsx +75 -0
- package/src/components/ui/feedback/DefaultCircularProgress.tsx +53 -0
- package/src/components/ui/feedback/Progress.tsx +38 -0
- package/src/components/ui/feedback/Toast.tsx +99 -0
- package/src/components/ui/form/Calendar.tsx +226 -0
- package/src/components/ui/form/Checkbox.tsx +31 -0
- package/src/components/ui/form/DatePicker.tsx +97 -0
- package/src/components/ui/form/DateRangePicker.tsx +108 -0
- package/src/components/ui/form/Input.tsx +18 -0
- package/src/components/ui/form/InputOtp.tsx +78 -0
- package/src/components/ui/form/RadioGroup.tsx +43 -0
- package/src/components/ui/form/Select.tsx +195 -0
- package/src/components/ui/form/Switch.tsx +30 -0
- package/src/components/ui/form/Textarea.tsx +17 -0
- package/src/components/ui/overlay/Command.tsx +183 -0
- package/src/components/ui/overlay/Dialog.tsx +146 -0
- package/src/components/ui/overlay/Popover.tsx +47 -0
- package/src/components/ui/overlay/Sheet.tsx +145 -0
- package/src/components/ui/overlay/Tooltip.tsx +60 -0
- package/src/hooks/copy-to-clipboard.hook.tsx +52 -0
- package/src/index.ts +50 -0
- package/src/infra/api/client.ts +142 -0
- package/src/infra/api/types.ts +79 -0
- package/src/infra/utils/client-info.ts +35 -0
- package/src/infra/utils/clsx.ts +6 -0
- package/src/infra/utils/params.ts +27 -0
- package/src/infra/utils/percentage.ts +42 -0
- package/src/middlewares/chain.ts +45 -0
- package/src/middlewares/create-auth-middleware.ts +38 -0
- package/src/middlewares/types.ts +24 -0
- package/src/middlewares/validate-session.ts +116 -0
- package/src/modules/auth/actions/login.action.ts +11 -0
- package/src/modules/auth/actions/logout.action.ts +11 -0
- package/src/modules/auth/actions/register.action.ts +8 -0
- package/src/modules/auth/actions/validate-session.action.ts +51 -0
- package/src/modules/auth/hooks/login.hook.tsx +10 -0
- package/src/modules/auth/hooks/logout.hook.tsx +10 -0
- package/src/modules/auth/hooks/register.hook.tsx +10 -0
- package/src/modules/auth/hooks/useUserQuery.ts +49 -0
- package/src/modules/auth/schema.ts +220 -0
- package/src/modules/auth/services/auth.service.ts +225 -0
- package/src/modules/users/action/find-user-by-id.action.ts +25 -0
- package/src/modules/users/schema.ts +79 -0
- package/src/modules/users/services/user.service.ts +63 -0
- package/src/modules/whitelabel/actions/find-whitelabel.action.ts +20 -0
- package/src/modules/whitelabel/schema.ts +49 -0
- package/src/modules/whitelabel/services/whitelabel.service.ts +77 -0
- package/src/providers/auth.provider.tsx +113 -0
- package/src/providers/query.provider.tsx +52 -0
- package/src/providers/whitelabel.provider.tsx +44 -0
- package/src/store/useMdSidebarStore.ts +15 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query';
|
|
4
|
+
import { User } from '../../users/schema';
|
|
5
|
+
|
|
6
|
+
export const USER_QUERY_KEY = ['user'];
|
|
7
|
+
|
|
8
|
+
async function fetchUser(): Promise<User | null> {
|
|
9
|
+
const { findUserById: getUserDataAction } = await import('../../users/action/find-user-by-id.action');
|
|
10
|
+
const result = await getUserDataAction();
|
|
11
|
+
return result.success && result.data ? result.data : null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async function validateUserSession(): Promise<boolean> {
|
|
15
|
+
const { validateSessionAction } = await import('../actions/validate-session.action');
|
|
16
|
+
return await validateSessionAction();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function useUserQuery() {
|
|
20
|
+
return useQuery({
|
|
21
|
+
queryKey: USER_QUERY_KEY,
|
|
22
|
+
queryFn: fetchUser,
|
|
23
|
+
staleTime: 5 * 60 * 1000,
|
|
24
|
+
gcTime: 10 * 60 * 1000,
|
|
25
|
+
retry: false,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function useUserValidateSession(options?: UseQueryOptions) {
|
|
30
|
+
return useQuery({
|
|
31
|
+
queryKey: ['user-validate-session'],
|
|
32
|
+
queryFn: validateUserSession,
|
|
33
|
+
retry: false,
|
|
34
|
+
staleTime: 5 * 60 * 1000,
|
|
35
|
+
...options,
|
|
36
|
+
refetchOnMount: 'always',
|
|
37
|
+
refetchOnWindowFocus: true,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function useInvalidateUser() {
|
|
42
|
+
const queryClient = useQueryClient();
|
|
43
|
+
return () => queryClient.invalidateQueries({ queryKey: USER_QUERY_KEY });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function useSetUserData() {
|
|
47
|
+
const queryClient = useQueryClient();
|
|
48
|
+
return (user: User | null) => queryClient.setQueryData(USER_QUERY_KEY, user);
|
|
49
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { User } from '../users/schema';
|
|
2
|
+
|
|
3
|
+
export interface ClientInfo {
|
|
4
|
+
location: GeoLocation;
|
|
5
|
+
ip: string;
|
|
6
|
+
timezone: string;
|
|
7
|
+
agent: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface LoginApiResponse {
|
|
11
|
+
status: 0 | 1;
|
|
12
|
+
message: string;
|
|
13
|
+
cookie?: string;
|
|
14
|
+
two_factor_authentication?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface GeoLocation {
|
|
18
|
+
continent: string;
|
|
19
|
+
country: string;
|
|
20
|
+
region: string;
|
|
21
|
+
city: string;
|
|
22
|
+
latitude: string;
|
|
23
|
+
longitude: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface AuthState {
|
|
27
|
+
user: User | null;
|
|
28
|
+
isAuthenticated: boolean;
|
|
29
|
+
isLoading: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface LoginRequest {
|
|
33
|
+
email: string;
|
|
34
|
+
password: string;
|
|
35
|
+
rememberMe?: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface LoginResponse {
|
|
39
|
+
user: User;
|
|
40
|
+
accessToken: string;
|
|
41
|
+
refreshToken: string;
|
|
42
|
+
expiresAt: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface RegisterRequest {
|
|
46
|
+
accountName: string;
|
|
47
|
+
businessType: number;
|
|
48
|
+
name: string;
|
|
49
|
+
lastName?: string;
|
|
50
|
+
email: string;
|
|
51
|
+
phone: string;
|
|
52
|
+
password: string;
|
|
53
|
+
gender: number;
|
|
54
|
+
rg?: string;
|
|
55
|
+
cpf?: string;
|
|
56
|
+
acceptTerms: boolean;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface RegisterApiRequest {
|
|
60
|
+
name: string;
|
|
61
|
+
bussiness_type: number;
|
|
62
|
+
language: string;
|
|
63
|
+
timezone: string;
|
|
64
|
+
currency: string;
|
|
65
|
+
user: {
|
|
66
|
+
id_api: string;
|
|
67
|
+
name: string;
|
|
68
|
+
last_name: string;
|
|
69
|
+
rg: string;
|
|
70
|
+
cpf: string;
|
|
71
|
+
gender: number;
|
|
72
|
+
email: string;
|
|
73
|
+
phone: string;
|
|
74
|
+
password: string;
|
|
75
|
+
profile: string;
|
|
76
|
+
language: string;
|
|
77
|
+
};
|
|
78
|
+
subscription: {
|
|
79
|
+
type: string;
|
|
80
|
+
id_cupom: string;
|
|
81
|
+
id_plan: number;
|
|
82
|
+
due_date: string;
|
|
83
|
+
id_product: number;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface RegisterApiResponse {
|
|
88
|
+
status: 0 | 1;
|
|
89
|
+
message: string;
|
|
90
|
+
data?: Array<{
|
|
91
|
+
id: number;
|
|
92
|
+
id_wl: number;
|
|
93
|
+
name: string;
|
|
94
|
+
language: string;
|
|
95
|
+
timezone: string;
|
|
96
|
+
currency: string;
|
|
97
|
+
verified: boolean;
|
|
98
|
+
user: {
|
|
99
|
+
id: number;
|
|
100
|
+
id_account: number;
|
|
101
|
+
id_api: number;
|
|
102
|
+
name: string;
|
|
103
|
+
last_name: string | null;
|
|
104
|
+
ddi: string;
|
|
105
|
+
phone: string;
|
|
106
|
+
email: string;
|
|
107
|
+
password: string;
|
|
108
|
+
gender: number;
|
|
109
|
+
two_factor_authentication: boolean;
|
|
110
|
+
profile: string;
|
|
111
|
+
language: string;
|
|
112
|
+
photo: string | null;
|
|
113
|
+
};
|
|
114
|
+
subscription: Array<{
|
|
115
|
+
id: number;
|
|
116
|
+
id_account: number;
|
|
117
|
+
type: string;
|
|
118
|
+
id_product: number;
|
|
119
|
+
id_plan: number;
|
|
120
|
+
active: boolean;
|
|
121
|
+
}>;
|
|
122
|
+
}>;
|
|
123
|
+
total?: number;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface RegisterResponse {
|
|
127
|
+
user: User;
|
|
128
|
+
accessToken: string;
|
|
129
|
+
refreshToken: string;
|
|
130
|
+
expiresAt: string;
|
|
131
|
+
requiresEmailVerification: boolean;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface ForgotPasswordRequest {
|
|
135
|
+
email: string;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface ForgotPasswordResponse {
|
|
139
|
+
status: 0 | 1;
|
|
140
|
+
message: string;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export interface ValidateForgotPasswordRequest {
|
|
144
|
+
email: string;
|
|
145
|
+
token: string;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export interface ValidateForgotPasswordResponse {
|
|
149
|
+
status: 0 | 1;
|
|
150
|
+
message: string;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export interface ResetPasswordRequest {
|
|
154
|
+
email: string;
|
|
155
|
+
token: string;
|
|
156
|
+
password: string;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export interface ResetPasswordResponse {
|
|
160
|
+
status: 0 | 1;
|
|
161
|
+
message: string;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export interface VerifyEmailRequest {
|
|
165
|
+
token: string;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export interface VerifyEmailResponse {
|
|
169
|
+
message: string;
|
|
170
|
+
user: User;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export interface ResendVerificationRequest {
|
|
174
|
+
email: string;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export interface ResendVerificationResponse {
|
|
178
|
+
message: string;
|
|
179
|
+
expiresAt: string;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export interface RefreshTokenRequest {
|
|
183
|
+
refreshToken: string;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export interface RefreshTokenResponse {
|
|
187
|
+
accessToken: string;
|
|
188
|
+
refreshToken: string;
|
|
189
|
+
expiresAt: string;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export interface SessionKeepRequest {
|
|
193
|
+
location: GeoLocation;
|
|
194
|
+
ip: string;
|
|
195
|
+
timezone: string;
|
|
196
|
+
agent: string;
|
|
197
|
+
cookie: string;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export interface SessionKeepResponse {
|
|
201
|
+
status: 0 | 1;
|
|
202
|
+
message: string;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export interface LogoutRequest {
|
|
206
|
+
location: GeoLocation;
|
|
207
|
+
ip: string;
|
|
208
|
+
timezone: string;
|
|
209
|
+
agent: string;
|
|
210
|
+
cookie: string;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export interface LogoutApiResponse {
|
|
214
|
+
status: 0 | 1;
|
|
215
|
+
message: string;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export interface LogoutResponse {
|
|
219
|
+
success: boolean;
|
|
220
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
|
|
3
|
+
import { cookies } from 'next/headers';
|
|
4
|
+
|
|
5
|
+
import { apiClient } from '../../../infra/api/client';
|
|
6
|
+
import { ApiError } from '../../../infra/api/types';
|
|
7
|
+
import { User } from '../../users/schema';
|
|
8
|
+
import {
|
|
9
|
+
ClientInfo,
|
|
10
|
+
ForgotPasswordRequest,
|
|
11
|
+
ForgotPasswordResponse,
|
|
12
|
+
GeoLocation,
|
|
13
|
+
LoginApiResponse,
|
|
14
|
+
LoginRequest,
|
|
15
|
+
LoginResponse,
|
|
16
|
+
LogoutApiResponse,
|
|
17
|
+
LogoutRequest,
|
|
18
|
+
LogoutResponse,
|
|
19
|
+
RegisterApiRequest,
|
|
20
|
+
RegisterApiResponse,
|
|
21
|
+
RegisterRequest,
|
|
22
|
+
RegisterResponse,
|
|
23
|
+
ResendVerificationRequest,
|
|
24
|
+
ResendVerificationResponse,
|
|
25
|
+
ResetPasswordRequest,
|
|
26
|
+
ResetPasswordResponse,
|
|
27
|
+
SessionKeepRequest,
|
|
28
|
+
SessionKeepResponse,
|
|
29
|
+
VerifyEmailRequest,
|
|
30
|
+
VerifyEmailResponse,
|
|
31
|
+
} from '../schema';
|
|
32
|
+
|
|
33
|
+
const AUTH_COOKIE_NAME = 'greatapps';
|
|
34
|
+
const COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
|
|
35
|
+
|
|
36
|
+
async function setAuthCookie(token: string): Promise<void> {
|
|
37
|
+
const cookieStore = await cookies();
|
|
38
|
+
cookieStore.set(AUTH_COOKIE_NAME, token, {
|
|
39
|
+
httpOnly: true,
|
|
40
|
+
secure: process.env.NODE_ENV === 'production',
|
|
41
|
+
sameSite: 'lax',
|
|
42
|
+
maxAge: COOKIE_MAX_AGE,
|
|
43
|
+
path: '/',
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function removeAuthCookie(): Promise<void> {
|
|
48
|
+
const cookieStore = await cookies();
|
|
49
|
+
cookieStore.delete(AUTH_COOKIE_NAME);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function getAuthCookie(): Promise<string | undefined> {
|
|
53
|
+
const cookieStore = await cookies();
|
|
54
|
+
return cookieStore.get(AUTH_COOKIE_NAME)?.value;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
class AuthService {
|
|
58
|
+
async login(credentials: LoginRequest, clientInfo: ClientInfo): Promise<LoginResponse> {
|
|
59
|
+
const response = await apiClient.post<LoginApiResponse>('/auth/login', {
|
|
60
|
+
email: credentials.email,
|
|
61
|
+
password: credentials.password,
|
|
62
|
+
location: clientInfo.location,
|
|
63
|
+
ip: clientInfo.ip,
|
|
64
|
+
timezone: clientInfo.timezone,
|
|
65
|
+
agent: clientInfo.agent,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (response.status === 0) {
|
|
69
|
+
throw new ApiError(response.message || 'E-mail ou senha incorretos', 'LOGIN_FAILED', 401);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!response.cookie) {
|
|
73
|
+
throw new ApiError('Resposta de autenticação inválida', 'INVALID_RESPONSE', 500);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
await setAuthCookie(response.cookie);
|
|
77
|
+
|
|
78
|
+
// O usuário completo será carregado pelo AuthProvider via getUserDataAction
|
|
79
|
+
return {
|
|
80
|
+
user: {} as User, // Placeholder, será preenchido pelo AuthProvider
|
|
81
|
+
accessToken: response.cookie,
|
|
82
|
+
refreshToken: '',
|
|
83
|
+
expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async register(data: RegisterRequest): Promise<RegisterResponse> {
|
|
88
|
+
const today = new Date();
|
|
89
|
+
const trialEndDate = new Date(today);
|
|
90
|
+
trialEndDate.setDate(today.getDate() + 7); // 7 dias de trial
|
|
91
|
+
|
|
92
|
+
const payload: RegisterApiRequest = {
|
|
93
|
+
name: data.accountName,
|
|
94
|
+
bussiness_type: data.businessType,
|
|
95
|
+
language: 'pt-br',
|
|
96
|
+
timezone: 'America/Sao_Paulo',
|
|
97
|
+
currency: 'BRL',
|
|
98
|
+
user: {
|
|
99
|
+
id_api: '',
|
|
100
|
+
name: data.name,
|
|
101
|
+
last_name: data.lastName || '',
|
|
102
|
+
rg: data.rg || '',
|
|
103
|
+
cpf: data.cpf || '',
|
|
104
|
+
gender: data.gender,
|
|
105
|
+
email: data.email,
|
|
106
|
+
phone: data.phone,
|
|
107
|
+
password: data.password,
|
|
108
|
+
profile: 'owner',
|
|
109
|
+
language: 'pt-br',
|
|
110
|
+
},
|
|
111
|
+
subscription: {
|
|
112
|
+
type: 'trial',
|
|
113
|
+
id_cupom: '',
|
|
114
|
+
id_plan: 1,
|
|
115
|
+
due_date: trialEndDate.toISOString().split('T')[0],
|
|
116
|
+
id_product: 1,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const response = await apiClient.post<RegisterApiResponse>('/accounts', payload);
|
|
121
|
+
|
|
122
|
+
if (response.status === 0) {
|
|
123
|
+
throw new ApiError(response.message || 'Erro ao criar conta', 'REGISTER_FAILED', 400);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (!response.data || response.data.length === 0) {
|
|
127
|
+
throw new ApiError('Resposta de registro inválida', 'INVALID_RESPONSE', 500);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const accountData = response.data[0];
|
|
131
|
+
|
|
132
|
+
// Retornar sem token pois o registro não retorna cookie diretamente
|
|
133
|
+
// O usuário precisará fazer login após o registro
|
|
134
|
+
// O usuário completo será carregado após o login
|
|
135
|
+
return {
|
|
136
|
+
user: {} as User, // Placeholder, será preenchido após login
|
|
137
|
+
accessToken: '',
|
|
138
|
+
refreshToken: '',
|
|
139
|
+
expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),
|
|
140
|
+
requiresEmailVerification: !accountData.verified,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async logout(clientInfo: ClientInfo): Promise<LogoutResponse> {
|
|
145
|
+
const cookie = await getAuthCookie();
|
|
146
|
+
|
|
147
|
+
if (!cookie) {
|
|
148
|
+
throw new ApiError('Usuário não autenticado', 'NOT_AUTHENTICATED', 401);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const payload: LogoutRequest = {
|
|
152
|
+
location: clientInfo.location,
|
|
153
|
+
ip: clientInfo.ip,
|
|
154
|
+
timezone: clientInfo.timezone,
|
|
155
|
+
agent: clientInfo.agent,
|
|
156
|
+
cookie,
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const response = await apiClient.post<LogoutApiResponse>('/auth/logout', payload);
|
|
160
|
+
|
|
161
|
+
if (response.status === 0) {
|
|
162
|
+
throw new ApiError(response.message || 'Erro ao realizar logout', 'LOGOUT_FAILED', 400);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
await removeAuthCookie();
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
success: true,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async forgotPassword(_data: ForgotPasswordRequest): Promise<ForgotPasswordResponse> {
|
|
173
|
+
throw new ApiError('Recuperação de senha não implementada', 'NOT_IMPLEMENTED', 501);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async resetPassword(_data: ResetPasswordRequest): Promise<ResetPasswordResponse> {
|
|
177
|
+
throw new ApiError('Redefinição de senha não implementada', 'NOT_IMPLEMENTED', 501);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async verifyEmail(_data: VerifyEmailRequest): Promise<VerifyEmailResponse> {
|
|
181
|
+
throw new ApiError('Verificação de email não implementada', 'NOT_IMPLEMENTED', 501);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async resendVerification(_data: ResendVerificationRequest): Promise<ResendVerificationResponse> {
|
|
185
|
+
throw new ApiError('Reenvio de verificação não implementado', 'NOT_IMPLEMENTED', 501);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async validateSession(clientInfo: ClientInfo): Promise<boolean> {
|
|
189
|
+
const cookie = await getAuthCookie();
|
|
190
|
+
|
|
191
|
+
if (!cookie) {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
try {
|
|
196
|
+
const payload: SessionKeepRequest = {
|
|
197
|
+
location: clientInfo.location,
|
|
198
|
+
ip: clientInfo.ip,
|
|
199
|
+
timezone: clientInfo.timezone,
|
|
200
|
+
agent: clientInfo.agent,
|
|
201
|
+
cookie,
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const response = await apiClient.post<SessionKeepResponse>('/auth/keep', payload);
|
|
205
|
+
|
|
206
|
+
return response.status === 1;
|
|
207
|
+
} catch (error) {
|
|
208
|
+
console.error('[AuthService] validateSession error', error);
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async isAuthenticated(): Promise<boolean> {
|
|
214
|
+
const token = await getAuthCookie();
|
|
215
|
+
return !!token;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
async getToken(): Promise<string | undefined> {
|
|
219
|
+
return getAuthCookie();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export const authService = new AuthService();
|
|
224
|
+
|
|
225
|
+
export type { ClientInfo, GeoLocation };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { userService } from '../services/user.service';
|
|
4
|
+
import { User } from '../schema';
|
|
5
|
+
|
|
6
|
+
export async function findUserById(): Promise<{
|
|
7
|
+
success: boolean;
|
|
8
|
+
data?: User;
|
|
9
|
+
error?: string;
|
|
10
|
+
}> {
|
|
11
|
+
try {
|
|
12
|
+
const user = await userService.findById();
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
success: true,
|
|
16
|
+
data: user,
|
|
17
|
+
};
|
|
18
|
+
} catch (error) {
|
|
19
|
+
console.error('[findUserById] Error:', error);
|
|
20
|
+
return {
|
|
21
|
+
success: false,
|
|
22
|
+
error: error instanceof Error ? error.message : 'Erro desconhecido',
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export enum UserProfile {
|
|
2
|
+
viewer = 'viewer',
|
|
3
|
+
collaborator = 'collaborator',
|
|
4
|
+
admin = 'admin',
|
|
5
|
+
owner = 'owner',
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface User {
|
|
9
|
+
// Identificação
|
|
10
|
+
id: number;
|
|
11
|
+
id_wl: number;
|
|
12
|
+
id_account: number;
|
|
13
|
+
id_api: number;
|
|
14
|
+
|
|
15
|
+
// Dados pessoais
|
|
16
|
+
name: string;
|
|
17
|
+
last_name: string;
|
|
18
|
+
email: string;
|
|
19
|
+
ddi: string;
|
|
20
|
+
phone: string;
|
|
21
|
+
rg: string | null;
|
|
22
|
+
cpf: string | null;
|
|
23
|
+
gender: number;
|
|
24
|
+
|
|
25
|
+
// Autenticação e segurança
|
|
26
|
+
two_factor_authentication: boolean;
|
|
27
|
+
|
|
28
|
+
// Perfil e permissões
|
|
29
|
+
profile: UserProfile;
|
|
30
|
+
|
|
31
|
+
// Preferências
|
|
32
|
+
language: string;
|
|
33
|
+
receive_sms: boolean;
|
|
34
|
+
receive_email: boolean;
|
|
35
|
+
photo: string | null;
|
|
36
|
+
|
|
37
|
+
// Metadados
|
|
38
|
+
deleted: number;
|
|
39
|
+
datetime_alt: string;
|
|
40
|
+
datetime_del: string | null;
|
|
41
|
+
datetime_add: string;
|
|
42
|
+
|
|
43
|
+
total_projects: number;
|
|
44
|
+
projects: { id: number; title: string }[];
|
|
45
|
+
|
|
46
|
+
initials?: string;
|
|
47
|
+
emailVerified?: boolean;
|
|
48
|
+
createdAt?: string;
|
|
49
|
+
updatedAt?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface GetUserDataResponse {
|
|
53
|
+
status: 0 | 1;
|
|
54
|
+
total: number;
|
|
55
|
+
data: User[];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface JWTPayload {
|
|
59
|
+
session: {
|
|
60
|
+
location: {
|
|
61
|
+
continent: string;
|
|
62
|
+
country: string;
|
|
63
|
+
region: string;
|
|
64
|
+
city: string;
|
|
65
|
+
latitude: string;
|
|
66
|
+
longitude: string;
|
|
67
|
+
};
|
|
68
|
+
ip: string;
|
|
69
|
+
timezone: string;
|
|
70
|
+
agent: string;
|
|
71
|
+
code: string | null;
|
|
72
|
+
};
|
|
73
|
+
id_wl: string;
|
|
74
|
+
id_account: number;
|
|
75
|
+
id_user: number;
|
|
76
|
+
iss: string;
|
|
77
|
+
aud: string;
|
|
78
|
+
iat: number;
|
|
79
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
|
|
3
|
+
import { cookies } from 'next/headers';
|
|
4
|
+
|
|
5
|
+
import { ApiError } from '../../../infra/api/types';
|
|
6
|
+
import { GetUserDataResponse, JWTPayload, User } from '../schema';
|
|
7
|
+
import { findWhitelabel } from '../../whitelabel/actions/find-whitelabel.action';
|
|
8
|
+
|
|
9
|
+
const AUTH_COOKIE_NAME = 'greatapps';
|
|
10
|
+
const API_BASE_URL = process.env.R3_API_URL || 'https://r3-api.greatapps.dev.br';
|
|
11
|
+
|
|
12
|
+
class UserService {
|
|
13
|
+
private async getAuthToken(): Promise<string> {
|
|
14
|
+
const cookieStore = await cookies();
|
|
15
|
+
const token = cookieStore.get(AUTH_COOKIE_NAME)?.value;
|
|
16
|
+
|
|
17
|
+
if (!token) {
|
|
18
|
+
throw new ApiError('Não autenticado', 'NOT_AUTHENTICATED', 401);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return token;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private decodeJWT(token: string): JWTPayload {
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(atob(token.split('.')[1])) as JWTPayload;
|
|
27
|
+
} catch {
|
|
28
|
+
throw new ApiError('Token inválido', 'INVALID_TOKEN', 401);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async findById(): Promise<User> {
|
|
33
|
+
const token = await this.getAuthToken();
|
|
34
|
+
const payload = this.decodeJWT(token);
|
|
35
|
+
|
|
36
|
+
const { id_wl, id_account, id_user } = payload;
|
|
37
|
+
const { token: wlToken } = await findWhitelabel();
|
|
38
|
+
|
|
39
|
+
const url = `${API_BASE_URL}/v1/pt-br/${id_wl}/accounts/${id_account}/users/${id_user}`;
|
|
40
|
+
|
|
41
|
+
const response = await fetch(url, {
|
|
42
|
+
method: 'GET',
|
|
43
|
+
headers: {
|
|
44
|
+
'Content-Type': 'application/json',
|
|
45
|
+
authorization: wlToken,
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
if (!response.ok) {
|
|
50
|
+
throw new ApiError('Erro ao buscar dados do usuário', 'FETCH_ERROR', response.status);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const data = (await response.json()) as GetUserDataResponse;
|
|
54
|
+
|
|
55
|
+
if (data.status === 0 || !data.data || data.data.length === 0) {
|
|
56
|
+
throw new ApiError('Dados do usuário não encontrados', 'USER_NOT_FOUND', 404);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return data.data[0];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const userService = new UserService();
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { headers } from "next/headers";
|
|
2
|
+
import { whitelabelService } from "../services/whitelabel.service";
|
|
3
|
+
import { ApiError } from "../../../infra/api/types";
|
|
4
|
+
|
|
5
|
+
export async function findWhitelabel() {
|
|
6
|
+
const headersList = await headers();
|
|
7
|
+
const host = headersList.get('host');
|
|
8
|
+
|
|
9
|
+
if (!host) {
|
|
10
|
+
throw new ApiError('Host header not found', 'HOST_NOT_FOUND', 400);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const whitelabel = await whitelabelService.getTokenByDomain(host);
|
|
14
|
+
|
|
15
|
+
if (!whitelabel) {
|
|
16
|
+
throw new ApiError('Whitelabel not found', 'WL_NOT_FOUND', 404);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return whitelabel;
|
|
20
|
+
}
|