mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Add projects to runtime-api
This commit is contained in:
		@@ -36,7 +36,7 @@
 | 
				
			|||||||
</head>
 | 
					</head>
 | 
				
			||||||
<body spellcheck="false">
 | 
					<body spellcheck="false">
 | 
				
			||||||
<div id="header">
 | 
					<div id="header">
 | 
				
			||||||
    <span class="logo">{{#header.url}}<a href="{{.}}">{{/header.url}}{{#header.image}}<img src="{{.}}" title="{{version}}">{{/header.image}} <span>{{ header.title }}</span>{{#header.url}}</a>{{/header.url}}</span>
 | 
					    <span class="logo">{{#header.url}}<a href="{{.}}">{{/header.url}}{{#header.image}}<img src="{{.}}">{{/header.image}} <span>{{ header.title }}</span>{{#header.url}}</a>{{/header.url}}</span>
 | 
				
			||||||
    <ul class="header-toolbar hide">
 | 
					    <ul class="header-toolbar hide">
 | 
				
			||||||
        <li><a id="btn-sidemenu" class="button" data-toggle="dropdown" href="#"><i class="fa fa-bars"></i></a></li>
 | 
					        <li><a id="btn-sidemenu" class="button" data-toggle="dropdown" href="#"><i class="fa fa-bars"></i></a></li>
 | 
				
			||||||
    </ul>
 | 
					    </ul>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,8 +51,7 @@ module.exports = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            var ui = require("./ui");
 | 
					            var ui = require("./ui");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // TODO: ui is passed runtime so it get access runtime.nodes.getNodeIconPath
 | 
					            ui.init(runtimeAPI);
 | 
				
			||||||
            ui.init(runtime);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var editorApp = express();
 | 
					            var editorApp = express();
 | 
				
			||||||
            if (settings.requireHttps === true) {
 | 
					            if (settings.requireHttps === true) {
 | 
				
			||||||
@@ -72,13 +71,13 @@ module.exports = {
 | 
				
			|||||||
            editorApp.get("/icons/:scope/:module/:icon",ui.icon);
 | 
					            editorApp.get("/icons/:scope/:module/:icon",ui.icon);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var theme = require("./theme");
 | 
					            var theme = require("./theme");
 | 
				
			||||||
            theme.init(settings, runtime.version());
 | 
					            theme.init(settings);
 | 
				
			||||||
            editorApp.use("/theme",theme.app());
 | 
					            editorApp.use("/theme",theme.app());
 | 
				
			||||||
            editorApp.use("/",ui.editorResources);
 | 
					            editorApp.use("/",ui.editorResources);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            //Projects
 | 
					            //Projects
 | 
				
			||||||
            var projects = require("./projects");
 | 
					            var projects = require("./projects");
 | 
				
			||||||
            projects.init(runtime);
 | 
					            projects.init(runtimeAPI);
 | 
				
			||||||
            editorApp.use("/projects",projects.app());
 | 
					            editorApp.use("/projects",projects.app());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Locales
 | 
					            // Locales
 | 
				
			||||||
@@ -89,7 +88,7 @@ module.exports = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            // Library
 | 
					            // Library
 | 
				
			||||||
            var library = require("./library");
 | 
					            var library = require("./library");
 | 
				
			||||||
            library.init(editorApp,runtimeAPI);
 | 
					            library.init(runtimeAPI);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            editorApp.get("/library/flows",needsPermission("library.read"),library.getAll,apiUtil.errorHandler);
 | 
					            editorApp.get("/library/flows",needsPermission("library.read"),library.getAll,apiUtil.errorHandler);
 | 
				
			||||||
            editorApp.get(/library\/([^\/]+)(?:$|\/(.*))/,needsPermission("library.read"),library.getEntry);
 | 
					            editorApp.get(/library\/([^\/]+)(?:$|\/(.*))/,needsPermission("library.read"),library.getEntry);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,7 +22,7 @@ var when = require('when');
 | 
				
			|||||||
var runtimeAPI;
 | 
					var runtimeAPI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
    init: function(app,_runtimeAPI) {
 | 
					    init: function(_runtimeAPI) {
 | 
				
			||||||
        runtimeAPI = _runtimeAPI;
 | 
					        runtimeAPI = _runtimeAPI;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,89 +15,74 @@
 | 
				
			|||||||
 **/
 | 
					 **/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var express = require("express");
 | 
					var express = require("express");
 | 
				
			||||||
var runtime;
 | 
					var apiUtils = require("../../util");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var runtimeAPI;
 | 
				
			||||||
var needsPermission = require("../../auth").needsPermission;
 | 
					var needsPermission = require("../../auth").needsPermission;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
    init: function(_runtime) {
 | 
					    init: function(_runtimeAPI) {
 | 
				
			||||||
        runtime = _runtime;
 | 
					        runtimeAPI = _runtimeAPI;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    app: function() {
 | 
					    app: function() {
 | 
				
			||||||
        var app = express();
 | 
					        var app = express();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        app.use(function(req,res,next) {
 | 
					        app.use(function(req,res,next) {
 | 
				
			||||||
            if (!runtime.storage.projects) {
 | 
					            runtimeAPI.projects.available().then(function(available) {
 | 
				
			||||||
 | 
					                if (!available) {
 | 
				
			||||||
                    res.status(404).end();
 | 
					                    res.status(404).end();
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    next();
 | 
					                    next();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Projects
 | 
					        // Projects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // List all projects
 | 
					        // List all projects
 | 
				
			||||||
        app.get("/", needsPermission("projects.read"), function(req,res) {
 | 
					        app.get("/", needsPermission("projects.read"), function(req,res) {
 | 
				
			||||||
            runtime.storage.projects.listProjects(req.user, req.user).then(function(list) {
 | 
					            var opts = {
 | 
				
			||||||
                var active = runtime.storage.projects.getActiveProject(req.user);
 | 
					                user: req.user
 | 
				
			||||||
                var response = {
 | 
					 | 
				
			||||||
                    projects: list
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
                if (active) {
 | 
					 | 
				
			||||||
                    response.active = active.name;
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
                res.json(response);
 | 
					            runtimeAPI.projects.listProjects(opts).then(function(result) {
 | 
				
			||||||
 | 
					                res.json(result);
 | 
				
			||||||
            }).catch(function(err) {
 | 
					            }).catch(function(err) {
 | 
				
			||||||
                console.log(err.stack);
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
                if (err.code) {
 | 
					            });
 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Create project
 | 
					        // Create project
 | 
				
			||||||
        app.post("/", needsPermission("projects.write"), function(req,res) {
 | 
					        app.post("/", needsPermission("projects.write"), function(req,res) {
 | 
				
			||||||
            runtime.storage.projects.createProject(req.user, req.body).then(function(data) {
 | 
					            var opts = {
 | 
				
			||||||
                res.json(data);
 | 
					                user: req.user,
 | 
				
			||||||
            }).catch(function(err) {
 | 
					                project: req.body
 | 
				
			||||||
                console.log(err.stack);
 | 
					 | 
				
			||||||
                if (err.code) {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            })
 | 
					            runtimeAPI.projects.createProject(opts).then(function(result) {
 | 
				
			||||||
 | 
					                res.json(result);
 | 
				
			||||||
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Update a project
 | 
					        // Update a project
 | 
				
			||||||
        app.put("/:id", needsPermission("projects.write"), function(req,res) {
 | 
					        app.put("/:id", needsPermission("projects.write"), function(req,res) {
 | 
				
			||||||
            //TODO: validate the payload properly
 | 
					            var opts = {
 | 
				
			||||||
 | 
					                user: req.user,
 | 
				
			||||||
 | 
					                id: req.params.id,
 | 
				
			||||||
 | 
					                project: req.body
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (req.body.active) {
 | 
					            if (req.body.active) {
 | 
				
			||||||
                var currentProject = runtime.storage.projects.getActiveProject(req.user);
 | 
					                runtimeAPI.projects.setActiveProject(opts).then(function() {
 | 
				
			||||||
                if (!currentProject || req.params.id !== currentProject.name) {
 | 
					 | 
				
			||||||
                    runtime.storage.projects.setActiveProject(req.user, req.params.id).then(function() {
 | 
					 | 
				
			||||||
                    res.redirect(303,req.baseUrl + '/');
 | 
					                    res.redirect(303,req.baseUrl + '/');
 | 
				
			||||||
                }).catch(function(err) {
 | 
					                }).catch(function(err) {
 | 
				
			||||||
                        if (err.code) {
 | 
					                    apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
                            res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                        } else {
 | 
					 | 
				
			||||||
                            res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.redirect(303,req.baseUrl + '/'+ req.params.id);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            } else if (req.body.initialise) {
 | 
					            } else if (req.body.initialise) {
 | 
				
			||||||
                // Initialised set when creating default files for an empty repo
 | 
					                runtimeAPI.projects.initialiseProject(opts).then(function() {
 | 
				
			||||||
                runtime.storage.projects.initialiseProject(req.user, req.params.id, req.body).then(function() {
 | 
					 | 
				
			||||||
                    res.redirect(303,req.baseUrl + '/'+ req.params.id);
 | 
					                    res.redirect(303,req.baseUrl + '/'+ req.params.id);
 | 
				
			||||||
                }).catch(function(err) {
 | 
					                }).catch(function(err) {
 | 
				
			||||||
                    if (err.code) {
 | 
					                    apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
                        res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
            } else if (req.body.hasOwnProperty('credentialSecret') ||
 | 
					            } else if (req.body.hasOwnProperty('credentialSecret') ||
 | 
				
			||||||
                       req.body.hasOwnProperty('description') ||
 | 
					                       req.body.hasOwnProperty('description') ||
 | 
				
			||||||
@@ -105,14 +90,10 @@ module.exports = {
 | 
				
			|||||||
                       req.body.hasOwnProperty('summary') ||
 | 
					                       req.body.hasOwnProperty('summary') ||
 | 
				
			||||||
                       req.body.hasOwnProperty('files') ||
 | 
					                       req.body.hasOwnProperty('files') ||
 | 
				
			||||||
                        req.body.hasOwnProperty('git')) {
 | 
					                        req.body.hasOwnProperty('git')) {
 | 
				
			||||||
                runtime.storage.projects.updateProject(req.user, req.params.id, req.body).then(function() {
 | 
					                runtimeAPI.projects.updateProject(opts).then(function() {
 | 
				
			||||||
                    res.redirect(303,req.baseUrl + '/'+ req.params.id);
 | 
					                    res.redirect(303,req.baseUrl + '/'+ req.params.id);
 | 
				
			||||||
                }).catch(function(err) {
 | 
					                }).catch(function(err) {
 | 
				
			||||||
                    if (err.code) {
 | 
					                    apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
                        res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                res.status(400).json({error:"unexpected_error", message:"invalid_request"});
 | 
					                res.status(400).json({error:"unexpected_error", message:"invalid_request"});
 | 
				
			||||||
@@ -121,437 +102,404 @@ module.exports = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Get project metadata
 | 
					        // Get project metadata
 | 
				
			||||||
        app.get("/:id", needsPermission("projects.read"), function(req,res) {
 | 
					        app.get("/:id", needsPermission("projects.read"), function(req,res) {
 | 
				
			||||||
            runtime.storage.projects.getProject(req.user, req.params.id).then(function(data) {
 | 
					            var opts = {
 | 
				
			||||||
 | 
					                user: req.user,
 | 
				
			||||||
 | 
					                id: req.params.id
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.getProject(opts).then(function(data) {
 | 
				
			||||||
                if (data) {
 | 
					                if (data) {
 | 
				
			||||||
                    res.json(data);
 | 
					                    res.json(data);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    res.status(404).end();
 | 
					                    res.status(404).end();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }).catch(function(err) {
 | 
					            }).catch(function(err) {
 | 
				
			||||||
                console.log(err.stack);
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
                res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Delete project
 | 
					        // Delete project
 | 
				
			||||||
        app.delete("/:id", needsPermission("projects.write"), function(req,res) {
 | 
					        app.delete("/:id", needsPermission("projects.write"), function(req,res) {
 | 
				
			||||||
            runtime.storage.projects.deleteProject(req.user, req.params.id).then(function() {
 | 
					            var opts = {
 | 
				
			||||||
 | 
					                user: req.user,
 | 
				
			||||||
 | 
					                id: req.params.id
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.deleteProject(opts).then(function() {
 | 
				
			||||||
                res.status(204).end();
 | 
					                res.status(204).end();
 | 
				
			||||||
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            .catch(function(err) {
 | 
					 | 
				
			||||||
                console.log(err.stack);
 | 
					 | 
				
			||||||
                res.status(400).json({error:"unexpected_error", message:err.toString()})
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Get project status - files, commit counts, branch info
 | 
					        // Get project status - files, commit counts, branch info
 | 
				
			||||||
        app.get("/:id/status", needsPermission("projects.read"), function(req,res) {
 | 
					        app.get("/:id/status", needsPermission("projects.read"), function(req,res) {
 | 
				
			||||||
            var includeRemote = req.query.remote;
 | 
					            var opts = {
 | 
				
			||||||
 | 
					                user: req.user,
 | 
				
			||||||
            runtime.storage.projects.getStatus(req.user, req.params.id, includeRemote).then(function(data) {
 | 
					                id: req.params.id,
 | 
				
			||||||
 | 
					                remote: req.query.remote
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.getStatus(opts).then(function(data){
 | 
				
			||||||
                if (data) {
 | 
					                if (data) {
 | 
				
			||||||
                    res.json(data);
 | 
					                    res.json(data);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    res.status(404).end();
 | 
					                    res.status(404).end();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }).catch(function(err) {
 | 
					            }).catch(function(err) {
 | 
				
			||||||
                if (err.code) {
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Project file listing
 | 
					        // Project file listing
 | 
				
			||||||
        app.get("/:id/files", needsPermission("projects.read"), function(req,res) {
 | 
					        app.get("/:id/files", needsPermission("projects.read"), function(req,res) {
 | 
				
			||||||
            runtime.storage.projects.getFiles(req.user, req.params.id).then(function(data) {
 | 
					            var opts = {
 | 
				
			||||||
                // console.log("TODO: REMOVE /:id/files as /:id/status is better!")
 | 
					                user: req.user,
 | 
				
			||||||
                res.json(data);
 | 
					                id: req.params.id
 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(function(err) {
 | 
					 | 
				
			||||||
                if (err.code) {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.getFiles(opts).then(function(data) {
 | 
				
			||||||
 | 
					                res.json(data);
 | 
				
			||||||
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Get file content in a given tree (index/stage)
 | 
					        // Get file content in a given tree (index/stage)
 | 
				
			||||||
        app.get("/:id/files/:treeish/*", needsPermission("projects.read"), function(req,res) {
 | 
					        app.get("/:id/files/:treeish/*", needsPermission("projects.read"), function(req,res) {
 | 
				
			||||||
            var projectId = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            var treeish = req.params.treeish;
 | 
					                user: req.user,
 | 
				
			||||||
            var filePath = req.params[0];
 | 
					                id: req.params.id,
 | 
				
			||||||
 | 
					                path: req.params[0],
 | 
				
			||||||
            runtime.storage.projects.getFile(req.user, projectId,filePath,treeish).then(function(data) {
 | 
					                tree: req.params.treeish
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.getFile(opts).then(function(data) {
 | 
				
			||||||
                res.json({content:data});
 | 
					                res.json({content:data});
 | 
				
			||||||
            })
 | 
					            }).catch(function(err) {
 | 
				
			||||||
            .catch(function(err) {
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
                console.log(err.stack);
 | 
					 | 
				
			||||||
                res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Revert a file
 | 
					        // Revert a file
 | 
				
			||||||
        app.delete("/:id/files/_/*", needsPermission("projects.write"), function(req,res) {
 | 
					        app.delete("/:id/files/_/*", needsPermission("projects.write"), function(req,res) {
 | 
				
			||||||
            var projectId = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            var filePath = req.params[0];
 | 
					                user: req.user,
 | 
				
			||||||
 | 
					                id: req.params.id,
 | 
				
			||||||
 | 
					                path: req.params[0]
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            runtime.storage.projects.revertFile(req.user, projectId,filePath).then(function() {
 | 
					            runtimeAPI.projects.revertFile(opts).then(function() {
 | 
				
			||||||
                res.status(204).end();
 | 
					                res.status(204).end();
 | 
				
			||||||
            })
 | 
					            }).catch(function(err) {
 | 
				
			||||||
            .catch(function(err) {
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
                console.log(err.stack);
 | 
					 | 
				
			||||||
                res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Stage a file
 | 
					        // Stage a file
 | 
				
			||||||
        app.post("/:id/stage/*", needsPermission("projects.write"), function(req,res) {
 | 
					        app.post("/:id/stage/*", needsPermission("projects.write"), function(req,res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            var file = req.params[0];
 | 
					                user: req.user,
 | 
				
			||||||
 | 
					                id: req.params.id,
 | 
				
			||||||
            runtime.storage.projects.stageFile(req.user, projectName,file).then(function(data) {
 | 
					                path: req.params[0]
 | 
				
			||||||
                res.redirect(303,req.baseUrl+"/"+projectName+"/status");
 | 
					            }
 | 
				
			||||||
            })
 | 
					            runtimeAPI.projects.stageFile(opts).then(function() {
 | 
				
			||||||
            .catch(function(err) {
 | 
					                res.redirect(303,req.baseUrl+"/"+opts.id+"/status");
 | 
				
			||||||
                console.log(err.stack);
 | 
					            }).catch(function(err) {
 | 
				
			||||||
                res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Stage multiple files
 | 
					        // Stage multiple files
 | 
				
			||||||
        app.post("/:id/stage", needsPermission("projects.write"), function(req,res) {
 | 
					        app.post("/:id/stage", needsPermission("projects.write"), function(req,res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            var files = req.body.files;
 | 
					                user: req.user,
 | 
				
			||||||
 | 
					                id: req.params.id,
 | 
				
			||||||
            runtime.storage.projects.stageFile(req.user, projectName,files).then(function(data) {
 | 
					                path: req.body.files
 | 
				
			||||||
                res.redirect(303,req.baseUrl+"/"+projectName+"/status");
 | 
					            }
 | 
				
			||||||
            })
 | 
					            runtimeAPI.projects.stageFile(opts).then(function() {
 | 
				
			||||||
            .catch(function(err) {
 | 
					                res.redirect(303,req.baseUrl+"/"+opts.id+"/status");
 | 
				
			||||||
                console.log(err.stack);
 | 
					            }).catch(function(err) {
 | 
				
			||||||
                res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Commit changes
 | 
					        // Commit changes
 | 
				
			||||||
        app.post("/:id/commit", needsPermission("projects.write"), function(req,res) {
 | 
					        app.post("/:id/commit", needsPermission("projects.write"), function(req,res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
 | 
					                user: req.user,
 | 
				
			||||||
            runtime.storage.projects.commit(req.user, projectName,req.body).then(function(data) {
 | 
					                id: req.params.id,
 | 
				
			||||||
                res.redirect(303,req.baseUrl+"/"+projectName+"/status");
 | 
					                message: req.body.message
 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(function(err) {
 | 
					 | 
				
			||||||
                if (err.code) {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.commit(opts).then(function() {
 | 
				
			||||||
 | 
					                res.redirect(303,req.baseUrl+"/"+opts.id+"/status");
 | 
				
			||||||
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Unstage a file
 | 
					        // Unstage a file
 | 
				
			||||||
        app.delete("/:id/stage/*", needsPermission("projects.write"), function(req,res) {
 | 
					        app.delete("/:id/stage/*", needsPermission("projects.write"), function(req,res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            var file = req.params[0];
 | 
					                user: req.user,
 | 
				
			||||||
 | 
					                id: req.params.id,
 | 
				
			||||||
            runtime.storage.projects.unstageFile(req.user, projectName,file).then(function(data) {
 | 
					                path: req.params[0]
 | 
				
			||||||
                res.redirect(303,req.baseUrl+"/"+projectName+"/status");
 | 
					            }
 | 
				
			||||||
            })
 | 
					            runtimeAPI.projects.unstageFile(opts).then(function() {
 | 
				
			||||||
            .catch(function(err) {
 | 
					                res.redirect(303,req.baseUrl+"/"+opts.id+"/status");
 | 
				
			||||||
                console.log(err.stack);
 | 
					            }).catch(function(err) {
 | 
				
			||||||
                res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Unstage multiple files
 | 
					        // Unstage multiple files
 | 
				
			||||||
        app.delete("/:id/stage", needsPermission("projects.write"), function(req, res) {
 | 
					        app.delete("/:id/stage", needsPermission("projects.write"), function(req, res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            runtime.storage.projects.unstageFile(req.user, projectName).then(function(data) {
 | 
					                user: req.user,
 | 
				
			||||||
                res.redirect(303,req.baseUrl+"/"+projectName+"/status");
 | 
					                id: req.params.id
 | 
				
			||||||
            })
 | 
					            }
 | 
				
			||||||
            .catch(function(err) {
 | 
					            runtimeAPI.projects.unstageFile(opts).then(function() {
 | 
				
			||||||
                console.log(err.stack);
 | 
					                res.redirect(303,req.baseUrl+"/"+opts.id+"/status");
 | 
				
			||||||
                res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Get a file diff
 | 
					        // Get a file diff
 | 
				
			||||||
        app.get("/:id/diff/:type/*", needsPermission("projects.read"), function(req,res) {
 | 
					        app.get("/:id/diff/:type/*", needsPermission("projects.read"), function(req,res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            var type = req.params.type;
 | 
					                user: req.user,
 | 
				
			||||||
            var file = req.params[0];
 | 
					                id: req.params.id,
 | 
				
			||||||
            runtime.storage.projects.getFileDiff(req.user, projectName,file,type).then(function(data) {
 | 
					                path: req.params[0],
 | 
				
			||||||
 | 
					                type: req.params.type
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.getFileDiff(opts).then(function(data) {
 | 
				
			||||||
                res.json({
 | 
					                res.json({
 | 
				
			||||||
                    diff: data
 | 
					                    diff: data
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
            })
 | 
					            }).catch(function(err) {
 | 
				
			||||||
            .catch(function(err) {
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
                console.log(err.stack);
 | 
					 | 
				
			||||||
                res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Get a list of commits
 | 
					        // Get a list of commits
 | 
				
			||||||
        app.get("/:id/commits", needsPermission("projects.read"), function(req, res) {
 | 
					        app.get("/:id/commits", needsPermission("projects.read"), function(req, res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            var options = {
 | 
					                user: req.user,
 | 
				
			||||||
                limit: req.query.limit||20,
 | 
					                id: req.params.id,
 | 
				
			||||||
 | 
					                limit: req.query.limit || 20,
 | 
				
			||||||
                before: req.query.before
 | 
					                before: req.query.before
 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
            runtime.storage.projects.getCommits(req.user, projectName,options).then(function(data) {
 | 
					 | 
				
			||||||
                res.json(data);
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(function(err) {
 | 
					 | 
				
			||||||
                console.log(err.stack);
 | 
					 | 
				
			||||||
                if (err.code) {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.getCommits(opts).then(function(data) {
 | 
				
			||||||
 | 
					                res.json(data);
 | 
				
			||||||
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Get an individual commit details
 | 
					        // Get an individual commit details
 | 
				
			||||||
        app.get("/:id/commits/:sha", needsPermission("projects.read"), function(req, res) {
 | 
					        app.get("/:id/commits/:sha", needsPermission("projects.read"), function(req, res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            var sha = req.params.sha;
 | 
					                user: req.user,
 | 
				
			||||||
 | 
					                id: req.params.id,
 | 
				
			||||||
            runtime.storage.projects.getCommit(req.user, projectName,sha).then(function(data) {
 | 
					                sha: req.params.sha
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.getCommit(opts).then(function(data) {
 | 
				
			||||||
                res.json({commit:data});
 | 
					                res.json({commit:data});
 | 
				
			||||||
            })
 | 
					            }).catch(function(err) {
 | 
				
			||||||
            .catch(function(err) {
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
                console.log(err.stack);
 | 
					 | 
				
			||||||
                res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Push local commits to remote
 | 
					        // Push local commits to remote
 | 
				
			||||||
        app.post("/:id/push/?*", needsPermission("projects.write"), function(req,res) {
 | 
					        app.post("/:id/push/?*", needsPermission("projects.write"), function(req,res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            var remoteBranchName = req.params[0]
 | 
					                user: req.user,
 | 
				
			||||||
            var setRemote = req.query.u;
 | 
					                id: req.params.id,
 | 
				
			||||||
            runtime.storage.projects.push(req.user, projectName,remoteBranchName,setRemote).then(function(data) {
 | 
					                remote: req.params[0],
 | 
				
			||||||
                res.status(204).end();
 | 
					                track: req.query.u
 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(function(err) {
 | 
					 | 
				
			||||||
                if (err.code) {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.push(opts).then(function(data) {
 | 
				
			||||||
 | 
					                res.status(204).end();
 | 
				
			||||||
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Pull remote commits
 | 
					        // Pull remote commits
 | 
				
			||||||
        app.post("/:id/pull/?*", needsPermission("projects.write"), function(req,res) {
 | 
					        app.post("/:id/pull/?*", needsPermission("projects.write"), function(req,res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            var remoteBranchName = req.params[0];
 | 
					                user: req.user,
 | 
				
			||||||
            var setUpstream = req.query.setUpstream;
 | 
					                id: req.params.id,
 | 
				
			||||||
            var allowUnrelatedHistories = req.query.allowUnrelatedHistories;
 | 
					                remote: req.params[0],
 | 
				
			||||||
            runtime.storage.projects.pull(req.user, projectName,remoteBranchName,setUpstream,allowUnrelatedHistories).then(function(data) {
 | 
					                track: req.query.setUpstream,
 | 
				
			||||||
                res.status(204).end();
 | 
					                allowUnrelatedHistories: req.query.allowUnrelatedHistories
 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(function(err) {
 | 
					 | 
				
			||||||
                console.log(err.stack);
 | 
					 | 
				
			||||||
                if (err.code) {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.pull(opts).then(function(data) {
 | 
				
			||||||
 | 
					                res.status(204).end();
 | 
				
			||||||
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Abort an ongoing merge
 | 
					        // Abort an ongoing merge
 | 
				
			||||||
        app.delete("/:id/merge", needsPermission("projects.write"), function(req, res) {
 | 
					        app.delete("/:id/merge", needsPermission("projects.write"), function(req, res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            runtime.storage.projects.abortMerge(req.user, projectName).then(function(data) {
 | 
					                user: req.user,
 | 
				
			||||||
                res.status(204).end();
 | 
					                id: req.params.id
 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(function(err) {
 | 
					 | 
				
			||||||
                console.log(err.stack);
 | 
					 | 
				
			||||||
                if (err.code) {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.abortMerge(opts).then(function() {
 | 
				
			||||||
 | 
					                res.status(204).end();
 | 
				
			||||||
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Resolve a merge
 | 
					        // Resolve a merge
 | 
				
			||||||
        app.post("/:id/resolve/*", needsPermission("projects.write"), function(req, res) {
 | 
					        app.post("/:id/resolve/*", needsPermission("projects.write"), function(req, res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            var file = req.params[0];
 | 
					                user: req.user,
 | 
				
			||||||
            var resolution = req.body.resolutions;
 | 
					                id: req.params.id,
 | 
				
			||||||
            runtime.storage.projects.resolveMerge(req.user, projectName,file,resolution).then(function(data) {
 | 
					                path: req.params[0],
 | 
				
			||||||
                res.status(204).end();
 | 
					                resolution: req.body.resolutions
 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(function(err) {
 | 
					 | 
				
			||||||
                console.log(err.stack);
 | 
					 | 
				
			||||||
                if (err.code) {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.resolveMerge(opts).then(function() {
 | 
				
			||||||
 | 
					                res.status(204).end();
 | 
				
			||||||
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Get a list of local branches
 | 
					        // Get a list of local branches
 | 
				
			||||||
        app.get("/:id/branches", needsPermission("projects.read"), function(req, res) {
 | 
					        app.get("/:id/branches", needsPermission("projects.read"), function(req, res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            runtime.storage.projects.getBranches(req.user, projectName,false).then(function(data) {
 | 
					                user: req.user,
 | 
				
			||||||
                res.json(data);
 | 
					                id: req.params.id,
 | 
				
			||||||
            })
 | 
					                remote: false
 | 
				
			||||||
            .catch(function(err) {
 | 
					 | 
				
			||||||
                console.log(err.stack);
 | 
					 | 
				
			||||||
                if (err.code) {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.getBranches(opts).then(function(data) {
 | 
				
			||||||
 | 
					                res.json(data);
 | 
				
			||||||
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Delete a local branch - ?force=true
 | 
					        // Delete a local branch - ?force=true
 | 
				
			||||||
        app.delete("/:id/branches/:branchName", needsPermission("projects.write"), function(req, res) {
 | 
					        app.delete("/:id/branches/:branchName", needsPermission("projects.write"), function(req, res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            var branchName = req.params.branchName;
 | 
					                user: req.user,
 | 
				
			||||||
            var force = !!req.query.force;
 | 
					                id: req.params.id,
 | 
				
			||||||
            runtime.storage.projects.deleteBranch(req.user, projectName, branchName, false, force).then(function(data) {
 | 
					                branch: req.params.branchName,
 | 
				
			||||||
                res.status(204).end();
 | 
					                force: !!req.query.force
 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(function(err) {
 | 
					 | 
				
			||||||
                if (err.code) {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            });
 | 
					            runtimeAPI.projects.deleteBranch(opts).then(function(data) {
 | 
				
			||||||
 | 
					                res.status(204).end();
 | 
				
			||||||
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Get a list of remote branches
 | 
					        // Get a list of remote branches
 | 
				
			||||||
        app.get("/:id/branches/remote", needsPermission("projects.read"), function(req, res) {
 | 
					        app.get("/:id/branches/remote", needsPermission("projects.read"), function(req, res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            runtime.storage.projects.getBranches(req.user, projectName,true).then(function(data) {
 | 
					                user: req.user,
 | 
				
			||||||
                res.json(data);
 | 
					                id: req.params.id,
 | 
				
			||||||
            })
 | 
					                remote: true
 | 
				
			||||||
            .catch(function(err) {
 | 
					 | 
				
			||||||
                console.log(err);
 | 
					 | 
				
			||||||
                if (err.code) {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message, remote: err.remote});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.getBranches(opts).then(function(data) {
 | 
				
			||||||
 | 
					                res.json(data);
 | 
				
			||||||
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Get branch status - commit counts/ahead/behind
 | 
					        // Get branch status - commit counts/ahead/behind
 | 
				
			||||||
        app.get("/:id/branches/remote/*/status", needsPermission("projects.read"), function(req, res) {
 | 
					        app.get("/:id/branches/remote/*/status", needsPermission("projects.read"), function(req, res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            var branch = req.params[0];
 | 
					                user: req.user,
 | 
				
			||||||
            runtime.storage.projects.getBranchStatus(req.user, projectName,branch).then(function(data) {
 | 
					                id: req.params.id,
 | 
				
			||||||
                res.json(data);
 | 
					                branch: req.params[0]
 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(function(err) {
 | 
					 | 
				
			||||||
                console.log(err.stack);
 | 
					 | 
				
			||||||
                if (err.code) {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.getBranchStatus(opts).then(function(data) {
 | 
				
			||||||
 | 
					                res.json(data);
 | 
				
			||||||
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Set the active local branch
 | 
					        // Set the active local branch
 | 
				
			||||||
        app.post("/:id/branches", needsPermission("projects.write"), function(req, res) {
 | 
					        app.post("/:id/branches", needsPermission("projects.write"), function(req, res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            var branchName = req.body.name;
 | 
					                user: req.user,
 | 
				
			||||||
            var isCreate = req.body.create;
 | 
					                id: req.params.id,
 | 
				
			||||||
            runtime.storage.projects.setBranch(req.user, projectName,branchName,isCreate).then(function(data) {
 | 
					                branch: req.body.name,
 | 
				
			||||||
                res.json(data);
 | 
					                create: req.body.create
 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(function(err) {
 | 
					 | 
				
			||||||
                console.log(err.stack);
 | 
					 | 
				
			||||||
                if (err.code) {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.setBranch(opts).then(function(data) {
 | 
				
			||||||
 | 
					                res.json(data);
 | 
				
			||||||
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Get a list of remotes
 | 
					        // Get a list of remotes
 | 
				
			||||||
        app.get("/:id/remotes", needsPermission("projects.read"), function(req, res) {
 | 
					        app.get("/:id/remotes", needsPermission("projects.read"), function(req, res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            runtime.storage.projects.getRemotes(req.user, projectName).then(function(data) {
 | 
					                user: req.user,
 | 
				
			||||||
                res.json(data);
 | 
					                id: req.params.id
 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(function(err) {
 | 
					 | 
				
			||||||
                console.log(err.stack);
 | 
					 | 
				
			||||||
                if (err.code) {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            runtimeAPI.projects.getRemotes(opts).then(function(data) {
 | 
				
			||||||
 | 
					                res.json(data);
 | 
				
			||||||
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Add a remote
 | 
					        // Add a remote
 | 
				
			||||||
        app.post("/:id/remotes", needsPermission("projects.write"), function(req,res) {
 | 
					        app.post("/:id/remotes", needsPermission("projects.write"), function(req,res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
 | 
					                user: req.user,
 | 
				
			||||||
 | 
					                id: req.params.id,
 | 
				
			||||||
 | 
					                remote: req.body
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            if (/^https?:\/\/[^/]+@/i.test(req.body.url)) {
 | 
					            if (/^https?:\/\/[^/]+@/i.test(req.body.url)) {
 | 
				
			||||||
                res.status(400).json({error:"unexpected_error", message:"Git http url must not include username/password"});
 | 
					                res.status(400).json({error:"unexpected_error", message:"Git http url must not include username/password"});
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            runtime.storage.projects.addRemote(req.user, projectName, req.body).then(function() {
 | 
					            runtimeAPI.projects.addRemote(opts).then(function(data) {
 | 
				
			||||||
                res.redirect(303,req.baseUrl+"/"+projectName+"/remotes");
 | 
					                res.redirect(303,req.baseUrl+"/"+opts.id+"/remotes");
 | 
				
			||||||
            }).catch(function(err) {
 | 
					            }).catch(function(err) {
 | 
				
			||||||
                console.log(err.stack);
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
                if (err.code) {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Delete a remote
 | 
					        // Delete a remote
 | 
				
			||||||
        app.delete("/:id/remotes/:remoteName", needsPermission("projects.write"), function(req, res) {
 | 
					        app.delete("/:id/remotes/:remoteName", needsPermission("projects.write"), function(req, res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var opts = {
 | 
				
			||||||
            var remoteName = req.params.remoteName;
 | 
					                user: req.user,
 | 
				
			||||||
            runtime.storage.projects.removeRemote(req.user, projectName, remoteName).then(function(data) {
 | 
					                id: req.params.id,
 | 
				
			||||||
                res.redirect(303,req.baseUrl+"/"+projectName+"/remotes");
 | 
					                remote: req.params.remoteName
 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(function(err) {
 | 
					 | 
				
			||||||
                if (err.code) {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            });
 | 
					            runtimeAPI.projects.removeRemote(opts).then(function(data) {
 | 
				
			||||||
 | 
					                res.redirect(303,req.baseUrl+"/"+opts.id+"/remotes");
 | 
				
			||||||
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Update a remote
 | 
					        // Update a remote
 | 
				
			||||||
        app.put("/:id/remotes/:remoteName", needsPermission("projects.write"), function(req,res) {
 | 
					        app.put("/:id/remotes/:remoteName", needsPermission("projects.write"), function(req,res) {
 | 
				
			||||||
            var projectName = req.params.id;
 | 
					            var remote = req.body || {};
 | 
				
			||||||
            var remoteName = req.params.remoteName;
 | 
					            remote.name = req.params.remoteName;
 | 
				
			||||||
            runtime.storage.projects.updateRemote(req.user, projectName, remoteName, req.body).then(function(data) {
 | 
					            var opts = {
 | 
				
			||||||
                res.status(204).end();
 | 
					                user: req.user,
 | 
				
			||||||
            })
 | 
					                id: req.params.id,
 | 
				
			||||||
            .catch(function(err) {
 | 
					                remote: remote
 | 
				
			||||||
                if (err.code) {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:err.code, message: err.message});
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    res.status(400).json({error:"unexpected_error", message:err.toString()});
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            });
 | 
					            runtimeAPI.projects.updateRemote(opts).then(function() {
 | 
				
			||||||
 | 
					                res.status(204).end();
 | 
				
			||||||
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 | 
					                apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return app;
 | 
					        return app;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -77,11 +77,8 @@ function serveFilesFromTheme(themeValue, themeApp, directory) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
    init: function(settings,version) {
 | 
					    init: function(settings) {
 | 
				
			||||||
        themeContext = clone(defaultContext);
 | 
					        themeContext = clone(defaultContext);
 | 
				
			||||||
        if (version) {
 | 
					 | 
				
			||||||
            themeContext.version = version;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        themeSettings = null;
 | 
					        themeSettings = null;
 | 
				
			||||||
        theme = settings.editorTheme || {};
 | 
					        theme = settings.editorTheme || {};
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,17 +17,20 @@ var express = require('express');
 | 
				
			|||||||
var fs = require("fs");
 | 
					var fs = require("fs");
 | 
				
			||||||
var path = require("path");
 | 
					var path = require("path");
 | 
				
			||||||
var Mustache = require("mustache");
 | 
					var Mustache = require("mustache");
 | 
				
			||||||
 | 
					var mime = require("mime");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var apiUtils = require("../util");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var theme = require("./theme");
 | 
					var theme = require("./theme");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var redNodes;
 | 
					var runtimeAPI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var templateDir = path.resolve(__dirname+"/../../../editor/templates");
 | 
					var templateDir = path.resolve(__dirname+"/../../../editor/templates");
 | 
				
			||||||
var editorTemplate;
 | 
					var editorTemplate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
    init: function(runtime) {
 | 
					    init: function(_runtimeAPI) {
 | 
				
			||||||
        redNodes = runtime.nodes;
 | 
					        runtimeAPI = _runtimeAPI;
 | 
				
			||||||
        editorTemplate = fs.readFileSync(path.join(templateDir,"index.mst"),"utf8");
 | 
					        editorTemplate = fs.readFileSync(path.join(templateDir,"index.mst"),"utf8");
 | 
				
			||||||
        Mustache.parse(editorTemplate);
 | 
					        Mustache.parse(editorTemplate);
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@@ -46,8 +49,18 @@ module.exports = {
 | 
				
			|||||||
        var icon = req.params.icon;
 | 
					        var icon = req.params.icon;
 | 
				
			||||||
        var scope = req.params.scope;
 | 
					        var scope = req.params.scope;
 | 
				
			||||||
        var module = scope ? scope + '/' +  req.params.module : req.params.module;
 | 
					        var module = scope ? scope + '/' +  req.params.module : req.params.module;
 | 
				
			||||||
        var iconPath = redNodes.getNodeIconPath(module,icon);
 | 
					        var opts = {
 | 
				
			||||||
        res.sendFile(iconPath);
 | 
					            user: req.user,
 | 
				
			||||||
 | 
					            module: module,
 | 
				
			||||||
 | 
					            icon: icon
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        runtimeAPI.nodes.getIcon(opts).then(function(data) {
 | 
				
			||||||
 | 
					            var contentType = mime.lookup(icon);
 | 
				
			||||||
 | 
					            res.set("Content-Type", contentType);
 | 
				
			||||||
 | 
					            res.send(data);
 | 
				
			||||||
 | 
					        }).catch(function(err) {
 | 
				
			||||||
 | 
					            apiUtils.rejectHandler(req,res,err);
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    editor: function(req,res) {
 | 
					    editor: function(req,res) {
 | 
				
			||||||
        res.send(Mustache.render(editorTemplate,theme.context()));
 | 
					        res.send(Mustache.render(editorTemplate,theme.context()));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,44 +21,30 @@
 | 
				
			|||||||
  * @type {object}
 | 
					  * @type {object}
 | 
				
			||||||
  */
 | 
					  */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var runtime;
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @namespace RED
 | 
					 * @namespace RED
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
var api = module.exports = {
 | 
					var api = module.exports = {
 | 
				
			||||||
    init: function(runtime, redUtil) {
 | 
					    init: function(_runtime, redUtil) {
 | 
				
			||||||
 | 
					        runtime = _runtime;
 | 
				
			||||||
        api.flows.init(runtime);
 | 
					        api.flows.init(runtime);
 | 
				
			||||||
        api.nodes.init(runtime);
 | 
					        api.nodes.init(runtime);
 | 
				
			||||||
        api.settings.init(runtime);
 | 
					        api.settings.init(runtime);
 | 
				
			||||||
        api.library.init(runtime);
 | 
					        api.library.init(runtime);
 | 
				
			||||||
 | 
					        api.projects.init(runtime);
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
    * Auth module
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
    auth: require("./auth"),
 | 
					    auth: require("./auth"),
 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
    * Comms module
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
    comms: require("./comms"),
 | 
					    comms: require("./comms"),
 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
    * Flows module
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
    flows: require("./flows"),
 | 
					    flows: require("./flows"),
 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
    * Library module
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
    library: require("./library"),
 | 
					    library: require("./library"),
 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
    * Nodes module
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
    nodes: require("./nodes"),
 | 
					    nodes: require("./nodes"),
 | 
				
			||||||
 | 
					    settings: require("./settings"),
 | 
				
			||||||
 | 
					    projects: require("./projects"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					
 | 
				
			||||||
    * Settings module
 | 
					    version: function(opts) {
 | 
				
			||||||
    */
 | 
					        return Promise.resolve(runtime.version());
 | 
				
			||||||
    settings: require("./settings")
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,8 @@
 | 
				
			|||||||
 * @namespace RED.nodes
 | 
					 * @namespace RED.nodes
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var fs = require("fs");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var runtime;
 | 
					var runtime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function putNode(node, enabled) {
 | 
					function putNode(node, enabled) {
 | 
				
			||||||
@@ -371,7 +373,24 @@ var api = module.exports = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    * TODO: getIcon
 | 
					    * Gets a node icon
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.module - the id of the module requesting the icon
 | 
				
			||||||
 | 
					    * @param {String} opts.icon - the name of the icon
 | 
				
			||||||
 | 
					    * @return {Promise<Buffer>} - the icon file as a Buffer
 | 
				
			||||||
 | 
					    * @memberof RED.nodes
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
    getIcon: function() {}
 | 
					    getIcon: function(opts) {
 | 
				
			||||||
 | 
					        return new Promise(function(resolve,reject) {
 | 
				
			||||||
 | 
					            var iconPath = runtime.nodes.getNodeIconPath(opts.module,opts.icon);
 | 
				
			||||||
 | 
					            fs.readFile(iconPath,function(err,data) {
 | 
				
			||||||
 | 
					                if (err) {
 | 
				
			||||||
 | 
					                    err.status = 400;
 | 
				
			||||||
 | 
					                    return reject(err);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return resolve(data)
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										441
									
								
								red/runtime-api/projects.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										441
									
								
								red/runtime-api/projects.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,441 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Copyright JS Foundation and other contributors, http://js.foundation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 **/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @namespace RED.projects
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var runtime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var api = module.exports = {
 | 
				
			||||||
 | 
					    init: function(_runtime) {
 | 
				
			||||||
 | 
					        runtime = _runtime;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    available: function(opts) {
 | 
				
			||||||
 | 
					        return Promise.resolve(!!runtime.storage.projects);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * List projects known to the runtime
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    listProjects: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.listProjects(opts.user).then(function(list) {
 | 
				
			||||||
 | 
					            var active = runtime.storage.projects.getActiveProject(opts.user);
 | 
				
			||||||
 | 
					            var response = {
 | 
				
			||||||
 | 
					                projects: list
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            if (active) {
 | 
				
			||||||
 | 
					                response.active = active.name;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return response;
 | 
				
			||||||
 | 
					        }).catch(function(err) {
 | 
				
			||||||
 | 
					            err.status = 400;
 | 
				
			||||||
 | 
					            throw err;
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Create a new project
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {Object} opts.project - the project information
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    createProject: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.createProject(opts.user, opts.project)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Initialises an empty project
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project to initialise
 | 
				
			||||||
 | 
					    * @param {Object} opts.project - the project information
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    initialiseProject: function(opts) {
 | 
				
			||||||
 | 
					        // Initialised set when creating default files for an empty repo
 | 
				
			||||||
 | 
					        return runtime.storage.projects.initialiseProject(opts.user, opts.id, opts.project)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Gets the active project
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - the active project
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getActiveProject: function(opts) {
 | 
				
			||||||
 | 
					        return Promise.resolve(runtime.storage.projects.getActiveProject(opts.user));
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    *
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project to activate
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    setActiveProject: function(opts) {
 | 
				
			||||||
 | 
					        var currentProject = runtime.storage.projects.getActiveProject(opts.user);
 | 
				
			||||||
 | 
					        if (!currentProject || opts.id !== currentProject.name) {
 | 
				
			||||||
 | 
					            return runtime.storage.projects.setActiveProject(opts.user, opts.id);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return Promise.resolve();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Gets a projects metadata
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project to get
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - the project metadata
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getProject: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.getProject(opts.user, opts.id)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Updates the metadata of an existing project
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project to update
 | 
				
			||||||
 | 
					    * @param {Object} opts.project - the project information
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    updateProject: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.updateProject(opts.user, opts.id, opts.project);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Deletes a project
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project to update
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    deleteProject: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.deleteProject(opts.user, opts.id);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Gets current git status of a project
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {Boolean} opts.remote - whether to include status of remote repos
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - the project status
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getStatus: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.getStatus(opts.user, opts.id, opts.remote)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Get a list of local branches
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {Boolean} opts.remote - whether to return remote branches (true) or local (false)
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - a list of the local branches
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getBranches: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.getBranches(opts.user, opts.id, opts.remote);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Gets the status of a branch
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {String} opts.branch - the name of the branch
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - the status of the branch
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getBranchStatus: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.getBranchStatus(opts.user, opts.id, opts.branch);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Sets the current local branch
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {String} opts.branch - the name of the branch
 | 
				
			||||||
 | 
					    * @param {Boolean} opts.create - whether to create the branch if it doesn't exist
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    setBranch: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.setBranch(opts.user, opts.id, opts.branch, opts.create)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Deletes a branch
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {String} opts.branch - the name of the branch
 | 
				
			||||||
 | 
					    * @param {Boolean} opts.force - whether to force delete
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    deleteBranch: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.deleteBranch(opts.user, opts.id, opts.branch, false, opts.force);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Commits the current staged files
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {String} opts.message - the message to associate with the commit
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    commit: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.commit(opts.user, opts.id,{message: opts.message});
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Gets the details of a single commit
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {String} opts.sha - the sha of the commit to return
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - the commit details
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getCommit: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.getCommit(opts.user, opts.id, opts.sha);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Gets the commit history of the project
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {String} opts.limit - limit how many to return
 | 
				
			||||||
 | 
					    * @param {String} opts.before - id of the commit to work back from
 | 
				
			||||||
 | 
					    * @return {Promise<Array>} - an array of commits
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getCommits: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.getCommits(opts.user, opts.id, {
 | 
				
			||||||
 | 
					            limit: opts.limit || 20,
 | 
				
			||||||
 | 
					            before: opts.before
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Abort an in-progress merge
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    abortMerge: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.abortMerge(opts.user, opts.id);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Resolves a merge conflict
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {String} opts.path - the path of the file being merged
 | 
				
			||||||
 | 
					    * @param {String} opts.resolutions - how to resolve the merge conflict
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    resolveMerge: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.resolveMerge(opts.user, opts.id, opts.path, opts.resolution);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Gets a listing of the files in the project
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - the file listing
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getFiles: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.getFiles(opts.user, opts.id);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Gets the contents of a file
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {String} opts.path - the path of the file
 | 
				
			||||||
 | 
					    * @param {String} opts.tree - the version control tree to use
 | 
				
			||||||
 | 
					    * @return {Promise<String>} - the content of the file
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getFile: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.getFile(opts.user, opts.id,opts.path,opts.tree);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    *
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {String|Array} opts.path - the path of the file, or an array of paths
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    stageFile: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.stageFile(opts.user, opts.id, opts.path);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    *
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {String} opts.path - the path of the file. If not set, all staged files are unstaged
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    unstageFile: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.unstageFile(opts.user, opts.id, opts.path);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Reverts changes to a file back to its commited version
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {String} opts.path - the path of the file
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    revertFile: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.revertFile(opts.user, opts.id,opts.path)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Get the diff of a file
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {String} opts.path - the path of the file
 | 
				
			||||||
 | 
					    * @param {String} opts.type - the type of diff
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - the requested diff
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getFileDiff: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.getFileDiff(opts.user, opts.id, opts.path, opts.type);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Gets a list of the project remotes
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - a list of project remotes
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getRemotes: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.getRemotes(opts.user, opts.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    *
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {Object} opts.remote - the remote metadata
 | 
				
			||||||
 | 
					    * @param {String} opts.remote.name - the name of the remote
 | 
				
			||||||
 | 
					    * @param {String} opts.remote.url - the url of the remote
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    addRemote: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.addRemote(opts.user, opts.id, opts.remote)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Remove a project remote
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {String} opts.remote - the name of the remote
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    removeRemote: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.removeRemote(opts.user, opts.id, opts.remote);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    *
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {Object} opts.remote - the remote metadata
 | 
				
			||||||
 | 
					    * @param {String} opts.remote.name - the name of the remote
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    updateRemote: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.updateRemote(opts.user, opts.id, opts.remote.name, opts.remote)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Pull changes from the remote
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    pull: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.pull(opts.user, opts.id, opts.remote, opts.track, opts.allowUnrelatedHistories);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Push changes to a remote
 | 
				
			||||||
 | 
					    * @param {Object} opts
 | 
				
			||||||
 | 
					    * @param {User} opts.user - the user calling the api
 | 
				
			||||||
 | 
					    * @param {String} opts.id - the id of the project
 | 
				
			||||||
 | 
					    * @param {String} opts.remote - the name of the remote
 | 
				
			||||||
 | 
					    * @param {String} opts.track - whether to set the remote as the upstream
 | 
				
			||||||
 | 
					    * @return {Promise<Object>} - resolves when complete
 | 
				
			||||||
 | 
					    * @memberof RED.projects
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    push: function(opts) {
 | 
				
			||||||
 | 
					        return runtime.storage.projects.push(opts.user, opts.id, opts.remote, opts.track);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -45,7 +45,7 @@ function extend(target, source) {
 | 
				
			|||||||
    return target;
 | 
					    return target;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getUsername(userObj) {
 | 
					function getSSHKeyUsername(userObj) {
 | 
				
			||||||
    var username = '__default';
 | 
					    var username = '__default';
 | 
				
			||||||
    if ( userObj && userObj.name ) {
 | 
					    if ( userObj && userObj.name ) {
 | 
				
			||||||
        username = userObj.name;
 | 
					        username = userObj.name;
 | 
				
			||||||
@@ -173,7 +173,7 @@ var api = module.exports = {
 | 
				
			|||||||
    */
 | 
					    */
 | 
				
			||||||
    getUserKeys: function(opts) {
 | 
					    getUserKeys: function(opts) {
 | 
				
			||||||
        return new Promise(function(resolve,reject) {
 | 
					        return new Promise(function(resolve,reject) {
 | 
				
			||||||
            var username = getUsername(opts.user);
 | 
					            var username = getSSHKeyUsername(opts.user);
 | 
				
			||||||
            runtime.storage.projects.ssh.listSSHKeys(username).then(function(list) {
 | 
					            runtime.storage.projects.ssh.listSSHKeys(username).then(function(list) {
 | 
				
			||||||
                return resolve(list);
 | 
					                return resolve(list);
 | 
				
			||||||
            }).catch(function(err) {
 | 
					            }).catch(function(err) {
 | 
				
			||||||
@@ -193,7 +193,7 @@ var api = module.exports = {
 | 
				
			|||||||
    */
 | 
					    */
 | 
				
			||||||
    getUserKey: function(opts) {
 | 
					    getUserKey: function(opts) {
 | 
				
			||||||
        return new Promise(function(resolve,reject) {
 | 
					        return new Promise(function(resolve,reject) {
 | 
				
			||||||
            var username = getUsername(opts.user);
 | 
					            var username = getSSHKeyUsername(opts.user);
 | 
				
			||||||
            // console.log('username:', username);
 | 
					            // console.log('username:', username);
 | 
				
			||||||
            runtime.storage.projects.ssh.getSSHKey(username, opts.id).then(function(data) {
 | 
					            runtime.storage.projects.ssh.getSSHKey(username, opts.id).then(function(data) {
 | 
				
			||||||
                if (data) {
 | 
					                if (data) {
 | 
				
			||||||
@@ -224,7 +224,7 @@ var api = module.exports = {
 | 
				
			|||||||
    */
 | 
					    */
 | 
				
			||||||
    generateUserKey: function(opts) {
 | 
					    generateUserKey: function(opts) {
 | 
				
			||||||
        return new Promise(function(resolve,reject) {
 | 
					        return new Promise(function(resolve,reject) {
 | 
				
			||||||
            var username = getUsername(opts.user);
 | 
					            var username = getSSHKeyUsername(opts.user);
 | 
				
			||||||
            runtime.storage.projects.ssh.generateSSHKey(username, opts).then(function(name) {
 | 
					            runtime.storage.projects.ssh.generateSSHKey(username, opts).then(function(name) {
 | 
				
			||||||
                return resolve(name);
 | 
					                return resolve(name);
 | 
				
			||||||
            }).catch(function(err) {
 | 
					            }).catch(function(err) {
 | 
				
			||||||
@@ -244,7 +244,7 @@ var api = module.exports = {
 | 
				
			|||||||
    */
 | 
					    */
 | 
				
			||||||
    removeUserKey: function(opts) {
 | 
					    removeUserKey: function(opts) {
 | 
				
			||||||
        return new Promise(function(resolve,reject) {
 | 
					        return new Promise(function(resolve,reject) {
 | 
				
			||||||
            var username = getUsername(req.user);
 | 
					            var username = getSSHKeyUsername(req.user);
 | 
				
			||||||
            runtime.storage.projects.ssh.deleteSSHKey(username, opts.id).then(function() {
 | 
					            runtime.storage.projects.ssh.deleteSSHKey(username, opts.id).then(function() {
 | 
				
			||||||
                return resolve();
 | 
					                return resolve();
 | 
				
			||||||
            }).catch(function(err) {
 | 
					            }).catch(function(err) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -615,6 +615,9 @@ function nodeIconDir(dir) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getNodeIconPath(module,icon) {
 | 
					function getNodeIconPath(module,icon) {
 | 
				
			||||||
 | 
					    if (/\.\./.test(icon)) {
 | 
				
			||||||
 | 
					        throw new Error();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    var iconName = module+"/"+icon;
 | 
					    var iconName = module+"/"+icon;
 | 
				
			||||||
    if (iconCache[iconName]) {
 | 
					    if (iconCache[iconName]) {
 | 
				
			||||||
        return iconCache[iconName];
 | 
					        return iconCache[iconName];
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user