add permission control

This commit is contained in:
2022-07-22 20:28:42 +08:00
parent b0280767cb
commit 51e5f2d0fb
13 changed files with 127 additions and 185 deletions

View File

@@ -94,11 +94,11 @@ func NewAPI(config commonconfig.Config) (*API, error) {
apiMux.HandleFunc("/update_review", api.HandleUpdateReview)
apiMux.HandleFunc("/delete_review", api.HandleDeleteReview)
apiMux.HandleFunc("/get_reviews_by_user", api.HandleGetReviewsByUser)
// below needs admin
// database
apiMux.HandleFunc("/walk", api.HandleWalk)
apiMux.HandleFunc("/reset", api.HandleReset)
mux.Handle("/api/v1/", http.StripPrefix("/api/v1", apiMux))
mux.Handle("/api/v1/", http.StripPrefix("/api/v1", api.PermissionMiddleware(apiMux)))
mux.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir("web/build"))))
return api, nil

View File

@@ -14,12 +14,6 @@ type WalkRequest struct {
func (api *API) HandleReset(w http.ResponseWriter, r *http.Request) {
var err error
// check admin
err = api.CheckAdmin(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
log.Println("[api] Reset database")
@@ -46,13 +40,6 @@ func (api *API) HandleWalk(w http.ResponseWriter, r *http.Request) {
return
}
// check admin
err = api.CheckAdmin(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
// check root empty
if walkRequest.Root == "" {
api.HandleErrorString(w, r, `key "root" can't be empty`)

View File

@@ -56,13 +56,6 @@ type GetFeedbacksResponse struct {
}
func (api *API) HandleGetFeedbacks(w http.ResponseWriter, r *http.Request) {
// check if admin
err := api.CheckAdmin(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
feedbacks, err := api.Db.GetFeedbacks()
if err != nil {
api.HandleError(w, r, err)
@@ -85,15 +78,8 @@ type DeleteFeedbackRequest struct {
}
func (api *API) HandleDeleteFeedback(w http.ResponseWriter, r *http.Request) {
// check if admin
err := api.CheckAdmin(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
req := &DeleteFeedbackRequest{}
err = json.NewDecoder(r.Body).Decode(req)
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
api.HandleError(w, r, err)
return

View File

@@ -11,15 +11,8 @@ type DeleteFileRequest struct {
}
func (api *API) HandleDeleteFile(w http.ResponseWriter, r *http.Request) {
// check admin
err := api.CheckAdmin(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
req := &DeleteFileRequest{}
err = json.NewDecoder(r.Body).Decode(req)
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
api.HandleError(w, r, err)
return
@@ -42,15 +35,8 @@ type UpdateFilenameRequest struct {
}
func (api *API) HandleUpdateFilename(w http.ResponseWriter, r *http.Request) {
// check admin
err := api.CheckAdmin(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
req := &UpdateFilenameRequest{}
err = json.NewDecoder(r.Body).Decode(req)
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
api.HandleError(w, r, err)
return
@@ -72,15 +58,8 @@ type ResetFilenameRequest struct {
}
func (api *API) HandleResetFilename(w http.ResponseWriter, r *http.Request) {
// check admin
err := api.CheckAdmin(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
req := &ResetFilenameRequest{}
err = json.NewDecoder(r.Body).Decode(req)
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
api.HandleError(w, r, err)
return

View File

@@ -11,15 +11,8 @@ type ResetFoldernameRequest struct {
}
func (api *API) HandleResetFoldername(w http.ResponseWriter, r *http.Request) {
// check admin
err := api.CheckAdmin(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
req := &ResetFoldernameRequest{}
err = json.NewDecoder(r.Body).Decode(req)
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
@@ -49,13 +42,6 @@ func (api *API) HandleUpdateFoldername(w http.ResponseWriter, r *http.Request) {
return
}
// check is admin
err = api.CheckAdmin(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
log.Println("[api] Update foldername folderID", req.ID, req.Foldername)
err = api.Db.UpdateFoldername(req.ID, req.Foldername)

View File

@@ -116,13 +116,8 @@ func (api *API) CheckUserCanModifyReview(w http.ResponseWriter, r *http.Request,
return err
}
err = api.CheckNotAnonymous(w, r)
if err != nil {
return err
}
err = api.CheckAdmin(w, r)
if err != nil {
userLevel := api.GetUserLevel(r)
if userLevel != database.RoleAdmin {
userID, err := api.GetUserID(w, r)
if err != nil {
return err

View File

@@ -34,15 +34,8 @@ type InsertTagResponse struct {
}
func (api *API) HandleInsertTag(w http.ResponseWriter, r *http.Request) {
// check if user is admin
err := api.CheckAdmin(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
req := &database.Tag{}
err = json.NewDecoder(r.Body).Decode(&req)
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
api.HandleError(w, r, err)
return
@@ -107,15 +100,8 @@ func (api *API) HandleGetTagInfo(w http.ResponseWriter, r *http.Request) {
}
func (api *API) HandleUpdateTag(w http.ResponseWriter, r *http.Request) {
// check if user is admin
err := api.CheckAdmin(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
req := &database.Tag{}
err = json.NewDecoder(r.Body).Decode(req)
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
api.HandleError(w, r, err)
return
@@ -135,15 +121,8 @@ type DeleteTagRequest struct {
}
func (api *API) HandleDeleteTag(w http.ResponseWriter, r *http.Request) {
// check if user is admin
err := api.CheckAdmin(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
req := &DeleteTagRequest{}
err = json.NewDecoder(r.Body).Decode(req)
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
api.HandleError(w, r, err)
return

View File

@@ -13,15 +13,8 @@ type PutTagOnFileRequest struct {
}
func (api *API) HandlePutTagOnFile(w http.ResponseWriter, r *http.Request) {
// check if the user is admin
err := api.CheckAdmin(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
req := &PutTagOnFileRequest{}
err = json.NewDecoder(r.Body).Decode(req)
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
api.HandleError(w, r, err)
return
@@ -87,15 +80,8 @@ type DeleteTagOnFileRequest struct {
}
func (api *API) HandleDeleteTagOnFile(w http.ResponseWriter, r *http.Request) {
// check if the user is admin
err := api.CheckAdmin(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
req := &DeleteTagOnFileRequest{}
err = json.NewDecoder(r.Body).Decode(req)
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
api.HandleError(w, r, err)
return

View File

@@ -142,44 +142,6 @@ func (api *API) HandleRegister(w http.ResponseWriter, r *http.Request) {
api.HandleOK(w, r)
}
func (api *API) CheckAdmin(w http.ResponseWriter, r *http.Request) error {
session, _ := api.store.Get(r, api.defaultSessionName)
userId, ok := session.Values["userId"]
if !ok {
return ErrNotLoggedIn
}
user, err := api.Db.GetUserById(userId.(int64))
if err != nil {
return err
}
if user.Role != database.RoleAdmin {
return ErrNotAdmin
}
return nil
}
func (api *API) CheckNotAnonymous(w http.ResponseWriter, r *http.Request) error {
session, _ := api.store.Get(r, api.defaultSessionName)
userId, ok := session.Values["userId"]
if !ok {
return ErrNotLoggedIn
}
user, err := api.Db.GetUserById(userId.(int64))
if err != nil {
return err
}
if user.Role == database.RoleAnonymous {
return ErrAnonymous
}
return nil
}
func (api *API) GetUserID(w http.ResponseWriter, r *http.Request) (int64, error) {
session, _ := api.store.Get(r, api.defaultSessionName)
userId, ok := session.Values["userId"]
@@ -218,14 +180,8 @@ type UpdateUserActiveRequest struct {
}
func (api *API) HandleUpdateUserActive(w http.ResponseWriter, r *http.Request) {
err := api.CheckAdmin(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
req := &UpdateUserActiveRequest{}
err = json.NewDecoder(r.Body).Decode(req)
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
api.HandleError(w, r, err)
return
@@ -245,16 +201,11 @@ type UpdateUsernameRequest struct {
}
func (api *API) HandleUpdateUsername(w http.ResponseWriter, r *http.Request) {
// reject anonymous user
err := api.CheckNotAnonymous(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
// middileware reject anonymous user
req := &UpdateUsernameRequest{}
err = json.NewDecoder(r.Body).Decode(req)
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
api.HandleError(w, r, err)
return
@@ -326,15 +277,10 @@ type UpdateUserPasswordRequest struct {
}
func (api *API) HandleUpdateUserPassword(w http.ResponseWriter, r *http.Request) {
// reject anonymous user
err := api.CheckNotAnonymous(w, r)
if err != nil {
api.HandleError(w, r, err)
return
}
// middleware reject anonymous user
req := &UpdateUserPasswordRequest{}
err = json.NewDecoder(r.Body).Decode(req)
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
api.HandleError(w, r, err)
return

55
pkg/api/middleware.go Normal file
View File

@@ -0,0 +1,55 @@
package api
import (
"errors"
"net/http"
)
func (api *API) PermissionMiddleware(next http.Handler) http.Handler {
// 0 anonymous user
// 1 admin
// 2 normal user
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// get permission of URL
permission, ok := api.APIConfig.Permission[r.URL.Path]
// 0 means no permission required
if !ok || permission == 0 {
next.ServeHTTP(w, r)
return
}
// ger user permission level
userLevel := api.GetUserLevel(r)
// admin has root (highest) permission level 1
if userLevel == 1 {
next.ServeHTTP(w, r)
return
}
// anonymous userLevel 0 don't have any permission
// check permission level for other users
if userLevel == 0 || userLevel > permission {
api.HandleError(w, r, errors.New("No enougth permission"))
return
}
next.ServeHTTP(w, r)
})
}
func (api *API) GetUserLevel(r *http.Request) int64 {
session, _ := api.store.Get(r, api.defaultSessionName)
userId, ok := session.Values["userId"]
if !ok {
// not logined user is considered anonymous user
return 0
}
user, err := api.Db.GetUserById(userId.(int64))
if err != nil {
return 0
}
return user.Role
}