From 6a183f2c4ea057830220c047730e0aeef7c4e090 Mon Sep 17 00:00:00 2001 From: Bagas Aulia Rezki Date: Sun, 18 Aug 2024 14:06:00 +0700 Subject: [PATCH 1/3] feat: add admin page --- app/app.go | 16 +++++++++++++++- main.go | 27 ++++++++++++++++++++++++--- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/app/app.go b/app/app.go index 7be9975..d63191a 100644 --- a/app/app.go +++ b/app/app.go @@ -8,6 +8,7 @@ import ( ) var Server App +var Admin App type App struct { http.Server @@ -16,7 +17,7 @@ type App struct { Mail *email.SmtpServer } -func NewServer(addr string, handler http.Handler, logger logger.AggregatedLogger, database db.Database, mail email.SmtpServer) App { +func NewClientServer(addr string, handler http.Handler, logger logger.AggregatedLogger, database db.Database, mail email.SmtpServer) App { return App{ Server: http.Server{ Addr: addr, @@ -27,3 +28,16 @@ func NewServer(addr string, handler http.Handler, logger logger.AggregatedLogger Mail: &mail, } } + +func NewAdminServer(addr string, handler http.Handler, database db.Database) App { + return App{ + Server: http.Server{ + Addr: addr, + Handler: handler, + }, + // TODO: Remove the dummy struct + Logger: &logger.AggregatedLogger{}, + DB: &database, + Mail: &email.SmtpServer{}, + } +} diff --git a/main.go b/main.go index c0e3e3d..93f2704 100644 --- a/main.go +++ b/main.go @@ -9,11 +9,13 @@ import ( "github.com/fossyy/filekeeper/middleware" "github.com/fossyy/filekeeper/routes" "github.com/fossyy/filekeeper/utils" + "net/http" "strconv" ) func main() { - serverAddr := fmt.Sprintf("%s:%s", utils.Getenv("SERVER_HOST"), utils.Getenv("SERVER_PORT")) + clientAddr := fmt.Sprintf("%s:%s", utils.Getenv("SERVER_HOST"), utils.Getenv("SERVER_PORT")) + adminAddr := fmt.Sprintf("%s:%s", utils.Getenv("SERVER_HOST"), "27000") dbUser := utils.Getenv("DB_USERNAME") dbPass := utils.Getenv("DB_PASSWORD") @@ -27,8 +29,27 @@ func main() { smtpPort, _ := strconv.Atoi(utils.Getenv("SMTP_PORT")) mailServer := email.NewSmtpServer(utils.Getenv("SMTP_HOST"), smtpPort, utils.Getenv("SMTP_USER"), utils.Getenv("SMTP_PASSWORD")) - app.Server = app.NewServer(serverAddr, middleware.Handler(routes.SetupRoutes()), *logger.Logger(), database, mailServer) - fmt.Printf("Listening on http://%s\n", app.Server.Addr) + app.Server = app.NewClientServer(clientAddr, middleware.Handler(routes.SetupRoutes()), *logger.Logger(), database, mailServer) + + //TODO: Move admin route to its own folder + testRoute := http.NewServeMux() + testRoute.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("Hello, World!")) + return + }) + + app.Admin = app.NewAdminServer(adminAddr, testRoute, database) + + go func() { + fmt.Printf("Admin Web App Listening on http://%s\n\n", app.Admin.Addr) + err := app.Admin.ListenAndServe() + if err != nil { + panic(err) + return + } + }() + + fmt.Printf("Client Web App Listening on http://%s\n", app.Server.Addr) err := app.Server.ListenAndServe() if err != nil { panic(err) From fa2f4e8a878364fc6f65d9f4e67aea08240d3754 Mon Sep 17 00:00:00 2001 From: Bagas Aulia Rezki Date: Mon, 19 Aug 2024 21:00:46 +0700 Subject: [PATCH 2/3] refactor: call database functions from app.Server.Database instead of directly from db --- .air.toml | 2 +- app/app.go | 18 ++++++------- cache/cache.go | 17 ++++++------ db/database.go | 2 -- handler/auth/google/callback/callback.go | 3 +-- handler/auth/google/setup/setup.go | 3 +-- handler/download/download.go | 3 +-- handler/download/file/file.go | 4 +-- handler/forgotPassword/verify/verify.go | 3 +-- handler/signup/signup.go | 3 +-- handler/signup/verify/verify.go | 3 +-- .../upload/initialisation/initialisation.go | 3 +-- handler/user/ResetPassword/ResetPassword.go | 4 +-- handler/user/totp/setup.go | 4 +-- logger/logger.go | 27 ++++++++++++++----- main.go | 19 ++++--------- routes/admin/routes.go | 12 +++++++++ routes/{ => client}/routes.go | 2 +- 18 files changed, 69 insertions(+), 63 deletions(-) create mode 100644 routes/admin/routes.go rename routes/{ => client}/routes.go (99%) diff --git a/.air.toml b/.air.toml index 3651e65..4c9eee1 100644 --- a/.air.toml +++ b/.air.toml @@ -4,7 +4,7 @@ tmp_dir = "tmp" [build] args_bin = [] - bin = "tmp\\main.exe" + bin = "tmp\\main.exe --log true" cmd = "go build -o ./tmp/main.exe ." delay = 1000 exclude_dir = ["assets", "tmp", "vendor", "testdata", "uploads"] diff --git a/app/app.go b/app/app.go index d63191a..bc1a906 100644 --- a/app/app.go +++ b/app/app.go @@ -12,9 +12,9 @@ var Admin App type App struct { http.Server - DB *db.Database - Logger *logger.AggregatedLogger - Mail *email.SmtpServer + Database db.Database + Logger *logger.AggregatedLogger + Mail *email.SmtpServer } func NewClientServer(addr string, handler http.Handler, logger logger.AggregatedLogger, database db.Database, mail email.SmtpServer) App { @@ -23,9 +23,9 @@ func NewClientServer(addr string, handler http.Handler, logger logger.Aggregated Addr: addr, Handler: handler, }, - Logger: &logger, - DB: &database, - Mail: &mail, + Logger: &logger, + Database: database, + Mail: &mail, } } @@ -36,8 +36,8 @@ func NewAdminServer(addr string, handler http.Handler, database db.Database) App Handler: handler, }, // TODO: Remove the dummy struct - Logger: &logger.AggregatedLogger{}, - DB: &database, - Mail: &email.SmtpServer{}, + Logger: &logger.AggregatedLogger{}, + Database: database, + Mail: &email.SmtpServer{}, } } diff --git a/cache/cache.go b/cache/cache.go index b769c3d..cc4dee5 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -3,7 +3,6 @@ package cache import ( "fmt" "github.com/fossyy/filekeeper/app" - "github.com/fossyy/filekeeper/db" "github.com/fossyy/filekeeper/utils" "github.com/google/uuid" "sync" @@ -74,8 +73,8 @@ func init() { for _, file := range fileCache { file.mu.Lock() if currentTime.Sub(file.AccessAt) > time.Minute*1 { - db.DB.UpdateUploadedByte(file.UploadedByte, file.ID.String()) - db.DB.UpdateUploadedChunk(file.UploadedChunk, file.ID.String()) + app.Server.Database.UpdateUploadedByte(file.UploadedByte, file.ID.String()) + app.Server.Database.UpdateUploadedChunk(file.UploadedChunk, file.ID.String()) delete(fileCache, file.ID.String()) cacheClean++ } @@ -92,7 +91,7 @@ func GetUser(email string) (*UserWithExpired, error) { return user, nil } - userData, err := db.DB.GetUser(email) + userData, err := app.Server.Database.GetUser(email) if err != nil { return nil, err } @@ -122,7 +121,7 @@ func GetFile(id string) (*FileWithExpired, error) { return file, nil } - uploadData, err := db.DB.GetFile(id) + uploadData, err := app.Server.Database.GetFile(id) if err != nil { return nil, err } @@ -149,7 +148,7 @@ func (file *FileWithExpired) UpdateProgress(index int64, size int64) { } func GetUserFile(name, ownerID string) (*FileWithExpired, error) { - fileData, err := db.DB.GetUserFile(name, ownerID) + fileData, err := app.Server.Database.GetUserFile(name, ownerID) if err != nil { return nil, err } @@ -163,9 +162,9 @@ func GetUserFile(name, ownerID string) (*FileWithExpired, error) { } func (file *FileWithExpired) FinalizeFileUpload() { - db.DB.UpdateUploadedByte(file.UploadedByte, file.ID.String()) - db.DB.UpdateUploadedChunk(file.UploadedChunk, file.ID.String()) - db.DB.FinalizeFileUpload(file.ID.String()) + app.Server.Database.UpdateUploadedByte(file.UploadedByte, file.ID.String()) + app.Server.Database.UpdateUploadedChunk(file.UploadedChunk, file.ID.String()) + app.Server.Database.FinalizeFileUpload(file.ID.String()) delete(fileCache, file.ID.String()) return } diff --git a/db/database.go b/db/database.go index 668b017..ff9d059 100644 --- a/db/database.go +++ b/db/database.go @@ -12,8 +12,6 @@ import ( "strings" ) -var DB Database - type mySQLdb struct { *gorm.DB } diff --git a/handler/auth/google/callback/callback.go b/handler/auth/google/callback/callback.go index 0ca0b98..c112c46 100644 --- a/handler/auth/google/callback/callback.go +++ b/handler/auth/google/callback/callback.go @@ -7,7 +7,6 @@ import ( "fmt" "github.com/fossyy/filekeeper/app" "github.com/fossyy/filekeeper/cache" - "github.com/fossyy/filekeeper/db" googleOauthSetupHandler "github.com/fossyy/filekeeper/handler/auth/google/setup" signinHandler "github.com/fossyy/filekeeper/handler/signin" "github.com/fossyy/filekeeper/session" @@ -145,7 +144,7 @@ func GET(w http.ResponseWriter, r *http.Request) { return } - if !db.DB.IsEmailRegistered(oauthUser.Email) { + if !app.Server.Database.IsEmailRegistered(oauthUser.Email) { code := utils.GenerateRandomString(64) googleOauthSetupHandler.SetupUser[code] = &googleOauthSetupHandler.UnregisteredUser{ Code: code, diff --git a/handler/auth/google/setup/setup.go b/handler/auth/google/setup/setup.go index 0324a61..17823f6 100644 --- a/handler/auth/google/setup/setup.go +++ b/handler/auth/google/setup/setup.go @@ -3,7 +3,6 @@ package googleOauthSetupHandler import ( "fmt" "github.com/fossyy/filekeeper/app" - "github.com/fossyy/filekeeper/db" signinHandler "github.com/fossyy/filekeeper/handler/signin" "github.com/fossyy/filekeeper/session" "github.com/fossyy/filekeeper/types" @@ -112,7 +111,7 @@ func POST(w http.ResponseWriter, r *http.Request) { Password: hashedPassword, } - err = db.DB.CreateUser(&newUser) + err = app.Server.Database.CreateUser(&newUser) if err != nil { component := signupView.Main("Filekeeper - Sign up Page", types.Message{ Code: 0, diff --git a/handler/download/download.go b/handler/download/download.go index 61209ec..277bf1e 100644 --- a/handler/download/download.go +++ b/handler/download/download.go @@ -5,14 +5,13 @@ import ( "github.com/fossyy/filekeeper/view/client/download" "net/http" - "github.com/fossyy/filekeeper/db" "github.com/fossyy/filekeeper/types" "github.com/fossyy/filekeeper/utils" ) func GET(w http.ResponseWriter, r *http.Request) { userSession := r.Context().Value("user").(types.User) - files, err := db.DB.GetFiles(userSession.UserID.String()) + files, err := app.Server.Database.GetFiles(userSession.UserID.String()) if err != nil { w.WriteHeader(http.StatusInternalServerError) return diff --git a/handler/download/file/file.go b/handler/download/file/file.go index 71f0ad3..e80c883 100644 --- a/handler/download/file/file.go +++ b/handler/download/file/file.go @@ -5,13 +5,11 @@ import ( "net/http" "os" "path/filepath" - - "github.com/fossyy/filekeeper/db" ) func GET(w http.ResponseWriter, r *http.Request) { fileID := r.PathValue("id") - file, err := db.DB.GetFile(fileID) + file, err := app.Server.Database.GetFile(fileID) if err != nil { w.WriteHeader(http.StatusInternalServerError) app.Server.Logger.Error(err.Error()) diff --git a/handler/forgotPassword/verify/verify.go b/handler/forgotPassword/verify/verify.go index 72b91a3..8deda5e 100644 --- a/handler/forgotPassword/verify/verify.go +++ b/handler/forgotPassword/verify/verify.go @@ -3,7 +3,6 @@ package forgotPasswordVerifyHandler import ( "github.com/fossyy/filekeeper/app" "github.com/fossyy/filekeeper/cache" - "github.com/fossyy/filekeeper/db" forgotPasswordHandler "github.com/fossyy/filekeeper/handler/forgotPassword" "github.com/fossyy/filekeeper/session" "github.com/fossyy/filekeeper/types" @@ -83,7 +82,7 @@ func POST(w http.ResponseWriter, r *http.Request) { return } - err = db.DB.UpdateUserPassword(data.User.Email, hashedPassword) + err = app.Server.Database.UpdateUserPassword(data.User.Email, hashedPassword) if err != nil { w.WriteHeader(http.StatusInternalServerError) app.Server.Logger.Error(err.Error()) diff --git a/handler/signup/signup.go b/handler/signup/signup.go index a62cc65..86d43ba 100644 --- a/handler/signup/signup.go +++ b/handler/signup/signup.go @@ -11,7 +11,6 @@ import ( "sync" "time" - "github.com/fossyy/filekeeper/db" "github.com/fossyy/filekeeper/types" "github.com/fossyy/filekeeper/types/models" "github.com/fossyy/filekeeper/utils" @@ -102,7 +101,7 @@ func POST(w http.ResponseWriter, r *http.Request) { Password: hashedPassword, } - if registered := db.DB.IsUserRegistered(userEmail, username); registered { + if registered := app.Server.Database.IsUserRegistered(userEmail, username); registered { component := signupView.Main("Filekeeper - Sign up Page", types.Message{ Code: 0, Message: "Email or Username has been registered", diff --git a/handler/signup/verify/verify.go b/handler/signup/verify/verify.go index cfef3b5..5c66d0c 100644 --- a/handler/signup/verify/verify.go +++ b/handler/signup/verify/verify.go @@ -5,7 +5,6 @@ import ( signupView "github.com/fossyy/filekeeper/view/client/signup" "net/http" - "github.com/fossyy/filekeeper/db" signupHandler "github.com/fossyy/filekeeper/handler/signup" "github.com/fossyy/filekeeper/types" ) @@ -19,7 +18,7 @@ func GET(w http.ResponseWriter, r *http.Request) { return } - err := db.DB.CreateUser(data.User) + err := app.Server.Database.CreateUser(data.User) if err != nil { component := signupView.Main("Filekeeper - Sign up Page", types.Message{ Code: 0, diff --git a/handler/upload/initialisation/initialisation.go b/handler/upload/initialisation/initialisation.go index 444d079..9c9158f 100644 --- a/handler/upload/initialisation/initialisation.go +++ b/handler/upload/initialisation/initialisation.go @@ -10,7 +10,6 @@ import ( "os" "path/filepath" - "github.com/fossyy/filekeeper/db" "github.com/fossyy/filekeeper/types" "github.com/fossyy/filekeeper/types/models" "github.com/google/uuid" @@ -93,7 +92,7 @@ func handleNewUpload(user types.User, file types.FileInfo) (models.File, error) Done: false, } - err = db.DB.CreateFile(&newFile) + err = app.Server.Database.CreateFile(&newFile) if err != nil { app.Server.Logger.Error(err.Error()) return models.File{}, err diff --git a/handler/user/ResetPassword/ResetPassword.go b/handler/user/ResetPassword/ResetPassword.go index 26776c6..0f0f934 100644 --- a/handler/user/ResetPassword/ResetPassword.go +++ b/handler/user/ResetPassword/ResetPassword.go @@ -1,8 +1,8 @@ package userHandlerResetPassword import ( + "github.com/fossyy/filekeeper/app" "github.com/fossyy/filekeeper/cache" - "github.com/fossyy/filekeeper/db" "github.com/fossyy/filekeeper/session" "github.com/fossyy/filekeeper/types" "github.com/fossyy/filekeeper/utils" @@ -31,7 +31,7 @@ func POST(w http.ResponseWriter, r *http.Request) { return } - err = db.DB.UpdateUserPassword(user.Email, hashPassword) + err = app.Server.Database.UpdateUserPassword(user.Email, hashPassword) if err != nil { w.WriteHeader(http.StatusInternalServerError) return diff --git a/handler/user/totp/setup.go b/handler/user/totp/setup.go index 90fb057..600e917 100644 --- a/handler/user/totp/setup.go +++ b/handler/user/totp/setup.go @@ -4,13 +4,13 @@ import ( "bytes" "encoding/base64" "fmt" + "github.com/fossyy/filekeeper/app" "github.com/fossyy/filekeeper/cache" "github.com/fossyy/filekeeper/view/client/user/totp" "image/png" "net/http" "time" - "github.com/fossyy/filekeeper/db" "github.com/fossyy/filekeeper/types" "github.com/skip2/go-qrcode" "github.com/xlzd/gotp" @@ -71,7 +71,7 @@ func POST(w http.ResponseWriter, r *http.Request) { return } if totp.Verify(code, time.Now().Unix()) { - if err := db.DB.InitializeTotp(userSession.Email, secret); err != nil { + if err := app.Server.Database.InitializeTotp(userSession.Email, secret); err != nil { w.WriteHeader(http.StatusInternalServerError) return } diff --git a/logger/logger.go b/logger/logger.go index eb3aab1..27689bb 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -1,6 +1,7 @@ package logger import ( + "flag" "fmt" "io" "log" @@ -8,6 +9,9 @@ import ( "time" ) +var logFlag *bool +var infoLoggerWriter io.Writer + type AggregatedLogger struct { infoLogger *log.Logger warnLogger *log.Logger @@ -16,6 +20,9 @@ type AggregatedLogger struct { } func init() { + logFlag = flag.Bool("log", false, "Enable logging") + flag.Parse() + if _, err := os.Stat("log"); os.IsNotExist(err) { os.Mkdir("log", os.ModePerm) } @@ -25,15 +32,23 @@ func Logger() *AggregatedLogger { currentTime := time.Now() formattedTime := currentTime.Format("2006-01-02-15-04") file, err := os.OpenFile(fmt.Sprintf("log/log-%s.log", formattedTime), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + multiLogger := io.MultiWriter(os.Stdout, file) + if err != nil { return &AggregatedLogger{} } - flag := log.Ldate | log.Ltime - multiLogger := io.MultiWriter(os.Stdout, file) - infoLogger := log.New(file, "INFO: ", flag) - warnLogger := log.New(multiLogger, "WARN: ", flag) - errorLogger := log.New(multiLogger, "ERROR: ", flag) - panicLogger := log.New(multiLogger, "PANIC: ", flag) + + if *logFlag { + infoLoggerWriter = multiLogger + } else { + infoLoggerWriter = file + } + + slug := log.Ldate | log.Ltime + infoLogger := log.New(infoLoggerWriter, "INFO: ", slug) + warnLogger := log.New(multiLogger, "WARN: ", slug) + errorLogger := log.New(multiLogger, "ERROR: ", slug) + panicLogger := log.New(multiLogger, "PANIC: ", slug) return &AggregatedLogger{ infoLogger: infoLogger, diff --git a/main.go b/main.go index 93f2704..9f5eb97 100644 --- a/main.go +++ b/main.go @@ -7,9 +7,9 @@ import ( "github.com/fossyy/filekeeper/email" "github.com/fossyy/filekeeper/logger" "github.com/fossyy/filekeeper/middleware" - "github.com/fossyy/filekeeper/routes" + "github.com/fossyy/filekeeper/routes/admin" + "github.com/fossyy/filekeeper/routes/client" "github.com/fossyy/filekeeper/utils" - "net/http" "strconv" ) @@ -24,24 +24,15 @@ func main() { dbName := utils.Getenv("DB_NAME") database := db.NewPostgresDB(dbUser, dbPass, dbHost, dbPort, dbName, db.DisableSSL) - db.DB = database smtpPort, _ := strconv.Atoi(utils.Getenv("SMTP_PORT")) mailServer := email.NewSmtpServer(utils.Getenv("SMTP_HOST"), smtpPort, utils.Getenv("SMTP_USER"), utils.Getenv("SMTP_PASSWORD")) - app.Server = app.NewClientServer(clientAddr, middleware.Handler(routes.SetupRoutes()), *logger.Logger(), database, mailServer) - - //TODO: Move admin route to its own folder - testRoute := http.NewServeMux() - testRoute.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("Hello, World!")) - return - }) - - app.Admin = app.NewAdminServer(adminAddr, testRoute, database) + app.Server = app.NewClientServer(clientAddr, middleware.Handler(client.SetupRoutes()), *logger.Logger(), database, mailServer) + app.Admin = app.NewAdminServer(adminAddr, middleware.Handler(admin.SetupRoutes()), database) go func() { - fmt.Printf("Admin Web App Listening on http://%s\n\n", app.Admin.Addr) + fmt.Printf("Admin Web App Listening on http://%s\n", app.Admin.Addr) err := app.Admin.ListenAndServe() if err != nil { panic(err) diff --git a/routes/admin/routes.go b/routes/admin/routes.go new file mode 100644 index 0000000..037a52d --- /dev/null +++ b/routes/admin/routes.go @@ -0,0 +1,12 @@ +package admin + +import "net/http" + +func SetupRoutes() *http.ServeMux { + handler := http.NewServeMux() + handler.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("Hello, World!")) + return + }) + return handler +} diff --git a/routes/routes.go b/routes/client/routes.go similarity index 99% rename from routes/routes.go rename to routes/client/routes.go index 890c668..621911f 100644 --- a/routes/routes.go +++ b/routes/client/routes.go @@ -1,4 +1,4 @@ -package routes +package client import ( googleOauthHandler "github.com/fossyy/filekeeper/handler/auth/google" From 9aff0dbdb192c6a03a3ab3bc2f69a50ebcec6aa0 Mon Sep 17 00:00:00 2001 From: Bagas Aulia Rezki Date: Tue, 20 Aug 2024 13:28:09 +0700 Subject: [PATCH 3/3] feat: add initial admin page view with layout and basic components --- db/database.go | 20 ++ routes/admin/routes.go | 36 ++- staging.bat | 2 +- view/admin/index/index.templ | 429 +++++++++++++++++++++++++++++++++++ view/admin/layout/base.templ | 19 ++ 5 files changed, 503 insertions(+), 3 deletions(-) create mode 100644 view/admin/index/index.templ create mode 100644 view/admin/layout/base.templ diff --git a/db/database.go b/db/database.go index ff9d059..e01b291 100644 --- a/db/database.go +++ b/db/database.go @@ -33,6 +33,7 @@ type Database interface { CreateUser(user *models.User) error GetUser(email string) (*models.User, error) + GetAllUsers() ([]models.User, error) UpdateUserPassword(email string, password string) error CreateFile(file *models.File) error @@ -195,6 +196,15 @@ func (db *mySQLdb) GetUser(email string) (*models.User, error) { return &user, nil } +func (db *mySQLdb) GetAllUsers() ([]models.User, error) { + var users []models.User + err := db.DB.Table("users").Select("user_id, Username, Email").Find(&users).Error + if err != nil { + return nil, err + } + return users, nil +} + func (db *mySQLdb) UpdateUserPassword(email string, password string) error { var user models.User err := db.DB.Table("users").Where("email = ?", email).First(&user).Error @@ -318,6 +328,16 @@ func (db *postgresDB) GetUser(email string) (*models.User, error) { return &user, nil } +func (db *postgresDB) GetAllUsers() ([]models.User, error) { + var users []models.User + err := db.DB.Table("users").Select("user_id, username, email").Find(&users).Error + if err != nil { + fmt.Println(err) + return nil, err + } + return users, nil +} + func (db *postgresDB) UpdateUserPassword(email string, password string) error { var user models.User err := db.DB.Table("users").Where("email = $1", email).First(&user).Error diff --git a/routes/admin/routes.go b/routes/admin/routes.go index 037a52d..ddda602 100644 --- a/routes/admin/routes.go +++ b/routes/admin/routes.go @@ -1,12 +1,44 @@ package admin -import "net/http" +import ( + "github.com/fossyy/filekeeper/app" + adminIndex "github.com/fossyy/filekeeper/view/admin/index" + "net/http" + "os" + "path/filepath" +) func SetupRoutes() *http.ServeMux { handler := http.NewServeMux() handler.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("Hello, World!")) + //users, err := app.Admin.Database.GetAllUsers() + //if err != nil { + // http.Error(w, "Unable to retrieve users", http.StatusInternalServerError) + // return + //} + //w.Header().Set("Content-Type", "application/json") + //if err := json.NewEncoder(w).Encode(users); err != nil { + // http.Error(w, "Failed to encode response", http.StatusInternalServerError) + // return + //} + adminIndex.Main().Render(r.Context(), w) return }) + handler.HandleFunc("/public/output.css", func(w http.ResponseWriter, r *http.Request) { + openFile, err := os.OpenFile(filepath.Join("public", "output.css"), os.O_RDONLY, 0) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + app.Server.Logger.Error(err.Error()) + return + } + defer openFile.Close() + stat, err := openFile.Stat() + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + app.Server.Logger.Error(err.Error()) + return + } + http.ServeContent(w, r, openFile.Name(), stat.ModTime(), openFile) + }) return handler } diff --git a/staging.bat b/staging.bat index cdbcc43..4e60c1f 100644 --- a/staging.bat +++ b/staging.bat @@ -7,4 +7,4 @@ REM Watch for changes in Tailwind CSS start "" npx tailwindcss -i ./public/input.css -o ./public/output.css --watch REM Watch for changes in templates and proxy to Go server -start "" cmd /k "templ generate -watch -proxy=http://localhost:8000" \ No newline at end of file +start "" cmd /k "templ generate -watch" \ No newline at end of file diff --git a/view/admin/index/index.templ b/view/admin/index/index.templ new file mode 100644 index 0000000..5cc2d96 --- /dev/null +++ b/view/admin/index/index.templ @@ -0,0 +1,429 @@ +package adminIndex + +import "github.com/fossyy/filekeeper/view/admin/layout" + +templ Main() { + @layout.Base() { +
+
+
+
+
+

System Usage

+

Real-time metrics for your server.

+
+
+
+
+ + + + + + + + + + + + +
75%
+
CPU Usage
+
+
+ + + + + + + + + + + +
8GB
+
Memory Usage
+
+
+ + + + + + + +
100Mbps
+
Network Usage
+
+
+
+
+
+
+

User List

+

Manage your registered users.

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Name + + Email + + Role + + Actions +
+
John Doe
+
+
john@example.com
+
+
+ Admin +
+
+
Jane Smith
+
+
jane@example.com
+
+
+ Editor +
+
+
Bob Johnson
+
+
bob@example.com
+
+
+ User +
+
+
+
+
+
+
+
+
+

Server Control

+

Manage your server instances.

+
+
+
+
+
+
Server 1
+
192.168.1.100
+
+
+ + + +
+
+
+
+
+
Server 2
+
192.168.1.101
+
+
+ + + +
+
+
+
+
+
Server 3
+
192.168.1.102
+
+
+ + + +
+
+
+
+
+
+
+

Server Environment

+

Manage your server environment variables.

+
+
+
+
+
+
NODE_ENV
+
Environment mode
+
+ +
+
+
+
+
+
+
+ } +} diff --git a/view/admin/layout/base.templ b/view/admin/layout/base.templ new file mode 100644 index 0000000..2506102 --- /dev/null +++ b/view/admin/layout/base.templ @@ -0,0 +1,19 @@ +package layout + +templ Base(){ + + + + + + + Admin Page + + + +
+ { children... } +
+ + +} \ No newline at end of file