feat: update option must have filter or filterByTk (#847)
* feat: update option must have filter or filterByTk * fix: typo * fix: typo (cherry picked from commit 83e6f93e1e3a188781530ec7492de1ed917a4dc1) # Conflicts: # packages/plugins/acl/src/server.ts # packages/plugins/collection-manager/src/__tests__/field-options/indexes.test.ts
This commit is contained in:
parent
ceed13d77e
commit
3082a7d6f8
@ -3,9 +3,9 @@ import { getRepositoryFromParams } from '../utils';
|
||||
|
||||
export async function update(ctx: Context, next) {
|
||||
const repository = getRepositoryFromParams(ctx);
|
||||
const { filterByTk, values, whitelist, blacklist, filter, updateAssociationValues } = ctx.action.params;
|
||||
const { forceUpdate, filterByTk, values, whitelist, blacklist, filter, updateAssociationValues } = ctx.action.params;
|
||||
|
||||
const instance = await repository.update({
|
||||
ctx.body = await repository.update({
|
||||
filterByTk,
|
||||
values,
|
||||
whitelist,
|
||||
@ -13,8 +13,8 @@ export async function update(ctx: Context, next) {
|
||||
filter,
|
||||
updateAssociationValues,
|
||||
context: ctx,
|
||||
forceUpdate,
|
||||
});
|
||||
|
||||
ctx.body = instance;
|
||||
await next();
|
||||
}
|
||||
|
@ -87,6 +87,7 @@ describe('has one repository', () => {
|
||||
avatar: 'new_updated_avatar',
|
||||
},
|
||||
});
|
||||
|
||||
expect((await UserProfileRepository.find())['avatar']).toEqual('new_updated_avatar');
|
||||
await UserProfileRepository.destroy();
|
||||
expect(await UserProfileRepository.find()).toBeNull();
|
||||
|
@ -57,4 +57,39 @@ describe('update', () => {
|
||||
|
||||
expect(p1.toJSON()['tags']).toEqual([]);
|
||||
});
|
||||
|
||||
it('should not update items without filter or filterByPk', async () => {
|
||||
await db.getRepository('posts').create({
|
||||
values: {
|
||||
title: 'p1',
|
||||
},
|
||||
});
|
||||
|
||||
let error;
|
||||
|
||||
try {
|
||||
await db.getRepository('posts').update({
|
||||
values: {
|
||||
title: 'p3',
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error).not.toBeUndefined();
|
||||
|
||||
const p1 = await db.getRepository('posts').findOne();
|
||||
expect(p1.toJSON()['title']).toEqual('p1');
|
||||
|
||||
await db.getRepository('posts').update({
|
||||
values: {
|
||||
title: 'p3',
|
||||
},
|
||||
filterByTk: p1.get('id') as number,
|
||||
});
|
||||
|
||||
await p1.reload();
|
||||
expect(p1.toJSON()['title']).toEqual('p3');
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,17 @@
|
||||
const mustHaveFilter = () => (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
|
||||
const oldValue = descriptor.value;
|
||||
|
||||
descriptor.value = function () {
|
||||
const options = arguments[0];
|
||||
|
||||
if (!options?.filter && !options?.filterByTk && !options?.forceUpdate) {
|
||||
throw new Error(`must provide filter or filterByTk for ${propertyKey} call, or set forceUpdate to true`);
|
||||
}
|
||||
|
||||
return oldValue.apply(this, arguments);
|
||||
};
|
||||
|
||||
return descriptor;
|
||||
};
|
||||
|
||||
export default mustHaveFilter;
|
@ -9,7 +9,7 @@ import {
|
||||
FindOptions,
|
||||
TargetKey,
|
||||
TK,
|
||||
UpdateOptions
|
||||
UpdateOptions,
|
||||
} from '../repository';
|
||||
import { updateModelByValues } from '../update-associations';
|
||||
import { UpdateGuard } from '../update-guard';
|
||||
|
@ -7,7 +7,7 @@ import FilterParser from '../filter-parser';
|
||||
import { Model } from '../model';
|
||||
import { OptionsParser } from '../options-parser';
|
||||
import { CreateOptions, Filter, FindOptions } from '../repository';
|
||||
import { transactionWrapperBuilder } from '../transaction-decorator';
|
||||
import { transactionWrapperBuilder } from '../decorators/transaction-decorator';
|
||||
import { updateAssociations } from '../update-associations';
|
||||
import { UpdateGuard } from '../update-guard';
|
||||
|
||||
|
@ -13,6 +13,8 @@ import {
|
||||
} from 'sequelize';
|
||||
import { Collection } from './collection';
|
||||
import { Database } from './database';
|
||||
import mustHaveFilter from './decorators/must-have-filter-decorator';
|
||||
import { transactionWrapperBuilder } from './decorators/transaction-decorator';
|
||||
import { RelationField } from './fields';
|
||||
import FilterParser from './filter-parser';
|
||||
import { Model } from './model';
|
||||
@ -22,7 +24,6 @@ import { BelongsToRepository } from './relation-repository/belongs-to-repository
|
||||
import { HasManyRepository } from './relation-repository/hasmany-repository';
|
||||
import { HasOneRepository } from './relation-repository/hasone-repository';
|
||||
import { RelationRepository } from './relation-repository/relation-repository';
|
||||
import { transactionWrapperBuilder } from './transaction-decorator';
|
||||
import { updateAssociations, updateModelByValues } from './update-associations';
|
||||
import { UpdateGuard } from './update-guard';
|
||||
|
||||
@ -345,7 +346,8 @@ export class Repository<TModelAttributes extends {} = any, TCreationAttributes e
|
||||
* @param options
|
||||
*/
|
||||
@transaction()
|
||||
async update(options: UpdateOptions) {
|
||||
@mustHaveFilter()
|
||||
async update(options: UpdateOptions & { forceUpdate?: boolean }) {
|
||||
const transaction = await this.getTransaction(options);
|
||||
const guard = UpdateGuard.fromOptions(this.model, options);
|
||||
|
||||
|
@ -26,14 +26,18 @@ describe('acl', () => {
|
||||
const UserRepo = db.getCollection('users').repository;
|
||||
admin = await UserRepo.create({
|
||||
values: {
|
||||
roles: ['admin']
|
||||
}
|
||||
roles: ['admin'],
|
||||
},
|
||||
});
|
||||
|
||||
const userPlugin = app.getPlugin('@nocobase/plugin-users') as UsersPlugin;
|
||||
adminAgent = app.agent().auth(userPlugin.jwtService.sign({
|
||||
userId: admin.get('id'),
|
||||
}), { type: 'bearer' });
|
||||
|
||||
adminAgent = app.agent().auth(
|
||||
userPlugin.jwtService.sign({
|
||||
userId: admin.get('id'),
|
||||
}),
|
||||
{ type: 'bearer' },
|
||||
);
|
||||
|
||||
uiSchemaRepository = db.getRepository('uiSchemas');
|
||||
});
|
||||
@ -41,7 +45,7 @@ describe('acl', () => {
|
||||
it('should works with universal actions', async () => {
|
||||
await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'new'
|
||||
name: 'new',
|
||||
},
|
||||
});
|
||||
|
||||
@ -54,16 +58,15 @@ describe('acl', () => {
|
||||
).toBeNull();
|
||||
|
||||
// grant universal action
|
||||
await adminAgent
|
||||
.resource('roles')
|
||||
.update({
|
||||
resourceIndex: 'new',
|
||||
values: {
|
||||
strategy: {
|
||||
actions: ['create'],
|
||||
},
|
||||
await adminAgent.resource('roles').update({
|
||||
resourceIndex: 'new',
|
||||
values: {
|
||||
strategy: {
|
||||
actions: ['create'],
|
||||
},
|
||||
});
|
||||
},
|
||||
forceUpdate: true,
|
||||
});
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
@ -104,15 +107,13 @@ describe('acl', () => {
|
||||
},
|
||||
});
|
||||
|
||||
await adminAgent
|
||||
.resource('roles.resources', 'new')
|
||||
.create({
|
||||
values: {
|
||||
name: 'c1',
|
||||
usingActionsConfig: true,
|
||||
actions: [],
|
||||
},
|
||||
});
|
||||
await adminAgent.resource('roles.resources', 'new').create({
|
||||
values: {
|
||||
name: 'c1',
|
||||
usingActionsConfig: true,
|
||||
actions: [],
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
@ -150,39 +151,37 @@ describe('acl', () => {
|
||||
});
|
||||
|
||||
// create c1 published scope
|
||||
const { body: { data: publishedScope } } = await adminAgent
|
||||
.resource('rolesResourcesScopes')
|
||||
.create({
|
||||
values: {
|
||||
resourceName: 'c1',
|
||||
name: 'published',
|
||||
scope: {
|
||||
published: true,
|
||||
},
|
||||
const {
|
||||
body: { data: publishedScope },
|
||||
} = await adminAgent.resource('rolesResourcesScopes').create({
|
||||
values: {
|
||||
resourceName: 'c1',
|
||||
name: 'published',
|
||||
scope: {
|
||||
published: true,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// await db.getRepository('rolesResourcesScopes').findOne();
|
||||
|
||||
// set admin resources
|
||||
await adminAgent
|
||||
.resource('roles.resources', 'new')
|
||||
.create({
|
||||
values: {
|
||||
name: 'c1',
|
||||
usingActionsConfig: true,
|
||||
actions: [
|
||||
{
|
||||
name: 'create',
|
||||
scope: publishedScope.id,
|
||||
},
|
||||
{
|
||||
name: 'view',
|
||||
fields: ['title', 'age'],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
await adminAgent.resource('roles.resources', 'new').create({
|
||||
values: {
|
||||
name: 'c1',
|
||||
usingActionsConfig: true,
|
||||
actions: [
|
||||
{
|
||||
name: 'create',
|
||||
scope: publishedScope.id,
|
||||
},
|
||||
{
|
||||
name: 'view',
|
||||
fields: ['title', 'age'],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
@ -215,32 +214,28 @@ describe('acl', () => {
|
||||
});
|
||||
|
||||
// revoke action
|
||||
const response = await adminAgent
|
||||
.resource('roles.resources', role.get('name'))
|
||||
.list({
|
||||
appends: ['actions'],
|
||||
});
|
||||
const response = await adminAgent.resource('roles.resources', role.get('name')).list({
|
||||
appends: ['actions'],
|
||||
});
|
||||
|
||||
expect(response.statusCode).toEqual(200);
|
||||
|
||||
const actions = response.body.data[0].actions;
|
||||
const collectionName = response.body.data[0].name;
|
||||
|
||||
await adminAgent
|
||||
.resource('roles.resources', role.get('name'))
|
||||
.update({
|
||||
filterByTk: collectionName,
|
||||
values: {
|
||||
name: 'c1',
|
||||
usingActionsConfig: true,
|
||||
actions: [
|
||||
{
|
||||
name: 'view',
|
||||
fields: ['title', 'age'],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
await adminAgent.resource('roles.resources', role.get('name')).update({
|
||||
filterByTk: collectionName,
|
||||
values: {
|
||||
name: 'c1',
|
||||
usingActionsConfig: true,
|
||||
actions: [
|
||||
{
|
||||
name: 'view',
|
||||
fields: ['title', 'age'],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
@ -254,7 +249,7 @@ describe('acl', () => {
|
||||
it('should revoke resource when collection destroy', async () => {
|
||||
await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'new'
|
||||
name: 'new',
|
||||
},
|
||||
});
|
||||
|
||||
@ -272,21 +267,19 @@ describe('acl', () => {
|
||||
},
|
||||
});
|
||||
|
||||
await adminAgent
|
||||
.resource('roles.resources')
|
||||
.create({
|
||||
associatedIndex: 'new',
|
||||
values: {
|
||||
name: 'posts',
|
||||
usingActionsConfig: true,
|
||||
actions: [
|
||||
{
|
||||
name: 'view',
|
||||
fields: ['title'],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
await adminAgent.resource('roles.resources').create({
|
||||
associatedIndex: 'new',
|
||||
values: {
|
||||
name: 'posts',
|
||||
usingActionsConfig: true,
|
||||
actions: [
|
||||
{
|
||||
name: 'view',
|
||||
fields: ['title'],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
@ -314,7 +307,7 @@ describe('acl', () => {
|
||||
it('should revoke actions when not using actions config', async () => {
|
||||
await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'new'
|
||||
name: 'new',
|
||||
},
|
||||
});
|
||||
|
||||
@ -325,20 +318,18 @@ describe('acl', () => {
|
||||
},
|
||||
});
|
||||
|
||||
await adminAgent
|
||||
.resource('roles.resources')
|
||||
.create({
|
||||
associatedIndex: 'new',
|
||||
values: {
|
||||
name: 'posts',
|
||||
usingActionsConfig: true,
|
||||
actions: [
|
||||
{
|
||||
name: 'create',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
await adminAgent.resource('roles.resources').create({
|
||||
associatedIndex: 'new',
|
||||
values: {
|
||||
name: 'posts',
|
||||
usingActionsConfig: true,
|
||||
actions: [
|
||||
{
|
||||
name: 'create',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
@ -352,21 +343,19 @@ describe('acl', () => {
|
||||
action: 'create',
|
||||
});
|
||||
|
||||
await adminAgent
|
||||
.resource('roles.resources', 'new')
|
||||
.update({
|
||||
filterByTk: (
|
||||
await db.getRepository('rolesResources').findOne({
|
||||
filter: {
|
||||
name: 'posts',
|
||||
roleName: 'new',
|
||||
},
|
||||
})
|
||||
).get('name') as string,
|
||||
values: {
|
||||
usingActionsConfig: false,
|
||||
},
|
||||
});
|
||||
await adminAgent.resource('roles.resources', 'new').update({
|
||||
filterByTk: (
|
||||
await db.getRepository('rolesResources').findOne({
|
||||
filter: {
|
||||
name: 'posts',
|
||||
roleName: 'new',
|
||||
},
|
||||
})
|
||||
).get('name') as string,
|
||||
values: {
|
||||
usingActionsConfig: false,
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
@ -376,21 +365,19 @@ describe('acl', () => {
|
||||
}),
|
||||
).toBeNull();
|
||||
|
||||
await adminAgent
|
||||
.resource('roles.resources', 'new')
|
||||
.update({
|
||||
filterByTk: (
|
||||
await db.getRepository('rolesResources').findOne({
|
||||
filter: {
|
||||
name: 'posts',
|
||||
roleName: 'new',
|
||||
},
|
||||
})
|
||||
).get('name') as string,
|
||||
values: {
|
||||
usingActionsConfig: true,
|
||||
},
|
||||
});
|
||||
await adminAgent.resource('roles.resources', 'new').update({
|
||||
filterByTk: (
|
||||
await db.getRepository('rolesResources').findOne({
|
||||
filter: {
|
||||
name: 'posts',
|
||||
roleName: 'new',
|
||||
},
|
||||
})
|
||||
).get('name') as string,
|
||||
values: {
|
||||
usingActionsConfig: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
@ -408,7 +395,7 @@ describe('acl', () => {
|
||||
it('should add fields when field created', async () => {
|
||||
await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'new'
|
||||
name: 'new',
|
||||
},
|
||||
});
|
||||
|
||||
@ -426,21 +413,19 @@ describe('acl', () => {
|
||||
},
|
||||
});
|
||||
|
||||
await adminAgent
|
||||
.resource('roles.resources')
|
||||
.create({
|
||||
associatedIndex: 'new',
|
||||
values: {
|
||||
name: 'posts',
|
||||
usingActionsConfig: true,
|
||||
actions: [
|
||||
{
|
||||
name: 'view',
|
||||
fields: ['title'],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
await adminAgent.resource('roles.resources').create({
|
||||
associatedIndex: 'new',
|
||||
values: {
|
||||
name: 'posts',
|
||||
usingActionsConfig: true,
|
||||
actions: [
|
||||
{
|
||||
name: 'view',
|
||||
fields: ['title'],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const allowFields = acl.can({
|
||||
role: 'new',
|
||||
@ -494,14 +479,17 @@ describe('acl', () => {
|
||||
const UserRepo = db.getCollection('users').repository;
|
||||
const user = await UserRepo.create({
|
||||
values: {
|
||||
roles: ['new']
|
||||
}
|
||||
roles: ['new'],
|
||||
},
|
||||
});
|
||||
|
||||
const userPlugin = app.getPlugin('@nocobase/plugin-users') as UsersPlugin;
|
||||
const userAgent = app.agent().auth(userPlugin.jwtService.sign({
|
||||
userId: user.get('id'),
|
||||
}), { type: 'bearer' });
|
||||
const userAgent = app.agent().auth(
|
||||
userPlugin.jwtService.sign({
|
||||
userId: user.get('id'),
|
||||
}),
|
||||
{ type: 'bearer' },
|
||||
);
|
||||
|
||||
const schema = {
|
||||
'x-uid': 'test',
|
||||
|
@ -17,7 +17,6 @@ export async function prepareApp() {
|
||||
app.plugin(PluginUiSchema);
|
||||
app.plugin(PluginErrorHandler);
|
||||
app.plugin(PluginCollectionManager);
|
||||
|
||||
app.plugin(PluginACL);
|
||||
await app.loadAndInstall();
|
||||
|
||||
|
@ -32,14 +32,17 @@ describe('role api', () => {
|
||||
const UserRepo = db.getCollection('users').repository;
|
||||
admin = await UserRepo.create({
|
||||
values: {
|
||||
roles: ['admin']
|
||||
}
|
||||
roles: ['admin'],
|
||||
},
|
||||
});
|
||||
|
||||
const userPlugin = app.getPlugin('@nocobase/plugin-users') as UsersPlugin;
|
||||
adminAgent = app.agent().auth(userPlugin.jwtService.sign({
|
||||
userId: admin.get('id'),
|
||||
}), { type: 'bearer' });
|
||||
adminAgent = app.agent().auth(
|
||||
userPlugin.jwtService.sign({
|
||||
userId: admin.get('id'),
|
||||
}),
|
||||
{ type: 'bearer' },
|
||||
);
|
||||
});
|
||||
|
||||
it('should list actions', async () => {
|
||||
@ -49,15 +52,14 @@ describe('role api', () => {
|
||||
|
||||
it('should grant universal role actions', async () => {
|
||||
// grant role actions
|
||||
const response = await adminAgent
|
||||
.resource('roles')
|
||||
.update({
|
||||
values: {
|
||||
strategy: {
|
||||
actions: ['create:all', 'view:own'],
|
||||
},
|
||||
const response = await adminAgent.resource('roles').update({
|
||||
forceUpdate: true,
|
||||
values: {
|
||||
strategy: {
|
||||
actions: ['create:all', 'view:own'],
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
expect(response.statusCode).toEqual(200);
|
||||
|
||||
|
@ -416,10 +416,12 @@ export class PluginACL extends Plugin {
|
||||
}
|
||||
|
||||
const User = this.db.getCollection('users');
|
||||
|
||||
await User.repository.update({
|
||||
values: {
|
||||
roles: ['root', 'admin', 'member'],
|
||||
},
|
||||
forceUpdate: true,
|
||||
});
|
||||
|
||||
const RolesUsers = this.db.getCollection('rolesUsers');
|
||||
|
@ -8,73 +8,70 @@ describe('field indexes', () => {
|
||||
beforeEach(async () => {
|
||||
app = await createApp();
|
||||
agent = app.agent();
|
||||
await agent
|
||||
.resource('collections')
|
||||
.create({
|
||||
values: {
|
||||
name: 'test1',
|
||||
},
|
||||
});
|
||||
await agent.resource('collections').create({
|
||||
values: {
|
||||
name: 'test1',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.destroy();
|
||||
});
|
||||
|
||||
it.only('create unique constraint after added dulplicated records', async () => {
|
||||
it('create unique constraint after added duplicated records', async () => {
|
||||
const tableName = 'test1';
|
||||
// create an field with unique constraint
|
||||
const field = await agent
|
||||
.resource('collections.fields', tableName)
|
||||
.create({
|
||||
values: {
|
||||
name: 'title',
|
||||
type: 'string'
|
||||
},
|
||||
});
|
||||
const field = await agent.resource('collections.fields', tableName).create({
|
||||
values: {
|
||||
name: 'title',
|
||||
type: 'string',
|
||||
},
|
||||
});
|
||||
|
||||
// create a record
|
||||
const response1 = await agent.resource(tableName).create({
|
||||
values: { title: 't1' }
|
||||
values: { title: 't1' },
|
||||
});
|
||||
|
||||
// create another same record
|
||||
const response2 = await agent.resource(tableName).create({
|
||||
values: { title: 't1' }
|
||||
values: { title: 't1' },
|
||||
});
|
||||
|
||||
const response3 = await agent.resource('fields').update({
|
||||
filterByTk: field.id,
|
||||
filterByTk: field.body.data.key,
|
||||
values: {
|
||||
unique: true
|
||||
}
|
||||
unique: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(response3.status).toBe(400);
|
||||
|
||||
const response4 = await agent.resource(tableName).create({
|
||||
values: { title: 't1' }
|
||||
values: { title: 't1' },
|
||||
});
|
||||
|
||||
expect(response4.status).toBe(200);
|
||||
expect(response4.body.data.title).toBe('t1');
|
||||
});
|
||||
|
||||
it('field value cannot be duplicated with unique index', async () => {
|
||||
const tableName = 'test1';
|
||||
// create an field with unique constraint
|
||||
const field = await agent
|
||||
.resource('collections.fields', tableName)
|
||||
.create({
|
||||
values: {
|
||||
name: 'title',
|
||||
type: 'string',
|
||||
unique: true
|
||||
},
|
||||
});
|
||||
// create a field with unique constraint
|
||||
const field = await agent.resource('collections.fields', tableName).create({
|
||||
values: {
|
||||
name: 'title',
|
||||
type: 'string',
|
||||
unique: true,
|
||||
},
|
||||
});
|
||||
|
||||
// create a record
|
||||
const response1 = await agent.resource(tableName).create({
|
||||
values: {
|
||||
title: 't1'
|
||||
}
|
||||
title: 't1',
|
||||
},
|
||||
});
|
||||
expect(response1.status).toBe(200);
|
||||
expect(response1.body.data.title).toBe('t1');
|
||||
@ -82,48 +79,49 @@ describe('field indexes', () => {
|
||||
// create another record with the same value on unique field should fail
|
||||
const response2 = await agent.resource(tableName).create({
|
||||
values: {
|
||||
title: 't1'
|
||||
}
|
||||
title: 't1',
|
||||
},
|
||||
});
|
||||
expect(response2.status).toBe(400);
|
||||
|
||||
// update field to remove unique constraint
|
||||
await agent.resource('fields').update({
|
||||
filterByTk: field.id,
|
||||
filterByTk: field.body.data.key,
|
||||
values: {
|
||||
unique: false
|
||||
}
|
||||
unique: false,
|
||||
},
|
||||
});
|
||||
|
||||
// create another record with the same value on unique field should be ok
|
||||
const response3 = await agent.resource(tableName).create({
|
||||
values: {
|
||||
title: 't1'
|
||||
}
|
||||
title: 't1',
|
||||
},
|
||||
});
|
||||
expect(response3.status).toBe(200);
|
||||
expect(response3.body.data.title).toBe('t1');
|
||||
|
||||
// update field to add unique constraint should fail because of duplicated records
|
||||
const response4 = await agent.resource('fields').update({
|
||||
filterByTk: field.id,
|
||||
filterByTk: field.body.data.key,
|
||||
values: {
|
||||
unique: true
|
||||
}
|
||||
unique: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(response4.status).toBe(400);
|
||||
|
||||
// remove a duplicated record
|
||||
await agent.resource(tableName).destroy({
|
||||
filterByTk: response3.body.data.id
|
||||
filterByTk: response3.body.data.id,
|
||||
});
|
||||
|
||||
// update field to add unique constraint should be ok
|
||||
const response6 = await agent.resource('fields').update({
|
||||
filterByTk: field.id,
|
||||
filterByTk: field.body.data.key,
|
||||
values: {
|
||||
unique: true
|
||||
}
|
||||
unique: true,
|
||||
},
|
||||
});
|
||||
expect(response6.status).toBe(200);
|
||||
});
|
||||
|
@ -11,7 +11,7 @@ import {
|
||||
afterCreateForReverseField,
|
||||
beforeCreateForChildrenCollection,
|
||||
beforeCreateForReverseField,
|
||||
beforeInitOptions
|
||||
beforeInitOptions,
|
||||
} from './hooks';
|
||||
import { CollectionModel, FieldModel } from './models';
|
||||
|
||||
@ -67,7 +67,7 @@ export class CollectionManagerPlugin extends Plugin {
|
||||
if (context) {
|
||||
await model.migrate({
|
||||
isNew: true,
|
||||
transaction
|
||||
transaction,
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -76,7 +76,7 @@ export class CollectionManagerPlugin extends Plugin {
|
||||
if (context) {
|
||||
await model.migrate({
|
||||
isNew: true,
|
||||
transaction
|
||||
transaction,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user