annotate controllers/pwreset.go @ 315:3ef0521609f5

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