|
| 1 | +package controller |
| 2 | + |
| 3 | +import ( |
| 4 | + "config" |
| 5 | + "filter" |
| 6 | + "fmt" |
| 7 | + "github.com/gorilla/sessions" |
| 8 | + "github.com/studygolang/mux" |
| 9 | + "html/template" |
| 10 | + "logger" |
| 11 | + "net/http" |
| 12 | + "service" |
| 13 | + "strings" |
| 14 | + "util" |
| 15 | +) |
| 16 | + |
| 17 | +// 用户注册 |
| 18 | +// uri: /account/register{json:(|.json)} |
| 19 | +func RegisterHandler(rw http.ResponseWriter, req *http.Request) { |
| 20 | + vars := mux.Vars(req) |
| 21 | + username := req.FormValue("username") |
| 22 | + // 请求注册页面 |
| 23 | + if username == "" || req.Method != "POST" || vars["json"] == "" { |
| 24 | + req.Form.Set(filter.CONTENT_TPL_KEY, "/template/register.html") |
| 25 | + return |
| 26 | + } |
| 27 | + |
| 28 | + // 入库 |
| 29 | + errMsg, err := service.CreateUser(req.Form) |
| 30 | + if err != nil { |
| 31 | + fmt.Fprint(rw, `{"errno": 1, "error":"`, errMsg, `"}`) |
| 32 | + return |
| 33 | + } |
| 34 | + // 注册成功,自动为其登录 |
| 35 | + setCookie(rw, req, req.FormValue("username")) |
| 36 | + // 发送欢迎邮件 |
| 37 | + go sendWelcomeMail([]string{req.FormValue("email")}) |
| 38 | + fmt.Fprint(rw, `{"errno": 0, "error":""}`) |
| 39 | +} |
| 40 | + |
| 41 | +func sendWelcomeMail(email []string) { |
| 42 | + content := `Welcome to Study Golang. |
| 43 | +欢迎您,成功注册成为 Golang中文社区 | Go语言学习园地 会员 |
| 44 | +
|
| 45 | +Study Golang 是一个Go语言技术社区,完全用Go语言开发。我们为gopher们提供一个好的学习交流场所。加入到社区中来,参与分享,学习,不断提高吧。前往 <a href="http://studygolang.com">Golang中文社区 | Go语言学习园地</a>` |
| 46 | + service.SendMail("Golang中文社区 | Go语言学习园地 注册成功通知", content, email) |
| 47 | +} |
| 48 | + |
| 49 | +// 登录 |
| 50 | +// uri : /account/login |
| 51 | +func LoginHandler(rw http.ResponseWriter, req *http.Request) { |
| 52 | + username := req.FormValue("username") |
| 53 | + if username == "" || req.Method != "POST" { |
| 54 | + req.Form.Set(filter.CONTENT_TPL_KEY, "/template/login.html") |
| 55 | + return |
| 56 | + } |
| 57 | + // 处理用户登录 |
| 58 | + passwd := req.FormValue("passwd") |
| 59 | + userLogin, err := service.Login(username, passwd) |
| 60 | + if err != nil { |
| 61 | + req.Form.Set(filter.CONTENT_TPL_KEY, "/template/login.html") |
| 62 | + filter.SetData(req, map[string]interface{}{"username": username, "error": err.Error()}) |
| 63 | + return |
| 64 | + } |
| 65 | + logger.Debugf("remember_me is %q\n", req.FormValue("remember_me")) |
| 66 | + // 登录成功,种cookie |
| 67 | + setCookie(rw, req, userLogin.Username) |
| 68 | + |
| 69 | + util.Redirect(rw, req, "/") |
| 70 | +} |
| 71 | + |
| 72 | +// 用户编辑个人信息 |
| 73 | +func AccountEditHandler(rw http.ResponseWriter, req *http.Request) { |
| 74 | + vars := mux.Vars(req) |
| 75 | + username := req.FormValue("username") |
| 76 | + curUser, _ := filter.CurrentUser(req) |
| 77 | + // 请求注册页面 |
| 78 | + if username == "" || req.Method != "POST" || vars["json"] == "" { |
| 79 | + // 获取用户信息 |
| 80 | + user := service.FindUserByUsername(curUser["username"].(string)) |
| 81 | + // 设置模板数据 |
| 82 | + filter.SetData(req, map[string]interface{}{"activeUsers": "active", "user": user}) |
| 83 | + req.Form.Set(filter.CONTENT_TPL_KEY, "/template/user/edit.html") |
| 84 | + return |
| 85 | + } |
| 86 | + |
| 87 | + // 只能编辑自己的信息 |
| 88 | + if username != curUser["username"].(string) { |
| 89 | + fmt.Fprint(rw, `{"errno": 1, "error": "非法请求"}`) |
| 90 | + return |
| 91 | + } |
| 92 | + |
| 93 | + // 更新个人信息 |
| 94 | + errMsg, err := service.UpdateUser(req.Form) |
| 95 | + if err != nil { |
| 96 | + fmt.Fprint(rw, `{"errno": 1, "error":"`, errMsg, `"}`) |
| 97 | + return |
| 98 | + } |
| 99 | + fmt.Fprint(rw, `{"errno": 0, "msg":"个人资料更新成功!"}`) |
| 100 | +} |
| 101 | + |
| 102 | +// 修改密码 |
| 103 | +// uri: /account/changepwd.json |
| 104 | +func ChangePwdHandler(rw http.ResponseWriter, req *http.Request) { |
| 105 | + username := req.FormValue("username") |
| 106 | + curUser, _ := filter.CurrentUser(req) |
| 107 | + // 只能修改自己的密码 |
| 108 | + if username != curUser["username"].(string) { |
| 109 | + fmt.Fprint(rw, `{"errno": 1, "error": "非法请求"}`) |
| 110 | + return |
| 111 | + } |
| 112 | + curPasswd := req.FormValue("cur_passwd") |
| 113 | + _, err := service.Login(username, curPasswd) |
| 114 | + if err != nil { |
| 115 | + // 原密码错误 |
| 116 | + fmt.Fprint(rw, `{"errno": 1, "error": "原密码填写错误!"}`) |
| 117 | + return |
| 118 | + } |
| 119 | + // 更新密码 |
| 120 | + errMsg, err := service.UpdatePasswd(username, req.FormValue("passwd")) |
| 121 | + if err != nil { |
| 122 | + fmt.Fprint(rw, `{"errno": 1, "error":"`, errMsg, `"}`) |
| 123 | + return |
| 124 | + } |
| 125 | + fmt.Fprint(rw, `{"errno": 0, "msg":"密码修改成功!"}`) |
| 126 | +} |
| 127 | + |
| 128 | +// 保存uuid和email的对应关系(TODO:重启如何处理,有效期问题) |
| 129 | +var resetPwdMap = map[string]string{} |
| 130 | + |
| 131 | +// 忘记密码 |
| 132 | +// uri: /account/forgetpwd |
| 133 | +func ForgetPasswdHandler(rw http.ResponseWriter, req *http.Request) { |
| 134 | + if _, ok := filter.CurrentUser(req); ok { |
| 135 | + util.Redirect(rw, req, "/") |
| 136 | + return |
| 137 | + } |
| 138 | + req.Form.Set(filter.CONTENT_TPL_KEY, "/template/user/forget_pwd.html") |
| 139 | + data := map[string]interface{}{"activeUsers": "active"} |
| 140 | + email := req.FormValue("email") |
| 141 | + if email == "" || req.Method != "POST" { |
| 142 | + filter.SetData(req, data) |
| 143 | + return |
| 144 | + } |
| 145 | + // 校验email是否存在 |
| 146 | + if service.EmailExists(email) { |
| 147 | + var uuid string |
| 148 | + for { |
| 149 | + uuid = util.GenUUID() |
| 150 | + if _, ok := resetPwdMap[uuid]; !ok { |
| 151 | + resetPwdMap[uuid] = email |
| 152 | + break |
| 153 | + } |
| 154 | + logger.Infoln("GenUUID 冲突....") |
| 155 | + } |
| 156 | + var emailUrl string |
| 157 | + if strings.HasSuffix(email, "@gmail.com") { |
| 158 | + emailUrl = "http://mail.google.com" |
| 159 | + } else { |
| 160 | + pos := strings.LastIndex(email, "@") |
| 161 | + emailUrl = "http://mail." + email[pos+1:] |
| 162 | + } |
| 163 | + data["success"] = template.HTML(`一封包含了重设密码链接的邮件已经发送到您的注册邮箱,按照邮件中的提示,即可重设您的密码。<a href="` + emailUrl + `" target="_blank">立即前往邮箱</a>`) |
| 164 | + go sendResetpwdMail(email, uuid) |
| 165 | + } else { |
| 166 | + data["error"] = "该邮箱没有在本社区注册过!" |
| 167 | + } |
| 168 | + filter.SetData(req, data) |
| 169 | +} |
| 170 | + |
| 171 | +// 重置密码 |
| 172 | +// uri: /account/resetpwd |
| 173 | +func ResetPasswdHandler(rw http.ResponseWriter, req *http.Request) { |
| 174 | + if _, ok := filter.CurrentUser(req); ok { |
| 175 | + util.Redirect(rw, req, "/") |
| 176 | + return |
| 177 | + } |
| 178 | + uuid := req.FormValue("code") |
| 179 | + if uuid == "" { |
| 180 | + util.Redirect(rw, req, "/account/login") |
| 181 | + return |
| 182 | + } |
| 183 | + req.Form.Set(filter.CONTENT_TPL_KEY, "/template/user/reset_pwd.html") |
| 184 | + data := map[string]interface{}{"activeUsers": "active"} |
| 185 | + |
| 186 | + passwd := req.FormValue("passwd") |
| 187 | + email, ok := resetPwdMap[uuid] |
| 188 | + if !ok { |
| 189 | + // 是提交重置密码 |
| 190 | + if passwd != "" && req.Method == "POST" { |
| 191 | + data["error"] = template.HTML(`非法请求!<p>将在<span id="jumpTo">3</span>秒后跳转到<a href="/" id="jump_url">首页</a></p>`) |
| 192 | + } else { |
| 193 | + data["error"] = template.HTML(`链接无效或过期,请重新操作。<a href="/account/forgetpwd">忘记密码?</a>`) |
| 194 | + } |
| 195 | + filter.SetData(req, data) |
| 196 | + return |
| 197 | + } |
| 198 | + |
| 199 | + data["valid"] = true |
| 200 | + data["code"] = uuid |
| 201 | + // 提交修改密码 |
| 202 | + if passwd != "" && req.Method == "POST" { |
| 203 | + // 简单校验 |
| 204 | + if len(passwd) < 6 || len(passwd) > 32 { |
| 205 | + data["error"] = "密码长度必须在6到32个字符之间" |
| 206 | + } else if passwd != req.FormValue("pass2") { |
| 207 | + data["error"] = "两次密码输入不一致" |
| 208 | + } else { |
| 209 | + // 更新密码 |
| 210 | + _, err := service.UpdatePasswd(email, passwd) |
| 211 | + if err != nil { |
| 212 | + data["error"] = "对不起,服务器错误,请重试!" |
| 213 | + } else { |
| 214 | + data["success"] = template.HTML(`密码重置成功,<p>将在<span id="jumpTo">3</span>秒后跳转到<a href="/account/login" id="jump_url">登录</a>页面</p>`) |
| 215 | + } |
| 216 | + } |
| 217 | + } |
| 218 | + filter.SetData(req, data) |
| 219 | +} |
| 220 | + |
| 221 | +// 发重置密码邮件 |
| 222 | +func sendResetpwdMail(email, uuid string) { |
| 223 | + content := `您好,` + email + `,<br/><br/> |
| 224 | + 我们的系统收到一个请求,说您希望通过电子邮件重新设置您在 <a href="http://` + config.Config["domain"] + `">Golang中文社区</a> 的密码。您可以点击下面的链接重设密码:<br/><br/> |
| 225 | +
|
| 226 | + http://` + config.Config["domain"] + `/account/resetpwd?code=` + uuid + ` <br/><br/> |
| 227 | +
|
| 228 | +如果这个请求不是由您发起的,那没问题,您不用担心,您可以安全地忽略这封邮件。<br/><br/> |
| 229 | +
|
| 230 | +如果您有任何疑问,可以回复这封邮件向我们提问。谢谢!<br/><br/> |
| 231 | +
|
| 232 | +<div style="text-align:right;">@2013 studygolang.com Golang中文社区 | Go语言学习园地</div>` |
| 233 | + service.SendMail("【Golang中文社区】重设密码 ", content, []string{email}) |
| 234 | +} |
| 235 | + |
| 236 | +func setCookie(rw http.ResponseWriter, req *http.Request, username string) { |
| 237 | + session, _ := filter.Store.Get(req, "user") |
| 238 | + if req.FormValue("remember_me") != "1" { |
| 239 | + // 浏览器关闭,cookie删除,否则保存30天 |
| 240 | + session.Options = &sessions.Options{ |
| 241 | + Path: "/", |
| 242 | + } |
| 243 | + } |
| 244 | + session.Values["username"] = username |
| 245 | + session.Save(req, rw) |
| 246 | + |
| 247 | +} |
| 248 | + |
| 249 | +// 注销 |
| 250 | +// uri : /account/logout |
| 251 | +func LogoutHandler(rw http.ResponseWriter, req *http.Request) { |
| 252 | + // 删除cookie信息 |
| 253 | + session, _ := filter.Store.Get(req, "user") |
| 254 | + session.Options = &sessions.Options{Path: "/", MaxAge: -1} |
| 255 | + session.Save(req, rw) |
| 256 | + // 重定向得到登录页(TODO:重定向到什么页面比较好?) |
| 257 | + util.Redirect(rw, req, "/account/login") |
| 258 | +} |
0 commit comments