Merge remote-tracking branch 'misskey-original/develop' into develop

# Conflicts:
#	packages/frontend/src/components/MkEmojiPicker.vue
#	packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts
#	packages/frontend/src/pages/timeline.vue
This commit is contained in:
mattyatea 2023-12-14 21:08:18 +09:00
commit 7313e13397
102 changed files with 2914 additions and 1291 deletions

View file

@ -50,6 +50,7 @@ export type RolePolicies = {
userListLimit: number;
userEachUserListsLimit: number;
rateLimitFactor: number;
avatarDecorationLimit: number;
};
export const DEFAULT_POLICIES: RolePolicies = {
@ -79,6 +80,7 @@ export const DEFAULT_POLICIES: RolePolicies = {
userListLimit: 10,
userEachUserListsLimit: 50,
rateLimitFactor: 1,
avatarDecorationLimit: 1,
};
@Injectable()
@ -335,6 +337,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)),
};
}

View file

@ -362,6 +362,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,

View file

@ -143,8 +143,10 @@ export class MiUser {
})
public avatarDecorations: {
id: string;
angle: number;
flipH: boolean;
angle?: number;
flipH?: boolean;
offsetX?: number;
offsetY?: number;
}[];
@Index()

View file

@ -145,6 +145,7 @@ export const packedRoleSchema = {
userEachUserListsLimit: rolePolicyValue,
canManageAvatarDecorations: rolePolicyValue,
canUseTranslator: rolePolicyValue,
avatarDecorationLimit: rolePolicyValue,
},
},
usersCount: {

View file

@ -681,6 +681,10 @@ export const packedMeDetailedOnlySchema = {
type: 'number',
nullable: false, optional: false,
},
avatarDecorationLimit: {
type: 'number',
nullable: false, optional: false,
},
},
},
//#region secrets

View file

@ -229,7 +229,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: {

View file

@ -14,7 +14,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireModerator: true,
requireAdmin: true,
res: {
type: 'array',

View file

@ -125,7 +125,7 @@ export const meta = {
const muteWords = { type: 'array', items: { oneOf: [
{ type: 'array', items: { type: 'string' } },
{ type: 'string' }
{ type: 'string' },
] } } as const;
export const paramDef = {
@ -137,12 +137,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'],
} },
@ -252,7 +254,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
function validateMuteWordRegex(mutedWords: (string[] | string)[]) {
for (const mutedWord of mutedWords) {
if (typeof mutedWord !== "string") continue;
if (typeof mutedWord !== 'string') continue;
const regexp = mutedWord.match(/^\/(.+)\/(.*)$/);
if (!regexp) throw new ApiError(meta.errors.invalidRegexp);
@ -335,16 +337,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,
}));
}

View file

@ -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