summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app.js2
-rw-r--r--lib/response.js135
-rw-r--r--package.json1
-rw-r--r--public/js/index.js5
-rw-r--r--public/views/header.ejs4
5 files changed, 145 insertions, 2 deletions
diff --git a/app.js b/app.js
index 5202ab57..fbaba1f1 100644
--- a/app.js
+++ b/app.js
@@ -244,6 +244,8 @@ app.get('/auth/github/callback',
function (req, res) {
res.redirect('/');
});
+//github callback actions
+app.get('/auth/github/callback/:noteId/:action', response.githubActions);
//dropbox auth
app.get('/auth/dropbox',
passport.authenticate('dropbox-oauth2'),
diff --git a/lib/response.js b/lib/response.js
index e656d550..daf5fb11 100644
--- a/lib/response.js
+++ b/lib/response.js
@@ -9,6 +9,8 @@ var LZString = require('lz-string');
var S = require('string');
var shortId = require('shortid');
var metaMarked = require('meta-marked');
+var querystring = require('querystring');
+var request = require('request');
//core
var config = require("../config.js");
@@ -56,7 +58,8 @@ var response = {
showPublishSlide: showPublishSlide,
showIndex: showIndex,
noteActions: noteActions,
- publishNoteActions: publishNoteActions
+ publishNoteActions: publishNoteActions,
+ githubActions: githubActions
};
function responseError(res, code, detail, msg) {
@@ -362,6 +365,28 @@ function actionPDF(req, res, noteId) {
});
}
+function actionGist(req, res, noteId) {
+ db.readFromDB(noteId, function (err, data) {
+ if (err) {
+ return response.errorNotFound(res);
+ }
+ var owner = data.rows[0].owner;
+ Note.findOrNewNote(noteId, owner, function (err, note) {
+ if (err) {
+ return response.errorNotFound(res);
+ }
+ var data = {
+ client_id: config.github.clientID,
+ redirect_uri: config.getserverurl() + '/auth/github/callback/' + LZString.compressToBase64(noteId) + '/gist',
+ scope: "gist",
+ state: shortId.generate()
+ };
+ var query = querystring.stringify(data);
+ res.redirect("https://github.com/login/oauth/authorize?" + query);
+ });
+ });
+}
+
function noteActions(req, res, next) {
var noteId = req.params.noteId;
if (noteId != config.featuresnotename) {
@@ -402,6 +427,9 @@ function noteActions(req, res, next) {
case "pdf":
actionPDF(req, res, noteId);
break;
+ case "gist":
+ actionGist(req, res, noteId);
+ break;
default:
if (noteId != config.featuresnotename)
res.redirect('/' + LZString.compressToBase64(noteId));
@@ -444,6 +472,111 @@ function publishNoteActions(req, res, next) {
}
}
+function githubActions(req, res, next) {
+ var noteId = req.params.noteId;
+ if (noteId != config.featuresnotename) {
+ if (!Note.checkNoteIdValid(noteId)) {
+ return response.errorNotFound(res);
+ }
+ noteId = LZString.decompressFromBase64(noteId);
+ if (!noteId) {
+ return response.errorNotFound(res);
+ }
+ }
+ Note.findNote(noteId, function (err, note) {
+ if (err || !note) {
+ return response.errorNotFound(res);
+ }
+ db.readFromDB(note.id, function (err, data) {
+ if (err) {
+ return response.errorNotFound(res);
+ }
+ var notedata = data.rows[0];
+ //check view permission
+ if (note.permission == 'private') {
+ if (!req.isAuthenticated() || notedata.owner != req.user._id)
+ return response.errorForbidden(res);
+ }
+ var action = req.params.action;
+ switch (action) {
+ case "gist":
+ githubActionGist(req, res, noteId);
+ break;
+ default:
+ if (noteId != config.featuresnotename)
+ res.redirect('/' + LZString.compressToBase64(noteId));
+ else
+ res.redirect('/' + noteId);
+ break;
+ }
+ });
+ });
+}
+
+function githubActionGist(req, res, noteId) {
+ db.readFromDB(noteId, function (err, data) {
+ if (err) {
+ return response.errorNotFound(res);
+ }
+ var notedata = data.rows[0];
+ var code = req.query.code;
+ var state = req.query.state;
+ if (!code || !state) {
+ return response.errorForbidden(res);
+ } else {
+ var data = {
+ client_id: config.github.clientID,
+ client_secret: config.github.clientSecret,
+ code: code,
+ state: state
+ }
+ var auth_url = 'https://github.com/login/oauth/access_token';
+ request({
+ url: auth_url,
+ method: "POST",
+ json: data
+ }, function (error, httpResponse, body) {
+ if (!error && httpResponse.statusCode == 200) {
+ var access_token = body.access_token;
+ if (access_token) {
+ var content = LZString.decompressFromBase64(notedata.content);
+ var title = notedata.title;
+ var decodedTitle = LZString.decompressFromBase64(title);
+ if (decodedTitle) title = decodedTitle;
+ var filename = title.replace('/', ' ') + '.md';
+ var gist = {
+ "files": {}
+ };
+ gist.files[filename] = {
+ "content": content
+ };
+ var gist_url = "https://api.github.com/gists";
+ request({
+ url: gist_url,
+ headers: {
+ 'User-Agent': 'HackMD',
+ 'Authorization': 'token ' + access_token
+ },
+ method: "POST",
+ json: gist
+ }, function (error, httpResponse, body) {
+ if (!error && httpResponse.statusCode == 201) {
+ res.redirect(body.html_url);
+ } else {
+ return response.errorForbidden(res);
+ }
+ });
+ } else {
+ return response.errorForbidden(res);
+ }
+ } else {
+ return response.errorForbidden(res);
+ }
+ })
+ }
+ });
+}
+
function showPublishSlide(req, res, next) {
var shortid = req.params.shortid;
if (shortId.isValid(shortid)) {
diff --git a/package.json b/package.json
index ba415315..d7fc7c97 100644
--- a/package.json
+++ b/package.json
@@ -42,6 +42,7 @@
"passport.socketio": "^3.6.1",
"pg": "4.x",
"randomcolor": "^0.4.3",
+ "request": "^2.69.0",
"shortid": "2.2.4",
"socket.io": "1.4.4",
"string": "^3.3.1",
diff --git a/public/js/index.js b/public/js/index.js
index bc3ee793..f4b6904e 100644
--- a/public/js/index.js
+++ b/public/js/index.js
@@ -311,7 +311,8 @@ var ui = {
html: $(".ui-download-html")
},
export: {
- dropbox: $(".ui-save-dropbox")
+ dropbox: $(".ui-save-dropbox"),
+ gist: $(".ui-save-gist")
},
import: {
dropbox: $(".ui-import-dropbox"),
@@ -857,6 +858,8 @@ ui.toolbar.export.dropbox.click(function () {
};
Dropbox.save(options);
});
+//export to gist
+ui.toolbar.export.gist.attr("href", url + "/gist");
//import from dropbox
ui.toolbar.import.dropbox.click(function () {
var options = {
diff --git a/public/views/header.ejs b/public/views/header.ejs
index c98202c0..4e3a9938 100644
--- a/public/views/header.ejs
+++ b/public/views/header.ejs
@@ -36,6 +36,8 @@
<li class="dropdown-header">Export</li>
<li role="presentation"><a role="menuitem" class="ui-save-dropbox" tabindex="-1" href="#" target="_self"><i class="fa fa-dropbox fa-fw"></i> Dropbox</a>
</li>
+ <li role="presentation"><a role="menuitem" class="ui-save-gist" tabindex="-1" href="#" target="_blank"><i class="fa fa-github fa-fw"></i> Gist</a>
+ </li>
<li class="divider"></li>
<li class="dropdown-header">Import</li>
<li role="presentation"><a role="menuitem" class="ui-import-dropbox" tabindex="-1" href="#" target="_self"><i class="fa fa-dropbox fa-fw"></i> Dropbox</a>
@@ -111,6 +113,8 @@
<li class="dropdown-header">Export</li>
<li role="presentation"><a role="menuitem" class="ui-save-dropbox" tabindex="-1" href="#" target="_self"><i class="fa fa-dropbox fa-fw"></i> Dropbox</a>
</li>
+ <li role="presentation"><a role="menuitem" class="ui-save-gist" tabindex="-1" href="#" target="_blank"><i class="fa fa-github fa-fw"></i> Gist</a>
+ </li>
<li class="divider"></li>
<li class="dropdown-header">Import</li>
<li role="presentation"><a role="menuitem" class="ui-import-dropbox" tabindex="-1" href="#" target="_self"><i class="fa fa-dropbox fa-fw"></i> Dropbox</a>