* wip

* wip

* wip

* wip

* wip

* Update registry.value.vue

* wip

* wip

* wip

* wip

* typo
This commit is contained in:
syuilo 2021-01-11 20:38:34 +09:00 committed by GitHub
parent 1286dee1ab
commit 6c975275f8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 1017 additions and 100 deletions

View file

@ -11,7 +11,7 @@ export default (endpoint: IEndpoint, ctx: Koa.Context) => new Promise((res) => {
const reply = (x?: any, y?: ApiError) => {
if (x == null) {
ctx.status = 204;
} else if (typeof x === 'number') {
} else if (typeof x === 'number' && y) {
ctx.status = x;
ctx.body = {
error: {
@ -23,7 +23,8 @@ export default (endpoint: IEndpoint, ctx: Koa.Context) => new Promise((res) => {
}
};
} else {
ctx.body = x;
// 文字列を返す場合は、JSON.stringify通さないとJSONと認識されない
ctx.body = typeof x === 'string' ? JSON.stringify(x) : x;
}
res();
};

View file

@ -1,5 +1,7 @@
import define from '../define';
import { Users } from '../../../models';
import { RegistryItems, UserProfiles, Users } from '../../../models';
import { ensure } from '../../../prelude/ensure';
import { genId } from '../../../misc/gen-id';
export const meta = {
desc: {
@ -22,6 +24,27 @@ export const meta = {
export default define(meta, async (ps, user, token) => {
const isSecure = token == null;
// TODO: そのうち消す
const profile = await UserProfiles.findOne(user.id).then(ensure);
for (const [k, v] of Object.entries(profile.clientData)) {
await RegistryItems.insert({
id: genId(),
createdAt: new Date(),
updatedAt: new Date(),
userId: user.id,
domain: null,
scope: ['client', 'base'],
key: k,
value: v
});
}
await UserProfiles.createQueryBuilder().update()
.set({
clientData: {},
})
.where('userId = :id', { id: user.id })
.execute();
return await Users.pack(user, user, {
detail: true,
includeSecrets: isSecure

View file

@ -80,7 +80,7 @@ export default define(meta, async (ps, user) => {
.where('muting.muterId = :muterId', { muterId: user.id });
const suspendedQuery = Users.createQueryBuilder('users')
.select('id')
.select('users.id')
.where('users.isSuspended = TRUE');
const query = makePaginationQuery(Notifications.createQueryBuilder('notification'), ps.sinceId, ps.untilId)

View file

@ -0,0 +1,33 @@
import $ from 'cafy';
import define from '../../../define';
import { RegistryItems } from '../../../../../models';
export const meta = {
requireCredential: true as const,
secure: true,
params: {
scope: {
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
default: [],
},
}
};
export default define(meta, async (ps, user) => {
const query = RegistryItems.createQueryBuilder('item')
.where('item.domain IS NULL')
.andWhere('item.userId = :userId', { userId: user.id })
.andWhere('item.scope = :scope', { scope: ps.scope });
const items = await query.getMany();
const res = {} as Record<string, any>;
for (const item of items) {
res[item.key] = item.value;
}
return res;
});

View file

@ -0,0 +1,48 @@
import $ from 'cafy';
import define from '../../../define';
import { RegistryItems } from '../../../../../models';
import { ApiError } from '../../../error';
export const meta = {
requireCredential: true as const,
secure: true,
params: {
key: {
validator: $.str
},
scope: {
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
default: [],
},
},
errors: {
noSuchKey: {
message: 'No such key.',
code: 'NO_SUCH_KEY',
id: '97a1e8e7-c0f7-47d2-957a-92e61256e01a'
},
},
};
export default define(meta, async (ps, user) => {
const query = RegistryItems.createQueryBuilder('item')
.where('item.domain IS NULL')
.andWhere('item.userId = :userId', { userId: user.id })
.andWhere('item.key = :key', { key: ps.key })
.andWhere('item.scope = :scope', { scope: ps.scope });
const item = await query.getOne();
if (item == null) {
throw new ApiError(meta.errors.noSuchKey);
}
return {
updatedAt: item.updatedAt,
value: item.value,
};
});

View file

@ -0,0 +1,45 @@
import $ from 'cafy';
import define from '../../../define';
import { RegistryItems } from '../../../../../models';
import { ApiError } from '../../../error';
export const meta = {
requireCredential: true as const,
secure: true,
params: {
key: {
validator: $.str
},
scope: {
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
default: [],
},
},
errors: {
noSuchKey: {
message: 'No such key.',
code: 'NO_SUCH_KEY',
id: 'ac3ed68a-62f0-422b-a7bc-d5e09e8f6a6a'
},
},
};
export default define(meta, async (ps, user) => {
const query = RegistryItems.createQueryBuilder('item')
.where('item.domain IS NULL')
.andWhere('item.userId = :userId', { userId: user.id })
.andWhere('item.key = :key', { key: ps.key })
.andWhere('item.scope = :scope', { scope: ps.scope });
const item = await query.getOne();
if (item == null) {
throw new ApiError(meta.errors.noSuchKey);
}
return item.value;
});

View file

@ -0,0 +1,41 @@
import $ from 'cafy';
import define from '../../../define';
import { RegistryItems } from '../../../../../models';
export const meta = {
requireCredential: true as const,
secure: true,
params: {
scope: {
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
default: [],
},
}
};
export default define(meta, async (ps, user) => {
const query = RegistryItems.createQueryBuilder('item')
.where('item.domain IS NULL')
.andWhere('item.userId = :userId', { userId: user.id })
.andWhere('item.scope = :scope', { scope: ps.scope });
const items = await query.getMany();
const res = {} as Record<string, string>;
for (const item of items) {
const type = typeof item.value;
res[item.key] =
item.value === null ? 'null' :
Array.isArray(item.value) ? 'array' :
type === 'number' ? 'number' :
type === 'string' ? 'string' :
type === 'boolean' ? 'boolean' :
type === 'object' ? 'object' :
null as never;
}
return res;
});

View file

@ -0,0 +1,28 @@
import $ from 'cafy';
import define from '../../../define';
import { RegistryItems } from '../../../../../models';
export const meta = {
requireCredential: true as const,
secure: true,
params: {
scope: {
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
default: [],
},
}
};
export default define(meta, async (ps, user) => {
const query = RegistryItems.createQueryBuilder('item')
.select('item.key')
.where('item.domain IS NULL')
.andWhere('item.userId = :userId', { userId: user.id })
.andWhere('item.scope = :scope', { scope: ps.scope });
const items = await query.getMany();
return items.map(x => x.key);
});

View file

@ -0,0 +1,45 @@
import $ from 'cafy';
import define from '../../../define';
import { RegistryItems } from '../../../../../models';
import { ApiError } from '../../../error';
export const meta = {
requireCredential: true as const,
secure: true,
params: {
key: {
validator: $.str
},
scope: {
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
default: [],
},
},
errors: {
noSuchKey: {
message: 'No such key.',
code: 'NO_SUCH_KEY',
id: '1fac4e8a-a6cd-4e39-a4a5-3a7e11f1b019'
},
},
};
export default define(meta, async (ps, user) => {
const query = RegistryItems.createQueryBuilder('item')
.where('item.domain IS NULL')
.andWhere('item.userId = :userId', { userId: user.id })
.andWhere('item.key = :key', { key: ps.key })
.andWhere('item.scope = :scope', { scope: ps.scope });
const item = await query.getOne();
if (item == null) {
throw new ApiError(meta.errors.noSuchKey);
}
RegistryItems.remove(item);
});

View file

@ -0,0 +1,30 @@
import $ from 'cafy';
import define from '../../../define';
import { RegistryItems } from '../../../../../models';
export const meta = {
requireCredential: true as const,
secure: true,
params: {
}
};
export default define(meta, async (ps, user) => {
const query = RegistryItems.createQueryBuilder('item')
.select('item.scope')
.where('item.domain IS NULL')
.andWhere('item.userId = :userId', { userId: user.id });
const items = await query.getMany();
const res = [] as string[][];
for (const item of items) {
if (res.some(scope => scope.join('.') === item.scope.join('.'))) continue;
res.push(item.scope);
}
return res;
});

View file

@ -0,0 +1,61 @@
import $ from 'cafy';
import { publishMainStream } from '../../../../../services/stream';
import define from '../../../define';
import { RegistryItems } from '../../../../../models';
import { genId } from '../../../../../misc/gen-id';
export const meta = {
requireCredential: true as const,
secure: true,
params: {
key: {
validator: $.str.min(1)
},
value: {
validator: $.nullable.any
},
scope: {
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
default: [],
},
}
};
export default define(meta, async (ps, user) => {
const query = RegistryItems.createQueryBuilder('item')
.where('item.domain IS NULL')
.andWhere('item.userId = :userId', { userId: user.id })
.andWhere('item.key = :key', { key: ps.key })
.andWhere('item.scope = :scope', { scope: ps.scope });
const existingItem = await query.getOne();
if (existingItem) {
await RegistryItems.update(existingItem.id, {
updatedAt: new Date(),
value: ps.value
});
} else {
await RegistryItems.insert({
id: genId(),
createdAt: new Date(),
updatedAt: new Date(),
userId: user.id,
domain: null,
scope: ps.scope,
key: ps.key,
value: ps.value
});
}
// TODO: サードパーティアプリが傍受出来てしまうのでどうにかする
publishMainStream(user.id, 'registryUpdated', {
scope: ps.scope,
key: ps.key,
value: ps.value
});
});

View file

@ -1,40 +0,0 @@
import $ from 'cafy';
import { publishMainStream } from '../../../../services/stream';
import define from '../../define';
import { UserProfiles } from '../../../../models';
import { ensure } from '../../../../prelude/ensure';
export const meta = {
requireCredential: true as const,
secure: true,
params: {
name: {
validator: $.str.match(/^[a-zA-Z]+$/)
},
value: {
validator: $.nullable.any
}
}
};
export default define(meta, async (ps, user) => {
const profile = await UserProfiles.findOne(user.id).then(ensure);
await UserProfiles.createQueryBuilder().update()
.set({
clientData: Object.assign(profile.clientData, {
[ps.name]: ps.value
}),
})
.where('userId = :id', { id: user.id })
.execute();
// Publish event
publishMainStream(user.id, 'clientSettingUpdated', {
key: ps.name,
value: ps.value
});
});