package controllers 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" "code.crute.us/mcrute/golib/echo/controller" "github.com/labstack/echo/v4" ) type jsonAccount struct { Vendor string `json:"vendor,omitempty"` AccountNumber int `json:"account_number"` ShortName string `json:"short_name"` Name string `json:"name"` SelfUrl string `json:"url"` ConsoleUrl string `json:"get_console_url,omitempty"` ConsoleRedirectUrl string `json:"console_redirect_url,omitempty"` CredentialsUrl string `json:"credentials_url"` GlobalCredentialsUrl string `json:"global_credential_url,omitempty"` } func jsonAccountFromAccount(c echo.Context, a *models.Account) *jsonAccount { u := app.AppURL{} return &jsonAccount{ AccountNumber: a.AccountNumber, ShortName: a.ShortName, Name: a.Name, 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"), } } type APIAccountListHandler struct { store models.AccountStore } func NewAPIAccountListHandler(s models.AccountStore) echo.HandlerFunc { al := &APIAccountListHandler{store: s} h := &controller.ContentTypeNegotiatingHandler{ DefaultHandler: al.HandleV1, Handlers: map[string]echo.HandlerFunc{ contentTypeV1: al.HandleV1, contentTypeV2: al.HandleV2, }, } return h.Handle } // getAccountList returns the account list. This does the same work that // GetContext would do for most AWSAPI handlers but is a little different // because it deals with lists of accounts. // // Authorization of the account is handled within the store. The store will not // return accounts for which the user does not have access. func (h *APIAccountListHandler) getAccountList(c echo.Context) ([]*models.Account, error) { principal, err := middleware.GetAuthorizedPrincipal(c) if err != nil { return nil, echo.ErrUnauthorized } accounts, err := h.store.ListForUser(context.Background(), principal) if err != nil { c.Logger().Errorf("Unable to load account list: %w", err) return nil, echo.ErrInternalServerError } return accounts, nil } // HandleV1 returns a list of JSON account objects func (h *APIAccountListHandler) HandleV1(c echo.Context) error { accounts, err := h.getAccountList(c) if err != nil { return err } out := []*jsonAccount{} for _, a := range accounts { ja := jsonAccountFromAccount(c, a) ja.Vendor = "aws" out = append(out, ja) } return c.JSON(http.StatusOK, out) } // HandleV2 returns a map of lists of account objects. the key to the map is // the short name of the cloud provider. func (h *APIAccountListHandler) HandleV2(c echo.Context) error { accounts, err := h.getAccountList(c) if err != nil { return err } out := map[string][]*jsonAccount{ "aws": []*jsonAccount{}, } for _, a := range accounts { ja := jsonAccountFromAccount(c, a) out["aws"] = append(out["aws"], ja) } return c.JSON(http.StatusOK, out) }