diff options
author | Richard Ipsum <richard.ipsum@codethink.co.uk> | 2014-01-08 16:46:43 +0000 |
---|---|---|
committer | Richard Ipsum <richard.ipsum@codethink.co.uk> | 2014-01-23 17:18:41 +0000 |
commit | 0d4a9b22594a3973b1d54a51d9c123671af5a503 (patch) | |
tree | c37c658d67f68fb08b66165bfd4cab9908d150fe | |
parent | 989779be747661660aad655befa2d77ad14a6430 (diff) | |
download | gitano-0d4a9b22594a3973b1d54a51d9c123671af5a503.tar.gz |
Add the seed of our cgi script
-rwxr-xr-x | cgi/command.cgi | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/cgi/command.cgi b/cgi/command.cgi new file mode 100755 index 0000000..041d6ca --- /dev/null +++ b/cgi/command.cgi @@ -0,0 +1,204 @@ +#!/usr/bin/lua5.1 + +print "Content-type:text/plain\r\n\r\n" +io.flush() +os.execute("env") +print "\n" + +local function run_command(user) + -- we may need to do some kind of input validation on the query string + local query_string = os.getenv("QUERY_STRING") + + --local cmdline = query_string + + local _, e = string.find(query_string, "cmd=") + + local cmdline = string.sub(query_string, e + 1, #query_string) -- select command from query string + + print("cmdline: " .. cmdline) + print("package.path: " .. package.path .. '\n') + + local gitano = require "gitano" + local gall = require "gall" + local luxio = require "luxio" + local sio = require "luxio.simple" + local sp = require "luxio.subprocess" + + gitano.config.lib_bin_path("/usr/lib/gitano/bin") + gitano.config.share_path("/usr/share/gitano") + + -- local repo_root, username, keytag = "..." + -- fake this for now + local repo_root = "/home/git/repos" + local username = user + local keytag = "default" + + gitano.config.repo_path(repo_root) + + gitano.log.set_source("http") + + local transactionid = gitano.log.syslog.open() + + if cmdline:match("^[ \t\n]*$") then + gitano.log.fatal("cmdline: " .. cmdline) + gitano.log.fatal("No command provided, cannot continue") + end + + local parsed_cmdline, warnings = gitano.util.parse_cmdline(cmdline) + + local start_log_level = gitano.log.get_level() + -- Clamp level at info until we have checked if the caller + -- is an admin or not + gitano.log.cap_level(gitano.log.level.INFO) + + if (#warnings > 0) then + gitano.log.error("Warnings encountered parsing commandline."); + gitano.log.warn("\t" .. cmdline) + gitano.log.warn("") + gitano.log.warn("Parsed as:") + for i = 1, #parsed_cmdline do + gitano.log.warn((" =[%2d]> %s"):format(i, parsed_cmdline[i])) + end + gitano.log.warn("\nWarnings were:") + for i = 1, #warnings do + gitano.log.warn(" * " .. warnings[i]) + end + gitano.log.warn("") + gitano.log.fatal("Game over, sorry\n") + end + + -- Now load the administration data + + local admin_repo = gall.repository.new((repo_root or "") .. "/gitano-admin.git") + + if not admin_repo then + gitano.log.fatal("Unable to locate administration repository. Cannot continue"); + end + + local admin_head = admin_repo:get(admin_repo.HEAD) + + if not admin_head then + gitano.log.fatal("Unable to find the HEAD of the administration repository. Cannot continue"); + end + + local config, msg = gitano.config.parse(admin_head) + + if not config then + gitano.log.critical("Unable to parse administration repository.") + gitano.log.critical(" * " .. (msg or "No error?")) + gitano.log.fatal("Cannot continue") + end + + -- Now, are we an admin? + if config.groups["gitano-admin"].filtered_members[username] then + -- Yep, so blithely reset logging level + gitano.log.set_level(start_log_level) + end + + if not config.global.silent then + -- Not silent, bump to chatty level automatically + gitano.log.bump_level(gitano.log.level.CHAT) + end + + local repo + + -- Find the command + + + -- ip = string.match(luxio.getenv "SSH_CLIENT", "^[^ ]+") or "" + + gitano.log.syslog.info("Client connected from", ip, "as", username, + "(" .. keytag .. ")", "Executing command:", + cmdline) + + local cmd = gitano.command.get(parsed_cmdline[1]) + + if not cmd then + gitano.log.fatal("Unknown command: " .. parsed_cmdline[1]) + end + + if cmd.takes_repo and #parsed_cmdline > 1 then + -- Acquire the repository object for the target repo + local msg + repo, msg = gitano.repository.find(config, parsed_cmdline[2]) + if not repo then + gitano.log.critical("Unable to locate repository.") + gitano.log.critical(" * " .. (tostring(msg))) + gitano.log.fatal("Cannot continue") + end + + if repo.is_nascent then + gitano.log.info("Repository " .. repo.name .. " is nascent") + end + end + + -- Validate the commandline, massaging it as necessary. + + if not cmd.validate(config, repo, parsed_cmdline) then + gitano.log.fatal("Validation of command line failed") + end + + -- Construct our context ready for prep + local context = { + source = "ssh", + user = user, + keytag = keytag, + } + + local action, reason = cmd.prep(config, repo, parsed_cmdline, context) + + if not action then + gitano.log.crit(reason) + gitano.log.fatal("Ruleset did not complete cleanly") + end + + if action == "allow" then + gitano.log.info(reason or "Ruleset permitted action") + else + gitano.log.critical(reason) + gitano.log.fatal("Ruleset denied action. Sorry.") + end + + gitano.log.debug("Welcome to " .. config.global.site_name) + gitano.log.debug("Running:") + for i = 1, #parsed_cmdline do + gitano.log.debug(" => " .. parsed_cmdline[i]) + end + gitano.log.debug("") + gitano.log.debug("On behalf of " .. username .. " using key " .. keytag) + + -- Set up some useful environment variables + + local env = { + ["GITANO_ROOT"] = repo_root, + ["GITANO_USER"] = username, + ["GITANO_KEYTAG"] = keytag, + ["GITANO_PROJECT"] = (repo or {}).name, + ["GITANO_SOURCE"] = "ssh", + ["GITANO_TRANSACTION_ID"] = transactionid, + } + + local how, why = cmd.run(config, repo, parsed_cmdline, env) + + if how ~= "exit" or why ~= 0 then + gitano.log.critical("Error running sub-process:", + ("%s (%d)"):format(how, why)) + gitano.log.fatal("Unable to continue") + else + gitano.log.syslog.info(cmdline, "completed successfully") + end + + gitano.log.syslog.close() + + print(gitano.log.get_stream()) +end + +local authenticated_user = os.getenv("REMOTE_USER") + +if authenticated_user then + run_command(authenticated_user) +else + -- ask the browser to authenticate + print "Status:401 Unauthorized" + print "WWW-Authenticate: Basic realm=\"foorealm\"\r\n\r\n" +end |