comparison pkg/controllers/user.go @ 5345:95dafb72a288 extented-report

Added a PATCH endpoint for /api/users/{user}
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Sun, 20 Jun 2021 04:17:53 +0200
parents b1b9b384540d
children 566c8063223b
comparison
equal deleted inserted replaced
5344:7df6062a1371 5345:95dafb72a288
19 "bytes" 19 "bytes"
20 "database/sql" 20 "database/sql"
21 "fmt" 21 "fmt"
22 "log" 22 "log"
23 "net/http" 23 "net/http"
24 "strconv"
25 "strings"
24 "text/template" 26 "text/template"
25 "time" 27 "time"
26 28
27 "github.com/gorilla/mux" 29 "github.com/gorilla/mux"
28 30
243 }{"success"}, 245 }{"success"},
244 } 246 }
245 return 247 return
246 } 248 }
247 249
250 func patchUser(req *http.Request) (jr mw.JSONResult, err error) {
251
252 user := models.UserName(mux.Vars(req)["user"])
253 if !user.IsValid() {
254 err = mw.JSONError{
255 Code: http.StatusBadRequest,
256 Message: "error: user invalid",
257 }
258 return
259 }
260
261 s, ok := auth.GetSession(req)
262 if !ok {
263 err = mw.JSONError{
264 Code: http.StatusUnauthorized,
265 Message: "error: not logged in",
266 }
267 return
268 }
269
270 priv := s.Roles.Has("sys_admin")
271
272 if !priv && s.User != string(user) {
273 err = mw.JSONError{
274 Code: http.StatusUnauthorized,
275 Message: "error: not allowed to modify someone else",
276 }
277 return
278 }
279
280 var (
281 columns []string
282 positions []string
283 args []interface{}
284 )
285
286 update := func(column string, value interface{}) {
287 columns = append(columns, column)
288 positions = append(positions, "$"+strconv.Itoa(len(positions)+1))
289 args = append(args, value)
290 }
291
292 updateBox := func(column string, extent *models.BoundingBox) {
293 columns = append(columns, column)
294 pos := len(positions)
295 position := fmt.Sprintf("ST_MakeBox2D(ST_Point($%d, $%d), ST_Point($%d, $%d))",
296 pos+1, pos+2, pos+3, pos+4)
297 positions = append(positions, position)
298 args = append(args, extent.X1, extent.Y1, extent.X2, extent.Y2)
299 }
300
301 patch := mw.JSONInput(req).(*models.UserPatch)
302
303 if patch.User != nil && priv {
304 update("user", *patch.User)
305 }
306 if patch.Role != nil && priv {
307 update("rolname", *patch.Role)
308 }
309 if patch.Password != nil {
310 update("pw", *patch.Password)
311 }
312 if patch.Email != nil {
313 update("email_address", *patch.Email)
314 }
315 if patch.Country != nil && priv {
316 update("country", *patch.Country)
317 }
318 if patch.Reports != nil && priv {
319 update("report_reciever", *patch.Reports)
320 }
321 if patch.Extent != nil {
322 updateBox("map_extent", patch.Extent)
323 }
324
325 var colsS, posS string
326
327 switch len(columns) {
328 case 0: // Nothing to do
329 jr = mw.JSONResult{
330 Code: http.StatusCreated,
331 Result: struct {
332 Result string `json:"result"`
333 }{"success"},
334 }
335 return
336 case 1: // No brackets if there is only one argument.
337 colsS = columns[0]
338 posS = positions[0]
339 default:
340 colsS = "(" + strings.Join(columns, ",") + ")"
341 posS = "(" + strings.Join(positions, ",") + ")"
342 }
343
344 stmt := fmt.Sprintf(
345 `UPDATE users.list_users SET %s = %s WHERE username = $%d`,
346 colsS,
347 posS,
348 len(positions)+1)
349
350 args = append(args, user)
351
352 db := mw.JSONConn(req)
353
354 var res sql.Result
355 if res, err = db.ExecContext(req.Context(), stmt, args...); err != nil {
356 return
357 }
358
359 if n, err2 := res.RowsAffected(); err2 == nil && n == 0 {
360 err = mw.JSONError{
361 Code: http.StatusNotFound,
362 Message: fmt.Sprintf("Cannot find user %s.", user),
363 }
364 return
365 }
366
367 if patch.User != nil && *patch.User != user {
368 // Running in a go routine should not be necessary.
369 go func() { auth.Sessions.Logout(string(user)) }()
370 }
371
372 jr = mw.JSONResult{
373 Code: http.StatusCreated,
374 Result: struct {
375 Result string `json:"result"`
376 }{"success"},
377 }
378 return
379 }
380
248 func createUser(req *http.Request) (jr mw.JSONResult, err error) { 381 func createUser(req *http.Request) (jr mw.JSONResult, err error) {
249 382
250 user := mw.JSONInput(req).(*models.User) 383 user := mw.JSONInput(req).(*models.User)
251 384
252 db := mw.JSONConn(req) 385 db := mw.JSONConn(req)