Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blob #26

Merged
merged 4 commits into from
Nov 15, 2019
Merged

Blob #26

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.env
node_modules/
node_modules/
.vscode/
172 changes: 172 additions & 0 deletions classes/ImageFile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
const axios = require('axios');
const _ = require('lodash')

const GITHUB_ORG_NAME = 'isomerpages'

// validateStatus allows axios to handle a 404 HTTP status without rejecting the promise.
// This is necessary because GitHub returns a 404 status when the file does not exist.
const validateStatus = (status) => {
return (status >= 200 && status < 300) || status === 404
}

class ImageFile {
constructor(accessToken, siteName) {
this.accessToken = accessToken
this.siteName = siteName
this.baseEndpoint = null
this.blobEndpoint = null
this.fileType = null
}

setFileTypeToImage() {
this.fileType = new ImageType()
this.baseEndpoint = `https://api.github.com/repos/${GITHUB_ORG_NAME}/${this.siteName}/contents/${this.fileType.getFolderName()}`
// Endpoint to retrieve files greater than 1MB
this.baseBlobEndpoint = `https://api.github.com/repos/${GITHUB_ORG_NAME}/${this.siteName}/git/blobs`
}



async list() {
try {
const endpoint = `${this.baseEndpoint}`

const resp = await axios.get(endpoint, {
validateStatus: validateStatus,
headers: {
Authorization: `token ${this.accessToken}`,
"Content-Type": "application/json"
}
})

if (resp.status !== 200) return {}

const files = resp.data.map(object => {
const pathNameSplit = object.path.split("/")
const fileName = pathNameSplit[pathNameSplit.length - 1]
if (object.type === 'file') {
return {
path: encodeURIComponent(object.path),
fileName,
sha: object.sha
}
}
})

return _.compact(files)
} catch (err) {
throw err
}
}

async create(fileName, content) {
try {
const endpoint = `${this.baseEndpoint}/${fileName}`

let params = {
"message": `Create file: ${fileName}`,
"content": content,
"branch": "staging",
}

const resp = await axios.put(endpoint, params, {
headers: {
Authorization: `token ${this.accessToken}`,
"Content-Type": "application/json"
}
})

return { sha: resp.data.content.sha }
} catch (err) {
throw err
}
}

async read(fileName) {
try {
/**
* Images that are bigger than 1 MB needs to be retrieved
* via Github Blob API. The content can only be retrieved through
* the `sha` of the file.
* The code below takes the `fileName`,
* lists all the files in the image directory
* and filters it down to get the sha of the file
*/
const images = await this.list()
const imageSha = images.filter(image => image.fileName === fileName)[0].sha

const blobEndpoint = `${this.baseBlobEndpoint}/${imageSha}`

const resp = await axios.get(blobEndpoint, {
validateStatus: validateStatus,
headers: {
Authorization: `token ${this.accessToken}`,
}
})

if (resp.status === 404) throw new Error ('Page does not exist')

const { content, sha } = resp.data

return { content, sha }
} catch (err) {
throw err
}
}

async update(fileName, content, sha) {
try {
const endpoint = `${this.baseEndpoint}/${fileName}`

let params = {
"message": `Update file: ${fileName}`,
"content": content,
"branch": "staging",
"sha": sha
}

const resp = await axios.put(endpoint, params, {
headers: {
Authorization: `token ${this.accessToken}`,
"Content-Type": "application/json"
}
})

return { newSha: resp.data.commit.sha }
} catch (err) {
throw err
}
}

async delete (fileName, sha) {
try {
const endpoint = `${this.baseEndpoint}/${fileName}`

let params = {
"message": `Delete file: ${fileName}`,
"branch": "staging",
"sha": sha
}

await axios.delete(endpoint, {
data: params,
headers: {
Authorization: `token ${this.accessToken}`,
"Content-Type": "application/json"
}
})
} catch (err) {
throw err
}
}
}

class ImageType {
constructor() {
this.folderName = 'images'
}
getFolderName() {
return this.folderName
}
}
module.exports = { ImageFile }
8 changes: 4 additions & 4 deletions routes/images.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const jwtUtils = require('../utils/jwt-utils')

// Import classes
const { File, ImageType } = require('../classes/File.js')
const { ImageFile } = require('../classes/ImageFile.js')

// List images
router.get('/:siteName/images', async function(req, res, next) {
Expand Down Expand Up @@ -54,10 +55,9 @@ router.get('/:siteName/images/:imageName', async function(req, res, next) {

const { siteName, imageName } = req.params

const IsomerFile = new File(access_token, siteName)
const imageType = new ImageType()
IsomerFile.setFileType(imageType)
const { sha, content } = await IsomerFile.read(imageName)
const IsomerImageFile = new ImageFile(access_token, siteName)
IsomerImageFile.setFileTypeToImage()
const { sha, content } = await IsomerImageFile.read(imageName)

// TO-DO:
// Validate content
Expand Down
4 changes: 2 additions & 2 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const menuRouter = require('./routes/menus')
const app = express();

app.use(logger('dev'));
app.use(express.json());
app.use(express.json({ limit: '5mb'}));
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
Expand Down Expand Up @@ -62,7 +62,7 @@ app.use(function(err, req, res, next) {

// render the error page
res.status(err.status || 500);
res.render('error');
res.json({ error: err });
});

module.exports = app;