/
form.go
178 lines (146 loc) · 4.41 KB
/
form.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
package oauth2
import (
"net/url"
"strings"
"djinn-ci.com/errors"
"github.com/andrewpillar/query"
"github.com/andrewpillar/webutil"
)
// AppForm if the type that represents input data for creating a new App.
type AppForm struct {
Apps *AppStore `schema:"-"`
App *App `schema:"-"`
Name string `schema:"name"`
Description string `schema:"description"`
HomepageURI string `schema:"homepage_uri"`
RedirectURI string `schema:"redirect_uri"`
}
// AuthorizeForm is the type that represents input data of the OAuth
// authorization page, for when a user authorizes an App's access to their
// account.
type AuthorizeForm struct {
Authorize bool `schema:"bool"`
ClientID string `schema:"client_id"`
Handle string `schema:"handle"`
Password string `schema:"password"`
Scope string `schema:"scope"`
State string `schema:"state"`
RedirectURI string `schema:"redirect_uri"`
}
// TokenForm is the type that represents the input data for creating a new
// Token.
type TokenForm struct {
Tokens *TokenStore `schema:"-"`
Token *Token `schema:"-"`
Name string `schema:"name"`
Scope []string `schema:"scope[]"`
}
var (
_ webutil.Form = (*AppForm)(nil)
_ webutil.Form = (*AuthorizeForm)(nil)
_ webutil.Form = (*TokenForm)(nil)
)
// Fields returns a map of the name, description, homepage_uri, and
// redirect_uri fields for the current AppForm.
func (f AppForm) Fields() map[string]string {
return map[string]string{
"name": f.Name,
"description": f.Description,
"homepage_uri": f.HomepageURI,
"redirect_uri": f.RedirectURI,
}
}
// Validate checks to see if the Name field is present in the form, and is
// unique. This uniqueness check is skipped if an App is set on the form, and
// the Name field already matches that name (assuming it's being edited). The
// Homepage, and Redirect URIs are checked for presence too, and if they are
// valid URLs.
func (f AppForm) Validate() error {
errs := webutil.NewErrors()
if f.Name == "" {
errs.Put("name", webutil.ErrFieldRequired("Name"))
}
checkUnique := true
if f.App != nil {
if f.App.Name == f.Name {
checkUnique = false
}
}
if checkUnique {
a, err := f.Apps.Get(query.Where("name", "=", query.Arg(f.Name)))
if err != nil {
return errors.Err(err)
}
if !a.IsZero() {
errs.Put("name", webutil.ErrFieldExists("Name"))
}
}
if f.HomepageURI == "" {
errs.Put("homepage_uri", webutil.ErrFieldRequired("Homepage URI"))
}
if _, err := url.Parse(f.HomepageURI); err != nil {
errs.Put("homepage_uri", webutil.ErrField("Homepage URI", err))
}
if f.RedirectURI == "" {
errs.Put("redirect_uri", webutil.ErrFieldRequired("Redirect URI"))
}
if _, err := url.Parse(f.RedirectURI); err != nil {
errs.Put("redirect_uri", webutil.ErrField("Redirect URI", err))
}
return errs.Err()
}
// Fields returns a map of fields for the current AuthorizeForm. This map will
// contain the Handle field of the current AuthorizeForm.
func (f AuthorizeForm) Fields() map[string]string {
return map[string]string{
"handle": f.Handle,
}
}
// Validate checks to see if the Handle, and Password fields are present in the
// current AuthorizeForm.
func (f AuthorizeForm) Validate() error {
if !f.Authorize {
return nil
}
errs := webutil.NewErrors()
if f.Handle == "" {
errs.Put("handle", webutil.ErrFieldRequired("Email or username"))
}
if f.Password == "" {
errs.Put("password", webutil.ErrFieldRequired("Password"))
}
return errs.Err()
}
// Fields returns a map of the Name, and Scope fields in the current TokenForm.
// The Scope field is serialized into a space delimited string of the scopes.
func (f TokenForm) Fields() map[string]string {
return map[string]string{
"name": f.Name,
"scope": strings.Join(f.Scope, " "),
}
}
// Validate cheks to see if the Name field is present in the form, and if it is
// unique. This uniquess check is skipped if a Token is set on the form, and
// Name field matches that.
func (f TokenForm) Validate() error {
errs := webutil.NewErrors()
if f.Name == "" {
errs.Put("name", webutil.ErrFieldRequired("Name"))
}
checkUnique := true
if f.Token != nil {
if f.Token.Name == f.Name {
checkUnique = false
}
}
if checkUnique {
t, err := f.Tokens.Get(query.Where("name", "=", query.Arg(f.Name)))
if err != nil {
return errors.Err(err)
}
if !t.IsZero() {
errs.Put("name", webutil.ErrFieldExists("Name"))
}
}
return errs.Err()
}