aboutsummaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
authorEugene Sokolov <eug-vs@keemail.me>2020-08-12 19:09:54 +0300
committerGitHub <noreply@github.com>2020-08-12 19:09:54 +0300
commit5462174ca076aef53d06b92372141c665c923ea3 (patch)
tree1bbe4629b0a0ee537a21be15c91fd31b243df97d /services
parentc2e16321e679d52ad9d6e08b5cdb785b172ad830 (diff)
parent8f4ae4fd89cab5ba4f9e8d2750bc8589ce997ff1 (diff)
downloadwhich-api-5462174ca076aef53d06b92372141c665c923ea3.tar.gz
Merge pull request #19 from which-ecosystem/s3-reuploads
S3 reuploads
Diffstat (limited to 'services')
-rw-r--r--services/files/files.class.ts69
-rw-r--r--services/polls/polls.hooks.ts4
-rw-r--r--services/users/users.hooks.ts3
3 files changed, 70 insertions, 6 deletions
diff --git a/services/files/files.class.ts b/services/files/files.class.ts
index e2f9df3..f2a0960 100644
--- a/services/files/files.class.ts
+++ b/services/files/files.class.ts
@@ -1,27 +1,86 @@
import { Application } from '@feathersjs/express';
import { Params } from '@feathersjs/feathers';
import { v4 } from 'uuid';
+import axios from 'axios';
+import fs from 'fs';
// Use require to avoid bug
// https://stackoverflow.com/questions/62611373/heroku-crashes-when-importing-aws-sdk
+// TODO: use import statement
+// eslint-disable-next-line
const S3 = require('aws-sdk/clients/s3');
export default class Files {
- app!: Application;
- s3!: any;
- bucket!: string;
+ public app!: Application;
+
+ private s3!: typeof S3;
+
+ private bucket!: string;
async find(params: Params): Promise<string> {
+ const path = this.generateS3Path(params.user?.username);
+ return this.getUploadUrl(path);
+ }
+
+ public isS3url(url: string): boolean {
+ return url.startsWith(`https://${this.bucket}.s3`);
+ }
+
+ public generateS3Path(prefix = '', ext = 'png'): string {
+ const key = v4();
+ const fileName = `${key}.${ext}`;
+ return prefix ? `${prefix}/${fileName}` : fileName;
+ }
+
+ async getUploadUrl(path: string): Promise<string> {
// Return signed upload URL
return this.s3.getSignedUrl('putObject', {
Bucket: this.bucket,
- Key: `${params.user?.username}/${v4()}.png`,
+ Key: path,
ContentType: 'image/*',
- Expires: 300,
+ Expires: 300
});
}
+ async getDownloadUrl(path: string): Promise<string> {
+ return this.getUploadUrl(path).then((url: string) => {
+ const queryIndex = url.indexOf('?');
+ return url.slice(0, queryIndex);
+ });
+ }
+
+ private createTmpDir() {
+ if (!fs.existsSync('tmp')) fs.mkdirSync('tmp');
+ }
+
+ async downloadFile(url: string): Promise<string> {
+ return new Promise((resolve, reject) => {
+ this.createTmpDir();
+ const filePath = `tmp/${v4()}`;
+ const fileStream = fs.createWriteStream(filePath);
+ axios.get(url, { responseType: 'stream' })
+ .then(response => {
+ response.data.pipe(fileStream)
+ .on('error', reject)
+ .on('close', () => resolve(filePath));
+ })
+ .catch(error => reject(error));
+ });
+ }
+
+ async uploadFileToS3(filePath: string, s3Path: string): Promise<string> {
+ const fileStream = fs.createReadStream(filePath);
+ await this.s3.upload({
+ Bucket: this.bucket,
+ Key: s3Path,
+ Body: fileStream,
+ ContentType: 'image/png'
+ }).promise();
+ fs.unlinkSync(filePath);
+ return this.getDownloadUrl(s3Path);
+ }
+
setup(app: Application): void {
this.app = app;
this.s3 = new S3({
diff --git a/services/polls/polls.hooks.ts b/services/polls/polls.hooks.ts
index 35eae29..7a5b1da 100644
--- a/services/polls/polls.hooks.ts
+++ b/services/polls/polls.hooks.ts
@@ -8,6 +8,7 @@ import { PollSchema } from '../../models/polls/poll.schema';
import VoteModel from '../../models/votes/vote.model';
import sortByDate from '../../hooks/sortByDate';
import signAuthority from '../../hooks/signAuthority';
+import fetchImages from '../../hooks/fetchImages';
const convertPoll = async (context: HookContext): Promise<HookContext> => {
@@ -53,7 +54,8 @@ export default {
patch: disallow('external')
},
after: {
- all: convertPoll
+ all: convertPoll,
+ create: fetchImages(['contents.left.url', 'contents.right.url'])
}
};
diff --git a/services/users/users.hooks.ts b/services/users/users.hooks.ts
index 29f1074..ddfc47f 100644
--- a/services/users/users.hooks.ts
+++ b/services/users/users.hooks.ts
@@ -4,6 +4,7 @@ import { discard, disallow } from 'feathers-hooks-common';
import { HookContext } from '@feathersjs/feathers';
import { NotAuthenticated } from '@feathersjs/errors';
import requireAuth from '../../hooks/requireAuth';
+import fetchImages from '../../hooks/fetchImages';
const hashPassword = hooks.hashPassword('password');
@@ -24,6 +25,8 @@ const compareUser = async (context: HookContext): Promise<HookContext> => {
export default {
after: {
all: hooks.protect('password'),
+ create: fetchImages(['avatarUrl']),
+ patch: fetchImages(['avatarUrl']),
get: discard('password') // Protect password from local get's
},
before: {