fix: update assocations in belongs to many repository (#3229)

This commit is contained in:
ChengLei Shao 2023-12-19 10:07:25 +08:00 committed by GitHub
parent c129889df6
commit f60c7626e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 131 additions and 45 deletions

View File

@ -344,6 +344,38 @@ describe('belongs to many', () => {
await db.close();
});
it('should create associations with associations', async () => {
const p1 = await Post.repository.create({
values: {
title: 'p1',
},
});
const postTagsRepository = new BelongsToManyRepository(Post, 'tags', p1.id);
await postTagsRepository.create({
values: {
name: 't1',
colors: [
{
name: 'red',
},
],
},
});
const t1 = await postTagsRepository.findOne({
filter: {
name: 't1',
},
appends: ['colors'],
});
expect(t1.name).toEqual('t1');
expect(t1.colors.length).toEqual(1);
expect(t1.colors[0].name).toEqual('red');
});
test('create with through values', async () => {
const p1 = await Post.repository.create({
values: {

View File

@ -1,7 +1,7 @@
import lodash from 'lodash';
import { BelongsToMany, Op, Transaction } from 'sequelize';
import { AggregateOptions, CreateOptions, DestroyOptions, TargetKey } from '../repository';
import { updateThroughTableValue } from '../update-associations';
import { updateAssociations, updateThroughTableValue } from '../update-associations';
import { MultipleRelationRepository } from './multiple-relation-repository';
import { transaction } from './relation-repository';
import { AssociatedOptions, PrimaryKeyWithThroughValues } from './types';
@ -53,7 +53,9 @@ export class BelongsToManyRepository extends MultipleRelationRepository {
transaction,
};
return sourceModel[createAccessor](values, createOptions);
const instance = await sourceModel[createAccessor](values, createOptions);
await updateAssociations(instance, values, { ...options, transaction });
return instance;
}
@transaction((args, transaction) => {
@ -129,49 +131,6 @@ export class BelongsToManyRepository extends MultipleRelationRepository {
return true;
}
protected async setTargets(
call: 'add' | 'set',
options: TargetKey | TargetKey[] | PrimaryKeyWithThroughValues | PrimaryKeyWithThroughValues[] | AssociatedOptions,
) {
const handleKeys: TargetKey[] | PrimaryKeyWithThroughValues[] = this.convertTks(options) as any;
const transaction = await this.getTransaction(options, false);
const sourceModel = await this.getSourceModel(transaction);
const setObj = (<any>handleKeys).reduce((carry, item) => {
if (Array.isArray(item)) {
carry[item[0]] = item[1];
} else {
carry[item] = true;
}
return carry;
}, {});
const targetKeys = Object.keys(setObj);
const association = this.association;
const targetObjects = await this.targetModel.findAll({
where: {
[association['targetKey']]: targetKeys,
},
transaction,
});
await sourceModel[this.accessors()[call]](targetObjects, {
transaction,
});
for (const [id, throughValues] of Object.entries(setObj)) {
if (typeof throughValues === 'object') {
const instance = await this.targetModel.findByPk(id, {
transaction,
});
await updateThroughTableValue(instance, this.throughName(), throughValues, sourceModel, transaction);
}
}
}
@transaction((args, transaction) => {
return {
tk: args[0],
@ -244,4 +203,47 @@ export class BelongsToManyRepository extends MultipleRelationRepository {
throughModel() {
return (<any>this.association).through.model;
}
protected async setTargets(
call: 'add' | 'set',
options: TargetKey | TargetKey[] | PrimaryKeyWithThroughValues | PrimaryKeyWithThroughValues[] | AssociatedOptions,
) {
const handleKeys: TargetKey[] | PrimaryKeyWithThroughValues[] = this.convertTks(options) as any;
const transaction = await this.getTransaction(options, false);
const sourceModel = await this.getSourceModel(transaction);
const setObj = (<any>handleKeys).reduce((carry, item) => {
if (Array.isArray(item)) {
carry[item[0]] = item[1];
} else {
carry[item] = true;
}
return carry;
}, {});
const targetKeys = Object.keys(setObj);
const association = this.association;
const targetObjects = await this.targetModel.findAll({
where: {
[association['targetKey']]: targetKeys,
},
transaction,
});
await sourceModel[this.accessors()[call]](targetObjects, {
transaction,
});
for (const [id, throughValues] of Object.entries(setObj)) {
if (typeof throughValues === 'object') {
const instance = await this.targetModel.findByPk(id, {
transaction,
});
await updateThroughTableValue(instance, this.throughName(), throughValues, sourceModel, transaction);
}
}
}
}

View File

@ -26,6 +26,58 @@ describe('destroy action with acl', () => {
await app.destroy();
});
it('should create role through user resource', async () => {
const UserCollection = app.db.getCollection('users');
const user = await UserCollection.repository.create({
values: {
name: 'test_user',
},
});
const userRolesRepository = app.db.getRepository('users.roles', user.get('id'));
const roleName = 'r_voluptas-assumenda-omnis';
await userRolesRepository.create({
values: {
name: roleName,
snippets: ['!ui.*', '!pm', '!pm.*'],
title: 'r_harum-qui-doloremque',
resources: [
{
usingActionsConfig: true,
actions: [
{
name: 'create',
fields: ['id', 'nickname', 'username', 'email', 'phone', 'password', 'roles'],
scope: null,
},
{
name: 'view',
fields: ['id', 'nickname', 'username', 'email', 'phone', 'password', 'roles'],
scope: {
name: '数据范围',
scope: {
createdById: '{{ ctx.state.currentUser.id }}',
},
},
},
],
name: 'users',
},
],
},
});
const role = await app.db.getRepository('roles').findOne({
filter: {
name: roleName,
},
appends: ['resources'],
});
expect(role.get('resources').length).toBe(1);
});
it('should load the association collection when the source collection does not have the createdById field', async () => {
const A = app.collection({
name: 'a',