-
Notifications
You must be signed in to change notification settings - Fork 28
/
util.go
161 lines (139 loc) · 3.59 KB
/
util.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
package webapp
import (
"image"
"net/url"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/qr"
"github.com/iawaknahc/jsonschema/pkg/jsonpointer"
"github.com/authgear/authgear-server/pkg/api/model"
"github.com/authgear/authgear-server/pkg/auth/webapp"
"github.com/authgear/authgear-server/pkg/lib/config"
)
func FormToJSON(form url.Values) map[string]interface{} {
j := make(map[string]interface{})
// Do not support recurring parameter
for name := range form {
value := form.Get(name)
if value != "" {
j[name] = value
}
}
return j
}
func JSONPointerFormToMap(form url.Values) map[string]string {
out := make(map[string]string)
for ptrStr := range form {
val := form.Get(ptrStr)
_, err := jsonpointer.Parse(ptrStr)
if err != nil {
// ignore this field because it does not seem a valid json pointer.
continue
}
out[ptrStr] = val
}
return out
}
type FormPrefiller struct {
LoginID *config.LoginIDConfig
UI *config.UIConfig
}
//nolint:gocognit
func (p *FormPrefiller) Prefill(form url.Values) {
hasEmail := false
hasUsername := false
for _, k := range p.LoginID.Keys {
switch k.Type {
case model.LoginIDKeyTypeEmail:
hasEmail = true
case model.LoginIDKeyTypeUsername:
hasUsername = true
}
}
nonPhoneLoginIDInputType := "text"
if hasEmail && !hasUsername {
nonPhoneLoginIDInputType = "email"
}
// Set q_login_id_input_type to the type of the first login ID.
if _, ok := form["q_login_id_input_type"]; !ok {
// When SIWE is enabled, keys will be empty.
// but q_login_id_input_type should always be there.
if len(p.LoginID.Keys) > 0 {
if string(p.LoginID.Keys[0].Type) == "phone" {
form.Set("q_login_id_input_type", "phone")
} else {
form.Set("q_login_id_input_type", nonPhoneLoginIDInputType)
}
} else {
form.Set("q_login_id_input_type", "text")
}
}
// Set q_login_id_key to match q_login_id_input_type
if inKey := form.Get("q_login_id_key"); inKey == "" {
Switch:
switch form.Get("q_login_id_input_type") {
case "phone":
for _, k := range p.LoginID.Keys {
if k.Type == model.LoginIDKeyTypePhone {
form.Set("q_login_id_key", k.Key)
break Switch
}
}
case "email":
for _, k := range p.LoginID.Keys {
if k.Type == model.LoginIDKeyTypeEmail {
form.Set("q_login_id_key", k.Key)
break Switch
}
}
case "text":
fallthrough
default:
for _, k := range p.LoginID.Keys {
if k.Type != model.LoginIDKeyTypePhone {
form.Set("q_login_id_key", k.Key)
break Switch
}
}
}
}
}
func CreateQRCodeImage(content string, width int, height int, level qr.ErrorCorrectionLevel) (image.Image, error) {
b, err := qr.Encode(content, level, qr.Auto)
if err != nil {
return nil, err
}
b, err = barcode.Scale(b, width, height)
if err != nil {
return nil, err
}
return b, nil
}
func FindLoginIDInPreviousInput(s *webapp.Session, xStep string) (string, bool) {
if s.Authflow == nil {
return "", false
}
for {
screen := s.Authflow.AllScreens[xStep]
if screen == nil {
return "", false
}
if screen.PreviousInput != nil {
previousInput := screen.PreviousInput
if loginID, ok := previousInput["login_id"].(string); ok {
return loginID, true
}
}
if screen.BranchStateToken != nil {
branchXStep := screen.BranchStateToken.XStep
branchScreen := s.Authflow.AllScreens[branchXStep]
if branchScreen != nil {
previousInput := branchScreen.PreviousInput
if loginID, ok := previousInput["login_id"].(string); ok {
return loginID, true
}
}
}
// Otherwise update xStep and find recursively.
xStep = screen.PreviousXStep
}
}