From 0b41f38661d4ce3f90ad4df7cc5a17efae8352aa Mon Sep 17 00:00:00 2001 From: HampusM Date: Fri, 16 Apr 2021 23:05:12 +0200 Subject: Added basic backend code, two api endpoints & sanitization --- api/git.js | 62 +++++++++++++++++++++++++++++++++++++++++++++ api/sanitization.js | 10 ++++++++ api/v1.js | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 api/git.js create mode 100644 api/sanitization.js create mode 100644 api/v1.js (limited to 'api') diff --git a/api/git.js b/api/git.js new file mode 100644 index 0000000..b8d89c3 --- /dev/null +++ b/api/git.js @@ -0,0 +1,62 @@ +const { exec } = require("child_process"); + +const log_format='{"hash": "%H", "author": "%an", "author_email": "%ae", "date": "%at", "subject": "%s"}' + +function getLog(path) +{ + return new Promise((resolve) => + { + exec(`git -C ${path} log --format=format:'${log_format}'`, (error, stdout, stderr) => + { + if(error) { + const no_such_fileor_dir = new RegExp(`cannot change to '${path.replace('/', "\/")}': No such file or directory\\n$`); + + if(no_such_fileor_dir.test(error.message)) { + resolve({ "error": 404 }); + return; + } + resolve({ "error": error.message }); + return; + } + if(stderr) { + resolve({ "error": "Failed to communicate with git!" }); + return; + } + + const log = stdout.split('\n'); + log.forEach((entry, index) => log[index] = JSON.parse(entry)); + + resolve({ "data": log }); + }); + }); +} + +function getTimeSinceLatestCommit(path) +{ + return new Promise((resolve) => + { + exec(`git -C ${path} log -n 1 --date=unix'`, (error, stdout, stderr) => + { + if(error) { + const no_such_fileor_dir = new RegExp(`cannot change to '${path.replace('/', "\/")}': No such file or directory\\n$`); + + if(no_such_fileor_dir.test(error.message)) { + resolve({ "error": 404 }); + return; + } + resolve({ "error": error.message }); + return; + } + if(stderr) { + resolve({ "error": "Failed to communicate with git!" }); + return; + } + + const + + resolve({ "data": log }); + }); + }); +} + +module.exports.getLog = getLog; \ No newline at end of file diff --git a/api/sanitization.js b/api/sanitization.js new file mode 100644 index 0000000..5c9d009 --- /dev/null +++ b/api/sanitization.js @@ -0,0 +1,10 @@ +function sanitizeRepoName(dirty) +{ + const valid_repo_name = /^[a-zA-Z0-9\.\-_]+$/; + if(valid_repo_name.test(dirty)) { + return true; + } + return false; +} + +module.exports.sanitizeRepoName = sanitizeRepoName; \ No newline at end of file diff --git a/api/v1.js b/api/v1.js new file mode 100644 index 0000000..6b96e94 --- /dev/null +++ b/api/v1.js @@ -0,0 +1,72 @@ +const express = require("express"); +const git = require("./git"); +const sanitization = require("./sanitization"); +const fs = require('fs'); + +const router = express.Router(); +const base_dir="/home/hampus/Projects/" + +router.get("/repos", async function(req, res) +{ + fs.readdir(base_dir, (err, files) => + { + if(err) { + throw err; + } + + var repos = {}; + + files = files.filter(repo => repo.endsWith(".git")); + + let getRepoInfo = new Promise((resolve) => + { + files.forEach((repo, index, arr) => + { + fs.readFile(`${base_dir}/${repo}/description`, (err, content) => + { + let desc = ""; + + if(!err) { + desc = content.toString(); + } + + repos[repo.slice(0, -4)] = { "description": desc }; + + if(index === arr.length -1) resolve(); + }) + }); + }); + + getRepoInfo.then(() => + { + console.log(`Sist: ${JSON.stringify(repos)}`); + res.json({ "data": repos }); + }) + }); +}); + +router.get("/repos/:repo/log", async function(req, res) +{ + if(sanitization.sanitizeRepoName(req.params.repo)) { + const repo = `${req.params.repo}.git`; + const log = await git.getLog(`${base_dir}/${repo}`); + + if(log["error"]) { + if(typeof log["error"] === "string") { + res.status(500).json({ "error": log["error"] }); + return; + } + switch(log["error"]) { + case 404: + res.status(404).json({ "error": "Git repository doesn't exist!" }); + return; + } + return; + } + res.json(log); + return; + } + res.status(400).json({ "error": "Unacceptable git repository name!" }); +}); + +module.exports = router; \ No newline at end of file -- cgit v1.2.3-18-g5258