@drax/identity-back 0.0.30 → 0.1.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/config/IdentityConfig.js +2 -3
- package/dist/factory/RoleServiceFactory.js +8 -7
- package/dist/factory/TenantServiceFactory.js +8 -7
- package/dist/factory/UserApiKeyServiceFactory.js +24 -0
- package/dist/factory/UserServiceFactory.js +8 -7
- package/dist/graphql/resolvers/user-api-key.resolvers.js +89 -0
- package/dist/graphql/resolvers/user.resolvers.js +7 -2
- package/dist/graphql/types/tenant.graphql +2 -0
- package/dist/graphql/types/user.graphql +2 -0
- package/dist/graphql/types/userApiKey.graphql +33 -0
- package/dist/index.js +4 -2
- package/dist/interfaces/IUserApiKeyRepository.js +1 -0
- package/dist/middleware/apiKeyMiddleware.js +30 -0
- package/dist/middleware/rbacMiddleware.js +0 -1
- package/dist/models/TenantModel.js +2 -4
- package/dist/models/UserApiKeyModel.js +44 -0
- package/dist/permissions/IdentityPermissions.js +6 -0
- package/dist/rbac/Rbac.js +8 -0
- package/dist/repository/mongo/UserApiKeyMongoRepository.js +82 -0
- package/dist/repository/mongo/UserMongoRepository.js +3 -3
- package/dist/repository/sqlite/RoleSqliteRepository.js +16 -18
- package/dist/repository/sqlite/TenantSqliteRepository.js +13 -11
- package/dist/repository/sqlite/UserApiKeySqliteRepository.js +147 -0
- package/dist/repository/sqlite/UserSqliteRepository.js +29 -26
- package/dist/routes/UserApiKeyRoutes.js +119 -0
- package/dist/routes/UserRoutes.js +5 -1
- package/dist/services/UserApiKeyService.js +65 -0
- package/dist/setup/LoadIdentityConfigFromEnv.js +3 -3
- package/dist/utils/AuthUtils.js +10 -0
- package/dist/zod/UserApiKeyZod.js +9 -0
- package/package.json +7 -6
- package/src/config/IdentityConfig.ts +4 -3
- package/src/factory/RoleServiceFactory.ts +11 -11
- package/src/factory/TenantServiceFactory.ts +11 -11
- package/src/factory/UserApiKeyServiceFactory.ts +30 -0
- package/src/factory/UserServiceFactory.ts +8 -7
- package/src/graphql/resolvers/tenant.resolvers.ts +0 -1
- package/src/graphql/resolvers/user-api-key.resolvers.ts +94 -0
- package/src/graphql/resolvers/user.resolvers.ts +9 -2
- package/src/graphql/types/tenant.graphql +2 -0
- package/src/graphql/types/user.graphql +2 -0
- package/src/graphql/types/userApiKey.graphql +33 -0
- package/src/index.ts +10 -0
- package/src/interfaces/IUserApiKeyRepository.ts +8 -0
- package/src/middleware/apiKeyMiddleware.ts +35 -0
- package/src/middleware/rbacMiddleware.ts +1 -2
- package/src/models/TenantModel.ts +2 -4
- package/src/models/UserApiKeyModel.ts +59 -0
- package/src/permissions/IdentityPermissions.ts +7 -0
- package/src/rbac/Rbac.ts +13 -2
- package/src/repository/mongo/UserApiKeyMongoRepository.ts +114 -0
- package/src/repository/mongo/UserMongoRepository.ts +3 -3
- package/src/repository/sqlite/RoleSqliteRepository.ts +28 -20
- package/src/repository/sqlite/TenantSqliteRepository.ts +25 -11
- package/src/repository/sqlite/UserApiKeySqliteRepository.ts +197 -0
- package/src/repository/sqlite/UserSqliteRepository.ts +37 -27
- package/src/routes/UserApiKeyRoutes.ts +128 -0
- package/src/routes/UserRoutes.ts +5 -1
- package/src/services/UserApiKeyService.ts +86 -0
- package/src/setup/LoadIdentityConfigFromEnv.ts +5 -3
- package/src/utils/AuthUtils.ts +11 -0
- package/src/zod/UserApiKeyZod.ts +15 -0
- package/test/data-obj/apikey/root-mongo-user-apikey.ts +10 -0
- package/test/data-obj/roles/admin-mongo-role.ts +0 -3
- package/test/initializers/RoleMongoInitializer.ts +1 -0
- package/test/initializers/RoleSqliteInitializer.ts +1 -0
- package/test/initializers/UserMongoInitializer.ts +18 -0
- package/test/repository/mongo/user-apikey-mongo-repository.test.ts +73 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/types/factory/RoleServiceFactory.d.ts.map +1 -1
- package/types/factory/TenantServiceFactory.d.ts.map +1 -1
- package/types/factory/UserApiKeyServiceFactory.d.ts.map +1 -0
- package/types/factory/UserServiceFactory.d.ts.map +1 -1
- package/types/graphql/resolvers/tenant.resolvers.d.ts.map +1 -1
- package/types/graphql/resolvers/user-api-key.resolvers.d.ts.map +1 -0
- package/types/graphql/resolvers/user.resolvers.d.ts.map +1 -1
- package/types/index.d.ts.map +1 -1
- package/types/interfaces/IRoleRepository.d.ts.map +1 -0
- package/types/interfaces/ITenantRepository.d.ts.map +1 -0
- package/types/interfaces/IUserApiKeyRepository.d.ts.map +1 -0
- package/types/interfaces/IUserRepository.d.ts.map +1 -0
- package/types/middleware/apiKeyMiddleware.d.ts.map +1 -0
- package/types/middleware/rbacMiddleware.d.ts.map +1 -1
- package/types/models/TenantModel.d.ts.map +1 -1
- package/types/models/UserApiKeyModel.d.ts.map +1 -0
- package/types/rbac/Rbac.d.ts +15 -0
- package/types/rbac/Rbac.d.ts.map +1 -0
- package/types/repository/mongo/UserApiKeyMongoRepository.d.ts.map +1 -0
- package/types/repository/sqlite/RoleSqliteRepository.d.ts.map +1 -1
- package/types/repository/sqlite/TenantSqliteRepository.d.ts.map +1 -1
- package/types/repository/sqlite/UserApiKeySqliteRepository.d.ts +19 -0
- package/types/repository/sqlite/UserApiKeySqliteRepository.d.ts.map +1 -0
- package/types/repository/sqlite/UserSqliteRepository.d.ts.map +1 -1
- package/types/routes/UserApiKeyRoutes.d.ts.map +1 -0
- package/types/routes/UserRoutes.d.ts.map +1 -1
- package/types/services/UserApiKeyService.d.ts.map +1 -0
- package/types/setup/LoadIdentityConfigFromEnv.d.ts.map +1 -1
- package/types/utils/AuthUtils.d.ts.map +1 -1
- package/types/zod/UserApiKeyZod.d.ts +16 -0
- package/types/zod/UserApiKeyZod.d.ts.map +1 -0
- package/src/utils/DbSetupUtils.ts +0 -41
- package/types/config/IdentityConfig.d.ts +0 -13
- package/types/config/IdentityConfig.d.ts.map +0 -1
- package/types/graphql/resolvers/role.resolvers.d.ts +0 -52
- package/types/graphql/resolvers/tenant.resolvers.d.ts +0 -49
- package/types/graphql/resolvers/user.resolvers.d.ts +0 -67
- package/types/utils/DbSetupUtils.d.ts.map +0 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import {IUserApiKeyRepository} from "../interfaces/IUserApiKeyRepository";
|
|
2
|
+
import {DraxConfig, ValidationError, ZodErrorToValidationError} from "@drax/common-back"
|
|
3
|
+
import {userApiKeySchema} from "../zod/UserApiKeyZod.js";
|
|
4
|
+
import {ZodError} from "zod";
|
|
5
|
+
import {IUserApiKeyBase, IUserApiKey} from "@drax/identity-share";
|
|
6
|
+
import {IDraxPaginateOptions, IDraxPaginateResult} from "@drax/common-share";
|
|
7
|
+
import crypto from "node:crypto";
|
|
8
|
+
import AuthUtils from "../utils/AuthUtils.js";
|
|
9
|
+
import IdentityConfig from "../config/IdentityConfig.js";
|
|
10
|
+
|
|
11
|
+
class UserApiKeyService {
|
|
12
|
+
|
|
13
|
+
_repository: IUserApiKeyRepository
|
|
14
|
+
|
|
15
|
+
constructor(userApiKeyRepostitory: IUserApiKeyRepository) {
|
|
16
|
+
this._repository = userApiKeyRepostitory
|
|
17
|
+
console.log("UserApiKeyService constructor")
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async create(userApiKeyData: IUserApiKeyBase): Promise<IUserApiKey> {
|
|
21
|
+
try {
|
|
22
|
+
userApiKeyData.name = userApiKeyData?.name?.trim()
|
|
23
|
+
const secret = crypto.randomUUID()
|
|
24
|
+
const APIKEY_SECRET = DraxConfig.getOrLoad(IdentityConfig.ApiKeySecret)
|
|
25
|
+
userApiKeyData.secret = AuthUtils.generateHMAC(APIKEY_SECRET, secret)
|
|
26
|
+
await userApiKeySchema.parseAsync(userApiKeyData)
|
|
27
|
+
const userApiKey = await this._repository.create(userApiKeyData)
|
|
28
|
+
userApiKey.secret = secret
|
|
29
|
+
return userApiKey
|
|
30
|
+
} catch (e) {
|
|
31
|
+
if (e instanceof ZodError) {
|
|
32
|
+
throw ZodErrorToValidationError(e, userApiKeyData)
|
|
33
|
+
}
|
|
34
|
+
throw e
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async update(id: string, userApiKeyData: IUserApiKeyBase) {
|
|
39
|
+
try {
|
|
40
|
+
userApiKeyData.name = userApiKeyData?.name?.trim()
|
|
41
|
+
delete userApiKeyData.secret
|
|
42
|
+
await userApiKeySchema.parseAsync(userApiKeyData)
|
|
43
|
+
const userApiKey = await this._repository.update(id, userApiKeyData)
|
|
44
|
+
return userApiKey
|
|
45
|
+
} catch (e) {
|
|
46
|
+
if (e instanceof ZodError) {
|
|
47
|
+
throw ZodErrorToValidationError(e, userApiKeyData)
|
|
48
|
+
}
|
|
49
|
+
throw e
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async delete(id: string): Promise<boolean> {
|
|
54
|
+
const currentUserApiKey = await this.findById(id)
|
|
55
|
+
const deletedUserApiKey = await this._repository.delete(id);
|
|
56
|
+
return deletedUserApiKey;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async findById(id: string): Promise<IUserApiKey | null> {
|
|
60
|
+
const userApiKey: IUserApiKey = await this._repository.findById(id);
|
|
61
|
+
return userApiKey
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async findBySecret(secret: string): Promise<IUserApiKey | null> {
|
|
65
|
+
const APIKEY_SECRET = DraxConfig.getOrLoad(IdentityConfig.ApiKeySecret)
|
|
66
|
+
const hashedSecret = AuthUtils.generateHMAC(APIKEY_SECRET, secret)
|
|
67
|
+
const userApiKey: IUserApiKey = await this._repository.findBySecret(hashedSecret);
|
|
68
|
+
return userApiKey
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
async paginate({
|
|
73
|
+
page= 1,
|
|
74
|
+
limit= 5,
|
|
75
|
+
orderBy= '',
|
|
76
|
+
orderDesc= false,
|
|
77
|
+
search= '',
|
|
78
|
+
filters= []} : IDraxPaginateOptions): Promise<IDraxPaginateResult<IUserApiKey>>{
|
|
79
|
+
const pagination = await this._repository.paginate({page, limit, orderBy, orderDesc, search, filters});
|
|
80
|
+
return pagination;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export default UserApiKeyService
|
|
@@ -2,12 +2,14 @@ import {DraxConfig} from "@drax/common-back";
|
|
|
2
2
|
import IdentityConfig from "../config/IdentityConfig.js";
|
|
3
3
|
|
|
4
4
|
function LoadIdentityConfigFromEnv() {
|
|
5
|
-
|
|
6
|
-
DraxConfig.set(IdentityConfig.SqliteDbFile, process.env[IdentityConfig.SqliteDbFile])
|
|
7
|
-
DraxConfig.set(IdentityConfig.MongoDbUri, process.env[IdentityConfig.MongoDbUri])
|
|
5
|
+
|
|
8
6
|
DraxConfig.set(IdentityConfig.JwtSecret, process.env[IdentityConfig.JwtSecret])
|
|
9
7
|
DraxConfig.set(IdentityConfig.JwtExpiration, process.env[IdentityConfig.JwtExpiration])
|
|
10
8
|
DraxConfig.set(IdentityConfig.JwtIssuer, process.env[IdentityConfig.JwtIssuer])
|
|
9
|
+
DraxConfig.set(IdentityConfig.ApiKeySecret, process.env[IdentityConfig.ApiKeySecret])
|
|
10
|
+
|
|
11
|
+
DraxConfig.set(IdentityConfig.RbacCacheTTL, process.env[IdentityConfig.RbacCacheTTL])
|
|
12
|
+
DraxConfig.set(IdentityConfig.AvatarDir, process.env[IdentityConfig.AvatarDir])
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
export default LoadIdentityConfigFromEnv
|
package/src/utils/AuthUtils.ts
CHANGED
|
@@ -2,6 +2,7 @@ import bcryptjs from "bcryptjs";
|
|
|
2
2
|
import jsonwebtoken, {SignOptions, VerifyOptions} from "jsonwebtoken";
|
|
3
3
|
import {DraxConfig} from "@drax/common-back";
|
|
4
4
|
import IdentityConfig from "../config/IdentityConfig.js";
|
|
5
|
+
import crypto from "crypto";
|
|
5
6
|
|
|
6
7
|
class AuthUtils{
|
|
7
8
|
|
|
@@ -67,6 +68,16 @@ class AuthUtils{
|
|
|
67
68
|
|
|
68
69
|
return token
|
|
69
70
|
}
|
|
71
|
+
|
|
72
|
+
static generateHMAC(secret: string, apikey: string) {
|
|
73
|
+
// Crear un objeto HMAC utilizando el algoritmo SHA-256 y el secreto
|
|
74
|
+
const hmac = crypto.createHmac('sha256', secret);
|
|
75
|
+
// Actualizar el HMAC con la apikey
|
|
76
|
+
hmac.update(apikey);
|
|
77
|
+
// Generar el hash en formato hexadecimal
|
|
78
|
+
return hmac.digest('hex');
|
|
79
|
+
}
|
|
70
80
|
}
|
|
71
81
|
|
|
72
82
|
export default AuthUtils
|
|
83
|
+
export {AuthUtils}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {array, object, string} from "zod"
|
|
2
|
+
|
|
3
|
+
const userApiKeySchema = object({
|
|
4
|
+
name: string({ required_error: "validation.required" })
|
|
5
|
+
.min(1, "validation.required"),
|
|
6
|
+
ipv4: array(string().ip({version: "v4", message: 'validation.invalidIpv4'})),
|
|
7
|
+
ipv6: array(string().ip({version: "v6", message: 'validation.invalidIpv6'})),
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
export default userApiKeySchema
|
|
14
|
+
|
|
15
|
+
export {userApiKeySchema}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import UserService from "../../src/services/UserService";
|
|
2
|
+
import {IUser} from "../../../identity-share/src/interfaces/IUser";
|
|
3
|
+
import UserMongoRepository from "../../src/repository/mongo/UserMongoRepository";
|
|
4
|
+
|
|
5
|
+
class UserMongoInitializer {
|
|
6
|
+
|
|
7
|
+
static async initRootUser(): Promise<IUser>{
|
|
8
|
+
const userService = new UserService(new UserMongoRepository())
|
|
9
|
+
let data = (await import("../data-obj/users/root-mongo-user")).default
|
|
10
|
+
let userCreated = await userService.create(data)
|
|
11
|
+
return userCreated
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default UserMongoInitializer
|
|
16
|
+
export {
|
|
17
|
+
UserMongoInitializer
|
|
18
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {before, after, describe, it, test} from "node:test"
|
|
2
|
+
import assert, {equal} from "assert";
|
|
3
|
+
import UserApiKeyMongoRepository from "../../../src/repository/mongo/UserApiKeyMongoRepository";
|
|
4
|
+
import MongoInMemory from "../../db/MongoInMemory";
|
|
5
|
+
import RoleMongoInitializer from "../../initializers/RoleMongoInitializer";
|
|
6
|
+
import UserMongoInitializer from "../../initializers/UserMongoInitializer";
|
|
7
|
+
import {IUserApiKey} from "../../../../identity-share/src/interfaces/IUserApiKey";
|
|
8
|
+
import type {IDraxPaginateResult} from "@drax/common-share";
|
|
9
|
+
import {mongoose, ValidationError} from "@drax/common-back";
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
test.describe("UserApiKeyRepositoryTest", function () {
|
|
13
|
+
|
|
14
|
+
let userApiKeyRepository = new UserApiKeyMongoRepository()
|
|
15
|
+
let data
|
|
16
|
+
let adminRole
|
|
17
|
+
let rootUser
|
|
18
|
+
|
|
19
|
+
before(async () => {
|
|
20
|
+
await MongoInMemory.connect()
|
|
21
|
+
adminRole = await RoleMongoInitializer.initAdminRole()
|
|
22
|
+
rootUser = await UserMongoInitializer.initRootUser()
|
|
23
|
+
|
|
24
|
+
//console.log("BEFORE USER", MongoInMemory.mongooseStatus, MongoInMemory.serverStatus)
|
|
25
|
+
return
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
after(async () => {
|
|
29
|
+
await MongoInMemory.DropAndClose()
|
|
30
|
+
//console.log("AFTER USER", MongoInMemory.status, MongoInMemory.serverStatus)
|
|
31
|
+
return
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test("Create mongo user apikey successfully", async function () {
|
|
35
|
+
data = (await import("../../data-obj/apikey/root-mongo-user-apikey")).default
|
|
36
|
+
let userApiKeyCreated = await userApiKeyRepository.create(data)
|
|
37
|
+
equal(userApiKeyCreated.name, data.name)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test("Find mongo user by ID successfully", async function () {
|
|
41
|
+
data = (await import("../../data-obj/apikey/root-mongo-user-apikey")).default
|
|
42
|
+
let userApiKeyFound = await userApiKeyRepository.findById(data._id)
|
|
43
|
+
|
|
44
|
+
equal(userApiKeyFound.name, data.name)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
test("Find mongo user by secret successfully", async function () {
|
|
48
|
+
data = (await import("../../data-obj/apikey/root-mongo-user-apikey")).default
|
|
49
|
+
console.log("Data:",data)
|
|
50
|
+
let userApiKeyFound = await userApiKeyRepository.findBySecret(data.secret)
|
|
51
|
+
console.log("userApiKeyFound",userApiKeyFound)
|
|
52
|
+
equal(userApiKeyFound.secret, data.secret)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
test("Update mongo user apikey successfully.", async function () {
|
|
57
|
+
data = (await import("../../data-obj/apikey/root-mongo-user-apikey")).default
|
|
58
|
+
data.name = "AdminUpdated"
|
|
59
|
+
let userUpdated: IUserApiKey = await userApiKeyRepository.update(data._id, data)
|
|
60
|
+
equal(userUpdated.name, userUpdated.name)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
test("Paginate mongo users successfully.", async function () {
|
|
65
|
+
let paginateUsersApiKey: IDraxPaginateResult<IUserApiKey> = await userApiKeyRepository.paginate({
|
|
66
|
+
page: 1,
|
|
67
|
+
limit: 5
|
|
68
|
+
})
|
|
69
|
+
equal(paginateUsersApiKey.items.length, 1)
|
|
70
|
+
equal(paginateUsersApiKey.total, 1)
|
|
71
|
+
equal(paginateUsersApiKey.page, 1)
|
|
72
|
+
})
|
|
73
|
+
})
|