You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
5.3 KiB
188 lines
5.3 KiB
package api
|
|
|
|
import (
|
|
"git.aiterp.net/stufflog3/stufflog3-api/internal/auth"
|
|
"git.aiterp.net/stufflog3/stufflog3-api/internal/database"
|
|
"git.aiterp.net/stufflog3/stufflog3-api/internal/models"
|
|
"git.aiterp.net/stufflog3/stufflog3-api/internal/slerrors"
|
|
"github.com/gin-gonic/gin"
|
|
"time"
|
|
)
|
|
|
|
func Projects(g *gin.RouterGroup, db database.Database) {
|
|
g.Use(scopeIDMiddleware(db))
|
|
|
|
g.GET("", handler("projects", func(c *gin.Context) (interface{}, error) {
|
|
return db.Projects(getScope(c).ID).List(c.Request.Context())
|
|
}))
|
|
|
|
g.GET("/:id", handler("project", func(c *gin.Context) (interface{}, error) {
|
|
id, err := reqInt(c, "id")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return db.Projects(getScope(c).ID).Find(c.Request.Context(), id)
|
|
}))
|
|
|
|
g.POST("", handler("project", func(c *gin.Context) (interface{}, error) {
|
|
project := &models.Project{}
|
|
err := c.BindJSON(project)
|
|
if err != nil {
|
|
return nil, slerrors.BadRequest("Invalid JSON input: " + err.Error())
|
|
}
|
|
|
|
if !project.Status.Valid() {
|
|
return nil, slerrors.BadRequest("Unknown/unsupported project status")
|
|
}
|
|
if project.Name == "" {
|
|
return nil, slerrors.BadRequest("Project name cannot be blank")
|
|
}
|
|
if len(project.Requirements) > 0 {
|
|
return nil, slerrors.BadRequest("You cannot submit requirements this way")
|
|
}
|
|
|
|
project.OwnerID = auth.UserID(c)
|
|
project.CreatedTime = time.Now()
|
|
|
|
return db.Projects(getScope(c).ID).Create(c.Request.Context(), *project)
|
|
}))
|
|
|
|
g.PUT("/:id", handler("project", func(c *gin.Context) (interface{}, error) {
|
|
id, err := reqInt(c, "id")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
update := &models.ProjectUpdate{}
|
|
err = c.BindJSON(update)
|
|
if err != nil {
|
|
return nil, slerrors.BadRequest("Invalid JSON input: " + err.Error())
|
|
}
|
|
|
|
project, err := db.Projects(getScope(c).ID).Find(c.Request.Context(), id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return db.Projects(getScope(c).ID).Update(c.Request.Context(), *project, *update)
|
|
}))
|
|
|
|
g.POST("/:id/requirements", handler("project", func(c *gin.Context) (interface{}, error) {
|
|
id, err := reqInt(c, "id")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
requirement := &models.ProjectRequirement{}
|
|
err = c.BindJSON(requirement)
|
|
if err != nil {
|
|
return nil, slerrors.BadRequest("Invalid JSON input: " + err.Error())
|
|
}
|
|
|
|
if requirement.Name == "" {
|
|
return nil, slerrors.BadRequest("Requirement name cannot be empty.")
|
|
}
|
|
if !requirement.Status.Valid() {
|
|
return nil, slerrors.BadRequest("Bad requirement status.")
|
|
}
|
|
for _, stat := range requirement.Stats {
|
|
if getScope(c).Stat(stat.ID) == nil {
|
|
return nil, slerrors.Forbidden("One or more stats are not part of scope.")
|
|
}
|
|
if stat.Required < 0 {
|
|
return nil, slerrors.BadRequest("-1 stats are not allowed when creating project requirements.")
|
|
}
|
|
}
|
|
|
|
project, err := db.Projects(getScope(c).ID).Find(c.Request.Context(), id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return db.Projects(getScope(c).ID).AddRequirement(c.Request.Context(), project.ProjectEntry, *requirement)
|
|
}))
|
|
|
|
g.PUT("/:id/requirements/:rid", handler("project", func(c *gin.Context) (interface{}, error) {
|
|
id, err := reqInt(c, "id")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
rid, err := reqInt(c, "rid")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
update := &models.ProjectRequirementUpdate{}
|
|
err = c.BindJSON(update)
|
|
if err != nil {
|
|
return nil, slerrors.BadRequest("Invalid JSON input: " + err.Error())
|
|
}
|
|
|
|
if update.Name != nil && *update.Name == "" {
|
|
return nil, slerrors.BadRequest("Requirement name cannot be empty.")
|
|
}
|
|
if update.Status != nil && !update.Status.Valid() {
|
|
return nil, slerrors.BadRequest("Bad requirement status.")
|
|
}
|
|
for _, stat := range update.Stats {
|
|
if getScope(c).Stat(stat.ID) == nil {
|
|
return nil, slerrors.Forbidden("One or more stats are not part of scope.")
|
|
}
|
|
}
|
|
|
|
project, err := db.Projects(getScope(c).ID).Find(c.Request.Context(), id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
requirement := project.Requirement(rid)
|
|
if requirement == nil {
|
|
return nil, slerrors.NotFound("Project requirement")
|
|
}
|
|
|
|
return db.Projects(getScope(c).ID).UpdateRequirement(c.Request.Context(), project.ProjectEntry, *requirement, *update)
|
|
}))
|
|
|
|
g.DELETE("/:id/requirements/:rid", handler("project", func(c *gin.Context) (interface{}, error) {
|
|
deleteItems := c.Query("deleteItems") == "true"
|
|
id, err := reqInt(c, "id")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
rid, err := reqInt(c, "rid")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
project, err := db.Projects(getScope(c).ID).Find(c.Request.Context(), id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
requirement := project.Requirement(rid)
|
|
if requirement == nil {
|
|
return nil, slerrors.NotFound("Project requirement")
|
|
}
|
|
|
|
return db.Projects(getScope(c).ID).DeleteRequirement(c.Request.Context(), project.ProjectEntry, *requirement, deleteItems)
|
|
}))
|
|
|
|
g.DELETE("/:id", handler("project", func(c *gin.Context) (interface{}, error) {
|
|
deleteItems := c.Query("deleteItems") == "true"
|
|
id, err := reqInt(c, "id")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
project, err := db.Projects(getScope(c).ID).Find(c.Request.Context(), id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = db.Projects(getScope(c).ID).Delete(c.Request.Context(), project.ProjectEntry, deleteItems)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return project, nil
|
|
}))
|
|
}
|