@zauru-sdk/utils 6.22.1 → 6.23.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.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { redirect } from "@remix-run/node";
|
|
2
2
|
import { config } from "@zauru-sdk/config";
|
|
3
|
-
import { commitSession, destroySession, getRefreshSession, getSession, loginWebApp, } from "@zauru-sdk/services";
|
|
3
|
+
import { commitSession, destroySession, getHeaders, getRefreshSession, getSession, loginWebApp, } from "@zauru-sdk/services";
|
|
4
4
|
const loginErrorPayload = (description, title) => ({
|
|
5
5
|
error: true,
|
|
6
6
|
type: "error",
|
|
@@ -9,6 +9,23 @@ const loginErrorPayload = (description, title) => ({
|
|
|
9
9
|
description,
|
|
10
10
|
});
|
|
11
11
|
const isDenied = (result) => result === false;
|
|
12
|
+
const isResponse = (value) => typeof Response !== "undefined" && value instanceof Response;
|
|
13
|
+
const deniedLoginPayload = () => loginErrorPayload("No tienes permiso para acceder a esta aplicación. Si crees que esto es un error, contacta al administrador.", "Acceso denegado");
|
|
14
|
+
const evaluateLoginAccess = async (extras, session, headers) => {
|
|
15
|
+
try {
|
|
16
|
+
if (isDenied(await extras?.requireAccess?.(session, headers))) {
|
|
17
|
+
return Response.json(deniedLoginPayload());
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
if (isResponse(error)) {
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
const description = error instanceof Error ? error.message : String(error);
|
|
26
|
+
return Response.json(loginErrorPayload(description));
|
|
27
|
+
}
|
|
28
|
+
};
|
|
12
29
|
const authorizeUrl = (request) => {
|
|
13
30
|
const url = new URL(request.url);
|
|
14
31
|
const hostname = `${url.port ? "http://" : "https://"}${url.hostname}${url.port ? `:${url.port}` : ""}`;
|
|
@@ -41,7 +58,16 @@ export function createLoginAction(extras) {
|
|
|
41
58
|
return redirect(authorizeUrl(request));
|
|
42
59
|
}
|
|
43
60
|
if (session.has("code")) {
|
|
44
|
-
|
|
61
|
+
const existingHeaders = await getHeaders(null, session);
|
|
62
|
+
try {
|
|
63
|
+
if (isDenied(await extras?.requireAccess?.(session, existingHeaders))) {
|
|
64
|
+
return redirect("/");
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
if (isResponse(error)) {
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
45
71
|
return redirect("/");
|
|
46
72
|
}
|
|
47
73
|
return redirect("/home");
|
|
@@ -50,8 +76,9 @@ export function createLoginAction(extras) {
|
|
|
50
76
|
if (loginResponse.error || !loginResponse.data) {
|
|
51
77
|
return Response.json(loginErrorPayload(loginResponse.userMsg?.toString() ?? ""));
|
|
52
78
|
}
|
|
53
|
-
|
|
54
|
-
|
|
79
|
+
const denied = await evaluateLoginAccess(extras, session, loginResponse.data.headers);
|
|
80
|
+
if (denied) {
|
|
81
|
+
return denied;
|
|
55
82
|
}
|
|
56
83
|
if (extras?.afterLogin) {
|
|
57
84
|
await extras.afterLogin({
|
|
@@ -78,7 +105,8 @@ export function createSessionGuardLoader(extras) {
|
|
|
78
105
|
if (!session.has("username")) {
|
|
79
106
|
return redirect("/");
|
|
80
107
|
}
|
|
81
|
-
|
|
108
|
+
const headers = await getHeaders(null, session);
|
|
109
|
+
if (isDenied(await extras?.requireAccess?.(session, headers))) {
|
|
82
110
|
return redirect("/");
|
|
83
111
|
}
|
|
84
112
|
return Response.json({});
|
|
@@ -104,7 +132,8 @@ export function createIndexLoader(extras) {
|
|
|
104
132
|
return async ({ request }) => {
|
|
105
133
|
const session = await getSession(request.headers.get("Cookie"));
|
|
106
134
|
if (session.has("username")) {
|
|
107
|
-
|
|
135
|
+
const headers = await getHeaders(null, session);
|
|
136
|
+
if (isDenied(await extras?.requireAccess?.(session, headers))) {
|
|
108
137
|
return Response.json({});
|
|
109
138
|
}
|
|
110
139
|
return redirect("/home");
|
|
@@ -121,7 +150,8 @@ export function createReloadCatalogsLoader(extras) {
|
|
|
121
150
|
if (!session.has("username")) {
|
|
122
151
|
return redirect("/");
|
|
123
152
|
}
|
|
124
|
-
|
|
153
|
+
const headers = await getHeaders(null, session);
|
|
154
|
+
if (isDenied(await extras?.requireAccess?.(session, headers))) {
|
|
125
155
|
return redirect("/");
|
|
126
156
|
}
|
|
127
157
|
try {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { redirect } from "@remix-run/node";
|
|
2
2
|
import { handlePossibleAxiosErrors } from "@zauru-sdk/common";
|
|
3
|
-
import { createWebAppTableRegister, getVariablesByName, getWebAppRow, getWebAppTableRegisters, updateWebAppTableRegister, } from "@zauru-sdk/services";
|
|
3
|
+
import { createWebAppTableRegister, getHeaders, getVariablesByName, getWebAppRow, getWebAppTableRegisters, updateWebAppTableRegister, } from "@zauru-sdk/services";
|
|
4
4
|
import { hasPermission as hasPermissionInContext, isActiveWebappRow, isSuperAdminEmail, } from "./access.js";
|
|
5
5
|
import { DEFAULT_SUPER_ADMIN_EMAIL_SUFFIXES, isValidPermissionKey, normalizePermissionKeys, } from "./catalog.js";
|
|
6
6
|
const deletedAt = () => new Date().toISOString();
|
|
@@ -11,11 +11,14 @@ const toNumber = (value) => {
|
|
|
11
11
|
export function createWebappRbac(config) {
|
|
12
12
|
const suffixes = config.superAdminEmailSuffixes ?? DEFAULT_SUPER_ADMIN_EMAIL_SUFFIXES;
|
|
13
13
|
const validKeys = new Set(config.allPermissionKeys);
|
|
14
|
+
const resolveHeaders = async (headers, session) => {
|
|
15
|
+
if (headers?.["X-User-Token"] || headers?.["x-user-token"]) {
|
|
16
|
+
return headers;
|
|
17
|
+
}
|
|
18
|
+
return getHeaders(null, session);
|
|
19
|
+
};
|
|
14
20
|
const getTableIds = async (headers, session) => {
|
|
15
|
-
const vars = await getVariablesByName(headers, session, [
|
|
16
|
-
config.rolesTableVar,
|
|
17
|
-
config.employeeRolesTableVar,
|
|
18
|
-
]);
|
|
21
|
+
const vars = await getVariablesByName(await resolveHeaders(headers, session), session, [config.rolesTableVar, config.employeeRolesTableVar]);
|
|
19
22
|
return {
|
|
20
23
|
rolesTableId: vars[config.rolesTableVar],
|
|
21
24
|
employeeRolesTableId: vars[config.employeeRolesTableVar],
|
|
@@ -210,6 +213,7 @@ export function createWebappRbac(config) {
|
|
|
210
213
|
const context = await resolveAccess(headers, session);
|
|
211
214
|
return context != null;
|
|
212
215
|
};
|
|
216
|
+
const hasAppAccessFromSession = (session) => hasAppAccess(undefined, session);
|
|
213
217
|
const requireAppAccess = async (headers, session) => {
|
|
214
218
|
if (!session.has("username")) {
|
|
215
219
|
throw redirect("/");
|
|
@@ -220,6 +224,7 @@ export function createWebappRbac(config) {
|
|
|
220
224
|
}
|
|
221
225
|
return context;
|
|
222
226
|
};
|
|
227
|
+
const requireAppAccessFromSession = (session) => requireAppAccess(undefined, session);
|
|
223
228
|
const requirePermission = async (headers, session, key) => {
|
|
224
229
|
const context = await requireAppAccess(headers, session);
|
|
225
230
|
if (!hasPermissionInContext(context, key)) {
|
|
@@ -240,7 +245,9 @@ export function createWebappRbac(config) {
|
|
|
240
245
|
assignEmployeeRole,
|
|
241
246
|
resolveAccess,
|
|
242
247
|
hasAppAccess,
|
|
248
|
+
hasAppAccessFromSession,
|
|
243
249
|
requireAppAccess,
|
|
250
|
+
requireAppAccessFromSession,
|
|
244
251
|
requirePermission,
|
|
245
252
|
hasPermission: hasPermissionInContext,
|
|
246
253
|
isSuperAdminEmail: (email) => isSuperAdminEmail(email, suffixes),
|
|
@@ -6,8 +6,12 @@ export type AuthAccessExtras = {
|
|
|
6
6
|
/**
|
|
7
7
|
* Return `false` to deny. Throw `redirect(...)` to send the user elsewhere.
|
|
8
8
|
* Any other return (including `void`) allows access.
|
|
9
|
+
*
|
|
10
|
+
* `headers` is present after a successful `loginWebApp`; otherwise it is
|
|
11
|
+
* built from the session (`X-User-Email` / `X-User-Token`). Prefer
|
|
12
|
+
* `rbac.hasAppAccessFromSession` so callers do not pass `{}`.
|
|
9
13
|
*/
|
|
10
|
-
requireAccess?: (session: AuthSession) => boolean | void | Promise<boolean | void>;
|
|
14
|
+
requireAccess?: (session: AuthSession, headers?: Record<string, string>) => boolean | void | Promise<boolean | void>;
|
|
11
15
|
};
|
|
12
16
|
export type LoginActionExtras = AuthAccessExtras & {
|
|
13
17
|
afterLogin?: (ctx: {
|
|
@@ -29,7 +29,9 @@ export declare function createWebappRbac(config: WebappRbacConfig): {
|
|
|
29
29
|
assignEmployeeRole: (headers: any, session: Session, body: AssignEmployeeRoleInput) => Promise<AxiosUtilsResponse<WebAppTableUpdateResponse>>;
|
|
30
30
|
resolveAccess: (headers: any, session: Session) => Promise<WebappAccessContext | null>;
|
|
31
31
|
hasAppAccess: (headers: any, session: Session) => Promise<boolean>;
|
|
32
|
+
hasAppAccessFromSession: (session: Session) => Promise<boolean>;
|
|
32
33
|
requireAppAccess: (headers: any, session: Session) => Promise<WebappAccessContext>;
|
|
34
|
+
requireAppAccessFromSession: (session: Session) => Promise<WebappAccessContext>;
|
|
33
35
|
requirePermission: (headers: any, session: Session, key: string) => Promise<WebappAccessContext>;
|
|
34
36
|
hasPermission: typeof hasPermissionInContext;
|
|
35
37
|
isSuperAdminEmail: (email: string | null | undefined) => boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zauru-sdk/utils",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.23.0",
|
|
4
4
|
"description": "Utilidades, parseo de request y demás para desarrollo de webapps de Zauru",
|
|
5
5
|
"main": "./dist/esm/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -78,5 +78,5 @@
|
|
|
78
78
|
"@zauru-sdk/types": "^6.24.0",
|
|
79
79
|
"moment": "^2.30.1"
|
|
80
80
|
},
|
|
81
|
-
"gitHead": "
|
|
81
|
+
"gitHead": "7020f7ea3b89b2c07998a5f7eb8586452c0cdc28"
|
|
82
82
|
}
|