-
Notifications
You must be signed in to change notification settings - Fork 208
/
user.go
197 lines (164 loc) · 5.61 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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
package authboss
import (
"fmt"
"strings"
"time"
"github.com/friendsofgo/errors"
)
// User has functions for each piece of data it requires.
// Data should not be persisted on each function call.
// User has a PID (primary ID) that is used on the site as
// a single unique identifier to any given user (very typically e-mail
// or username).
//
// User interfaces return no errors or bools to signal that a value was
// not present. Instead 0-value = null = not present, this puts the onus
// on Authboss code to check for this.
type User interface {
GetPID() (pid string)
PutPID(pid string)
}
// AuthableUser is identified by a password
type AuthableUser interface {
User
GetPassword() (password string)
PutPassword(password string)
}
// ConfirmableUser can be in a state of confirmed or not
type ConfirmableUser interface {
User
GetEmail() (email string)
GetConfirmed() (confirmed bool)
GetConfirmSelector() (selector string)
GetConfirmVerifier() (verifier string)
PutEmail(email string)
PutConfirmed(confirmed bool)
PutConfirmSelector(selector string)
PutConfirmVerifier(verifier string)
}
// LockableUser is a user that can be locked
type LockableUser interface {
User
GetAttemptCount() (attempts int)
GetLastAttempt() (last time.Time)
GetLocked() (locked time.Time)
PutAttemptCount(attempts int)
PutLastAttempt(last time.Time)
PutLocked(locked time.Time)
}
// RecoverableUser is a user that can be recovered via e-mail
type RecoverableUser interface {
AuthableUser
GetEmail() (email string)
GetRecoverSelector() (selector string)
GetRecoverVerifier() (verifier string)
GetRecoverExpiry() (expiry time.Time)
PutEmail(email string)
PutRecoverSelector(selector string)
PutRecoverVerifier(verifier string)
PutRecoverExpiry(expiry time.Time)
}
type RecoverableUserWithSecondaryEmails interface {
RecoverableUser
GetSecondaryEmails() (secondaryEmails []string)
}
// ArbitraryUser allows arbitrary data from the web form through. You should
// definitely only pull the keys you want from the map, since this is unfiltered
// input from a web request and is an attack vector.
type ArbitraryUser interface {
User
// GetArbitrary is used only to display the arbitrary data back to the user
// when the form is reset.
GetArbitrary() (arbitrary map[string]string)
// PutArbitrary allows arbitrary fields defined by the authboss library
// consumer to add fields to the user registration piece.
PutArbitrary(arbitrary map[string]string)
}
// OAuth2User allows reading and writing values relating to OAuth2
// Also see MakeOAuthPID/ParseOAuthPID for helpers to fulfill the User
// part of the interface.
type OAuth2User interface {
User
// IsOAuth2User checks to see if a user was registered in the site as an
// oauth2 user.
IsOAuth2User() bool
GetOAuth2UID() (uid string)
GetOAuth2Provider() (provider string)
GetOAuth2AccessToken() (token string)
GetOAuth2RefreshToken() (refreshToken string)
GetOAuth2Expiry() (expiry time.Time)
PutOAuth2UID(uid string)
PutOAuth2Provider(provider string)
PutOAuth2AccessToken(token string)
PutOAuth2RefreshToken(refreshToken string)
PutOAuth2Expiry(expiry time.Time)
}
// MustBeAuthable forces an upgrade to an AuthableUser or panic.
func MustBeAuthable(u User) AuthableUser {
if au, ok := u.(AuthableUser); ok {
return au
}
panic(fmt.Sprintf("could not upgrade user to an authable user, type: %T", u))
}
// MustBeConfirmable forces an upgrade to a ConfirmableUser or panic.
func MustBeConfirmable(u User) ConfirmableUser {
if cu, ok := u.(ConfirmableUser); ok {
return cu
}
panic(fmt.Sprintf("could not upgrade user to a confirmable user, type: %T", u))
}
// MustBeLockable forces an upgrade to a LockableUser or panic.
func MustBeLockable(u User) LockableUser {
if lu, ok := u.(LockableUser); ok {
return lu
}
panic(fmt.Sprintf("could not upgrade user to a lockable user, given type: %T", u))
}
// MustBeRecoverable forces an upgrade to a RecoverableUser or panic.
func MustBeRecoverable(u User) RecoverableUser {
if lu, ok := u.(RecoverableUser); ok {
return lu
}
panic(fmt.Sprintf("could not upgrade user to a recoverable user, given type: %T", u))
}
func CanBeRecoverableUserWithSecondaryEmails(u User) (RecoverableUserWithSecondaryEmails, bool) {
if lu, ok := u.(RecoverableUserWithSecondaryEmails); ok {
return lu, true
}
return nil, false
}
// MustBeOAuthable forces an upgrade to an OAuth2User or panic.
func MustBeOAuthable(u User) OAuth2User {
if ou, ok := u.(OAuth2User); ok {
return ou
}
panic(fmt.Sprintf("could not upgrade user to an oauthable user, given type: %T", u))
}
// MakeOAuth2PID is used to create a pid for users that don't have
// an e-mail address or username in the normal system. This allows
// all the modules to continue to working as intended without having
// a true primary id. As well as not having to divide the regular and oauth
// stuff all down the middle.
func MakeOAuth2PID(provider, uid string) string {
return fmt.Sprintf("oauth2;;%s;;%s", provider, uid)
}
// ParseOAuth2PID returns the uid and provider for a given OAuth2 pid
func ParseOAuth2PID(pid string) (provider, uid string, err error) {
splits := strings.Split(pid, ";;")
if len(splits) != 3 {
return "", "", errors.Errorf("failed to parse oauth2 pid, too many segments: %s", pid)
}
if splits[0] != "oauth2" {
return "", "", errors.Errorf("invalid oauth2 pid, did not start with oauth2: %s", pid)
}
return splits[1], splits[2], nil
}
// ParseOAuth2PIDP returns the uid and provider for a given OAuth2 pid
func ParseOAuth2PIDP(pid string) (provider, uid string) {
var err error
provider, uid, err = ParseOAuth2PID(pid)
if err != nil {
panic(err)
}
return provider, uid
}