@oondemand/oon-core-back 0.3.0 → 0.3.4
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/package.json
CHANGED
package/src/api/auth.routes.js
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
const express = require("express");
|
|
2
2
|
const axios = require("axios");
|
|
3
|
-
const ctx = require("../core/context");
|
|
4
3
|
const auth = require("../core/middlewares/auth");
|
|
4
|
+
const ctx = require("../core/context");
|
|
5
5
|
const GenericError = require("../core/errors/GenericError");
|
|
6
|
+
const { asyncHandler, sendResponse } = require("../core/utils/helpers");
|
|
6
7
|
const {
|
|
7
8
|
LOGIN_PATH,
|
|
8
9
|
getBaseUrl,
|
|
9
10
|
getAppCode,
|
|
10
11
|
getTimeout,
|
|
11
12
|
} = require("../core/utils/activationProvider");
|
|
12
|
-
const {
|
|
13
|
-
ensureInstance,
|
|
14
|
-
instanceHeaders,
|
|
15
|
-
} = require("../core/utils/instanceActivation");
|
|
16
|
-
const { asyncHandler, sendResponse } = require("../core/utils/helpers");
|
|
17
13
|
|
|
14
|
+
const DEV_ACTIVATION_PATH = "/integracao/dev-local/ativar-central";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Rotas de autenticação do Core. Em aplicações member, o login é delegado para
|
|
18
|
+
* a Central de Ativações com o código do app carregado do ambiente do backend.
|
|
19
|
+
*/
|
|
18
20
|
const router = express.Router();
|
|
19
21
|
|
|
20
22
|
function readBasicAuthorization(req) {
|
|
@@ -27,23 +29,21 @@ function readBasicAuthorization(req) {
|
|
|
27
29
|
return authorization;
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
function
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return instanceHeaders(instance);
|
|
32
|
+
function readOptionalAppCode() {
|
|
33
|
+
return String(
|
|
34
|
+
process.env.APP_CODE ||
|
|
35
|
+
process.env.APP_CODIGO ||
|
|
36
|
+
process.env.OON_APP_CODE ||
|
|
37
|
+
process.env.OON_APP_CODIGO ||
|
|
38
|
+
"",
|
|
39
|
+
)
|
|
40
|
+
.trim()
|
|
41
|
+
.toLowerCase();
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
function translateProviderError(error) {
|
|
46
45
|
if (error instanceof GenericError) return error;
|
|
46
|
+
|
|
47
47
|
const timedOut = error.code === "ECONNABORTED";
|
|
48
48
|
const statusCode = timedOut ? 504 : error.response?.status || 502;
|
|
49
49
|
const message =
|
|
@@ -51,17 +51,13 @@ function translateProviderError(error) {
|
|
|
51
51
|
(timedOut
|
|
52
52
|
? "A Central de Ativações não respondeu dentro do prazo."
|
|
53
53
|
: "Não foi possível autenticar o usuário na Central de Ativações.");
|
|
54
|
+
|
|
54
55
|
return new GenericError(message, { statusCode });
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
async function
|
|
58
|
+
async function authenticateLocal(req, res, authorization) {
|
|
58
59
|
const authenticate = ctx.config.auth?.authenticate;
|
|
59
|
-
if (typeof authenticate !== "function")
|
|
60
|
-
throw new GenericError(
|
|
61
|
-
"A aplicação root não configurou a autenticação local.",
|
|
62
|
-
{ statusCode: 500 },
|
|
63
|
-
);
|
|
64
|
-
}
|
|
60
|
+
if (typeof authenticate !== "function") return false;
|
|
65
61
|
|
|
66
62
|
const result = await authenticate({ authorization, req });
|
|
67
63
|
const statusCode = result?.statusCode || 200;
|
|
@@ -69,17 +65,15 @@ async function authenticateRoot(req, res, authorization) {
|
|
|
69
65
|
|
|
70
66
|
res.set("Cache-Control", "no-store");
|
|
71
67
|
res.status(statusCode).json(data);
|
|
68
|
+
return true;
|
|
72
69
|
}
|
|
73
70
|
|
|
74
71
|
router.post(
|
|
75
72
|
"/autenticar",
|
|
76
73
|
asyncHandler(async (req, res) => {
|
|
77
74
|
const authorization = readBasicAuthorization(req);
|
|
78
|
-
const instance = await ensureInstance();
|
|
79
75
|
|
|
80
|
-
if (
|
|
81
|
-
return authenticateRoot(req, res, authorization);
|
|
82
|
-
}
|
|
76
|
+
if (await authenticateLocal(req, res, authorization)) return;
|
|
83
77
|
|
|
84
78
|
const baseUrl = getBaseUrl(req);
|
|
85
79
|
const appCode = getAppCode();
|
|
@@ -87,7 +81,10 @@ router.post(
|
|
|
87
81
|
try {
|
|
88
82
|
const response = await axios.post(
|
|
89
83
|
`${baseUrl}${LOGIN_PATH}`,
|
|
90
|
-
{
|
|
84
|
+
{
|
|
85
|
+
codigoApp: appCode,
|
|
86
|
+
codigo: appCode,
|
|
87
|
+
},
|
|
91
88
|
{
|
|
92
89
|
timeout: getTimeout(),
|
|
93
90
|
maxRedirects: 0,
|
|
@@ -95,7 +92,46 @@ router.post(
|
|
|
95
92
|
Authorization: authorization,
|
|
96
93
|
"Content-Type": "application/json",
|
|
97
94
|
"x-app-code": appCode,
|
|
98
|
-
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
res.set("Cache-Control", "no-store");
|
|
100
|
+
res.status(response.status).json(response.data);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
throw translateProviderError(error);
|
|
103
|
+
}
|
|
104
|
+
}),
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
router.post(
|
|
108
|
+
"/ativar-dev-local",
|
|
109
|
+
asyncHandler(async (req, res) => {
|
|
110
|
+
const authorization = readBasicAuthorization(req);
|
|
111
|
+
const baseUrl = getBaseUrl(req);
|
|
112
|
+
const appCode = readOptionalAppCode();
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
const response = await axios.post(
|
|
116
|
+
`${baseUrl}${DEV_ACTIVATION_PATH}`,
|
|
117
|
+
{
|
|
118
|
+
appCode: appCode || req.body?.appCode || req.body?.codigoApp,
|
|
119
|
+
nomeCentral: req.body?.nomeCentral || ctx.config.name,
|
|
120
|
+
appName: req.body?.appName || ctx.config.name,
|
|
121
|
+
appSlug: req.body?.appSlug || ctx.config.slug,
|
|
122
|
+
ambiente: req.body?.ambiente || process.env.NODE_ENV || "development",
|
|
123
|
+
urlPublica: req.body?.urlPublica,
|
|
124
|
+
repositorio: req.body?.repositorio,
|
|
125
|
+
branch: req.body?.branch,
|
|
126
|
+
nomeUsuario: req.body?.nomeUsuario,
|
|
127
|
+
nomeTenant: req.body?.nomeTenant,
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
timeout: getTimeout(),
|
|
131
|
+
maxRedirects: 0,
|
|
132
|
+
headers: {
|
|
133
|
+
Authorization: authorization,
|
|
134
|
+
"Content-Type": "application/json",
|
|
99
135
|
},
|
|
100
136
|
},
|
|
101
137
|
);
|
|
@@ -7,76 +7,42 @@ const {
|
|
|
7
7
|
getAppCode,
|
|
8
8
|
getTimeout,
|
|
9
9
|
} = require("../utils/activationProvider");
|
|
10
|
-
const {
|
|
11
|
-
ensureInstance,
|
|
12
|
-
instanceHeaders,
|
|
13
|
-
} = require("../utils/instanceActivation");
|
|
14
|
-
|
|
15
|
-
function resolveInstanceHeaders(instance) {
|
|
16
|
-
if (instance.ecosystemRole !== "member") return {};
|
|
17
|
-
|
|
18
|
-
if (!instance.instanceId) {
|
|
19
|
-
if (process.env.NODE_TEST_CONTEXT) return {};
|
|
20
10
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return instanceHeaders(instance);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async function defaultVerifyToken(token, context = {}) {
|
|
32
|
-
const baseUrl = getBaseUrl(context.req);
|
|
11
|
+
/**
|
|
12
|
+
* Verificador padrão: delega para a Central de Ativações e valida o token no
|
|
13
|
+
* contexto do app configurado no backend por APP_CODE/APP_CODIGO.
|
|
14
|
+
* Pode ser sobrescrito via `central.config.js -> auth.verifyToken`.
|
|
15
|
+
*/
|
|
16
|
+
async function defaultVerifyToken(token, { req } = {}) {
|
|
17
|
+
const baseUrl = getBaseUrl(req);
|
|
33
18
|
const appCode = getAppCode();
|
|
34
|
-
const instance = await ensureInstance();
|
|
35
19
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
20
|
+
const response = await axios.get(`${baseUrl}${PERMISSION_PATH}`, {
|
|
21
|
+
timeout: getTimeout(),
|
|
22
|
+
maxRedirects: 0,
|
|
23
|
+
headers: {
|
|
39
24
|
Authorization: `Bearer ${token}`,
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (!data) {
|
|
51
|
-
const error = new Error(
|
|
52
|
-
"Usuário não retornado pela Central de Ativações.",
|
|
53
|
-
);
|
|
54
|
-
error.statusCode = 502;
|
|
55
|
-
throw error;
|
|
56
|
-
}
|
|
25
|
+
"x-app-code": appCode,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const data = response.data.usuario;
|
|
30
|
+
if (!data) {
|
|
31
|
+
const err = new Error("Usuário não retornado pela Central de Ativações.");
|
|
32
|
+
err.statusCode = 401;
|
|
33
|
+
throw err;
|
|
34
|
+
}
|
|
57
35
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
tipo:
|
|
61
|
-
data.tipo === "master" || data.perfil === "administrador"
|
|
62
|
-
? "admin"
|
|
63
|
-
: data.tipo || data.perfil,
|
|
64
|
-
};
|
|
65
|
-
} catch (error) {
|
|
66
|
-
if (error.statusCode) throw error;
|
|
36
|
+
const tipoAcesso =
|
|
37
|
+
data.aplicativo?.tipoAcesso || data.tipoAcesso || data.perfil || data.tipo;
|
|
67
38
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
translated.statusCode = timedOut
|
|
76
|
-
? 504
|
|
77
|
-
: error.response?.status || 502;
|
|
78
|
-
throw translated;
|
|
79
|
-
}
|
|
39
|
+
return {
|
|
40
|
+
...data,
|
|
41
|
+
tipo: tipoAcesso === "master" ? "admin" : tipoAcesso,
|
|
42
|
+
perfil: data.perfil || tipoAcesso,
|
|
43
|
+
nome: data.nome,
|
|
44
|
+
email: data.email,
|
|
45
|
+
};
|
|
80
46
|
}
|
|
81
47
|
|
|
82
48
|
const authMiddleware = async (req, res, next) => {
|
|
@@ -102,16 +68,11 @@ const authMiddleware = async (req, res, next) => {
|
|
|
102
68
|
req.usuario = usuario;
|
|
103
69
|
next();
|
|
104
70
|
} catch (error) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
? "Token inválido ou expirado."
|
|
111
|
-
: error.message ||
|
|
112
|
-
"Erro ao validar autenticação e permissão do aplicativo.";
|
|
113
|
-
|
|
114
|
-
return Helpers.sendErrorResponse({ res, message, statusCode });
|
|
71
|
+
return Helpers.sendErrorResponse({
|
|
72
|
+
res,
|
|
73
|
+
message: error.message || "Token inválido ou erro na autenticação.",
|
|
74
|
+
statusCode: error.statusCode || error.response?.status || 401,
|
|
75
|
+
});
|
|
115
76
|
}
|
|
116
77
|
};
|
|
117
78
|
|
|
@@ -6,14 +6,18 @@ const PERMISSION_PATH = "/integracao/autenticacao-aplicativos/verificar-permissa
|
|
|
6
6
|
function getBaseUrl(req) {
|
|
7
7
|
const value = process.env.CENTRAL_ATIVACAO_URL || process.env.MEUS_APPS_BACKEND_URL;
|
|
8
8
|
if (!value) {
|
|
9
|
-
throw new GenericError("CENTRAL_ATIVACAO_URL não configurada.", {
|
|
9
|
+
throw new GenericError("CENTRAL_ATIVACAO_URL não configurada.", {
|
|
10
|
+
statusCode: 500,
|
|
11
|
+
});
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
let parsed;
|
|
13
15
|
try {
|
|
14
16
|
parsed = new URL(value);
|
|
15
17
|
} catch {
|
|
16
|
-
throw new GenericError("CENTRAL_ATIVACAO_URL inválida.", {
|
|
18
|
+
throw new GenericError("CENTRAL_ATIVACAO_URL inválida.", {
|
|
19
|
+
statusCode: 500,
|
|
20
|
+
});
|
|
17
21
|
}
|
|
18
22
|
|
|
19
23
|
const currentHost = String(
|
|
@@ -38,12 +42,22 @@ function getBaseUrl(req) {
|
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
function getAppCode() {
|
|
41
|
-
const value = String(
|
|
45
|
+
const value = String(
|
|
46
|
+
process.env.APP_CODE ||
|
|
47
|
+
process.env.APP_CODIGO ||
|
|
48
|
+
process.env.OON_APP_CODE ||
|
|
49
|
+
process.env.OON_APP_CODIGO ||
|
|
50
|
+
"",
|
|
51
|
+
)
|
|
42
52
|
.trim()
|
|
43
53
|
.toLowerCase();
|
|
54
|
+
|
|
44
55
|
if (value) return value;
|
|
45
56
|
if (process.env.NODE_TEST_CONTEXT) return "oon-core-test";
|
|
46
|
-
|
|
57
|
+
|
|
58
|
+
throw new GenericError("APP_CODE não configurada no backend.", {
|
|
59
|
+
statusCode: 500,
|
|
60
|
+
});
|
|
47
61
|
}
|
|
48
62
|
|
|
49
63
|
function getTimeout() {
|
|
@@ -51,4 +65,10 @@ function getTimeout() {
|
|
|
51
65
|
return Number.isFinite(value) && value > 0 ? value : 10000;
|
|
52
66
|
}
|
|
53
67
|
|
|
54
|
-
module.exports = {
|
|
68
|
+
module.exports = {
|
|
69
|
+
LOGIN_PATH,
|
|
70
|
+
PERMISSION_PATH,
|
|
71
|
+
getBaseUrl,
|
|
72
|
+
getAppCode,
|
|
73
|
+
getTimeout,
|
|
74
|
+
};
|