changeset 296:b1116c4ce57f usermanagement

merge with default
author Thomas Junk <thomas.junk@intevation.de>
date Tue, 31 Jul 2018 15:56:11 +0200
parents 22deb76dff2c (current diff) c2334b5d3dd0 (diff)
children 57de8b62b47e
files
diffstat 7 files changed, 198 insertions(+), 188 deletions(-) [+]
line wrap: on
line diff
--- a/README.md	Tue Jul 31 15:01:10 2018 +0200
+++ b/README.md	Tue Jul 31 15:56:11 2018 +0200
@@ -9,6 +9,8 @@
 
 - To only build the SPA-Client you can use `make client`.
 
+For further details see [docs/DEVELOPMENT](docs/DEVELOPMENT.md),
+
 
 ## Setup Database
 
@@ -41,31 +43,3 @@
 
 - `./cmd/gemma/gemma -h` gives you an overview of more available
   options.
-
-
-# Manual setup
-
-## Backend
-
-In Go.
-
-* Install dependencies
-
-    `sh 3rdpartylibs`
-
-* Build
-
-    Prerequesite: compile server
-    ```
-    cd cmd/gemma/
-    go build
-    cd ../../
-    ```
-
-* Run
-    Run server with  `./cmd/gemma/gemma`
-
-
-## Client
-
-See [client/README](client/README.md).
--- a/cmd/gemma/root.go	Tue Jul 31 15:01:10 2018 +0200
+++ b/cmd/gemma/root.go	Tue Jul 31 15:56:11 2018 +0200
@@ -38,7 +38,7 @@
 	fl().StringVarP(&config.Config.DBHost, "dbhost", "H", "localhost", "host of the database")
 	fl().UintVarP(&config.Config.DBPort, "dbport", "P", 5432, "port of the database")
 	fl().StringVarP(&config.Config.DBName, "dbname", "d", "gemma", "name of the database")
-	fl().StringVarP(&config.Config.DBSSLMode, "dbssl", "S", "require", "SSL mode of the database")
+	fl().StringVarP(&config.Config.DBSSLMode, "dbssl", "S", "prefer", "SSL mode of the database")
 
 	fl().StringVarP(&config.Config.SessionStore, "sessions", "s", "", "path to the sessions file")
 
--- a/controllers/token.go	Tue Jul 31 15:01:10 2018 +0200
+++ b/controllers/token.go	Tue Jul 31 15:56:11 2018 +0200
@@ -9,6 +9,13 @@
 	"gemma.intevation.de/gemma/auth"
 )
 
+func sendJSON(rw http.ResponseWriter, data interface{}) {
+	rw.Header().Set("Content-Type", "application/json")
+	if err := json.NewEncoder(rw).Encode(data); err != nil {
+		log.Printf("error: %v\n", err)
+	}
+}
+
 func renew(rw http.ResponseWriter, req *http.Request) {
 	token, _ := auth.GetToken(req)
 	newToken, err := auth.ConnPool.Renew(token)
@@ -35,10 +42,7 @@
 		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)
-	}
+	sendJSON(rw, &result)
 }
 
 func logout(rw http.ResponseWriter, req *http.Request) {
@@ -53,11 +57,18 @@
 }
 
 func login(rw http.ResponseWriter, req *http.Request) {
-	user := req.FormValue("user")
-	password := req.FormValue("password")
+
+	var (
+		user     = req.FormValue("user")
+		password = req.FormValue("password")
+	)
+
+	if user == "" || password == "" {
+		http.Error(rw, "Invalid credentials", http.StatusBadRequest)
+		return
+	}
 
 	token, session, err := auth.GenerateSession(user, password)
-
 	if err != nil {
 		http.Error(rw, fmt.Sprintf("error: %v", err), http.StatusInternalServerError)
 		return
@@ -75,8 +86,5 @@
 		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)
-	}
+	sendJSON(rw, &result)
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/controllers/types.go	Tue Jul 31 15:56:11 2018 +0200
@@ -0,0 +1,146 @@
+package controllers
+
+import (
+	"database/sql/driver"
+	"encoding/json"
+	"errors"
+	"regexp"
+	"strings"
+)
+
+type (
+	Email   string
+	Country string
+	Role    string
+
+	BoundingBox struct {
+		X1 float64 `json:"x1"`
+		Y1 float64 `json:"y1"`
+		X2 float64 `json:"x2"`
+		Y2 float64 `json:"y2"`
+	}
+
+	User struct {
+		User     string       `json:"user"`
+		Role     Role         `json:"role"`
+		Password string       `json:"password,omitempty"`
+		Email    Email        `json:"email"`
+		Country  Country      `json:"country"`
+		Extent   *BoundingBox `json:"extent"`
+	}
+)
+
+var (
+	// https://stackoverflow.com/questions/201323/how-to-validate-an-email-address-using-a-regular-expression
+	emailRe = regexp.MustCompile(
+		`(?:[a-z0-9!#$%&'*+/=?^_` + "`" +
+			`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_` + "`" +
+			`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]` +
+			`|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")` +
+			`@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?` +
+			`|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}` +
+			`(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]` +
+			`:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]` +
+			`|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])`)
+
+	errNoEmailAddress = errors.New("Not a valid email address")
+	errNoString       = errors.New("Not a string")
+)
+
+func (e *Email) UnmarshalJSON(data []byte) error {
+	var s string
+	if err := json.Unmarshal(data, &s); err != nil {
+		return err
+	}
+	if !emailRe.MatchString(s) {
+		return errNoEmailAddress
+	}
+	*e = Email(s)
+	return nil
+}
+
+func (e Email) Value() (driver.Value, error) {
+	return string(e), nil
+}
+
+func (e *Email) Scan(src interface{}) (err error) {
+	if s, ok := src.(string); ok {
+		*e = Email(s)
+	} else {
+		err = errNoString
+	}
+	return
+}
+
+var (
+	validCountries = []string{
+		"AT", "BG", "DE", "HU", "HR",
+		"MD", "RO", "RS", "SK", "UA",
+	}
+	errNoValidCountry = errors.New("Not a valid country")
+)
+
+func (c *Country) UnmarshalJSON(data []byte) error {
+	var s string
+	if err := json.Unmarshal(data, &s); err != nil {
+		return err
+	}
+	s = strings.ToUpper(s)
+	for _, v := range validCountries {
+		if v == s {
+			*c = Country(v)
+			return nil
+		}
+	}
+	return errNoValidCountry
+}
+
+func (c Country) Value() (driver.Value, error) {
+	return string(c), nil
+}
+
+func (c *Country) Scan(src interface{}) (err error) {
+	if s, ok := src.(string); ok {
+		*c = Country(s)
+	} else {
+		err = errNoString
+	}
+	return
+}
+
+var (
+	validRoles = []string{
+		"waterway_user",
+		"waterway_admin",
+		"sys_admin",
+	}
+	errNoValidRole = errors.New("Not a valid role")
+)
+
+func (r Role) Value() (driver.Value, error) {
+	return string(r), nil
+}
+
+func (r *Role) Scan(src interface{}) (err error) {
+	if s, ok := src.(string); ok {
+		*r = Role(s)
+	} else {
+		err = errNoString
+	}
+	return
+}
+
+func (r *Role) UnmarshalJSON(data []byte) error {
+	var s string
+	if err := json.Unmarshal(data, &s); err != nil {
+		return err
+	}
+	s = strings.ToLower(s)
+	for _, v := range validRoles {
+		if v == s {
+			*r = Role(v)
+			return nil
+		}
+	}
+	return errNoValidRole
+}
--- a/controllers/user.go	Tue Jul 31 15:01:10 2018 +0200
+++ b/controllers/user.go	Tue Jul 31 15:56:11 2018 +0200
@@ -2,41 +2,14 @@
 
 import (
 	"database/sql"
-	"database/sql/driver"
-	"encoding/json"
-	"errors"
 	"fmt"
 	"net/http"
-	"regexp"
-	"strings"
 
 	"github.com/gorilla/mux"
 
 	"gemma.intevation.de/gemma/auth"
 )
 
-type (
-	Email   string
-	Country string
-	Role    string
-
-	BoundingBox struct {
-		X1 float64 `json:"x1"`
-		Y1 float64 `json:"y1"`
-		X2 float64 `json:"x2"`
-		Y2 float64 `json:"y2"`
-	}
-
-	User struct {
-		User     string       `json:"user"`
-		Role     Role         `json:"role"`
-		Password string       `json:"password,omitempty"`
-		Email    Email        `json:"email"`
-		Country  Country      `json:"country"`
-		Extent   *BoundingBox `json:"extent"`
-	}
-)
-
 const (
 	createUserSQL       = `SELECT sys_admin.create_user($1, $2, $3, $4, NULL, $5)`
 	createUserExtentSQL = `SELECT sys_admin.create_user($1, $2, $3, $4,
@@ -67,123 +40,8 @@
 WHERE username = $1`
 )
 
-var errNoString = errors.New("Not a string")
-
-var (
-	// https://stackoverflow.com/questions/201323/how-to-validate-an-email-address-using-a-regular-expression
-	emailRe = regexp.MustCompile(
-		`(?:[a-z0-9!#$%&'*+/=?^_` + "`" +
-			`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_` + "`" +
-			`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]` +
-			`|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")` +
-			`@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?` +
-			`|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}` +
-			`(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]` +
-			`:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]` +
-			`|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])`)
-	errNoEmailAddress = errors.New("Not a valid email address")
-)
-
-func (e *Email) UnmarshalJSON(data []byte) error {
-	var s string
-	if err := json.Unmarshal(data, &s); err != nil {
-		return err
-	}
-	if !emailRe.MatchString(s) {
-		return errNoEmailAddress
-	}
-	*e = Email(s)
-	return nil
-}
-
-func (e Email) Value() (driver.Value, error) {
-	return string(e), nil
-}
-
-func (e *Email) Scan(src interface{}) (err error) {
-	if s, ok := src.(string); ok {
-		*e = Email(s)
-	} else {
-		err = errNoString
-	}
-	return
-}
-
-var (
-	validCountries = []string{
-		"AT", "BG", "DE", "HU", "HR",
-		"MD", "RO", "RS", "SK", "UA",
-	}
-	errNoValidCountry = errors.New("Not a valid country")
-)
-
-func (c *Country) UnmarshalJSON(data []byte) error {
-	var s string
-	if err := json.Unmarshal(data, &s); err != nil {
-		return err
-	}
-	s = strings.ToUpper(s)
-	for _, v := range validCountries {
-		if v == s {
-			*c = Country(v)
-			return nil
-		}
-	}
-	return errNoValidCountry
-}
-
-func (c Country) Value() (driver.Value, error) {
-	return string(c), nil
-}
-
-func (c *Country) Scan(src interface{}) (err error) {
-	if s, ok := src.(string); ok {
-		*c = Country(s)
-	} else {
-		err = errNoString
-	}
-	return
-}
-
-var (
-	validRoles = []string{
-		"waterway_user",
-		"waterway_admin",
-		"sys_admin",
-	}
-	errNoValidRole = errors.New("Not a valid role")
-)
-
-func (r Role) Value() (driver.Value, error) {
-	return string(r), nil
-}
-
-func (r *Role) Scan(src interface{}) (err error) {
-	if s, ok := src.(string); ok {
-		*r = Role(s)
-	} else {
-		err = errNoString
-	}
-	return
-}
-
-func (r *Role) UnmarshalJSON(data []byte) error {
-	var s string
-	if err := json.Unmarshal(data, &s); err != nil {
-		return err
-	}
-	s = strings.ToLower(s)
-	for _, v := range validRoles {
-		if v == s {
-			*r = Role(v)
-			return nil
-		}
-	}
-	return errNoValidRole
-}
-
 func deleteUser(
-	input interface{}, req *http.Request,
+	_ interface{}, req *http.Request,
 	db *sql.DB,
 ) (jr JSONResult, err error) {
 
@@ -312,7 +170,7 @@
 }
 
 func listUsers(
-	input interface{}, req *http.Request,
+	_ interface{}, req *http.Request,
 	db *sql.DB,
 ) (jr JSONResult, err error) {
 
@@ -352,7 +210,7 @@
 }
 
 func listUser(
-	input interface{}, req *http.Request,
+	_ interface{}, req *http.Request,
 	db *sql.DB,
 ) (jr JSONResult, err error) {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/DEVELOPMENT.md	Tue Jul 31 15:56:11 2018 +0200
@@ -0,0 +1,25 @@
+# Development
+
+## Backend
+
+You need a working [Go](https://golang.org/dl) build environment (1.10+).
+
+* Install dependencies
+
+    `sh 3rdpartylibs`
+
+* Build
+
+    Prerequesite: compile server
+    ```
+    cd cmd/gemma/
+    go build
+    cd ../../
+    ```
+
+* Run
+    Run server with  `./cmd/gemma/gemma`
+
+## Client
+
+See [client/README](../client/README.md) for details.
--- a/schema/install-db.sh	Tue Jul 31 15:01:10 2018 +0200
+++ b/schema/install-db.sh	Tue Jul 31 15:56:11 2018 +0200
@@ -98,9 +98,8 @@
   if [[ $a == "yes" ]] ; then
     dropdb -p "$port" "$db"
     for r in `psql -p $port -t -c '\du' | awk -F '|' \
-              '$3 ~/waterway_user|waterway_admin|sys_admin/ \
-               || $1 ~/waterway_user|waterway_admin|sys_admin/ \
-               {print $1}'`
+          '$1 "." $3 ~ /waterway_user|waterway_admin|sys_admin/ \
+           {print $1}'`
     do
       dropuser -p "$port" "$r"
     done