comparison controllers/user.go @ 226:63dd5216eee4

Refactored gemma server to be more REST-like.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 26 Jul 2018 12:24:30 +0200
parents cmd/gemma/user.go@bcd9016dcd4d
children 7d1f0ffdfa41
comparison
equal deleted inserted replaced
225:8b9cae6d3a21 226:63dd5216eee4
1 package controllers
2
3 import (
4 "database/sql"
5 "encoding/json"
6 "errors"
7 "log"
8 "net/http"
9 "regexp"
10 "strings"
11
12 "gemma.intevation.de/gemma/auth"
13 "github.com/jackc/pgx"
14 )
15
16 type (
17 Email string
18 Country string
19 Role string
20
21 BoundingBox struct {
22 X1 float64 `json:"x1"`
23 Y1 float64 `json:"y1"`
24 X2 float64 `json:"x2"`
25 Y2 float64 `json:"y2"`
26 }
27
28 User struct {
29 User string `json:"user"`
30 Role Role `json:"role"`
31 Password string `json:"password"`
32 Email Email `json:"email"`
33 Country Country `json:"country"`
34 Extent *BoundingBox `json:"extent"`
35 }
36 )
37
38 const (
39 createUserSQL = `SELECT sys_admin.create_user($1, $2, $3, $4, NULL, $5)`
40 createUserExtentSQL = `SELECT sys_admin.create_user($1, $2, $3, $4,
41 ST_MakeBox2D(ST_Point($5, $6), ST_Point($7, $8)), $9)`
42 )
43
44 var (
45 // https://stackoverflow.com/questions/201323/how-to-validate-an-email-address-using-a-regular-expression
46 emailRe = regexp.MustCompile(
47 `(?:[a-z0-9!#$%&'*+/=?^_` + "`" +
48 `{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_` + "`" +
49 `{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]` +
50 `|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")` +
51 `@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?` +
52 `|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}` +
53 `(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]` +
54 `:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]` +
55 `|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])`)
56 errNoEmailAddress = errors.New("Not a valid email address")
57 )
58
59 func (e *Email) UnmarshalJSON(data []byte) error {
60 var s string
61 if err := json.Unmarshal(data, &s); err != nil {
62 return err
63 }
64 if !emailRe.MatchString(s) {
65 return errNoEmailAddress
66 }
67 *e = Email(s)
68 return nil
69 }
70
71 var (
72 validCountries = []string{
73 "AT", "BG", "DE", "HU", "HR",
74 "MD", "RO", "RS", "SK", "UA",
75 }
76 errNoValidCountry = errors.New("Not a valid country")
77 )
78
79 func (c *Country) UnmarshalJSON(data []byte) error {
80 var s string
81 if err := json.Unmarshal(data, &s); err != nil {
82 return err
83 }
84 s = strings.ToUpper(s)
85 for _, v := range validCountries {
86 if v == s {
87 *c = Country(v)
88 return nil
89 }
90 }
91 return errNoValidCountry
92 }
93
94 var (
95 validRoles = []string{
96 "waterway_user",
97 "waterway_admin",
98 "sys_admin",
99 }
100 errNoValidRole = errors.New("Not a valid role")
101 )
102
103 func (r *Role) UnmarshalJSON(data []byte) error {
104 var s string
105 if err := json.Unmarshal(data, &s); err != nil {
106 return err
107 }
108 s = strings.ToLower(s)
109 for _, v := range validRoles {
110 if v == s {
111 *r = Role(v)
112 return nil
113 }
114 }
115 return errNoValidRole
116 }
117
118 func createUser(rw http.ResponseWriter, req *http.Request) {
119
120 var user User
121
122 defer req.Body.Close()
123 if err := json.NewDecoder(req.Body).Decode(&user); err != nil {
124 http.Error(rw, "error: "+err.Error(), http.StatusBadRequest)
125 return
126 }
127
128 token, _ := auth.GetToken(req)
129 err := auth.ConnPool.Do(token, func(db *sql.DB) (err error) {
130 if user.Extent == nil {
131 _, err = db.Exec(
132 createUserSQL,
133 string(user.Role),
134 user.User,
135 user.Password,
136 string(user.Country),
137 string(user.Email),
138 )
139 } else {
140 _, err = db.Exec(
141 createUserExtentSQL,
142 string(user.Role),
143 user.User,
144 user.Password,
145 string(user.Country),
146 user.Extent.X1, user.Extent.Y1,
147 user.Extent.X2, user.Extent.Y2,
148 string(user.Email),
149 )
150 }
151 return
152 })
153
154 var res struct {
155 Result string `json:"result"`
156 Code string `json:"code,omitempty"`
157 Message string `json:"message,omitempty"`
158 }
159
160 if err != nil {
161 if pgErr, ok := err.(pgx.PgError); ok {
162 res.Result = "failure"
163 res.Code = pgErr.Code
164 res.Message = pgErr.Message
165 } else {
166 log.Printf("err: %v\n", err)
167 http.Error(rw,
168 "error: "+err.Error(),
169 http.StatusInternalServerError)
170 return
171 }
172 } else {
173 res.Result = "success"
174 }
175
176 rw.Header().Set("Content-Type", "application/json")
177 if err := json.NewEncoder(rw).Encode(&res); err != nil {
178 log.Printf("error: %v\n", err)
179 }
180 }