add permission control
This commit is contained in:
15
README.md
15
README.md
@@ -62,6 +62,17 @@ Go to register page, select the role to admin, and register the first admin acco
|
|||||||
- `file_life_time` integer type (second). Life time for temporary file. If the temporary file is not accessed for more than this time, back-end server will delete this file.
|
- `file_life_time` integer type (second). Life time for temporary file. If the temporary file is not accessed for more than this time, back-end server will delete this file.
|
||||||
- `cleaner_internal` integer type (second). Interval for `tmpfs` checking temporary file.
|
- `cleaner_internal` integer type (second). Interval for `tmpfs` checking temporary file.
|
||||||
- `root` string type. Directory to store temporary files. Default is `/tmp`, **please modify this directory if you are using Windows.** Directory will be created if not exists.
|
- `root` string type. Directory to store temporary files. Default is `/tmp`, **please modify this directory if you are using Windows.** Directory will be created if not exists.
|
||||||
|
- `permission`. Specify each API's permission level.
|
||||||
|
- `0` for no permission required.
|
||||||
|
- `1` require admin level (highest level) permission.
|
||||||
|
- `2` require normal user level permission. That is, both admins and registered users can access to this URL, except anonymous users.
|
||||||
|
- If you want to avoid abuse of the playback API, you can adjust the permission level for these 5 playback-related APIs.
|
||||||
|
- `/get_file` get file with `io.copy()` method
|
||||||
|
- `/get_file_direct` get file with `http.serveFile()` method
|
||||||
|
- `/get_file_stream` call ffmpeg and stream its `stdout` output
|
||||||
|
- `/prepare_file_stream_direct` call ffmpeg to convert a file
|
||||||
|
- `/get_file_stream_direct` get the converted file with `http.serveFile()`
|
||||||
|
- Other URLs not metion in `config.json` will have `0` permission level by default.
|
||||||
|
|
||||||
For windows user, make sure you have `ffmpeg` installed.
|
For windows user, make sure you have `ffmpeg` installed.
|
||||||
|
|
||||||
@@ -99,7 +110,7 @@ API does not need to respond any data will return the following JSON object.
|
|||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"status": "OK"
|
"status": "OK"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -107,7 +118,7 @@ Sometime errors happen, server will return the following JSON object, which `err
|
|||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"error": "Wrong password"
|
"error": "Wrong password"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
35
config.json
35
config.json
@@ -38,8 +38,39 @@
|
|||||||
},
|
},
|
||||||
{ "name": "MP3 128k", "args": "-c:a mp3 -ab 128k -vn", "format": "mp3" },
|
{ "name": "MP3 128k", "args": "-c:a mp3 -ab 128k -vn", "format": "mp3" },
|
||||||
{ "name": "MP3 320k", "args": "-c:a mp3 -ab 320k -vn", "format": "mp3" },
|
{ "name": "MP3 320k", "args": "-c:a mp3 -ab 320k -vn", "format": "mp3" },
|
||||||
{ "name": "全损音质 8k", "args": "-c:a libopus -ab 8k -vn", "format": "webm" }
|
{
|
||||||
]
|
"name": "全损音质 8k",
|
||||||
|
"args": "-c:a libopus -ab 8k -vn",
|
||||||
|
"format": "webm"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"permission": {
|
||||||
|
"/register": 0,
|
||||||
|
"/get_file": 0,
|
||||||
|
"/get_file_direct": 0,
|
||||||
|
"/get_file_stream": 0,
|
||||||
|
"/prepare_file_stream_direct": 0,
|
||||||
|
"/get_file_stream_direct": 0,
|
||||||
|
"/walk": 1,
|
||||||
|
"/reset": 1,
|
||||||
|
"/update_user_active": 1,
|
||||||
|
"/get_feedbacks": 1,
|
||||||
|
"/delete_feedback": 1,
|
||||||
|
"/delete_file": 1,
|
||||||
|
"/update_filename": 1,
|
||||||
|
"/reset_filename": 1,
|
||||||
|
"/reset_foldername": 1,
|
||||||
|
"/update_foldername": 1,
|
||||||
|
"/insert_tag": 1,
|
||||||
|
"/update_tag": 1,
|
||||||
|
"/delete_tag": 1,
|
||||||
|
"/put_tag_on_file": 1,
|
||||||
|
"/delete_tag_on_file": 1,
|
||||||
|
"/delete_review": 2,
|
||||||
|
"/update_review": 2,
|
||||||
|
"/update_user_password": 2,
|
||||||
|
"/update_username": 2
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"tmpfs": {
|
"tmpfs": {
|
||||||
"file_life_time": 600,
|
"file_life_time": 600,
|
||||||
|
|||||||
@@ -94,11 +94,11 @@ func NewAPI(config commonconfig.Config) (*API, error) {
|
|||||||
apiMux.HandleFunc("/update_review", api.HandleUpdateReview)
|
apiMux.HandleFunc("/update_review", api.HandleUpdateReview)
|
||||||
apiMux.HandleFunc("/delete_review", api.HandleDeleteReview)
|
apiMux.HandleFunc("/delete_review", api.HandleDeleteReview)
|
||||||
apiMux.HandleFunc("/get_reviews_by_user", api.HandleGetReviewsByUser)
|
apiMux.HandleFunc("/get_reviews_by_user", api.HandleGetReviewsByUser)
|
||||||
// below needs admin
|
// database
|
||||||
apiMux.HandleFunc("/walk", api.HandleWalk)
|
apiMux.HandleFunc("/walk", api.HandleWalk)
|
||||||
apiMux.HandleFunc("/reset", api.HandleReset)
|
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"))))
|
mux.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir("web/build"))))
|
||||||
|
|
||||||
return api, nil
|
return api, nil
|
||||||
|
|||||||
@@ -14,12 +14,6 @@ type WalkRequest struct {
|
|||||||
|
|
||||||
func (api *API) HandleReset(w http.ResponseWriter, r *http.Request) {
|
func (api *API) HandleReset(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
// check admin
|
|
||||||
err = api.CheckAdmin(w, r)
|
|
||||||
if err != nil {
|
|
||||||
api.HandleError(w, r, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Println("[api] Reset database")
|
log.Println("[api] Reset database")
|
||||||
|
|
||||||
@@ -46,13 +40,6 @@ func (api *API) HandleWalk(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// check admin
|
|
||||||
err = api.CheckAdmin(w, r)
|
|
||||||
if err != nil {
|
|
||||||
api.HandleError(w, r, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// check root empty
|
// check root empty
|
||||||
if walkRequest.Root == "" {
|
if walkRequest.Root == "" {
|
||||||
api.HandleErrorString(w, r, `key "root" can't be empty`)
|
api.HandleErrorString(w, r, `key "root" can't be empty`)
|
||||||
|
|||||||
@@ -56,13 +56,6 @@ type GetFeedbacksResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) HandleGetFeedbacks(w http.ResponseWriter, r *http.Request) {
|
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()
|
feedbacks, err := api.Db.GetFeedbacks()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleError(w, r, err)
|
api.HandleError(w, r, err)
|
||||||
@@ -85,15 +78,8 @@ type DeleteFeedbackRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) HandleDeleteFeedback(w http.ResponseWriter, r *http.Request) {
|
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{}
|
req := &DeleteFeedbackRequest{}
|
||||||
err = json.NewDecoder(r.Body).Decode(req)
|
err := json.NewDecoder(r.Body).Decode(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleError(w, r, err)
|
api.HandleError(w, r, err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -11,15 +11,8 @@ type DeleteFileRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) HandleDeleteFile(w http.ResponseWriter, r *http.Request) {
|
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{}
|
req := &DeleteFileRequest{}
|
||||||
err = json.NewDecoder(r.Body).Decode(req)
|
err := json.NewDecoder(r.Body).Decode(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleError(w, r, err)
|
api.HandleError(w, r, err)
|
||||||
return
|
return
|
||||||
@@ -42,15 +35,8 @@ type UpdateFilenameRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) HandleUpdateFilename(w http.ResponseWriter, r *http.Request) {
|
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{}
|
req := &UpdateFilenameRequest{}
|
||||||
err = json.NewDecoder(r.Body).Decode(req)
|
err := json.NewDecoder(r.Body).Decode(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleError(w, r, err)
|
api.HandleError(w, r, err)
|
||||||
return
|
return
|
||||||
@@ -72,15 +58,8 @@ type ResetFilenameRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) HandleResetFilename(w http.ResponseWriter, r *http.Request) {
|
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{}
|
req := &ResetFilenameRequest{}
|
||||||
err = json.NewDecoder(r.Body).Decode(req)
|
err := json.NewDecoder(r.Body).Decode(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleError(w, r, err)
|
api.HandleError(w, r, err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -11,15 +11,8 @@ type ResetFoldernameRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) HandleResetFoldername(w http.ResponseWriter, r *http.Request) {
|
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{}
|
req := &ResetFoldernameRequest{}
|
||||||
err = json.NewDecoder(r.Body).Decode(req)
|
err := json.NewDecoder(r.Body).Decode(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
@@ -49,13 +42,6 @@ func (api *API) HandleUpdateFoldername(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
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)
|
log.Println("[api] Update foldername folderID", req.ID, req.Foldername)
|
||||||
|
|
||||||
err = api.Db.UpdateFoldername(req.ID, req.Foldername)
|
err = api.Db.UpdateFoldername(req.ID, req.Foldername)
|
||||||
|
|||||||
@@ -116,13 +116,8 @@ func (api *API) CheckUserCanModifyReview(w http.ResponseWriter, r *http.Request,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = api.CheckNotAnonymous(w, r)
|
userLevel := api.GetUserLevel(r)
|
||||||
if err != nil {
|
if userLevel != database.RoleAdmin {
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = api.CheckAdmin(w, r)
|
|
||||||
if err != nil {
|
|
||||||
userID, err := api.GetUserID(w, r)
|
userID, err := api.GetUserID(w, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -34,15 +34,8 @@ type InsertTagResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) HandleInsertTag(w http.ResponseWriter, r *http.Request) {
|
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{}
|
req := &database.Tag{}
|
||||||
err = json.NewDecoder(r.Body).Decode(&req)
|
err := json.NewDecoder(r.Body).Decode(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleError(w, r, err)
|
api.HandleError(w, r, err)
|
||||||
return
|
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) {
|
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{}
|
req := &database.Tag{}
|
||||||
err = json.NewDecoder(r.Body).Decode(req)
|
err := json.NewDecoder(r.Body).Decode(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleError(w, r, err)
|
api.HandleError(w, r, err)
|
||||||
return
|
return
|
||||||
@@ -135,15 +121,8 @@ type DeleteTagRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) HandleDeleteTag(w http.ResponseWriter, r *http.Request) {
|
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{}
|
req := &DeleteTagRequest{}
|
||||||
err = json.NewDecoder(r.Body).Decode(req)
|
err := json.NewDecoder(r.Body).Decode(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleError(w, r, err)
|
api.HandleError(w, r, err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -13,15 +13,8 @@ type PutTagOnFileRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) HandlePutTagOnFile(w http.ResponseWriter, r *http.Request) {
|
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{}
|
req := &PutTagOnFileRequest{}
|
||||||
err = json.NewDecoder(r.Body).Decode(req)
|
err := json.NewDecoder(r.Body).Decode(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleError(w, r, err)
|
api.HandleError(w, r, err)
|
||||||
return
|
return
|
||||||
@@ -87,15 +80,8 @@ type DeleteTagOnFileRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) HandleDeleteTagOnFile(w http.ResponseWriter, r *http.Request) {
|
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{}
|
req := &DeleteTagOnFileRequest{}
|
||||||
err = json.NewDecoder(r.Body).Decode(req)
|
err := json.NewDecoder(r.Body).Decode(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleError(w, r, err)
|
api.HandleError(w, r, err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -142,44 +142,6 @@ func (api *API) HandleRegister(w http.ResponseWriter, r *http.Request) {
|
|||||||
api.HandleOK(w, r)
|
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) {
|
func (api *API) GetUserID(w http.ResponseWriter, r *http.Request) (int64, error) {
|
||||||
session, _ := api.store.Get(r, api.defaultSessionName)
|
session, _ := api.store.Get(r, api.defaultSessionName)
|
||||||
userId, ok := session.Values["userId"]
|
userId, ok := session.Values["userId"]
|
||||||
@@ -218,14 +180,8 @@ type UpdateUserActiveRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) HandleUpdateUserActive(w http.ResponseWriter, r *http.Request) {
|
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{}
|
req := &UpdateUserActiveRequest{}
|
||||||
err = json.NewDecoder(r.Body).Decode(req)
|
err := json.NewDecoder(r.Body).Decode(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleError(w, r, err)
|
api.HandleError(w, r, err)
|
||||||
return
|
return
|
||||||
@@ -245,16 +201,11 @@ type UpdateUsernameRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) HandleUpdateUsername(w http.ResponseWriter, r *http.Request) {
|
func (api *API) HandleUpdateUsername(w http.ResponseWriter, r *http.Request) {
|
||||||
// reject anonymous user
|
// middileware reject anonymous user
|
||||||
err := api.CheckNotAnonymous(w, r)
|
|
||||||
if err != nil {
|
|
||||||
api.HandleError(w, r, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &UpdateUsernameRequest{}
|
req := &UpdateUsernameRequest{}
|
||||||
|
|
||||||
err = json.NewDecoder(r.Body).Decode(req)
|
err := json.NewDecoder(r.Body).Decode(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleError(w, r, err)
|
api.HandleError(w, r, err)
|
||||||
return
|
return
|
||||||
@@ -326,15 +277,10 @@ type UpdateUserPasswordRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) HandleUpdateUserPassword(w http.ResponseWriter, r *http.Request) {
|
func (api *API) HandleUpdateUserPassword(w http.ResponseWriter, r *http.Request) {
|
||||||
// reject anonymous user
|
// middleware reject anonymous user
|
||||||
err := api.CheckNotAnonymous(w, r)
|
|
||||||
if err != nil {
|
|
||||||
api.HandleError(w, r, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &UpdateUserPasswordRequest{}
|
req := &UpdateUserPasswordRequest{}
|
||||||
err = json.NewDecoder(r.Body).Decode(req)
|
err := json.NewDecoder(r.Body).Decode(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleError(w, r, err)
|
api.HandleError(w, r, err)
|
||||||
return
|
return
|
||||||
|
|||||||
55
pkg/api/middleware.go
Normal file
55
pkg/api/middleware.go
Normal 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
|
||||||
|
}
|
||||||
@@ -6,12 +6,13 @@ type Config struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type APIConfig struct {
|
type APIConfig struct {
|
||||||
DatabaseName string `json:"database_name"`
|
DatabaseName string `json:"database_name"`
|
||||||
SingleThread bool `json:"single_thread,default=true"`
|
SingleThread bool `json:"single_thread,default=true"`
|
||||||
Addr string `json:"addr"`
|
Addr string `json:"addr"`
|
||||||
FfmpegThreads int64 `json:"ffmpeg_threads"`
|
FfmpegThreads int64 `json:"ffmpeg_threads"`
|
||||||
FfmpegConfigList []FfmpegConfig `json:"ffmpeg_config_list"`
|
FfmpegConfigList []FfmpegConfig `json:"ffmpeg_config_list"`
|
||||||
SECRET string `json:"secret"`
|
SECRET string `json:"secret"`
|
||||||
|
Permission map[string]int64 `json:"permission"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type FfmpegConfigList struct {
|
type FfmpegConfigList struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user