apigen: endpint to update project
Implemented new endpoint for project update using apigen. Implemented new service method compatible with new generated api. Change-Id: Ic0a7e0bbf3ea942275bd927d6e30cfb7e721e9c1
This commit is contained in:
parent
c944c3f289
commit
c32ca6e67f
@ -227,6 +227,24 @@ func (a *API) generateGo() ([]byte, error) {
|
||||
p("}")
|
||||
p("")
|
||||
}
|
||||
case http.MethodPatch:
|
||||
for _, param := range endpoint.Params {
|
||||
if param.Type == reflect.TypeOf(uuid.UUID{}) {
|
||||
p("%s, err := uuid.FromString(r.URL.Query().Get(\"%s\"))", param.Name, param.Name)
|
||||
p("if err != nil {")
|
||||
p("api.ServeError(h.log, w, http.StatusBadRequest, err)")
|
||||
p("return")
|
||||
p("}")
|
||||
p("")
|
||||
} else {
|
||||
p("%s := &%s{}", param.Name, param.Type)
|
||||
p("if err = json.NewDecoder(r.Body).Decode(&%s); err != nil {", param.Name)
|
||||
p("api.ServeError(h.log, w, http.StatusBadRequest, err)")
|
||||
p("return")
|
||||
p("}")
|
||||
p("")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
methodFormat := "retVal, httpErr := h.service.%s(ctx, "
|
||||
@ -239,6 +257,14 @@ func (a *API) generateGo() ([]byte, error) {
|
||||
for _, methodParam := range endpoint.Params {
|
||||
methodFormat += "*" + methodParam.Name + ", "
|
||||
}
|
||||
case http.MethodPatch:
|
||||
for _, methodParam := range endpoint.Params {
|
||||
if methodParam.Type == reflect.TypeOf(uuid.UUID{}) {
|
||||
methodFormat += methodParam.Name + ", "
|
||||
} else {
|
||||
methodFormat += "*" + methodParam.Name + ", "
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
methodFormat += ")"
|
||||
|
@ -48,6 +48,11 @@ func (eg *EndpointGroup) Get(path string, endpoint *Endpoint) {
|
||||
eg.addEndpoint(path, http.MethodGet, endpoint)
|
||||
}
|
||||
|
||||
// Patch adds new PATCH endpoint to endpoints group.
|
||||
func (eg *EndpointGroup) Patch(path string, endpoint *Endpoint) {
|
||||
eg.addEndpoint(path, http.MethodPatch, endpoint)
|
||||
}
|
||||
|
||||
// Put adds new PUT endpoint to endpoints group.
|
||||
func (eg *EndpointGroup) Put(path string, endpoint *Endpoint) {
|
||||
eg.addEndpoint(path, http.MethodPut, endpoint)
|
||||
|
@ -23,10 +23,11 @@ import (
|
||||
var ErrProjectsAPI = errs.Class("consoleapi projects api")
|
||||
|
||||
type ProjectManagementService interface {
|
||||
GenCreateProject(context.Context, console.ProjectInfo) (*console.Project, api.HTTPError)
|
||||
GenUpdateProject(context.Context, uuid.UUID, console.ProjectInfo) (*console.Project, api.HTTPError)
|
||||
GenGetUsersProjects(context.Context) ([]console.Project, api.HTTPError)
|
||||
GenGetSingleBucketUsageRollup(context.Context, uuid.UUID, string, time.Time, time.Time) (*accounting.BucketUsageRollup, api.HTTPError)
|
||||
GenGetBucketUsageRollups(context.Context, uuid.UUID, time.Time, time.Time) ([]accounting.BucketUsageRollup, api.HTTPError)
|
||||
GenCreateProject(context.Context, console.ProjectInfo) (*console.Project, api.HTTPError)
|
||||
}
|
||||
|
||||
// Handler is an api handler that exposes all projects related functionality.
|
||||
@ -44,14 +45,62 @@ func NewProjectManagement(log *zap.Logger, service ProjectManagementService, rou
|
||||
}
|
||||
|
||||
projectsRouter := router.PathPrefix("/api/v0/projects").Subrouter()
|
||||
projectsRouter.HandleFunc("/create", handler.handleGenCreateProject).Methods("PUT")
|
||||
projectsRouter.HandleFunc("/", handler.handleGenGetUsersProjects).Methods("GET")
|
||||
projectsRouter.HandleFunc("/bucket-rollup", handler.handleGenGetSingleBucketUsageRollup).Methods("GET")
|
||||
projectsRouter.HandleFunc("/bucket-rollups", handler.handleGenGetBucketUsageRollups).Methods("GET")
|
||||
projectsRouter.HandleFunc("/create", handler.handleGenCreateProject).Methods("PUT")
|
||||
projectsRouter.HandleFunc("/update", handler.handleGenUpdateProject).Methods("PATCH")
|
||||
|
||||
return handler
|
||||
}
|
||||
|
||||
func (h *Handler) handleGenGetBucketUsageRollups(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
var err error
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
ctx, err = h.auth.IsAuthenticated(ctx, r, true, true)
|
||||
if err != nil {
|
||||
api.ServeError(h.log, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
projectID, err := uuid.FromString(r.URL.Query().Get("projectID"))
|
||||
if err != nil {
|
||||
api.ServeError(h.log, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
sinceStamp, err := strconv.ParseInt(r.URL.Query().Get("since"), 10, 64)
|
||||
if err != nil {
|
||||
api.ServeError(h.log, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
since := time.Unix(sinceStamp, 0).UTC()
|
||||
|
||||
beforeStamp, err := strconv.ParseInt(r.URL.Query().Get("before"), 10, 64)
|
||||
if err != nil {
|
||||
api.ServeError(h.log, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
before := time.Unix(beforeStamp, 0).UTC()
|
||||
|
||||
retVal, httpErr := h.service.GenGetBucketUsageRollups(ctx, projectID, since, before)
|
||||
if httpErr.Err != nil {
|
||||
api.ServeError(h.log, w, httpErr.Status, httpErr.Err)
|
||||
return
|
||||
}
|
||||
|
||||
err = json.NewEncoder(w).Encode(retVal)
|
||||
if err != nil {
|
||||
h.log.Debug("failed to write json GenGetBucketUsageRollups response", zap.Error(ErrProjectsAPI.Wrap(err)))
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) handleGenCreateProject(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
var err error
|
||||
@ -83,6 +132,43 @@ func (h *Handler) handleGenCreateProject(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) handleGenUpdateProject(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
var err error
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
ctx, err = h.auth.IsAuthenticated(ctx, r, true, true)
|
||||
if err != nil {
|
||||
api.ServeError(h.log, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := uuid.FromString(r.URL.Query().Get("id"))
|
||||
if err != nil {
|
||||
api.ServeError(h.log, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
projectInfo := &console.ProjectInfo{}
|
||||
if err = json.NewDecoder(r.Body).Decode(&projectInfo); err != nil {
|
||||
api.ServeError(h.log, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
retVal, httpErr := h.service.GenUpdateProject(ctx, id, *projectInfo)
|
||||
if httpErr.Err != nil {
|
||||
api.ServeError(h.log, w, httpErr.Status, httpErr.Err)
|
||||
return
|
||||
}
|
||||
|
||||
err = json.NewEncoder(w).Encode(retVal)
|
||||
if err != nil {
|
||||
h.log.Debug("failed to write json GenUpdateProject response", zap.Error(ErrProjectsAPI.Wrap(err)))
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) handleGenGetUsersProjects(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
var err error
|
||||
@ -160,50 +246,3 @@ func (h *Handler) handleGenGetSingleBucketUsageRollup(w http.ResponseWriter, r *
|
||||
h.log.Debug("failed to write json GenGetSingleBucketUsageRollup response", zap.Error(ErrProjectsAPI.Wrap(err)))
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) handleGenGetBucketUsageRollups(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
var err error
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
ctx, err = h.auth.IsAuthenticated(ctx, r, true, true)
|
||||
if err != nil {
|
||||
api.ServeError(h.log, w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
projectID, err := uuid.FromString(r.URL.Query().Get("projectID"))
|
||||
if err != nil {
|
||||
api.ServeError(h.log, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
sinceStamp, err := strconv.ParseInt(r.URL.Query().Get("since"), 10, 64)
|
||||
if err != nil {
|
||||
api.ServeError(h.log, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
since := time.Unix(sinceStamp, 0).UTC()
|
||||
|
||||
beforeStamp, err := strconv.ParseInt(r.URL.Query().Get("before"), 10, 64)
|
||||
if err != nil {
|
||||
api.ServeError(h.log, w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
before := time.Unix(beforeStamp, 0).UTC()
|
||||
|
||||
retVal, httpErr := h.service.GenGetBucketUsageRollups(ctx, projectID, since, before)
|
||||
if httpErr.Err != nil {
|
||||
api.ServeError(h.log, w, httpErr.Status, httpErr.Err)
|
||||
return
|
||||
}
|
||||
|
||||
err = json.NewEncoder(w).Encode(retVal)
|
||||
if err != nil {
|
||||
h.log.Debug("failed to write json GenGetBucketUsageRollups response", zap.Error(ErrProjectsAPI.Wrap(err)))
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +65,17 @@ func main() {
|
||||
apigen.NewParam("projectInfo", console.ProjectInfo{}),
|
||||
},
|
||||
})
|
||||
|
||||
g.Patch("/update", &apigen.Endpoint{
|
||||
Name: "Update Project",
|
||||
Description: "Updates project with given info",
|
||||
MethodName: "GenUpdateProject",
|
||||
Response: &console.Project{},
|
||||
Params: []apigen.Param{
|
||||
apigen.NewParam("id", uuid.UUID{}),
|
||||
apigen.NewParam("projectInfo", console.ProjectInfo{}),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
a.MustWrite("satellite/console/consoleweb/consoleapi/api.gen.go")
|
||||
|
@ -1388,6 +1388,117 @@ func (s *Service) UpdateProject(ctx context.Context, projectID uuid.UUID, projec
|
||||
return project, nil
|
||||
}
|
||||
|
||||
// GenUpdateProject is a method for updating project name and description by id for generated api.
|
||||
func (s *Service) GenUpdateProject(ctx context.Context, projectID uuid.UUID, projectInfo ProjectInfo) (p *Project, httpError api.HTTPError) {
|
||||
var err error
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
auth, err := s.getAuthAndAuditLog(ctx, "update project name and description", zap.String("projectID", projectID.String()))
|
||||
if err != nil {
|
||||
return nil, api.HTTPError{
|
||||
Status: http.StatusUnauthorized,
|
||||
Err: Error.Wrap(err),
|
||||
}
|
||||
}
|
||||
|
||||
err = ValidateNameAndDescription(projectInfo.Name, projectInfo.Description)
|
||||
if err != nil {
|
||||
return nil, api.HTTPError{
|
||||
Status: http.StatusBadRequest,
|
||||
Err: Error.Wrap(err),
|
||||
}
|
||||
}
|
||||
|
||||
isMember, err := s.isProjectMember(ctx, auth.User.ID, projectID)
|
||||
if err != nil {
|
||||
return nil, api.HTTPError{
|
||||
Status: http.StatusUnauthorized,
|
||||
Err: Error.Wrap(err),
|
||||
}
|
||||
}
|
||||
project := isMember.project
|
||||
project.Name = projectInfo.Name
|
||||
project.Description = projectInfo.Description
|
||||
|
||||
if auth.User.PaidTier {
|
||||
if project.BandwidthLimit != nil && *project.BandwidthLimit == 0 {
|
||||
return nil, api.HTTPError{
|
||||
Status: http.StatusInternalServerError,
|
||||
Err: Error.New("current bandwidth limit for project is set to 0 (updating disabled)"),
|
||||
}
|
||||
}
|
||||
if project.StorageLimit != nil && *project.StorageLimit == 0 {
|
||||
return nil, api.HTTPError{
|
||||
Status: http.StatusInternalServerError,
|
||||
Err: Error.New("current storage limit for project is set to 0 (updating disabled)"),
|
||||
}
|
||||
}
|
||||
if projectInfo.StorageLimit <= 0 || projectInfo.BandwidthLimit <= 0 {
|
||||
return nil, api.HTTPError{
|
||||
Status: http.StatusBadRequest,
|
||||
Err: Error.New("project limits must be greater than 0"),
|
||||
}
|
||||
}
|
||||
|
||||
if projectInfo.StorageLimit > s.config.UsageLimits.Storage.Paid {
|
||||
return nil, api.HTTPError{
|
||||
Status: http.StatusBadRequest,
|
||||
Err: Error.New("specified storage limit exceeds allowed maximum for current tier"),
|
||||
}
|
||||
}
|
||||
|
||||
if projectInfo.BandwidthLimit > s.config.UsageLimits.Bandwidth.Paid {
|
||||
return nil, api.HTTPError{
|
||||
Status: http.StatusBadRequest,
|
||||
Err: Error.New("specified bandwidth limit exceeds allowed maximum for current tier"),
|
||||
}
|
||||
}
|
||||
|
||||
storageUsed, err := s.projectUsage.GetProjectStorageTotals(ctx, projectID)
|
||||
if err != nil {
|
||||
return nil, api.HTTPError{
|
||||
Status: http.StatusInternalServerError,
|
||||
Err: Error.Wrap(err),
|
||||
}
|
||||
}
|
||||
if projectInfo.StorageLimit.Int64() < storageUsed {
|
||||
return nil, api.HTTPError{
|
||||
Status: http.StatusBadRequest,
|
||||
Err: Error.New("cannot set storage limit below current usage"),
|
||||
}
|
||||
}
|
||||
|
||||
bandwidthUsed, err := s.projectUsage.GetProjectBandwidthTotals(ctx, projectID)
|
||||
if err != nil {
|
||||
return nil, api.HTTPError{
|
||||
Status: http.StatusInternalServerError,
|
||||
Err: Error.Wrap(err),
|
||||
}
|
||||
}
|
||||
if projectInfo.BandwidthLimit.Int64() < bandwidthUsed {
|
||||
return nil, api.HTTPError{
|
||||
Status: http.StatusBadRequest,
|
||||
Err: Error.New("cannot set bandwidth limit below current usage"),
|
||||
}
|
||||
}
|
||||
|
||||
project.StorageLimit = new(memory.Size)
|
||||
*project.StorageLimit = projectInfo.StorageLimit
|
||||
project.BandwidthLimit = new(memory.Size)
|
||||
*project.BandwidthLimit = projectInfo.BandwidthLimit
|
||||
}
|
||||
|
||||
err = s.store.Projects().Update(ctx, project)
|
||||
if err != nil {
|
||||
return nil, api.HTTPError{
|
||||
Status: http.StatusInternalServerError,
|
||||
Err: Error.Wrap(err),
|
||||
}
|
||||
}
|
||||
|
||||
return project, httpError
|
||||
}
|
||||
|
||||
// AddProjectMembers adds users by email to given project.
|
||||
func (s *Service) AddProjectMembers(ctx context.Context, projectID uuid.UUID, emails []string) (users []*User, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
Loading…
Reference in New Issue
Block a user