# HG changeset patch # User Sascha L. Teichmann # Date 1532018032 -7200 # Node ID fe3a88f00b0ae3c3a04c88dd8cdbe2e022fdada2 # Parent a9d9c2b1d08c89ac9433477dd85da62937264497 Experimental user creation support. diff -r a9d9c2b1d08c -r fe3a88f00b0a cmd/tokenserver/main.go --- a/cmd/tokenserver/main.go Thu Jul 19 16:37:52 2018 +0200 +++ b/cmd/tokenserver/main.go Thu Jul 19 18:33:52 2018 +0200 @@ -2,7 +2,6 @@ import ( "context" - "encoding/json" "flag" "fmt" "log" @@ -21,78 +20,6 @@ fmt.Fprintf(rw, "%s is a sys_admin\n", session.User) } -func renew(rw http.ResponseWriter, req *http.Request) { - token, _ := auth.GetToken(req) - newToken, err := auth.ConnPool.Renew(token) - switch { - case err == auth.ErrNoSuchToken: - http.NotFound(rw, req) - return - case err != nil: - http.Error(rw, fmt.Sprintf("error: %v", err), http.StatusInternalServerError) - return - } - - session, _ := auth.GetSession(req) - - var result = struct { - Token string `json:"token"` - Expires int64 `json:"expires"` - User string `json:"user"` - Roles []string `json:"roles"` - }{ - Token: newToken, - Expires: session.ExpiresAt, - User: session.User, - Roles: session.Roles, - } - - rw.Header().Set("Content-Type", "text/plain") - if err := json.NewEncoder(rw).Encode(&result); err != nil { - log.Printf("error: %v\n", err) - } -} - -func logout(rw http.ResponseWriter, req *http.Request) { - token, _ := auth.GetToken(req) - deleted := auth.ConnPool.Delete(token) - if !deleted { - http.NotFound(rw, req) - return - } - rw.Header().Set("Content-Type", "text/plain") - fmt.Fprintln(rw, "token deleted") -} - -func token(rw http.ResponseWriter, req *http.Request) { - user := req.FormValue("user") - password := req.FormValue("password") - - token, session, err := auth.GenerateSession(user, password) - - if err != nil { - http.Error(rw, fmt.Sprintf("error: %v", err), http.StatusInternalServerError) - return - } - - var result = struct { - Token string `json:"token"` - Expires int64 `json:"expires"` - User string `json:"user"` - Roles []string `json:"roles"` - }{ - Token: token, - Expires: session.ExpiresAt, - User: session.User, - Roles: session.Roles, - } - - rw.Header().Set("Content-Type", "application/json") - if err := json.NewEncoder(rw).Encode(&result); err != nil { - log.Printf("error: %v\n", err) - } -} - func main() { port := flag.Int("port", 8000, "port to listen at.") host := flag.String("host", "localhost", "host to listen at.") @@ -106,6 +33,9 @@ mux.Handle("/api/sys_admin", auth.SessionMiddleware( auth.SessionChecker(http.HandlerFunc(sysAdmin), auth.HasRole("sys_admin")))) + mux.Handle("/api/create_user", + auth.SessionMiddleware( + auth.SessionChecker(http.HandlerFunc(createUser), auth.HasRole("sys_admin")))) addr := fmt.Sprintf("%s:%d", *host, *port) diff -r a9d9c2b1d08c -r fe3a88f00b0a cmd/tokenserver/token.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmd/tokenserver/token.go Thu Jul 19 18:33:52 2018 +0200 @@ -0,0 +1,82 @@ +package main + +import ( + "encoding/json" + "fmt" + "log" + "net/http" + + "gemma.intevation.de/gemma/auth" +) + +func renew(rw http.ResponseWriter, req *http.Request) { + token, _ := auth.GetToken(req) + newToken, err := auth.ConnPool.Renew(token) + switch { + case err == auth.ErrNoSuchToken: + http.NotFound(rw, req) + return + case err != nil: + http.Error(rw, fmt.Sprintf("error: %v", err), http.StatusInternalServerError) + return + } + + session, _ := auth.GetSession(req) + + var result = struct { + Token string `json:"token"` + Expires int64 `json:"expires"` + User string `json:"user"` + Roles []string `json:"roles"` + }{ + Token: newToken, + Expires: session.ExpiresAt, + User: session.User, + Roles: session.Roles, + } + + rw.Header().Set("Content-Type", "text/plain") + if err := json.NewEncoder(rw).Encode(&result); err != nil { + log.Printf("error: %v\n", err) + } +} + +func logout(rw http.ResponseWriter, req *http.Request) { + token, _ := auth.GetToken(req) + deleted := auth.ConnPool.Delete(token) + if !deleted { + http.NotFound(rw, req) + return + } + rw.Header().Set("Content-Type", "text/plain") + fmt.Fprintln(rw, "token deleted") +} + +func token(rw http.ResponseWriter, req *http.Request) { + user := req.FormValue("user") + password := req.FormValue("password") + + token, session, err := auth.GenerateSession(user, password) + + if err != nil { + http.Error(rw, fmt.Sprintf("error: %v", err), http.StatusInternalServerError) + return + } + + var result = struct { + Token string `json:"token"` + Expires int64 `json:"expires"` + User string `json:"user"` + Roles []string `json:"roles"` + }{ + Token: token, + Expires: session.ExpiresAt, + User: session.User, + Roles: session.Roles, + } + + rw.Header().Set("Content-Type", "application/json") + if err := json.NewEncoder(rw).Encode(&result); err != nil { + log.Printf("error: %v\n", err) + } +} diff -r a9d9c2b1d08c -r fe3a88f00b0a cmd/tokenserver/user.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmd/tokenserver/user.go Thu Jul 19 18:33:52 2018 +0200 @@ -0,0 +1,72 @@ +package main + +import ( + "database/sql" + "encoding/json" + "log" + "net/http" + + "gemma.intevation.de/gemma/auth" +) + +type BoundingBox struct { + X1 float64 `json:"x1"` + Y1 float64 `json:"y1"` + X2 float64 `json:"x2"` + Y2 float64 `json:"y2"` +} + +type User struct { + User string `json:"user"` + Role string `json:"role"` + Password string `json:"password"` + Email string `json:"email"` + Country string `json:"country"` + Extent *BoundingBox `json:"extent"` +} + +const ( + createUserSQL = `SELECT create_user($1, $2, $3, $4, $5, $6)` +) + +func createUser(rw http.ResponseWriter, req *http.Request) { + + var user User + + defer req.Body.Close() + if err := json.NewDecoder(req.Body).Decode(&user); err != nil { + log.Printf("err: %v\n", err) + http.Error(rw, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) + return + } + + token, _ := auth.GetToken(req) + err := auth.ConnPool.Do(token, func(db *sql.DB) error { + _, err := db.Exec( + createUserSQL, + user.Role, + user.User, + user.Password, + user.Country, + nil, + ) + return err + }) + + if err != nil { + log.Printf("err: %v\n", err) + http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + return + } + + var result = struct { + Result string `json:"result"` + }{ + Result: "success", + } + + rw.Header().Set("Content-Type", "application/json") + if err := json.NewEncoder(rw).Encode(&result); err != nil { + log.Printf("error: %v\n", err) + } +}