feat: AWS S3 + Digitalocean Spaces storage modules (#1015)

* Provide basic implementation of AWS S3 storage module

* Abstract S3 Compatible Storage Module logic

* Refactor `getFileExtension()` into the `page` object

* Add implementation for Digitalocean storage module

* Remove accidental `async`/`await` in S3 Storage Module

* Remove argument from the call to `page.getFileExtension()`

https://github.com/Requarks/wiki/pull/1015#discussion_r321990073
This commit is contained in:
Andrew Sim
2019-09-09 02:11:25 +01:00
committed by Nicolas Giard
parent 3ab7bcf8ea
commit 5202eadebb
8 changed files with 132 additions and 101 deletions

View File

@@ -0,0 +1,64 @@
const S3 = require('aws-sdk/clients/s3')
/* global WIKI */
/**
* Deduce the file path given the `page` object and the object's key to the page's path.
*/
const getFilePath = (page, pathKey) => {
const fileName = `${page[pathKey]}.${page.getFileExtension()}`
const withLocaleCode = WIKI.config.lang.namespacing && WIKI.config.lang.code !== page.localeCode
return withLocaleCode ? `${page.localeCode}/${fileName}` : fileName
}
/**
* Can be used with S3 compatible storage.
*/
module.exports = class S3CompatibleStorage {
constructor(storageName) {
this.storageName = storageName
}
async activated() {
// not used
}
async deactivated() {
// not used
}
async init() {
WIKI.logger.info(`(STORAGE/${this.storageName}) Initializing...`)
const { accessKeyId, secretAccessKey, region, bucket, endpoint } = this.config
this.s3 = new S3({
accessKeyId,
secretAccessKey,
region,
endpoint,
params: { Bucket: bucket },
apiVersions: '2006-03-01'
})
// determine if a bucket exists and you have permission to access it
await this.s3.headBucket().promise()
WIKI.logger.info(`(STORAGE/${this.storageName}) Initialization completed.`)
}
async created(page) {
WIKI.logger.info(`(STORAGE/${this.storageName}) Creating file ${page.path}...`)
const filePath = getFilePath(page, 'path')
await this.s3.putObject({ Key: filePath, Body: page.injectMetadata() }).promise()
}
async updated(page) {
WIKI.logger.info(`(STORAGE/${this.storageName}) Updating file ${page.path}...`)
const filePath = getFilePath(page, 'path')
await this.s3.putObject({ Key: filePath, Body: page.injectMetadata() }).promise()
}
async deleted(page) {
WIKI.logger.info(`(STORAGE/${this.storageName}) Deleting file ${page.path}...`)
const filePath = getFilePath(page, 'path')
await this.s3.deleteObject({ Key: filePath }).promise()
}
async renamed(page) {
WIKI.logger.info(`(STORAGE/${this.storageName}) Renaming file ${page.sourcePath} to ${page.destinationPath}...`)
const sourceFilePath = getFilePath(page, 'sourcePath')
const destinationFilePath = getFilePath(page, 'destinationPath')
await this.s3.copyObject({ CopySource: sourceFilePath, Key: destinationFilePath }).promise()
await this.s3.deleteObject({ Key: sourceFilePath }).promise()
}
}

View File

@@ -1,11 +1,32 @@
key: s3
title: Amazon S3
description: Amazon S3 is a cloud computing web service offered by Amazon Web Services which provides object storage.
author: requarks.io
author: andrewsim
logo: https://static.requarks.io/logo/aws-s3.svg
website: https://aws.amazon.com/s3/
isAvailable: true
supportedModes:
- push
defaultMode: push
schedule: false
props:
accessKeyId: String
accessSecret: String
region: String
bucket: String
region:
type: String
title: Region
hint: The AWS datacenter region where the bucket will be created.
order: 1
bucket:
type: String
title: Unique bucket name
hint: The unique bucket name to create (e.g. wiki-johndoe).
order: 2
accessKeyId:
type: String
title: Access Key ID
hint: The Access Key.
order: 3
secretAccessKey:
type: String
title: Secret Access Key
hint: The Secret Access Key for the Access Key ID you created above.
order: 4

View File

@@ -1,23 +1,3 @@
module.exports = {
async activated() {
const S3CompatibleStorage = require('./common')
},
async deactivated() {
},
async init() {
},
async created() {
},
async updated() {
},
async deleted() {
},
async renamed() {
}
}
module.exports = new S3CompatibleStorage('S3')