💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Gemigit › files › 78fd9fcee28502d5386de1e86b… captured on 2024-02-05 at 09:48:44. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
0 package main
1
2 import (
3 "fmt"
4 "log"
5 "os"
6
7 "golang.org/x/term"
8
9 "gemigit/access"
10 "gemigit/auth"
11 "gemigit/config"
12 "gemigit/db"
13 "gemigit/httpgit"
14 "gemigit/sshgit"
15 "gemigit/repo"
16 "gemigit/gmi"
17 "gemigit/csrf"
18
19 "github.com/pitr/gig"
20 )
21
22 func main() {
23
24 if err := config.LoadConfig(); err != nil {
25 log.Fatalln(err.Error())
26 }
27
28 if len(os.Args) > 1 {
29 switch (os.Args[1]) {
30 case "chpasswd":
31 if (config.Cfg.Ldap.Enabled) {
32 fmt.Println("Not valid when LDAP is enabled")
33 return
34 }
35 if len(os.Args) < 3 {
36 fmt.Println(os.Args[0] +
37 " chpasswd <username>")
38 return
39 }
40 fmt.Print("New Password : ")
41 password, err := term.ReadPassword(0)
42 fmt.Print("\n")
43 if err != nil {
44 log.Fatalln(err.Error())
45 }
46 err = db.Init(config.Cfg.Database.Type,
47 config.Cfg.Database.Url, false)
48 if err != nil {
49 log.Fatalln(err.Error())
50 }
51 defer db.Close()
52 if err := db.ChangePassword(os.Args[2],
53 string(password));
54 err != nil {
55 fmt.Println(err.Error())
56 return
57 }
58 fmt.Println(os.Args[2] + "'s password changed")
59 return
60 case "register":
61 if (config.Cfg.Ldap.Enabled) {
62 fmt.Println("Not valid when LDAP is enabled")
63 return
64 }
65 if len(os.Args) < 3 {
66 fmt.Println(os.Args[0] +
67 " register <username>")
68 return
69 }
70 fmt.Print("Password : ")
71 password, err := term.ReadPassword(0)
72 fmt.Print("\n")
73 if err != nil {
74 log.Fatalln(err.Error())
75 }
76 err = db.Init(config.Cfg.Database.Type,
77 config.Cfg.Database.Url, false)
78 if err != nil {
79 log.Fatalln(err.Error())
80 }
81 defer db.Close()
82 if err := db.Register(os.Args[2], string(password));
83 err != nil {
84 fmt.Println(err.Error())
85 return
86 }
87 fmt.Println("User " + os.Args[2] + " created")
88 return
89 case "rmuser":
90 if len(os.Args) < 3 {
91 fmt.Println(os.Args[0] + " rmuser <username>")
92 return
93 }
94 err := db.Init(config.Cfg.Database.Type,
95 config.Cfg.Database.Url, false)
96 if err != nil {
97 log.Fatalln(err.Error())
98 }
99 defer db.Close()
100 err = db.DeleteUser(os.Args[2])
101 if err != nil {
102 log.Fatalln(err)
103 }
104 fmt.Println("User " + os.Args[2] +
105 " deleted successfully")
106 return
107 case "init":
108 err := db.Init(config.Cfg.Database.Type,
109 config.Cfg.Database.Url, true)
110 if err != nil {
111 log.Fatalln(err.Error())
112 }
113 db.Close()
114 return
115 case "update":
116 err := db.Init(config.Cfg.Database.Type,
117 config.Cfg.Database.Url, false)
118 if err != nil {
119 log.Fatalln(err.Error())
120 }
121 db.UpdateTable()
122 db.Close()
123 return
124 }
125 fmt.Println("usage: " + os.Args[0] + " [command]")
126 fmt.Println("commands :")
127 fmt.Println("\tchpasswd <username> - Change user password")
128 fmt.Println("\tregister <username> - Create user")
129 fmt.Println("\trmuser <username> - Remove user")
130 fmt.Println("\tupdate - Update database " +
131 "(Warning, it is recommended to do a backup of " +
132 "the database before using this command)")
133 fmt.Println("\tinit - Initialize database")
134 return
135 }
136
137 log.SetFlags(log.LstdFlags | log.Lshortfile)
138
139 if err := access.Init(); err != nil {
140 log.Fatalln(err.Error())
141 }
142
143 if err := gmi.LoadTemplate(config.Cfg.Gemini.Templates); err != nil {
144 log.Fatalln(err.Error())
145 }
146
147 err := db.Init(config.Cfg.Database.Type,
148 config.Cfg.Database.Url, false)
149 if err != nil {
150 log.Fatalln(err.Error())
151 }
152 defer db.Close()
153 if err := repo.Init("repos"); err != nil {
154 log.Fatalln(err.Error())
155 }
156
157 if !config.Cfg.Git.Remote.Enabled {
158 if config.Cfg.Git.Http.Enabled {
159 go httpgit.Listen(config.Cfg.Git.Path,
160 config.Cfg.Git.Http.Address,
161 config.Cfg.Git.Http.Port)
162 }
163 if config.Cfg.Git.SSH.Enabled {
164 go sshgit.Listen(config.Cfg.Git.Path,
165 config.Cfg.Git.SSH.Address,
166 config.Cfg.Git.SSH.Port)
167 }
168 }
169 go auth.Decrease()
170
171 gig.DefaultLoggerConfig.Format = "${time_rfc3339} - ${remote_ip} | " +
172 "Path=${path}, Status=${status}, " +
173 "Latency=${latency}\n"
174 g := gig.Default()
175 g.Use(gig.Recover())
176 g.File("/robots.txt", config.Cfg.Gemini.Templates + "/robots.txt")
177 if config.Cfg.Gemini.StaticDirectory != "" {
178 g.Static("/static", config.Cfg.Gemini.StaticDirectory)
179 }
180
181 g.Handle("/account", csrf.New)
182 g.Handle("/account/:csrf", func(c gig.Context) error {
183 return c.NoContent(gig.StatusRedirectTemporary,
184 "/account/" + c.Param("csrf") + "/")
185 })
186 passAuth := gig.PassAuth(csrf.Verify)
187
188 secure := g.Group("/account/:csrf/", passAuth)
189
190 secure.Handle("", gmi.ShowAccount)
191 // groups management
192 secure.Handle("groups", gmi.ShowGroups)
193 secure.Handle("groups/:group", gmi.ShowMembers)
194 secure.Handle("groups/:group/desc", gmi.SetGroupDesc)
195 secure.Handle("groups/:group/add", gmi.AddToGroup)
196 secure.Handle("groups/:group/leave", gmi.LeaveGroup)
197 secure.Handle("groups/:group/delete", gmi.DeleteGroup)
198 secure.Handle("groups/:group/kick/:user", gmi.RmFromGroup)
199
200 // repository settings
201 secure.Handle("repo/:repo/*", gmi.RepoFile)
202 secure.Handle("repo/:repo/togglepublic", gmi.TogglePublic)
203 secure.Handle("repo/:repo/chname", gmi.ChangeRepoName)
204 secure.Handle("repo/:repo/chdesc", gmi.ChangeRepoDesc)
205 secure.Handle("repo/:repo/delrepo", gmi.DeleteRepo)
206
207 // access management
208 secure.Handle("repo/:repo/access", gmi.ShowAccess)
209 secure.Handle("repo/:repo/access/add", gmi.AddUserAccess)
210 secure.Handle("repo/:repo/access/addg", gmi.AddGroupAccess)
211 secure.Handle("repo/:repo/access/:user/first",
212 gmi.UserAccessFirstOption)
213 secure.Handle("repo/:repo/access/:user/second",
214 gmi.UserAccessSecondOption)
215 secure.Handle("repo/:repo/access/:group/g/first",
216 gmi.GroupAccessFirstOption)
217 secure.Handle("repo/:repo/access/:group/g/second",
218 gmi.GroupAccessSecondOption)
219 secure.Handle("repo/:repo/access/:user/kick",
220 gmi.RemoveUserAccess)
221 secure.Handle("repo/:repo/access/:group/g/kick",
222 gmi.RemoveGroupAccess)
223
224 // repository view
225 secure.Handle("repo/:repo", gmi.RepoLog)
226 secure.Handle("repo/:repo/", func(c gig.Context) error {
227 return c.NoContent(gig.StatusRedirectTemporary,
228 "/account/" + c.Param("csrf") +
229 "/repo/" + c.Param("repo"))
230 })
231 secure.Handle("repo/:repo/license", gmi.RepoLicense)
232 secure.Handle("repo/:repo/readme", gmi.RepoReadme)
233 secure.Handle("repo/:repo/refs", gmi.RepoRefs)
234 secure.Handle("repo/:repo/files", gmi.RepoFiles)
235 secure.Handle("repo/:repo/files/:blob", gmi.RepoFileContent)
236
237 // user page
238 secure.Handle("chdesc", gmi.ChangeDesc)
239 secure.Handle("addrepo", gmi.AddRepo)
240 secure.Handle("addgroup", gmi.AddGroup)
241 // otp
242 secure.Handle("otp", gmi.ShowOTP)
243 secure.Handle("otp/qr", gmi.CreateTOTP)
244 secure.Handle("otp/confirm", gmi.ConfirmTOTP)
245 secure.Handle("otp/rm", gmi.RemoveTOTP)
246 // token
247 secure.Handle("token", gmi.ListTokens)
248 secure.Handle("token/new", gmi.CreateWriteToken)
249 secure.Handle("token/new_ro", gmi.CreateReadToken)
250 secure.Handle("token/secure", gmi.ToggleTokenAuth)
251 secure.Handle("token/renew/:token", gmi.RenewToken)
252 secure.Handle("token/delete/:token", gmi.DeleteToken)
253
254 if !config.Cfg.Ldap.Enabled {
255 secure.Handle("chpasswd", gmi.ChangePassword)
256 }
257
258 secure.Handle("disconnect", gmi.Disconnect)
259 secure.Handle("disconnectall", gmi.DisconnectAll)
260
261 if config.Cfg.Git.Key != "" {
262 api := g.Group("/api")
263 api.Handle("/:key/init/:username/:repo", repo.ApiInit)
264 api.Handle("/:key/rm/:username/:repo", repo.ApiRemove)
265 api.Handle("/:key/mv/:username/:repo/:newname",
266 repo.ApiRename)
267 }
268
269 var public *gig.Group
270 if config.Cfg.Git.Public {
271 public = g.Group("/repo")
272 } else {
273 public = g.Group("/repo", gig.PassAuth(
274 func(sig string, c gig.Context) (string, error) {
275 _, exist := db.GetUser(sig)
276 if !exist { return "/", nil }
277 return "", nil
278 }))
279 }
280
281 public.Handle("", gmi.PublicList)
282 public.Handle("/:user/:repo/*", gmi.PublicFile)
283 public.Handle("/:user", gmi.PublicAccount)
284 public.Handle("/:user/:repo", gmi.PublicLog)
285 public.Handle("/:user/:repo/refs", gmi.PublicRefs)
286 public.Handle("/:user/:repo/license", gmi.PublicLicense)
287 public.Handle("/:user/:repo/readme", gmi.PublicReadme)
288 public.Handle("/:user/:repo/files", gmi.PublicFiles)
289 public.Handle("/:user/:repo/files/:blob", gmi.PublicFileContent)
290
291 g.PassAuthLoginHandle("/login", gmi.Login)
292
293 if config.Cfg.Users.Registration {
294 g.Handle("/register", gmi.Register)
295 g.Handle("/register/:name", gmi.RegisterConfirm)
296 }
297 g.Handle("/otp", gmi.LoginOTP)
298
299 g.Handle("/", func(c gig.Context) error {
300 return gmi.ShowIndex(c)
301 })
302
303 err = g.Run(config.Cfg.Gemini.Address + ":" + config.Cfg.Gemini.Port,
304 config.Cfg.Gemini.Certificate, config.Cfg.Gemini.Key)
305
306 if err != nil {
307 log.Fatal(err.Error())
308 }
309 }
310