Taobin-Recipe-Manager/server/middlewares/authorized.go

127 lines
3.2 KiB
Go
Raw Normal View History

2023-12-06 20:21:25 +07:00
package middlewares
import (
2023-12-08 14:46:07 +07:00
"context"
2023-12-06 20:21:25 +07:00
"encoding/json"
2023-12-08 14:46:07 +07:00
"fmt"
2023-12-06 20:21:25 +07:00
"net/http"
"recipe-manager/enums/permissions"
"recipe-manager/models"
2023-12-08 14:46:07 +07:00
"recipe-manager/services/oauth"
"recipe-manager/services/user"
2024-02-20 15:01:43 +07:00
"github.com/go-chi/chi/v5"
"golang.org/x/oauth2"
2023-12-06 20:21:25 +07:00
)
2023-12-08 14:46:07 +07:00
// ========================== ValidatePermissions =========================================
func Authorize(oauthService oauth.OAuthService, userService user.UserService, nextRoute http.Handler) http.HandlerFunc {
2023-12-06 20:21:25 +07:00
return func(w http.ResponseWriter, r *http.Request) {
2023-12-08 14:46:07 +07:00
token := &oauth2.Token{}
if cookie, err := r.Cookie("access_token"); err == nil {
token.AccessToken = cookie.Value
2024-02-20 15:01:43 +07:00
} else {
token.AccessToken = r.Header.Get("X-Access-Token")
2023-12-08 14:46:07 +07:00
}
userInfo, err := oauthService.GetUserInfo(r.Context(), token)
if err != nil {
// if have refresh token, set refresh token to token
if cookie, err := r.Cookie("refresh_token"); err == nil {
token.RefreshToken = cookie.Value
2024-02-20 15:01:43 +07:00
} else {
token.RefreshToken = r.Header.Get("X-Refresh-Token")
2023-12-08 14:46:07 +07:00
}
newToken, err := oauthService.RefreshToken(r.Context(), token)
if err != nil {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
userInfo, err = oauthService.GetUserInfo(r.Context(), newToken)
if err != nil {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
// set new token to cookie
w.Header().Add("set-cookie", fmt.Sprintf("access_token=%s; Path=/; HttpOnly; SameSite=None; Secure; Max-Age=3600", newToken.AccessToken))
}
if userInfo != nil {
userFromDB, err := userService.GetUserByEmail(r.Context(), userInfo.Email)
if err != nil {
if err != nil {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
}
if userFromDB != nil {
userInfo.ID = userFromDB.ID
userInfo.Name = userFromDB.Name
if userFromDB.Picture != "" {
userInfo.Picture = userFromDB.Picture
}
userInfo.Permissions = userFromDB.Permissions
}
}
ctx := context.WithValue(r.Context(), "user", userInfo)
nextRoute.ServeHTTP(w, r.WithContext(ctx))
}
}
// ========================== Permissions =========================================
func ValidatePermissions(p []permissions.Permission, nextRoute http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
u := r.Context().Value("user").(*models.User)
2023-12-06 20:21:25 +07:00
for _, pm := range p {
2023-12-08 14:46:07 +07:00
if !u.Permissions.IsHavePermission(pm) {
2023-12-06 20:21:25 +07:00
// If not have permission response unauthorized
w.WriteHeader(http.StatusUnauthorized)
err := json.NewEncoder(w).Encode("Unauthorized")
if err != nil {
panic(err)
}
return
}
}
nextRoute.ServeHTTP(w, r)
}
}
2023-12-08 14:46:07 +07:00
func ValidateOwnerOrPermissions(p []permissions.Permission, nextRoute http.HandlerFunc) http.HandlerFunc {
2023-12-06 20:21:25 +07:00
return func(w http.ResponseWriter, r *http.Request) {
reqUserID := chi.URLParam(r, "id")
2023-12-08 14:46:07 +07:00
u := r.Context().Value("user").(*models.User)
2023-12-06 20:21:25 +07:00
if reqUserID == "" {
// If not have permission response unauthorized
w.WriteHeader(http.StatusUnauthorized)
err := json.NewEncoder(w).Encode("Unauthorized")
if err != nil {
panic(err)
}
return
}
2023-12-08 14:46:07 +07:00
if reqUserID == u.ID {
2023-12-06 20:21:25 +07:00
nextRoute.ServeHTTP(w, r)
return
}
2023-12-08 14:46:07 +07:00
ValidatePermissions(p, nextRoute)
2023-12-06 20:21:25 +07:00
}
}