Mercurial > gemma
view pkg/models/user.go @ 5637:7f9600ab5461
merge
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Wed, 14 Jun 2023 08:45:11 +0200 |
parents | f0c668bc4082 |
children | 6270951dda28 |
line wrap: on
line source
// This is Free Software under GNU Affero General Public License v >= 3.0 // without warranty, see README.md and license for details. // // SPDX-License-Identifier: AGPL-3.0-or-later // License-Filename: LICENSES/AGPL-3.0.txt // // Copyright (C) 2018 by via donau // – Österreichische Wasserstraßen-Gesellschaft mbH // Software engineering by Intevation GmbH // // Author(s): // * Sascha L. Teichmann <sascha.teichmann@intevation.de> // * Tom Gottfried <tom.gottfried@intevation.de> package models import ( "database/sql/driver" "encoding/json" "errors" "regexp" "strings" ) type ( // Email is a string formed by a valid EMail address. Email string // Role is a string with a valid gemma role. Role string // UserName is a string forming a valid user name. UserName string // BoundingBox is a spatial bounding box of user's // responsibility area. BoundingBox struct { X1 float64 `json:"x1"` Y1 float64 `json:"y1"` X2 float64 `json:"x2"` Y2 float64 `json:"y2"` } // User is a serialized JSON form of user data. User struct { User UserName `json:"user"` Role Role `json:"role"` Password string `json:"password,omitempty"` Email Email `json:"email"` Country Country `json:"country"` Reports bool `json:"reports"` Active bool `json:"active"` Extent *BoundingBox `json:"extent"` } // UserPatch is used to send only partial updates. UserPatch struct { User *UserName `json:"user,omitempty"` Role *Role `json:"role,omitempty"` Password *string `json:"password,omitempty"` Email *Email `json:"email,omitempty"` Country *Country `json:"country,omitempty"` Reports *bool `json:"reports,omitempty"` Active *bool `json:"active,omitempty"` Extent *BoundingBox `json:"extent,omitempty"` } // PWResetUser is send to request a password reset for a user. PWResetUser struct { User string `json:"user"` } ) 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") ) // UnmarshalJSON ensures that the given string forms 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 } // Value implements the driver.Valuer interface. func (e Email) Value() (driver.Value, error) { return string(e), nil } // Scan implements the sql.Scanner interface. func (e *Email) Scan(src interface{}) (err error) { if s, ok := src.(string); ok { *e = Email(s) } else { err = errNoString } return } var errNoValidUser = errors.New("not a valid user") // IsValid checks if a given user name is valid. func (u UserName) IsValid() bool { return u != "" } // UnmarshalJSON ensures that the given string forms a valid user name. func (u *UserName) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return err } if user := UserName(s); user.IsValid() { *u = user return nil } return errNoValidUser } // Scan implements the sql.Scanner interface. func (u *UserName) Scan(src interface{}) (err error) { if s, ok := src.(string); ok { *u = UserName(s) } else { err = errNoString } return } var ( validRoles = []string{ "waterway_user", "waterway_admin", "sys_admin", } errNoValidRole = errors.New("not a valid role") ) // Value implements the driver.Valuer interface. func (r Role) Value() (driver.Value, error) { return string(r), nil } // Scan implements the sql.Scanner interface. func (r *Role) Scan(src interface{}) (err error) { if s, ok := src.(string); ok { *r = Role(s) } else { err = errNoString } return } // UnmarshalJSON ensure that the given string is a valid user name. 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 }