8
"github.com/xelbot/yetacache"
9
"xelbot.com/reprogl/container"
10
"xelbot.com/reprogl/models"
11
"xelbot.com/reprogl/models/repositories"
12
"xelbot.com/reprogl/services/auth"
13
"xelbot.com/reprogl/session"
14
"xelbot.com/reprogl/views"
17
func LoginAction(app *container.Application) http.HandlerFunc {
18
return func(w http.ResponseWriter, r *http.Request) {
22
cache := app.GetStringCache()
24
if cookie, errNoCookie := r.Cookie(session.CsrfCookie); errNoCookie != nil {
25
csrfToken = generateCsrfPair(w, cache)
27
csrfTokenKey := cookie.Value
28
if csrfToken, found = cache.Get(csrfTokenKey); !found {
29
csrfToken = generateCsrfPair(w, cache)
33
saveLoginReferer(w, r)
34
errorMessage, hasError := session.Pop[string](r.Context(), session.FlashErrorKey)
36
templateData := views.NewLoginPageData(csrfToken, errorMessage, hasError)
37
err := views.WriteTemplate(w, "login.gohtml", templateData)
39
app.ServerError(w, err)
46
func LoginCheck(app *container.Application) http.HandlerFunc {
47
return func(w http.ResponseWriter, r *http.Request) {
51
if session.HasIdentity(r.Context()) {
52
session.ClearIdentity(r.Context())
55
cache := app.GetStringCache()
56
if cookie, errNoCookie := r.Cookie(session.CsrfCookie); errNoCookie == nil {
57
csrfTokenKey := cookie.Value
58
if csrfToken, found = cache.Get(csrfTokenKey); !found {
60
session.Put(r.Context(), session.FlashErrorKey, "Непонятная ошибка")
61
app.InfoLog.Println("[AUTH] not found CSRF-token in cache")
62
http.Redirect(w, r, container.GenerateURL("login"), http.StatusSeeOther)
70
app.ClientError(w, http.StatusBadRequest)
74
formCsrfToken := r.PostForm.Get("_csrf_token")
75
if formCsrfToken != csrfToken {
77
session.Put(r.Context(), session.FlashErrorKey, "Непонятная ошибка")
78
app.InfoLog.Println("[AUTH] wrong CSRF-token")
79
http.Redirect(w, r, container.GenerateURL("login"), http.StatusSeeOther)
83
user, err := auth.HandleLoginPassword(app, r.PostForm.Get("username"), r.PostForm.Get("password"))
86
if authError, found := err.(auth.Error); found {
87
session.Put(r.Context(), session.FlashErrorKey, err.Error())
88
app.InfoLog.Println("[AUTH] " + authError.InfoLogMessage())
89
http.Redirect(w, r, container.GenerateURL("login"), http.StatusSeeOther)
91
app.ServerError(w, err)
97
session.Put(r.Context(), session.FlashSuccessKey, fmt.Sprintf("Привет, %s :)", user.Username))
98
app.InfoLog.Printf("[AUTH] success for \"%s\"\n", user.Username)
99
authSuccess(user, app, container.RealRemoteAddress(r), r.Context())
101
var redirectUrl string
102
if redirectUrl, found = popLoginReferer(w, r); !found {
107
http.Redirect(w, r, redirectUrl, http.StatusFound)
111
func LogoutAction(w http.ResponseWriter, r *http.Request) {
112
session.Destroy(r.Context())
113
http.Redirect(w, r, "/", http.StatusFound)
116
func AuthNavigation(app *container.Application) http.HandlerFunc {
117
return func(w http.ResponseWriter, r *http.Request) {
118
cacheControl(w, container.DefaultEsiTTL)
119
templateData := views.NewAuthNavigationData()
120
err := views.WriteTemplateWithContext(r.Context(), w, "auth-navigation.gohtml", templateData)
122
app.ServerError(w, err)
127
func MenuAuth(app *container.Application) http.HandlerFunc {
128
return func(w http.ResponseWriter, r *http.Request) {
129
var user *models.User
130
if identity, ok := session.GetIdentity(r.Context()); ok {
131
repo := repositories.UserRepository{DB: app.DB}
132
user, _ = repo.Find(identity.ID)
135
templateData := views.NewMenuAuthData(user)
136
cacheControl(w, container.DefaultEsiTTL)
138
err := views.WriteTemplateWithContext(r.Context(), w, "menu-auth.gohtml", templateData)
140
app.ServerError(w, err)
145
func generateCsrfPair(w http.ResponseWriter, cache *yetacache.Cache[string, string]) string {
146
csrfToken := generateRandomToken()
147
csrfTokenKey := generateRandomToken()
149
cache.Set(csrfTokenKey, csrfToken, 30*time.Minute)
150
session.WriteSessionCookie(w, session.CsrfCookie, csrfTokenKey, "/login")
155
func deleteCsrfCookie(w http.ResponseWriter) {
156
session.DeleteCookie(w, session.CsrfCookie, "/login")