· 6 years ago · Mar 31, 2020, 09:48 AM
1import AWS from 'aws-sdk';
2
3export default class DocumentManager {
4
5 static providers = new Map();
6
7 /**
8 * Get Document Manager Account type and initiate process.
9 *
10 * @param {Object} api Get account Details
11 *
12 * @return
13 */
14 static async initiate(api) {
15
16 const accountCredential = await api.credential.get(api.account.id, 'document-storage');
17
18 const documentProvider = DocumentManager.providers.get(accountCredential.credential.type);
19
20 return new documentProvider(api);
21 }
22
23 async insert(file) {
24
25 const data = {
26 id: id,
27 account_id: this.account.id,
28 name: data.name,
29 url: data.Location,
30 metadata: {size: data.size},
31 service_provider_metadata: {bucket: data.Bucket},
32 type: '',
33 extension: '',
34 created_by: this.user.id,
35 };
36
37 return await this.mysql.query(
38 'INSERT INTO file SET ?',
39 data,
40 'write'
41 );
42 }
43
44 /**
45 * Check document read is exist on server.
46 *
47 * @param {Integer} id file id.
48 *
49 * @return return file details.
50 */
51 async read(id) {
52
53 const [file] = await this.api.mysql.query(
54 `SELECT
55 id,
56 name,
57 metadata,
58 service_provider_metadata
59 FROM
60 file
61 WHERE
62 id = ? AND is_deleted = 0`,
63 [id]
64 );
65
66 if(!file) {
67 throw new Error('Invalid File Id');
68 }
69
70 file.service_provider_metadata = JSON.parse(file.service_provider_metadata);
71
72 return file;
73 }
74
75 async delete(id) {
76
77 const [file] = await this.mysql.query(
78 'SELECT id FROM file WHERE id = ? account_id = ? AND is_deleted = 0',
79 [id, this.account.id]
80 );
81
82 if(!file) {
83 throw new API.Exception(400, 'Invalid File Id.');
84 }
85
86 return await this.mysql.query(
87 'UPDATE file SET is_deleted = 1 WHERE id = ?',
88 [file.id],
89 'write'
90 );
91 }
92}
93
94DocumentManager.providers.set('aws-s3', class extends DocumentManager {
95
96 constructor(api) {
97
98 this.api = api;
99 }
100
101 /**
102 * Get Account credential and set into AWS S3.
103 */
104 async configuration() {
105
106 const accountCredential = await this.api.credential.get(this.api.account.id, 'document-storage');
107
108 return new AWS.S3({
109 accessKeyId: accountCredential.credential.accessKeyId,
110 secretAccessKey: accountCredential.credential.secretAccessKey,
111 signatureVersion: 'v4',
112 });
113 }
114
115 /**
116 * Upload file into AWS S3 bucket.
117 *
118 * @param {String} bucket bucket name.
119 * @param {String} fileName file name.
120 * @param {file} path file path.
121 * @param {String} acl permission.
122 *
123 * @return {Array} return uploaded file location and othrs details.
124 */
125 async upload(bucket, fileName, path, acl = 'public-read') {
126
127 const params = {
128 Bucket: bucket,
129 Key: fileName,
130 Body: path,
131 ACL: acl
132 };
133
134 const configuration = await this.configuration();
135
136 return new Promise((resolve, reject) => {
137
138 configuration.upload(params, (error, response) => {
139
140 if (error) {
141 return reject();
142 }
143
144 resolve(response);
145 });
146 });
147 }
148
149 /**
150 * Read file from S3 bucket using file key and bucket.
151 *
152 * @param {Integer} id file id.
153 *
154 * @return {Object} Return file location.
155 */
156 async read(id) {
157
158 const [file, configuration] = await Promise.all([this.file(id), this.configuration()]);
159
160 const params = {
161 Bucket: file.service_provider_metadata.bucket,
162 Key: file.name,
163 Expires: 30 * 60
164 };
165
166 return new Promise((resolve, reject) => {
167
168 configuration.getSignedUrl('putObject', params, (error, response) => {
169
170 if (error) {
171 return reject(error);
172 }
173
174 resolve(response);
175 });
176 });
177 }
178
179 /**
180 * Delete file from S3 bucket using file key and bucket.
181 *
182 * @param {Integer} id file id.
183 *
184 * @return
185 */
186 async delete(id) {
187
188 const [file, configuration] = await Promise.all([this.file(id), this.configuration()]);
189
190 const params = {
191 Bucket: file.service_provider_metadata.bucket,
192 Key: file.name,
193 };
194
195 return new Promise((resolve, reject) => {
196
197 configuration.deleteObject(params, (error, response) => {
198
199 if (error) {
200 return reject(error);
201 }
202
203 resolve(response);
204 });
205 });
206 }
207});