@vegait/accounts-sdk 0.1.0-beta.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/README.md +25 -0
- package/dist/index.cjs +216 -0
- package/dist/index.d.cts +68 -0
- package/dist/index.d.ts +68 -0
- package/dist/index.js +180 -0
- package/package.json +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# @vegait/accounts-sdk
|
|
2
|
+
|
|
3
|
+
Cola de integracao frontend do Accounts: persona, catalogo de produtos VEGA,
|
|
4
|
+
tipos de claims e o adapter da casca de identidade (`buildIdentityModel`).
|
|
5
|
+
Puro TS — sem React, sem dependencia do design system.
|
|
6
|
+
|
|
7
|
+
## Uso
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { buildIdentityModel, decodeAccessToken } from "@vegait/accounts-sdk";
|
|
11
|
+
|
|
12
|
+
const claims = decodeAccessToken(accessToken);
|
|
13
|
+
const model = buildIdentityModel(claims, {
|
|
14
|
+
currentProductCode: "accounts",
|
|
15
|
+
urls: { "media-hub": mediaHubUrl }, // o host resolve o env; o SDK nunca toca process.env
|
|
16
|
+
});
|
|
17
|
+
// host mapeia `model` -> props da IdentityBar do @vegait/lyra-ds-v2
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## ⚠️ Seguranca: `derivePersona` NAO e autorizacao
|
|
21
|
+
|
|
22
|
+
`derivePersona` e o `IdentityModel` servem para **gating de apresentacao**
|
|
23
|
+
(o que mostrar/esconder na UI). **Nunca** os use como controle de acesso.
|
|
24
|
+
A autorizacao real e feita **server-side** (scopes/claims OIDC, RBAC+ABAC no
|
|
25
|
+
`accounts.api`). Gating de UI e defense-in-depth, nunca o unico controle.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
PRODUCT_CATALOG: () => PRODUCT_CATALOG,
|
|
24
|
+
buildIdentityModel: () => buildIdentityModel,
|
|
25
|
+
decodeAccessToken: () => decodeAccessToken,
|
|
26
|
+
decodeJwtPayload: () => decodeJwtPayload,
|
|
27
|
+
derivePersona: () => derivePersona,
|
|
28
|
+
getAccessibleProducts: () => getAccessibleProducts,
|
|
29
|
+
getCatalogWithAccess: () => getCatalogWithAccess,
|
|
30
|
+
normalizeClaimArray: () => normalizeClaimArray,
|
|
31
|
+
parseJsonArrayClaim: () => parseJsonArrayClaim,
|
|
32
|
+
resolveProduct: () => resolveProduct
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(index_exports);
|
|
35
|
+
|
|
36
|
+
// src/claims.ts
|
|
37
|
+
function decodeJwtPayload(token) {
|
|
38
|
+
const parts = token.split(".");
|
|
39
|
+
if (parts.length !== 3) {
|
|
40
|
+
throw new Error("Invalid JWT format");
|
|
41
|
+
}
|
|
42
|
+
const payload = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
43
|
+
const padded = payload + "=".repeat((4 - payload.length % 4) % 4);
|
|
44
|
+
const binary = atob(padded);
|
|
45
|
+
const bytes = new Uint8Array(binary.length);
|
|
46
|
+
for (let i = 0; i < binary.length; i++) {
|
|
47
|
+
bytes[i] = binary.charCodeAt(i);
|
|
48
|
+
}
|
|
49
|
+
const json = new TextDecoder("utf-8").decode(bytes);
|
|
50
|
+
return JSON.parse(json);
|
|
51
|
+
}
|
|
52
|
+
function normalizeClaimArray(value) {
|
|
53
|
+
if (!value) return [];
|
|
54
|
+
return Array.isArray(value) ? value : [value];
|
|
55
|
+
}
|
|
56
|
+
function parseJsonArrayClaim(value) {
|
|
57
|
+
if (!value) return [];
|
|
58
|
+
try {
|
|
59
|
+
const parsed = JSON.parse(value);
|
|
60
|
+
return Array.isArray(parsed) ? parsed.filter((v) => typeof v === "string") : [];
|
|
61
|
+
} catch {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function decodeAccessToken(token) {
|
|
66
|
+
if (!token) return null;
|
|
67
|
+
try {
|
|
68
|
+
return decodeJwtPayload(token);
|
|
69
|
+
} catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/persona.ts
|
|
75
|
+
function derivePersona(claims) {
|
|
76
|
+
if (claims?.platform_role) return "vega";
|
|
77
|
+
if (claims?.can_manage_scope_members === "true") return "gestor";
|
|
78
|
+
return "usuario";
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// src/productCatalog.ts
|
|
82
|
+
var PRODUCT_CATALOG = {
|
|
83
|
+
accounts: {
|
|
84
|
+
code: "accounts",
|
|
85
|
+
name: "Accounts",
|
|
86
|
+
description: "Identidade unificada do ecossistema",
|
|
87
|
+
url: "/",
|
|
88
|
+
accent: "#1F2E52",
|
|
89
|
+
ssoEnabled: true
|
|
90
|
+
// e o proprio IdP; excluido da gaveta de qualquer forma
|
|
91
|
+
},
|
|
92
|
+
"media-hub": {
|
|
93
|
+
code: "media-hub",
|
|
94
|
+
name: "Media Hub",
|
|
95
|
+
description: "Sinalizacao digital nas unidades",
|
|
96
|
+
url: "https://media-hub.vega.com.br/",
|
|
97
|
+
accent: "#EF802D",
|
|
98
|
+
ssoEnabled: true
|
|
99
|
+
},
|
|
100
|
+
sig: {
|
|
101
|
+
code: "sig",
|
|
102
|
+
name: "SIG",
|
|
103
|
+
description: "Housekeeping e governanca das unidades",
|
|
104
|
+
url: "https://sig.app.vegait.com/",
|
|
105
|
+
accent: "#B0C925",
|
|
106
|
+
ssoEnabled: true
|
|
107
|
+
},
|
|
108
|
+
gdi: {
|
|
109
|
+
code: "gdi",
|
|
110
|
+
name: "GDI",
|
|
111
|
+
description: "Gestao de dispositivos e internet",
|
|
112
|
+
url: "https://gdi.vega.com.br/",
|
|
113
|
+
accent: "#7B8B7E",
|
|
114
|
+
ssoEnabled: false
|
|
115
|
+
},
|
|
116
|
+
sim: {
|
|
117
|
+
code: "sim",
|
|
118
|
+
name: "SIM",
|
|
119
|
+
description: "Service Issue Management",
|
|
120
|
+
url: "https://sim.vega.com.br/",
|
|
121
|
+
accent: "#5B7DB1",
|
|
122
|
+
ssoEnabled: false
|
|
123
|
+
},
|
|
124
|
+
hxp: {
|
|
125
|
+
code: "hxp",
|
|
126
|
+
name: "HXP",
|
|
127
|
+
description: "Hotel Experience Platform",
|
|
128
|
+
url: "https://hxp.vega.com.br/",
|
|
129
|
+
accent: "#9B6A4F",
|
|
130
|
+
ssoEnabled: false
|
|
131
|
+
},
|
|
132
|
+
feedback: {
|
|
133
|
+
code: "feedback",
|
|
134
|
+
name: "Feedback",
|
|
135
|
+
description: "Pesquisas e NPS de hospedes",
|
|
136
|
+
url: "https://feedback.vega.com.br/",
|
|
137
|
+
accent: "#C26A8C",
|
|
138
|
+
ssoEnabled: false
|
|
139
|
+
},
|
|
140
|
+
behavior: {
|
|
141
|
+
code: "behavior",
|
|
142
|
+
name: "Behavior",
|
|
143
|
+
description: "Inteligencia comportamental",
|
|
144
|
+
url: "https://behavior.vega.com.br/",
|
|
145
|
+
accent: "#4A7C7E",
|
|
146
|
+
ssoEnabled: false
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
var LEGACY_CODE_ALIASES = {
|
|
150
|
+
governanca: "sig"
|
|
151
|
+
};
|
|
152
|
+
function resolveProduct(code, urls) {
|
|
153
|
+
const canonical = LEGACY_CODE_ALIASES[code] ?? code;
|
|
154
|
+
const base = PRODUCT_CATALOG[canonical] ?? {
|
|
155
|
+
code,
|
|
156
|
+
name: code,
|
|
157
|
+
description: "",
|
|
158
|
+
url: "#",
|
|
159
|
+
accent: "#1F2E52",
|
|
160
|
+
ssoEnabled: false
|
|
161
|
+
};
|
|
162
|
+
const override = urls?.[canonical];
|
|
163
|
+
return override ? { ...base, url: override } : base;
|
|
164
|
+
}
|
|
165
|
+
function getCatalogWithAccess(claims, opts) {
|
|
166
|
+
const urls = opts?.urls;
|
|
167
|
+
const isVega = claims != null && derivePersona(claims) === "vega";
|
|
168
|
+
const accessibleCodes = new Set(
|
|
169
|
+
parseJsonArrayClaim(claims?.products).map(
|
|
170
|
+
(code) => LEGACY_CODE_ALIASES[code] ?? code
|
|
171
|
+
)
|
|
172
|
+
);
|
|
173
|
+
return Object.values(PRODUCT_CATALOG).filter((p) => p.code !== "accounts").map((p) => ({
|
|
174
|
+
...urls?.[p.code] ? { ...p, url: urls[p.code] } : p,
|
|
175
|
+
accessible: isVega || accessibleCodes.has(p.code)
|
|
176
|
+
}));
|
|
177
|
+
}
|
|
178
|
+
function getAccessibleProducts(claims, opts) {
|
|
179
|
+
if (!claims) return [];
|
|
180
|
+
const urls = opts?.urls;
|
|
181
|
+
if (derivePersona(claims) === "vega") {
|
|
182
|
+
return Object.values(PRODUCT_CATALOG).filter((p) => p.code !== "accounts" && p.ssoEnabled).map((p) => urls?.[p.code] ? { ...p, url: urls[p.code] } : p);
|
|
183
|
+
}
|
|
184
|
+
return parseJsonArrayClaim(claims.products).map((code) => resolveProduct(code, urls)).filter((p) => p.ssoEnabled);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// src/identityModel.ts
|
|
188
|
+
function buildIdentityModel(claims, cfg) {
|
|
189
|
+
const persona = derivePersona(claims);
|
|
190
|
+
return {
|
|
191
|
+
persona,
|
|
192
|
+
user: { name: claims?.name ?? "", email: claims?.email ?? "" },
|
|
193
|
+
products: getAccessibleProducts(claims, { urls: cfg?.urls }),
|
|
194
|
+
catalog: getCatalogWithAccess(claims, { urls: cfg?.urls }),
|
|
195
|
+
currentProductCode: cfg?.currentProductCode,
|
|
196
|
+
capabilities: {
|
|
197
|
+
manageUsers: persona === "gestor" || persona === "vega",
|
|
198
|
+
adminConsole: persona === "vega",
|
|
199
|
+
switchContext: persona === "gestor" || persona === "vega",
|
|
200
|
+
manageNetwork: persona === "gestor"
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
205
|
+
0 && (module.exports = {
|
|
206
|
+
PRODUCT_CATALOG,
|
|
207
|
+
buildIdentityModel,
|
|
208
|
+
decodeAccessToken,
|
|
209
|
+
decodeJwtPayload,
|
|
210
|
+
derivePersona,
|
|
211
|
+
getAccessibleProducts,
|
|
212
|
+
getCatalogWithAccess,
|
|
213
|
+
normalizeClaimArray,
|
|
214
|
+
parseJsonArrayClaim,
|
|
215
|
+
resolveProduct
|
|
216
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
declare function decodeJwtPayload<T = Record<string, unknown>>(token: string): T;
|
|
2
|
+
type AccountsClaims = {
|
|
3
|
+
sub?: string;
|
|
4
|
+
email?: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
platform_role?: string;
|
|
7
|
+
can_manage_scope_members?: string;
|
|
8
|
+
org_id?: string | string[];
|
|
9
|
+
unit_ids?: string;
|
|
10
|
+
active_unit_id?: string;
|
|
11
|
+
products?: string;
|
|
12
|
+
exp?: number;
|
|
13
|
+
iat?: number;
|
|
14
|
+
iss?: string;
|
|
15
|
+
aud?: string | string[];
|
|
16
|
+
};
|
|
17
|
+
declare function normalizeClaimArray(value: string | string[] | undefined): string[];
|
|
18
|
+
declare function parseJsonArrayClaim(value: string | undefined): string[];
|
|
19
|
+
declare function decodeAccessToken(token: string | null | undefined): AccountsClaims | null;
|
|
20
|
+
|
|
21
|
+
type Persona = "usuario" | "gestor" | "vega";
|
|
22
|
+
declare function derivePersona(claims: AccountsClaims | null): Persona;
|
|
23
|
+
|
|
24
|
+
type ProductMeta = {
|
|
25
|
+
code: string;
|
|
26
|
+
name: string;
|
|
27
|
+
description: string;
|
|
28
|
+
url: string;
|
|
29
|
+
accent: string;
|
|
30
|
+
ssoEnabled: boolean;
|
|
31
|
+
};
|
|
32
|
+
declare const PRODUCT_CATALOG: Record<string, ProductMeta>;
|
|
33
|
+
declare function resolveProduct(code: string, urls?: Record<string, string>): ProductMeta;
|
|
34
|
+
type CatalogProduct = ProductMeta & {
|
|
35
|
+
accessible: boolean;
|
|
36
|
+
};
|
|
37
|
+
declare function getCatalogWithAccess(claims: AccountsClaims | null, opts?: {
|
|
38
|
+
urls?: Record<string, string>;
|
|
39
|
+
}): CatalogProduct[];
|
|
40
|
+
declare function getAccessibleProducts(claims: AccountsClaims | null, opts?: {
|
|
41
|
+
urls?: Record<string, string>;
|
|
42
|
+
}): ProductMeta[];
|
|
43
|
+
|
|
44
|
+
type IdentityModel = {
|
|
45
|
+
persona: Persona;
|
|
46
|
+
user: {
|
|
47
|
+
name: string;
|
|
48
|
+
email: string;
|
|
49
|
+
};
|
|
50
|
+
products: ProductMeta[];
|
|
51
|
+
/** Catalogo completo (menos Accounts) com flag de acesso — pro waffle
|
|
52
|
+
* mostrar tudo e desabilitar o que a persona nao acessa. `products`
|
|
53
|
+
* permanece so-acessiveis por retrocompat (SIG consome hoje). */
|
|
54
|
+
catalog: CatalogProduct[];
|
|
55
|
+
currentProductCode?: string;
|
|
56
|
+
capabilities: {
|
|
57
|
+
manageUsers: boolean;
|
|
58
|
+
adminConsole: boolean;
|
|
59
|
+
switchContext: boolean;
|
|
60
|
+
manageNetwork: boolean;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
declare function buildIdentityModel(claims: AccountsClaims | null, cfg?: {
|
|
64
|
+
currentProductCode?: string;
|
|
65
|
+
urls?: Record<string, string>;
|
|
66
|
+
}): IdentityModel;
|
|
67
|
+
|
|
68
|
+
export { type AccountsClaims, type CatalogProduct, type IdentityModel, PRODUCT_CATALOG, type Persona, type ProductMeta, buildIdentityModel, decodeAccessToken, decodeJwtPayload, derivePersona, getAccessibleProducts, getCatalogWithAccess, normalizeClaimArray, parseJsonArrayClaim, resolveProduct };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
declare function decodeJwtPayload<T = Record<string, unknown>>(token: string): T;
|
|
2
|
+
type AccountsClaims = {
|
|
3
|
+
sub?: string;
|
|
4
|
+
email?: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
platform_role?: string;
|
|
7
|
+
can_manage_scope_members?: string;
|
|
8
|
+
org_id?: string | string[];
|
|
9
|
+
unit_ids?: string;
|
|
10
|
+
active_unit_id?: string;
|
|
11
|
+
products?: string;
|
|
12
|
+
exp?: number;
|
|
13
|
+
iat?: number;
|
|
14
|
+
iss?: string;
|
|
15
|
+
aud?: string | string[];
|
|
16
|
+
};
|
|
17
|
+
declare function normalizeClaimArray(value: string | string[] | undefined): string[];
|
|
18
|
+
declare function parseJsonArrayClaim(value: string | undefined): string[];
|
|
19
|
+
declare function decodeAccessToken(token: string | null | undefined): AccountsClaims | null;
|
|
20
|
+
|
|
21
|
+
type Persona = "usuario" | "gestor" | "vega";
|
|
22
|
+
declare function derivePersona(claims: AccountsClaims | null): Persona;
|
|
23
|
+
|
|
24
|
+
type ProductMeta = {
|
|
25
|
+
code: string;
|
|
26
|
+
name: string;
|
|
27
|
+
description: string;
|
|
28
|
+
url: string;
|
|
29
|
+
accent: string;
|
|
30
|
+
ssoEnabled: boolean;
|
|
31
|
+
};
|
|
32
|
+
declare const PRODUCT_CATALOG: Record<string, ProductMeta>;
|
|
33
|
+
declare function resolveProduct(code: string, urls?: Record<string, string>): ProductMeta;
|
|
34
|
+
type CatalogProduct = ProductMeta & {
|
|
35
|
+
accessible: boolean;
|
|
36
|
+
};
|
|
37
|
+
declare function getCatalogWithAccess(claims: AccountsClaims | null, opts?: {
|
|
38
|
+
urls?: Record<string, string>;
|
|
39
|
+
}): CatalogProduct[];
|
|
40
|
+
declare function getAccessibleProducts(claims: AccountsClaims | null, opts?: {
|
|
41
|
+
urls?: Record<string, string>;
|
|
42
|
+
}): ProductMeta[];
|
|
43
|
+
|
|
44
|
+
type IdentityModel = {
|
|
45
|
+
persona: Persona;
|
|
46
|
+
user: {
|
|
47
|
+
name: string;
|
|
48
|
+
email: string;
|
|
49
|
+
};
|
|
50
|
+
products: ProductMeta[];
|
|
51
|
+
/** Catalogo completo (menos Accounts) com flag de acesso — pro waffle
|
|
52
|
+
* mostrar tudo e desabilitar o que a persona nao acessa. `products`
|
|
53
|
+
* permanece so-acessiveis por retrocompat (SIG consome hoje). */
|
|
54
|
+
catalog: CatalogProduct[];
|
|
55
|
+
currentProductCode?: string;
|
|
56
|
+
capabilities: {
|
|
57
|
+
manageUsers: boolean;
|
|
58
|
+
adminConsole: boolean;
|
|
59
|
+
switchContext: boolean;
|
|
60
|
+
manageNetwork: boolean;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
declare function buildIdentityModel(claims: AccountsClaims | null, cfg?: {
|
|
64
|
+
currentProductCode?: string;
|
|
65
|
+
urls?: Record<string, string>;
|
|
66
|
+
}): IdentityModel;
|
|
67
|
+
|
|
68
|
+
export { type AccountsClaims, type CatalogProduct, type IdentityModel, PRODUCT_CATALOG, type Persona, type ProductMeta, buildIdentityModel, decodeAccessToken, decodeJwtPayload, derivePersona, getAccessibleProducts, getCatalogWithAccess, normalizeClaimArray, parseJsonArrayClaim, resolveProduct };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// src/claims.ts
|
|
2
|
+
function decodeJwtPayload(token) {
|
|
3
|
+
const parts = token.split(".");
|
|
4
|
+
if (parts.length !== 3) {
|
|
5
|
+
throw new Error("Invalid JWT format");
|
|
6
|
+
}
|
|
7
|
+
const payload = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
8
|
+
const padded = payload + "=".repeat((4 - payload.length % 4) % 4);
|
|
9
|
+
const binary = atob(padded);
|
|
10
|
+
const bytes = new Uint8Array(binary.length);
|
|
11
|
+
for (let i = 0; i < binary.length; i++) {
|
|
12
|
+
bytes[i] = binary.charCodeAt(i);
|
|
13
|
+
}
|
|
14
|
+
const json = new TextDecoder("utf-8").decode(bytes);
|
|
15
|
+
return JSON.parse(json);
|
|
16
|
+
}
|
|
17
|
+
function normalizeClaimArray(value) {
|
|
18
|
+
if (!value) return [];
|
|
19
|
+
return Array.isArray(value) ? value : [value];
|
|
20
|
+
}
|
|
21
|
+
function parseJsonArrayClaim(value) {
|
|
22
|
+
if (!value) return [];
|
|
23
|
+
try {
|
|
24
|
+
const parsed = JSON.parse(value);
|
|
25
|
+
return Array.isArray(parsed) ? parsed.filter((v) => typeof v === "string") : [];
|
|
26
|
+
} catch {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function decodeAccessToken(token) {
|
|
31
|
+
if (!token) return null;
|
|
32
|
+
try {
|
|
33
|
+
return decodeJwtPayload(token);
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/persona.ts
|
|
40
|
+
function derivePersona(claims) {
|
|
41
|
+
if (claims?.platform_role) return "vega";
|
|
42
|
+
if (claims?.can_manage_scope_members === "true") return "gestor";
|
|
43
|
+
return "usuario";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// src/productCatalog.ts
|
|
47
|
+
var PRODUCT_CATALOG = {
|
|
48
|
+
accounts: {
|
|
49
|
+
code: "accounts",
|
|
50
|
+
name: "Accounts",
|
|
51
|
+
description: "Identidade unificada do ecossistema",
|
|
52
|
+
url: "/",
|
|
53
|
+
accent: "#1F2E52",
|
|
54
|
+
ssoEnabled: true
|
|
55
|
+
// e o proprio IdP; excluido da gaveta de qualquer forma
|
|
56
|
+
},
|
|
57
|
+
"media-hub": {
|
|
58
|
+
code: "media-hub",
|
|
59
|
+
name: "Media Hub",
|
|
60
|
+
description: "Sinalizacao digital nas unidades",
|
|
61
|
+
url: "https://media-hub.vega.com.br/",
|
|
62
|
+
accent: "#EF802D",
|
|
63
|
+
ssoEnabled: true
|
|
64
|
+
},
|
|
65
|
+
sig: {
|
|
66
|
+
code: "sig",
|
|
67
|
+
name: "SIG",
|
|
68
|
+
description: "Housekeeping e governanca das unidades",
|
|
69
|
+
url: "https://sig.app.vegait.com/",
|
|
70
|
+
accent: "#B0C925",
|
|
71
|
+
ssoEnabled: true
|
|
72
|
+
},
|
|
73
|
+
gdi: {
|
|
74
|
+
code: "gdi",
|
|
75
|
+
name: "GDI",
|
|
76
|
+
description: "Gestao de dispositivos e internet",
|
|
77
|
+
url: "https://gdi.vega.com.br/",
|
|
78
|
+
accent: "#7B8B7E",
|
|
79
|
+
ssoEnabled: false
|
|
80
|
+
},
|
|
81
|
+
sim: {
|
|
82
|
+
code: "sim",
|
|
83
|
+
name: "SIM",
|
|
84
|
+
description: "Service Issue Management",
|
|
85
|
+
url: "https://sim.vega.com.br/",
|
|
86
|
+
accent: "#5B7DB1",
|
|
87
|
+
ssoEnabled: false
|
|
88
|
+
},
|
|
89
|
+
hxp: {
|
|
90
|
+
code: "hxp",
|
|
91
|
+
name: "HXP",
|
|
92
|
+
description: "Hotel Experience Platform",
|
|
93
|
+
url: "https://hxp.vega.com.br/",
|
|
94
|
+
accent: "#9B6A4F",
|
|
95
|
+
ssoEnabled: false
|
|
96
|
+
},
|
|
97
|
+
feedback: {
|
|
98
|
+
code: "feedback",
|
|
99
|
+
name: "Feedback",
|
|
100
|
+
description: "Pesquisas e NPS de hospedes",
|
|
101
|
+
url: "https://feedback.vega.com.br/",
|
|
102
|
+
accent: "#C26A8C",
|
|
103
|
+
ssoEnabled: false
|
|
104
|
+
},
|
|
105
|
+
behavior: {
|
|
106
|
+
code: "behavior",
|
|
107
|
+
name: "Behavior",
|
|
108
|
+
description: "Inteligencia comportamental",
|
|
109
|
+
url: "https://behavior.vega.com.br/",
|
|
110
|
+
accent: "#4A7C7E",
|
|
111
|
+
ssoEnabled: false
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
var LEGACY_CODE_ALIASES = {
|
|
115
|
+
governanca: "sig"
|
|
116
|
+
};
|
|
117
|
+
function resolveProduct(code, urls) {
|
|
118
|
+
const canonical = LEGACY_CODE_ALIASES[code] ?? code;
|
|
119
|
+
const base = PRODUCT_CATALOG[canonical] ?? {
|
|
120
|
+
code,
|
|
121
|
+
name: code,
|
|
122
|
+
description: "",
|
|
123
|
+
url: "#",
|
|
124
|
+
accent: "#1F2E52",
|
|
125
|
+
ssoEnabled: false
|
|
126
|
+
};
|
|
127
|
+
const override = urls?.[canonical];
|
|
128
|
+
return override ? { ...base, url: override } : base;
|
|
129
|
+
}
|
|
130
|
+
function getCatalogWithAccess(claims, opts) {
|
|
131
|
+
const urls = opts?.urls;
|
|
132
|
+
const isVega = claims != null && derivePersona(claims) === "vega";
|
|
133
|
+
const accessibleCodes = new Set(
|
|
134
|
+
parseJsonArrayClaim(claims?.products).map(
|
|
135
|
+
(code) => LEGACY_CODE_ALIASES[code] ?? code
|
|
136
|
+
)
|
|
137
|
+
);
|
|
138
|
+
return Object.values(PRODUCT_CATALOG).filter((p) => p.code !== "accounts").map((p) => ({
|
|
139
|
+
...urls?.[p.code] ? { ...p, url: urls[p.code] } : p,
|
|
140
|
+
accessible: isVega || accessibleCodes.has(p.code)
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
143
|
+
function getAccessibleProducts(claims, opts) {
|
|
144
|
+
if (!claims) return [];
|
|
145
|
+
const urls = opts?.urls;
|
|
146
|
+
if (derivePersona(claims) === "vega") {
|
|
147
|
+
return Object.values(PRODUCT_CATALOG).filter((p) => p.code !== "accounts" && p.ssoEnabled).map((p) => urls?.[p.code] ? { ...p, url: urls[p.code] } : p);
|
|
148
|
+
}
|
|
149
|
+
return parseJsonArrayClaim(claims.products).map((code) => resolveProduct(code, urls)).filter((p) => p.ssoEnabled);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// src/identityModel.ts
|
|
153
|
+
function buildIdentityModel(claims, cfg) {
|
|
154
|
+
const persona = derivePersona(claims);
|
|
155
|
+
return {
|
|
156
|
+
persona,
|
|
157
|
+
user: { name: claims?.name ?? "", email: claims?.email ?? "" },
|
|
158
|
+
products: getAccessibleProducts(claims, { urls: cfg?.urls }),
|
|
159
|
+
catalog: getCatalogWithAccess(claims, { urls: cfg?.urls }),
|
|
160
|
+
currentProductCode: cfg?.currentProductCode,
|
|
161
|
+
capabilities: {
|
|
162
|
+
manageUsers: persona === "gestor" || persona === "vega",
|
|
163
|
+
adminConsole: persona === "vega",
|
|
164
|
+
switchContext: persona === "gestor" || persona === "vega",
|
|
165
|
+
manageNetwork: persona === "gestor"
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
export {
|
|
170
|
+
PRODUCT_CATALOG,
|
|
171
|
+
buildIdentityModel,
|
|
172
|
+
decodeAccessToken,
|
|
173
|
+
decodeJwtPayload,
|
|
174
|
+
derivePersona,
|
|
175
|
+
getAccessibleProducts,
|
|
176
|
+
getCatalogWithAccess,
|
|
177
|
+
normalizeClaimArray,
|
|
178
|
+
parseJsonArrayClaim,
|
|
179
|
+
resolveProduct
|
|
180
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vegait/accounts-sdk",
|
|
3
|
+
"version": "0.1.0-beta.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public",
|
|
6
|
+
"tag": "beta"
|
|
7
|
+
},
|
|
8
|
+
"description": "Cola de integracao frontend do Accounts (persona, catalogo de produtos, adapter da casca de identidade).",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"main": "./dist/index.cjs",
|
|
11
|
+
"module": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"require": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsup",
|
|
26
|
+
"prepublishOnly": "tsup",
|
|
27
|
+
"test": "vitest run",
|
|
28
|
+
"typecheck": "tsc --noEmit"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"tsup": "^8.0.0",
|
|
32
|
+
"typescript": "^5.4.0",
|
|
33
|
+
"vitest": "^2.0.0"
|
|
34
|
+
}
|
|
35
|
+
}
|