Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: KSP-SpaceDock/SpaceDock-Backend
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 2fae74566381
Choose a base ref
...
head repository: KSP-SpaceDock/SpaceDock-Backend
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: c951b64ba674
Choose a head ref
  • 2 commits
  • 5 files changed
  • 1 contributor

Commits on Mar 19, 2017

  1. Redo some stuff

    Dorian Stoll committed Mar 19, 2017
    Copy the full SHA
    2d0f866 View commit details
  2. Start with the mod routes

    Dorian Stoll committed Mar 19, 2017
    Copy the full SHA
    c951b64 View commit details
Showing with 304 additions and 16 deletions.
  1. +7 −4 src/SpaceDock/objects/mod.go
  2. +4 −4 src/SpaceDock/routes/featured.go
  3. +4 −4 src/SpaceDock/routes/modlists.go
  4. +285 −0 src/SpaceDock/routes/mods.go
  5. +4 −4 src/SpaceDock/routes/publisher.go
11 changes: 7 additions & 4 deletions src/SpaceDock/objects/mod.go
Original file line number Diff line number Diff line change
@@ -27,10 +27,13 @@ type Mod struct {
DefaultVersion *ModVersion `json:"-" spacedock:"lock"`
DefaultVersionID uint `json:"default_version"`
Versions []ModVersion `json:"-" spacedock:"lock"`
// Todo: Tracking API
Followers []User `json"-" gorm:"many2many:mod_followers" spacedock:"lock"`
Ratings []Rating `json:"-" spacedock:"lock"`
TotalScore float64 `json:"total_score" gorm:"not null" json:"total_score" spacedock:"lock"`
DownloadEvents []DownloadEvent `json:"-" spacedock:"lock"`
FollowEvents []FollowEvent `json:"-" spacedock:"lock"`
ReferralEvents []ReferralEvent `json:"-" spacedock:"lock"`
Followers []User `json"-" gorm:"many2many:mod_followers" spacedock:"lock"`
Ratings []Rating `json:"-" spacedock:"lock"`
TotalScore float64 `json:"total_score" gorm:"not null" spacedock:"lock"`
DownloadCount int64 `json:"download_count" spacedock:"lock"`
}

func (s *Mod) AfterFind() {
8 changes: 4 additions & 4 deletions src/SpaceDock/routes/featured.go
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@ func FeaturedRegister() {
middleware.NeedsPermission("mods-feature", true, "gameshort"),
add_featured,
)
Register(DELETE, "/api/featured/:gameshort",
Register(DELETE, "/api/featured",
middleware.NeedsPermission("mods-feature", true, "gameshort"),
remove_featured,
)
@@ -115,14 +115,14 @@ func add_featured(ctx *iris.Context) {
}

/*
Path: /api/featured/:gameshort
Path: /api/featured
Method: DELETE
Description: Unfeatures a mod for this game. Required fields: modid
Description: Unfeatures a mod for this game. Required fields: gameshort, modid
Abilities: mods-feature
*/
func remove_featured(ctx *iris.Context) {
// Get the mod
gameshort := ctx.GetString("gameshort")
gameshort := utils.GetJSON(ctx,"gameshort")
modid := cast.ToUint(utils.GetJSON(ctx, "modid"))

// Get the mod
8 changes: 4 additions & 4 deletions src/SpaceDock/routes/modlists.go
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ func ModlistsRegister() {
middleware.NeedsPermission("lists-edit", true, "gameshort", "listid"),
list_edit,
)
Register(DELETE, "/api/lists/:gameshort/:listid",
Register(DELETE, "/api/lists/:gameshort",
middleware.NeedsPermission("lists-remove", true, "gameshort", "listid"),
list_remove,
)
@@ -181,14 +181,14 @@ func list_edit(ctx *iris.Context) {
}

/*
Path: /api/lists/:gameshort/:listid
Path: /api/lists/:gameshort
Method: DELETE
Description: Removes a modlist
Description: Removes a modlist. Required parameters: listid
*/
func list_remove(ctx *iris.Context) {
// Get params
gameshort := ctx.GetString("gameshort")
listid := cast.ToUint(ctx.GetString("listid"))
listid := cast.ToUint(utils.GetJSON(ctx,"listid"))

// Get the modlist
modlist := &objects.ModList{}
285 changes: 285 additions & 0 deletions src/SpaceDock/routes/mods.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
/*
SpaceDock Backend
API Backend for the SpaceDock infrastructure to host modfiles for various games
SpaceDock Backend is licensed under the Terms of the MIT License.
Copyright (c) 2017 Dorian Stoll (StollD), RockyTV
*/

package routes

import (
"SpaceDock"
"SpaceDock/middleware"
"SpaceDock/objects"
"SpaceDock/utils"
"github.com/spf13/cast"
"gopkg.in/kataras/iris.v6"
"os"
"path/filepath"
"time"
)

/*
Registers the routes for the mod section
*/
func ModsRegister() {

}

/*
Path: /api/mods
Method: GET
Description: Returns a list of all mods
*/
func mod_list(ctx *iris.Context) {
var mods []objects.Mod
SpaceDock.Database.Find(&mods)
output := make([]map[string]interface{}, len(mods))
for i,element := range mods {
output[i] = utils.ToMap(element)
}
utils.WriteJSON(ctx, iris.StatusOK, iris.Map{"error": false, "count": len(output), "data": output})
}

/*
Path: /api/mods/:gameshort
Method: GET
Description: Returns a list with all mods for this game.
*/
func mod_game_list(ctx *iris.Context) {
gameshort := ctx.GetString("gameshort")
var mods []objects.Mod
SpaceDock.Database.Find(&mods)
output := []map[string]interface{}{}
for _,element := range mods {
if element.Game.Short == gameshort {
output = append(output, utils.ToMap(element))
}
}
utils.WriteJSON(ctx, iris.StatusOK, iris.Map{"error": false, "count": len(output), "data": output})
}

/*
Path: /api/mods/:gameshort/:modid
Method: GET
Description: Returns information for one mod
*/
func mods_info(ctx *iris.Context) {
// Get params
gameshort := ctx.GetString("gameshort")
modid := cast.ToUint(ctx.GetString("modid"))

// Get the mod
mod := &objects.Mod{}
SpaceDock.Database.Where("id = ?", modid).First(mod)
if mod.ID != modid {
utils.WriteJSON(ctx, iris.StatusNotFound, utils.Error("The modid is invalid").Code(2130))
return
}
if mod.Game.Short != gameshort {
utils.WriteJSON(ctx, iris.StatusBadRequest, utils.Error("The gameshort is invalid.").Code(2125))
return
}
if !mod.Published && !middleware.IsCurrentUser(ctx, &mod.User) {
utils.WriteJSON(ctx, iris.StatusForbidden, utils.Error("The mod is not published").Code(3020))
return
}
// Display info
utils.WriteJSON(ctx, iris.StatusOK, iris.Map{"error": false, "count": 1, "data": utils.ToMap(mod)})
}

/*
Path: /api/mods/:gameshort/:modid/download/:versionname
Method: GET
Description: Downloads the latest non-beta version of the mod
*/
func mods_download(ctx *iris.Context) {
// Get params
gameshort := ctx.GetString("gameshort")
modid := cast.ToUint(ctx.GetString("modid"))
versionname := ctx.GetString("versionname")

// Get the mod
mod := &objects.Mod{}
SpaceDock.Database.Where("id = ?", modid).First(mod)
if mod.ID != modid {
utils.WriteJSON(ctx, iris.StatusNotFound, utils.Error("The modid is invalid").Code(2130))
return
}
if mod.Game.Short != gameshort {
utils.WriteJSON(ctx, iris.StatusBadRequest, utils.Error("The gameshort is invalid.").Code(2125))
return
}
if !mod.Published && !middleware.IsCurrentUser(ctx, &mod.User) {
utils.WriteJSON(ctx, iris.StatusForbidden, utils.Error("The mod is not published").Code(3020))
return
}

// Get the version
version := &objects.ModVersion{}
SpaceDock.Database.Where("friendly_version = ?", versionname).Where("mod_id = ?", mod.ID).First(version)
if version.FriendlyVersion != versionname {
utils.WriteJSON(ctx, iris.StatusNotFound, utils.Error("The version is invalid.").Code(2155))
return
}

// Grab events
download := &objects.DownloadEvent{}
SpaceDock.Database.
Where("mod_id = ?", mod.ID).
Where("version_id = ?", version.ID).
Order("download_event.created_at desc").
First(download)

// Check whether the path exists
if _, err := os.Stat(filepath.Join(SpaceDock.Settings.Storage, version.DownloadPath)); os.IsNotExist(err) {
utils.WriteJSON(ctx, iris.StatusNotFound, utils.Error("The file you tried to access doesn't exist.").Code(2120))
return
}

if ctx.Header().Get("Range") == "" {
if download.ID == 0 || (time.Now().Sub(download.CreatedAt).Seconds() / 60 / 60) >= 1 {
download = objects.NewDownloadEvent(*mod, *version)
download.Downloads += 1
SpaceDock.Database.Save(download)
} else {
download.Downloads += 1
}
mod.DownloadCount += 1
}
SpaceDock.Database.Save(mod)

// Download
ctx.Redirect("/content/" + version.DownloadPath, iris.StatusTemporaryRedirect)
}

/*
Path: /api/mods/:gameshort/:modid
Method: PUT
Description: Edits a mod, based on the request parameters. Required fields: data
Abilities: mods-edit
*/
func mods_edit(ctx *iris.Context) {
// Get params
gameshort := ctx.GetString("gameshort")
modid := cast.ToUint(ctx.GetString("modid"))

// Get the mod
mod := &objects.Mod{}
SpaceDock.Database.Where("id = ?", modid).First(mod)
if mod.ID != modid {
utils.WriteJSON(ctx, iris.StatusNotFound, utils.Error("The modid is invalid").Code(2130))
return
}
if mod.Game.Short != gameshort {
utils.WriteJSON(ctx, iris.StatusBadRequest, utils.Error("The gameshort is invalid.").Code(2125))
return
}

// Edit the mod
code := utils.EditObject(mod, utils.GetFullJSON(ctx))
if code == 3 {
utils.WriteJSON(ctx, iris.StatusBadRequest, utils.Error("The value you submitted is invalid").Code(2180))
return
} else if code == 2 {
utils.WriteJSON(ctx, iris.StatusBadRequest, utils.Error("You tried to edit a value that doesn't exist.").Code(3090))
return
} else if code == 1 {
utils.WriteJSON(ctx, iris.StatusBadRequest, utils.Error("You tried to edit a value that is marked as read-only.").Code(3095))
return
}
SpaceDock.Database.Save(mod)

// Display info
utils.WriteJSON(ctx, iris.StatusOK, iris.Map{"error": false, "count": 1, "data": utils.ToMap(mod)})
}

/*
Path: /api/mods
Method: POST
Description: Adds a mod, based on the request parameters. Required fields: name, gameshort, license
Abilities: mods-add
*/
func mod_add(ctx *iris.Context) {
// Get params
name := cast.ToString(utils.GetJSON(ctx, "name"))
gameshort := cast.ToString(utils.GetJSON(ctx, "gameshort"))
license := cast.ToString(utils.GetJSON(ctx, "license"))

// Check the vars
errors := []string{}
codes := []int{}
if name == "" {
errors = append(errors, "Invalid mod name.")
codes = append(codes, 2117)
}
mod := &objects.Mod{}
SpaceDock.Database.Where("name = ?", name).First(mod)
if mod.Name == name {
errors = append(errors, "A mod with this name already exists.")
codes = append(codes, 2035)
}
game := &objects.Game{}
SpaceDock.Database.Where("short = ?", gameshort).First(game)
if game.Short != gameshort {
errors = append(errors, "Invalid gameshort.")
codes = append(codes, 2125)
}
if license == "" {
errors = append(errors, "Invalid License.")
codes = append(codes, 2190)
}
if len(errors) > 0 {
utils.WriteJSON(ctx, iris.StatusBadRequest, utils.Error(errors...).Code(codes...))
return
}

// Add new mod
mod = objects.NewMod(name, *middleware.CurrentUser(ctx), *game, license)
SpaceDock.Database.Save(mod)
role := mod.User.AddRole(name)
role.AddAbility("mods-edit")
role.AddAbility("mods-remove")
role.AddParam("mods-edit", "modid", cast.ToString(mod.ID))
role.AddParam("mods-remove", "name", name)
SpaceDock.Database.Save(role)

// Display info
utils.WriteJSON(ctx, iris.StatusOK, iris.Map{"error": false, "count": 1, "data": utils.ToMap(mod)})
}

/*
Path: /api/mods
Method: DELETE
Description: Removes a mod, based on the request parameters. Required fields: name, gameshort
Abilities: mods-remove
*/
func mods_remove(ctx *iris.Context) {
// Get params
gameshort := utils.GetJSON(ctx, "gameshort")
modid := cast.ToUint(utils.GetJSON(ctx,"modid"))

// Get the mod
mod := &objects.Mod{}
SpaceDock.Database.Where("id = ?", modid).First(mod)
if mod.ID != modid {
utils.WriteJSON(ctx, iris.StatusNotFound, utils.Error("The modid is invalid").Code(2130))
return
}
if mod.Game.Short != gameshort {
utils.WriteJSON(ctx, iris.StatusBadRequest, utils.Error("The gameshort is invalid.").Code(2125))
return
}

// Delete the mod
role := &objects.Role{}
SpaceDock.Database.Where("name = ?", mod.Name).First(role)
role.RemoveAbility("mods-edit")
role.RemoveAbility("mods-remove")
mod.User.RemoveRole(mod.Name)
SpaceDock.Database.Delete(mod).Delete(role)

// Display info
utils.WriteJSON(ctx, iris.StatusOK, iris.Map{"error": false})
}
8 changes: 4 additions & 4 deletions src/SpaceDock/routes/publisher.go
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@ func PublisherRegister() {
middleware.NeedsPermission("publisher-add", true),
add_publisher,
)
Register(DELETE, "/api/publishers/:pubid",
Register(DELETE, "/api/publishers",
middleware.NeedsPermission("publisher-remove", true),
remove_publisher,
)
@@ -129,13 +129,13 @@ func add_publisher(ctx *iris.Context) {
}

/*
Path: /api/publishers/:pubid
Path: /api/publishers
Method: DELETE
Description: Removes a game from existence. Required fields: pubid
Description: Removes a publisher from existence. Required fields: pubid
Abilities: publisher-remove
*/
func remove_publisher(ctx *iris.Context) {
pubid := cast.ToUint(ctx.GetString("pubid"))
pubid := cast.ToUint(utils.GetJSON(ctx, "pubid"))

// Get the publisher
pub := &objects.Publisher{}