...
 
Commits (4)
  • Andreas Mieke's avatar
    Adding GET endpoints for crashes, reports and symfiles · 0afd8895
    Andreas Mieke authored
    Filtering is possible with filter_field=fieldname and filter_value=value
    It is also possible to AND-combine multiple filters by setting the query-parameters
    multiple times.
    
    Ordering is possible with order_field=fieldname and order_direction=desc (the default
    ordering direction is asc so there is no parameter needed). If direction is something other
    than `desc` it will also be ordered ascending.
    
    Pagination is possible with limit=numer and offset=number. If nothing is specified limit
    will be 50 and offset 0.
    0afd8895
  • Andreas Mieke's avatar
    Adapted API · 0eb210da
    Andreas Mieke authored
    Filtering now works with <field>=<value> syntax. Ordering is possible with o_<field>,
    o_<field>= (which will order ASCending) or o_<field>=desc which will order in DESCending
    mode.
    0eb210da
  • Andreas Mieke's avatar
    Added all GET endpoints · 62e834ff
    Andreas Mieke authored
    62e834ff
  • Andreas Mieke's avatar
    Adding/Changing post/put/delete endpoints · a4d759bc
    Andreas Mieke authored
    a4d759bc
......@@ -14,10 +14,10 @@ import (
// Product defines the structure of a product
type Product struct {
ID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
ID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL" json:",omitempty"`
CreatedAt time.Time `json:",omitempty"`
UpdatedAt time.Time `json:",omitempty"`
DeletedAt *time.Time `json:",omitempty"`
Name string
Slug string
......@@ -28,20 +28,20 @@ var Products []Product
// Version defines the structure of a product
type Version struct {
ID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
ID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL" json:",omitempty"`
CreatedAt time.Time `json:",omitempty"`
UpdatedAt time.Time `json:",omitempty"`
DeletedAt *time.Time `json:",omitempty"`
Name string
Slug string
GitRepo string
Ignore bool
ProductID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL"`
Product Product
ProductID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL" json:",omitempty"`
Product Product `json:"-"`
Crashes []*Crash `gorm:"many2many:crash_versions;"`
Crashes []*Crash `gorm:"many2many:crash_versions;" json:"-"`
}
// Versions contains all currently available versions and is used for the switcher in the header
......@@ -49,69 +49,69 @@ var Versions []Version
// User defines the structure of a user
type User struct {
ID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
ID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL" json:",omitempty"`
CreatedAt time.Time `json:",omitempty"`
UpdatedAt time.Time `json:",omitempty"`
DeletedAt *time.Time `json:",omitempty"`
Name string
IsAdmin bool
Comments []Comment
Comments []Comment `json:"-"`
}
// Comment defines the structure of a comment
type Comment struct {
ID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
ID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL" json:",omitempty"`
CreatedAt time.Time `json:",omitempty"`
UpdatedAt time.Time `json:",omitempty"`
DeletedAt *time.Time `json:",omitempty"`
CrashID uuid.UUID `sql:"type:uuid DEFAULT NULL"`
ReportID uuid.UUID `sql:"type:uuid DEFAULT NULL"`
CrashID uuid.UUID `sql:"type:uuid DEFAULT NULL" json:",omitempty"`
ReportID uuid.UUID `sql:"type:uuid DEFAULT NULL" json:",omitempty"`
UserID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL"`
User User
UserID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL" json:",omitempty"`
User User `json:"-"`
Content template.HTML
}
// Crash database model
type Crash struct {
ID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
ID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL" json:",omitempty"`
CreatedAt time.Time `json:",omitempty"`
UpdatedAt time.Time `json:",omitempty"`
DeletedAt *time.Time `json:",omitempty"`
Signature string
Module string
AllCrashCount uint `gorm:"-"`
WinCrashCount uint `gorm:"-"`
MacCrashCount uint `gorm:"-"`
AllCrashCount uint `gorm:"-" json:",omitempty"`
WinCrashCount uint `gorm:"-" json:",omitempty"`
MacCrashCount uint `gorm:"-" json:",omitempty"`
Reports []Report
Comments []Comment
Reports []Report `json:",omitempty"`
Comments []Comment `json:",omitempty"`
FirstReported time.Time
LastReported time.Time
ProductID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL"`
Product Product
ProductID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL" json:",omitempty"`
Product Product `json:"-"`
Versions []*Version `gorm:"many2many:crash_versions;"`
Versions []*Version `gorm:"many2many:crash_versions;" json:",omitempty"`
Fixed *time.Time `sql:"DEFAULT NULL"`
}
// Report database model
type Report struct {
ID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
ID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL" json:",omitempty"`
CreatedAt time.Time `json:",omitempty"`
UpdatedAt time.Time `json:",omitempty"`
DeletedAt *time.Time `json:",omitempty"`
CrashID uuid.UUID `sql:"type:uuid DEFAULT NULL"`
Crash Crash
CrashID uuid.UUID `sql:"type:uuid DEFAULT NULL" json:",omitempty"`
Crash Crash `json:"-"`
ProcessUptime int
EMail string
......@@ -127,26 +127,26 @@ type Report struct {
CrashPath string
CrashLine int
Comments []Comment
Comments []Comment `json:"-"`
ReportContentJSON string `sql:"type:JSONB NOT NULL DEFAULT '{}'::JSONB" json:"-"`
Report ReportContent `gorm:"-"`
Report ReportContent `gorm:"-" json:",omitempty"`
ProductID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL"`
Product Product
ProductID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL" json:",omitempty"`
Product Product `json:"-"`
VersionID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL"`
Version Version
VersionID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL" json:",omitempty"`
Version Version `json:"-"`
ProcessingTime float64
}
// Symfile database model
type Symfile struct {
ID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
ID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL" json:",omitempty"`
CreatedAt time.Time `json:",omitempty"`
UpdatedAt time.Time `json:",omitempty"`
DeletedAt *time.Time `json:",omitempty"`
Os string
......@@ -154,11 +154,11 @@ type Symfile struct {
Code string `gorm:"unique;index"`
Name string
ProductID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL"`
Product Product
ProductID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL" json:",omitempty"`
Product Product `json:"-"`
VersionID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL"`
Version Version
VersionID uuid.UUID `sql:"type:uuid NOT NULL DEFAULT NULL" json:",omitempty"`
Version Version `json:"-"`
}
// ReportContent of a crashreport
......
......@@ -2,109 +2,508 @@ package main
import (
"net/http"
"strconv"
"code.videolan.org/videolan/CrashDragon/database"
"github.com/gin-gonic/gin"
"github.com/jinzhu/copier"
"github.com/jinzhu/gorm"
uuid "github.com/satori/go.uuid"
)
// ---------------------------- Product endpoints ------------------------------
func filters(qry *gorm.DB, c *gin.Context) *gorm.DB {
query := qry
if value, exists := c.GetQuery("id"); exists {
query = query.Where("id = ?", value)
}
if value, exists := c.GetQuery("created_at"); exists {
query = query.Where("created_at = ?", value)
}
if value, exists := c.GetQuery("updated_at"); exists {
query = query.Where("updated_at = ?", value)
}
if value, exists := c.GetQuery("deleted_at"); exists {
query = query.Where("deleted_at = ?", value)
}
if value, exists := c.GetQuery("signature"); exists {
query = query.Where("signature = ?", value)
}
if value, exists := c.GetQuery("module"); exists {
query = query.Where("module = ?", value)
}
if value, exists := c.GetQuery("first_reported"); exists {
query = query.Where("first_reported = ?", value)
}
if value, exists := c.GetQuery("last_reported"); exists {
query = query.Where("last_reported = ?", value)
}
if value, exists := c.GetQuery("product_id"); exists {
query = query.Where("product_id = ?", value)
}
if value, exists := c.GetQuery("fixed"); exists {
query = query.Where("fixed = ?", value)
}
if value, exists := c.GetQuery("crash_id"); exists {
query = query.Where("crash_id = ?", value)
}
if value, exists := c.GetQuery("process_uptime"); exists {
query = query.Where("process_uptime = ?", value)
}
if value, exists := c.GetQuery("e_mail"); exists {
query = query.Where("e_mail = ?", value)
}
if value, exists := c.GetQuery("comment"); exists {
query = query.Where("comment = ?", value)
}
if value, exists := c.GetQuery("processed"); exists {
query = query.Where("processed = ?", value)
}
if value, exists := c.GetQuery("os"); exists {
query = query.Where("os = ?", value)
}
if value, exists := c.GetQuery("os_version"); exists {
query = query.Where("os_version = ?", value)
}
if value, exists := c.GetQuery("arch"); exists {
query = query.Where("arch = ?", value)
}
if value, exists := c.GetQuery("crash_location"); exists {
query = query.Where("crash_location = ?", value)
}
if value, exists := c.GetQuery("crash_path"); exists {
query = query.Where("crash_path = ?", value)
}
if value, exists := c.GetQuery("crash_line"); exists {
query = query.Where("crash_line = ?", value)
}
if value, exists := c.GetQuery("version_id"); exists {
query = query.Where("version_id = ?", value)
}
if value, exists := c.GetQuery("processing_time"); exists {
query = query.Where("processing_time = ?", value)
}
if value, exists := c.GetQuery("code"); exists {
query = query.Where("code = ?", value)
}
if value, exists := c.GetQuery("name"); exists {
query = query.Where("name = ?", value)
}
if value, exists := c.GetQuery("slug"); exists {
query = query.Where("slug = ?", value)
}
if value, exists := c.GetQuery("git_repo"); exists {
query = query.Where("git_repo = ?", value)
}
if value, exists := c.GetQuery("ignore"); exists {
query = query.Where("ignore = ?", value)
}
if value, exists := c.GetQuery("is_admin"); exists {
query = query.Where("is_admin = ?", value)
}
if value, exists := c.GetQuery("user_id"); exists {
query = query.Where("user_id = ?", value)
}
if value, exists := c.GetQuery("content"); exists {
query = query.Where("content = ?", value)
}
return query
}
// DSC stands for descending order direction
const DSC = "desc"
func order(qry *gorm.DB, c *gin.Context) *gorm.DB {
query := qry
if value, exists := c.GetQuery("o_id"); exists {
if value == DSC {
query = query.Order("id DESC")
} else {
query = query.Order("id ASC")
}
}
if value, exists := c.GetQuery("o_created_at"); exists {
if value == DSC {
query = query.Order("created_at DESC")
} else {
query = query.Order("created_at ASC")
}
}
if value, exists := c.GetQuery("o_updated_at"); exists {
if value == DSC {
query = query.Order("updated_at DESC")
} else {
query = query.Order("updated_at ASC")
}
}
if value, exists := c.GetQuery("o_deleted_at"); exists {
if value == DSC {
query = query.Order("deleted_at DESC")
} else {
query = query.Order("deleted_at ASC")
}
}
if value, exists := c.GetQuery("o_signature"); exists {
if value == DSC {
query = query.Order("signature DESC")
} else {
query = query.Order("signature ASC")
}
}
if value, exists := c.GetQuery("o_module"); exists {
if value == DSC {
query = query.Order("module DESC")
} else {
query = query.Order("module ASC")
}
}
if value, exists := c.GetQuery("o_first_reported"); exists {
if value == DSC {
query = query.Order("first_reported DESC")
} else {
query = query.Order("first_reported ASC")
}
}
if value, exists := c.GetQuery("o_last_reported"); exists {
if value == DSC {
query = query.Order("last_reported DESC")
} else {
query = query.Order("last_reported ASC")
}
}
if value, exists := c.GetQuery("o_product_id"); exists {
if value == DSC {
query = query.Order("product_id DESC")
} else {
query = query.Order("product_id ASC")
}
}
if value, exists := c.GetQuery("o_fixed"); exists {
if value == DSC {
query = query.Order("fixed DESC")
} else {
query = query.Order("fixed ASC")
}
}
if value, exists := c.GetQuery("o_crash_id"); exists {
if value == DSC {
query = query.Order("crash_id DESC")
} else {
query = query.Order("crash_id ASC")
}
}
if value, exists := c.GetQuery("o_process_uptime"); exists {
if value == DSC {
query = query.Order("process_uptime DESC")
} else {
query = query.Order("process_uptime ASC")
}
}
if value, exists := c.GetQuery("o_e_mail"); exists {
if value == DSC {
query = query.Order("e_mail DESC")
} else {
query = query.Order("e_mail ASC")
}
}
if value, exists := c.GetQuery("o_comment"); exists {
if value == DSC {
query = query.Order("comment DESC")
} else {
query = query.Order("comment ASC")
}
}
if value, exists := c.GetQuery("o_processed"); exists {
if value == DSC {
query = query.Order("processed DESC")
} else {
query = query.Order("processed ASC")
}
}
if value, exists := c.GetQuery("o_os"); exists {
if value == DSC {
query = query.Order("os DESC")
} else {
query = query.Order("os ASC")
}
}
if value, exists := c.GetQuery("o_os_version"); exists {
if value == DSC {
query = query.Order("os_version DESC")
} else {
query = query.Order("os_version ASC")
}
}
if value, exists := c.GetQuery("o_arch"); exists {
if value == DSC {
query = query.Order("arch DESC")
} else {
query = query.Order("arch ASC")
}
}
if value, exists := c.GetQuery("o_crash_location"); exists {
if value == DSC {
query = query.Order("crash_location DESC")
} else {
query = query.Order("crash_location ASC")
}
}
if value, exists := c.GetQuery("o_crash_path"); exists {
if value == DSC {
query = query.Order("crash_path DESC")
} else {
query = query.Order("crash_path ASC")
}
}
if value, exists := c.GetQuery("o_crash_line"); exists {
if value == DSC {
query = query.Order("crash_line DESC")
} else {
query = query.Order("crash_line ASC")
}
}
if value, exists := c.GetQuery("o_version_id"); exists {
if value == DSC {
query = query.Order("version_id DESC")
} else {
query = query.Order("version_id ASC")
}
}
if value, exists := c.GetQuery("o_processing_time"); exists {
if value == DSC {
query = query.Order("processing_time DESC")
} else {
query = query.Order("processing_time ASC")
}
}
if value, exists := c.GetQuery("o_code"); exists {
if value == DSC {
query = query.Order("code DESC")
} else {
query = query.Order("code ASC")
}
}
if value, exists := c.GetQuery("o_name"); exists {
if value == DSC {
query = query.Order("name DESC")
} else {
query = query.Order("name ASC")
}
}
if value, exists := c.GetQuery("o_slug"); exists {
if value == DSC {
query = query.Order("slug DESC")
} else {
query = query.Order("slug ASC")
}
}
if value, exists := c.GetQuery("o_git_repo"); exists {
if value == DSC {
query = query.Order("git_repo DESC")
} else {
query = query.Order("git_repo ASC")
}
}
if value, exists := c.GetQuery("o_ignore"); exists {
if value == DSC {
query = query.Order("ignore DESC")
} else {
query = query.Order("ignore ASC")
}
}
if value, exists := c.GetQuery("o_is_admin"); exists {
if value == DSC {
query = query.Order("is_admin DESC")
} else {
query = query.Order("is_admin ASC")
}
}
if value, exists := c.GetQuery("o_user_id"); exists {
if value == DSC {
query = query.Order("user_id DESC")
} else {
query = query.Order("user_id ASC")
}
}
if value, exists := c.GetQuery("o_content"); exists {
if value == DSC {
query = query.Order("content DESC")
} else {
query = query.Order("content ASC")
}
}
return query
}
func paginate(qry *gorm.DB, c *gin.Context) (*gorm.DB, uint, int, int) {
var total uint
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "50"))
offset, _ := strconv.Atoi(c.DefaultQuery("offset", "0"))
query := qry.Count(&total).Limit(limit).Offset(offset)
return query, total, limit, offset
}
// APIv1GetCrashes is the GET endpoint for crashes in API v1
func APIv1GetCrashes(c *gin.Context) {
var Crashes []database.Crash
query := database.Db.Model(&database.Crash{})
query = filters(query, c)
query = order(query, c)
query, total, limit, offset := paginate(query, c)
query.Find(&Crashes)
c.JSON(http.StatusOK, gin.H{"Items": &Crashes, "ItemCount": total, "Limit": limit, "Offset": offset})
}
// APIv1GetCrash is the GET endpoint for a single crash in API v1
func APIv1GetCrash(c *gin.Context) {
var Crash database.Crash
database.Db.First(&Crash, "id = ?", c.Param("id"))
c.JSON(http.StatusOK, Crash)
}
// APIv1GetReports is the GET endpoint for reports in API v1
func APIv1GetReports(c *gin.Context) {
var Reports []database.Report
query := database.Db.Model(&database.Report{})
query = filters(query, c)
query = order(query, c)
query, total, limit, offset := paginate(query, c)
query.Find(&Reports)
c.JSON(http.StatusOK, gin.H{"Items": Reports, "ItemCount": total, "Limit": limit, "Offset": offset})
}
// APIv1GetReport is the GET endpoint for a single report in API v1
func APIv1GetReport(c *gin.Context) {
var Report database.Report
database.Db.First(&Report, "id = ?", c.Param("id"))
c.JSON(http.StatusOK, Report)
}
// APIv1GetSymfiles is the GET endpoint for symfiles in API v1
func APIv1GetSymfiles(c *gin.Context) {
var Symfiles []database.Symfile
query := database.Db.Model(&database.Symfile{})
query = filters(query, c)
query = order(query, c)
query, total, limit, offset := paginate(query, c)
query.Find(&Symfiles)
c.JSON(http.StatusOK, gin.H{"Items": Symfiles, "ItemCount": total, "Limit": limit, "Offset": offset})
}
// APIv1GetSymfile is the GET endpoint for a single symfile in API v1
func APIv1GetSymfile(c *gin.Context) {
var Symfile database.Symfile
database.Db.First(&Symfile, "id = ?", c.Param("id"))
c.JSON(http.StatusOK, Symfile)
}
// APINewProduct processes the new product endpoint
func APINewProduct(c *gin.Context) {
// APIv1GetProducts is the GET endpoint for products in API v1
func APIv1GetProducts(c *gin.Context) {
var Products []database.Product
query := database.Db.Model(&database.Product{})
query = filters(query, c)
query = order(query, c)
query, total, limit, offset := paginate(query, c)
query.Find(&Products)
c.JSON(http.StatusOK, gin.H{"Items": Products, "ItemCount": total, "Limit": limit, "Offset": offset})
}
// APIv1GetProduct is the GET endpoint for product in API v1
func APIv1GetProduct(c *gin.Context) {
var Product database.Product
database.Db.First(&Product, "id = ?", c.Param("id"))
c.JSON(http.StatusOK, Product)
}
// APIv1NewProduct processes the new product endpoint
func APIv1NewProduct(c *gin.Context) {
var Product database.Product
if err := c.BindJSON(&Product); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
return
}
Product.ID = uuid.NewV4()
if err := database.Db.Create(&Product).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
} else {
c.JSON(http.StatusCreated, gin.H{"error": nil, "object": Product})
c.JSON(http.StatusCreated, gin.H{"Error": nil, "Item": Product})
}
}
// APIUpdateProduct processes the update product endpoint
func APIUpdateProduct(c *gin.Context) {
// APIv1UpdateProduct processes the update product endpoint
func APIv1UpdateProduct(c *gin.Context) {
var Product database.Product
var Product2 database.Product
if err := c.BindJSON(&Product2); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
return
}
if err := database.Db.Where("id = ?", uuid.FromStringOrNil(c.Param("id"))).Find(&Product).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
return
}
Product2.CreatedAt = Product.CreatedAt
Product2.ID = Product.ID
copier.Copy(&Product, &Product2)
if err := database.Db.Save(&Product).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
} else {
c.JSON(http.StatusAccepted, gin.H{"error": nil, "object": Product})
c.JSON(http.StatusAccepted, gin.H{"Error": nil, "Item": Product})
}
}
// APIGetProducts processes the get products endpoint
func APIGetProducts(c *gin.Context) {
var Products []database.Product
if err := database.Db.Find(&Products).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
// APIv1DeleteProduct processes the delete product endpoint
func APIv1DeleteProduct(c *gin.Context) {
if err := database.Db.Delete(database.Product{}, "id = ?", uuid.FromStringOrNil(c.Param("id"))).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
} else {
c.JSON(http.StatusOK, gin.H{"error": nil, "object": Products})
c.JSON(http.StatusOK, gin.H{"Error": nil, "Item": nil})
}
}
// APIGetProduct processes the get product endpoint
func APIGetProduct(c *gin.Context) {
var Product database.Product
if err := database.Db.Where("id = ?", uuid.FromStringOrNil(c.Param("id"))).Find(&Product).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
} else {
c.JSON(http.StatusOK, gin.H{"error": nil, "object": Product})
}
// APIv1GetVersions is the GET endpoint for versions in API v1
func APIv1GetVersions(c *gin.Context) {
var Versions []database.Version
query := database.Db.Model(&database.Version{})
query = filters(query, c)
query = order(query, c)
query, total, limit, offset := paginate(query, c)
query.Find(&Versions)
c.JSON(http.StatusOK, gin.H{"Items": Versions, "ItemCount": total, "Limit": limit, "Offset": offset})
}
// APIDeleteProduct processes the delete product endpoint
func APIDeleteProduct(c *gin.Context) {
if err := database.Db.Delete(database.Product{}, "id = ?", uuid.FromStringOrNil(c.Param("id"))).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
} else {
c.JSON(http.StatusOK, gin.H{"error": nil, "object": nil})
}
// APIv1GetVersion is the GET endpoint for version in API v1
func APIv1GetVersion(c *gin.Context) {
var Version database.Version
database.Db.First(&Version, "id = ?", c.Param("id"))
c.JSON(http.StatusOK, Version)
}
// ---------------------------- Version endpoints ------------------------------
// APINewVersion processes the new product form
func APINewVersion(c *gin.Context) {
// APIv1NewVersion processes the new product form
func APIv1NewVersion(c *gin.Context) {
var Version database.Version
if err := c.BindJSON(&Version); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
return
}
Version.ID = uuid.NewV4()
if err := database.Db.Create(&Version).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
} else {
c.JSON(http.StatusCreated, gin.H{"error": nil, "object": Version})
c.JSON(http.StatusCreated, gin.H{"Error": nil, "Item": Version})
}
}
// APIUpdateVersion processes the new product form
func APIUpdateVersion(c *gin.Context) {
// APIv1UpdateVersion processes the new product form
func APIv1UpdateVersion(c *gin.Context) {
var Version database.Version
var Version2 database.Version
if err := c.BindJSON(&Version2); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
return
}
if err := database.Db.Where("id = ?", uuid.FromStringOrNil(c.Param("id"))).Find(&Version).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
return
}
Version2.CreatedAt = Version.CreatedAt
......@@ -114,105 +513,145 @@ func APIUpdateVersion(c *gin.Context) {
}
copier.Copy(&Version, &Version2)
if err := database.Db.Save(&Version).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
} else {
c.JSON(http.StatusAccepted, gin.H{"error": nil, "object": Version})
c.JSON(http.StatusAccepted, gin.H{"Error": nil, "Item": Version})
}
}
// APIGetVersions processes the get versions endpoint
func APIGetVersions(c *gin.Context) {
var Versions []database.Version
if err := database.Db.Preload("Product").Find(&Versions).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
// APIv1DeleteVersion processes the delete version endpoint
func APIv1DeleteVersion(c *gin.Context) {
if err := database.Db.Delete(database.Version{}, "id = ?", uuid.FromStringOrNil(c.Param("id"))).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
} else {
c.JSON(http.StatusOK, gin.H{"error": nil, "object": Versions})
c.JSON(http.StatusOK, gin.H{"Error": nil, "Item": nil})
}
}
// APIGetVersion processes the get version endpoint
func APIGetVersion(c *gin.Context) {
var Version database.Version
if err := database.Db.Where("id = ?", uuid.FromStringOrNil(c.Param("id"))).Preload("Product").Find(&Version).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
} else {
c.JSON(http.StatusOK, gin.H{"error": nil, "object": Version})
}
// APIv1GetUsers is the GET endpoint for users in API v1
func APIv1GetUsers(c *gin.Context) {
var Users []database.User
query := database.Db.Model(&database.User{})
query = filters(query, c)
query = order(query, c)
query, total, limit, offset := paginate(query, c)
query.Find(&Users)
c.JSON(http.StatusOK, gin.H{"Items": Users, "ItemCount": total, "Limit": limit, "Offset": offset})
}
// APIDeleteVersion processes the delete version endpoint
func APIDeleteVersion(c *gin.Context) {
if err := database.Db.Delete(database.Version{}, "id = ?", uuid.FromStringOrNil(c.Param("id"))).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
} else {
c.JSON(http.StatusOK, gin.H{"error": nil, "object": nil})
}
// APIv1GetUser is the GET endpoint for user in API v1
func APIv1GetUser(c *gin.Context) {
var User database.User
database.Db.First(&User, "id = ?", c.Param("id"))
c.JSON(http.StatusOK, User)
}
// ------------------------------ User endpoints -------------------------------
// APINewUser processes the new user endpoint
func APINewUser(c *gin.Context) {
// APIv1NewUser processes the new user endpoint
func APIv1NewUser(c *gin.Context) {
var User database.User
if err := c.BindJSON(&User); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
return
}
User.ID = uuid.NewV4()
if err := database.Db.Create(&User).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
} else {
c.JSON(http.StatusCreated, gin.H{"error": nil, "object": User})
c.JSON(http.StatusCreated, gin.H{"Error": nil, "Item": User})
}
}
// APIUpdateUser processes the update user endpoint
func APIUpdateUser(c *gin.Context) {
// APIv1UpdateUser processes the update user endpoint
func APIv1UpdateUser(c *gin.Context) {
var User database.User
var User2 database.User
if err := c.BindJSON(&User2); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
return
}
if err := database.Db.Where("id = ?", uuid.FromStringOrNil(c.Param("id"))).Find(&User).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
return
}
User2.CreatedAt = User.CreatedAt
User2.ID = User.ID
copier.Copy(&User, &User2)
if err := database.Db.Save(&User).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
} else {
c.JSON(http.StatusAccepted, gin.H{"error": nil, "object": User})
c.JSON(http.StatusAccepted, gin.H{"Error": nil, "Item": User})
}
}
// APIGetUsers processes the get Users endpoint
func APIGetUsers(c *gin.Context) {
var Users []database.User
if err := database.Db.Find(&Users).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
// APIv1DeleteUser processes the delete user endpoint
func APIv1DeleteUser(c *gin.Context) {
if err := database.Db.Delete(database.User{}, "id = ?", uuid.FromStringOrNil(c.Param("id"))).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
} else {
c.JSON(http.StatusOK, gin.H{"error": nil, "object": Users})
c.JSON(http.StatusOK, gin.H{"Error": nil, "Item": nil})
}
}
// APIGetUser processes the get user endpoint
func APIGetUser(c *gin.Context) {
var User database.User
if err := database.Db.Where("id = ?", uuid.FromStringOrNil(c.Param("id"))).Find(&User).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
// APIv1GetComments is the GET endpoint for comments in API v1
func APIv1GetComments(c *gin.Context) {
var Comments []database.Comment
query := database.Db.Model(&database.Comment{})
query = filters(query, c)
query = order(query, c)
query, total, limit, offset := paginate(query, c)
query.Find(&Comments)
c.JSON(http.StatusOK, gin.H{"Items": Comments, "ItemCount": total, "Limit": limit, "Offset": offset})
}
// APIv1GetComment is the GET endpoint for comment in API v1
func APIv1GetComment(c *gin.Context) {
var Comment database.Comment
database.Db.First(&Comment, "id = ?", c.Param("id"))
c.JSON(http.StatusOK, Comment)
}
// APIv1NewComment processes the new comment endpoint
func APIv1NewComment(c *gin.Context) {
var Comment database.Comment
if err := c.BindJSON(&Comment); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
return
}
Comment.ID = uuid.NewV4()
if err := database.Db.Create(&Comment).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
} else {
c.JSON(http.StatusOK, gin.H{"error": nil, "object": User})
c.JSON(http.StatusCreated, gin.H{"Error": nil, "Item": Comment})
}
}
// APIDeleteUser processes the delete user endpoint
func APIDeleteUser(c *gin.Context) {
if err := database.Db.Delete(database.User{}, "id = ?", uuid.FromStringOrNil(c.Param("id"))).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "object": nil})
// APIv1UpdateComment processes the update comment endpoint
func APIv1UpdateComment(c *gin.Context) {
var Comment database.Comment
var Comment2 database.Comment
if err := c.BindJSON(&Comment2); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
return
}
if err := database.Db.Where("id = ?", uuid.FromStringOrNil(c.Param("id"))).Find(&Comment).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
return
}
Comment2.CreatedAt = Comment.CreatedAt
Comment2.ID = Comment.ID
copier.Copy(&Comment, &Comment2)
if err := database.Db.Save(&Comment).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
} else {
c.JSON(http.StatusAccepted, gin.H{"Error": nil, "Item": Comment})
}
}
// APIv1DeleteComment processes the delete comment endpoint
func APIv1DeleteComment(c *gin.Context) {
if err := database.Db.Delete(database.Comment{}, "id = ?", uuid.FromStringOrNil(c.Param("id"))).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"Error": err.Error(), "Item": nil})
} else {
c.JSON(http.StatusOK, gin.H{"error": nil, "object": nil})
c.JSON(http.StatusOK, gin.H{"Error": nil, "Item": nil})
}
}
......@@ -59,31 +59,36 @@ func initRouter() *gin.Engine {
// Admin JSON endpoints
apiv1 := auth.Group("/api/v1")
apiv1.GET("/products", APIGetProducts)
apiv1.GET("/products/:id", APIGetProduct)
apiv1.POST("/products", APINewProduct)
apiv1.PUT("/products/:id", APIUpdateProduct)
apiv1.DELETE("/products/:id", APIDeleteProduct)
apiv1.GET("/versions", APIGetVersions)
apiv1.GET("/versions/:id", APIGetVersion)
apiv1.POST("/versions", APINewVersion)
apiv1.PUT("/versions/:id", APIUpdateVersion)
apiv1.DELETE("/versions/:id", APIDeleteVersion)
apiv1.GET("/users", APIGetUsers)
apiv1.GET("/users/:id", APIGetUser)
apiv1.POST("/users", APINewUser)
apiv1.PUT("/users/:id", APIUpdateUser)
apiv1.DELETE("/users/:id", APIDeleteUser)
apiv1.GET("/stats", GetIndex)
apiv1.GET("/crashes", GetCrashes)
apiv1.GET("/crashes/:id", GetCrash)
apiv1.GET("/reports", GetReports)
apiv1.GET("/reports/:id", GetReport)
apiv1.GET("/symfiles", GetSymfiles)
apiv1.GET("/symfiles/:id", GetSymfile)
apiv1.GET("/crashes", APIv1GetCrashes)
apiv1.GET("/crashes/:id", APIv1GetCrash)
apiv1.GET("/reports", APIv1GetReports)
apiv1.GET("/reports/:id", APIv1GetReport)
apiv1.GET("/symfiles", APIv1GetSymfiles)
apiv1.GET("/symfiles/:id", APIv1GetSymfile)
apiv1.GET("/products", APIv1GetProducts)
apiv1.GET("/products/:id", APIv1GetProduct)
apiv1.POST("/products", APIv1NewProduct)
apiv1.PUT("/products/:id", APIv1UpdateProduct)
apiv1.DELETE("/products/:id", APIv1DeleteProduct)
apiv1.GET("/versions", APIv1GetVersions)
apiv1.GET("/versions/:id", APIv1GetVersion)
apiv1.POST("/versions", APIv1NewVersion)
apiv1.PUT("/versions/:id", APIv1UpdateVersion)
apiv1.DELETE("/versions/:id", APIv1DeleteVersion)
apiv1.GET("/users", APIv1GetUsers)
apiv1.GET("/users/:id", APIv1GetUser)
apiv1.POST("/users", APIv1NewUser)
apiv1.PUT("/users/:id", APIv1UpdateUser)
apiv1.DELETE("/users/:id", APIv1DeleteUser)
apiv1.GET("/comments", APIv1GetComments)
apiv1.GET("/comments/:id", APIv1GetComment)
apiv1.POST("/comments", APIv1NewComment)
apiv1.PUT("/comments/:id", APIv1UpdateComment)
apiv1.DELETE("/comments/:id", APIv1DeleteComment)
// simple-breakpad endpoints
router.GET("/", GetIndex)
......