0
|
1 local Luan = require "luan:Luan.luan"
|
|
2 local error = Luan.error
|
|
3 local ipairs = Luan.ipairs or error()
|
|
4 local pairs = Luan.pairs or error()
|
|
5 local type = Luan.type or error()
|
|
6 local set_metatable = Luan.set_metatable or error()
|
|
7 local stringify = Luan.stringify or error()
|
|
8 local parse = Luan.parse or error()
|
|
9 local range = Luan.range or error()
|
|
10 local String = require "luan:String.luan"
|
|
11 local split = String.split or error()
|
|
12 local trim = String.trim or error()
|
|
13 local sub_string = String.sub or error()
|
|
14 local Table = require "luan:Table.luan"
|
|
15 local concat = Table.concat or error()
|
|
16 local Math = require "luan:Math.luan"
|
|
17 local random = Math.random or error()
|
|
18 local Binary = require "luan:Binary.luan"
|
|
19 local binary_base64_decode = Binary.base64_decode or error()
|
|
20 local binary_to_string = Binary.to_string or error()
|
|
21 local Io = require "luan:Io.luan"
|
|
22 local uri = Io.uri or error()
|
|
23 local Http = require "luan:http/Http.luan"
|
|
24 local Logging = require "luan:logging/Logging.luan"
|
|
25 local logger = Logging.logger "Shared"
|
|
26
|
|
27
|
|
28 local Shared = {}
|
|
29
|
|
30 function Shared.head()
|
|
31 %>
|
|
32 <meta name="viewport" content="width=device-width, initial-scale=1">
|
|
33 <style>
|
|
34 @import "/site.css";
|
|
35 </style>
|
|
36 <%
|
|
37 end
|
|
38
|
|
39 local function header(crumbs)
|
|
40 %>
|
|
41 <div header>
|
|
42 <a href="/">Mercurial Hosting</a>
|
|
43 <% for _, crumb in ipairs(crumbs or {}) do %>
|
|
44 / <%=crumb%>
|
|
45 <% end %>
|
|
46 </div>
|
|
47 <%
|
|
48 end
|
|
49 Shared.header = header
|
|
50
|
|
51 function Shared.admin_header()
|
|
52 header{
|
|
53 [[<a href="/admin/">Your Repositories</a>]]
|
|
54 }
|
|
55 end
|
|
56
|
|
57 function Shared.private_header()
|
|
58 header{
|
|
59 [[<a href="/private/">private</a>]]
|
|
60 [[<a href="/private/tools/">tools</a>]]
|
|
61 }
|
|
62 end
|
|
63
|
|
64 Shared.admin_return = [[<p>Return to <a href="/admin/">Your Repositories</a></p>]]
|
|
65
|
|
66 local function base64_decode(s)
|
|
67 return binary_to_string(binary_base64_decode(s))
|
|
68 end
|
|
69
|
|
70 function Shared.get_user()
|
|
71 local s = Http.request.headers["Authorization"] or error "not authorized"
|
|
72 local tp, auth = split(s," ")
|
|
73 tp=="Basic" or error("invalid auth type: "..tp)
|
|
74 s = base64_decode(auth)
|
|
75 s = split(s,":")
|
|
76 return s
|
|
77 end
|
|
78
|
|
79 local function deep_copy(tbl)
|
|
80 local t = {}
|
|
81 for k,v in pairs(tbl) do
|
|
82 if type(v)=="table" then
|
|
83 v = deep_copy(v)
|
|
84 end
|
|
85 t[k] = v
|
|
86 end
|
|
87 return t
|
|
88 end
|
|
89
|
|
90 local set_mt = {}
|
|
91 function set_mt.__index(table,key)
|
|
92 return false
|
|
93 end
|
|
94
|
|
95 local function list_to_set(list)
|
|
96 local set = {}
|
|
97 for _, v in ipairs(list) do
|
|
98 set[v] = true
|
|
99 end
|
|
100 set_metatable(set,set_mt)
|
|
101 return set
|
|
102 end
|
|
103 Shared.list_to_set = list_to_set
|
|
104
|
|
105 function Shared.text_to_list(text)
|
|
106 local list = {}
|
|
107 for line in Io.schemes.string(text).read_lines() do
|
|
108 line = trim(line)
|
|
109 if line ~= "" then
|
|
110 list[#list+1] = line
|
|
111 end
|
|
112 end
|
|
113 return list
|
|
114 end
|
|
115
|
|
116 local password_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
117 do
|
|
118 local t = {}
|
|
119 for i in range(1,#password_chars) do
|
|
120 t[#t+1] = sub_string(password_chars,i,i)
|
|
121 end
|
|
122 password_chars = t
|
|
123 end
|
|
124
|
|
125 function Shared.new_password()
|
|
126 local n = #password_chars
|
|
127 local t = {}
|
|
128 for _ in range(1,10) do
|
|
129 t[#t+1] = password_chars[random(n)]
|
|
130 end
|
|
131 return concat(t)
|
|
132 end
|
|
133
|
|
134 local raw_config = parse( uri("file:config/config.luano").read_text() )
|
|
135 local config = deep_copy(raw_config)
|
|
136 for name, repo in pairs(config.repos) do
|
|
137 repo.name = name
|
|
138 repo.users = list_to_set(repo.users)
|
|
139 repo.admins = list_to_set(repo.admins)
|
|
140 end
|
|
141 config.private = config.private and list_to_set(config.private)
|
|
142 Shared.config = config
|
|
143
|
4
|
144 local user_repos = {}
|
|
145 for _, repo in pairs(config.repos) do
|
|
146 for user in pairs(repo.users) do
|
|
147 local repos = user_repos[user]
|
|
148 if repos == nil then
|
|
149 repos = {}
|
|
150 user_repos[user] = repos
|
|
151 end
|
|
152 repos[#repos+1] = repo
|
|
153 end
|
|
154 end
|
|
155 Shared.user_repos = user_repos
|
|
156
|
0
|
157 function Shared.get_raw_config()
|
|
158 return deep_copy(raw_config)
|
|
159 end
|
|
160
|
|
161 local function reload_nginx()
|
|
162 local cmd = [[sudo $(which nginx) -s reload]]
|
|
163 local s = uri("bash:"..cmd).read_text()
|
|
164 logger.info("reload_nginx "..s)
|
|
165 end
|
|
166
|
|
167 function Shared.save_raw_config(raw_config)
|
|
168 local config_file = uri("file:config/config.luano")
|
|
169 local config_old = uri("file:config/config.luano.old")
|
|
170 config_old.delete()
|
|
171 config_file.move_to(config_old)
|
|
172 config_file.write_text(stringify(raw_config).."\n")
|
|
173 Http.reset_luan()
|
|
174 Luan.do_file "update_repositories.luan"
|
|
175 reload_nginx()
|
|
176 end
|
|
177
|
|
178 return Shared
|