Refactor drive

This commit is contained in:
syuilo 2019-02-28 15:20:40 +09:00
parent 517084b1fc
commit b5c235f837
No known key found for this signature in database
GPG key ID: BDC4C49D06AB9D69
11 changed files with 47 additions and 116 deletions

View file

@ -1,31 +0,0 @@
import { IDriveFile } from '../models/drive-file';
import config from '../config';
export default function(file: IDriveFile, thumbnail = false): string {
if (file == null) return null;
const isImage = file.contentType && file.contentType.startsWith('image/');
if (file.metadata.withoutChunks) {
if (thumbnail) {
return file.metadata.thumbnailUrl || file.metadata.webpublicUrl || (isImage ? file.metadata.url : null);
} else {
return file.metadata.webpublicUrl || file.metadata.url;
}
} else {
if (thumbnail) {
return `${config.driveUrl}/${file._id}?thumbnail`;
} else {
return `${config.driveUrl}/${file._id}?web`;
}
}
}
export function getOriginalUrl(file: IDriveFile) {
if (file.metadata && file.metadata.url) {
return file.metadata.url;
}
const accessKey = file.metadata ? file.metadata.accessKey : null;
return `${config.driveUrl}/${file._id}${accessKey ? '?original=' + accessKey : ''}`;
}

View file

@ -4,7 +4,6 @@ import { pack as packFolder } from './drive-folder';
import { pack as packUser } from './user';
import monkDb, { nativeDbConn, dbLogger } from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
import getDriveFileUrl, { getOriginalUrl } from '../misc/get-drive-file-url';
const DriveFile = monkDb.get<IDriveFile>('driveFiles.files');
DriveFile.createIndex('md5');
@ -36,26 +35,10 @@ export type IMetadata = {
*/
uri?: string;
/**
* URL for web() or original
* * or
*/
url?: string;
/**
* URL for thumbnail (thumbnailがなければなし)
* * or
*/
url: string;
thumbnailUrl?: string;
/**
* URL for original (web用が生成されてない場合はurlがoriginalを指す)
* * or
*/
webpublicUrl?: string;
accessKey?: string;
src?: string;
deletedAt?: Date;
@ -188,8 +171,8 @@ export const pack = (
_target = Object.assign(_target, _file.metadata);
_target.url = getDriveFileUrl(_file);
_target.thumbnailUrl = getDriveFileUrl(_file, true);
_target.url = _file.metadata.webpublicUrl;
_target.thumbnailUrl = _file.metadata.thumbnailUrl;
_target.isRemote = _file.metadata.isRemote;
if (_target.properties == null) _target.properties = {};
@ -224,7 +207,7 @@ export const pack = (
delete _target._user;
if (opts.self) {
_target.url = getOriginalUrl(_file);
_target.url = _file.metadata.url;
}
resolve(_target);

View file

@ -16,7 +16,6 @@ import { URL } from 'url';
import { resolveNote, extractEmojis } from './note';
import { registerOrFetchInstanceDoc } from '../../../services/register-or-fetch-instance-doc';
import Instance from '../../../models/instance';
import getDriveFileUrl from '../../../misc/get-drive-file-url';
import { IEmoji } from '../../../models/emoji';
import { ITag, extractHashtags } from './tag';
import Following from '../../../models/following';
@ -227,8 +226,8 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<IU
const avatarId = avatar ? avatar._id : null;
const bannerId = banner ? banner._id : null;
const avatarUrl = getDriveFileUrl(avatar, true);
const bannerUrl = getDriveFileUrl(banner, false);
const avatarUrl = avatar.metadata.thumbnailUrl;
const bannerUrl = banner.metadata.webpublicUrl;
const avatarColor = avatar && avatar.metadata.properties.avgColor ? avatar.metadata.properties.avgColor : null;
const bannerColor = banner && avatar.metadata.properties.avgColor ? banner.metadata.properties.avgColor : null;
@ -373,13 +372,13 @@ export async function updatePerson(uri: string, resolver?: Resolver, hint?: obje
if (avatar) {
updates.avatarId = avatar._id;
updates.avatarUrl = getDriveFileUrl(avatar, true);
updates.avatarUrl = avatar.metadata.thumbnailUrl;
updates.avatarColor = avatar.metadata.properties.avgColor ? avatar.metadata.properties.avgColor : null;
}
if (banner) {
updates.bannerId = banner._id;
updates.bannerUrl = getDriveFileUrl(banner, true);
updates.bannerUrl = banner.metadata.webpublicUrl;
updates.bannerColor = banner.metadata.properties.avgColor ? banner.metadata.properties.avgColor : null;
}

View file

@ -1,8 +1,7 @@
import { IDriveFile } from '../../../models/drive-file';
import getDriveFileUrl from '../../../misc/get-drive-file-url';
export default (file: IDriveFile) => ({
type: 'Document',
mediaType: file.contentType,
url: getDriveFileUrl(file)
url: file.metadata.webpublicUrl
});

View file

@ -1,8 +1,7 @@
import { IDriveFile } from '../../../models/drive-file';
import getDriveFileUrl from '../../../misc/get-drive-file-url';
export default (file: IDriveFile) => ({
type: 'Image',
url: getDriveFileUrl(file),
url: file.metadata.webpublicUrl,
sensitive: file.metadata.isSensitive
});

View file

@ -1,9 +1,7 @@
import $ from 'cafy';
import * as mongo from 'mongodb';
import ID, { transform } from '../../../../../misc/cafy-id';
import DriveFile, { pack, IDriveFile } from '../../../../../models/drive-file';
import define from '../../../define';
import config from '../../../../../config';
import { ApiError } from '../../../error';
export const meta = {
@ -73,28 +71,16 @@ export default define(meta, async (ps, user) => {
'metadata.deletedAt': { $exists: false }
});
} else if (ps.url) {
const isInternalStorageUrl = ps.url.startsWith(config.driveUrl);
if (isInternalStorageUrl) {
// Extract file ID from url
// e.g.
// http://misskey.local/files/foo?original=bar --> foo
const fileId = new mongo.ObjectID(ps.url.replace(config.driveUrl, '').replace(/\?(.*)$/, '').replace(/\//g, ''));
file = await DriveFile.findOne({
_id: fileId,
'metadata.deletedAt': { $exists: false }
});
} else {
file = await DriveFile.findOne({
$or: [{
'metadata.url': ps.url
}, {
'metadata.webpublicUrl': ps.url
}, {
'metadata.thumbnailUrl': ps.url
}],
'metadata.deletedAt': { $exists: false }
});
}
file = await DriveFile.findOne({
$or: [{
'metadata.url': ps.url
}, {
'metadata.webpublicUrl': ps.url
}, {
'metadata.thumbnailUrl': ps.url
}],
'metadata.deletedAt': { $exists: false }
});
} else {
throw new ApiError(meta.errors.fileIdOrUrlRequired);
}

View file

@ -6,7 +6,6 @@ import DriveFile from '../../../../models/drive-file';
import acceptAllFollowRequests from '../../../../services/following/requests/accept-all';
import { publishToFollowers } from '../../../../services/i/update';
import define from '../../define';
import getDriveFileUrl from '../../../../misc/get-drive-file-url';
import { parse, parsePlain } from '../../../../mfm/parse';
import extractEmojis from '../../../../misc/extract-emojis';
import extractHashtags from '../../../../misc/extract-hashtags';
@ -195,7 +194,7 @@ export default define(meta, async (ps, user, app) => {
if (avatar.metadata.deletedAt) {
updates.avatarUrl = null;
} else {
updates.avatarUrl = getDriveFileUrl(avatar, true);
updates.avatarUrl = avatar.metadata.thumbnailUrl;
if (avatar.metadata.properties.avgColor) {
updates.avatarColor = avatar.metadata.properties.avgColor;
@ -214,7 +213,7 @@ export default define(meta, async (ps, user, app) => {
if (banner.metadata.deletedAt) {
updates.bannerUrl = null;
} else {
updates.bannerUrl = getDriveFileUrl(banner, false);
updates.bannerUrl = banner.metadata.webpublicUrl;
if (banner.metadata.properties.avgColor) {
updates.bannerColor = banner.metadata.properties.avgColor;
@ -236,7 +235,7 @@ export default define(meta, async (ps, user, app) => {
if (wallpaper.metadata.deletedAt) {
updates.wallpaperUrl = null;
} else {
updates.wallpaperUrl = getDriveFileUrl(wallpaper);
updates.wallpaperUrl = wallpaper.metadata.webpublicUrl;
if (wallpaper.metadata.properties.avgColor) {
updates.wallpaperColor = wallpaper.metadata.properties.avgColor;

View file

@ -33,8 +33,7 @@ router.get('/app-default.jpg', ctx => {
ctx.body = file;
});
router.get('/:id', sendDriveFile);
router.get('/:id/*', sendDriveFile);
router.get('/*', sendDriveFile);
// Register router
app.use(router.routes());

View file

@ -1,6 +1,5 @@
import * as Koa from 'koa';
import * as send from 'koa-send';
import * as mongodb from 'mongodb';
import DriveFile, { getDriveFileBucket } from '../../models/drive-file';
import DriveFileThumbnail, { getDriveFileThumbnailBucket } from '../../models/drive-file-thumbnail';
import DriveFileWebpublic, { getDriveFileWebpublicBucket } from '../../models/drive-file-webpublic';
@ -14,16 +13,18 @@ const commonReadableHandlerGenerator = (ctx: Koa.BaseContext) => (e: Error): voi
};
export default async function(ctx: Koa.BaseContext) {
// Validate id
if (!mongodb.ObjectID.isValid(ctx.params.id)) {
ctx.throw(400, 'incorrect id');
return;
}
const fileId = new mongodb.ObjectID(ctx.params.id);
const url = ctx.href;
// Fetch drive file
const file = await DriveFile.findOne({ _id: fileId });
const file = await DriveFile.findOne({
$or: [{
'metadata.url': url
}, {
'metadata.webpublicUrl': url
}, {
'metadata.thumbnailUrl': url
}],
});
if (file == null) {
ctx.status = 404;
@ -43,21 +44,16 @@ export default async function(ctx: Koa.BaseContext) {
}
const sendRaw = async () => {
if (file.metadata && file.metadata.accessKey && file.metadata.accessKey != ctx.query['original']) {
ctx.status = 403;
return;
}
const bucket = await getDriveFileBucket();
const readable = bucket.openDownloadStream(fileId);
const readable = bucket.openDownloadStream(file._id);
readable.on('error', commonReadableHandlerGenerator(ctx));
ctx.set('Content-Type', file.contentType);
ctx.body = readable;
};
if ('thumbnail' in ctx.query) {
if (file.metadata.thumbnailUrl === url) {
const thumb = await DriveFileThumbnail.findOne({
'metadata.originalId': fileId
'metadata.originalId': file._id
});
if (thumb != null) {
@ -72,9 +68,9 @@ export default async function(ctx: Koa.BaseContext) {
await send(ctx as any, '/dummy.png', { root: assets });
}
}
} else if ('web' in ctx.query) {
} else if (file.metadata.webpublicUrl === url) {
const web = await DriveFileWebpublic.findOne({
'metadata.originalId': fileId
'metadata.originalId': file._id
});
if (web != null) {

View file

@ -2,7 +2,6 @@ import { Feed } from 'feed';
import config from '../../config';
import Note from '../../models/note';
import { IUser } from '../../models/user';
import { getOriginalUrl } from '../../misc/get-drive-file-url';
export default async function(user: IUser) {
const author: Author = {
@ -38,7 +37,7 @@ export default async function(user: IUser) {
} as FeedOptions);
for (const note of notes) {
const file = note._files && note._files.find(file => file.contentType.startsWith('image/'));
const file = note._files ? note._files.find(file => file.contentType.startsWith('image/')) : null;
feed.addItem({
title: `New note by ${author.name}`,
@ -46,7 +45,7 @@ export default async function(user: IUser) {
date: note.createdAt,
description: note.cw,
content: note.text,
image: file && getOriginalUrl(file)
image: file ? file.metadata.webpublicUrl : null
});
}

View file

@ -117,12 +117,15 @@ async function save(path: string, name: string, type: string, hash: string, size
return file;
} else { // use MongoDB GridFS
Object.assign(metadata, {
url: `${config.driveUrl}/${uuid.v4()}`,
webpublicUrl: `${config.driveUrl}/${uuid.v4()}?web`,
thumbnailUrl: `${config.driveUrl}/${uuid.v4()}?thumbnail`,
} as IMetadata);
// #region store original
const originalDst = await getDriveFileBucket();
// web用(Exif削除済み)がある場合はオリジナルにアクセス制限
if (alts.webpublic) metadata.accessKey = uuid.v4();
const originalFile = await storeOriginal(originalDst, name, path, type, metadata);
logger.info(`original stored to ${originalFile._id}`);