From a3c61430140beaae7d32ebdd5c718675f760c2ab Mon Sep 17 00:00:00 2001 From: gmemstr Date: Wed, 29 Nov 2017 12:56:51 -0800 Subject: [PATCH] Added user permissions! --- admin/admin.go | 34 +++++++++++++++------------- assets/config/users.db | Bin 20480 -> 32768 bytes auth/auth.go | 50 +++++++++++++++++++++++++++++++++++++++-- router/router.go | 40 ++++++++++++++++----------------- 4 files changed, 86 insertions(+), 38 deletions(-) diff --git a/admin/admin.go b/admin/admin.go index d667096..d59608a 100644 --- a/admin/admin.go +++ b/admin/admin.go @@ -7,32 +7,34 @@ package admin import ( + "database/sql" + "encoding/json" "fmt" + "golang.org/x/crypto/bcrypt" "io" "io/ioutil" "net/http" "os" "strings" - "encoding/json" - "golang.org/x/crypto/bcrypt" - "database/sql" - _ "github.com/mattn/go-sqlite3" "github.com/gorilla/mux" + _ "github.com/mattn/go-sqlite3" "github.com/gmemstr/pogo/common" ) + type User struct { - Id int `json:"id"` - Dbun string `json:"username"` - Dbrn string `json:"realname"` - Dbem string `json:"email"` + Id int `json:"id"` + Dbun string `json:"username"` + Dbrn string `json:"realname"` + Dbem string `json:"email"` } type UserList struct { Users []User } + /* - * The following is a set of admin commands + * The following is a set of admin commands * that the average user probably shouldn't be * able to have access to, mostly user management. */ @@ -71,7 +73,7 @@ func AddUser() common.Handler { hash, err := bcrypt.GenerateFromPassword([]byte(password), 4) - _, err = statement.Exec(username,hash,realname,email) + _, err = statement.Exec(username, hash, realname, email) if err != nil { return &common.HTTPError{ Message: fmt.Sprintf("error executing sqlite3 statement: %v", err), @@ -145,7 +147,7 @@ func EditUser() common.Handler { Message: fmt.Sprintf("error executing sqlite3 statement: %v", err), StatusCode: http.StatusInternalServerError, } - } + } } fmt.Println(hash) if bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) != nil { @@ -158,9 +160,9 @@ func EditUser() common.Handler { if newpassword != "" { pwhash, err = bcrypt.GenerateFromPassword([]byte(newpassword), 4) - } + } - _, err = statement.Exec(username,pwhash,realname,email,id) + _, err = statement.Exec(username, pwhash, realname, email, id) if err != nil { return &common.HTTPError{ Message: fmt.Sprintf("error executing sqlite3 statement: %v", err), @@ -328,15 +330,15 @@ func EditEpisode() common.Handler { fmt.Println(filename) description := strings.Join(r.Form["description"], "") - if ("./podcasts" + PreviousFilename + ".mp3" != filename) { - err = os.Rename("./podcasts/" + PreviousFilename + ".mp3", filename) + if "./podcasts"+PreviousFilename+".mp3" != filename { + err = os.Rename("./podcasts/"+PreviousFilename+".mp3", filename) if err != nil { return &common.HTTPError{ Message: err.Error(), StatusCode: http.StatusBadRequest, } } - err = os.Rename("./podcasts/" + PreviousFilename + "_SHOWNOTES.md", shownotes) + err = os.Rename("./podcasts/"+PreviousFilename+"_SHOWNOTES.md", shownotes) if err != nil { return &common.HTTPError{ Message: err.Error(), diff --git a/assets/config/users.db b/assets/config/users.db index ce23faea5360ab881878ef9a58f8666f86973ee8..cf14ec3cb9ecf97a7ca40c21a72cff3691991159 100644 GIT binary patch literal 32768 zcmeI)Z%^As90%}oE`$V>xT-Yy0Z*(7X^rRt0kW+RDiPWMY5qWhLlUIoILSc_w$s?o z0!Vv6_ZGINllFG@bmCR?2~XNR*@M|mAf(;8Xcd)!uOr8?bGf_U=gtu(zS}NjRhxI@>8{^*ih3!d<@j#P%VHal7I0Iq`?5N#xh?bi|5m z@V~f^Pkah*K>z{}fB*y_009U<;O+^$`8qf$l*`;t-`GlBV^&9V{t~a7?ViO<*<^;I zGr7^$y1F47tS673$oIUMN=hkFO0H&8Vr{I9YvSXnP)%*tLg~DeT2B?l{H7%4OWCZr zRZQoS#j2P|RmEgU+Dzx2{BxX>NJ>?%ztK{xR{x-z%w&o- zOy(Y8x}s{s1h1K?tCpp<4eP2VQ_;u@w;%`t_eS>++`=sHDKHZ0Bk$Ow{~O8Ky3-#2 zRLZF5XO{9sye^3KW0@nW(PYQ{=9iVO-S+n7vHF7?A1fJ+T#!BY)QnCAglEFP73npM zyy$KG(a?Vda?bx8`Qz?=$s!^MKmY;| zfB*y_009U<00I!WlLC8mlI+qwE=Ytkzc9xsO9poEOs+KqRG>{r{HmfAVh~4EJ9fSReoa2tWV=5P$## zAOHafKmY;|xOD~tfCT~&fB*y_009U< z00Izz00bZafuX>m&mEwDQ{(?f2k5`LoXddR$Xo{Q{r}$ezcc=S7$9Cj00Izz00bZa z0SG_<0uX=z1R!wx1>EufKA$`Oe-Mj1?tju*1GhgmL;wK@KmY;|fB*y_009U<00I!W O*8Mhsrv@+o4+a*#c?^6X_|Nh$;+wZwP(X`s z@;tsEmPUO>_Q_xPtS3wH6tZw>YBEpu;?rVe0+LFyhNZ=+Ma9fO<2XP@^77AOVB*(j z;9tbA&v$vVpu$1E$>-(RlGzzV8(G9POHzwVRE!c;3`|t?($c)#DpO2SgNjqjoQjiO zA}Z2zON-siGn4ZYyRXv80ok1LEqxR(ca-owFST?gLeB&2kVq#|I= permission { + isAllowed = true + } + } + return isAllowed, nil +} + +func RequireAuthorization(permission int) common.Handler { return func(rc *common.RouterContext, w http.ResponseWriter, r *http.Request) *common.HTTPError { usr, err := DecryptCookie(r) if err != nil { @@ -46,6 +81,17 @@ func RequireAuthorization() common.Handler { } rc.User = usr + + username := rc.User.Username + + hasPermission, err := UserPermissions(string(username), permission) + + if !hasPermission { + return &common.HTTPError{ + Message: "Unauthorized! Redirecting to /admin", + StatusCode: http.StatusUnauthorized, + } + } return nil } } diff --git a/router/router.go b/router/router.go index 0fe53aa..9c31b9a 100644 --- a/router/router.go +++ b/router/router.go @@ -1,21 +1,21 @@ package router import ( + "database/sql" "encoding/json" "fmt" + "golang.org/x/crypto/bcrypt" "io/ioutil" "log" "net/http" "strings" - "golang.org/x/crypto/bcrypt" - "database/sql" _ "github.com/mattn/go-sqlite3" - "github.com/gorilla/mux" "github.com/gmemstr/pogo/admin" "github.com/gmemstr/pogo/auth" "github.com/gmemstr/pogo/common" + "github.com/gorilla/mux" ) type NewConfig struct { @@ -70,7 +70,7 @@ func Init() *mux.Router { // Authenticated endpoints should be passed to BasicAuth() // first r.Handle("/admin", Handle( - auth.RequireAuthorization(), + auth.RequireAuthorization(0), adminHandler(), )).Methods("GET", "POST") @@ -79,45 +79,45 @@ func Init() *mux.Router { )).Methods("GET", "POST") r.Handle("/admin/publish", Handle( - auth.RequireAuthorization(), + auth.RequireAuthorization(0), admin.CreateEpisode(), )).Methods("POST") r.Handle("/admin/edituser", Handle( - auth.RequireAuthorization(), + auth.RequireAuthorization(2), admin.EditUser(), )).Methods("POST") r.Handle("/admin/newuser", Handle( - auth.RequireAuthorization(), + auth.RequireAuthorization(2), admin.AddUser(), )).Methods("POST") r.Handle("/admin/deleteuser/{id}", Handle( - auth.RequireAuthorization(), + auth.RequireAuthorization(2), admin.DeleteUser(), )).Methods("GET") r.Handle("/admin/edit", Handle( - auth.RequireAuthorization(), + auth.RequireAuthorization(0), admin.EditEpisode(), )).Methods("POST") r.Handle("/admin/delete", Handle( - auth.RequireAuthorization(), + auth.RequireAuthorization(0), admin.RemoveEpisode(), )).Methods("GET") r.Handle("/admin/css", Handle( - auth.RequireAuthorization(), + auth.RequireAuthorization(2), admin.CustomCss(), )).Methods("GET", "POST") r.Handle("/admin/adduser", Handle( - auth.RequireAuthorization(), + auth.RequireAuthorization(1), admin.AddUser(), )).Methods("POST") r.Handle("/admin/listusers", Handle( - auth.RequireAuthorization(), + auth.RequireAuthorization(1), admin.ListUsers(), )).Methods("GET") @@ -169,13 +169,14 @@ func loginHandler() common.Handler { StatusCode: http.StatusBadRequest, } } - var id int - var dbun string + var id int + var dbun string var dbhsh string - var dbrn string - var dbem string + var dbrn string + var dbem string + var dbperm int for rows.Next() { - err := rows.Scan(&id,&dbun,&dbhsh,&dbrn,&dbem) + err := rows.Scan(&id, &dbun, &dbhsh, &dbrn, &dbem, &dbperm) if err != nil { return &common.HTTPError{ Message: fmt.Sprintf("error in decoding sql data", err), @@ -186,7 +187,7 @@ func loginHandler() common.Handler { } // Create a cookie here because the credentials are correct if dbun == username && bcrypt.CompareHashAndPassword([]byte(dbhsh), []byte(password)) == nil { - c, err := auth.CreateSession(&common.User{ + c, err := auth.CreateSession(&common.User{ Username: username, }) if err != nil { @@ -204,7 +205,6 @@ func loginHandler() common.Handler { return nil } - return &common.HTTPError{ Message: "Invalid credentials!", StatusCode: http.StatusUnauthorized,