annotate controllers/pwreset.go @ 314:adceb47920fb

Cosmetics. Little less structure bloat.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 01 Aug 2018 18:35:30 +0200
parents 74559e12a59f
children 3ef0521609f5
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
1 package controllers
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
2
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
3 import (
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
4 "bytes"
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
5 "database/sql"
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
6 "encoding/hex"
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
7 "log"
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
8 "math/big"
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
9 "net/http"
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
10 "os/exec"
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
11 "strings"
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
12 "sync"
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
13 "text/template"
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
14 "time"
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
15
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
16 "gemma.intevation.de/gemma/auth"
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
17 "gemma.intevation.de/gemma/config"
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
18 "github.com/gorilla/mux"
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
19
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
20 gomail "gopkg.in/gomail.v2"
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
21 )
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
22
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
23 const (
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
24 userExistsSQL = `SELECT email_address
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
25 FROM users.list_users WHERE username = $1
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
26 LIMIT 1`
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
27
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
28 updatePasswordSQL = `UPDATE users.list_users
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
29 SET pw = $1 WHERE username = $2`
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
30 )
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
31
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
32 const (
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
33 passwordResetValid = time.Hour
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
34 maxPasswordResets = 1000
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
35 maxPasswordRequestsPerUser = 5
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
36 )
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
37
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
38 var (
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
39 passwordResetRequestMailTmpl = template.Must(
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
40 template.New("request").Parse(`You have requested a password change
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
41 for your account {{ .User }} on
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
42 {{ .HTTPS }}://{{ .Server }}
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
43
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
44 Please follow this link to get to the page where you can change your password.
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
45
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
46 {{ .HTTPS }}://{{ .Server }}/api/users/passwordreset/{{ .Hash }}
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
47
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
48 The link is only valid for one hour.
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
49
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
50 Best regards
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
51 Your service team`))
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
52
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
53 passwordResetMailTmpl = template.Must(
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
54 template.New("reset").Parse(`Your password for your account {{ .User }} on
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
55 {{ .HTTPS }}://{{ .Server }}
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
56
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
57 has been changed to
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
58 {{ .Password }}
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
59
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
60 Change it as soon as possible.
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
61
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
62 Best regards
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
63 Your service team`))
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
64 )
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
65
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
66 type timedUser struct {
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
67 user string
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
68 email string
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
69 time time.Time
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
70 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
71
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
72 type resetRequests struct {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
73 sync.Mutex
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
74 reqs map[string]*timedUser
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
75 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
76
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
77 var passwordResetRequests = func() *resetRequests {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
78 rr := &resetRequests{reqs: map[string]*timedUser{}}
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
79 go func() {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
80 for {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
81 time.Sleep(2 * time.Minute)
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
82 rr.removeOutdated()
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
83 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
84 }()
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
85 return rr
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
86 }()
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
87
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
88 func (rr *resetRequests) len() int {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
89 rr.Lock()
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
90 l := len(rr.reqs)
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
91 rr.Unlock()
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
92 return l
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
93 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
94
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
95 func (rr *resetRequests) userAllowed(user string) bool {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
96 rr.Lock()
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
97 defer rr.Unlock()
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
98 var count int
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
99 for _, v := range rr.reqs {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
100 if v.user == user {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
101 if count++; count >= maxPasswordRequestsPerUser {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
102 return false
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
103 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
104 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
105 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
106 return true
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
107 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
108
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
109 func (rr *resetRequests) store(hash, user, email string) {
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
110 now := time.Now()
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
111 rr.Lock()
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
112 rr.reqs[hash] = &timedUser{user, email, now}
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
113 rr.Unlock()
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
114 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
115
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
116 func (rr *resetRequests) fetch(hash string) *timedUser {
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
117 rr.Lock()
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
118 defer rr.Unlock()
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
119 tu := rr.reqs[hash]
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
120 if tu == nil {
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
121 return nil
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
122 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
123 if tu.time.Before(time.Now().Add(-passwordResetValid)) {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
124 delete(rr.reqs, hash)
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
125 return nil
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
126 }
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
127 return tu
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
128 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
129
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
130 func (rr *resetRequests) delete(hash string) {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
131 rr.Lock()
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
132 delete(rr.reqs, hash)
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
133 rr.Unlock()
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
134 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
135
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
136 func (rr *resetRequests) removeOutdated() {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
137 good := time.Now().Add(-passwordResetValid)
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
138 rr.Lock()
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
139 defer rr.Unlock()
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
140 for k, v := range rr.reqs {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
141 if v.time.Before(good) {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
142 delete(rr.reqs, k)
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
143 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
144 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
145 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
146
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
147 func requestMessageBody(https, user, hash, server string) string {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
148 var content = struct {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
149 User string
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
150 HTTPS string
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
151 Server string
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
152 Hash string
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
153 }{
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
154 User: user,
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
155 HTTPS: https,
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
156 Server: server,
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
157 Hash: hash,
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
158 }
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
159 var buf bytes.Buffer
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
160 if err := passwordResetRequestMailTmpl.Execute(&buf, &content); err != nil {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
161 log.Printf("error: %v\n", err)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
162 }
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
163 return buf.String()
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
164 }
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
165
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
166 func changedMessageBody(https, user, password, server string) string {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
167 var content = struct {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
168 User string
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
169 HTTPS string
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
170 Server string
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
171 Password string
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
172 }{
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
173 User: user,
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
174 HTTPS: https,
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
175 Server: server,
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
176 Password: password,
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
177 }
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
178 var buf bytes.Buffer
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
179 if err := passwordResetMailTmpl.Execute(&buf, &content); err != nil {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
180 log.Printf("error: %v\n", err)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
181 }
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
182 return buf.String()
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
183 }
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
184
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
185 func useHTTPS(req *http.Request) string {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
186 if strings.ToLower(req.URL.Scheme) == "https" {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
187 return "https"
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
188 }
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
189 return "http"
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
190 }
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
191
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
192 const (
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
193 hashLength = 32
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
194 passwordLength = 20
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
195 )
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
196
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
197 func generateHash() string {
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
198 return hex.EncodeToString(auth.GenerateRandomKey(hashLength))
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
199 }
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
200
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
201 const (
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
202 base62alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
203 special = ",.!;"
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
204 )
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
205
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
206 var (
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
207 zero = big.NewInt(0)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
208 div62 = big.NewInt(62)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
209 )
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
210
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
211 func encodeToString(src []byte, max int) string {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
212 v := new(big.Int)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
213 v.SetBytes(src[1:])
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
214 m := new(big.Int)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
215 z := new(big.Int)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
216 out := make([]byte, 0, max)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
217 for {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
218 z.DivMod(v, div62, m)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
219 // reverse order but it doesnt matter.
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
220 out = append(out, base62alphabet[m.Int64()])
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
221 if len(out) == max-1 || z.Cmp(zero) == 0 {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
222 break
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
223 }
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
224 v, z = z, v
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
225 }
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
226 out = append(out, special[int(src[0])%len(special)])
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
227 return string(out)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
228 }
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
229
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
230 func generateNewPassword() string {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
231 // First try pwgen
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
232 out, err := exec.Command("pwgen", "-y", "20", "1").Output()
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
233 if err == nil {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
234 return strings.TrimSpace(string(out))
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
235 }
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
236
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
237 // Use internal base62 encoder.
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
238 return encodeToString(auth.GenerateRandomKey(20), 20)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
239
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
240 }
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
241
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
242 func sendMail(email, subject, body string) error {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
243 cfg := &config.Config
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
244 m := gomail.NewMessage()
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
245 m.SetHeader("From", cfg.MailFrom)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
246 m.SetHeader("To", email)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
247 m.SetHeader("Subject", subject)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
248 m.SetBody("text/plain", body)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
249
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
250 d := gomail.Dialer{
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
251 Host: cfg.MailHost,
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
252 Port: int(cfg.MailPort),
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
253 Username: cfg.MailUser,
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
254 Password: cfg.MailPassword,
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
255 LocalName: cfg.MailHelo,
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
256 SSL: cfg.MailPort == 465,
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
257 }
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
258
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
259 return d.DialAndSend(m)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
260 }
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
261
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
262 func passwordResetRequest(
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
263 input interface{},
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
264 req *http.Request,
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
265 db *sql.DB,
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
266 ) (jr JSONResult, err error) {
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
267
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
268 // Limit total number of password requests.
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
269 if passwordResetRequests.len() >= maxPasswordResets {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
270 err = JSONError{
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
271 Code: http.StatusServiceUnavailable,
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
272 Message: "Too much password reset request",
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
273 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
274 return
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
275 }
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
276
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
277 user := input.(*PWResetUser)
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
278
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
279 if user.User == "" {
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
280 err = JSONError{http.StatusBadRequest, "Invalid user name"}
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
281 return
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
282 }
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
283
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
284 cfg := &config.Config
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
285 if db, err = auth.OpenDB(cfg.ServiceUser, cfg.ServicePassword); err != nil {
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
286 return
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
287 }
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
288 defer db.Close()
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
289
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
290 var email string
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
291 err = db.QueryRow(userExistsSQL, user.User).Scan(&email)
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
292
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
293 switch {
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
294 case err == sql.ErrNoRows:
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
295 err = JSONError{http.StatusNotFound, "User does not exist."}
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
296 return
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
297 case err != nil:
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
298 return
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
299 }
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
300
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
301 // Limit requests per user
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
302 if !passwordResetRequests.userAllowed(user.User) {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
303 err = JSONError{
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
304 Code: http.StatusServiceUnavailable,
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
305 Message: "Too much password reset requests for user",
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
306 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
307 return
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
308 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
309
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
310 hash := generateHash()
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
311
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
312 passwordResetRequests.store(hash, user.User, email)
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
313
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
314 body := requestMessageBody(useHTTPS(req), user.User, hash, req.Host)
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
315
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
316 if err = sendMail(email, "Password Reset Link", body); err != nil {
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
317 return
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
318 }
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
319
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
320 jr.Result = &struct {
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
321 SendTo string `json:"send-to"`
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
322 }{email}
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
323
302
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
324 return
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
325 }
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
326
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
327 func passwordReset(
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
328 input interface{},
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
329 req *http.Request,
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
330 db *sql.DB,
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
331 ) (jr JSONResult, err error) {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
332
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
333 hash := mux.Vars(req)["hash"]
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
334 if _, err = hex.DecodeString(hash); err != nil {
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
335 err = JSONError{http.StatusBadRequest, "Invalid hash"}
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
336 return
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
337 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
338
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
339 tu := passwordResetRequests.fetch(hash)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
340 if tu == nil {
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
341 err = JSONError{http.StatusNotFound, "No such hash"}
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
342 return
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
343 }
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
344
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
345 password := generateNewPassword()
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
346
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
347 cfg := &config.Config
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
348 if db, err = auth.OpenDB(cfg.ServiceUser, cfg.ServicePassword); err != nil {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
349 return
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
350 }
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
351 defer db.Close()
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
352
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
353 var res sql.Result
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
354 if res, err = db.Exec(
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
355 updatePasswordSQL,
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
356 password,
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
357 tu.user,
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
358 ); err != nil {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
359 return
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
360 }
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
361
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
362 passwordResetRequests.delete(hash)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
363
311
74559e12a59f sql.Result.RowsAffected is a driver specific feature. Check
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 310
diff changeset
364 if n, err2 := res.RowsAffected(); err2 == nil && n == 0 {
314
adceb47920fb Cosmetics. Little less structure bloat.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 311
diff changeset
365 err = JSONError{http.StatusNotFound, "User not found"}
310
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
366 return
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
367 }
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
368
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
369 body := changedMessageBody(useHTTPS(req), tu.user, password, req.Host)
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
370 if err = sendMail(tu.email, "Password Reset Done", body); err != nil {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
371 return
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
372 }
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
373
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
374 jr.Result = &struct {
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
375 Message string `json:"message"`
4bee4ba6dc58 Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 304
diff changeset
376 }{"User password changed"}
304
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
377
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
378 return
69e291f26bbd Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 302
diff changeset
379 }