120 lines
3.5 KiB
Go
120 lines
3.5 KiB
Go
package web
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
|
|
"daili/internal/store"
|
|
)
|
|
|
|
func (s *Server) handleSetupPage(w http.ResponseWriter, r *http.Request) {
|
|
n, err := s.db.CountUsers()
|
|
if err != nil {
|
|
http.Error(w, "数据库异常", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
if n > 0 {
|
|
http.Redirect(w, r, "/login", http.StatusFound)
|
|
return
|
|
}
|
|
p := s.newPage(r, "初始化管理员", "")
|
|
s.render(w, r, "setup", p)
|
|
}
|
|
|
|
func (s *Server) handleSetupPost(w http.ResponseWriter, r *http.Request) {
|
|
n, _ := s.db.CountUsers()
|
|
if n > 0 {
|
|
http.Redirect(w, r, "/login", http.StatusFound)
|
|
return
|
|
}
|
|
if !sameOrigin(r) {
|
|
http.Error(w, "跨站请求被拒绝", http.StatusForbidden)
|
|
return
|
|
}
|
|
username := strings.TrimSpace(r.PostFormValue("username"))
|
|
display := strings.TrimSpace(r.PostFormValue("display_name"))
|
|
pw := r.PostFormValue("password")
|
|
pw2 := r.PostFormValue("password2")
|
|
p := s.newPage(r, "初始化管理员", "")
|
|
switch {
|
|
case len(username) < 3:
|
|
s.fail(w, r, "setup", "用户名至少 3 个字符", p)
|
|
return
|
|
case len(pw) < 6:
|
|
s.fail(w, r, "setup", "密码至少 6 位", p)
|
|
return
|
|
case pw != pw2:
|
|
s.fail(w, r, "setup", "两次输入的密码不一致", p)
|
|
return
|
|
}
|
|
if display == "" {
|
|
display = username
|
|
}
|
|
u, err := s.db.CreateUser(username, display, pw)
|
|
if err != nil {
|
|
s.fail(w, r, "setup", "创建失败:"+err.Error(), p)
|
|
return
|
|
}
|
|
_ = s.db.Log(store.OpLog{OperatorID: u.ID, OperatorName: u.DisplayName, Action: "创建管理员",
|
|
Entity: "user", EntityID: u.ID, Summary: "初始化管理员账号 " + username, IP: clientIP(r)})
|
|
s.startSession(w, r, u)
|
|
s.redirect(w, r, "/packages", "管理员已创建,先添加一个服务套餐吧")
|
|
}
|
|
|
|
func (s *Server) handleLoginPage(w http.ResponseWriter, r *http.Request) {
|
|
n, _ := s.db.CountUsers()
|
|
if n == 0 {
|
|
http.Redirect(w, r, "/setup", http.StatusFound)
|
|
return
|
|
}
|
|
if s.userFromRequest(r) != nil {
|
|
http.Redirect(w, r, "/calendar", http.StatusFound)
|
|
return
|
|
}
|
|
p := s.newPage(r, "登录", "")
|
|
s.render(w, r, "login", p)
|
|
}
|
|
|
|
func (s *Server) handleLoginPost(w http.ResponseWriter, r *http.Request) {
|
|
if !sameOrigin(r) {
|
|
http.Error(w, "跨站请求被拒绝", http.StatusForbidden)
|
|
return
|
|
}
|
|
username := strings.TrimSpace(r.PostFormValue("username"))
|
|
pw := r.PostFormValue("password")
|
|
next := r.PostFormValue("next")
|
|
if !strings.HasPrefix(next, "/") || strings.HasPrefix(next, "//") {
|
|
next = "/calendar"
|
|
}
|
|
u, err := s.db.Authenticate(username, pw)
|
|
if err != nil {
|
|
p := s.newPage(r, "登录", "")
|
|
s.fail(w, r, "login", "用户名或密码不正确", p)
|
|
return
|
|
}
|
|
_ = s.db.Log(store.OpLog{OperatorID: u.ID, OperatorName: u.DisplayName, Action: "登录",
|
|
Entity: "session", Summary: "登录成功", IP: clientIP(r)})
|
|
s.startSession(w, r, u)
|
|
s.redirect(w, r, next, "欢迎回来,"+u.DisplayName)
|
|
}
|
|
|
|
func (s *Server) handleLogout(w http.ResponseWriter, r *http.Request) {
|
|
if c, err := r.Cookie(cookieSession); err == nil && c.Value != "" {
|
|
_ = s.db.DeleteSession(c.Value)
|
|
}
|
|
http.SetCookie(w, &http.Cookie{Name: cookieSession, Value: "", Path: "/", MaxAge: -1, HttpOnly: true})
|
|
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
|
}
|
|
|
|
// logOp 是写操作日志的便捷方法。
|
|
func (s *Server) logOp(r *http.Request, action, entity string, entityID int64, summary string) {
|
|
u := s.currentUser(r)
|
|
if u == nil {
|
|
return
|
|
}
|
|
_ = s.db.Log(store.OpLog{
|
|
OperatorID: u.ID, OperatorName: u.DisplayName, Action: action,
|
|
Entity: entity, EntityID: entityID, Summary: summary, IP: clientIP(r),
|
|
})
|
|
}
|