annotate controllers/pwreset.go @ 302:0777aa6de45b

Password reset. Part I
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 01 Aug 2018 12:29:55 +0200
parents
children 69e291f26bbd
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 (
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
4 "database/sql"
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
5 "encoding/hex"
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
6 "fmt"
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
7 "log"
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
8 "net/http"
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
9 "strings"
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
10
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
11 "gemma.intevation.de/gemma/auth"
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
12 "gemma.intevation.de/gemma/config"
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
13 gomail "gopkg.in/gomail.v2"
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
14 )
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 const (
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
17 userExistsSQL = `SELECT email_address
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
18 FROM users.list_users WHERE username = $1
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
19 LIMIT 1`
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
20 )
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 const (
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
23 mailTmpl = `You have requested a password change for your account on
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
24 %s://%s
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
25
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
26 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
27
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
28 %s://%s/#/users/passwordreset/%s
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 The link is only valid for one hour.
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 Best regards
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
33 Your service team`
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
34 )
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
35
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
36 func messageBody(https bool, hash, serverName string) string {
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
37
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
38 var proto string
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
39
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
40 if https {
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
41 proto = "https"
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
42 } else {
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
43 proto = "http"
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
44 }
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
45
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
46 return fmt.Sprintf(mailTmpl,
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
47 proto, serverName,
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
48 proto, serverName,
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
49 hash)
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
50 }
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
51
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
52 const hashLength = 32
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
53
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
54 func generateHash() string {
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
55 return hex.EncodeToString(auth.GenerateRandomKey(hashLength))
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
56 }
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
57
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
58 func passwordReset(
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
59 input interface{},
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
60 req *http.Request,
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
61 db *sql.DB,
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
62 ) (jr JSONResult, err error) {
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 log.Println("passwordreset")
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
65
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
66 user := input.(*PWResetUser)
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
67
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
68 if user.User == "" {
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
69 err = JSONError{http.StatusBadRequest, "Invalid user name"}
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
70 return
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
71 }
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
72
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
73 cfg := &config.Config
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
74
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
75 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
76 return
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
77 }
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
78 defer db.Close()
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
79
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
80 var email string
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
81 err = db.QueryRow(userExistsSQL, user.User).Scan(&email)
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
82
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
83 switch {
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
84 case err == sql.ErrNoRows:
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
85 err = JSONError{http.StatusNotFound, "User does not exist."}
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
86 return
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
87 case err != nil:
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
88 return
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
89 }
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
90
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
91 hash := generateHash()
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
92
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
93 serverName := req.Host
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
94 useHTTPS := strings.ToLower(req.URL.Scheme) == "https"
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
95
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
96 body := messageBody(useHTTPS, hash, serverName)
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
97
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
98 m := gomail.NewMessage()
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
99 m.SetHeader("From", cfg.MailFrom)
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
100 m.SetHeader("To", email)
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
101 m.SetHeader("Subject", "Password Reset Link")
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
102 m.SetBody("text/plain", body)
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
103
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
104 d := gomail.Dialer{
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
105 Host: cfg.MailHost,
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
106 Port: int(cfg.MailPort),
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
107 Username: cfg.MailUser,
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
108 Password: cfg.MailPassword,
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
109 LocalName: cfg.MailHelo,
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
110 SSL: cfg.MailPort == 465,
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
111 }
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
112
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
113 if err = d.DialAndSend(m); err != nil {
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
114 return
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
115 }
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
116
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
117 // TODO: Keep hash/user for one hour or till resolved.
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
118
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
119 jr.Result = &struct {
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
120 SendTo string `json:"send-to"`
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
121 }{
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
122 SendTo: email,
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
123 }
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
124 return
0777aa6de45b Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
125 }