aboutsummaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/structs/admin_user.go2
-rw-r--r--modules/validation/binding.go20
-rw-r--r--modules/validation/helpers.go12
-rw-r--r--modules/validation/helpers_test.go31
-rw-r--r--modules/web/middleware/binding.go2
5 files changed, 66 insertions, 1 deletions
diff --git a/modules/structs/admin_user.go b/modules/structs/admin_user.go
index eccbf29a46..2f6f502af6 100644
--- a/modules/structs/admin_user.go
+++ b/modules/structs/admin_user.go
@@ -10,7 +10,7 @@ type CreateUserOption struct {
SourceID int64 `json:"source_id"`
LoginName string `json:"login_name"`
// required: true
- Username string `json:"username" binding:"Required;AlphaDashDot;MaxSize(40)"`
+ Username string `json:"username" binding:"Required;Username;MaxSize(40)"`
FullName string `json:"full_name" binding:"MaxSize(100)"`
// required: true
// swagger:strfmt email
diff --git a/modules/validation/binding.go b/modules/validation/binding.go
index f08f632426..c054fbe7b6 100644
--- a/modules/validation/binding.go
+++ b/modules/validation/binding.go
@@ -24,6 +24,9 @@ const (
// ErrRegexPattern is returned when a regex pattern is invalid
ErrRegexPattern = "RegexPattern"
+
+ // ErrUsername is username error
+ ErrUsername = "UsernameError"
)
// AddBindingRules adds additional binding rules
@@ -34,6 +37,7 @@ func AddBindingRules() {
addGlobPatternRule()
addRegexPatternRule()
addGlobOrRegexPatternRule()
+ addUsernamePatternRule()
}
func addGitRefNameBindingRule() {
@@ -148,6 +152,22 @@ func addGlobOrRegexPatternRule() {
})
}
+func addUsernamePatternRule() {
+ binding.AddRule(&binding.Rule{
+ IsMatch: func(rule string) bool {
+ return rule == "Username"
+ },
+ IsValid: func(errs binding.Errors, name string, val interface{}) (bool, binding.Errors) {
+ str := fmt.Sprintf("%v", val)
+ if !IsValidUsername(str) {
+ errs.Add([]string{name}, ErrUsername, "invalid username")
+ return false, errs
+ }
+ return true, errs
+ },
+ })
+}
+
func portOnly(hostport string) string {
colon := strings.IndexByte(hostport, ':')
if colon == -1 {
diff --git a/modules/validation/helpers.go b/modules/validation/helpers.go
index 484b12b2a2..8e49c7855e 100644
--- a/modules/validation/helpers.go
+++ b/modules/validation/helpers.go
@@ -91,3 +91,15 @@ func IsValidExternalTrackerURLFormat(uri string) bool {
return true
}
+
+var (
+ validUsernamePattern = regexp.MustCompile(`^[\da-zA-Z][-.\w]*$`)
+ invalidUsernamePattern = regexp.MustCompile(`[-._]{2,}|[-._]$`) // No consecutive or trailing non-alphanumeric chars
+)
+
+// IsValidUsername checks if username is valid
+func IsValidUsername(name string) bool {
+ // It is difficult to find a single pattern that is both readable and effective,
+ // but it's easier to use positive and negative checks.
+ return validUsernamePattern.MatchString(name) && !invalidUsernamePattern.MatchString(name)
+}
diff --git a/modules/validation/helpers_test.go b/modules/validation/helpers_test.go
index f6f897e821..9bdbdb4a77 100644
--- a/modules/validation/helpers_test.go
+++ b/modules/validation/helpers_test.go
@@ -155,3 +155,34 @@ func Test_IsValidExternalTrackerURLFormat(t *testing.T) {
})
}
}
+
+func TestIsValidUsername(t *testing.T) {
+ tests := []struct {
+ arg string
+ want bool
+ }{
+ {arg: "a", want: true},
+ {arg: "abc", want: true},
+ {arg: "0.b-c", want: true},
+ {arg: "a.b-c_d", want: true},
+ {arg: "", want: false},
+ {arg: ".abc", want: false},
+ {arg: "abc.", want: false},
+ {arg: "a..bc", want: false},
+ {arg: "a...bc", want: false},
+ {arg: "a.-bc", want: false},
+ {arg: "a._bc", want: false},
+ {arg: "a_-bc", want: false},
+ {arg: "a/bc", want: false},
+ {arg: "☁️", want: false},
+ {arg: "-", want: false},
+ {arg: "--diff", want: false},
+ {arg: "-im-here", want: false},
+ {arg: "a space", want: false},
+ }
+ for _, tt := range tests {
+ t.Run(tt.arg, func(t *testing.T) {
+ assert.Equalf(t, tt.want, IsValidUsername(tt.arg), "IsValidUsername(%v)", tt.arg)
+ })
+ }
+}
diff --git a/modules/web/middleware/binding.go b/modules/web/middleware/binding.go
index 636e655b9e..cced9717be 100644
--- a/modules/web/middleware/binding.go
+++ b/modules/web/middleware/binding.go
@@ -135,6 +135,8 @@ func Validate(errs binding.Errors, data map[string]interface{}, f Form, l transl
data["ErrorMsg"] = trName + l.Tr("form.glob_pattern_error", errs[0].Message)
case validation.ErrRegexPattern:
data["ErrorMsg"] = trName + l.Tr("form.regex_pattern_error", errs[0].Message)
+ case validation.ErrUsername:
+ data["ErrorMsg"] = trName + l.Tr("form.username_error")
default:
msg := errs[0].Classification
if msg != "" && errs[0].Message != "" {
table29'>backport/47848/stable29 Nextcloud server, a safe home for all your data: https://github.com/nextcloud/serverwww-data
summaryrefslogtreecommitdiffstats
path: root/issue_template.md
blob: e614ea0aed0ac9db61570a8d6372742a4f808c21 (plain)
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