Skip to content

Commit

Permalink
Fixes fossasia#132: option added to push documentation to GH-PAGES (f…
Browse files Browse the repository at this point in the history
  • Loading branch information
poonai authored and mariobehling committed Jun 17, 2017
1 parent 034e03b commit dc18c38
Show file tree
Hide file tree
Showing 12 changed files with 226 additions and 12 deletions.
2 changes: 2 additions & 0 deletions .gitignore
@@ -1,3 +1,5 @@
node_modules/
temp/
.idea/
.env
npm-debug.log
34 changes: 34 additions & 0 deletions app.js
Expand Up @@ -4,11 +4,17 @@ var favicon = require("serve-favicon");
var logger = require("morgan");
var cookieParser = require("cookie-parser");
var bodyParser = require("body-parser");
var passport = require("passport");
var githubStrategy = require("passport-github").Strategy;
var dotenv = require("dotenv");
var session = require("express-session");

dotenv.config({path: './.env'})
/**
* Backend Scripts
*/
var generator = require("./backend/generator");
var ghdeploy = require("./backend/ghdeploy")


var app = express();
Expand All @@ -32,8 +38,33 @@ app.use(logger("dev"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({
secret: process.env.SECRET,
resave: true,
saveUninitialized: true,
store: new session.MemoryStore()
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(path.join(__dirname, "public")));

passport.use(new githubStrategy({
clientID: process.env.CLIENTID,
clientSecret: process.env.CLIENTSECRET,
callbackURL: process.env.CALLBACKURL
}, function (accessToken, refreshToken, profile, cb) {
profile.token = accessToken;
cb(null, profile)
}))

passport.serializeUser(function(user, cb) {
cb(null, user);
});

passport.deserializeUser(function(obj, cb) {
cb(null, obj);
});

app.use("/preview", express.static(path.join(__dirname, "temp")))

app.use("/", index);
Expand All @@ -45,6 +76,9 @@ io.on('connection', function(socket){
socket.on('execute', function (formData) {
generator.executeScript(socket, formData);
});
socket.on('deploy', function (data) {
ghdeploy.deployPages(socket, data);
});
});

// catch 404 and forward to error handler
Expand Down
7 changes: 3 additions & 4 deletions backend/generator.js
Expand Up @@ -2,14 +2,13 @@ var exports = module.exports = {};

var uuidV4 = require("uuid/v4");
var validation = require("../public/scripts/validation.js");
var spawn = require('child_process').spawn;

exports.executeScript = function (socket, formData) {
if (!validation.isValid(formData)) {
socket.emit('err-logs', "Failed to generated documentation due to an error in input fields");
return false;
}
var spawn = require('child_process').spawn;

var email = formData.email;
var gitUrl = formData.gitUrl;
var docTheme = formData.docTheme;
Expand Down Expand Up @@ -41,10 +40,10 @@ exports.executeScript = function (socket, formData) {
process.on('exit', function (code) {
console.log('child process exited with code ' + code);
if (code === 0) {
socket.emit('success', {email: email, uniqueId: uniqueId});
socket.emit('success', {email: email, uniqueId: uniqueId, gitUrl: gitUrl});
} else {
socket.emit('failure', {errorCode: code});
}
});
return true;
};
};
37 changes: 37 additions & 0 deletions backend/ghdeploy.js
@@ -0,0 +1,37 @@
var crypter = require("../util/crypter.js")
var spawn = require('child_process').spawn;

exports.deployPages = function (socket, data) {
var donePercent = 0;
var repoName = data.gitURL.split("/")[4].split(".")[0];
var webUI = "true";
var username = data.username
var oauthToken = crypter.decrypt(data.encryptedToken)
const args = [
"-e", data.email,
"-i", data.uniqueId,
"-w", webUI,
"-n", username,
"-o", oauthToken,
"-r", repoName
];
var process = spawn("./publish_docs.sh", args);

process.stdout.on('data', function (data) {
console.log(data.toString());
socket.emit('deploy-logs', {donePercent: donePercent, data: data.toString()});
donePercent += 18;
});

process.stderr.on('data', function (data) {
console.log(data.toString());
socket.emit('err-logs', data.toString());
});

process.on('exit', function (code) {
console.log('child process exited with code ' + code);
if (code === 0) {
socket.emit('deploy-success', {pagesURL: "https://" + data.username + ".github.io/" + repoName});
}
});
}
4 changes: 4 additions & 0 deletions package.json
Expand Up @@ -9,9 +9,13 @@
"body-parser": "~1.17.1",
"cookie-parser": "~1.4.3",
"debug": "~2.6.3",
"dotenv": "^4.0.0",
"express": "~4.15.2",
"express-session": "^1.15.3",
"jade": "~1.11.0",
"morgan": "~1.8.1",
"passport": "^0.3.2",
"passport-github": "^1.1.0",
"serve-favicon": "~2.4.2",
"socket.io": "^2.0.2",
"sys": "^0.0.1",
Expand Down
4 changes: 3 additions & 1 deletion public/scripts/form.js
Expand Up @@ -44,6 +44,8 @@ $(function () {
$('#notification-container').css("visibility", "hidden");
$('#notification-container').css("opacity", "0");
}, 5000)
$('#btnDeploy').css("display", "inline");
$('#btnDeploy').attr("href", '/github?email='+data.email+'&uniqueId='+data.uniqueId+'&gitURL='+data.gitUrl);
});

socket.on('failure', function (data) {
Expand All @@ -70,4 +72,4 @@ function getData() {
});

return data;
}
}
8 changes: 7 additions & 1 deletion public/stylesheets/style.css
Expand Up @@ -46,6 +46,12 @@ a {
margin-left: 10px;
}

#btnDeploy {
display: none;
width: -moz-fit-content;
margin-left: 10px;
}

#notification-container {
position: absolute;
text-align: center;
Expand Down Expand Up @@ -81,4 +87,4 @@ a {

.error {
color: red;
}
}
48 changes: 43 additions & 5 deletions publish_docs.sh
Expand Up @@ -5,24 +5,49 @@
# Environment Variables:
# $DOCURL - Custom URL where the documentation would be published.

while getopts e:i:w:n:o:r: option
do
case "${option}"
in
e) EMAIL=${OPTARG};;
i) UNIQUEID=${OPTARG};;
w) WEBUI=${OPTARG};;
n) USERNAME=${OPTARG};;
o) OAUTH_TOKEN=${OPTARG};;
r) REPONAME=${OPTARG};;
esac
done

git config --global user.name "Yaydoc Bot"
git config --global user.email "noreply+bot@example.com"

GIT_SSH_URL=git@github.com:$USERNAME/$REPONAME.git

git clone --quiet $GIT_SSH_URL gh-pages
if [ $? -ne 0 ]; then
echo -e "Cloning using SSH failed. Trying with Github token instead\n"
GIT_HTTPS_URL=https://$USERNAME:$OAUTH_TOKEN@github.com/$USERNAME/$REPONAME.git
git clone --quiet $GIT_HTTPS_URL gh-pages
if [ "${WEBUI:-false}" == "true" ]; then
cd temp/${EMAIL}
git clone --quiet $GIT_HTTPS_URL ${UNIQUEID}_pages
else
git clone --quiet $GIT_HTTPS_URL gh-pages
fi

if [[ $? -ne 0 ]]; then
echo -e "Failed to clone gh-pages.\n"
clean
exit 3
fi
fi

cd gh-pages
echo -e "Cloned successfully! \n"

if [ "${WEBUI:-false}" == "true" ]; then
cd ${UNIQUEID}_pages
else
cd gh-pages
fi


# Create gh-pages branch if it doesn't exist
git fetch
Expand All @@ -32,12 +57,19 @@ fi

# Overwrite files in the branch
git rm -rfq ./*
cp -a ../_build/html/. ./
if [ "${WEBUI:-false}" == "true" ]; then
cp -a ../${UNIQUEID}_preview/. ./
else
cp -a ../_build/html/. ./
fi

echo -e "Overwrite successfully \n"

# Enable publishing documentation to custom URL
if [[ -z "${DOCURL}" ]]; then
echo -e "DOCURL not set. Using default github pages URL"
else
echo -e "DOCURL set."
echo $DOCURL > CNAME
fi

Expand All @@ -46,5 +78,11 @@ git add -f .
git commit -q -m "[Auto] Update Built Docs ($(date +%Y-%m-%d.%H:%M:%S))"
git push origin gh-pages

echo -e "github pages pushed successfully!\n"
# Cleanup
clean
if [ "${WEBUI:-false}" == "true" ]; then
cd ..
rm -r ${UNIQUEID}_pages
else
clean
fi
31 changes: 30 additions & 1 deletion routes/index.js
@@ -1,6 +1,7 @@
var express = require("express");
var router = express.Router();

var passport = require("passport")
var crypter = require("../util/crypter.js")
/* GET home page. */
router.get("/", function(req, res, next) {
res.render("index", { title: "Yaydoc" });
Expand All @@ -12,4 +13,32 @@ router.get('/download/:email/:uniqueId', function (req, res, next) {
res.download(file);
});

router.get("/github", function (req, res, next) {
req.session.uniqueId = req.query.uniqueId;
req.session.email = req.query.email
req.session.gitURL = req.query.gitURL
next()
}, passport.authenticate('github', {
scope: [
'public_repo',
'read:org'
]
}))

router.get("/callback", passport.authenticate('github'), function (req, res, next) {
req.session.username = req.user.username;
req.session.token = req.user.token
res.redirect("/deploy")
})

router.get("/deploy", function (req, res, next) {
res.render("deploy", {
email: req.session.email,
gitURL: req.session.gitURL,
uniqueId: req.session.uniqueId,
token: crypter.encrypt(req.session.token),
username: req.session.username
})
})

module.exports = router;
30 changes: 30 additions & 0 deletions util/crypter.js
@@ -0,0 +1,30 @@
const crypto = require('crypto');

const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY; // Must be 256 bytes (32 characters)
const IV_LENGTH = 16; // For AES, this is always 16

function encrypt(text) {
let iv = crypto.randomBytes(IV_LENGTH);
let cipher = crypto.createCipheriv('aes-256-cbc', new Buffer(ENCRYPTION_KEY), iv);
let encrypted = cipher.update(text);

encrypted = Buffer.concat([encrypted, cipher.final()]);

return iv.toString('hex') + ':' + encrypted.toString('hex');
}

function decrypt(text) {
let textParts = text.split(':');
let iv = new Buffer(textParts.shift(), 'hex');
let encryptedText = new Buffer(textParts.join(':'), 'hex');
let decipher = crypto.createDecipheriv('aes-256-cbc', new Buffer(ENCRYPTION_KEY), iv);
let decrypted = decipher.update(encryptedText);

decrypted = Buffer.concat([decrypted, decipher.final()]);

return decrypted.toString();
}

exports.encrypt = encrypt

exports.decrypt = decrypt
32 changes: 32 additions & 0 deletions views/deploy.jade
@@ -0,0 +1,32 @@
extends layout

block content
script(src="/socket.io/socket.io.js")
script.
var socket = io();
socket.emit('deploy', {
'email': "#{email}",
'gitURL': "#{gitURL}",
'uniqueId': "#{uniqueId}",
'encryptedToken': "#{token}",
'username': "#{username}"
})

socket.on('deploy-logs', function (data) {
$('#messages').append($('<li>').text(data.data));
$("#progress").css("width", data.donePercent + "%");
})

socket.on('deploy-success', function(data) {
$("#progress").css("width", "100%");
$("#main-content").append('<br><center><a class="btn btn-default" href="'+ data.pagesURL +'" target="_blank">GH-PAGES</a></center>')
})

.container
.col-md-6.col-md-offset-3#main-content
.progress
#progress.progress-bar(role='progressbar', aria-valuenow='0', aria-valuemin='0', aria-valuemax='100', style='width:0%')
span.sr-only
.logs.pre-scrollable
h4(style='text-align: center; padding-top: 5px; color: #ffffff') Console Output
ul#messages
1 change: 1 addition & 0 deletions views/index.jade
Expand Up @@ -35,6 +35,7 @@ block content
.row
a.btn.btn-default(type='button' id='btnDownload') Download
a.btn.btn-default(type='button' id='btnPreview' target='_blank') Preview
a.btn.btn-default(type='button' id='btnDeploy') Deploy
.progress
#progress.progress-bar(role='progressbar', aria-valuenow='0', aria-valuemin='0', aria-valuemax='100', style='width:0%')
span.sr-only
Expand Down

0 comments on commit dc18c38

Please sign in to comment.