/
user.go
140 lines (121 loc) · 3.05 KB
/
user.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package user
import (
"crypto/md5"
"database/sql"
"encoding/hex"
"fmt"
"github.com/target/goalert/permission"
"github.com/target/goalert/validation/validate"
"github.com/google/uuid"
)
// A User is the base information of a user of the system. Authentication details are stored
// separately based on the auth provider.
//
type User struct {
// ID is the unique identifier for the user
ID string `json:"id"`
// Name is the full name of the user
Name string `json:"name"`
// Email is the primary contact email for the user. It is used for account-related communications
Email string `json:"email"`
// AvatarURL is an absolute address for an image to be used as the avatar.
AvatarURL string `json:"avatar_url"`
// AlertStatusCMID defines a contact method ID for alert status updates.
AlertStatusCMID string `json:"alert_status_log_contact_method_id"`
// The Role of the user
Role permission.Role `json:"role" store:"readonly"`
// isUserFavorite returns true if a user is favorited by the current user.
isUserFavorite bool
}
// ResolveAvatarURL will resolve the user avatar URL, using the email if none is set.
func (u User) ResolveAvatarURL(fullSize bool) string {
if u.AvatarURL == "" {
suffix := ""
if fullSize {
suffix = "&s=2048"
}
sum := md5.Sum([]byte(u.Email))
u.AvatarURL = fmt.Sprintf("https://gravatar.com/avatar/%s?d=retro%s", hex.EncodeToString(sum[:]), suffix)
}
return u.AvatarURL
}
type scanFn func(...interface{}) error
func (u *User) scanFrom(fn scanFn) error {
var statusCM sql.NullString
err := fn(
&u.ID,
&u.Name,
&u.Email,
&u.AvatarURL,
&u.Role,
&statusCM,
&u.isUserFavorite,
)
u.AlertStatusCMID = statusCM.String
return err
}
func (u *User) userUpdateFields() []interface{} {
var statusCM sql.NullString
if u.AlertStatusCMID != "" {
statusCM.Valid = true
statusCM.String = u.AlertStatusCMID
}
return []interface{}{
u.ID,
u.Name,
u.Email,
statusCM,
}
}
func (u *User) fields() []interface{} {
var statusCM sql.NullString
if u.AlertStatusCMID != "" {
statusCM.Valid = true
statusCM.String = u.AlertStatusCMID
}
return []interface{}{
u.ID,
u.Name,
u.Email,
u.AvatarURL,
u.Role,
statusCM,
}
}
// Normalize will produce a normalized/validated User struct.
func (u User) Normalize() (*User, error) {
var err error
if u.ID == "" {
u.ID = uuid.New().String()
}
if u.Email != "" {
err = validate.Email("Email", u.Email)
// Sanitize Email after it has been validated.
u.Email = validate.SanitizeEmail(u.Email)
}
if u.AvatarURL != "" {
err = validate.Many(
err,
validate.AbsoluteURL("AvatarURL", u.AvatarURL),
)
}
if u.AlertStatusCMID != "" {
err = validate.Many(
err,
validate.UUID("AlertStatusCMID", u.AlertStatusCMID),
)
}
err = validate.Many(
err,
validate.Name("Name", u.Name),
validate.OneOf("Role", u.Role, permission.RoleAdmin, permission.RoleUser),
)
if err != nil {
return nil, err
}
return &u, nil
}
// IsUserFavorite returns true if a user is a favorite of the current user.
func (u User) IsUserFavorite() bool {
return u.isUserFavorite
}