Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add non-admin/admin version split for instant launches, to allow users to create/update/delete #70

Merged
merged 2 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions instantlaunches/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,14 @@ func New(db *sqlx.DB, group *echo.Group, init *Init) *App {
instance.Group.DELETE("/:id", instance.DeleteInstantLaunchHandler)
instance.Group.GET("/:id/full", instance.FullInstantLaunchHandler)
instance.Group.GET("/:id/metadata", instance.GetMetadataHandler)
instance.Group.POST("/:id/metadata", instance.AddOrUpdateMetadataHandler)
instance.Group.PUT("/:id/metadata", instance.SetAllMetadataHandler)

iladmin := instance.Group.Group("/admin")
iladmin.PUT("/", instance.AdminAddInstantLaunchHandler)
iladmin.PUT("", instance.AdminAddInstantLaunchHandler)
iladmin.POST("/:id", instance.AdminUpdateInstantLaunchHandler)
iladmin.DELETE("/:id", instance.AdminDeleteInstantLaunchHandler)
iladmin.POST("/:id/metadata", instance.AdminAddOrUpdateMetadataHandler)
iladmin.PUT("/:id/metadata", instance.AdminSetAllMetadataHandler)

return instance
}
16 changes: 8 additions & 8 deletions instantlaunches/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,12 @@ func (a *App) GetMetadataHandler(c echo.Context) error {
return c.Blob(resp.StatusCode, resp.Header.Get("content-type"), body)
}

// AddOrUpdateMetadataHandler adds or updates one or more AVUs on an instant
// launch.
func (a *App) AddOrUpdateMetadataHandler(c echo.Context) error {
// AdminAddOrUpdateMetadataHandler adds or updates one or more AVUs on an instant
// launch as an admin
func (a *App) AdminAddOrUpdateMetadataHandler(c echo.Context) error {
ctx := c.Request().Context()

log.Debug("in AddOrUpdateMetadataHandler")
log.Debug("in AdminAddOrUpdateMetadataHandler")

id := c.Param("id")
if id == "" {
Expand Down Expand Up @@ -260,12 +260,12 @@ func (a *App) AddOrUpdateMetadataHandler(c echo.Context) error {
return c.Blob(resp.StatusCode, resp.Header.Get("content-type"), body)
}

// SetAllMetadataHandler sets all of the AVUs associated with an instant
// launch to the set contained in the body of the request.
func (a *App) SetAllMetadataHandler(c echo.Context) error {
// AdminSetAllMetadataHandler sets all of the AVUs associated with an instant
// launch to the set contained in the body of the request (as an admin).
func (a *App) AdminSetAllMetadataHandler(c echo.Context) error {
ctx := c.Request().Context()

log.Debug("in SetAllMetadataHandler")
log.Debug("in AdminSetAllMetadataHandler")

id := c.Param("id")
if id == "" {
Expand Down
127 changes: 122 additions & 5 deletions instantlaunches/mgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,62 @@ import (
"database/sql"
"fmt"
"net/http"
"regexp"
"strings"

"github.com/labstack/echo/v4"
)

// AddInstantLaunchHandler is the HTTP handler for adding a new instant launch.
// suffixUsername takes a possibly-already-suffixed username, strips any suffix, and adds the provided one, to ensure proper suffixing
func suffixUsername(username, suffix string) string {
re, _ := regexp.Compile(`@.*$`)
return fmt.Sprintf("%s@%s", re.ReplaceAllString(username, ""), strings.Trim(suffix, "@"))
}

// checkUserMatches ensures that `first` and `second` match when both suffixed the same.
func checkUserMatches(first, second, suffix string) bool {
return (suffixUsername(first, suffix) == suffixUsername(second, suffix))
}

// AddInstantLaunchHandler is the HTTP handler for adding a new instant launch
// as a regular user
func (a *App) AddInstantLaunchHandler(c echo.Context) error {
ctx := c.Request().Context()
user := c.QueryParam("user")
if user == "" {
return echo.NewHTTPError(http.StatusBadRequest, "user query parameter must be set")
}

il, err := NewInstantLaunchFromJSON(c.Request().Body)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "cannot parse JSON")
}

if il.AddedBy == "" {
return echo.NewHTTPError(http.StatusBadRequest, "username was not set")
}

if !checkUserMatches(il.AddedBy, user, a.UserSuffix) {
return echo.NewHTTPError(http.StatusBadRequest, "not authorized to create instant launches as another user")
}

if !strings.HasSuffix(il.AddedBy, a.UserSuffix) {
il.AddedBy = suffixUsername(il.AddedBy, a.UserSuffix)
}

newil, err := a.AddInstantLaunch(ctx, il.QuickLaunchID, il.AddedBy)
if err != nil {
if err == sql.ErrNoRows {
return echo.NewHTTPError(http.StatusNotFound, err.Error())
}
return err
}

return c.JSON(http.StatusOK, newil)
}

// AdminAddInstantLaunchHandler is the HTTP handler for adding a new instant launch as an admin.
func (a *App) AdminAddInstantLaunchHandler(c echo.Context) error {
ctx := c.Request().Context()
il, err := NewInstantLaunchFromJSON(c.Request().Body)
if err != nil {
Expand Down Expand Up @@ -77,8 +126,49 @@ func (a *App) FullInstantLaunchHandler(c echo.Context) error {
return c.JSON(http.StatusOK, il)
}

// UpdateInstantLaunchHandler is the HTTP handler for updating an instant launch.
// UpdateInstantLaunchHandler is the HTTP handler for updating an instant launch as a regular user
func (a *App) UpdateInstantLaunchHandler(c echo.Context) error {
ctx := c.Request().Context()
user := c.QueryParam("user")
if user == "" {
return echo.NewHTTPError(http.StatusBadRequest, "user query parameter must be set")
}

id := c.Param("id")
if id == "" {
return echo.NewHTTPError(http.StatusNotFound, "id is missing")
}

il, err := a.GetInstantLaunch(ctx, id)
if err != nil {
if err == sql.ErrNoRows {
return echo.NewHTTPError(http.StatusNotFound, err.Error())
}
return err
}

updated, err := NewInstantLaunchFromJSON(c.Request().Body)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "cannot parse JSON")
}

if !checkUserMatches(il.AddedBy, user, a.UserSuffix) || !checkUserMatches(il.AddedBy, updated.AddedBy, a.UserSuffix) {
return echo.NewHTTPError(http.StatusBadRequest, "not authorized to edit other users' instant launches")
}

newvalue, err := a.UpdateInstantLaunch(ctx, id, updated.QuickLaunchID)
if err != nil {
if err == sql.ErrNoRows {
return echo.NewHTTPError(http.StatusNotFound, err.Error())
}
return err
}

return c.JSON(http.StatusOK, newvalue)
}

// AdminUpdateInstantLaunchHandler is the HTTP handler for updating an instant launch as an admin.
func (a *App) AdminUpdateInstantLaunchHandler(c echo.Context) error {
ctx := c.Request().Context()
id := c.Param("id")
if id == "" {
Expand All @@ -102,17 +192,44 @@ func (a *App) UpdateInstantLaunchHandler(c echo.Context) error {
}

// DeleteInstantLaunchHandler is the HTTP handler for deleting an Instant Launch
// based on its UUID.
// based on its UUID as a regular user
func (a *App) DeleteInstantLaunchHandler(c echo.Context) error {
ctx := c.Request().Context()
user := c.QueryParam("user")
if user == "" {
return echo.NewHTTPError(http.StatusBadRequest, "user query parameter must be set")
}

id := c.Param("id")
if id == "" {
return echo.NewHTTPError(http.StatusNotFound, "id is missing")
}

err := a.DeleteInstantLaunch(ctx, id)
return err
il, err := a.GetInstantLaunch(ctx, id)
if err != nil {
if err == sql.ErrNoRows {
return echo.NewHTTPError(http.StatusNotFound, err.Error())
}
return err
}

if !checkUserMatches(il.AddedBy, user, a.UserSuffix) {
return echo.NewHTTPError(http.StatusBadRequest, "not authorized to delete other users' instant launches")
}

return a.DeleteInstantLaunch(ctx, id)
}

// AdminDeleteInstantLaunchHandler is the HTTP handler for deleting an Instant Launch
// based on its UUID as an admin
func (a *App) AdminDeleteInstantLaunchHandler(c echo.Context) error {
ctx := c.Request().Context()
id := c.Param("id")
if id == "" {
return echo.NewHTTPError(http.StatusNotFound, "id is missing")
}

return a.DeleteInstantLaunch(ctx, id)
}

// ListInstantLaunchesHandler is the HTTP handler for listing all of the
Expand Down