@kne/fastify-account 1.0.0-alpha.9 → 2.0.0-alpha.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.
Files changed (44) hide show
  1. package/README.md +6 -2046
  2. package/index.js +31 -21
  3. package/libs/controllers/account.js +246 -173
  4. package/libs/controllers/admin-user.js +110 -0
  5. package/libs/controllers/admin.js +55 -146
  6. package/libs/controllers/user.js +7 -24
  7. package/libs/models/example._js +13 -0
  8. package/libs/models/user-account.js +13 -32
  9. package/libs/models/user.js +37 -36
  10. package/libs/models/verification-code.js +16 -21
  11. package/libs/services/account.js +124 -149
  12. package/libs/services/admin.js +21 -73
  13. package/libs/services/user.js +52 -58
  14. package/package.json +24 -28
  15. package/libs/controllers/adminPermission.js +0 -237
  16. package/libs/controllers/adminRole.js +0 -146
  17. package/libs/controllers/adminTenant.js +0 -464
  18. package/libs/controllers/tenant.js +0 -34
  19. package/libs/models/admin-role.js +0 -15
  20. package/libs/models/application.js +0 -42
  21. package/libs/models/login-log.js +0 -11
  22. package/libs/models/permission.js +0 -51
  23. package/libs/models/tenant-application.js +0 -26
  24. package/libs/models/tenant-org.js +0 -26
  25. package/libs/models/tenant-permission.js +0 -26
  26. package/libs/models/tenant-role-application.js +0 -37
  27. package/libs/models/tenant-role-permission.js +0 -34
  28. package/libs/models/tenant-role.js +0 -23
  29. package/libs/models/tenant-share-group-permission.js +0 -18
  30. package/libs/models/tenant-share-group.js +0 -18
  31. package/libs/models/tenant-source-user-share-group.js +0 -18
  32. package/libs/models/tenant-token.js +0 -30
  33. package/libs/models/tenant-user-org.js +0 -23
  34. package/libs/models/tenant-user-role.js +0 -23
  35. package/libs/models/tenant-user-share-group.js +0 -18
  36. package/libs/models/tenant-user.js +0 -75
  37. package/libs/models/tenant.js +0 -46
  38. package/libs/services/application.js +0 -151
  39. package/libs/services/permission.js +0 -367
  40. package/libs/services/tenant-invite.js +0 -62
  41. package/libs/services/tenant-org.js +0 -97
  42. package/libs/services/tenant-role.js +0 -108
  43. package/libs/services/tenant-user.js +0 -555
  44. package/libs/services/tenant.js +0 -132
@@ -1,555 +0,0 @@
1
- const fp = require('fastify-plugin');
2
- const transform = require('lodash/transform');
3
- const groupBy = require('lodash/groupBy');
4
- const { Unauthorized } = require('http-errors');
5
- const pick = require('lodash/pick');
6
- const isNil = require('lodash/isNil');
7
- module.exports = fp(async (fastify, options) => {
8
- const { models, services } = fastify.account;
9
- const { Op } = fastify.sequelize.Sequelize;
10
-
11
- const getTenantUserPermissionList = async ({ tenantRoleIds }) => {
12
- const tenantRoleApplication = await models.tenantRoleApplication.findAll({
13
- attributes: ['applicationId'],
14
- where: {
15
- roleId: {
16
- [Op.in]: tenantRoleIds
17
- }
18
- }
19
- });
20
-
21
- const applications = await services.application.getApplicationListByIds({ ids: tenantRoleApplication.map(({ applicationId }) => applicationId) });
22
- const permissions = await services.tenantRole.getPermissionByTenantRoles({ tenantRoleIds });
23
- const permissionMapping = transform(
24
- await models.permission.findAll({
25
- where: {
26
- id: {
27
- [Op.in]: permissions.map(({ paths }) => paths).reduce((list, item) => [...list, ...(item || [])], [])
28
- }
29
- }
30
- }),
31
- (result, value) => {
32
- result[value.id] = { code: value.code, name: value.name };
33
- },
34
- {}
35
- );
36
-
37
- const applicationsMapping = transform(
38
- applications,
39
- (result, value) => {
40
- result[value.uuid] = value;
41
- },
42
- {}
43
- );
44
-
45
- const findEndChildren = permissions => {
46
- const output = [];
47
- const core = (list, node) => {
48
- const { children, other } = groupBy(list, item => (item.pid === node.id ? 'children' : 'other'));
49
- if (!(children && children.length > 0)) {
50
- node.id !== 0 && output.push(node);
51
- return;
52
- }
53
- children.forEach(node => {
54
- core(other || [], node);
55
- });
56
- return output;
57
- };
58
- core(permissions, { id: 0 });
59
- return output;
60
- };
61
-
62
- const userPermissionList = findEndChildren(permissions).map(({ code, applicationId, paths }) => {
63
- return `${applicationsMapping[applicationId].code}${
64
- paths && paths.length > 0
65
- ? `:${paths
66
- .map(id => {
67
- return permissionMapping[id].code;
68
- })
69
- .join(':')}`
70
- : ''
71
- }:${code}`;
72
- });
73
-
74
- return {
75
- applications: applications,
76
- permissions: permissions.map(item =>
77
- Object.assign(
78
- {},
79
- {
80
- code: item.code,
81
- name: item.name,
82
- isModule: item.isModule,
83
- paths: (item.paths || []).map(id => permissionMapping[id])
84
- }
85
- )
86
- ),
87
- userPermissionList
88
- };
89
- };
90
-
91
- const getUserTenant = async authenticatePayload => {
92
- const user = await services.user.getUser(authenticatePayload);
93
- const tenantUserList = await models.tenantUser.findAll({
94
- where: {
95
- userId: user.id
96
- }
97
- });
98
-
99
- const tenantList =
100
- tenantUserList.length > 0
101
- ? await models.tenant.findAll({
102
- where: {
103
- uuid: {
104
- [Op.in]: tenantUserList.map(({ tenantId }) => tenantId)
105
- },
106
- status: 0
107
- }
108
- })
109
- : [];
110
-
111
- const currentTenantUser = user.currentTenantId && tenantUserList.find(({ tenantId }) => tenantId === user.currentTenantId);
112
- const currentTenant = currentTenantUser && tenantList.find(({ uuid }) => uuid === currentTenantUser.tenantId);
113
-
114
- return {
115
- currentTenant: currentTenant && Object.assign({}, currentTenant.get({ plain: true }), { id: currentTenant.uuid }),
116
- currentTenantUser: currentTenantUser && Object.assign({}, currentTenantUser.get({ plain: true }), { id: currentTenantUser.uuid }),
117
- tenantList: tenantList.map(item => {
118
- return Object.assign({}, item.get({ plain: true }), { id: item.uuid });
119
- }),
120
- tenantUserList: tenantUserList.map(item => {
121
- return Object.assign({}, item.get({ plain: true }), { id: item.uuid });
122
- }),
123
- userInfo: user
124
- };
125
- };
126
-
127
- const getTenantUserInstance = async ({ id }) => {
128
- const currentTenantUser = await models.tenantUser.findOne({
129
- where: {
130
- uuid: id
131
- }
132
- });
133
- if (!currentTenantUser) {
134
- throw new Error('租户用户不存在');
135
- }
136
-
137
- return currentTenantUser;
138
- };
139
-
140
- const getTenantUserByUserId = async user => {
141
- if (!user.currentTenantId) {
142
- throw new Unauthorized('没有找到当前绑定租户');
143
- }
144
- const tenant = await services.tenant.getTenant({ id: user.currentTenantId });
145
-
146
- const tenantUser = await models.tenantUser.findOne({
147
- attributes: ['uuid', 'avatar', 'name', 'description', 'phone', 'email'],
148
- include: [
149
- {
150
- attributes: ['id', 'name'],
151
- model: models.tenantOrg
152
- },
153
- {
154
- attributes: ['id', 'name'],
155
- model: models.tenantRole
156
- }
157
- ],
158
- where: {
159
- tenantId: tenant.id,
160
- userId: user.id,
161
- status: 0
162
- }
163
- });
164
-
165
- if (!tenantUser) {
166
- throw Unauthorized('租户用户不存在');
167
- }
168
-
169
- // 获取当前租户默认角色
170
- const defaultTenant = await models.tenantRole.findOne({
171
- where: {
172
- type: 1,
173
- tenantId: tenant.id
174
- }
175
- });
176
-
177
- if (!defaultTenant) {
178
- throw new Error('租户默认角色未设置,请联系管理员');
179
- }
180
-
181
- const tenantRoleIds = tenantUser.tenantRoles.map(({ id }) => id);
182
- tenantRoleIds.push(defaultTenant.id);
183
-
184
- const { userPermissionList } = await getTenantUserPermissionList({ tenantRoleIds });
185
- if (!tenantUser) {
186
- throw new Error('当前租户用户不存在或者已经被关闭');
187
- }
188
-
189
- const outputTenantUser = Object.assign({}, tenantUser.get({ plain: true }), { id: tenantUser.uuid });
190
- outputTenantUser.tenantOrgs = outputTenantUser?.tenantOrgs.map(({ id, name }) => ({ id, name }));
191
- outputTenantUser.tenantRoles = outputTenantUser?.tenantRoles.map(({ id, name }) => ({ id, name }));
192
- return {
193
- tenant: pick(tenant, ['id', 'name', 'description']),
194
- tenantUser: Object.assign({}, outputTenantUser, {
195
- permissions: userPermissionList
196
- }),
197
- user
198
- };
199
- };
200
-
201
- const checkTenantRoleUsed = async ({ tenantRoleId }) => {
202
- if (
203
- (await models.tenantUserRole.count({
204
- where: {
205
- tenantRoleId
206
- }
207
- })) > 0
208
- ) {
209
- throw new Error('该角色已经被使用,请在租户用户种处理掉所有使用该角色的租户用户后重试');
210
- }
211
- };
212
-
213
- const checkTenantUserInfoValidate = async ({ tenantId, roleIds, orgIds, userId }) => {
214
- await services.tenant.getTenant({ id: tenantId });
215
- if (
216
- roleIds &&
217
- roleIds.length > 0 &&
218
- (await models.tenantRole.count({
219
- where: {
220
- id: {
221
- [Op.in]: roleIds
222
- }
223
- }
224
- })) < roleIds.length
225
- ) {
226
- throw new Error('包含租户不存在的角色');
227
- }
228
- if (orgIds && orgIds.length === 0) {
229
- const tenantOrg = await models.tenantOrg.findOne({
230
- where: {
231
- pid: 0,
232
- tenantId
233
- }
234
- });
235
- if (!tenantOrg) {
236
- throw new Error('租户根节点不存在');
237
- }
238
- }
239
-
240
- if (
241
- orgIds &&
242
- orgIds.length > 0 &&
243
- (await models.tenantOrg.count({
244
- where: {
245
- tenantId,
246
- id: {
247
- [Op.in]: orgIds
248
- }
249
- }
250
- })) < orgIds.length
251
- ) {
252
- throw new Error('包含租户不存在组织');
253
- }
254
-
255
- try {
256
- await services.user.getUserInstance({ id: userId });
257
- } catch (e) {
258
- throw new Error('用户不存在,应该先创建用户再创建租户用户');
259
- }
260
- };
261
-
262
- const addTenantUser = async ({ tenantId, roleIds, orgIds, userId, ...tenantUser }) => {
263
- const tenant = await services.tenant.getTenant({ id: tenantId });
264
-
265
- const currentAccountNumber = await models.tenantUser.count({
266
- where: { tenantId }
267
- });
268
-
269
- if (currentAccountNumber >= tenant.accountNumber) {
270
- throw new Error('租户用户数量已达上限');
271
- }
272
-
273
- await checkTenantUserInfoValidate({ tenantId, roleIds, orgIds, userId });
274
-
275
- const t = await fastify.sequelize.instance.transaction();
276
-
277
- if (
278
- (await models.tenantUser.count({
279
- where: {
280
- userId,
281
- tenantId
282
- }
283
- })) > 0
284
- ) {
285
- throw new Error('该用户已经属于该租户,不能重复添加');
286
- }
287
-
288
- try {
289
- const currentTenantUser = await models.tenantUser.create(
290
- {
291
- name: tenantUser.name,
292
- avatar: tenantUser.avatar,
293
- phone: tenantUser.phone,
294
- email: tenantUser.email,
295
- description: tenantUser.description,
296
- tenantId,
297
- userId
298
- },
299
- { transaction: t }
300
- );
301
- roleIds.length > 0 &&
302
- (await models.tenantUserRole.bulkCreate(
303
- roleIds.map(roleId => {
304
- return {
305
- tenantRoleId: roleId,
306
- tenantId,
307
- tenantUserId: currentTenantUser.uuid
308
- };
309
- }),
310
- { transaction: t }
311
- ));
312
-
313
- await models.tenantUserOrg.bulkCreate(
314
- orgIds.map(orgId => {
315
- return {
316
- tenantOrgId: orgId,
317
- tenantId,
318
- tenantUserId: currentTenantUser.uuid
319
- };
320
- }),
321
- { transaction: t }
322
- );
323
-
324
- await t.commit();
325
- } catch (e) {
326
- await t.rollback();
327
- throw e;
328
- }
329
- };
330
-
331
- const saveTenantUser = async ({ id, tenantId, roleIds, orgIds, userId, ...tenantUser }) => {
332
- const currentTenantUser = await getTenantUserInstance({ id });
333
- if (tenantId !== currentTenantUser.tenantId) {
334
- throw new Error('租户Id和当前租户用户的租户Id不一致');
335
- }
336
- await checkTenantUserInfoValidate({ tenantId, roleIds, orgIds, userId: currentTenantUser.userId });
337
-
338
- const tenantRoleIds = (
339
- await models.tenantUserRole.findAll({
340
- attributes: ['tenantRoleId'],
341
- where: {
342
- tenantId,
343
- tenantUserId: currentTenantUser.uuid
344
- }
345
- })
346
- ).map(({ tenantRoleId }) => tenantRoleId);
347
-
348
- const tenantOrgIds = (
349
- await models.tenantUserOrg.findAll({
350
- attributes: ['tenantOrgId'],
351
- where: {
352
- tenantId,
353
- tenantUserId: currentTenantUser.uuid
354
- }
355
- })
356
- ).map(({ tenantOrgId }) => tenantOrgId);
357
-
358
- const t = await fastify.sequelize.instance.transaction();
359
-
360
- try {
361
- ['name', 'avatar', 'phone', 'email', 'description'].forEach(name => {
362
- if (!isNil(tenantUser[name])) {
363
- currentTenantUser[name] = tenantUser[name];
364
- }
365
- });
366
- await currentTenantUser.save({ transaction: t });
367
- // 修改角色
368
- if (roleIds) {
369
- const needDeleteTenantRole = tenantRoleIds.filter(targetId => roleIds.indexOf(targetId) === -1);
370
- const needAddTenantRole = roleIds.filter(targetId => tenantRoleIds.indexOf(targetId) === -1);
371
- await models.tenantUserRole.destroy({
372
- where: {
373
- tenantId,
374
- tenantUserId: currentTenantUser.uuid,
375
- tenantRoleId: {
376
- [Op.in]: needDeleteTenantRole
377
- }
378
- },
379
- transaction: t
380
- });
381
- await models.tenantUserRole.bulkCreate(
382
- needAddTenantRole.map(tenantRoleId => {
383
- return { tenantId, tenantUserId: currentTenantUser.uuid, tenantRoleId };
384
- }),
385
- { transaction: t }
386
- );
387
- }
388
- //修改组织
389
- if (orgIds) {
390
- const needDeleteTenantOrg = tenantOrgIds.filter(targetId => orgIds.indexOf(targetId) === -1);
391
- const needAddTenantOrg = orgIds.filter(targetId => tenantOrgIds.indexOf(targetId) === -1);
392
- await models.tenantUserOrg.destroy({
393
- where: {
394
- tenantId,
395
- tenantUserId: currentTenantUser.uuid,
396
- tenantOrgId: {
397
- [Op.in]: needDeleteTenantOrg
398
- }
399
- },
400
- transaction: t
401
- });
402
- await models.tenantUserOrg.bulkCreate(
403
- needAddTenantOrg.map(tenantOrgId => {
404
- return { tenantId, tenantUserId: currentTenantUser.uuid, tenantOrgId };
405
- }),
406
- { transaction: t }
407
- );
408
- }
409
- await t.commit();
410
- } catch (e) {
411
- await t.rollback();
412
- throw e;
413
- }
414
- };
415
-
416
- const deleteTenantUser = async ({ tenantId, tenantUserId }) => {
417
- await services.tenant.getTenant({ id: tenantId });
418
- const tenantUser = await getTenantUserInstance({ id: tenantUserId });
419
-
420
- const t = await fastify.sequelize.instance.transaction();
421
-
422
- try {
423
- await models.tenantUserOrg.destroy({
424
- where: {
425
- tenantId,
426
- tenantUserId: tenantUser.uuid
427
- },
428
- transaction: t
429
- });
430
- await models.tenantUserRole.destroy({
431
- where: {
432
- tenantId,
433
- tenantUserId: tenantUser.uuid
434
- },
435
- transaction: t
436
- });
437
- await tenantUser.destroy({ transaction: t });
438
- await t.commit();
439
- } catch (e) {
440
- await t.rollback();
441
- throw e;
442
- }
443
- };
444
-
445
- const closeTenantUser = async ({ tenantId, tenantUserId }) => {
446
- await services.tenant.getTenant({ id: tenantId });
447
- const tenantUser = await getTenantUserInstance({ id: tenantUserId });
448
- tenantUser.status = 12;
449
- await tenantUser.save();
450
- };
451
-
452
- const openTenantUser = async ({ tenantId, tenantUserId }) => {
453
- await services.tenant.getTenant({ id: tenantId });
454
- const tenantUser = await getTenantUserInstance({ id: tenantUserId });
455
- tenantUser.status = 0;
456
- await tenantUser.save();
457
- };
458
-
459
- const getTenantUserList = async ({ tenantId }) => {
460
- await services.tenant.getTenant({ id: tenantId });
461
-
462
- const { count, rows } = await fastify.account.models.tenantUser.findAndCountAll({
463
- include: [fastify.account.models.tenantRole, fastify.account.models.tenantOrg, fastify.account.models.user],
464
- where: { tenantId }
465
- });
466
-
467
- return {
468
- pageData: rows.map(item => {
469
- return Object.assign({}, item.get({ pain: true }), { id: item.uuid });
470
- }),
471
- totalCount: count
472
- };
473
- };
474
-
475
- const includeTenantUserBatch = async ({ tenantId, list }) => {
476
- await services.tenant.getTenant({ id: tenantId });
477
- const errors = [],
478
- successes = [];
479
- for (let current of list) {
480
- if (!(current.phone || current.email)) {
481
- errors.push({ item: current, msg: '电话和邮箱不能同时为空' });
482
- continue;
483
- }
484
- const currentQuery = [];
485
- if (current.phone) {
486
- currentQuery.push({ phone: current.phone });
487
- }
488
- if (current.email) {
489
- currentQuery.push({ email: current.email });
490
- }
491
-
492
- if (
493
- (await models.tenantUser.count({
494
- where: {
495
- [Op.or]: currentQuery
496
- }
497
- })) > 0
498
- ) {
499
- errors.push({ item: current, msg: '租户用户已经存在,或手机邮箱和已有租户用户重复' });
500
- continue;
501
- }
502
-
503
- if (await services.user.accountIsExists(current, {})) {
504
- errors.push({ item: current, msg: '用户已经存在,已发送加入租户邀请等待对方同意' });
505
- continue;
506
- }
507
-
508
- try {
509
- const user = await services.user.addUser({
510
- nickname: current.name,
511
- phone: current.phone,
512
- email: current.email,
513
- password: services.account.md5(current.password || options.defaultPassword),
514
- status: 1
515
- });
516
- const rootOrg = await services.tenantOrg.getTenantOrgRoot({ tenantId });
517
- await services.tenantUser.addTenantUser(
518
- Object.assign(
519
- {},
520
- {
521
- orgIds: [rootOrg.id],
522
- roleIds: []
523
- },
524
- {
525
- tenantId,
526
- userId: user.id,
527
- ...current
528
- }
529
- )
530
- );
531
- successes.push({ item: current });
532
- } catch (e) {
533
- errors.push({ item: current, msg: e.message });
534
- throw e;
535
- }
536
- }
537
-
538
- return { errors, successes };
539
- };
540
-
541
- services.tenantUser = {
542
- getUserTenant,
543
- getTenantUserPermissionList,
544
- getTenantUserByUserId,
545
- checkTenantRoleUsed,
546
- checkTenantUserInfoValidate,
547
- addTenantUser,
548
- saveTenantUser,
549
- deleteTenantUser,
550
- closeTenantUser,
551
- openTenantUser,
552
- getTenantUserList,
553
- includeTenantUserBatch
554
- };
555
- });
@@ -1,132 +0,0 @@
1
- const fp = require('fastify-plugin');
2
-
3
- module.exports = fp(async (fastify, options) => {
4
- const { models, services } = fastify.account;
5
-
6
- const getTenantInstance = async ({ id }) => {
7
- const tenant = await models.tenant.findOne({
8
- where: {
9
- uuid: id
10
- }
11
- });
12
- if (!tenant) {
13
- throw new Error('租户不存在');
14
- }
15
-
16
- if (tenant.status !== 0) {
17
- throw new Error('租户已关闭');
18
- }
19
- return tenant;
20
- };
21
-
22
- const getTenant = async ({ id }) => {
23
- const tenant = await getTenantInstance({ id });
24
-
25
- return Object.assign({}, tenant.get({ plain: true }), { id: tenant.uuid });
26
- };
27
-
28
- const closeTenant = async ({ tenantId }) => {
29
- const tenant = await getTenant({ id: tenantId });
30
- tenant.status = 12;
31
- await tenant.save();
32
- };
33
-
34
- const openTenant = async ({ tenantId }) => {
35
- const tenant = await getTenant({ id: tenantId });
36
- tenant.status = 0;
37
- await tenant.save();
38
- };
39
-
40
- const saveTenant = async tenant => {
41
- const currentTenant = await services.tenant.getTenantInstance({ id: tenant.id });
42
- if (!currentTenant) {
43
- throw new Error('租户不存在,请刷新以后重试');
44
- }
45
- await currentTenant.update(tenant);
46
- };
47
-
48
- const addTenant = async tenant => {
49
- if (await models.tenant.count({ where: { name: tenant.name } })) {
50
- throw new Error('租户名称不能重复');
51
- }
52
-
53
- const t = await fastify.sequelize.instance.transaction();
54
- try {
55
- const currentTenant = await models.tenant.create(tenant);
56
- await models.tenantRole.create(
57
- {
58
- name: '系统默认角色',
59
- tenantId: currentTenant.uuid,
60
- description: '创建租户时自动生成,可以设置权限,不可更改删除,所有租户用户默认拥有该角色',
61
- type: 1
62
- },
63
- { transaction: t }
64
- );
65
- await models.tenantOrg.create(
66
- {
67
- name: '根组织',
68
- tenantId: currentTenant.uuid
69
- },
70
- { transaction: t }
71
- );
72
- await t.commit();
73
- } catch (e) {
74
- await t.rollback();
75
- throw e;
76
- }
77
- };
78
-
79
- const getAllTenantList = async ({ filter, perPage, currentPage }) => {
80
- const queryFilter = {};
81
- if (filter?.name) {
82
- queryFilter.name = {
83
- [fastify.sequelize.Sequelize.Op.like]: `%${filter.name}%`
84
- };
85
- }
86
-
87
- if (filter?.serviceStartTime) {
88
- queryFilter.serviceStartTime = {
89
- [fastify.sequelize.Sequelize.Op.gt]: filter.serviceStartTime
90
- };
91
- }
92
-
93
- if (filter?.serviceEndTime) {
94
- queryFilter.serviceEndTime = {
95
- [fastify.sequelize.Sequelize.Op.lt]: filter.serviceEndTime
96
- };
97
- }
98
-
99
- const { count, rows } = await models.tenant.findAndCountAll({
100
- where: queryFilter,
101
- offset: currentPage * (currentPage - 1),
102
- limit: perPage
103
- });
104
-
105
- /*const res = await models.tenantUser.findAll({
106
- attributes: ['tenantId', fastify.sequelize.instance.fn('count', fastify.sequelize.instance.col('tenantId'))],
107
- where: {
108
- tenantId: {
109
- [fastify.sequelize.Sequelize.Op.in]: rows.map(({ id }) => id)
110
- }
111
- },
112
- group: 'tenantId'
113
- });*/
114
-
115
- return {
116
- pageData: rows.map(item => {
117
- return Object.assign({}, item.get({ pain: true }), { id: item.uuid });
118
- }),
119
- totalCount: count
120
- };
121
- };
122
-
123
- services.tenant = {
124
- getTenantInstance,
125
- getTenant,
126
- closeTenant,
127
- openTenant,
128
- saveTenant,
129
- addTenant,
130
- getAllTenantList
131
- };
132
- });