@pengzi/kms 1.2.0 → 1.3.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.
@@ -5,9 +5,10 @@
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.KeyService = void 0;
8
- const key_model_1 = require("../models/key.model");
9
8
  const types_1 = require("../types");
9
+ const key_model_1 = require("../models/key.model");
10
10
  const types_2 = require("../types");
11
+ const types_3 = require("../types");
11
12
  const crypto_1 = require("../core/crypto");
12
13
  class KeyService {
13
14
  constructor(keyRepo, auditService, permissionService, cryptoService) {
@@ -27,16 +28,16 @@ class KeyService {
27
28
  */
28
29
  async createKey(projectId, userId, masterPassword, keyData) {
29
30
  // 验证权限
30
- await this.permissionService.requirePermission(projectId, userId, types_2.Permission.KEY_CREATE);
31
+ await this.permissionService.requirePermission(projectId, userId, types_3.Permission.KEY_CREATE);
31
32
  // 验证密钥数据
32
33
  const validation = (0, key_model_1.validateKey)(keyData);
33
34
  if (!validation.valid) {
34
- throw new types_1.ValidationError(validation.errors.join(', '));
35
+ throw new types_2.ValidationError(validation.errors.join(', '));
35
36
  }
36
37
  // 检查密钥名称是否已存在
37
38
  const existingKey = await this.keyRepo.findByProjectAndName(projectId, keyData.keyName);
38
39
  if (existingKey) {
39
- throw new types_1.ValidationError('Key with this name already exists');
40
+ throw new types_2.ValidationError('Key with this name already exists');
40
41
  }
41
42
  // 加密密钥值
42
43
  const masterKeyHex = await this.getMasterKey(projectId, masterPassword);
@@ -54,19 +55,19 @@ class KeyService {
54
55
  */
55
56
  async getKey(projectId, userId, masterPassword, keyId) {
56
57
  // 验证权限
57
- await this.permissionService.requirePermission(projectId, userId, types_2.Permission.KEY_READ);
58
+ await this.permissionService.requirePermission(projectId, userId, types_3.Permission.KEY_READ);
58
59
  // 获取密钥
59
60
  const key = await this.keyRepo.findByKeyId(keyId);
60
61
  if (!key) {
61
- throw new types_1.KeyNotFoundError(keyId);
62
+ throw new types_2.KeyNotFoundError(keyId);
62
63
  }
63
64
  // 验证项目
64
65
  if (key.projectId !== projectId) {
65
- throw new types_1.ValidationError('Key does not belong to this project');
66
+ throw new types_2.ValidationError('Key does not belong to this project');
66
67
  }
67
68
  // 检查密钥是否可访问
68
69
  if (!(0, key_model_1.isKeyAccessible)(key)) {
69
- throw new types_1.ValidationError('Key is not accessible');
70
+ throw new types_2.ValidationError('Key is not accessible');
70
71
  }
71
72
  // 解密密钥值
72
73
  const masterKeyHex = await this.getMasterKey(projectId, masterPassword);
@@ -83,7 +84,7 @@ class KeyService {
83
84
  */
84
85
  async listKeys(projectId, userId, filters, options) {
85
86
  // 验证权限
86
- await this.permissionService.requirePermission(projectId, userId, types_2.Permission.KEY_LIST);
87
+ await this.permissionService.requirePermission(projectId, userId, types_3.Permission.KEY_LIST);
87
88
  return await this.keyRepo.findByProjectId(projectId, filters, options);
88
89
  }
89
90
  /**
@@ -91,11 +92,11 @@ class KeyService {
91
92
  */
92
93
  async updateKey(projectId, userId, masterPassword, keyId, updates) {
93
94
  // 验证权限
94
- await this.permissionService.requirePermission(projectId, userId, types_2.Permission.KEY_UPDATE);
95
+ await this.permissionService.requirePermission(projectId, userId, types_3.Permission.KEY_UPDATE);
95
96
  const key = await this.keyRepo.getByKeyId(keyId);
96
97
  // 验证项目
97
98
  if (key.projectId !== projectId) {
98
- throw new types_1.ValidationError('Key does not belong to this project');
99
+ throw new types_2.ValidationError('Key does not belong to this project');
99
100
  }
100
101
  let newEncryptedData;
101
102
  // 如果更新密钥值,需要重新加密
@@ -113,16 +114,74 @@ class KeyService {
113
114
  */
114
115
  async deleteKey(projectId, userId, keyId) {
115
116
  // 验证权限
116
- await this.permissionService.requirePermission(projectId, userId, types_2.Permission.KEY_DELETE);
117
+ await this.permissionService.requirePermission(projectId, userId, types_3.Permission.KEY_DELETE);
117
118
  const key = await this.keyRepo.getByKeyId(keyId);
118
119
  // 验证项目
119
120
  if (key.projectId !== projectId) {
120
- throw new types_1.ValidationError('Key does not belong to this project');
121
+ throw new types_2.ValidationError('Key does not belong to this project');
121
122
  }
122
123
  await this.keyRepo.softDeleteKey(keyId);
123
124
  // 记录审计日志
124
125
  await this.auditService.logKeyDeleted(projectId, userId, keyId, key.keyName, true);
125
126
  }
127
+ /**
128
+ * 设置密钥(简化 API:自动创建或更新)
129
+ * 如果密钥已存在则更新,不存在则创建
130
+ */
131
+ async setKey(projectId, userId, masterPassword, keyName, value, options) {
132
+ // 验证权限
133
+ await this.permissionService.requirePermission(projectId, userId, types_3.Permission.KEY_CREATE);
134
+ // 检查密钥是否已存在
135
+ const existingKey = await this.keyRepo.findByProjectAndName(projectId, keyName);
136
+ if (existingKey) {
137
+ // 验证更新权限
138
+ await this.permissionService.requirePermission(projectId, userId, types_3.Permission.KEY_UPDATE);
139
+ let newEncryptedData;
140
+ const masterKeyHex = await this.getMasterKey(projectId, masterPassword);
141
+ const masterKey = (0, crypto_1.hexToBuffer)(masterKeyHex);
142
+ newEncryptedData = await this.cryptoService.encryptKey(value, masterKey);
143
+ const updatedKey = (0, key_model_1.updateKey)(existingKey, {
144
+ value,
145
+ tags: options?.tags,
146
+ description: options?.description,
147
+ }, newEncryptedData);
148
+ await this.keyRepo.updateKey(existingKey.keyId, updatedKey);
149
+ // 记录审计日志
150
+ await this.auditService.logKeyUpdated(projectId, userId, existingKey.keyId, keyName, true);
151
+ // 返回解密后的值
152
+ return (0, key_model_1.toKeyValue)(updatedKey, value);
153
+ }
154
+ // 创建新密钥
155
+ const keyData = {
156
+ keyName,
157
+ keyType: options?.keyType || types_1.KeyType.CUSTOM,
158
+ value,
159
+ tags: options?.tags,
160
+ description: options?.description,
161
+ };
162
+ const validation = (0, key_model_1.validateKey)(keyData);
163
+ if (!validation.valid) {
164
+ throw new types_2.ValidationError(validation.errors.join(', '));
165
+ }
166
+ const masterKeyHex = await this.getMasterKey(projectId, masterPassword);
167
+ const masterKey = (0, crypto_1.hexToBuffer)(masterKeyHex);
168
+ const encryptedData = await this.cryptoService.encryptKey(value, masterKey);
169
+ const key = (0, key_model_1.createKey)(projectId, keyData, encryptedData, userId);
170
+ await this.keyRepo.insertOne(key);
171
+ // 记录审计日志
172
+ await this.auditService.logKeyCreated(projectId, userId, key.keyId, key.keyName, key.keyType, true);
173
+ return (0, key_model_1.toKeyValue)(key, value);
174
+ }
175
+ /**
176
+ * 通过密钥名称获取密钥(简化 API)
177
+ */
178
+ async getKeyByName(projectId, userId, masterPassword, keyName) {
179
+ const key = await this.keyRepo.findByProjectAndName(projectId, keyName);
180
+ if (!key) {
181
+ throw new types_2.KeyNotFoundError(keyName);
182
+ }
183
+ return await this.getKey(projectId, userId, masterPassword, key.keyId);
184
+ }
126
185
  /**
127
186
  * 获取项目主密钥(需要从项目服务获取)
128
187
  */
@@ -98,5 +98,55 @@ class ProjectService {
98
98
  const masterKey = await this.cryptoService.unlockProjectMasterKey(masterPassword, project.salt, project.masterKeyHash);
99
99
  return masterKey.toString('hex');
100
100
  }
101
+ /**
102
+ * 获取或创建项目(简化 API 使用)
103
+ * 如果项目不存在,自动创建项目并生成默认 SDK 用户
104
+ */
105
+ async getOrCreateProject(projectName, masterPassword) {
106
+ // 查找现有项目
107
+ let project = await this.projectRepo.findByProjectName(projectName);
108
+ if (project) {
109
+ // 验证主密码是否正确
110
+ await this.unlockProjectMasterKey(project.projectId, masterPassword);
111
+ // 确保存在 SDK 默认用户
112
+ await this.ensureSdkUser(project.projectId, masterPassword);
113
+ return { project, isNew: false };
114
+ }
115
+ // 创建新项目,使用 SDK 默认用户作为创建者
116
+ project = await this.createProject({ projectName, masterPassword }, '__sdk_auto__');
117
+ return { project, isNew: true };
118
+ }
119
+ /**
120
+ * 确保项目存在 SDK 默认用户(用于简化 API 的权限绕过)
121
+ * 如果项目是通过 CLI 创建的,可能没有 __sdk_auto__ 用户,此时自动创建
122
+ */
123
+ async ensureSdkUser(projectId, masterPassword) {
124
+ // 尝试查找 SDK 默认用户
125
+ let user = await this.userRepo.findByProjectAndUsername(projectId, '__sdk_auto__');
126
+ if (user) {
127
+ return user;
128
+ }
129
+ // 不存在则自动创建(仅当主密码正确时)
130
+ // 先验证主密码
131
+ await this.unlockProjectMasterKey(projectId, masterPassword);
132
+ const sdkUser = (0, user_model_1.createUser)(projectId, {
133
+ username: '__sdk_auto__',
134
+ password: masterPassword,
135
+ roles: [types_1.Role.ADMIN],
136
+ }, await (0, bcrypt_1.hash)(masterPassword, 10));
137
+ await this.userRepo.insertOne(sdkUser);
138
+ await this.auditService.log({
139
+ projectId,
140
+ userId: '__sdk_auto__',
141
+ action: types_3.AuditAction.CREATE_USER,
142
+ resourceType: types_3.ResourceType.USER,
143
+ resourceId: sdkUser.userId,
144
+ details: {
145
+ success: true,
146
+ note: 'Auto-created SDK default user',
147
+ },
148
+ });
149
+ return sdkUser;
150
+ }
101
151
  }
102
152
  exports.ProjectService = ProjectService;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pengzi/kms",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "High-security Key Management System for Node.js applications",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",