feat: user sync support custom fields and department owner (#5158)
Some checks are pending
Build Docker Image / build-and-push (push) Waiting to run
Build Pro Image / app-token (push) Waiting to run
Build Pro Image / build-and-push (push) Blocked by required conditions
E2E / Build (push) Waiting to run
E2E / Core and plugins (push) Blocked by required conditions
E2E / plugin-workflow (push) Blocked by required conditions
E2E / plugin-workflow-approval (push) Blocked by required conditions
E2E / plugin-data-source-main (push) Blocked by required conditions
E2E / Comment on PR (push) Blocked by required conditions
NocoBase Backend Test / sqlite-test (20, false) (push) Waiting to run
NocoBase Backend Test / sqlite-test (20, true) (push) Waiting to run
NocoBase Backend Test / postgres-test (public, 20, nocobase, false) (push) Waiting to run
NocoBase Backend Test / postgres-test (public, 20, nocobase, true) (push) Waiting to run
NocoBase Backend Test / postgres-test (public, 20, public, false) (push) Waiting to run
NocoBase Backend Test / postgres-test (public, 20, public, true) (push) Waiting to run
NocoBase Backend Test / postgres-test (user_schema, 20, nocobase, false) (push) Waiting to run
NocoBase Backend Test / postgres-test (user_schema, 20, nocobase, true) (push) Waiting to run
NocoBase Backend Test / postgres-test (user_schema, 20, public, false) (push) Waiting to run
NocoBase Backend Test / postgres-test (user_schema, 20, public, true) (push) Waiting to run
NocoBase Backend Test / mysql-test (20, false) (push) Waiting to run
NocoBase Backend Test / mysql-test (20, true) (push) Waiting to run
NocoBase Backend Test / mariadb-test (20, false) (push) Waiting to run
NocoBase Backend Test / mariadb-test (20, true) (push) Waiting to run
Test on Windows / build (push) Waiting to run

This commit is contained in:
Zhi Chen 2024-09-02 09:10:19 +08:00 committed by GitHub
parent 71c547f1a7
commit 472190b7d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 84 additions and 25 deletions

View File

@ -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';

View File

@ -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');
});
});

View File

@ -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));
}
}

View File

@ -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 }];