From 7b4d9ee83f408ea0f09a4985d13e3a468978d300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lie=20Delhaie?= Date: Sun, 29 May 2022 23:05:06 +0200 Subject: [PATCH] List of users for admin, build script, update dump --- .gitignore | 3 ++- build.sh | 24 ++++++++++++++++++++++++ database/database.go | 14 ++++++++++++++ db_dump.sql | 7 ++----- server/data.go | 10 ++++++++++ server/response.go | 21 +++++++++++++++++++++ server/server.go | 34 +++++++++++++++++++++++++++++++++- 7 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 build.sh diff --git a/.gitignore b/.gitignore index 92bdb86..514b75d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ config.yml cache/ opensavecloudserver storage/ -.idea/ \ No newline at end of file +.idea/ +build \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..844bda2 --- /dev/null +++ b/build.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +platforms=("windows/amd64" "windows/arm64" "darwin/amd64" "darwin/arm64" "linux/amd64" "linux/arm64") + +if [[ -d "./build" ]] +then + rm -r ./build +fi + +mkdir build +cd build + +for platform in "${platforms[@]}" +do + echo "* Compiling for $platform..." + platform_split=(${platform//\// }) + GOOS=${platform_split[0]} + GOARCH=${platform_split[1]} + output_name='osc-'$GOOS'-'$GOARCH + if [ $GOOS = "windows" ]; then + output_name+='.exe' + fi + env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name -a ../main.go +done \ No newline at end of file diff --git a/database/database.go b/database/database.go index ea61cca..a24b9de 100644 --- a/database/database.go +++ b/database/database.go @@ -49,6 +49,20 @@ func init() { } } +func AllUsers() ([]*User, error) { + var users []*User + err := db.Model(User{}).Find(&users).Error + if err != nil { + return nil, err + } + for _, user := range users { + if user.Role == adminRole { + user.IsAdmin = true + } + } + return users, nil +} + // UserByUsername get a user by the username func UserByUsername(username string) (*User, error) { var user *User diff --git a/db_dump.sql b/db_dump.sql index 674e3cc..177cafc 100644 --- a/db_dump.sql +++ b/db_dump.sql @@ -16,18 +16,15 @@ -- Dumping database structure for osc -DROP DATABASE IF EXISTS `osc`; -CREATE DATABASE IF NOT EXISTS `osc` /*!40100 DEFAULT CHARACTER SET utf8 */ /*!80016 DEFAULT ENCRYPTION='N' */; USE `osc`; -- Dumping structure for table osc.games -DROP TABLE IF EXISTS `games`; CREATE TABLE IF NOT EXISTS `games` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL DEFAULT '0', `revision` bigint unsigned NOT NULL DEFAULT '0', `path_storage` text NOT NULL, - `hash` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, + `hash` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `last_update` datetime DEFAULT NULL, `user_id` bigint unsigned NOT NULL DEFAULT '0', `available` tinyint unsigned NOT NULL DEFAULT '0', @@ -37,11 +34,11 @@ CREATE TABLE IF NOT EXISTS `games` ( -- Data exporting was unselected. -- Dumping structure for table osc.users -DROP TABLE IF EXISTS `users`; CREATE TABLE IF NOT EXISTS `users` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `password` binary(60) NOT NULL, + `role` varchar(10) NOT NULL DEFAULT 'user', PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3; diff --git a/server/data.go b/server/data.go index 98dcb2a..bd82de6 100644 --- a/server/data.go +++ b/server/data.go @@ -281,3 +281,13 @@ func ChangePassword(w http.ResponseWriter, r *http.Request) { } ok(payload, w, r) } + +func AllUsers(w http.ResponseWriter, r *http.Request) { + users, err := database.AllUsers() + if err != nil { + internalServerError(w, r) + log.Println(err) + return + } + ok(users, w, r) +} diff --git a/server/response.go b/server/response.go index da81db3..d6328d5 100644 --- a/server/response.go +++ b/server/response.go @@ -64,6 +64,27 @@ func unauthorized(w http.ResponseWriter, r *http.Request) { } } +func forbidden(w http.ResponseWriter, r *http.Request) { + e := httpError{ + Status: 403, + Error: "Unauthorized", + Message: "The access is permanently forbidden and tied to the application logic, such as insufficient rights to a resource.", + Path: r.RequestURI, + Timestamp: time.Now(), + } + + payload, err := json.Marshal(e) + if err != nil { + log.Println(err) + } + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(403) + _, err = w.Write(payload) + if err != nil { + log.Println(err) + } +} + func ok(obj interface{}, w http.ResponseWriter, _ *http.Request) { payload, err := json.Marshal(obj) if err != nil { diff --git a/server/server.go b/server/server.go index 4c7eb64..4ee2919 100644 --- a/server/server.go +++ b/server/server.go @@ -10,6 +10,7 @@ import ( "net/http" "opensavecloudserver/authentication" "opensavecloudserver/config" + "opensavecloudserver/database" "opensavecloudserver/upload" ) @@ -34,7 +35,9 @@ func Serve() { } r.Route("/system", func(systemRouter chi.Router) { systemRouter.Get("/information", Information) - + systemRouter.Group(func(secureRouter chi.Router) { + secureRouter.Get("/users", AllUsers) + }) }) r.Route("/user", func(secureRouter chi.Router) { secureRouter.Use(authMiddleware) @@ -82,6 +85,35 @@ func authMiddleware(next http.Handler) http.Handler { }) } +// adminMiddleware check the role of the user before accessing to the resource +func adminMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + header := r.Header.Get("Authorization") + if len(header) > 7 { + userId, err := authentication.ParseToken(header[7:]) + if err != nil { + unauthorized(w, r) + return + } + user, err := database.UserById(userId) + if err != nil { + internalServerError(w, r) + log.Println(err) + return + } + if !user.IsAdmin { + forbidden(w, r) + return + } + ctx := context.WithValue(r.Context(), UserIdKey, userId) + r = r.WithContext(ctx) + next.ServeHTTP(w, r) + return + } + unauthorized(w, r) + }) +} + // uploadMiddleware check the upload key before allowing to upload a file func uploadMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {