From e5629fb163c7cf303438afc5be6075299cfc6071 Mon Sep 17 00:00:00 2001 From: Mike Crute Date: Wed, 24 Nov 2021 21:58:09 -0800 Subject: Extract URL building logic --- app/controllers/api.go | 8 +++--- app/controllers/api_account.go | 3 ++- app/controllers/api_account_list.go | 14 +++++----- app/controllers/api_region_list.go | 13 ++++++---- app/controllers/api_user.go | 3 ++- app/controllers/api_user_list.go | 4 +-- app/urls.go | 51 +++++++++++++++++++++++++++++++++++++ cmd/web/server.go | 8 +++--- 8 files changed, 82 insertions(+), 22 deletions(-) create mode 100644 app/urls.go diff --git a/app/controllers/api.go b/app/controllers/api.go index 39fc227..0820584 100644 --- a/app/controllers/api.go +++ b/app/controllers/api.go @@ -3,9 +3,9 @@ package controllers import ( "net/http" + "code.crute.us/mcrute/cloud-identity-broker/app" "code.crute.us/mcrute/cloud-identity-broker/app/middleware" - glecho "code.crute.us/mcrute/golib/echo" "github.com/labstack/echo/v4" ) @@ -23,12 +23,14 @@ func APIIndexHandler(c echo.Context) error { return echo.ErrUnauthorized } + au := app.AppURL{} + out := map[string]string{ - "accounts": glecho.URLFor(c, "/api/account").String(), + "accounts": au.Account(c, "", nil), } if p.IsAdmin { - out["users"] = glecho.URLFor(c, "/api/user").String() + out["users"] = au.User(c, nil) } return c.JSON(http.StatusOK, out) diff --git a/app/controllers/api_account.go b/app/controllers/api_account.go index f22191d..815daf4 100644 --- a/app/controllers/api_account.go +++ b/app/controllers/api_account.go @@ -6,6 +6,7 @@ import ( "net/http" "time" + "code.crute.us/mcrute/cloud-identity-broker/app" "code.crute.us/mcrute/cloud-identity-broker/app/middleware" "code.crute.us/mcrute/cloud-identity-broker/app/models" "code.crute.us/mcrute/cloud-identity-broker/cloud/aws" @@ -191,7 +192,7 @@ func (h *APIAccountHandler) HandlePost(c echo.Context) error { return echo.ErrInternalServerError } - c.Response().Header().Add("Location", glecho.URLFor(c, "/api/account", in.ShortName).String()) + c.Response().Header().Add("Location", app.AppURL{}.Account(c, "aws", &in.ShortName)) return c.String(http.StatusCreated, "") } diff --git a/app/controllers/api_account_list.go b/app/controllers/api_account_list.go index 28b64c1..4835d0c 100644 --- a/app/controllers/api_account_list.go +++ b/app/controllers/api_account_list.go @@ -4,10 +4,10 @@ import ( "context" "net/http" + "code.crute.us/mcrute/cloud-identity-broker/app" "code.crute.us/mcrute/cloud-identity-broker/app/middleware" "code.crute.us/mcrute/cloud-identity-broker/app/models" - glecho "code.crute.us/mcrute/golib/echo" "code.crute.us/mcrute/golib/echo/controller" "github.com/labstack/echo/v4" ) @@ -25,15 +25,17 @@ type jsonAccount struct { } func jsonAccountFromAccount(c echo.Context, a *models.Account) *jsonAccount { + u := app.AppURL{} + return &jsonAccount{ AccountNumber: a.AccountNumber, ShortName: a.ShortName, Name: a.Name, - SelfUrl: glecho.URLFor(c, "/api/account", a.ShortName).String(), - ConsoleUrl: glecho.URLFor(c, "/api/account", a.ShortName, "console").String(), - ConsoleRedirectUrl: glecho.URLFor(c, "/api/account", a.ShortName, "console").Query("redirect", "1").String(), - CredentialsUrl: glecho.URLFor(c, "/api/account", a.ShortName, "credentials").String(), - GlobalCredentialsUrl: glecho.URLFor(c, "/api/account", a.ShortName, "credentials/global").String(), + SelfUrl: u.Account(c, "aws", &a.ShortName), + ConsoleUrl: u.AccountConsole(c, "aws", a.ShortName, false), + ConsoleRedirectUrl: u.AccountConsole(c, "aws", a.ShortName, true), + CredentialsUrl: u.AccountCredentials(c, "aws", a.ShortName, ""), + GlobalCredentialsUrl: u.AccountCredentials(c, "aws", a.ShortName, "global"), } } diff --git a/app/controllers/api_region_list.go b/app/controllers/api_region_list.go index 44d591c..c34ac3a 100644 --- a/app/controllers/api_region_list.go +++ b/app/controllers/api_region_list.go @@ -3,7 +3,7 @@ package controllers import ( "net/http" - glecho "code.crute.us/mcrute/golib/echo" + "code.crute.us/mcrute/cloud-identity-broker/app" "code.crute.us/mcrute/golib/echo/controller" "github.com/labstack/echo/v4" ) @@ -17,10 +17,14 @@ type jsonRegion struct { type APIRegionListHandler struct { *AWSAPI + urls app.AppURL } func NewAPIRegionListHandler(a *AWSAPI) echo.HandlerFunc { - al := &APIRegionListHandler{a} + al := &APIRegionListHandler{ + AWSAPI: a, + urls: app.AppURL{}, + } h := &controller.ContentTypeNegotiatingHandler{ DefaultHandler: al.Handle, Handlers: map[string]echo.HandlerFunc{ @@ -52,9 +56,8 @@ func (h *APIRegionListHandler) Handle(c echo.Context) error { Default: rc.Account.DefaultRegion == r.Name, } if r.Enabled { - out[i].CredentialsURL = glecho.URLFor(c, - "/api/account", rc.Account.ShortName, "credentials", r.Name, - ).String() + out[i].CredentialsURL = h.urls.AccountCredentials( + c, "aws", rc.Account.ShortName, r.Name) } } diff --git a/app/controllers/api_user.go b/app/controllers/api_user.go index e55d88d..b024ffd 100644 --- a/app/controllers/api_user.go +++ b/app/controllers/api_user.go @@ -4,6 +4,7 @@ import ( "context" "net/http" + "code.crute.us/mcrute/cloud-identity-broker/app" "code.crute.us/mcrute/cloud-identity-broker/app/models" glecho "code.crute.us/mcrute/golib/echo" @@ -152,7 +153,7 @@ func (h *APIUserHandler) HandlePost(c echo.Context) error { return echo.ErrInternalServerError } - c.Response().Header().Add("Location", glecho.URLFor(c, "/api/user", in.Username).String()) + c.Response().Header().Add("Location", app.AppURL{}.User(c, &in.Username)) return c.String(http.StatusCreated, "") } diff --git a/app/controllers/api_user_list.go b/app/controllers/api_user_list.go index c753093..415517d 100644 --- a/app/controllers/api_user_list.go +++ b/app/controllers/api_user_list.go @@ -5,9 +5,9 @@ import ( "net/http" "time" + "code.crute.us/mcrute/cloud-identity-broker/app" "code.crute.us/mcrute/cloud-identity-broker/app/models" - glecho "code.crute.us/mcrute/golib/echo" "code.crute.us/mcrute/golib/echo/controller" "github.com/labstack/echo/v4" ) @@ -47,7 +47,7 @@ func (h *APIUserListHandler) Handle(c echo.Context) error { Username: v.Username, IsAdmin: v.IsAdmin, IsService: v.IsService, - SelfLink: glecho.URLFor(c, "/api/user", v.Username).String(), + SelfLink: app.AppURL{}.User(c, &v.Username), Deleted: v.Deleted, } } diff --git a/app/urls.go b/app/urls.go new file mode 100644 index 0000000..8cceb37 --- /dev/null +++ b/app/urls.go @@ -0,0 +1,51 @@ +package app + +import ( + glecho "code.crute.us/mcrute/golib/echo" + "github.com/labstack/echo/v4" +) + +// AppURL is an interface to building URLs to the application. This exists +// because the Echo reverse URL functionality requires keeping references to +// handler functions for the ability to reverse URLs which doesn't work at all +// for the structure of this application. This interface is effectively named +// URLs. If Echo supports named URLs in the future this struct can be removed. +type AppURL struct{} + +func (u AppURL) Account(c echo.Context, provider string, shortName *string) string { + parts := []string{"/api/account"} + + if provider != "" { + parts = append(parts, provider) + } + + if shortName != nil { + parts = append(parts, *shortName) + } + + return glecho.URLFor(c, parts...).String() +} + +func (u AppURL) User(c echo.Context, username *string) string { + if username != nil { + return glecho.URLFor(c, "/api/user", *username).String() + } else { + return glecho.URLFor(c, "/api/user").String() + } +} + +func (u AppURL) AccountConsole(c echo.Context, provider, shortName string, redir bool) string { + au := glecho.URLFor(c, "/api/account", provider, shortName, "console") + if redir { + au = au.Query("redirect", "1") + } + return au.String() +} + +func (u AppURL) AccountCredentials(c echo.Context, provider, shortName string, region string) string { + if region != "" { + return glecho.URLFor(c, "/api/account", provider, shortName, "credentials", region).String() + } else { + return glecho.URLFor(c, "/api/account", provider, shortName, "credentials").String() + } +} diff --git a/cmd/web/server.go b/cmd/web/server.go index 9f750bc..610cc72 100644 --- a/cmd/web/server.go +++ b/cmd/web/server.go @@ -143,23 +143,23 @@ func webMain(cfg app.Config, embeddedTemplates fs.FS, version string) { { account.GET("", controllers.NewAPIAccountListHandler(as)) account.GET( - "/:account/credentials", + "/:provider/:account/credentials", controllers.NewAPIRegionListHandler(aws), ) account.GET( - "/:account/console", + "/:provider/:account/console", controllers.NewAPIConsoleRedirectHandler(aws, cfg.IssuerEndpoint), rateLimit, ) account.GET( - "/:account/credentials/:region", + "/:provider/:account/credentials/:region", controllers.NewAPICredentialsHandler(aws), rateLimit, ) (&controllers.APIAccountHandler{ Store: as, AdminStore: adminAccountStore, - }).Register("/:account", "", account) + }).Register("/:provider/:account", "", account) } user := api.Group("/user") -- cgit v1.2.3