package main import ( "fmt" "os" _ "ttime/docs" "ttime/internal/config" "ttime/internal/database" "ttime/internal/handlers/projects" "ttime/internal/handlers/reports" "ttime/internal/handlers/users" "github.com/BurntSushi/toml" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/logger" "github.com/gofiber/swagger" jwtware "github.com/gofiber/contrib/jwt" ) // @title TTime API // @version 0.0.1 // @description This is the API for TTime, a time tracking application. // @license.name AGPL // @license.url https://www.gnu.org/licenses/agpl-3.0.html // @securityDefinitions.apikey JWT // @in header // @name Authorization // @description Use the JWT token provided by the login endpoint to authenticate requests. **Prefix the token with "Bearer ".** // @host localhost:8080 // @BasePath /api // @externalDocs.description OpenAPI // @externalDocs.url https://swagger.io/resources/open-api/ /** Main function for starting the server and initializing configurations. Reads configuration from file, pretty prints it, connects to the database, migrates it, and sets up routes for the server. */ func main() { conf, err := config.ReadConfigFromFile("config.toml") if err != nil { conf = config.NewConfig() _ = conf.WriteConfigToFile("config.toml") } // Pretty print the current config with toml _ = toml.NewEncoder(os.Stdout).Encode(conf) fmt.Printf("Starting server on http://localhost:%d\n", conf.Port) fmt.Printf("For documentation, go to http://localhost:%d/swagger/index.html\n", conf.Port) // Connect to the database db := database.DbConnect(conf.DbPath) // Migrate the database if err = database.Migrate(db); err != nil { fmt.Println("Error migrating database: ", err) os.Exit(1) } // Migrate sample data, should not be used in production if err = database.MigrateSampleData(db); err != nil { fmt.Println("Error migrating sample data: ", err) os.Exit(1) } // Create the server server := fiber.New() // We want some logs server.Use(logger.New()) // Sets up db middleware, accessed as Local "db" key server.Use(database.DbMiddleware(&db)) // Mounts the swagger documentation, this is available at /swagger/index.html server.Get("/swagger/*", swagger.HandlerDefault) // Mount our static files (Beware of the security implications of this!) // This will likely be replaced by an embedded filesystem in the future server.Static("/", "./static") // Create a group for our API api := server.Group("/api") // Register our unprotected routes api.Post("/register", users.Register) api.Post("/login", users.Login) // Every route from here on will require a valid // JWT bearer token authentication in the header server.Use(jwtware.New(jwtware.Config{ SigningKey: jwtware.SigningKey{Key: []byte("secret")}, })) // All user related routes // userGroup := api.Group("/user") // Not currently in use api.Get("/users/all", users.ListAllUsers) api.Get("/project/getAllUsers", users.GetAllUsersProject) api.Get("/username", users.GetUserName) api.Post("/login", users.Login) api.Post("/register", users.Register) api.Post("/loginrenew", users.LoginRenew) api.Post("/promoteToAdmin", users.PromoteToAdmin) api.Put("/changeUserName", users.ChangeUserName) api.Delete("/userdelete/:username", users.UserDelete) // Perhaps just use POST to avoid headaches api.Put("/changeUserPassword/:username", users.ChangeUserPassword) // All project related routes // projectGroup := api.Group("/project") // Not currently in use api.Get("/getProjectTimes/:projectName", projects.GetProjectTimesHandler) api.Get("/getUserProjects/:username", projects.GetUserProjects) api.Get("/project/:projectId", projects.GetProject) api.Get("/checkIfProjectManager/:projectName", projects.IsProjectManagerHandler) api.Get("/getUsersProject/:projectName", projects.ListAllUsersProject) api.Post("/project", projects.CreateProject) api.Post("/ProjectRoleChange", projects.ProjectRoleChange) api.Put("/promoteToPm/:projectName", projects.PromoteToPm) api.Put("/addUserToProject/:projectName", projects.AddUserToProjectHandler) api.Delete("/removeUserFromProject/:projectName", projects.RemoveUserFromProject) api.Delete("/removeProject/:projectName", projects.RemoveProject) api.Delete("/project/:projectID", projects.DeleteProject) api.Put("/ChangeProjectName/:projectName", projects.ChangeProjectName) // All report related routes // reportGroup := api.Group("/report") // Not currently in use api.Get("/getWeeklyReport", reports.GetWeeklyReport) api.Get("/getUnsignedReports/:projectName", reports.GetUnsignedReports) api.Get("/getAllWeeklyReports/:projectName", reports.GetAllWeeklyReports) api.Get("/getStatistics", reports.GetStatistics) api.Post("/submitWeeklyReport", reports.SubmitWeeklyReport) api.Put("/signReport/:reportId", reports.SignReport) api.Put("/updateWeeklyReport", reports.UpdateWeeklyReport) api.Put("/unsignReport/:reportId", reports.UnsignReport) api.Delete("/deleteReport/:reportId", reports.DeleteReport) // Announce the port we are listening on and start the server err = server.Listen(fmt.Sprintf(":%d", conf.Port)) if err != nil { fmt.Println("Error starting server: ", err) } }