aboutsummaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
authorQuentin <quentin@dufour.io>2023-09-26 06:44:36 +0000
committerQuentin <quentin@dufour.io>2023-09-26 06:44:36 +0000
commit49d8e81fbea0d4703a33e87a807927169a8060ac (patch)
treed0b655454d5e13ed2238060fee27fc0d951d64c8 /main.go
parent1e75c21b65021da0c3c5a8be9be12114a2327464 (diff)
parent706ff58a6f6608719feda15075d50f978df39c5b (diff)
downloadguichet-49d8e81fbea0d4703a33e87a807927169a8060ac.tar.gz
guichet-49d8e81fbea0d4703a33e87a807927169a8060ac.zip
Merge pull request 'An API for Guichet' (#23) from api into main
Reviewed-on: https://git.deuxfleurs.fr/Deuxfleurs/guichet/pulls/23
Diffstat (limited to 'main.go')
-rw-r--r--main.go224
1 files changed, 47 insertions, 177 deletions
diff --git a/main.go b/main.go
index ae8fe06..6553bef 100644
--- a/main.go
+++ b/main.go
@@ -2,10 +2,8 @@ package main
import (
"crypto/rand"
- "crypto/tls"
"encoding/json"
"flag"
- "fmt"
"html/template"
"io/ioutil"
"log"
@@ -58,7 +56,8 @@ type ConfigFile struct {
S3Bucket string `json:"s3_bucket"`
}
-var configFlag = flag.String("config", "./config.json", "Configuration file path")
+var fsServer = flag.NewFlagSet("server", flag.ContinueOnError)
+var configFlag = fsServer.String("config", "./config.json", "Configuration file path")
var config *ConfigFile
@@ -114,8 +113,25 @@ func getTemplate(name string) *template.Template {
}
func main() {
- flag.Parse()
+ if len(os.Args) < 2 {
+ server(os.Args[1:])
+ return
+ }
+
+ switch os.Args[1] {
+ case "cli":
+ cliMain(os.Args[2:])
+ case "server":
+ server(os.Args[2:])
+ default:
+ log.Println("Usage: guichet [server|cli] --help")
+ os.Exit(1)
+ }
+}
+func server(args []string) {
+ log.Println("Starting Guichet Server")
+ fsServer.Parse(args)
config_file := readConfig()
config = &config_file
@@ -128,8 +144,12 @@ func main() {
r := mux.NewRouter()
r.HandleFunc("/", handleHome)
+ r.HandleFunc("/login", handleLogin)
r.HandleFunc("/logout", handleLogout)
+ r.HandleFunc("/api/unstable/website", handleAPIWebsiteList)
+ r.HandleFunc("/api/unstable/website/{bucket}", handleAPIWebsiteInspect)
+
r.HandleFunc("/profile", handleProfile)
r.HandleFunc("/passwd", handlePasswd)
r.HandleFunc("/picture/{name}", handleDownloadPicture)
@@ -137,10 +157,10 @@ func main() {
r.HandleFunc("/directory/search", handleDirectorySearch)
r.HandleFunc("/directory", handleDirectory)
- r.HandleFunc("/garage/key", handleGarageKey)
- r.HandleFunc("/garage/website", handleGarageWebsiteList)
- r.HandleFunc("/garage/website/new", handleGarageWebsiteNew)
- r.HandleFunc("/garage/website/b/{bucket}", handleGarageWebsiteInspect)
+ r.HandleFunc("/website", handleWebsiteList)
+ r.HandleFunc("/website/new", handleWebsiteNew)
+ r.HandleFunc("/website/configure", handleWebsiteConfigure)
+ r.HandleFunc("/website/inspect/{bucket}", handleWebsiteInspect)
r.HandleFunc("/invite/new_account", handleInviteNewAccount)
r.HandleFunc("/invite/send_code", handleInviteSendCode)
@@ -163,31 +183,6 @@ func main() {
}
}
-type LoginInfo struct {
- Username string
- DN string
- Password string
-}
-
-type LoginStatus struct {
- Info *LoginInfo
- conn *ldap.Conn
- UserEntry *ldap.Entry
- CanAdmin bool
- CanInvite bool
-}
-
-func (login *LoginStatus) WelcomeName() string {
- ret := login.UserEntry.GetAttributeValue("givenname")
- if ret == "" {
- ret = login.UserEntry.GetAttributeValue("displayname")
- }
- if ret == "" {
- ret = login.Info.Username
- }
- return ret
-}
-
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)
@@ -195,149 +190,31 @@ func logRequest(handler http.Handler) http.Handler {
})
}
-func checkLogin(w http.ResponseWriter, r *http.Request) *LoginStatus {
- var login_info *LoginInfo
-
- session, err := store.Get(r, SESSION_NAME)
- if err == nil {
- username, ok := session.Values["login_username"]
- password, ok2 := session.Values["login_password"]
- user_dn, ok3 := session.Values["login_dn"]
-
- if ok && ok2 && ok3 {
- login_info = &LoginInfo{
- DN: user_dn.(string),
- Username: username.(string),
- Password: password.(string),
- }
- }
- }
-
- if login_info == nil {
- login_info = handleLogin(w, r)
- if login_info == nil {
- return nil
- }
- }
-
- l := ldapOpen(w)
- if l == nil {
- return nil
- }
-
- err = l.Bind(login_info.DN, login_info.Password)
- if err != nil {
- delete(session.Values, "login_username")
- delete(session.Values, "login_password")
- delete(session.Values, "login_dn")
-
- err = session.Save(r, w)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return nil
- }
- return checkLogin(w, r)
- }
-
- loginStatus := &LoginStatus{
- Info: login_info,
- conn: l,
- }
-
- requestKind := "(objectClass=organizationalPerson)"
- if strings.EqualFold(login_info.DN, config.AdminAccount) {
- requestKind = "(objectclass=*)"
- }
- searchRequest := ldap.NewSearchRequest(
- login_info.DN,
- ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
- requestKind,
- []string{
- "dn",
- "displayname",
- "givenname",
- "sn",
- "mail",
- "memberof",
- "description",
- "garage_s3_access_key",
- FIELD_NAME_DIRECTORY_VISIBILITY,
- FIELD_NAME_PROFILE_PICTURE,
- },
- nil)
-
- sr, err := l.Search(searchRequest)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return nil
- }
-
- if len(sr.Entries) != 1 {
- http.Error(w, fmt.Sprintf("Unable to find entry for %s", login_info.DN), http.StatusInternalServerError)
- return nil
- }
-
- loginStatus.UserEntry = sr.Entries[0]
-
- loginStatus.CanAdmin = strings.EqualFold(loginStatus.Info.DN, config.AdminAccount)
- loginStatus.CanInvite = false
- for _, attr := range loginStatus.UserEntry.Attributes {
- if strings.EqualFold(attr.Name, "memberof") {
- for _, group := range attr.Values {
- if config.GroupCanInvite != "" && strings.EqualFold(group, config.GroupCanInvite) {
- loginStatus.CanInvite = true
- }
- if config.GroupCanAdmin != "" && strings.EqualFold(group, config.GroupCanAdmin) {
- loginStatus.CanAdmin = true
- }
- }
- }
- }
-
- return loginStatus
-}
-
-func ldapOpen(w http.ResponseWriter) *ldap.Conn {
- l, err := ldap.DialURL(config.LdapServerAddr)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return nil
- }
-
- if config.LdapTLS {
- err = l.StartTLS(&tls.Config{InsecureSkipVerify: true})
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return nil
- }
- }
-
- return l
-}
-
// Page handlers ----
+// --- Home Controller
type HomePageData struct {
- Login *LoginStatus
+ User *LoggedUser
BaseDN string
}
func handleHome(w http.ResponseWriter, r *http.Request) {
templateHome := getTemplate("home.html")
- login := checkLogin(w, r)
- if login == nil {
+ user := RequireUserHtml(w, r)
+ if user == nil {
return
}
data := &HomePageData{
- Login: login,
+ User: user,
BaseDN: config.BaseDN,
}
templateHome.Execute(w, data)
}
+// --- Logout Controller
func handleLogout(w http.ResponseWriter, r *http.Request) {
session, err := store.Get(r, SESSION_NAME)
if err != nil {
@@ -354,9 +231,10 @@ func handleLogout(w http.ResponseWriter, r *http.Request) {
return
}
- http.Redirect(w, r, "/", http.StatusFound)
+ http.Redirect(w, r, "/login", http.StatusFound)
}
+// --- Login Controller ---
type LoginFormData struct {
Username string
WrongUser bool
@@ -364,28 +242,26 @@ type LoginFormData struct {
ErrorMessage string
}
-func handleLogin(w http.ResponseWriter, r *http.Request) *LoginInfo {
+func handleLogin(w http.ResponseWriter, r *http.Request) {
templateLogin := getTemplate("login.html")
if r.Method == "GET" {
templateLogin.Execute(w, LoginFormData{})
- return nil
+ return
} else if r.Method == "POST" {
r.ParseForm()
username := strings.Join(r.Form["username"], "")
password := strings.Join(r.Form["password"], "")
- user_dn := fmt.Sprintf("%s=%s,%s", config.UserNameAttr, username, config.UserBaseDN)
- if strings.EqualFold(username, config.AdminAccount) {
- user_dn = username
- }
+ loginInfo := LoginInfo{username, password}
- l := ldapOpen(w)
- if l == nil {
- return nil
+ l, err := NewLdapCon()
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
}
- err := l.Bind(user_dn, password)
+ err = l.Bind(loginInfo.DN(), loginInfo.Password)
if err != nil {
data := &LoginFormData{
Username: username,
@@ -398,7 +274,7 @@ func handleLogin(w http.ResponseWriter, r *http.Request) *LoginInfo {
data.ErrorMessage = err.Error()
}
templateLogin.Execute(w, data)
- return nil
+ return
}
// Successfully logged in, save it to session
@@ -409,21 +285,15 @@ func handleLogin(w http.ResponseWriter, r *http.Request) *LoginInfo {
session.Values["login_username"] = username
session.Values["login_password"] = password
- session.Values["login_dn"] = user_dn
err = session.Save(r, w)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
- return nil
+ return
}
- return &LoginInfo{
- DN: user_dn,
- Username: username,
- Password: password,
- }
+ http.Redirect(w, r, "/", http.StatusFound)
} else {
http.Error(w, "Unsupported method", http.StatusBadRequest)
- return nil
}
}