Merge pull request 'Use session-based flash messages instead of query params' (#46) from fix/session-flash into main
Reviewed-on: https://git.ts.mattnite.net/mattnite/forgejo-tickets/pulls/46
This commit is contained in:
commit
dca569b278
|
|
@ -4,12 +4,12 @@ import (
|
|||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"github.com/mattnite/forgejo-tickets/internal/forgejo"
|
||||
"github.com/mattnite/forgejo-tickets/internal/middleware"
|
||||
"github.com/mattnite/forgejo-tickets/internal/models"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
|
@ -202,11 +202,8 @@ func (h *UserHandler) Approve(c *gin.Context) {
|
|||
log.Error().Err(err).Msg("send approval email error")
|
||||
}
|
||||
|
||||
redirectURL := "/users/pending?" + url.Values{
|
||||
"flash": {"User " + user.Email + " has been approved"},
|
||||
"flash_type": {"success"},
|
||||
}.Encode()
|
||||
c.Redirect(http.StatusSeeOther, redirectURL)
|
||||
middleware.SetFlash(c, "success", "User "+user.Email+" has been approved")
|
||||
c.Redirect(http.StatusSeeOther, "/users/pending")
|
||||
}
|
||||
|
||||
func (h *UserHandler) Reject(c *gin.Context) {
|
||||
|
|
@ -222,11 +219,8 @@ func (h *UserHandler) Reject(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
redirectURL := "/users/pending?" + url.Values{
|
||||
"flash": {"User request has been rejected"},
|
||||
"flash_type": {"success"},
|
||||
}.Encode()
|
||||
c.Redirect(http.StatusSeeOther, redirectURL)
|
||||
middleware.SetFlash(c, "success", "User request has been rejected")
|
||||
c.Redirect(http.StatusSeeOther, "/users/pending")
|
||||
}
|
||||
|
||||
func (h *UserHandler) UpdateRepos(c *gin.Context) {
|
||||
|
|
@ -257,9 +251,6 @@ func (h *UserHandler) UpdateRepos(c *gin.Context) {
|
|||
h.deps.DB.Create(&models.UserRepo{UserID: userID, RepoID: repoID})
|
||||
}
|
||||
|
||||
redirectURL := "/users/" + userID.String() + "?" + url.Values{
|
||||
"flash": {"Project assignments updated"},
|
||||
"flash_type": {"success"},
|
||||
}.Encode()
|
||||
c.Redirect(http.StatusSeeOther, redirectURL)
|
||||
middleware.SetFlash(c, "success", "Project assignments updated")
|
||||
c.Redirect(http.StatusSeeOther, "/users/"+userID.String())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ package public
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mattnite/forgejo-tickets/internal/auth"
|
||||
"github.com/mattnite/forgejo-tickets/internal/middleware"
|
||||
"github.com/mattnite/forgejo-tickets/internal/models"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
|
@ -111,11 +111,8 @@ func (h *AuthHandler) Register(c *gin.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
redirectURL := "/login?" + url.Values{
|
||||
"flash": {"Account requested! Please check your email to verify your address. After verification, an admin will review your request."},
|
||||
"flash_type": {"success"},
|
||||
}.Encode()
|
||||
c.Redirect(http.StatusSeeOther, redirectURL)
|
||||
middleware.SetFlash(c, "success", "Account requested! Please check your email to verify your address. After verification, an admin will review your request.")
|
||||
c.Redirect(http.StatusSeeOther, "/login")
|
||||
}
|
||||
|
||||
func (h *AuthHandler) Logout(c *gin.Context) {
|
||||
|
|
@ -138,11 +135,8 @@ func (h *AuthHandler) VerifyEmail(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
redirectURL := "/login?" + url.Values{
|
||||
"flash": {"Email verified successfully. Your account is pending admin approval."},
|
||||
"flash_type": {"success"},
|
||||
}.Encode()
|
||||
c.Redirect(http.StatusSeeOther, redirectURL)
|
||||
middleware.SetFlash(c, "success", "Email verified successfully. Your account is pending admin approval.")
|
||||
c.Redirect(http.StatusSeeOther, "/login")
|
||||
}
|
||||
|
||||
func (h *AuthHandler) ForgotPasswordForm(c *gin.Context) {
|
||||
|
|
@ -206,9 +200,6 @@ func (h *AuthHandler) ResetPassword(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
redirectURL := "/login?" + url.Values{
|
||||
"flash": {"Password reset successfully. You can now log in."},
|
||||
"flash_type": {"success"},
|
||||
}.Encode()
|
||||
c.Redirect(http.StatusSeeOther, redirectURL)
|
||||
middleware.SetFlash(c, "success", "Password reset successfully. You can now log in.")
|
||||
c.Redirect(http.StatusSeeOther, "/login")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ import (
|
|||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mattnite/forgejo-tickets/internal/auth"
|
||||
"github.com/mattnite/forgejo-tickets/internal/middleware"
|
||||
"github.com/rs/zerolog/log"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
|
@ -98,11 +98,8 @@ func (h *OAuthHandler) Callback(c *gin.Context) {
|
|||
user, err := h.deps.Auth.FindOrCreateOAuthUser(c.Request.Context(), provider.Name, info)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "pending admin approval") {
|
||||
redirectURL := "/login?" + url.Values{
|
||||
"flash": {err.Error()},
|
||||
"flash_type": {"info"},
|
||||
}.Encode()
|
||||
c.Redirect(http.StatusSeeOther, redirectURL)
|
||||
middleware.SetFlash(c, "info", err.Error())
|
||||
c.Redirect(http.StatusSeeOther, "/login")
|
||||
return
|
||||
}
|
||||
log.Error().Err(err).Msg("find or create oauth user error")
|
||||
|
|
@ -196,11 +193,8 @@ func (h *OAuthHandler) AppleCallback(c *gin.Context) {
|
|||
user, err := h.deps.Auth.FindOrCreateOAuthUser(c.Request.Context(), "apple", info)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "pending admin approval") {
|
||||
redirectURL := "/login?" + url.Values{
|
||||
"flash": {err.Error()},
|
||||
"flash_type": {"info"},
|
||||
}.Encode()
|
||||
c.Redirect(http.StatusSeeOther, redirectURL)
|
||||
middleware.SetFlash(c, "info", err.Error())
|
||||
c.Redirect(http.StatusSeeOther, "/login")
|
||||
return
|
||||
}
|
||||
log.Error().Err(err).Msg("find or create apple user error")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// SetFlash sets a flash message cookie that will be consumed on the next render.
|
||||
func SetFlash(c *gin.Context, flashType, message string) {
|
||||
// Encode as "type:message" in base64 to avoid cookie value issues
|
||||
value := base64.StdEncoding.EncodeToString([]byte(flashType + ":" + message))
|
||||
http.SetCookie(c.Writer, &http.Cookie{
|
||||
Name: "flash",
|
||||
Value: value,
|
||||
Path: "/",
|
||||
MaxAge: 60,
|
||||
HttpOnly: true,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
})
|
||||
}
|
||||
|
||||
// GetFlash reads and clears the flash message cookie.
|
||||
func GetFlash(r *http.Request, w http.ResponseWriter) (flashType, message string) {
|
||||
cookie, err := r.Cookie("flash")
|
||||
if err != nil || cookie.Value == "" {
|
||||
return "", ""
|
||||
}
|
||||
// Clear the cookie
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "flash",
|
||||
Path: "/",
|
||||
MaxAge: -1,
|
||||
})
|
||||
data, err := base64.StdEncoding.DecodeString(cookie.Value)
|
||||
if err != nil {
|
||||
return "", ""
|
||||
}
|
||||
parts := strings.SplitN(string(data), ":", 2)
|
||||
if len(parts) != 2 {
|
||||
return "", ""
|
||||
}
|
||||
return parts[0], parts[1]
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
"github.com/gorilla/csrf"
|
||||
"github.com/mattnite/forgejo-tickets/internal/auth"
|
||||
"github.com/mattnite/forgejo-tickets/internal/middleware"
|
||||
"github.com/mattnite/forgejo-tickets/internal/models"
|
||||
)
|
||||
|
||||
|
|
@ -103,12 +104,8 @@ func (r *Renderer) Render(w http.ResponseWriter, req *http.Request, name string,
|
|||
Data: data,
|
||||
}
|
||||
|
||||
if msg := req.URL.Query().Get("flash"); msg != "" {
|
||||
flashType := req.URL.Query().Get("flash_type")
|
||||
if flashType == "" {
|
||||
flashType = "info"
|
||||
}
|
||||
pd.Flash = &Flash{Type: flashType, Message: msg}
|
||||
if flashType, flashMsg := middleware.GetFlash(req, w); flashMsg != "" {
|
||||
pd.Flash = &Flash{Type: flashType, Message: flashMsg}
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
|
|
|||
Loading…
Reference in New Issue