View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/1139 Closes #1121 Approved-by: Hazelnoot <acomputerdog@gmail.com> Approved-by: Marie <github@yuugi.dev>
This commit is contained in:
commit
fad58ddc1c
3 changed files with 30 additions and 22 deletions
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: dakkar and other Sharkey contributors
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class RegistryUniqueConstraints1750591589187 {
|
||||||
|
async up(queryRunner) {
|
||||||
|
await queryRunner.query(`DELETE FROM "registry_item" WHERE "id" IN (
|
||||||
|
SELECT t."id" FROM (
|
||||||
|
SELECT *, ROW_NUMBER() OVER (PARTITION BY "userId","key","scope","domain" ORDER BY "updatedAt" DESC) rn
|
||||||
|
FROM "registry_item"
|
||||||
|
) t WHERE t.rn>1)`);
|
||||||
|
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_d9c48d580287308f8c1f674946" ON "registry_item" ("userId", "key", "scope", "domain") NULLS NOT DISTINCT`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
await queryRunner.query(`DROP INDEX "public"."IDX_d9c48d580287308f8c1f674946"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -27,25 +27,9 @@ export class RegistryApiService {
|
||||||
public async set(userId: MiUser['id'], domain: string | null, scope: string[], key: string, value: any) {
|
public async set(userId: MiUser['id'], domain: string | null, scope: string[], key: string, value: any) {
|
||||||
// TODO: 作成できるキーの数を制限する
|
// TODO: 作成できるキーの数を制限する
|
||||||
|
|
||||||
const query = this.registryItemsRepository.createQueryBuilder('item');
|
await this.registryItemsRepository.createQueryBuilder('item')
|
||||||
if (domain) {
|
.insert()
|
||||||
query.where('item.domain = :domain', { domain: domain });
|
.values({
|
||||||
} else {
|
|
||||||
query.where('item.domain IS NULL');
|
|
||||||
}
|
|
||||||
query.andWhere('item.userId = :userId', { userId: userId });
|
|
||||||
query.andWhere('item.key = :key', { key: key });
|
|
||||||
query.andWhere('item.scope = :scope', { scope: scope });
|
|
||||||
|
|
||||||
const existingItem = await query.getOne();
|
|
||||||
|
|
||||||
if (existingItem) {
|
|
||||||
await this.registryItemsRepository.update(existingItem.id, {
|
|
||||||
updatedAt: new Date(),
|
|
||||||
value: value,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await this.registryItemsRepository.insert({
|
|
||||||
id: this.idService.gen(),
|
id: this.idService.gen(),
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
userId: userId,
|
userId: userId,
|
||||||
|
|
@ -53,8 +37,13 @@ export class RegistryApiService {
|
||||||
scope: scope,
|
scope: scope,
|
||||||
key: key,
|
key: key,
|
||||||
value: value,
|
value: value,
|
||||||
});
|
})
|
||||||
}
|
.orUpdate(
|
||||||
|
['updatedAt', 'value'],
|
||||||
|
['userId', 'key', 'scope', 'domain'],
|
||||||
|
{ upsertType: 'on-conflict-do-update' }
|
||||||
|
)
|
||||||
|
.execute();
|
||||||
|
|
||||||
if (domain == null) {
|
if (domain == null) {
|
||||||
// TODO: サードパーティアプリが傍受出来てしまうのでどうにかする
|
// TODO: サードパーティアプリが傍受出来てしまうのでどうにかする
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typ
|
||||||
import { id } from './util/id.js';
|
import { id } from './util/id.js';
|
||||||
import { MiUser } from './User.js';
|
import { MiUser } from './User.js';
|
||||||
|
|
||||||
// TODO: 同じdomain、同じscope、同じkeyのレコードは二つ以上存在しないように制約付けたい
|
|
||||||
@Entity('registry_item')
|
@Entity('registry_item')
|
||||||
|
@Index(['userId', 'key', 'scope', 'domain'], { unique: true })
|
||||||
export class MiRegistryItem {
|
export class MiRegistryItem {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
public id: string;
|
public id: string;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue