Merge branch 'develop' into complete-emoji-after-last-colon
This commit is contained in:
commit
19751a7dcb
|
@ -5,9 +5,11 @@
|
|||
|
||||
### Client
|
||||
- Enhance: Unicode絵文字をslugから入力する際に`:ok:`のように最後の`:`を入力したあとにUnicode絵文字に変換できるように
|
||||
- Fix: ログアウトした際に処理が終了しない問題を修正
|
||||
- Fix: 自動バックアップが設定されている環境でログアウト直前に設定をバックアップするように
|
||||
|
||||
### Server
|
||||
-
|
||||
- Fix: システムアカウントの名前がサーバー名と同期されない問題を修正
|
||||
|
||||
|
||||
## 2025.4.0
|
||||
|
|
|
@ -3934,6 +3934,10 @@ export interface Locale extends ILocale {
|
|||
* ログアウトしますか?
|
||||
*/
|
||||
"logoutConfirm": string;
|
||||
/**
|
||||
* ログアウトするとクライアントの設定情報がブラウザから消去されます。再ログイン時に設定情報を復元できるようにするためには、設定の自動バックアップを有効にしてください。
|
||||
*/
|
||||
"logoutWillClearClientData": string;
|
||||
/**
|
||||
* 最終利用日時
|
||||
*/
|
||||
|
|
|
@ -979,6 +979,7 @@ document: "ドキュメント"
|
|||
numberOfPageCache: "ページキャッシュ数"
|
||||
numberOfPageCacheDescription: "多くすると利便性が向上しますが、負荷とメモリ使用量が増えます。"
|
||||
logoutConfirm: "ログアウトしますか?"
|
||||
logoutWillClearClientData: "ログアウトするとクライアントの設定情報がブラウザから消去されます。再ログイン時に設定情報を復元できるようにするためには、設定の自動バックアップを有効にしてください。"
|
||||
lastActiveDate: "最終利用日時"
|
||||
statusbar: "ステータスバー"
|
||||
pleaseSelect: "選択してください"
|
||||
|
|
|
@ -37,17 +37,17 @@
|
|||
},
|
||||
"optionalDependencies": {
|
||||
"@swc/core-android-arm64": "1.3.11",
|
||||
"@swc/core-darwin-arm64": "1.11.11",
|
||||
"@swc/core-darwin-x64": "1.11.11",
|
||||
"@swc/core-darwin-arm64": "1.11.18",
|
||||
"@swc/core-darwin-x64": "1.11.18",
|
||||
"@swc/core-freebsd-x64": "1.3.11",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.11.11",
|
||||
"@swc/core-linux-arm64-gnu": "1.11.11",
|
||||
"@swc/core-linux-arm64-musl": "1.11.11",
|
||||
"@swc/core-linux-x64-gnu": "1.11.11",
|
||||
"@swc/core-linux-x64-musl": "1.11.11",
|
||||
"@swc/core-win32-arm64-msvc": "1.11.11",
|
||||
"@swc/core-win32-ia32-msvc": "1.11.11",
|
||||
"@swc/core-win32-x64-msvc": "1.11.11",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.11.18",
|
||||
"@swc/core-linux-arm64-gnu": "1.11.18",
|
||||
"@swc/core-linux-arm64-musl": "1.11.18",
|
||||
"@swc/core-linux-x64-gnu": "1.11.18",
|
||||
"@swc/core-linux-x64-musl": "1.11.18",
|
||||
"@swc/core-win32-arm64-msvc": "1.11.18",
|
||||
"@swc/core-win32-ia32-msvc": "1.11.18",
|
||||
"@swc/core-win32-x64-msvc": "1.11.18",
|
||||
"@tensorflow/tfjs": "4.22.0",
|
||||
"@tensorflow/tfjs-node": "4.22.0",
|
||||
"bufferutil": "4.0.9",
|
||||
|
@ -67,8 +67,8 @@
|
|||
"utf-8-validate": "6.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "3.772.0",
|
||||
"@aws-sdk/lib-storage": "3.772.0",
|
||||
"@aws-sdk/client-s3": "3.782.0",
|
||||
"@aws-sdk/lib-storage": "3.782.0",
|
||||
"@discordapp/twemoji": "15.1.0",
|
||||
"@fastify/accepts": "5.0.2",
|
||||
"@fastify/cookie": "11.0.2",
|
||||
|
@ -78,12 +78,12 @@
|
|||
"@fastify/multipart": "9.0.3",
|
||||
"@fastify/static": "8.1.1",
|
||||
"@fastify/view": "10.0.2",
|
||||
"@misskey-dev/sharp-read-bmp": "1.2.0",
|
||||
"@misskey-dev/sharp-read-bmp": "1.3.0",
|
||||
"@misskey-dev/summaly": "5.2.0",
|
||||
"@napi-rs/canvas": "0.1.68",
|
||||
"@nestjs/common": "11.0.12",
|
||||
"@nestjs/core": "11.0.12",
|
||||
"@nestjs/testing": "11.0.12",
|
||||
"@napi-rs/canvas": "0.1.69",
|
||||
"@nestjs/common": "11.0.16",
|
||||
"@nestjs/core": "11.0.15",
|
||||
"@nestjs/testing": "11.0.15",
|
||||
"@peertube/http-signature": "1.7.0",
|
||||
"@sentry/node": "8.55.0",
|
||||
"@sentry/profiling-node": "8.55.0",
|
||||
|
@ -91,7 +91,7 @@
|
|||
"@sinonjs/fake-timers": "11.3.1",
|
||||
"@smithy/node-http-handler": "2.5.0",
|
||||
"@swc/cli": "0.6.0",
|
||||
"@swc/core": "1.11.11",
|
||||
"@swc/core": "1.11.18",
|
||||
"@twemoji/parser": "15.1.1",
|
||||
"accepts": "1.3.8",
|
||||
"ajv": "8.17.1",
|
||||
|
@ -100,7 +100,7 @@
|
|||
"bcryptjs": "2.4.3",
|
||||
"blurhash": "2.0.5",
|
||||
"body-parser": "1.20.3",
|
||||
"bullmq": "5.44.1",
|
||||
"bullmq": "5.48.1",
|
||||
"cacheable-lookup": "7.0.0",
|
||||
"cbor": "9.0.2",
|
||||
"chalk": "5.4.1",
|
||||
|
@ -111,13 +111,13 @@
|
|||
"content-disposition": "0.5.4",
|
||||
"date-fns": "2.30.0",
|
||||
"deep-email-validator": "0.1.21",
|
||||
"fastify": "5.2.1",
|
||||
"fastify": "5.2.2",
|
||||
"fastify-raw-body": "5.0.0",
|
||||
"feed": "4.2.2",
|
||||
"file-type": "19.6.0",
|
||||
"fluent-ffmpeg": "2.1.3",
|
||||
"form-data": "4.0.2",
|
||||
"got": "14.4.6",
|
||||
"got": "14.4.7",
|
||||
"happy-dom": "16.8.1",
|
||||
"hpagent": "1.2.0",
|
||||
"htmlescape": "1.1.1",
|
||||
|
@ -148,7 +148,7 @@
|
|||
"oauth2orize": "1.12.0",
|
||||
"oauth2orize-pkce": "0.1.2",
|
||||
"os-utils": "0.0.14",
|
||||
"otpauth": "9.3.6",
|
||||
"otpauth": "9.4.0",
|
||||
"parse5": "7.2.1",
|
||||
"pg": "8.14.1",
|
||||
"pkce-challenge": "4.1.0",
|
||||
|
@ -166,17 +166,17 @@
|
|||
"rxjs": "7.8.2",
|
||||
"sanitize-html": "2.15.0",
|
||||
"secure-json-parse": "3.0.2",
|
||||
"sharp": "0.33.5",
|
||||
"sharp": "0.34.1",
|
||||
"slacc": "0.0.10",
|
||||
"strict-event-emitter-types": "2.0.0",
|
||||
"stringz": "2.1.0",
|
||||
"systeminformation": "5.25.11",
|
||||
"tinycolor2": "1.6.0",
|
||||
"tmp": "0.2.3",
|
||||
"tsc-alias": "1.8.11",
|
||||
"tsc-alias": "1.8.15",
|
||||
"tsconfig-paths": "4.2.0",
|
||||
"typeorm": "0.3.21",
|
||||
"typescript": "5.8.2",
|
||||
"typeorm": "0.3.22",
|
||||
"typescript": "5.8.3",
|
||||
"ulid": "2.4.0",
|
||||
"vary": "1.1.2",
|
||||
"web-push": "3.6.7",
|
||||
|
@ -186,7 +186,7 @@
|
|||
"devDependencies": {
|
||||
"@jest/globals": "29.7.0",
|
||||
"@nestjs/platform-express": "10.4.15",
|
||||
"@sentry/vue": "9.8.0",
|
||||
"@sentry/vue": "9.12.0",
|
||||
"@simplewebauthn/types": "12.0.0",
|
||||
"@swc/jest": "0.2.37",
|
||||
"@types/accepts": "1.3.7",
|
||||
|
@ -205,7 +205,7 @@
|
|||
"@types/jsrsasign": "10.5.15",
|
||||
"@types/mime-types": "2.1.4",
|
||||
"@types/ms": "0.7.34",
|
||||
"@types/node": "22.13.10",
|
||||
"@types/node": "22.14.0",
|
||||
"@types/nodemailer": "6.4.17",
|
||||
"@types/oauth": "0.9.6",
|
||||
"@types/oauth2orize": "1.11.5",
|
||||
|
@ -216,17 +216,17 @@
|
|||
"@types/random-seed": "0.3.5",
|
||||
"@types/ratelimiter": "3.4.6",
|
||||
"@types/rename": "1.0.7",
|
||||
"@types/sanitize-html": "2.13.0",
|
||||
"@types/semver": "7.5.8",
|
||||
"@types/sanitize-html": "2.15.0",
|
||||
"@types/semver": "7.7.0",
|
||||
"@types/simple-oauth2": "5.0.7",
|
||||
"@types/sinonjs__fake-timers": "8.1.5",
|
||||
"@types/tinycolor2": "1.4.6",
|
||||
"@types/tmp": "0.2.6",
|
||||
"@types/vary": "1.1.3",
|
||||
"@types/web-push": "3.6.4",
|
||||
"@types/ws": "8.18.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.27.0",
|
||||
"@typescript-eslint/parser": "8.27.0",
|
||||
"@types/ws": "8.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.29.1",
|
||||
"@typescript-eslint/parser": "8.29.1",
|
||||
"aws-sdk-client-mock": "4.1.0",
|
||||
"cross-env": "7.0.3",
|
||||
"eslint-plugin-import": "2.31.0",
|
||||
|
|
|
@ -5,11 +5,14 @@
|
|||
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import type { OnApplicationShutdown } from '@nestjs/common';
|
||||
import { DataSource, IsNull } from 'typeorm';
|
||||
import * as Redis from 'ioredis';
|
||||
import bcrypt from 'bcryptjs';
|
||||
import { MiLocalUser, MiUser } from '@/models/User.js';
|
||||
import { MiSystemAccount, MiUsedUsername, MiUserKeypair, MiUserProfile, type UsersRepository, type SystemAccountsRepository } from '@/models/_.js';
|
||||
import type { MiMeta, UserProfilesRepository } from '@/models/_.js';
|
||||
import type { GlobalEvents } from '@/core/GlobalEventService.js';
|
||||
import { MemoryKVCache } from '@/misc/cache.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
@ -20,10 +23,13 @@ import { genRsaKeyPair } from '@/misc/gen-key-pair.js';
|
|||
export const SYSTEM_ACCOUNT_TYPES = ['actor', 'relay', 'proxy'] as const;
|
||||
|
||||
@Injectable()
|
||||
export class SystemAccountService {
|
||||
export class SystemAccountService implements OnApplicationShutdown {
|
||||
private cache: MemoryKVCache<MiLocalUser>;
|
||||
|
||||
constructor(
|
||||
@Inject(DI.redisForSub)
|
||||
private redisForSub: Redis.Redis,
|
||||
|
||||
@Inject(DI.db)
|
||||
private db: DataSource,
|
||||
|
||||
|
@ -42,6 +48,31 @@ export class SystemAccountService {
|
|||
private idService: IdService,
|
||||
) {
|
||||
this.cache = new MemoryKVCache<MiLocalUser>(1000 * 60 * 10); // 10m
|
||||
|
||||
this.redisForSub.on('message', this.onMessage);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
private async onMessage(_: string, data: string): Promise<void> {
|
||||
const obj = JSON.parse(data);
|
||||
|
||||
if (obj.channel === 'internal') {
|
||||
const { type, body } = obj.message as GlobalEvents['internal']['payload'];
|
||||
switch (type) {
|
||||
case 'metaUpdated': {
|
||||
if (body.before != null && body.before.name !== body.after.name) {
|
||||
for (const account of SYSTEM_ACCOUNT_TYPES) {
|
||||
await this.updateCorrespondingUserProfile(account, {
|
||||
name: body.after.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@bindThis
|
||||
|
@ -145,7 +176,7 @@ export class SystemAccountService {
|
|||
|
||||
@bindThis
|
||||
public async updateCorrespondingUserProfile(type: typeof SYSTEM_ACCOUNT_TYPES[number], extra: {
|
||||
name?: string;
|
||||
name?: string | null;
|
||||
description?: MiUserProfile['description'];
|
||||
}): Promise<MiLocalUser> {
|
||||
const user = await this.fetch(type);
|
||||
|
@ -169,4 +200,15 @@ export class SystemAccountService {
|
|||
|
||||
return updated;
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public dispose(): void {
|
||||
this.redisForSub.off('message', this.onMessage);
|
||||
this.cache.dispose();
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public onApplicationShutdown(signal?: string): void {
|
||||
this.dispose();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -177,7 +177,8 @@ const menuDef = computed<SuperMenuDef[]>(() => [{
|
|||
action: async () => {
|
||||
const { canceled } = await os.confirm({
|
||||
type: 'warning',
|
||||
text: i18n.ts.logoutConfirm,
|
||||
title: i18n.ts.logoutConfirm,
|
||||
text: i18n.ts.logoutWillClearClientData,
|
||||
});
|
||||
if (canceled) return;
|
||||
signout();
|
||||
|
|
|
@ -4,28 +4,48 @@
|
|||
*/
|
||||
|
||||
import { apiUrl } from '@@/js/config.js';
|
||||
import { defaultMemoryStorage } from '@/memory-storage';
|
||||
import { cloudBackup } from '@/preferences/utility.js';
|
||||
import { store } from '@/store.js';
|
||||
import { waiting } from '@/os.js';
|
||||
import { unisonReload, reloadChannel } from '@/utility/unison-reload.js';
|
||||
import { unisonReload } from '@/utility/unison-reload.js';
|
||||
import { clear } from '@/utility/idb-proxy.js';
|
||||
import { $i } from '@/i.js';
|
||||
|
||||
export async function signout() {
|
||||
if (!$i) return;
|
||||
|
||||
// TODO: preferの自動バックアップがオンの場合、いろいろ消す前に強制バックアップ
|
||||
|
||||
waiting();
|
||||
|
||||
localStorage.clear();
|
||||
defaultMemoryStorage.clear();
|
||||
if (store.s.enablePreferencesAutoCloudBackup) {
|
||||
await cloudBackup();
|
||||
}
|
||||
|
||||
const idbPromises = ['MisskeyClient', 'keyval-store'].map((name, i, arr) => new Promise<void>((res, rej) => {
|
||||
localStorage.clear();
|
||||
|
||||
const idbAbortController = new AbortController();
|
||||
const timeout = window.setTimeout(() => idbAbortController.abort(), 5000);
|
||||
|
||||
const idbPromises = ['MisskeyClient'].map((name, i, arr) => new Promise<void>((res, rej) => {
|
||||
const delidb = indexedDB.deleteDatabase(name);
|
||||
delidb.onsuccess = () => res();
|
||||
delidb.onerror = e => rej(e);
|
||||
delidb.onblocked = () => idbAbortController.signal.aborted && rej(new Error('Operation aborted'));
|
||||
}));
|
||||
|
||||
await Promise.all(idbPromises);
|
||||
try {
|
||||
await Promise.race([
|
||||
Promise.all([
|
||||
...idbPromises,
|
||||
// idb keyval-storeはidb-keyvalライブラリによる別管理
|
||||
clear(),
|
||||
]),
|
||||
new Promise((_, rej) => idbAbortController.signal.addEventListener('abort', () => rej(new Error('Operation timed out')))),
|
||||
]);
|
||||
} catch {
|
||||
// nothing
|
||||
} finally {
|
||||
window.clearTimeout(timeout);
|
||||
}
|
||||
|
||||
//#region Remove service worker registration
|
||||
try {
|
||||
|
@ -50,7 +70,9 @@ export async function signout() {
|
|||
.then(registrations => {
|
||||
return Promise.all(registrations.map(registration => registration.unregister()));
|
||||
});
|
||||
} catch (err) {}
|
||||
} catch {
|
||||
// nothing
|
||||
}
|
||||
//#endregion
|
||||
|
||||
unisonReload('/');
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
get as iget,
|
||||
set as iset,
|
||||
del as idel,
|
||||
clear as iclear,
|
||||
} from 'idb-keyval';
|
||||
import { miLocalStorage } from '@/local-storage.js';
|
||||
|
||||
|
@ -51,3 +52,7 @@ export async function del(key: string) {
|
|||
if (idbAvailable) return idel(key);
|
||||
return miLocalStorage.removeItem(`${PREFIX}${key}`);
|
||||
}
|
||||
|
||||
export async function clear() {
|
||||
if (idbAvailable) return iclear();
|
||||
}
|
||||
|
|
2152
pnpm-lock.yaml
2152
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue