Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d9cd92d

Browse files
committed
目前线上版本
1 parent e56a180 commit d9cd92d

File tree

132 files changed

+9817
-739
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

132 files changed

+9817
-739
lines changed

README.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,22 @@
11
studygolang
2-
===========
2+
===========
3+
[Golang中文社区 | Go语言学习园地](http://studygolang.com "Golang中文社区 | Go语言学习园地") 源码
4+
5+
网址上线时间:2013-03-15 14:38:09
6+
7+
目前只开发了主要功能,还有不少功能在不断开发中。欢迎有兴趣的gopher们参与进来,一起构建一个完善的 Golang 中文社区,Go语言爱好者的学习家园。
8+
9+
#目前在正开发或需要开发的功能
10+
1. 热门节点
11+
2. 小贴士
12+
3. 喜欢
13+
4. 收藏
14+
5. 活跃用户
15+
6. 关注
16+
7. 用第三方账号登录
17+
8. 绑定github后显示其代码
18+
9. 同步到微博?
19+
10. wiki
20+
11. 资源
21+
12. 酷站
22+
13. 后台管理

websites/code/studygolang/clean.bat

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
@echo off
2+
3+
setlocal
4+
5+
if exist clean.bat goto ok
6+
echo clean.bat must be run from its folder
7+
goto end
8+
9+
:ok
10+
11+
set OLDGOPATH=%GOPATH%
12+
set GOPATH=%~dp0;
13+
14+
go clean -i -r studygolang
15+
16+
set GOPATH=%OLDGOPATH%
17+
18+
:end
19+
echo finished
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"domain": "dev.studygolang.com",
3+
"host": "127.0.0.1:8080",
4+
"drive_name": "mysql",
5+
"dsn": "root:@tcp(localhost:3306)/studygolang?charset=utf8",
6+
"cookie_secret": "2fwefefwf",
7+
"smtp_username": "example_username",
8+
"smtp_password": "example_password",
9+
"smtp_host": "smtp.example.com",
10+
"smtp_addr": "smtp.example.com:25",
11+
"from_email": "[email protected]"
12+
}

websites/code/studygolang/install

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
if [ ! -f install ]; then
6+
echo 'install must be run within its container folder' 1>&2
7+
exit 1
8+
fi
9+
10+
CURDIR=`pwd`
11+
OLDGOPATH="$GOPATH"
12+
export GOPATH="$CURDIR:$CURDIR/../thirdparty"
13+
14+
gofmt -w src
15+
16+
go install studygolang
17+
18+
export GOPATH="$OLDGOPATH"
19+
export PATH="$OLDPATH"
20+
21+
echo 'finished'

websites/code/studygolang/install.bat

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ set GOPATH=%~dp0;%~dp0..\thirdparty
1313

1414
gofmt -w src
1515

16-
go install studygolang
17-
go install test
16+
go install -tags "debug" studygolang
17+
go install -tags "debug" datamig
1818

1919
set GOPATH=%OLDGOPATH%
2020

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package api
2+
3+
// 发帖子
4+
// uri: /topic/publish
5+
func Publish(rw http.ResponseWriter, req *http.Request) {
6+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,33 @@
11
package config
22

33
import (
4+
"encoding/json"
5+
"io/ioutil"
46
"path"
57
"process"
68
)
79

810
// 项目根目录
911
var ROOT string
1012

13+
var Config map[string]string
14+
1115
func init() {
1216
binDir, err := process.ExecutableDir()
1317
if err != nil {
1418
panic(err)
1519
}
1620
ROOT = path.Dir(binDir)
21+
22+
// Load配置文件
23+
configFile := ROOT + "/conf/config.json"
24+
content, err := ioutil.ReadFile(configFile)
25+
if err != nil {
26+
panic(err)
27+
}
28+
Config = make(map[string]string)
29+
err = json.Unmarshal(content, &Config)
30+
if err != nil {
31+
panic(err)
32+
}
1733
}
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
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+
&nbsp;&nbsp;&nbsp;&nbsp;我们的系统收到一个请求,说您希望通过电子邮件重新设置您在 <a href="http://` + config.Config["domain"] + `">Golang中文社区</a> 的密码。您可以点击下面的链接重设密码:<br/><br/>
225+
226+
&nbsp;&nbsp;&nbsp;&nbsp;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

Comments
 (0)