2022-03-03 10:09:18 (UTC-03:00)
Marcel Rodrigues <marcelgmr@gmail.com>
make app modular
diff --git a/app.lua b/app.lua deleted file mode 100644 index 4ef6f96..0000000 --- a/app.lua +++ /dev/null @@ -1,241 +0,0 @@ -local git = require "git" -local scan = require "scan" -local hash = require "hash" - -local lud = require "ludweb" - -local function time_fmt(sig) - local s = os.date("%Y-%m-%d %H:%M:%S", sig.time_) - local offset = sig.offset - local sign - if offset < 0 then - offset = -offset - sign = "-" - else - sign = "+" - end - local hours = math.floor(offset / 60) - local mins = offset % 60 - s = s .. (" (UTC%s%02d:%02d)"):format(sign, hours, mins) - return s -end - -local function diff_cb(line_type, line) - line = lud.template.escape(line:sub(1, #line-1)) - if line_type == " " then - line = ' <span class="diff_ctx">' .. line .. '</span>' - elseif line_type == "+" then - line = '+<span class="diff_add">' .. line .. '</span>' - elseif line_type == "-" then - line = '-<span class="diff_del">' .. line .. '</span>' - elseif line_type == "=" then - line = ' <span class="diff_nonl diff_ctx_nonl">' .. line .. '</span>' - elseif line_type == ">" then - line = ' <span class="diff_nonl diff_old_nonl">' .. line .. '</span>' - elseif line_type == "<" then - line = ' <span class="diff_nonl diff_new_nonl">' .. line .. '</span>' - elseif line_type == "F" then - line = '\n<span class="diff_file_hdr">' .. line .. '</span>' - elseif line_type == "H" then - line = '<span class="diff_hunk_hdr">' .. line .. '</span>' - elseif line_type == "B" then - line = '<span class="diff_bin">' .. line .. '</span>' - else - line = line_type .. line - end - return line .. "\n" -end - -local function allowed(user, gname) - if gname == "public" then - return true - elseif user == nil then - return false - end - for _, ok in ipairs(user.groups) do - if gname == ok then - return true - end - end - return false -end - -local LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DEBUG = 0, 1, 2, 3 - -local path = arg[1] -local conf = dofile(path.."/conf.lua") -local title = conf.title - -git.init() -local groups = scan.scanrepos(path) - -local sessions = {} - -local function get_user(cookies) - local session_id = cookies["sid"] - if session_id == nil then - return nil - end - local uname = sessions[session_id] - if uname == nil then - return nil - end - return conf.users[uname] -end - -local routes = { - {"GET", "/?", - function (req) - local user = get_user(req.cookies) - local gnames = {} - groups = scan.scanrepos(path) - for gname in pairs(groups) do - if allowed(user, gname) then - table.insert(gnames, gname) - end - end - local env = {title=title, user=user, gnames=gnames} - return lud.template.render_file("view/home.html", env) - end}, - {"GET", "/login", - function (req) - local user = get_user(req.cookies) - if user ~= nil then -- already logged in - return "/", 303 - else - return lud.template.render_file("view/login.html", {title=title}) - end - end}, - {"POST", "/login", - function (req) - local uname = req.form.username - local pass = req.form.password - local user = conf.users[uname] - local salt, h - if user == nil then - -- hash something as if we're trying to login anyway - salt = hash.get_salt() - h = hash.hash_pass(pass, salt) - conf.log(LOG_INFO, "invalid username") - else - salt = lud.crypt.b64_dec(user.salt) - h = hash.hash_pass(pass, salt) - if h == lud.crypt.b64_dec(user.hash) then - local session_id = lud.crypt.b64_enc(lud.crypt.uuid4()) - sessions[session_id] = uname - conf.log(LOG_INFO, "logged in as "..uname) - local age = conf.session_age - local cookie = {key="sid", val=session_id, path="/", age=age} - return "/", 303, "See Other", {cookie} - else - conf.log(LOG_INFO, "invalid password") - end - end - return "/login", 303 - end}, - {"GET", "/logout", - function (req) - local session_id = req.cookies["sid"] - if session_id ~= nil then - conf.log(LOG_INFO, "logged out as "..sessions[session_id]) - sessions[session_id] = nil - end - return "/", 303 - end}, - {"GET", "/group/([%w_-]+)", - function (req, gname) - local user = get_user(req.cookies) - if not allowed(user, gname) then - return "/login", 303 - end - local rnames = {} - for rname in pairs(groups[gname]) do - table.insert(rnames, rname) - end - local env = {title=title, user=user, gname=gname, rnames=rnames} - return lud.template.render_file("view/group.html", env) - end}, - {"GET", "/group/([%w_-]+)/repo/([%w_-]+)", - function (req, gname, rname) - local user = get_user(req.cookies) - if not allowed(user, gname) then - return "/login", 303 - end - local repo = groups[gname][rname] - local bnames = repo:branches() - local tnames = repo:tags() - local env = { - title=title, user=user, repo=repo, gname=gname, - rname=rname, bnames=bnames, tnames=tnames, - } - return lud.template.render_file("view/repo.html", env) - end}, - {"GET", "/group/([%w_-]+)/repo/([%w_-]+)/history/([%w_-]+)", - function (req, gname, rname, first) - local user = get_user(req.cookies) - if not allowed(user, gname) then - return "/login", 303 - end - local repo = groups[gname][rname] - local commit = repo:commit(first) - local prev = repo:find_prev(commit:id(), conf.limit) - local env = { - title=title, user=user, gname=gname, rname=rname, bname=bname, - commit=commit, limit=conf.limit, prev=prev, first=first, - } - return lud.template.render_file("view/history.html", env) - end}, - {"GET", "/group/([%w_-]+)/repo/([%w_-]+)/commit/([%w_-]+)", - function (req, gname, rname, cid) - local user = get_user(req.cookies) - if not allowed(user, gname) then - return "/login", 303 - end - local repo = groups[gname][rname] - local commit = repo:commit(cid) - local prev = repo:find_prev(commit:id(), 1) - local sig = commit:signature() - local time_str = time_fmt(sig) - local diff = repo:diff(commit, diff_cb) - local env = { - title=title, user=user, gname=gname, rname=rname, bname=bname, - commit=commit, time_str=time_str, sig=sig, cid=cid, prev=prev, diff=diff, - } - return lud.template.render_file("view/commit.html", env) - end}, - {"GET", "/group/([%w_-]+)/repo/([%w_-]+)/commit/([%w_-]+)/tree/(.*)", - function (req, gname, rname, cid, path) - local user = get_user(req.cookies) - if not allowed(user, gname) then - return "/login", 303 - end - local repo = groups[gname][rname] - local commit = repo:commit(cid) - local node = commit:tree_entry(path) - if node == nil then - return "File not found", 404, "Not found" - end - local parts = {} - for part in path:gmatch("[^/]+") do - table.insert(parts, part) - end - local base = req.path - if base:sub(#base) ~= "/" then - base = base .. "/" - end - local env = { - title=title, user=user, gname=gname, rname=rname, cid=cid, - path=path, base=base, parts=parts, node=node, - } - if node.type_ == "dir" then - return lud.template.render_file("view/dir.html", env) - elseif node.type_ == "file" then - return lud.template.render_file("view/file.html", env) - end - end}, -} - -conf.log(LOG_INFO, "server running on port "..conf.port) -lud.app.new_app(routes):run(conf.port) - -git.shutdown() diff --git a/cogit.lua b/cogit.lua new file mode 100644 index 0000000..344cd5a --- /dev/null +++ b/cogit.lua @@ -0,0 +1,275 @@ +local git = require "git" +local scan = require "scan" +local hash = require "hash" + +local lud = require "ludweb" + +local function time_fmt(sig) + local s = os.date("%Y-%m-%d %H:%M:%S", sig.time_) + local offset = sig.offset + local sign + if offset < 0 then + offset = -offset + sign = "-" + else + sign = "+" + end + local hours = math.floor(offset / 60) + local mins = offset % 60 + s = s .. (" (UTC%s%02d:%02d)"):format(sign, hours, mins) + return s +end + +local function diff_cb(line_type, line) + line = lud.template.escape(line:sub(1, #line-1)) + if line_type == " " then + line = ' <span class="diff_ctx">' .. line .. '</span>' + elseif line_type == "+" then + line = '+<span class="diff_add">' .. line .. '</span>' + elseif line_type == "-" then + line = '-<span class="diff_del">' .. line .. '</span>' + elseif line_type == "=" then + line = ' <span class="diff_nonl diff_ctx_nonl">' .. line .. '</span>' + elseif line_type == ">" then + line = ' <span class="diff_nonl diff_old_nonl">' .. line .. '</span>' + elseif line_type == "<" then + line = ' <span class="diff_nonl diff_new_nonl">' .. line .. '</span>' + elseif line_type == "F" then + line = '\n<span class="diff_file_hdr">' .. line .. '</span>' + elseif line_type == "H" then + line = '<span class="diff_hunk_hdr">' .. line .. '</span>' + elseif line_type == "B" then + line = '<span class="diff_bin">' .. line .. '</span>' + else + line = line_type .. line + end + return line .. "\n" +end + +local function allowed(user, gname) + if gname == "public" then + return true + elseif user == nil then + return false + end + for _, ok in ipairs(user.groups) do + if gname == ok then + return true + end + end + return false +end + +local LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DEBUG = 0, 1, 2, 3 + +local Cogit = {} +Cogit.__index = Cogit + +function Cogit:init() + if not self.initialized then + git.init() + self.initialized = true + end +end + +function Cogit:finish() + git.shutdown() + self.initialized = false +end + +local function get_user(cookies) + local session_id = cookies["sid"] + if session_id == nil then + return nil + end + local uname = sessions[session_id] + if uname == nil then + return nil + end + return conf.users[uname] +end + +function Cogit:run() + self:init() + self.conf.log(LOG_INFO, "server running on port "..self.conf.port) + self.app:run(self.conf.port) +end + +function Cogit:scan() + self.conf.log(LOG_INFO, "scanning repos in "..self.path) + self.groups = scan.scanrepos(self.path) +end + +function Cogit:log(level, msg) + self.conf.log(level, msg) +end + +function Cogit:routes() + title = self.title + conf = self.conf + sessions = self.sessions + return { + {"GET", "/?", + function (req) + local user = get_user(req.cookies) + local gnames = {} + self:scan() + for gname in pairs(self.groups) do + if allowed(user, gname) then + table.insert(gnames, gname) + end + end + local env = {title=title, user=user, gnames=gnames} + return lud.template.render_file("view/home.html", env) + end}, + {"GET", "/login", + function (req) + local user = get_user(req.cookies) + if user ~= nil then -- already logged in + return "/", 303 + else + return lud.template.render_file("view/login.html", {title=title}) + end + end}, + {"POST", "/login", + function (req) + local uname = req.form.username + local pass = req.form.password + local user = conf.users[uname] + local salt, h + if user == nil then + -- hash something as if we're trying to login anyway + salt = hash.get_salt() + h = hash.hash_pass(pass, salt) + conf.log(LOG_INFO, "invalid username") + else + salt = lud.crypt.b64_dec(user.salt) + h = hash.hash_pass(pass, salt) + if h == lud.crypt.b64_dec(user.hash) then + local session_id = lud.crypt.b64_enc(lud.crypt.uuid4()) + sessions[session_id] = uname + conf.log(LOG_INFO, "logged in as "..uname) + local age = conf.session_age + local cookie = {key="sid", val=session_id, path="/", age=age} + return "/", 303, "See Other", {cookie} + else + conf.log(LOG_INFO, "invalid password") + end + end + return "/login", 303 + end}, + {"GET", "/logout", + function (req) + local session_id = req.cookies["sid"] + if session_id ~= nil then + conf.log(LOG_INFO, "logged out as "..sessions[session_id]) + sessions[session_id] = nil + end + return "/", 303 + end}, + {"GET", "/group/([%w_-]+)", + function (req, gname) + local user = get_user(req.cookies) + if not allowed(user, gname) then + return "/login", 303 + end + local rnames = {} + for rname in pairs(self.groups[gname]) do + table.insert(rnames, rname) + end + local env = {title=title, user=user, gname=gname, rnames=rnames} + return lud.template.render_file("view/group.html", env) + end}, + {"GET", "/group/([%w_-]+)/repo/([%w_-]+)", + function (req, gname, rname) + local user = get_user(req.cookies) + if not allowed(user, gname) then + return "/login", 303 + end + local repo = self.groups[gname][rname] + local bnames = repo:branches() + local tnames = repo:tags() + local env = { + title=title, user=user, repo=repo, gname=gname, + rname=rname, bnames=bnames, tnames=tnames, + } + return lud.template.render_file("view/repo.html", env) + end}, + {"GET", "/group/([%w_-]+)/repo/([%w_-]+)/history/([%w_-]+)", + function (req, gname, rname, first) + local user = get_user(req.cookies) + if not allowed(user, gname) then + return "/login", 303 + end + local repo = self.groups[gname][rname] + local commit = repo:commit(first) + local prev = repo:find_prev(commit:id(), conf.limit) + local env = { + title=title, user=user, gname=gname, rname=rname, bname=bname, + commit=commit, limit=conf.limit, prev=prev, first=first, + } + return lud.template.render_file("view/history.html", env) + end}, + {"GET", "/group/([%w_-]+)/repo/([%w_-]+)/commit/([%w_-]+)", + function (req, gname, rname, cid) + local user = get_user(req.cookies) + if not allowed(user, gname) then + return "/login", 303 + end + local repo = self.groups[gname][rname] + local commit = repo:commit(cid) + local prev = repo:find_prev(commit:id(), 1) + local sig = commit:signature() + local time_str = time_fmt(sig) + local diff = repo:diff(commit, diff_cb) + local env = { + title=title, user=user, gname=gname, rname=rname, bname=bname, + commit=commit, time_str=time_str, sig=sig, cid=cid, prev=prev, diff=diff, + } + return lud.template.render_file("view/commit.html", env) + end}, + {"GET", "/group/([%w_-]+)/repo/([%w_-]+)/commit/([%w_-]+)/tree/(.*)", + function (req, gname, rname, cid, path) + local user = get_user(req.cookies) + if not allowed(user, gname) then + return "/login", 303 + end + local repo = self.groups[gname][rname] + local commit = repo:commit(cid) + local node = commit:tree_entry(path) + if node == nil then + return "File not found", 404, "Not found" + end + local parts = {} + for part in path:gmatch("[^/]+") do + table.insert(parts, part) + end + local base = req.path + if base:sub(#base) ~= "/" then + base = base .. "/" + end + local env = { + title=title, user=user, gname=gname, rname=rname, cid=cid, + path=path, base=base, parts=parts, node=node, + } + if node.type_ == "dir" then + return lud.template.render_file("view/dir.html", env) + elseif node.type_ == "file" then + return lud.template.render_file("view/file.html", env) + end + end}, +} end + +local function new_cogit(path) + local self = setmetatable({}, Cogit) + self.path = path + self.sessions = {} + self.initialized = false + self.conf = dofile(path.."/conf.lua") + self:init() + self:scan() + self.app = lud.app.new_app(self:routes()) + return self +end + +return {new_cogit=new_cogit} diff --git a/main.lua b/main.lua new file mode 100644 index 0000000..28f1316 --- /dev/null +++ b/main.lua @@ -0,0 +1,3 @@ +local cogit = require "cogit" + +cogit.new_cogit(arg[1]):run()