Better auth handling in projects

This commit is contained in:
Nick O'Leary
2017-11-23 00:27:13 +00:00
parent 10057de9b3
commit 5c88888e02
8 changed files with 303 additions and 102 deletions

View File

@@ -28,8 +28,8 @@ module.exports = {
// Projects
// List all projects
app.get("/", function(req,res) {
// List projects
runtime.storage.projects.listProjects().then(function(list) {
var active = runtime.storage.projects.getActiveProject();
var response = {
@@ -47,8 +47,8 @@ module.exports = {
})
});
// Create project
app.post("/", function(req,res) {
// Create project
runtime.storage.projects.createProject(req.body).then(function(data) {
res.json(data);
}).catch(function(err) {
@@ -61,8 +61,8 @@ module.exports = {
})
});
// Update a project
app.put("/:id", function(req,res) {
// Update a project
//TODO: validate the payload properly
if (req.body.active) {
var currentProject = runtime.storage.projects.getActiveProject();
@@ -83,7 +83,8 @@ module.exports = {
req.body.hasOwnProperty('description') ||
req.body.hasOwnProperty('dependencies')||
req.body.hasOwnProperty('summary') ||
req.body.hasOwnProperty('files')) {
req.body.hasOwnProperty('files') ||
req.body.hasOwnProperty('remote')) {
runtime.storage.projects.updateProject(req.params.id, req.body).then(function() {
res.redirect(303,req.baseUrl + '/'+ req.params.id);
}).catch(function(err) {
@@ -96,11 +97,10 @@ module.exports = {
} else {
res.status(400).json({error:"unexpected_error", message:"invalid_request"});
}
});
// Get project metadata
app.get("/:id", function(req,res) {
// Get project metadata
runtime.storage.projects.getProject(req.params.id).then(function(data) {
if (data) {
res.json(data);
@@ -113,13 +113,13 @@ module.exports = {
})
});
app.delete("/:id",function(req,res) {
// Delete project
// Delete project - tbd
app.delete("/:id", function(req,res) {
});
// Get project status - files, commit counts, branch info
app.get("/:id/status", function(req,res) {
// Get project metadata
runtime.storage.projects.getStatus(req.params.id).then(function(data) {
if (data) {
res.json(data);
@@ -133,8 +133,7 @@ module.exports = {
});
// Project Files
// Project file listing
app.get("/:id/files", function(req,res) {
runtime.storage.projects.getFiles(req.params.id).then(function(data) {
console.log("TODO: REMOVE /:id/files as /:id/status is better!")
@@ -146,7 +145,8 @@ module.exports = {
})
});
// /:project/files/:treeish/file-path
// Get file content in a given tree (index/stage)
app.get("/:id/files/:treeish/*", function(req,res) {
var projectId = req.params.id;
var treeish = req.params.treeish;
@@ -161,6 +161,7 @@ module.exports = {
})
});
// Stage a file
app.post("/:id/stage/*", function(req,res) {
var projectName = req.params.id;
var file = req.params[0];
@@ -173,6 +174,8 @@ module.exports = {
res.status(400).json({error:"unexpected_error", message:err.toString()});
})
});
// Stage multiple files
app.post("/:id/stage", function(req,res) {
var projectName = req.params.id;
var files = req.body.files;
@@ -186,6 +189,7 @@ module.exports = {
})
});
// Commit changes
app.post("/:id/commit", function(req,res) {
var projectName = req.params.id;
@@ -198,6 +202,7 @@ module.exports = {
})
});
// Unstage a file
app.delete("/:id/stage/*", function(req,res) {
var projectName = req.params.id;
var file = req.params[0];
@@ -210,6 +215,8 @@ module.exports = {
res.status(400).json({error:"unexpected_error", message:err.toString()});
})
});
// Unstage multiple files
app.delete("/:id/stage", function(req, res) {
var projectName = req.params.id;
runtime.storage.projects.unstageFile(projectName).then(function(data) {
@@ -221,6 +228,7 @@ module.exports = {
})
});
// Get a file diff
app.get("/:id/diff/:type/*", function(req,res) {
var projectName = req.params.id;
var type = req.params.type;
@@ -236,6 +244,7 @@ module.exports = {
})
});
// Get a list of commits
app.get("/:id/commits", function(req, res) {
var projectName = req.params.id;
var options = {
@@ -255,6 +264,7 @@ module.exports = {
})
});
// Get an individual commit details
app.get("/:id/commits/:sha", function(req, res) {
var projectName = req.params.id;
var sha = req.params.sha;
@@ -268,6 +278,7 @@ module.exports = {
})
});
// Push local commits to remote
app.post("/:id/push/?*", function(req,res) {
var projectName = req.params.id;
var remoteBranchName = req.params[0]
@@ -284,6 +295,8 @@ module.exports = {
}
})
});
// Pull remote commits
app.get("/:id/pull/?*", function(req,res) {
var projectName = req.params.id;
var remoteBranchName = req.params[0];
@@ -301,6 +314,7 @@ module.exports = {
})
});
// Abort an ongoing merge
app.delete("/:id/merge", function(req, res) {
var projectName = req.params.id;
runtime.storage.projects.abortMerge(projectName).then(function(data) {
@@ -316,6 +330,7 @@ module.exports = {
})
});
// Resolve a merge
app.post("/:id/resolve/*", function(req, res) {
var projectName = req.params.id;
var file = req.params[0];
@@ -333,6 +348,7 @@ module.exports = {
})
});
// Get a list of local branches
app.get("/:id/branches", function(req, res) {
var projectName = req.params.id;
runtime.storage.projects.getBranches(projectName,false).then(function(data) {
@@ -347,6 +363,8 @@ module.exports = {
}
})
});
// Get a list of remote branches
app.get("/:id/branches/remote", function(req, res) {
var projectName = req.params.id;
runtime.storage.projects.getBranches(projectName,true).then(function(data) {
@@ -362,6 +380,7 @@ module.exports = {
})
});
// Get branch status - commit counts/ahead/behind
app.get("/:id/branches/remote/*/status", function(req, res) {
var projectName = req.params.id;
var branch = req.params[0];
@@ -378,7 +397,7 @@ module.exports = {
})
});
// Set the active local branch
app.post("/:id/branches", function(req, res) {
var projectName = req.params.id;
var branchName = req.body.name;

View File

@@ -29,10 +29,19 @@ var log;
var projectsDir;
var authCache = {};
function getAuth(project,remote) {
if (authCache.hasOwnProperty(project) && authCache[project].hasOwnProperty(remote)) {
return authCache[project][remote];
}
return null;
}
function Project(name) {
this.name = name;
this.path = fspath.join(projectsDir,name);
this.paths = {};
this.auth = {origin:{}};
this.missingFiles = [];
@@ -169,7 +178,14 @@ Project.prototype.update = function (data) {
savePackage = true;
this.package.description = data.summary;
}
if (data.hasOwnProperty('remote')) {
authCache[project.name] = authCache[project.name]||{};
for (var remote in data.remote) {
if (data.remote.hasOwnProperty(remote)) {
authCache[project.name][remote] = data.remote[remote];
}
}
}
if (data.hasOwnProperty('files')) {
this.package['node-red'] = this.package['node-red'] || { settings: {}};
if (data.files.hasOwnProperty('flow') && this.package['node-red'].settings.flowFile !== data.files.flow) {
@@ -221,24 +237,7 @@ Project.prototype.getFileDiff = function(file,type) {
return gitTools.getFileDiff(this.path,file,type);
}
Project.prototype.getCommits = function(options) {
var self = this;
var fetchPromise;
if (this.remote) {
options.hasRemote = true;
fetchPromise = gitTools.fetch(this.path)
} else {
fetchPromise = when.resolve();
}
return fetchPromise.then(function() {
return gitTools.getCommits(self.path,options);
}).otherwise(function(e) {
if (e.code === 'git_auth_failed') {
throw e;
}
console.log("Fetch failed");
console.log(e);
return gitTools.getCommits(self.path,options);
});
return gitTools.getCommits(this.path,options);
}
Project.prototype.getCommit = function(sha) {
return gitTools.getCommit(this.path,sha);
@@ -253,32 +252,56 @@ Project.prototype.getFile = function (filePath,treeish) {
Project.prototype.status = function() {
var self = this;
var promises = [
gitTools.getStatus(this.path),
fs.exists(fspath.join(this.path,".git","MERGE_HEAD"))
]
return when.all(promises).then(function(results) {
var result = results[0];
if (results[1]) {
result.merging = true;
var fetchPromise;
if (this.remote) {
fetchPromise = gitTools.fetch(this.path,getAuth(this.name,'origin'));
} else {
fetchPromise = when.resolve();
}
var completeStatus = function(fetchError) {
var promises = [
gitTools.getStatus(self.path),
fs.exists(fspath.join(self.path,".git","MERGE_HEAD"))
];
return when.all(promises).then(function(results) {
var result = results[0];
if (results[1]) {
result.merging = true;
}
self.branches.local = result.branches.local;
self.branches.remote = result.branches.remote;
if (fetchError) {
result.branches.remoteError = {
code: fetchError.code
}
}
return result;
});
}
return fetchPromise.then(completeStatus).catch(function(e) {
if (e.code === 'git_auth_failed') {
console.log("Fetch auth failed");
} else {
console.log("Fetch failed");
console.log(e);
}
self.branches.local = result.branches.local;
self.branches.remote = result.branches.remote;
return result;
return completeStatus(e);
})
};
Project.prototype.push = function (remoteBranchName,setRemote) {
return gitTools.push(this.path, remoteBranchName, setRemote);
return gitTools.push(this.path, remoteBranchName, setRemote, getAuth(this.name,'origin'));
};
Project.prototype.pull = function (remoteBranchName,setRemote) {
if (setRemote) {
return gitTools.setUpstream(this.path, remoteBranchName).then(function() {
return gitTools.pull(this.path);
return gitTools.pull(this.path, null, getAuth(this.name,'origin'));
})
} else {
return gitTools.pull(this.path, remoteBranchName);
return gitTools.pull(this.path, remoteBranchName, getAuth(this.name,'origin'));
}
};
@@ -328,7 +351,16 @@ Project.prototype.abortMerge = function () {
};
Project.prototype.getBranches = function (remote) {
return gitTools.getBranches(this.path,remote);
var self = this;
var fetchPromise;
if (remote) {
fetchPromise = gitTools.fetch(this.path,getAuth(this.name,'origin'))
} else {
fetchPromise = when.resolve();
}
return fetchPromise.then(function() {
return gitTools.getBranches(self.path,remote);
});
};
Project.prototype.setBranch = function (branchName, isCreate) {
var self = this;
@@ -347,6 +379,7 @@ Project.prototype.getFlowFile = function() {
return null;
}
}
Project.prototype.getFlowFileBackup = function() {
return getBackupFilename(this.getFlowFile());
}
@@ -499,8 +532,18 @@ function createProject(metadata) {
return settings.set('projects',projects);
}).then(function() {
if (metadata.remote) {
console.log(metadata.remote);
return gitTools.clone(metadata.remote,projectPath).then(function(result) {
var auth;
if (metadata.remote.hasOwnProperty("username") && metadata.remote.hasOwnProperty("password")) {
authCache[project] = {
origin: { // TODO: hardcoded remote name
username: metadata.remote.username,
password: metadata.remote.password
}
}
auth = authCache[project].origin;
}
return gitTools.clone(metadata.remote,auth,projectPath).then(function(result) {
// Check this is a valid project
// If it is empty
// - if 'populate' flag is set, call populateProject

View File

@@ -28,7 +28,7 @@ function getListenPath() {
} else {
listenPath = path.join(process.env['XDG_RUNTIME_DIR'] || os.tmpdir(), fn);
}
console.log(listenPath);
// console.log(listenPath);
return listenPath;
}
@@ -68,7 +68,7 @@ var ResponseServer = function(auth) {
resolve({path:listenPath,close:function() { server.close(); }});
});
server.on('close', function() {
console.log("Closing response server");
// console.log("Closing response server");
fs.removeSync(listenPath);
});
server.on('error',function(err) {

View File

@@ -263,26 +263,6 @@ function parseLog(log) {
return commits;
}
// function getCommitCounts(cwd, options) {
// var commands = [
// runGitCommand(['rev-list', 'HEAD', '--count'],cwd), // #commits on master
// ];
// if (options.hasRemote) {
// commands.push(runGitCommand(['rev-list', 'master','^origin/master', '--count'],cwd)); // #commits master ahead
// commands.push(runGitCommand(['rev-list', '^master','origin/master', '--count'],cwd)); // #commits master behind
// }
// return when.all(commands).then(function(results) {
// var result = {
// total: parseInt(results[0])
// }
// if (options.hasRemote) {
// result.ahead = parseInt(results[1]);
// result.behind = parseInt(results[2]);
// }
// return result;
// });
// }
function getRemotes(cwd) {
return runGitCommand(['remote','-v'],cwd).then(function(output) {
var result;
@@ -362,7 +342,7 @@ module.exports = {
throw err;
});
},
push: function(cwd,remoteBranch,setUpstream) {
push: function(cwd,remoteBranch,setUpstream, auth) {
var args = ["push"];
var m = /^(.*?)\/(.*)$/.exec(remoteBranch);
if (m) {
@@ -375,7 +355,13 @@ module.exports = {
args.push("origin");
}
args.push("--porcelain");
return runGitCommand(args,cwd).otherwise(function(err) {
var promise;
if (auth) {
promise = runGitCommandWithAuth(args,cwd,auth);
} else {
promise = runGitCommand(args,cwd)
}
return promise.catch(function(err) {
if (err.code === 'git_error') {
if (/^!.*non-fast-forward/m.test(err.stdout)) {
err.code = 'git_push_failed';
@@ -384,7 +370,7 @@ module.exports = {
}
});
},
clone: function(remote, cwd) {
clone: function(remote, auth, cwd) {
var args = ["clone",remote.url];
if (remote.name) {
args.push("-o");
@@ -395,8 +381,8 @@ module.exports = {
args.push(remote.branch);
}
args.push(".");
if (remote.hasOwnProperty("username") && remote.hasOwnProperty("password")) {
return runGitCommandWithAuth(args,cwd,remote);
if (auth) {
return runGitCommandWithAuth(args,cwd,auth);
} else {
return runGitCommand(args,cwd);
}
@@ -441,8 +427,13 @@ module.exports = {
args.push(file);
return runGitCommand(args,cwd);
},
fetch: function(cwd) {
return runGitCommand(["fetch"],cwd);
fetch: function(cwd,auth) {
var args = ["fetch"];
if (auth) {
return runGitCommandWithAuth(args,cwd,auth);
} else {
return runGitCommand(args,cwd);
}
},
getCommits: function(cwd,options) {
var args = ["log", "--format=sha: %H%nparents: %p%nrefs: %D%nauthor: %an%ndate: %ct%nsubject: %s%n-----"];