139 lines
3.6 KiB
Go
139 lines
3.6 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
|
|
"vpn-panel/internal/auth"
|
|
"vpn-panel/internal/session"
|
|
"vpn-panel/internal/store"
|
|
)
|
|
|
|
func (h *Handler) currentUser(r *http.Request) *session.Data {
|
|
c, err := r.Cookie(session.CookieName())
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
d, err := session.Verify(h.secret, c.Value)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return d
|
|
}
|
|
|
|
func (h *Handler) RegisterAdmin(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
has, err := h.users.HasAdmin(ctx)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
if has {
|
|
flashSet(w, "Администратор уже создан. Регистрация закрыта.", "error")
|
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
|
return
|
|
}
|
|
|
|
if r.Method == http.MethodGet {
|
|
h.render(w, "register", h.pageData(w, r, "Регистрация администратора", nil))
|
|
return
|
|
}
|
|
|
|
email := strings.TrimSpace(strings.ToLower(r.FormValue("email")))
|
|
password := r.FormValue("password")
|
|
confirm := r.FormValue("password_confirm")
|
|
|
|
if email == "" || len(password) < 8 {
|
|
flashSet(w, "Email обязателен, пароль — минимум 8 символов.", "error")
|
|
http.Redirect(w, r, "/register", http.StatusSeeOther)
|
|
return
|
|
}
|
|
if password != confirm {
|
|
flashSet(w, "Пароли не совпадают.", "error")
|
|
http.Redirect(w, r, "/register", http.StatusSeeOther)
|
|
return
|
|
}
|
|
|
|
hash, err := auth.HashPassword(password)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
u, err := h.users.CreateAdmin(ctx, email, hash)
|
|
if err == store.ErrAdminExists {
|
|
flashSet(w, "Администратор уже существует.", "error")
|
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
|
return
|
|
}
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
token, err := session.Sign(h.secret, session.Data{
|
|
UserID: u.ID,
|
|
Email: u.Email,
|
|
Role: u.Role,
|
|
})
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
http.SetCookie(w, &http.Cookie{
|
|
Name: session.CookieName(),
|
|
Value: token,
|
|
Path: "/",
|
|
MaxAge: int((7 * 24 * 60 * 60)),
|
|
HttpOnly: true,
|
|
SameSite: http.SameSiteLaxMode,
|
|
Secure: r.TLS != nil,
|
|
})
|
|
flashSet(w, "Администратор успешно создан. Добро пожаловать!", "success")
|
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
|
}
|
|
|
|
func (h *Handler) Login(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method == http.MethodGet {
|
|
h.render(w, "login", h.pageData(w, r, "Вход", nil))
|
|
return
|
|
}
|
|
|
|
email := strings.TrimSpace(strings.ToLower(r.FormValue("email")))
|
|
password := r.FormValue("password")
|
|
|
|
u, err := h.users.GetByEmail(r.Context(), email)
|
|
if err != nil || u == nil || !auth.CheckPassword(u.PasswordHash, password) {
|
|
flashSet(w, "Неверный email или пароль.", "error")
|
|
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
|
return
|
|
}
|
|
|
|
token, err := session.Sign(h.secret, session.Data{
|
|
UserID: u.ID,
|
|
Email: u.Email,
|
|
Role: u.Role,
|
|
})
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
http.SetCookie(w, &http.Cookie{
|
|
Name: session.CookieName(),
|
|
Value: token,
|
|
Path: "/",
|
|
MaxAge: 7 * 24 * 60 * 60,
|
|
HttpOnly: true,
|
|
SameSite: http.SameSiteLaxMode,
|
|
Secure: r.TLS != nil,
|
|
})
|
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
|
}
|
|
|
|
func (h *Handler) Logout(w http.ResponseWriter, r *http.Request) {
|
|
http.SetCookie(w, &http.Cookie{
|
|
Name: session.CookieName(), Path: "/", MaxAge: -1,
|
|
})
|
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
|
}
|