diff --git a/go/admin/admin.go b/go/admin/admin.go index 85d5d57c..aec1632b 100644 --- a/go/admin/admin.go +++ b/go/admin/admin.go @@ -26,6 +26,8 @@ import ( "time" "github.com/gin-contrib/cors" + "github.com/gin-contrib/sessions" + "github.com/gin-contrib/sessions/cookie" "github.com/gin-gonic/gin" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -38,6 +40,7 @@ const ( flagMode = "admin-mode" flagAdminAppId = "admin-gh-app-id" flagAdminAppSecret = "admin-gh-app-secret" + flagGhAuth = "auth" ) var workloads = []string{"OLTP", "OLTP-READONLY", "OLTP-SET", "TPCC", "TPCC_FK", "TPCC_FK_UNMANAGED", "TPCC_UNSHARDED"} @@ -48,6 +51,7 @@ type Admin struct { ghAppId string ghAppSecret string + ghTokenSalt string dbCfg *psdb.Config dbClient *psdb.Client @@ -60,11 +64,13 @@ func (a *Admin) AddToCommand(cmd *cobra.Command) { cmd.Flags().Var(&a.Mode, flagMode, "Specify the mode on which the server will run") cmd.Flags().StringVar(&a.ghAppId, flagAdminAppId, "", "The ID of the GitHub App") cmd.Flags().StringVar(&a.ghAppSecret, flagAdminAppSecret, "", "The secret of the GitHub App") + cmd.Flags().StringVar(&a.ghTokenSalt, flagGhAuth, "", "The salt string to salt the GitHub Token") _ = viper.BindPFlag(flagPort, cmd.Flags().Lookup(flagPort)) _ = viper.BindPFlag(flagMode, cmd.Flags().Lookup(flagMode)) _ = viper.BindPFlag(flagAdminAppId, cmd.Flags().Lookup(flagAdminAppId)) _ = viper.BindPFlag(flagAdminAppSecret, cmd.Flags().Lookup(flagAdminAppSecret)) + _ = viper.BindPFlag(flagGhAuth, cmd.Flags().Lookup(flagGhAuth)) if a.dbCfg == nil { a.dbCfg = &psdb.Config{} @@ -113,15 +119,18 @@ func (a *Admin) Run() error { a.Mode.SetGin() a.router = gin.Default() + store := cookie.NewStore([]byte("secret")) + a.router.Use(sessions.Sessions("admin-session", store)) + a.router.Static("/assets", filepath.Join(basepath, "assets")) a.router.LoadHTMLGlob(filepath.Join(basepath, "templates/*")) a.router.Use(cors.New(cors.Config{ AllowOrigins: []string{"*"}, - AllowMethods: []string{"GET"}, + AllowMethods: []string{"GET", "POST"}, AllowHeaders: []string{"Origin"}, - ExposeHeaders: []string{"Content-Length"}, + ExposeHeaders: []string{"Content-Length", "Content-Type"}, AllowCredentials: true, MaxAge: 12 * time.Hour, })) @@ -130,6 +139,7 @@ func (a *Admin) Run() error { a.router.GET("/admin", a.login) a.router.GET("/admin/login", a.handleGitHubLogin) a.router.GET("/admin/auth/callback", a.handleGitHubCallback) + a.router.POST("/admin/executions/add", a.handleExecutionsAdd) a.router.GET("/admin/dashboard", a.authMiddleware(), a.dashboard) return a.router.Run(":" + a.port) diff --git a/go/admin/api.go b/go/admin/api.go index db1fd3b9..c31f52b6 100644 --- a/go/admin/api.go +++ b/go/admin/api.go @@ -19,7 +19,9 @@ package admin import ( + "bytes" "context" + "encoding/json" "net/http" "strings" "time" @@ -39,6 +41,7 @@ var ( RedirectURL: "http://localhost:8081/admin/auth/callback", } oauthStateString = random.String(10) // A random string to protect against CSRF attacks + client *goGithub.Client ) const ( @@ -46,19 +49,20 @@ const ( arewefastyetTeamGitHub = "arewefastyet" ) +type ExecutionRequest struct { + Auth string `json:"auth"` + Source string `json:"source"` + SHA string `json:"sha"` + Workloads []string `json:"workloads"` + NumberOfExecutions string `json:"number_of_executions"` +} + func (a *Admin) login(c *gin.Context) { a.render(c, gin.H{}, "login.html") } func (a *Admin) dashboard(c *gin.Context) { - user, err := c.Cookie("ghtoken") - if err != nil { - c.Abort() - return - } - a.render(c, gin.H{ - "ghtoken": user, - }, "base.html") + a.render(c, gin.H{}, "base.html") } func (a *Admin) authMiddleware() gin.HandlerFunc { @@ -153,3 +157,70 @@ func (a *Admin) checkUserOrgMembership(client *goGithub.Client, username, orgNam } return isMember, nil } + +func (a *Admin) handleExecutionsAdd(c *gin.Context) { + slog.Info("Adding execution") + token, err := c.Cookie("ghtoken") + source := c.PostForm("source") + sha := c.PostForm("sha") + workloads := c.PostFormArray("workloads") + numberOfExecutions := c.PostForm("numberOfExecutions") + + if err != nil { + slog.Error("Failed to get token from cookie: ", err) + c.AbortWithStatus(http.StatusUnauthorized) + return + } + + encryptedToken := server.Encrypt(token, a.ghTokenSalt) + + requestPayload := ExecutionRequest{ + Auth: encryptedToken, + Source: source, + SHA: sha, + Workloads: workloads, + NumberOfExecutions: numberOfExecutions, + } + + jsonData, err := json.Marshal(requestPayload) + + slog.Infof("Request payload: %s", jsonData) + + if err != nil { + slog.Error("Failed to marshal request payload: ", err) + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to marshal request payload"}) + return + } + + serverAPIURL := "http://localhost:8080/api/executions/add" + // make a body with "admin-user": {encryptedToken}, "source": {source}, "sha": {sha}, "workloads": workloads, "numberOfExecutions": {numberOfExecutions}} + + req, err := http.NewRequest("POST", serverAPIURL, bytes.NewBuffer(jsonData)) + + if err != nil { + slog.Error("Failed to create new HTTP request: ", err) + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create request to server API"}) + return + } + + req.Header.Set("Content-Type", "application/json") + + // Execute the request + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + slog.Error("Failed to send request to server API: ", err) + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to send request to server API"}) + return + } + defer resp.Body.Close() + + // Handle the response from the server API + if resp.StatusCode != http.StatusOK { + slog.Error("Server API returned an error: ", resp.Status) + c.JSON(resp.StatusCode, gin.H{"error": "Failed to process request on server API"}) + return + } + + c.JSON(http.StatusOK, gin.H{"message": "Request forwarded to server API"}) +} diff --git a/go/admin/templates/content.html b/go/admin/templates/content.html index 1017c302..ca8a5584 100644 --- a/go/admin/templates/content.html +++ b/go/admin/templates/content.html @@ -42,7 +42,7 @@ type="number" name="numberOfExecutions" value="1" min="1" max="10"> - diff --git a/go/admin/templates/executions.html b/go/admin/templates/executions.html deleted file mode 100644 index 5a985748..00000000 --- a/go/admin/templates/executions.html +++ /dev/null @@ -1,36 +0,0 @@ -