package middlewares import ( "context" "encoding/json" "fmt" "net/http" "recipe-manager/enums/permissions" "recipe-manager/models" "recipe-manager/services/oauth" "recipe-manager/services/user" "github.com/go-chi/chi/v5" "golang.org/x/oauth2" ) // ========================== ValidatePermissions ========================================= func Authorize(oauthService oauth.OAuthService, userService user.UserService, nextRoute http.Handler) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { token := &oauth2.Token{} if cookie, err := r.Cookie("access_token"); err == nil { token.AccessToken = cookie.Value } else { token.AccessToken = r.Header.Get("X-Access-Token") } 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 } else { token.RefreshToken = r.Header.Get("X-Refresh-Token") } 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) for _, pm := range p { if !u.Permissions.IsHavePermission(pm) { // If not have permission response unauthorized fmt.Println("tried access " + fmt.Sprintf("%v", pm)) w.WriteHeader(http.StatusUnauthorized) err := json.NewEncoder(w).Encode("Unauthorized") if err != nil { panic(err) } return } } nextRoute.ServeHTTP(w, r) } } func ValidateOwnerOrPermissions(p []permissions.Permission, nextRoute http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { reqUserID := chi.URLParam(r, "id") u := r.Context().Value("user").(*models.User) fmt.Println(u) if reqUserID == "" { // If not have permission response unauthorized w.WriteHeader(http.StatusUnauthorized) err := json.NewEncoder(w).Encode("Unauthorized") if err != nil { panic(err) } return } if reqUserID == u.ID { nextRoute.ServeHTTP(w, r) return } ValidatePermissions(p, nextRoute) } }