diff --git a/.config/example.yml b/.config/example.yml index 2e13b6397..2d4d36e8d 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -155,6 +155,9 @@ id: 'aid' # Media Proxy #mediaProxy: https://example.com/proxy +# Proxy remote files (default: false) +#proxyRemoteFiles: true + # Sign to ActivityPub GET request (default: false) #signToActivityPubGet: true diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index e22f50668..5798df5ae 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -320,8 +320,6 @@ disablingTimelinesInfo: "これらのタイムラインを無効化しても、 registration: "登録" enableRegistration: "誰でも新規登録できるようにする" invite: "招待" -proxyRemoteFiles: "リモートのファイルをプロキシする" -proxyRemoteFilesDescription: "この設定を有効にすると、未保存または保存容量超過で削除されたリモートファイルをローカルでプロキシし、サムネイルも生成するようになります。サーバーのストレージには影響しません、" driveCapacityPerLocalAccount: "ローカルユーザーひとりあたりのドライブ容量" driveCapacityPerRemoteAccount: "リモートユーザーひとりあたりのドライブ容量" inMb: "メガバイト単位" diff --git a/migration/1626509500668-fix-remote-file-proxy.ts b/migration/1626509500668-fix-remote-file-proxy.ts new file mode 100644 index 000000000..d9d031acc --- /dev/null +++ b/migration/1626509500668-fix-remote-file-proxy.ts @@ -0,0 +1,21 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class fixRemoteFileProxy1626509500668 implements MigrationInterface { + name = 'fixRemoteFileProxy1626509500668' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "avatarUrl"`); + await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "bannerUrl"`); + await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "avatarBlurhash"`); + await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "bannerBlurhash"`); + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "proxyRemoteFiles"`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "meta" ADD "proxyRemoteFiles" boolean NOT NULL DEFAULT false`); + await queryRunner.query(`ALTER TABLE "user" ADD "bannerBlurhash" character varying(128)`); + await queryRunner.query(`ALTER TABLE "user" ADD "avatarBlurhash" character varying(128)`); + await queryRunner.query(`ALTER TABLE "user" ADD "bannerUrl" character varying(512)`); + await queryRunner.query(`ALTER TABLE "user" ADD "avatarUrl" character varying(512)`); + } +} diff --git a/src/client/pages/instance/files-settings.vue b/src/client/pages/instance/files-settings.vue index 614c7d4db..4f80bf0b4 100644 --- a/src/client/pages/instance/files-settings.vue +++ b/src/client/pages/instance/files-settings.vue @@ -6,11 +6,6 @@ - - {{ $ts.proxyRemoteFiles }} - - - {{ $ts.driveCapacityPerLocalAccount }} @@ -59,7 +54,6 @@ export default defineComponent({ icon: 'fas fa-cloud' }, cacheRemoteFiles: false, - proxyRemoteFiles: false, localDriveCapacityMb: 0, remoteDriveCapacityMb: 0, } @@ -73,14 +67,12 @@ export default defineComponent({ async init() { const meta = await os.api('meta', { detail: true }); this.cacheRemoteFiles = meta.cacheRemoteFiles; - this.proxyRemoteFiles = meta.proxyRemoteFiles; this.localDriveCapacityMb = meta.driveCapacityPerLocalUserMb; this.remoteDriveCapacityMb = meta.driveCapacityPerRemoteUserMb; }, save() { os.apiWithDialog('admin/update-meta', { cacheRemoteFiles: this.cacheRemoteFiles, - proxyRemoteFiles: this.proxyRemoteFiles, localDriveCapacityMb: parseInt(this.localDriveCapacityMb, 10), remoteDriveCapacityMb: parseInt(this.remoteDriveCapacityMb, 10), }).then(() => { diff --git a/src/config/types.ts b/src/config/types.ts index 55beac6f5..525d32c8d 100644 --- a/src/config/types.ts +++ b/src/config/types.ts @@ -60,6 +60,7 @@ export type Source = { }; mediaProxy?: string; + proxyRemoteFiles?: boolean; signToActivityPubGet?: boolean; }; diff --git a/src/models/entities/meta.ts b/src/models/entities/meta.ts index 6428aacdf..e99163703 100644 --- a/src/models/entities/meta.ts +++ b/src/models/entities/meta.ts @@ -131,11 +131,6 @@ export class Meta { }) public cacheRemoteFiles: boolean; - @Column('boolean', { - default: false, - }) - public proxyRemoteFiles: boolean; - @Column({ ...id(), nullable: true, diff --git a/src/models/entities/user.ts b/src/models/entities/user.ts index 65aebd2d1..3e41137a2 100644 --- a/src/models/entities/user.ts +++ b/src/models/entities/user.ts @@ -106,26 +106,6 @@ export class User { }) public tags: string[]; - @Column('varchar', { - length: 512, nullable: true, - }) - public avatarUrl: string | null; - - @Column('varchar', { - length: 512, nullable: true, - }) - public bannerUrl: string | null; - - @Column('varchar', { - length: 128, nullable: true, - }) - public avatarBlurhash: string | null; - - @Column('varchar', { - length: 128, nullable: true, - }) - public bannerBlurhash: string | null; - @Column('boolean', { default: false, comment: 'Whether the User is suspended.' diff --git a/src/models/repositories/drive-file.ts b/src/models/repositories/drive-file.ts index 42a60ff03..f038fb657 100644 --- a/src/models/repositories/drive-file.ts +++ b/src/models/repositories/drive-file.ts @@ -30,7 +30,7 @@ export class DriveFileRepository extends Repository { ); } - public getPublicUrl(file: DriveFile, thumbnail = false, meta?: Meta): string | null { + public getPublicUrl(file: DriveFile, thumbnail = false): string | null { // リモートかつメディアプロキシ if (file.uri != null && file.userHost != null && config.mediaProxy != null) { return appendQuery(config.mediaProxy, query({ @@ -40,7 +40,7 @@ export class DriveFileRepository extends Repository { } // リモートかつ期限切れはローカルプロキシを試みる - if (file.uri != null && file.isLink && meta && meta.proxyRemoteFiles) { + if (file.uri != null && file.isLink && config.proxyRemoteFiles) { const key = thumbnail ? file.thumbnailAccessKey : file.webpublicAccessKey; if (key && !key.match('/')) { // 古いものはここにオブジェクトストレージキーが入ってるので除外 @@ -113,8 +113,6 @@ export class DriveFileRepository extends Repository { const file = typeof src === 'object' ? src : await this.findOne(src); if (file == null) return null; - const meta = await fetchMeta(); - return await awaitAll({ id: file.id, createdAt: file.createdAt.toISOString(), @@ -125,8 +123,8 @@ export class DriveFileRepository extends Repository { isSensitive: file.isSensitive, blurhash: file.blurhash, properties: file.properties, - url: opts.self ? file.url : this.getPublicUrl(file, false, meta), - thumbnailUrl: this.getPublicUrl(file, true, meta), + url: opts.self ? file.url : this.getPublicUrl(file, false), + thumbnailUrl: this.getPublicUrl(file, true), comment: file.comment, folderId: file.folderId, folder: opts.detail && file.folderId ? DriveFolders.pack(file.folderId, { diff --git a/src/models/repositories/user.ts b/src/models/repositories/user.ts index d4bb995ce..dbf22e4ba 100644 --- a/src/models/repositories/user.ts +++ b/src/models/repositories/user.ts @@ -1,7 +1,7 @@ import $ from 'cafy'; import { EntityRepository, Repository, In, Not } from 'typeorm'; import { User, ILocalUser, IRemoteUser } from '@/models/entities/user'; -import { Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles, UserSecurityKeys, UserGroupJoinings, Pages, Announcements, AnnouncementReads, Antennas, AntennaNotes, ChannelFollowings, Instances } from '../index'; +import { Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles, UserSecurityKeys, UserGroupJoinings, Pages, Announcements, AnnouncementReads, Antennas, AntennaNotes, ChannelFollowings, Instances, DriveFiles } from '../index'; import config from '@/config/index'; import { SchemaType } from '@/misc/schema'; import { awaitAll } from '@/prelude/await-all'; @@ -170,7 +170,18 @@ export class UserRepository extends Repository { includeSecrets: false }, options); - const user = typeof src === 'object' ? src : await this.findOneOrFail(src); + let user: User; + + if (typeof src === 'object') { + user = src; + if (src.avatar === undefined && src.avatarId) src.avatar = await DriveFiles.findOne(src.avatarId) || null; + if (src.banner === undefined && src.bannerId) src.banner = await DriveFiles.findOne(src.bannerId) || null; + } else { + user = await this.findOneOrFail(src, { + relations: ['avatar', 'banner'] + }); + } + const meId = me ? me.id : null; const relation = meId && (meId !== user.id) && opts.detail ? await this.getRelation(meId, user.id) : null; @@ -188,8 +199,8 @@ export class UserRepository extends Repository { name: user.name, username: user.username, host: user.host, - avatarUrl: user.avatarUrl ? user.avatarUrl : config.url + '/avatar/' + user.id, - avatarBlurhash: user.avatarBlurhash, + avatarUrl: user.avatar ? DriveFiles.getPublicUrl(user.avatar, true) : config.url + '/avatar/' + user.id, + avatarBlurhash: user.avatar?.blurhash || null, avatarColor: null, // 後方互換性のため isAdmin: user.isAdmin || falsy, isModerator: user.isModerator || falsy, @@ -212,8 +223,8 @@ export class UserRepository extends Repository { createdAt: user.createdAt.toISOString(), updatedAt: user.updatedAt ? user.updatedAt.toISOString() : null, lastFetchedAt: user.lastFetchedAt?.toISOString(), - bannerUrl: user.bannerUrl, - bannerBlurhash: user.bannerBlurhash, + bannerUrl: user.banner ? DriveFiles.getPublicUrl(user.banner, false) : null, + bannerBlurhash: user.banner?.blurhash || null, bannerColor: null, // 後方互換性のため isLocked: user.isLocked, isModerator: user.isModerator || falsy, diff --git a/src/remote/activitypub/models/person.ts b/src/remote/activitypub/models/person.ts index 4823def7c..eaa9fc3a7 100644 --- a/src/remote/activitypub/models/person.ts +++ b/src/remote/activitypub/models/person.ts @@ -231,26 +231,14 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise { set.cacheRemoteFiles = ps.cacheRemoteFiles; } - if (ps.proxyRemoteFiles !== undefined) { - set.proxyRemoteFiles = ps.proxyRemoteFiles; - } - if (ps.enableHcaptcha !== undefined) { set.enableHcaptcha = ps.enableHcaptcha; } diff --git a/src/server/api/endpoints/i/update.ts b/src/server/api/endpoints/i/update.ts index fb7e12760..001a512a2 100644 --- a/src/server/api/endpoints/i/update.ts +++ b/src/server/api/endpoints/i/update.ts @@ -195,12 +195,6 @@ export default define(meta, async (ps, _user, token) => { if (avatar == null || avatar.userId !== user.id) throw new ApiError(meta.errors.noSuchAvatar); if (!avatar.type.startsWith('image/')) throw new ApiError(meta.errors.avatarNotAnImage); - - updates.avatarUrl = DriveFiles.getPublicUrl(avatar, true); - - if (avatar.blurhash) { - updates.avatarBlurhash = avatar.blurhash; - } } if (ps.bannerId) { @@ -208,12 +202,6 @@ export default define(meta, async (ps, _user, token) => { if (banner == null || banner.userId !== user.id) throw new ApiError(meta.errors.noSuchBanner); if (!banner.type.startsWith('image/')) throw new ApiError(meta.errors.bannerNotAnImage); - - updates.bannerUrl = DriveFiles.getPublicUrl(banner, false); - - if (banner.blurhash) { - updates.bannerBlurhash = banner.blurhash; - } } if (ps.pinnedPageId) { diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts index 3f422dff0..74c9a96d2 100644 --- a/src/server/api/endpoints/meta.ts +++ b/src/server/api/endpoints/meta.ts @@ -100,10 +100,6 @@ export const meta = { type: 'boolean' as const, optional: false as const, nullable: false as const }, - proxyRemoteFiles: { - type: 'boolean' as const, - optional: false as const, nullable: false as const - }, enableHcaptcha: { type: 'boolean' as const, optional: false as const, nullable: false as const @@ -522,7 +518,6 @@ export default define(meta, async (ps, me) => { pinnedPages: instance.pinnedPages, pinnedClipId: instance.pinnedClipId, cacheRemoteFiles: instance.cacheRemoteFiles, - proxyRemoteFiles: instance.proxyRemoteFiles, requireSetup: (await Users.count({ host: null, })) === 0,