diff options
Diffstat (limited to 'web.go')
-rw-r--r-- | web.go | 171 |
1 files changed, 171 insertions, 0 deletions
@@ -0,0 +1,171 @@ +package main + +import ( + "crypto/rand" + "html/template" + "log" + "net/http" + "strings" + + "github.com/gorilla/mux" + "github.com/gorilla/sessions" + + "git.deuxfleurs.fr/Deuxfleurs/easybridge/mxlib" +) + +const SESSION_NAME = "easybridge_session" + +var sessionsStore sessions.Store = nil + +func StartWeb() { + session_key := make([]byte, 32) + n, err := rand.Read(session_key) + if err != nil || n != 32 { + log.Fatal(err) + } + sessionsStore = sessions.NewCookieStore(session_key) + + r := mux.NewRouter() + r.HandleFunc("/", handleHome) + r.HandleFunc("/logout", handleLogout) + + staticfiles := http.FileServer(http.Dir("static")) + r.Handle("/static/{file:.*}", http.StripPrefix("/static/", staticfiles)) + + log.Printf("Starting web UI HTTP server on %s", config.WebBindAddr) + go func() { + err = http.ListenAndServe(config.WebBindAddr, logRequest(r)) + if err != nil { + log.Fatal("Cannot start http server: ", err) + } + }() +} + +func logRequest(handler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + log.Printf("%s %s %s\n", r.RemoteAddr, r.Method, r.URL) + handler.ServeHTTP(w, r) + }) +} + +// ---- + +type LoginInfo struct { + MxId string +} + +func checkLogin(w http.ResponseWriter, r *http.Request) *LoginInfo { + var login_info *LoginInfo + + session, err := sessionsStore.Get(r, SESSION_NAME) + if err == nil { + mxid, ok := session.Values["login_mxid"] + if ok { + login_info = &LoginInfo{ + MxId: mxid.(string), + } + } + } + + if login_info == nil { + login_info = handleLogin(w, r) + } + + return login_info +} + +// ---- + +type HomeData struct { + Login *LoginInfo + Accounts map[string]*Account +} + +func handleHome(w http.ResponseWriter, r *http.Request) { + templateHome := template.Must(template.ParseFiles("templates/layout.html", "templates/home.html")) + + login := checkLogin(w, r) + if login == nil { + return + } + + accountsLock.Lock() + defer accountsLock.Unlock() + templateHome.Execute(w, &HomeData{ + Login: login, + Accounts: registeredAccounts[login.MxId], + }) +} + +func handleLogout(w http.ResponseWriter, r *http.Request) { + session, err := sessionsStore.Get(r, SESSION_NAME) + if err != nil { + session, _ = sessionsStore.New(r, SESSION_NAME) + } + + delete(session.Values, "login_mxid") + + err = session.Save(r, w) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + http.Redirect(w, r, "/", http.StatusFound) +} + +type LoginFormData struct { + Username string + WrongPass bool + ErrorMessage string + MatrixDomain string +} + +func handleLogin(w http.ResponseWriter, r *http.Request) *LoginInfo { + templateLogin := template.Must(template.ParseFiles("templates/layout.html", "templates/login.html")) + + data := &LoginFormData{ + MatrixDomain: config.MatrixDomain, + } + + if r.Method == "GET" { + templateLogin.Execute(w, data) + return nil + } else if r.Method == "POST" { + r.ParseForm() + + username := strings.Join(r.Form["username"], "") + password := strings.Join(r.Form["password"], "") + + cli := mxlib.NewClient(config.Server, "") + mxid, err := cli.PasswordLogin(username, password, "EZBRIDGE", "Easybridge") + + if err != nil { + data.Username = username + data.ErrorMessage = err.Error() + templateLogin.Execute(w, data) + return nil + } + + // Successfully logged in, save it to session + session, err := sessionsStore.Get(r, SESSION_NAME) + if err != nil { + session, _ = sessionsStore.New(r, SESSION_NAME) + } + + session.Values["login_mxid"] = mxid + + err = session.Save(r, w) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return nil + } + + return &LoginInfo{ + MxId: mxid, + } + } else { + http.Error(w, "Unsupported method", http.StatusBadRequest) + return nil + } +} |