From 472190b7d5b974c58cf9762e4f13c6b01ea5733c Mon Sep 17 00:00:00 2001 From: Zhi Chen <350447433@qq.com> Date: Mon, 2 Sep 2024 09:10:19 +0800 Subject: [PATCH] feat: user sync support custom fields and department owner (#5158) --- .../src/server/user-data-resource-manager.ts | 7 ++- .../src/server/__tests__/data-sync.test.ts | 48 +++++++++++++++++ .../plugin-users/src/server/server.ts | 2 +- .../src/server/user-data-sync-resource.ts | 52 +++++++++++-------- 4 files changed, 84 insertions(+), 25 deletions(-) diff --git a/packages/plugins/@nocobase/plugin-user-data-sync/src/server/user-data-resource-manager.ts b/packages/plugins/@nocobase/plugin-user-data-sync/src/server/user-data-resource-manager.ts index fa0aac086e..89a2bc3a5d 100644 --- a/packages/plugins/@nocobase/plugin-user-data-sync/src/server/user-data-resource-manager.ts +++ b/packages/plugins/@nocobase/plugin-user-data-sync/src/server/user-data-resource-manager.ts @@ -17,7 +17,7 @@ export type FormatUser = { email?: string; nickname?: string; phone?: string; - departments?: string[]; + departments?: (string | FormatUserDepartment)[]; isDeleted?: boolean; [key: string]: any; }; @@ -30,6 +30,11 @@ export type FormatDepartment = { [key: string]: any; }; +export type FormatUserDepartment = { + uid: string; + isOwner?: boolean; +}; + export type UserDataRecord = FormatUser | FormatDepartment; export type SyncDataType = 'user' | 'department'; diff --git a/packages/plugins/@nocobase/plugin-users/src/server/__tests__/data-sync.test.ts b/packages/plugins/@nocobase/plugin-users/src/server/__tests__/data-sync.test.ts index 816925a7dd..0b1d2f99c0 100644 --- a/packages/plugins/@nocobase/plugin-users/src/server/__tests__/data-sync.test.ts +++ b/packages/plugins/@nocobase/plugin-users/src/server/__tests__/data-sync.test.ts @@ -119,4 +119,52 @@ describe('user data sync', () => { expect(user2).toBeTruthy(); expect(user2.nickname).toBe('test2'); }); + + it('should update user custom field', async () => { + const userCollection = db.getCollection('users'); + userCollection.addField('customField', { type: 'string' }); + await db.sync({ + alter: true, + }); + await resourceManager.updateOrCreate({ + sourceName: 'test', + dataType: 'user', + matchKey: 'email', + records: [ + { + uid: '1', + nickname: 'test', + email: 'test@nocobase.com', + customField: 'test', + }, + ], + }); + const user = await db.getRepository('users').findOne({ + filter: { + email: 'test@nocobase.com', + }, + }); + expect(user).toBeTruthy(); + expect(user.customField).toBe('test'); + await resourceManager.updateOrCreate({ + sourceName: 'test', + dataType: 'user', + matchKey: 'email', + records: [ + { + uid: '1', + nickname: 'test', + email: 'test@nocobase.com', + customField: 'test2', + }, + ], + }); + const user2 = await db.getRepository('users').findOne({ + filter: { + id: user.id, + }, + }); + expect(user2).toBeTruthy(); + expect(user2.customField).toBe('test2'); + }); }); diff --git a/packages/plugins/@nocobase/plugin-users/src/server/server.ts b/packages/plugins/@nocobase/plugin-users/src/server/server.ts index ac4d218e0b..1034775186 100644 --- a/packages/plugins/@nocobase/plugin-users/src/server/server.ts +++ b/packages/plugins/@nocobase/plugin-users/src/server/server.ts @@ -182,7 +182,7 @@ export default class PluginUsersServer extends Plugin { }); const userDataSyncPlugin = this.app.pm.get('user-data-sync') as PluginUserDataSyncServer; - if (userDataSyncPlugin) { + if (userDataSyncPlugin && userDataSyncPlugin.enabled) { userDataSyncPlugin.resourceManager.registerResource(new UserDataSyncResource(this.db, this.app.logger)); } } diff --git a/packages/plugins/@nocobase/plugin-users/src/server/user-data-sync-resource.ts b/packages/plugins/@nocobase/plugin-users/src/server/user-data-sync-resource.ts index ec9137059b..02638e63fc 100644 --- a/packages/plugins/@nocobase/plugin-users/src/server/user-data-sync-resource.ts +++ b/packages/plugins/@nocobase/plugin-users/src/server/user-data-sync-resource.ts @@ -8,6 +8,8 @@ */ import { Model } from '@nocobase/database'; +import lodash from 'lodash'; + import { FormatUser, OriginRecord, @@ -24,7 +26,24 @@ export class UserDataSyncResource extends UserDataResource { get userRepo() { return this.db.getRepository('users'); } - + getFlteredSourceUser(sourceUser: FormatUser) { + const deleteProps = [ + 'id', + 'uid', + 'createdAt', + 'updatedAt', + 'appLang', + 'resetToken', + 'systemSettings', + 'password', + 'sort', + 'createdById', + 'updatedById', + 'isDeleted', + 'departments', + ]; + return lodash.omit(sourceUser, deleteProps); + } async updateUser(user: Model, sourceUser: FormatUser) { if (sourceUser.isDeleted) { // 删除用户 @@ -39,22 +58,13 @@ export class UserDataSyncResource extends UserDataResource { return; } let dataChanged = false; - if (sourceUser.username !== undefined && user.username !== sourceUser.username) { - user.username = sourceUser.username; - dataChanged = true; - } - if (sourceUser.phone !== undefined && user.phone !== sourceUser.phone) { - user.phone = sourceUser.phone; - dataChanged = true; - } - if (sourceUser.email !== undefined && user.email !== sourceUser.email) { - user.email = sourceUser.email; - dataChanged = true; - } - if (sourceUser.nickname !== undefined && user.nickname !== sourceUser.nickname) { - user.nickname = sourceUser.nickname; - dataChanged = true; - } + const filteredSourceUser = this.getFlteredSourceUser(sourceUser); + lodash.forOwn(filteredSourceUser, (value, key) => { + if (user[key] !== value) { + user[key] = value; + dataChanged = true; + } + }); if (dataChanged) { await user.save(); } @@ -88,13 +98,9 @@ export class UserDataSyncResource extends UserDataResource { if (user) { await this.updateUser(user, sourceUser); } else { + const filteredSourceUser = this.getFlteredSourceUser(sourceUser); user = await this.userRepo.create({ - values: { - nickname: sourceUser.nickname, - phone: sourceUser.phone, - email: sourceUser.email, - username: sourceUser.username, - }, + values: filteredSourceUser, }); } return [{ resourcesPk: user.id, isDeleted: false }];