@drax/identity-back 0.46.0 → 0.49.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.
@@ -8,6 +8,7 @@ var IdentityConfig;
8
8
  IdentityConfig["RbacCacheTTL"] = "DRAX_RBAC_CACHE_TTL";
9
9
  IdentityConfig["AvatarDir"] = "DRAX_AVATAR_DIR";
10
10
  IdentityConfig["defaultRole"] = "DRAX_DEFAULT_ROLE";
11
+ IdentityConfig["VerifyIP"] = "DRAX_VERIFY_IP";
11
12
  })(IdentityConfig || (IdentityConfig = {}));
12
13
  export default IdentityConfig;
13
14
  export { IdentityConfig };
@@ -1,7 +1,8 @@
1
1
  import { DraxCache, DraxConfig } from "@drax/common-back";
2
2
  import UserApiKeyServiceFactory from "../factory/UserApiKeyServiceFactory.js";
3
3
  import IdentityConfig from "../config/IdentityConfig.js";
4
- const cacheTTL = DraxConfig.getOrLoad(IdentityConfig.ApiKeyCacheTTL) ? parseInt(DraxConfig.getOrLoad(IdentityConfig.ApiKeyCacheTTL)) : 10000;
4
+ const verifyIp = DraxConfig.getOrLoad(IdentityConfig.VerifyIP, 'boolean', true);
5
+ const cacheTTL = DraxConfig.getOrLoad(IdentityConfig.ApiKeyCacheTTL, 'number', 10000);
5
6
  const draxCache = new DraxCache(cacheTTL);
6
7
  async function userApiKeyLoader(k) {
7
8
  const userApiKeyService = UserApiKeyServiceFactory();
@@ -27,6 +28,22 @@ async function apiKeyMiddleware(request, reply) {
27
28
  }
28
29
  if (apiKey) {
29
30
  const userApiKey = await draxCache.getOrLoad(apiKey, userApiKeyLoader);
31
+ if (verifyIp) {
32
+ if (userApiKey.ipv4 && userApiKey.ipv4.length > 0) {
33
+ const clientIp = request.ip;
34
+ if (!userApiKey.ipv4.includes(clientIp)) {
35
+ reply.code(401).send({ "statusCode": "401", error: 'IP not allowed', i18nMessage: 'error.ipNotAllowed', clientIp: clientIp, message: `Remote IP ${clientIp} is not allowed` });
36
+ return;
37
+ }
38
+ }
39
+ else if (userApiKey.ipv6 && userApiKey.ipv6.length > 0) {
40
+ const clientIp = request.ip;
41
+ if (!userApiKey.ipv6.includes(clientIp)) {
42
+ reply.code(401).send({ "statusCode": "401", error: 'IP not allowed', i18nMessage: 'error.ipNotAllowed', clientIp: clientIp, message: `Remote IP ${clientIp} is not allowed` });
43
+ return;
44
+ }
45
+ }
46
+ }
30
47
  if (userApiKey && userApiKey.user) {
31
48
  const authUser = {
32
49
  id: userApiKey.user._id.toString(),
@@ -2,7 +2,7 @@ import { DraxCache, DraxConfig } from "@drax/common-back";
2
2
  import RoleServiceFactory from "../factory/RoleServiceFactory.js";
3
3
  import Rbac from "../rbac/Rbac.js";
4
4
  import IdentityConfig from "../config/IdentityConfig.js";
5
- const cacheTTL = DraxConfig.getOrLoad(IdentityConfig.RbacCacheTTL) ? parseInt(DraxConfig.getOrLoad(IdentityConfig.RbacCacheTTL)) : 10000;
5
+ const cacheTTL = DraxConfig.getOrLoad(IdentityConfig.RbacCacheTTL, 'number', 10000);
6
6
  const draxCache = new DraxCache(cacheTTL);
7
7
  async function roleLoader(k) {
8
8
  const roleService = RoleServiceFactory();
@@ -32,12 +32,13 @@ class UserApiKeySqliteRepository extends AbstractSqliteRepository {
32
32
  if (item && item.createdBy) {
33
33
  item.createdBy = await this.findUserById(item.createdBy);
34
34
  }
35
- if (item && item.ipv4) {
36
- item.ipv4 = item.ipv4 != "" ? item.ipv4.split(',') : [];
35
+ if (item && item.hasOwnProperty('ipv4')) {
36
+ item.ipv4 = item.ipv4 ? item.ipv4.split(',') : [];
37
37
  }
38
- if (item && item.ipv6) {
39
- item.ipv6 = item.ipv6 != "" ? item.ipv6.split(',') : [];
38
+ if (item && item.hasOwnProperty('ipv6')) {
39
+ item.ipv6 = item.ipv6 ? item.ipv6.split(',') : [];
40
40
  }
41
+ return item;
41
42
  }
42
43
  async prepareData(userApiKeyData) {
43
44
  if (userApiKeyData.ipv4 && Array.isArray(userApiKeyData.ipv4) && userApiKeyData.ipv4.length > 0) {
@@ -52,6 +53,12 @@ class UserApiKeySqliteRepository extends AbstractSqliteRepository {
52
53
  else {
53
54
  userApiKeyData.ipv6 = "";
54
55
  }
56
+ if (userApiKeyData.user && userApiKeyData.user.hasOwnProperty('_id')) {
57
+ userApiKeyData.user = userApiKeyData.user._id;
58
+ }
59
+ if (userApiKeyData.createdBy && userApiKeyData.createdBy.hasOwnProperty('_id')) {
60
+ userApiKeyData.createdBy = userApiKeyData.createdBy._id;
61
+ }
55
62
  }
56
63
  async findBySecret(secret) {
57
64
  const userApiKey = this.db.prepare('SELECT * FROM user_api_keys WHERE secret = ?').get(secret);
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.46.0",
6
+ "version": "0.49.0",
7
7
  "description": "Identity module for user management, authentication and authorization.",
8
8
  "main": "dist/index.js",
9
9
  "types": "types/index.d.ts",
@@ -28,11 +28,11 @@
28
28
  "author": "Cristian Incarnato & Drax Team",
29
29
  "license": "ISC",
30
30
  "dependencies": {
31
- "@drax/common-back": "^0.46.0",
32
- "@drax/crud-back": "^0.46.0",
33
- "@drax/crud-share": "^0.46.0",
34
- "@drax/email-back": "^0.46.0",
35
- "@drax/identity-share": "^0.46.0",
31
+ "@drax/common-back": "^0.49.0",
32
+ "@drax/crud-back": "^0.49.0",
33
+ "@drax/crud-share": "^0.49.0",
34
+ "@drax/email-back": "^0.49.0",
35
+ "@drax/identity-share": "^0.49.0",
36
36
  "bcryptjs": "^2.4.3",
37
37
  "graphql": "^16.8.2",
38
38
  "jsonwebtoken": "^9.0.2"
@@ -63,5 +63,5 @@
63
63
  "debug": "0"
64
64
  }
65
65
  },
66
- "gitHead": "9625999c86d538dc3bee7c501acba6c51592ebca"
66
+ "gitHead": "ea99f6fd79d282e6efe02fca660d5733c13bb86d"
67
67
  }
@@ -1,7 +1,5 @@
1
1
  enum IdentityConfig {
2
2
 
3
-
4
-
5
3
  JwtSecret = "DRAX_JWT_SECRET",
6
4
  JwtExpiration = "DRAX_JWT_EXPIRATION",
7
5
  JwtIssuer = "DRAX_JWT_ISSUER",
@@ -15,6 +13,7 @@ enum IdentityConfig {
15
13
 
16
14
  defaultRole = "DRAX_DEFAULT_ROLE",
17
15
 
16
+ VerifyIP = "DRAX_VERIFY_IP",
18
17
 
19
18
  }
20
19
 
@@ -3,58 +3,78 @@ import {DraxCache, DraxConfig} from "@drax/common-back";
3
3
  import UserApiKeyServiceFactory from "../factory/UserApiKeyServiceFactory.js";
4
4
  import IdentityConfig from "../config/IdentityConfig.js";
5
5
 
6
- const cacheTTL = DraxConfig.getOrLoad(IdentityConfig.ApiKeyCacheTTL) ? parseInt(DraxConfig.getOrLoad(IdentityConfig.ApiKeyCacheTTL)) : 10000;
6
+ const verifyIp = DraxConfig.getOrLoad(IdentityConfig.VerifyIP, 'boolean', true);
7
+ const cacheTTL = DraxConfig.getOrLoad(IdentityConfig.ApiKeyCacheTTL, 'number',10000)
8
+
7
9
  const draxCache = new DraxCache<IUserApiKey>(cacheTTL);
8
10
 
9
11
 
10
- async function userApiKeyLoader(k):Promise<IUserApiKey | null> {
12
+ async function userApiKeyLoader(k): Promise<IUserApiKey | null> {
11
13
  const userApiKeyService = UserApiKeyServiceFactory()
12
14
  const userApiKey: IUserApiKey = await userApiKeyService.findBySecret(k)
13
15
  return userApiKey
14
16
  }
15
17
 
16
- async function apiKeyMiddleware (request, reply) {
17
- try{
18
- let apiKey: string
18
+ async function apiKeyMiddleware(request, reply) {
19
+ try {
20
+ let apiKey: string
19
21
 
20
- //Por header 'x-api-key'
21
- if(request.headers['x-api-key']){
22
- apiKey = request.headers['x-api-key']
23
- }
22
+ //Por header 'x-api-key'
23
+ if (request.headers['x-api-key']) {
24
+ apiKey = request.headers['x-api-key']
25
+ }
24
26
 
25
- //Por authorization 'ApiKey <uuid-key>'
26
- const apiKeyRegExp = /^ApiKey (.*)$/i;
27
- if(request.headers['authorization'] && apiKeyRegExp.test(request.headers['authorization'])){
28
- apiKey = request.headers?.authorization?.replace(/ApiKey /i, "")
29
- }
27
+ //Por authorization 'ApiKey <uuid-key>'
28
+ const apiKeyRegExp = /^ApiKey (.*)$/i;
29
+ if (request.headers['authorization'] && apiKeyRegExp.test(request.headers['authorization'])) {
30
+ apiKey = request.headers?.authorization?.replace(/ApiKey /i, "")
31
+ }
30
32
 
31
- //Por authorization '<uuid-key>'
32
- const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
33
- if(request.headers['authorization'] && uuidRegex.test(request.headers['authorization'])){
34
- apiKey = request.headers['authorization']
35
- }
33
+ //Por authorization '<uuid-key>'
34
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
35
+ if (request.headers['authorization'] && uuidRegex.test(request.headers['authorization'])) {
36
+ apiKey = request.headers['authorization']
37
+ }
36
38
 
37
- if(apiKey){
38
- const userApiKey : IUserApiKey = await draxCache.getOrLoad(apiKey, userApiKeyLoader)
39
- if(userApiKey && userApiKey.user){
40
- const authUser: IAuthUser = {
41
- id: userApiKey.user._id.toString(),
42
- username: userApiKey.user.username,
43
- roleId: userApiKey.user.role?._id?.toString(),
44
- roleName: userApiKey.user.role?.name,
45
- tenantId: userApiKey.user?.tenant?._id?.toString(),
46
- tenantName: userApiKey.user?.tenant?.name,
47
- apiKeyId: userApiKey?._id?.toString(),
48
- apiKeyName: userApiKey?.name
39
+ if (apiKey) {
40
+ const userApiKey: IUserApiKey = await draxCache.getOrLoad(apiKey, userApiKeyLoader)
41
+
42
+ if (verifyIp) {
43
+ if (userApiKey.ipv4 && userApiKey.ipv4.length > 0) {
44
+ const clientIp = request.ip
45
+ if (!userApiKey.ipv4.includes(clientIp)) {
46
+ reply.code(401).send({"statusCode": "401", error: 'IP not allowed', i18nMessage: 'error.ipNotAllowed', clientIp: clientIp, message: `Remote IP ${clientIp} is not allowed`});
47
+ return
48
+ }
49
+ } else if (userApiKey.ipv6 && userApiKey.ipv6.length > 0) {
50
+ const clientIp = request.ip
51
+ if (!userApiKey.ipv6.includes(clientIp)) {
52
+ reply.code(401).send({"statusCode": "401", error: 'IP not allowed', i18nMessage: 'error.ipNotAllowed', clientIp: clientIp, message: `Remote IP ${clientIp} is not allowed`});
53
+ return
49
54
  }
50
- request.authUser = authUser
51
55
  }
52
56
  }
53
- return
54
- }catch (e) {
55
- console.error(e)
56
- reply.code(500).send({ error: 'APIKEY ERROR' });
57
+
58
+
59
+ if (userApiKey && userApiKey.user) {
60
+ const authUser: IAuthUser = {
61
+ id: userApiKey.user._id.toString(),
62
+ username: userApiKey.user.username,
63
+ roleId: userApiKey.user.role?._id?.toString(),
64
+ roleName: userApiKey.user.role?.name,
65
+ tenantId: userApiKey.user?.tenant?._id?.toString(),
66
+ tenantName: userApiKey.user?.tenant?.name,
67
+ apiKeyId: userApiKey?._id?.toString(),
68
+ apiKeyName: userApiKey?.name
69
+ }
70
+ request.authUser = authUser
71
+ }
57
72
  }
73
+ return
74
+ } catch (e) {
75
+ console.error(e)
76
+ reply.code(500).send({error: 'APIKEY ERROR'});
77
+ }
58
78
  }
59
79
 
60
80
  export default apiKeyMiddleware;
@@ -4,7 +4,7 @@ import RoleServiceFactory from "../factory/RoleServiceFactory.js";
4
4
  import Rbac from "../rbac/Rbac.js";
5
5
  import IdentityConfig from "../config/IdentityConfig.js";
6
6
 
7
- const cacheTTL = DraxConfig.getOrLoad(IdentityConfig.RbacCacheTTL) ? parseInt(DraxConfig.getOrLoad(IdentityConfig.RbacCacheTTL)) : 10000;
7
+ const cacheTTL = DraxConfig.getOrLoad(IdentityConfig.RbacCacheTTL, 'number',10000) ;
8
8
  const draxCache = new DraxCache<IRole>(cacheTTL);
9
9
 
10
10
 
@@ -40,6 +40,8 @@ class UserApiKeySqliteRepository extends AbstractSqliteRepository<IUserApiKey, I
40
40
  }
41
41
 
42
42
  async prepareItem(item: any): Promise<any> {
43
+
44
+
43
45
  if (item && item.user) {
44
46
  item.user = await this.findUserById(item.user)
45
47
  }
@@ -48,16 +50,19 @@ class UserApiKeySqliteRepository extends AbstractSqliteRepository<IUserApiKey, I
48
50
  item.createdBy = await this.findUserById(item.createdBy)
49
51
  }
50
52
 
51
- if (item && item.ipv4) {
52
- item.ipv4 = item.ipv4 != "" ? item.ipv4.split(',') : []
53
+ if (item && item.hasOwnProperty('ipv4')) {
54
+ item.ipv4 = item.ipv4 ? item.ipv4.split(',') : []
53
55
  }
54
56
 
55
- if (item && item.ipv6) {
56
- item.ipv6 = item.ipv6 != "" ? item.ipv6.split(',') : []
57
+ if (item && item.hasOwnProperty('ipv6')) {
58
+ item.ipv6 = item.ipv6 ? item.ipv6.split(',') : []
57
59
  }
60
+
61
+ return item;
58
62
  }
59
63
 
60
64
  async prepareData(userApiKeyData) {
65
+
61
66
  if (userApiKeyData.ipv4 && Array.isArray(userApiKeyData.ipv4) && userApiKeyData.ipv4.length > 0) {
62
67
  userApiKeyData.ipv4 = userApiKeyData.ipv4.join(',')
63
68
  } else {
@@ -69,6 +74,15 @@ class UserApiKeySqliteRepository extends AbstractSqliteRepository<IUserApiKey, I
69
74
  } else {
70
75
  userApiKeyData.ipv6 = ""
71
76
  }
77
+
78
+ if(userApiKeyData.user && userApiKeyData.user.hasOwnProperty('_id')) {
79
+ userApiKeyData.user = userApiKeyData.user._id
80
+ }
81
+
82
+ if(userApiKeyData.createdBy && userApiKeyData.createdBy.hasOwnProperty('_id')) {
83
+ userApiKeyData.createdBy = userApiKeyData.createdBy._id
84
+ }
85
+
72
86
  }
73
87
 
74
88