Merge tag '2023.12.0-beta.5' into merge-upstream
This commit is contained in:
@@ -51,6 +51,7 @@ export type RolePolicies = {
|
||||
userListLimit: number;
|
||||
userEachUserListsLimit: number;
|
||||
rateLimitFactor: number;
|
||||
avatarDecorationLimit: number;
|
||||
};
|
||||
|
||||
export const DEFAULT_POLICIES: RolePolicies = {
|
||||
@@ -80,6 +81,7 @@ export const DEFAULT_POLICIES: RolePolicies = {
|
||||
userListLimit: 10,
|
||||
userEachUserListsLimit: 50,
|
||||
rateLimitFactor: 1,
|
||||
avatarDecorationLimit: 1,
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
@@ -333,6 +335,7 @@ export class RoleService implements OnApplicationShutdown {
|
||||
userListLimit: calc('userListLimit', vs => Math.max(...vs)),
|
||||
userEachUserListsLimit: calc('userEachUserListsLimit', vs => Math.max(...vs)),
|
||||
rateLimitFactor: calc('rateLimitFactor', vs => Math.max(...vs)),
|
||||
avatarDecorationLimit: calc('avatarDecorationLimit', vs => Math.max(...vs)),
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -361,6 +361,8 @@ export class UserEntityService implements OnModuleInit {
|
||||
id: ud.id,
|
||||
angle: ud.angle || undefined,
|
||||
flipH: ud.flipH || undefined,
|
||||
offsetX: ud.offsetX || undefined,
|
||||
offsetY: ud.offsetY || undefined,
|
||||
url: decorations.find(d => d.id === ud.id)!.url,
|
||||
}))) : [],
|
||||
isBot: user.isBot,
|
||||
|
@@ -150,8 +150,10 @@ export class MiUser {
|
||||
})
|
||||
public avatarDecorations: {
|
||||
id: string;
|
||||
angle: number;
|
||||
flipH: boolean;
|
||||
angle?: number;
|
||||
flipH?: boolean;
|
||||
offsetX?: number;
|
||||
offsetY?: number;
|
||||
}[];
|
||||
|
||||
@Index()
|
||||
|
@@ -145,6 +145,7 @@ export const packedRoleSchema = {
|
||||
userEachUserListsLimit: rolePolicyValue,
|
||||
canManageAvatarDecorations: rolePolicyValue,
|
||||
canUseTranslator: rolePolicyValue,
|
||||
avatarDecorationLimit: rolePolicyValue,
|
||||
},
|
||||
},
|
||||
usersCount: {
|
||||
|
@@ -74,6 +74,14 @@ export const packedUserLiteSchema = {
|
||||
format: 'url',
|
||||
nullable: false, optional: false,
|
||||
},
|
||||
offsetX: {
|
||||
type: 'number',
|
||||
nullable: false, optional: true,
|
||||
},
|
||||
offsetY: {
|
||||
type: 'number',
|
||||
nullable: false, optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -664,6 +672,10 @@ export const packedMeDetailedOnlySchema = {
|
||||
type: 'number',
|
||||
nullable: false, optional: false,
|
||||
},
|
||||
avatarDecorationLimit: {
|
||||
type: 'number',
|
||||
nullable: false, optional: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
//#region secrets
|
||||
|
@@ -233,7 +233,7 @@ export class QueueProcessorService implements OnApplicationShutdown {
|
||||
autorun: false,
|
||||
concurrency: this.config.inboxJobConcurrency ?? 16,
|
||||
limiter: {
|
||||
max: this.config.inboxJobPerSec ?? 16,
|
||||
max: this.config.inboxJobPerSec ?? 32,
|
||||
duration: 1000,
|
||||
},
|
||||
settings: {
|
||||
|
@@ -138,7 +138,7 @@ export class ActivityPubServerService {
|
||||
return;
|
||||
}
|
||||
|
||||
const algo = match[1];
|
||||
const algo = match[1].toUpperCase();
|
||||
const digestValue = match[2];
|
||||
|
||||
if (algo !== 'SHA-256') {
|
||||
@@ -493,8 +493,7 @@ export class ActivityPubServerService {
|
||||
|
||||
@bindThis
|
||||
public createServer(fastify: FastifyInstance, options: FastifyPluginOptions, done: (err?: Error) => void) {
|
||||
// addConstraintStrategy の型定義がおかしいため
|
||||
(fastify.addConstraintStrategy as any)({
|
||||
fastify.addConstraintStrategy({
|
||||
name: 'apOrHtml',
|
||||
storage() {
|
||||
const store = {} as any;
|
||||
|
@@ -61,6 +61,9 @@ export class FileServerService {
|
||||
public createServer(fastify: FastifyInstance, options: FastifyPluginOptions, done: (err?: Error) => void) {
|
||||
fastify.addHook('onRequest', (request, reply, done) => {
|
||||
reply.header('Content-Security-Policy', 'default-src \'none\'; img-src \'self\'; media-src \'self\'; style-src \'unsafe-inline\'');
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
reply.header('Access-Control-Allow-Origin', '*');
|
||||
}
|
||||
done();
|
||||
});
|
||||
|
||||
|
@@ -14,7 +14,7 @@ export const meta = {
|
||||
tags: ['admin'],
|
||||
|
||||
requireCredential: true,
|
||||
requireModerator: true,
|
||||
requireAdmin: true,
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
|
@@ -132,12 +132,14 @@ export const paramDef = {
|
||||
birthday: { ...birthdaySchema, nullable: true },
|
||||
lang: { type: 'string', enum: [null, ...Object.keys(langmap)] as string[], nullable: true },
|
||||
avatarId: { type: 'string', format: 'misskey:id', nullable: true },
|
||||
avatarDecorations: { type: 'array', maxItems: 1, items: {
|
||||
avatarDecorations: { type: 'array', maxItems: 16, items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', format: 'misskey:id' },
|
||||
angle: { type: 'number', nullable: true, maximum: 0.5, minimum: -0.5 },
|
||||
flipH: { type: 'boolean', nullable: true },
|
||||
offsetX: { type: 'number', nullable: true, maximum: 0.25, minimum: -0.25 },
|
||||
offsetY: { type: 'number', nullable: true, maximum: 0.25, minimum: -0.25 },
|
||||
},
|
||||
required: ['id'],
|
||||
} },
|
||||
@@ -313,16 +315,20 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
|
||||
if (ps.avatarDecorations) {
|
||||
const decorations = await this.avatarDecorationService.getAll(true);
|
||||
const myRoles = await this.roleService.getUserRoles(user.id);
|
||||
const [myRoles, myPolicies] = await Promise.all([this.roleService.getUserRoles(user.id), this.roleService.getUserPolicies(user.id)]);
|
||||
const allRoles = await this.roleService.getRoles();
|
||||
const decorationIds = decorations
|
||||
.filter(d => d.roleIdsThatCanBeUsedThisDecoration.filter(roleId => allRoles.some(r => r.id === roleId)).length === 0 || myRoles.some(r => d.roleIdsThatCanBeUsedThisDecoration.includes(r.id)))
|
||||
.map(d => d.id);
|
||||
|
||||
if (ps.avatarDecorations.length > myPolicies.avatarDecorationLimit) throw new ApiError(meta.errors.restrictedByRole);
|
||||
|
||||
updates.avatarDecorations = ps.avatarDecorations.filter(d => decorationIds.includes(d.id)).map(d => ({
|
||||
id: d.id,
|
||||
angle: d.angle ?? 0,
|
||||
flipH: d.flipH ?? false,
|
||||
offsetX: d.offsetX ?? 0,
|
||||
offsetY: d.offsetY ?? 0,
|
||||
}));
|
||||
}
|
||||
|
||||
|
@@ -10,6 +10,7 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { FeaturedService } from '@/core/FeaturedService.js';
|
||||
import { QueryService } from '@/core/QueryService.js';
|
||||
import { CacheService } from '@/core/CacheService.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['notes'],
|
||||
@@ -48,8 +49,16 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
private noteEntityService: NoteEntityService,
|
||||
private featuredService: FeaturedService,
|
||||
private queryService: QueryService,
|
||||
private cacheService: CacheService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
const userIdsWhoBlockingMe = me ? await this.cacheService.userBlockedCache.fetch(me.id) : new Set<string>();
|
||||
|
||||
// early return if me is blocked by requesting user
|
||||
if (userIdsWhoBlockingMe.has(ps.userId)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let noteIds = await this.featuredService.getPerUserNotesRanking(ps.userId, 50);
|
||||
|
||||
noteIds.sort((a, b) => a > b ? -1 : 1);
|
||||
|
@@ -86,6 +86,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
|
||||
if (ps.withReplies && ps.withFiles) throw new ApiError(meta.errors.bothWithRepliesAndWithFiles);
|
||||
|
||||
// early return if me is blocked by requesting user
|
||||
if (me != null) {
|
||||
const userIdsWhoBlockingMe = await this.cacheService.userBlockedCache.fetch(me.id);
|
||||
if (userIdsWhoBlockingMe.has(ps.userId)) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
if (!serverSettings.enableFanoutTimeline) {
|
||||
const timeline = await this.getFromDb({
|
||||
untilId,
|
||||
|
@@ -36,7 +36,7 @@ html
|
||||
link(rel='prefetch' href=infoImageUrl)
|
||||
link(rel='prefetch' href=notFoundImageUrl)
|
||||
//- https://github.com/misskey-dev/misskey/issues/9842
|
||||
link(rel='stylesheet' href='/assets/tabler-icons/tabler-icons.min.css?v2.37.0')
|
||||
link(rel='stylesheet' href='/assets/tabler-icons/tabler-icons.min.css?v2.44.0')
|
||||
link(rel='modulepreload' href=`/vite/${clientEntry.file}`)
|
||||
|
||||
if !config.clientManifestExists
|
||||
|
Reference in New Issue
Block a user