├── .gitignore ├── .gitmodules ├── .travis.yml ├── CONTRIBUTING.md ├── DATABASE_INSTRUCTIONS.md ├── Gopkg.lock ├── Gopkg.toml ├── License.md ├── README.md ├── app ├── contexts.go ├── controllers.go ├── hrefs.go ├── media_types.go ├── test │ ├── card_testing.go │ ├── category_testing.go │ ├── faction_testing.go │ ├── group_testing.go │ ├── index_testing.go │ └── rarity_testing.go └── user_types.go ├── card.go ├── category.go ├── config.toml ├── configuration └── config.go ├── dataLayer ├── dal │ ├── dalCard.go │ ├── dalCategory.go │ ├── dalFaction.go │ ├── dalGroup.go │ ├── dalRarity.go │ ├── dalVariation.go │ └── db.go ├── factory │ ├── FactoryCard.go │ ├── FactoryCategory.go │ ├── FactoryFaction.go │ ├── FactoryGroup.go │ ├── FactoryRarity.go │ └── FactoryVariation.go └── models │ ├── card.go │ ├── category.go │ ├── faction.go │ ├── group.go │ ├── rarity.go │ └── variation.go ├── design ├── api_definition.go ├── media_types_definition.go ├── resources_definition.go └── types_definition.go ├── faction.go ├── group.go ├── helpers ├── full_urls.go ├── header.go ├── pageHelper.go └── uuidEncoder.go ├── index.go ├── main.go ├── rarity.go ├── serverService ├── README.md ├── gwentapi.service ├── gwentapi.socket ├── serverCore.go ├── serverStart.go └── serverStart_linux.go └── swagger ├── swagger.json └── swagger.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | # Log files 2 | *.log 3 | 4 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 5 | *.o 6 | *.a 7 | *.so 8 | 9 | # Folders 10 | _obj 11 | _test 12 | 13 | # Architecture specific extensions/prefixes 14 | *.[568vq] 15 | [568vq].out 16 | 17 | *.cgo1.go 18 | *.cgo2.c 19 | _cgo_defun.c 20 | _cgo_gotypes.go 21 | _cgo_export.* 22 | 23 | _testmain.go 24 | 25 | *.exe 26 | *.test 27 | *.prof 28 | 29 | 30 | # Project related folder 31 | vendor/ 32 | .idea/ 33 | # Only for current directory 34 | /client/ 35 | /tool/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "manipulator"] 2 | path = manipulator 3 | url = https://github.com/GwentAPI/manipulator.git 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.8.x 4 | before_install: 5 | - go get -u github.com/golang/dep/cmd/dep 6 | install: 7 | - dep ensure 8 | script: 9 | - go build -ldflags="-s -X main.version=$TRAVIS_TAG" -o gwentapi-$TRAVIS_TAG.linux-amd64 github.com/GwentAPI/gwentapi 10 | - GOOS=windows GOARCH=amd64 go build -ldflags="-s -X main.version=$TRAVIS_TAG" -o gwentapi-$TRAVIS_TAG.windows-amd64.exe github.com/GwentAPI/gwentapi 11 | - go build -ldflags="-s" -o manipulator-$TRAVIS_TAG.linux-amd64 github.com/GwentAPI/gwentapi/manipulator 12 | - GOOS=windows GOARCH=amd64 go build -ldflags="-s" -o manipulator-$TRAVIS_TAG.windows-amd64.exe github.com/GwentAPI/gwentapi/manipulator 13 | before_deploy: 14 | - zip -j "gwentapi-$TRAVIS_TAG.linux-amd64.zip" ./config.toml ./serverService/gwentapi.service ./serverService/gwentapi.socket ./manipulator-$TRAVIS_TAG.linux-amd64 ./gwentapi-$TRAVIS_TAG.linux-amd64 15 | - zip -j "gwentapi-$TRAVIS_TAG.windows-amd64.zip" ./config.toml ./manipulator-$TRAVIS_TAG.windows-amd64.exe ./gwentapi-$TRAVIS_TAG.windows-amd64.exe 16 | deploy: 17 | provider: releases 18 | skip_cleanup: true 19 | prerelease: true 20 | name: GwentAPI $TRAVIS_TAG 21 | api_key: 22 | secure: k1y/HdVbx7NNztpFsAkwol552Qx8FVm5YZcGLk7zfPVH95YDofnisSXpl8Qo8uXZvSjARBCScqQKAH9lzgfWWYLOX/a1kbo7mh9TgbhRfWNeqQ2W9tTjaK9gtc6MPO+b1aguBd2X9JqHsHXPu15YZypls5Or5QbPNrTrSEcetdmbnEZ1eyn/ZxsjgXIeU8cF/IGQaNfsyR15qIuHUyI5LlB5ABeQHjVumLlMg66FYTTItFlxNldepeW6TQ2oniG2BgK/6GpaM5pVnBdkDatiKZjKUcE8kk6JPSeEM++oBM4H+CacV8W2R26HQQY2g1H3fJSN63pjoGrUhcDJyTpe2MHRIOqxTxzG1xNIt+goagYxnfGMejBITqA9tWsFhukDwpj9QJHugJxpLu31jVmFRTC9kJ6Q/pIJhZv4w8SgmVDTFjxuK7pUFKoJHr+afpg08nt0U39tE6DQ8992IpGGjLgeN4nGK1jUwufKgh+7nN9RJDz2gT9p4wkozznbYO35f6egf94LWetjwrqW70yc/vz7EfrY9eGi159Y0PkMlM9yDM80F1WHdg84+/8qW5tDnLneZ4EzDxsOLYK+wgAMzYHpeWXWZn6rd20f3lI6tJoLHJ9/HacYEW4U+e93/4pZYWvFbTA4axRSHcuwTA4zJhDoU4S1SZYfqQ+CR6m6rkc= 23 | file: 24 | - gwentapi-$TRAVIS_TAG.linux-amd64.zip 25 | - gwentapi-$TRAVIS_TAG.windows-amd64.zip 26 | on: 27 | repo: GwentAPI/gwentapi 28 | tags: true 29 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | ## Proposing API design change 4 | 5 | GwentAPI use the [goa](https://github.com/goadesign/goa) framework to generate most of code of the project. 6 | 7 | To modify the API you must first install goagen, modify the design file(s) and then run goa. Goa won't overwrite files in the ``main`` package if they already exists. 8 | 9 | If you drastically modify the resources or actions, it's your responsibility to properly implement them in the ``main`` package. 10 | 11 | ### Installing goagen 12 | 13 | Navigate to the ``goagen`` directory in vendor and install the go program: 14 | 15 | ``cd vendor/github.com/goadesign/goa/goagen`` 16 | 17 | ``go install`` 18 | 19 | ### Modifying the design file(s) 20 | 21 | They are located under the ``design`` directory. 22 | 23 | | File | Content | 24 | | ------------- |:-------------:| 25 | | api_definition.go | Main definition of the api | 26 | | media_types_definition.go | Define the different media returned by the API and the different views they have | 27 | | resources_definition.go | Endpoints, Return types, params, etc. | 28 | | types_definition.go | A bit like medias except more primitive-like. Medias can be composed of them. | 29 | 30 | Make sure to bump the api version in ``api_definition.go``. 31 | 32 | You can find more information about the goa design language [here](https://goa.design/reference/goa/design/apidsl/). 33 | 34 | 35 | ### Running goagen 36 | 37 | ``goagen bootstrap -d github.com/GwentAPI/gwentapi/design`` -------------------------------------------------------------------------------- /DATABASE_INSTRUCTIONS.md: -------------------------------------------------------------------------------- 1 | # GwentAPI 2 | How to install and seed the database 3 | 4 | 5 | ## Setup 6 | 7 | 1. From the project directory, initialize the submodules: 8 | * ``git submodule init`` 9 | * ``git submodule update`` 10 | 11 | ### Feed the database 12 | 13 | The ``manipulator`` submodule contains the software needed to feed the database. 14 | 15 | Assuming that you have a running mongoDB instance and you are located in the submodule folder: 16 | 17 | 1. Compile the program 18 | 2. Obtain a copy of the card data in json 19 | 3. Run manipulator by inputing the json file ``manipulator -db gwentapi -input data.json`` -------------------------------------------------------------------------------- /Gopkg.lock: -------------------------------------------------------------------------------- 1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 2 | 3 | 4 | [[projects]] 5 | branch = "master" 6 | name = "github.com/BurntSushi/toml" 7 | packages = ["."] 8 | revision = "a368813c5e648fee92e5f6c30e3944ff9d5e8895" 9 | 10 | [[projects]] 11 | branch = "master" 12 | name = "github.com/armon/go-metrics" 13 | packages = ["."] 14 | revision = "023a4bbe4bb9bfb23ee7e1afc8d0abad217641f3" 15 | 16 | [[projects]] 17 | name = "github.com/coreos/go-systemd" 18 | packages = ["activation"] 19 | revision = "48702e0da86bd25e76cfef347e2adeb434a0d0a6" 20 | version = "v14" 21 | 22 | [[projects]] 23 | branch = "master" 24 | name = "github.com/dimfeld/httppath" 25 | packages = ["."] 26 | revision = "ee938bf735983d53694d79138ad9820efff94c92" 27 | 28 | [[projects]] 29 | name = "github.com/dimfeld/httptreemux" 30 | packages = ["."] 31 | revision = "90654bdd3dfc3cac55538aa620f2f4d855bbdb83" 32 | version = "v4.0.1" 33 | 34 | [[projects]] 35 | name = "github.com/go-stack/stack" 36 | packages = ["."] 37 | revision = "817915b46b97fd7bb80e8ab6b69f01a53ac3eebf" 38 | version = "v1.6.0" 39 | 40 | [[projects]] 41 | branch = "v1" 42 | name = "github.com/goadesign/goa" 43 | packages = [".","client","design","design/apidsl","dslengine","goatest","logging/log15","middleware","middleware/gzip","uuid"] 44 | revision = "3899ac9f33296d9c3dd7f0a7a3939a18803390db" 45 | 46 | [[projects]] 47 | branch = "master" 48 | name = "github.com/hashicorp/go-immutable-radix" 49 | packages = ["."] 50 | revision = "8aac2701530899b64bdea735a1de8da899815220" 51 | 52 | [[projects]] 53 | branch = "master" 54 | name = "github.com/hashicorp/golang-lru" 55 | packages = ["simplelru"] 56 | revision = "0a025b7e63adc15a622f29b0b2c4c3848243bbf6" 57 | 58 | [[projects]] 59 | branch = "master" 60 | name = "github.com/inconshreveable/log15" 61 | packages = [".","term"] 62 | revision = "74a0988b5f804e8ce9ff74fca4f16980776dff29" 63 | 64 | [[projects]] 65 | name = "github.com/inconshreveable/mousetrap" 66 | packages = ["."] 67 | revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" 68 | version = "v1.0" 69 | 70 | [[projects]] 71 | branch = "master" 72 | name = "github.com/manveru/faker" 73 | packages = ["."] 74 | revision = "717f7cf83fb78669bfab612749c2e8ff63d5be11" 75 | 76 | [[projects]] 77 | name = "github.com/mattn/go-colorable" 78 | packages = ["."] 79 | revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072" 80 | version = "v0.0.9" 81 | 82 | [[projects]] 83 | name = "github.com/mattn/go-isatty" 84 | packages = ["."] 85 | revision = "fc9e8d8ef48496124e79ae0df75490096eccf6fe" 86 | version = "v0.0.2" 87 | 88 | [[projects]] 89 | branch = "master" 90 | name = "github.com/rainycape/unidecode" 91 | packages = ["."] 92 | revision = "cb7f23ec59bec0d61b19c56cd88cee3d0cc1870c" 93 | 94 | [[projects]] 95 | name = "github.com/satori/go.uuid" 96 | packages = ["."] 97 | revision = "879c5887cd475cd7864858769793b2ceb0d44feb" 98 | version = "v1.1.0" 99 | 100 | [[projects]] 101 | branch = "master" 102 | name = "github.com/spf13/cobra" 103 | packages = ["."] 104 | revision = "b26b538f693051ac6518e65672de3144ce3fbedc" 105 | 106 | [[projects]] 107 | name = "github.com/spf13/pflag" 108 | packages = ["."] 109 | revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66" 110 | version = "v1.0.0" 111 | 112 | [[projects]] 113 | branch = "master" 114 | name = "github.com/zach-klippenstein/goregen" 115 | packages = ["."] 116 | revision = "795b5e3961ea1912fde60af417ad85e86acc0d6a" 117 | 118 | [[projects]] 119 | branch = "master" 120 | name = "golang.org/x/net" 121 | packages = ["websocket"] 122 | revision = "1c05540f6879653db88113bc4a2b70aec4bd491f" 123 | 124 | [[projects]] 125 | branch = "master" 126 | name = "golang.org/x/sys" 127 | packages = ["unix"] 128 | revision = "e42485b6e20ae7d2304ec72e535b103ed350cc02" 129 | 130 | [[projects]] 131 | branch = "v2" 132 | name = "gopkg.in/mgo.v2" 133 | packages = [".","bson","internal/json","internal/sasl","internal/scram"] 134 | revision = "3f83fa5005286a7fe593b055f0d7771a7dce4655" 135 | 136 | [solve-meta] 137 | analyzer-name = "dep" 138 | analyzer-version = 1 139 | inputs-digest = "ceaac62c466728edf6f02afed4858d0948527b5dbc497657a772f2fee8b2b5ac" 140 | solver-name = "gps-cdcl" 141 | solver-version = 1 142 | -------------------------------------------------------------------------------- /Gopkg.toml: -------------------------------------------------------------------------------- 1 | 2 | ## Gopkg.toml example (these lines may be deleted) 3 | 4 | ## "metadata" defines metadata about the project that could be used by other independent 5 | ## systems. The metadata defined here will be ignored by dep. 6 | # [metadata] 7 | # key1 = "value that convey data to other systems" 8 | # system1-data = "value that is used by a system" 9 | # system2-data = "value that is used by another system" 10 | 11 | ## "required" lists a set of packages (not projects) that must be included in 12 | ## Gopkg.lock. This list is merged with the set of packages imported by the current 13 | ## project. Use it when your project needs a package it doesn't explicitly import - 14 | ## including "main" packages. 15 | # required = ["github.com/user/thing/cmd/thing"] 16 | 17 | ## "ignored" lists a set of packages (not projects) that are ignored when 18 | ## dep statically analyzes source code. Ignored packages can be in this project, 19 | ## or in a dependency. 20 | # ignored = ["github.com/user/project/badpkg"] 21 | 22 | ## Constraints are rules for how directly imported projects 23 | ## may be incorporated into the depgraph. They are respected by 24 | ## dep whether coming from the Gopkg.toml of the current project or a dependency. 25 | # [[constraint]] 26 | ## Required: the root import path of the project being constrained. 27 | # name = "github.com/user/project" 28 | # 29 | ## Recommended: the version constraint to enforce for the project. 30 | ## Only one of "branch", "version" or "revision" can be specified. 31 | # version = "1.0.0" 32 | # branch = "master" 33 | # revision = "abc123" 34 | # 35 | ## Optional: an alternate location (URL or import path) for the project's source. 36 | # source = "https://github.com/myfork/package.git" 37 | # 38 | ## "metadata" defines metadata about the dependency or override that could be used 39 | ## by other independent systems. The metadata defined here will be ignored by dep. 40 | # [metadata] 41 | # key1 = "value that convey data to other systems" 42 | # system1-data = "value that is used by a system" 43 | # system2-data = "value that is used by another system" 44 | 45 | ## Overrides have the same structure as [[constraint]], but supersede all 46 | ## [[constraint]] declarations from all projects. Only [[override]] from 47 | ## the current project's are applied. 48 | ## 49 | ## Overrides are a sledgehammer. Use them only as a last resort. 50 | # [[override]] 51 | ## Required: the root import path of the project being constrained. 52 | # name = "github.com/user/project" 53 | # 54 | ## Optional: specifying a version constraint override will cause all other 55 | ## constraints on this project to be ignored; only the overridden constraint 56 | ## need be satisfied. 57 | ## Again, only one of "branch", "version" or "revision" can be specified. 58 | # version = "1.0.0" 59 | # branch = "master" 60 | # revision = "abc123" 61 | # 62 | ## Optional: specifying an alternate source location as an override will 63 | ## enforce that the alternate location is used for that project, regardless of 64 | ## what source location any dependent projects specify. 65 | # source = "https://github.com/myfork/package.git" 66 | 67 | 68 | 69 | [[constraint]] 70 | branch = "master" 71 | name = "github.com/BurntSushi/toml" 72 | 73 | [[constraint]] 74 | branch = "v1" 75 | name = "github.com/goadesign/goa" 76 | 77 | [[constraint]] 78 | branch = "master" 79 | name = "github.com/inconshreveable/log15" 80 | 81 | [[constraint]] 82 | branch = "master" 83 | name = "github.com/spf13/cobra" 84 | 85 | [[constraint]] 86 | branch = "master" 87 | name = "golang.org/x/net" 88 | 89 | [[constraint]] 90 | branch = "master" 91 | name = "golang.org/x/sys" 92 | 93 | [[constraint]] 94 | branch = "v2" 95 | name = "gopkg.in/mgo.v2" 96 | 97 | [[constraint]] 98 | version = "v14" 99 | name = "github.com/coreos/go-systemd" -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Tristan Savaria. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of gwentapi nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GwentAPI 2 | The code for GwentAPI 3 | 4 | GwentAPI is a RESTful API dedicated to provide information regarding GWENT®: The Witcher Card Game. You may use its interface to consume information on cards, factions, etc. You can find the API documentation at [https://gwentapi.com/swagger/](https://gwentapi.com/swagger/). 5 | 6 | 7 | # How to use 8 | 9 | GwentAPI is release for both Linux and Windows. You can find the download [here](https://github.com/GwentAPI/gwentapi/releases). 10 | The data allowing you to seed the database is included in the releases. Read the file ``DATABASE_INSTRUCTIONS.md`` to know how to feed the database. 11 | 12 | Change the values found in ``config.toml`` to suit your environment. The configuration file must be kept in the same directory as the executable. 13 | 14 | 15 | # Install from source 16 | 17 | ## Requirement & dependencies 18 | 19 | * [Go 1.8](https://golang.org/dl/) 20 | * MongoDB 3.4 21 | * Git 22 | * [dep](https://github.com/golang/dep) 23 | 24 | ## Installation 25 | 26 | Assuming you installed and configure all the required softwares listed above and that you have a working Go setup: 27 | 28 | ### Install the go dependencies 29 | 30 | ``dep ensure`` 31 | 32 | ### Build the software 33 | 1. ``go get github.com/GwentAPI/gwentapi`` 34 | 3. GwentAPI uses the experimental [dep](https://github.com/golang/dep) tool to manage the Go dependencies, however they are included in the ``vendor`` directory to help build the software on CI platforms. 35 | 4. Change your monboDB credentials in the config file. By default it connects to localhost on no particular users (no SSL, access control not enabled) and uses the gwentapi database. 36 | 5. Compile: 37 | * ``go build`` 38 | 6. Optionally set the version of the binary (displayed with the -v flag) by changing the value of ``version`` in ``main.go`` before compiling or set it at compile time with the following command: 39 | * ``go build -ldflags="-X main.version=" `` 40 | 7. Optionally modify the ``baseURL`` in the ``config.toml`` file to change where resources are pointing to. 41 | 42 | **The program will run on localhost on port 8080 by default.** 43 | 44 | ## How to contribute? 45 | 46 | Read the ``CONTRIBUTING.md`` file. 47 | 48 | ## Where are the artworks? 49 | 50 | At the time of writing, the artworks is taken from http://gwentify.com (a copy is saved, they aren't hotlinked). 51 | The files aren't included in the repo because git doesn't like binary files and neither do I like including binary files in git. 52 | -------------------------------------------------------------------------------- /app/controllers.go: -------------------------------------------------------------------------------- 1 | // Code generated by goagen v1.2.0, DO NOT EDIT. 2 | // 3 | // API "gwentapi": Application Controllers 4 | // 5 | // Command: 6 | // $ goagen 7 | // --design=github.com/GwentAPI/gwentapi/design 8 | // --out=$(GOPATH)\src\github.com\GwentAPI\gwentapi 9 | // --version=v1.2.0 10 | 11 | package app 12 | 13 | import ( 14 | "context" 15 | "github.com/goadesign/goa" 16 | "net/http" 17 | ) 18 | 19 | // initService sets up the service encoders, decoders and mux. 20 | func initService(service *goa.Service) { 21 | // Setup encoders and decoders 22 | service.Encoder.Register(goa.NewJSONEncoder, "application/json") 23 | service.Decoder.Register(goa.NewJSONDecoder, "application/json") 24 | service.Decoder.Register(goa.NewGobDecoder, "application/gob", "application/x-gob") 25 | service.Decoder.Register(goa.NewXMLDecoder, "application/xml") 26 | 27 | // Setup default encoder and decoder 28 | service.Encoder.Register(goa.NewJSONEncoder, "*/*") 29 | service.Decoder.Register(goa.NewJSONDecoder, "*/*") 30 | } 31 | 32 | // CardController is the controller interface for the Card actions. 33 | type CardController interface { 34 | goa.Muxer 35 | CardFaction(*CardFactionCardContext) error 36 | CardLeader(*CardLeaderCardContext) error 37 | CardRarity(*CardRarityCardContext) error 38 | CardVariation(*CardVariationCardContext) error 39 | CardVariations(*CardVariationsCardContext) error 40 | List(*ListCardContext) error 41 | Show(*ShowCardContext) error 42 | } 43 | 44 | // MountCardController "mounts" a Card resource controller on the given service. 45 | func MountCardController(service *goa.Service, ctrl CardController) { 46 | initService(service) 47 | var h goa.Handler 48 | 49 | h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 50 | // Check if there was an error loading the request 51 | if err := goa.ContextError(ctx); err != nil { 52 | return err 53 | } 54 | // Build the context 55 | rctx, err := NewCardFactionCardContext(ctx, req, service) 56 | if err != nil { 57 | return err 58 | } 59 | return ctrl.CardFaction(rctx) 60 | } 61 | service.Mux.Handle("GET", "/v0/cards/factions/:factionID", ctrl.MuxHandler("cardFaction", h, nil)) 62 | service.LogInfo("mount", "ctrl", "Card", "action", "CardFaction", "route", "GET /v0/cards/factions/:factionID") 63 | 64 | h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 65 | // Check if there was an error loading the request 66 | if err := goa.ContextError(ctx); err != nil { 67 | return err 68 | } 69 | // Build the context 70 | rctx, err := NewCardLeaderCardContext(ctx, req, service) 71 | if err != nil { 72 | return err 73 | } 74 | return ctrl.CardLeader(rctx) 75 | } 76 | service.Mux.Handle("GET", "/v0/cards/leaders", ctrl.MuxHandler("cardLeader", h, nil)) 77 | service.LogInfo("mount", "ctrl", "Card", "action", "CardLeader", "route", "GET /v0/cards/leaders") 78 | 79 | h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 80 | // Check if there was an error loading the request 81 | if err := goa.ContextError(ctx); err != nil { 82 | return err 83 | } 84 | // Build the context 85 | rctx, err := NewCardRarityCardContext(ctx, req, service) 86 | if err != nil { 87 | return err 88 | } 89 | return ctrl.CardRarity(rctx) 90 | } 91 | service.Mux.Handle("GET", "/v0/cards/rarities/:rarityID", ctrl.MuxHandler("cardRarity", h, nil)) 92 | service.LogInfo("mount", "ctrl", "Card", "action", "CardRarity", "route", "GET /v0/cards/rarities/:rarityID") 93 | 94 | h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 95 | // Check if there was an error loading the request 96 | if err := goa.ContextError(ctx); err != nil { 97 | return err 98 | } 99 | // Build the context 100 | rctx, err := NewCardVariationCardContext(ctx, req, service) 101 | if err != nil { 102 | return err 103 | } 104 | return ctrl.CardVariation(rctx) 105 | } 106 | service.Mux.Handle("GET", "/v0/cards/:cardID/variations/:variationID", ctrl.MuxHandler("cardVariation", h, nil)) 107 | service.LogInfo("mount", "ctrl", "Card", "action", "CardVariation", "route", "GET /v0/cards/:cardID/variations/:variationID") 108 | 109 | h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 110 | // Check if there was an error loading the request 111 | if err := goa.ContextError(ctx); err != nil { 112 | return err 113 | } 114 | // Build the context 115 | rctx, err := NewCardVariationsCardContext(ctx, req, service) 116 | if err != nil { 117 | return err 118 | } 119 | return ctrl.CardVariations(rctx) 120 | } 121 | service.Mux.Handle("GET", "/v0/cards/:cardID/variations/", ctrl.MuxHandler("cardVariations", h, nil)) 122 | service.LogInfo("mount", "ctrl", "Card", "action", "CardVariations", "route", "GET /v0/cards/:cardID/variations/") 123 | 124 | h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 125 | // Check if there was an error loading the request 126 | if err := goa.ContextError(ctx); err != nil { 127 | return err 128 | } 129 | // Build the context 130 | rctx, err := NewListCardContext(ctx, req, service) 131 | if err != nil { 132 | return err 133 | } 134 | return ctrl.List(rctx) 135 | } 136 | service.Mux.Handle("GET", "/v0/cards", ctrl.MuxHandler("list", h, nil)) 137 | service.LogInfo("mount", "ctrl", "Card", "action", "List", "route", "GET /v0/cards") 138 | 139 | h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 140 | // Check if there was an error loading the request 141 | if err := goa.ContextError(ctx); err != nil { 142 | return err 143 | } 144 | // Build the context 145 | rctx, err := NewShowCardContext(ctx, req, service) 146 | if err != nil { 147 | return err 148 | } 149 | return ctrl.Show(rctx) 150 | } 151 | service.Mux.Handle("GET", "/v0/cards/:cardID", ctrl.MuxHandler("show", h, nil)) 152 | service.LogInfo("mount", "ctrl", "Card", "action", "Show", "route", "GET /v0/cards/:cardID") 153 | } 154 | 155 | // CategoryController is the controller interface for the Category actions. 156 | type CategoryController interface { 157 | goa.Muxer 158 | List(*ListCategoryContext) error 159 | Show(*ShowCategoryContext) error 160 | } 161 | 162 | // MountCategoryController "mounts" a Category resource controller on the given service. 163 | func MountCategoryController(service *goa.Service, ctrl CategoryController) { 164 | initService(service) 165 | var h goa.Handler 166 | 167 | h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 168 | // Check if there was an error loading the request 169 | if err := goa.ContextError(ctx); err != nil { 170 | return err 171 | } 172 | // Build the context 173 | rctx, err := NewListCategoryContext(ctx, req, service) 174 | if err != nil { 175 | return err 176 | } 177 | return ctrl.List(rctx) 178 | } 179 | service.Mux.Handle("GET", "/v0/categories", ctrl.MuxHandler("list", h, nil)) 180 | service.LogInfo("mount", "ctrl", "Category", "action", "List", "route", "GET /v0/categories") 181 | 182 | h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 183 | // Check if there was an error loading the request 184 | if err := goa.ContextError(ctx); err != nil { 185 | return err 186 | } 187 | // Build the context 188 | rctx, err := NewShowCategoryContext(ctx, req, service) 189 | if err != nil { 190 | return err 191 | } 192 | return ctrl.Show(rctx) 193 | } 194 | service.Mux.Handle("GET", "/v0/categories/:categoryID", ctrl.MuxHandler("show", h, nil)) 195 | service.LogInfo("mount", "ctrl", "Category", "action", "Show", "route", "GET /v0/categories/:categoryID") 196 | } 197 | 198 | // FactionController is the controller interface for the Faction actions. 199 | type FactionController interface { 200 | goa.Muxer 201 | List(*ListFactionContext) error 202 | Show(*ShowFactionContext) error 203 | } 204 | 205 | // MountFactionController "mounts" a Faction resource controller on the given service. 206 | func MountFactionController(service *goa.Service, ctrl FactionController) { 207 | initService(service) 208 | var h goa.Handler 209 | 210 | h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 211 | // Check if there was an error loading the request 212 | if err := goa.ContextError(ctx); err != nil { 213 | return err 214 | } 215 | // Build the context 216 | rctx, err := NewListFactionContext(ctx, req, service) 217 | if err != nil { 218 | return err 219 | } 220 | return ctrl.List(rctx) 221 | } 222 | service.Mux.Handle("GET", "/v0/factions", ctrl.MuxHandler("list", h, nil)) 223 | service.LogInfo("mount", "ctrl", "Faction", "action", "List", "route", "GET /v0/factions") 224 | 225 | h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 226 | // Check if there was an error loading the request 227 | if err := goa.ContextError(ctx); err != nil { 228 | return err 229 | } 230 | // Build the context 231 | rctx, err := NewShowFactionContext(ctx, req, service) 232 | if err != nil { 233 | return err 234 | } 235 | return ctrl.Show(rctx) 236 | } 237 | service.Mux.Handle("GET", "/v0/factions/:factionID", ctrl.MuxHandler("show", h, nil)) 238 | service.LogInfo("mount", "ctrl", "Faction", "action", "Show", "route", "GET /v0/factions/:factionID") 239 | } 240 | 241 | // GroupController is the controller interface for the Group actions. 242 | type GroupController interface { 243 | goa.Muxer 244 | List(*ListGroupContext) error 245 | Show(*ShowGroupContext) error 246 | } 247 | 248 | // MountGroupController "mounts" a Group resource controller on the given service. 249 | func MountGroupController(service *goa.Service, ctrl GroupController) { 250 | initService(service) 251 | var h goa.Handler 252 | 253 | h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 254 | // Check if there was an error loading the request 255 | if err := goa.ContextError(ctx); err != nil { 256 | return err 257 | } 258 | // Build the context 259 | rctx, err := NewListGroupContext(ctx, req, service) 260 | if err != nil { 261 | return err 262 | } 263 | return ctrl.List(rctx) 264 | } 265 | service.Mux.Handle("GET", "/v0/groups", ctrl.MuxHandler("list", h, nil)) 266 | service.LogInfo("mount", "ctrl", "Group", "action", "List", "route", "GET /v0/groups") 267 | 268 | h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 269 | // Check if there was an error loading the request 270 | if err := goa.ContextError(ctx); err != nil { 271 | return err 272 | } 273 | // Build the context 274 | rctx, err := NewShowGroupContext(ctx, req, service) 275 | if err != nil { 276 | return err 277 | } 278 | return ctrl.Show(rctx) 279 | } 280 | service.Mux.Handle("GET", "/v0/groups/:groupID", ctrl.MuxHandler("show", h, nil)) 281 | service.LogInfo("mount", "ctrl", "Group", "action", "Show", "route", "GET /v0/groups/:groupID") 282 | } 283 | 284 | // IndexController is the controller interface for the Index actions. 285 | type IndexController interface { 286 | goa.Muxer 287 | Show(*ShowIndexContext) error 288 | } 289 | 290 | // MountIndexController "mounts" a Index resource controller on the given service. 291 | func MountIndexController(service *goa.Service, ctrl IndexController) { 292 | initService(service) 293 | var h goa.Handler 294 | 295 | h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 296 | // Check if there was an error loading the request 297 | if err := goa.ContextError(ctx); err != nil { 298 | return err 299 | } 300 | // Build the context 301 | rctx, err := NewShowIndexContext(ctx, req, service) 302 | if err != nil { 303 | return err 304 | } 305 | return ctrl.Show(rctx) 306 | } 307 | service.Mux.Handle("GET", "/v0", ctrl.MuxHandler("show", h, nil)) 308 | service.LogInfo("mount", "ctrl", "Index", "action", "Show", "route", "GET /v0") 309 | } 310 | 311 | // RarityController is the controller interface for the Rarity actions. 312 | type RarityController interface { 313 | goa.Muxer 314 | List(*ListRarityContext) error 315 | Show(*ShowRarityContext) error 316 | } 317 | 318 | // MountRarityController "mounts" a Rarity resource controller on the given service. 319 | func MountRarityController(service *goa.Service, ctrl RarityController) { 320 | initService(service) 321 | var h goa.Handler 322 | 323 | h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 324 | // Check if there was an error loading the request 325 | if err := goa.ContextError(ctx); err != nil { 326 | return err 327 | } 328 | // Build the context 329 | rctx, err := NewListRarityContext(ctx, req, service) 330 | if err != nil { 331 | return err 332 | } 333 | return ctrl.List(rctx) 334 | } 335 | service.Mux.Handle("GET", "/v0/rarities", ctrl.MuxHandler("list", h, nil)) 336 | service.LogInfo("mount", "ctrl", "Rarity", "action", "List", "route", "GET /v0/rarities") 337 | 338 | h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 339 | // Check if there was an error loading the request 340 | if err := goa.ContextError(ctx); err != nil { 341 | return err 342 | } 343 | // Build the context 344 | rctx, err := NewShowRarityContext(ctx, req, service) 345 | if err != nil { 346 | return err 347 | } 348 | return ctrl.Show(rctx) 349 | } 350 | service.Mux.Handle("GET", "/v0/rarities/:rarityID", ctrl.MuxHandler("show", h, nil)) 351 | service.LogInfo("mount", "ctrl", "Rarity", "action", "Show", "route", "GET /v0/rarities/:rarityID") 352 | } 353 | -------------------------------------------------------------------------------- /app/hrefs.go: -------------------------------------------------------------------------------- 1 | // Code generated by goagen v1.2.0, DO NOT EDIT. 2 | // 3 | // API "gwentapi": Application Resource Href Factories 4 | // 5 | // Command: 6 | // $ goagen 7 | // --design=github.com/GwentAPI/gwentapi/design 8 | // --out=$(GOPATH)\src\github.com\GwentAPI\gwentapi 9 | // --version=v1.2.0 10 | 11 | package app 12 | 13 | import ( 14 | "fmt" 15 | "strings" 16 | ) 17 | 18 | // CardHref returns the resource href. 19 | func CardHref(cardID interface{}) string { 20 | paramcardID := strings.TrimLeftFunc(fmt.Sprintf("%v", cardID), func(r rune) bool { return r == '/' }) 21 | return fmt.Sprintf("/v0/cards/%v", paramcardID) 22 | } 23 | 24 | // CategoryHref returns the resource href. 25 | func CategoryHref(categoryID interface{}) string { 26 | paramcategoryID := strings.TrimLeftFunc(fmt.Sprintf("%v", categoryID), func(r rune) bool { return r == '/' }) 27 | return fmt.Sprintf("/v0/categories/%v", paramcategoryID) 28 | } 29 | 30 | // FactionHref returns the resource href. 31 | func FactionHref(factionID interface{}) string { 32 | paramfactionID := strings.TrimLeftFunc(fmt.Sprintf("%v", factionID), func(r rune) bool { return r == '/' }) 33 | return fmt.Sprintf("/v0/factions/%v", paramfactionID) 34 | } 35 | 36 | // GroupHref returns the resource href. 37 | func GroupHref(groupID interface{}) string { 38 | paramgroupID := strings.TrimLeftFunc(fmt.Sprintf("%v", groupID), func(r rune) bool { return r == '/' }) 39 | return fmt.Sprintf("/v0/groups/%v", paramgroupID) 40 | } 41 | 42 | // IndexHref returns the resource href. 43 | func IndexHref() string { 44 | return "/v0" 45 | } 46 | 47 | // RarityHref returns the resource href. 48 | func RarityHref(rarityID interface{}) string { 49 | paramrarityID := strings.TrimLeftFunc(fmt.Sprintf("%v", rarityID), func(r rune) bool { return r == '/' }) 50 | return fmt.Sprintf("/v0/rarities/%v", paramrarityID) 51 | } 52 | -------------------------------------------------------------------------------- /app/test/faction_testing.go: -------------------------------------------------------------------------------- 1 | // Code generated by goagen v1.2.0, DO NOT EDIT. 2 | // 3 | // API "gwentapi": faction TestHelpers 4 | // 5 | // Command: 6 | // $ goagen 7 | // --design=github.com/GwentAPI/gwentapi/design 8 | // --out=$(GOPATH)\src\github.com\GwentAPI\gwentapi 9 | // --version=v1.2.0 10 | 11 | package test 12 | 13 | import ( 14 | "bytes" 15 | "context" 16 | "fmt" 17 | "github.com/GwentAPI/gwentapi/app" 18 | "github.com/goadesign/goa" 19 | "github.com/goadesign/goa/goatest" 20 | "io" 21 | "log" 22 | "net/http" 23 | "net/http/httptest" 24 | "net/url" 25 | ) 26 | 27 | // ListFactionInternalServerError runs the method List of the given controller with the given parameters. 28 | // It returns the response writer so it's possible to inspect the response headers. 29 | // If ctx is nil then context.Background() is used. 30 | // If service is nil then a default service is created. 31 | func ListFactionInternalServerError(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.FactionController, ifModifiedSince *string) http.ResponseWriter { 32 | // Setup service 33 | var ( 34 | logBuf bytes.Buffer 35 | resp interface{} 36 | 37 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 38 | ) 39 | if service == nil { 40 | service = goatest.Service(&logBuf, respSetter) 41 | } else { 42 | logger := log.New(&logBuf, "", log.Ltime) 43 | service.WithLogger(goa.NewLogger(logger)) 44 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 45 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 46 | service.Encoder.Register(newEncoder, "*/*") 47 | } 48 | 49 | // Setup request context 50 | rw := httptest.NewRecorder() 51 | u := &url.URL{ 52 | Path: fmt.Sprintf("/v0/factions"), 53 | } 54 | req, err := http.NewRequest("GET", u.String(), nil) 55 | if err != nil { 56 | panic("invalid test " + err.Error()) // bug 57 | } 58 | if ifModifiedSince != nil { 59 | sliceVal := []string{*ifModifiedSince} 60 | req.Header["If-Modified-Since"] = sliceVal 61 | } 62 | prms := url.Values{} 63 | if ctx == nil { 64 | ctx = context.Background() 65 | } 66 | goaCtx := goa.NewContext(goa.WithAction(ctx, "FactionTest"), rw, req, prms) 67 | listCtx, _err := app.NewListFactionContext(goaCtx, req, service) 68 | if _err != nil { 69 | panic("invalid test data " + _err.Error()) // bug 70 | } 71 | 72 | // Perform action 73 | _err = ctrl.List(listCtx) 74 | 75 | // Validate response 76 | if _err != nil { 77 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 78 | } 79 | if rw.Code != 500 { 80 | t.Errorf("invalid response status code: got %+v, expected 500", rw.Code) 81 | } 82 | 83 | // Return results 84 | return rw 85 | } 86 | 87 | // ListFactionNotFound runs the method List of the given controller with the given parameters. 88 | // It returns the response writer so it's possible to inspect the response headers. 89 | // If ctx is nil then context.Background() is used. 90 | // If service is nil then a default service is created. 91 | func ListFactionNotFound(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.FactionController, ifModifiedSince *string) http.ResponseWriter { 92 | // Setup service 93 | var ( 94 | logBuf bytes.Buffer 95 | resp interface{} 96 | 97 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 98 | ) 99 | if service == nil { 100 | service = goatest.Service(&logBuf, respSetter) 101 | } else { 102 | logger := log.New(&logBuf, "", log.Ltime) 103 | service.WithLogger(goa.NewLogger(logger)) 104 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 105 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 106 | service.Encoder.Register(newEncoder, "*/*") 107 | } 108 | 109 | // Setup request context 110 | rw := httptest.NewRecorder() 111 | u := &url.URL{ 112 | Path: fmt.Sprintf("/v0/factions"), 113 | } 114 | req, err := http.NewRequest("GET", u.String(), nil) 115 | if err != nil { 116 | panic("invalid test " + err.Error()) // bug 117 | } 118 | if ifModifiedSince != nil { 119 | sliceVal := []string{*ifModifiedSince} 120 | req.Header["If-Modified-Since"] = sliceVal 121 | } 122 | prms := url.Values{} 123 | if ctx == nil { 124 | ctx = context.Background() 125 | } 126 | goaCtx := goa.NewContext(goa.WithAction(ctx, "FactionTest"), rw, req, prms) 127 | listCtx, _err := app.NewListFactionContext(goaCtx, req, service) 128 | if _err != nil { 129 | panic("invalid test data " + _err.Error()) // bug 130 | } 131 | 132 | // Perform action 133 | _err = ctrl.List(listCtx) 134 | 135 | // Validate response 136 | if _err != nil { 137 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 138 | } 139 | if rw.Code != 404 { 140 | t.Errorf("invalid response status code: got %+v, expected 404", rw.Code) 141 | } 142 | 143 | // Return results 144 | return rw 145 | } 146 | 147 | // ListFactionNotModified runs the method List of the given controller with the given parameters. 148 | // It returns the response writer so it's possible to inspect the response headers. 149 | // If ctx is nil then context.Background() is used. 150 | // If service is nil then a default service is created. 151 | func ListFactionNotModified(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.FactionController, ifModifiedSince *string) http.ResponseWriter { 152 | // Setup service 153 | var ( 154 | logBuf bytes.Buffer 155 | resp interface{} 156 | 157 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 158 | ) 159 | if service == nil { 160 | service = goatest.Service(&logBuf, respSetter) 161 | } else { 162 | logger := log.New(&logBuf, "", log.Ltime) 163 | service.WithLogger(goa.NewLogger(logger)) 164 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 165 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 166 | service.Encoder.Register(newEncoder, "*/*") 167 | } 168 | 169 | // Setup request context 170 | rw := httptest.NewRecorder() 171 | u := &url.URL{ 172 | Path: fmt.Sprintf("/v0/factions"), 173 | } 174 | req, err := http.NewRequest("GET", u.String(), nil) 175 | if err != nil { 176 | panic("invalid test " + err.Error()) // bug 177 | } 178 | if ifModifiedSince != nil { 179 | sliceVal := []string{*ifModifiedSince} 180 | req.Header["If-Modified-Since"] = sliceVal 181 | } 182 | prms := url.Values{} 183 | if ctx == nil { 184 | ctx = context.Background() 185 | } 186 | goaCtx := goa.NewContext(goa.WithAction(ctx, "FactionTest"), rw, req, prms) 187 | listCtx, _err := app.NewListFactionContext(goaCtx, req, service) 188 | if _err != nil { 189 | panic("invalid test data " + _err.Error()) // bug 190 | } 191 | 192 | // Perform action 193 | _err = ctrl.List(listCtx) 194 | 195 | // Validate response 196 | if _err != nil { 197 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 198 | } 199 | if rw.Code != 304 { 200 | t.Errorf("invalid response status code: got %+v, expected 304", rw.Code) 201 | } 202 | 203 | // Return results 204 | return rw 205 | } 206 | 207 | // ListFactionOK runs the method List of the given controller with the given parameters. 208 | // It returns the response writer so it's possible to inspect the response headers and the media type struct written to the response. 209 | // If ctx is nil then context.Background() is used. 210 | // If service is nil then a default service is created. 211 | func ListFactionOK(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.FactionController, ifModifiedSince *string) (http.ResponseWriter, app.GwentapiFactionCollection) { 212 | // Setup service 213 | var ( 214 | logBuf bytes.Buffer 215 | resp interface{} 216 | 217 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 218 | ) 219 | if service == nil { 220 | service = goatest.Service(&logBuf, respSetter) 221 | } else { 222 | logger := log.New(&logBuf, "", log.Ltime) 223 | service.WithLogger(goa.NewLogger(logger)) 224 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 225 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 226 | service.Encoder.Register(newEncoder, "*/*") 227 | } 228 | 229 | // Setup request context 230 | rw := httptest.NewRecorder() 231 | u := &url.URL{ 232 | Path: fmt.Sprintf("/v0/factions"), 233 | } 234 | req, err := http.NewRequest("GET", u.String(), nil) 235 | if err != nil { 236 | panic("invalid test " + err.Error()) // bug 237 | } 238 | if ifModifiedSince != nil { 239 | sliceVal := []string{*ifModifiedSince} 240 | req.Header["If-Modified-Since"] = sliceVal 241 | } 242 | prms := url.Values{} 243 | if ctx == nil { 244 | ctx = context.Background() 245 | } 246 | goaCtx := goa.NewContext(goa.WithAction(ctx, "FactionTest"), rw, req, prms) 247 | listCtx, _err := app.NewListFactionContext(goaCtx, req, service) 248 | if _err != nil { 249 | panic("invalid test data " + _err.Error()) // bug 250 | } 251 | 252 | // Perform action 253 | _err = ctrl.List(listCtx) 254 | 255 | // Validate response 256 | if _err != nil { 257 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 258 | } 259 | if rw.Code != 200 { 260 | t.Errorf("invalid response status code: got %+v, expected 200", rw.Code) 261 | } 262 | var mt app.GwentapiFactionCollection 263 | if resp != nil { 264 | var ok bool 265 | mt, ok = resp.(app.GwentapiFactionCollection) 266 | if !ok { 267 | t.Fatalf("invalid response media: got variable of type %T, value %+v, expected instance of app.GwentapiFactionCollection", resp, resp) 268 | } 269 | _err = mt.Validate() 270 | if _err != nil { 271 | t.Errorf("invalid response media type: %s", _err) 272 | } 273 | } 274 | 275 | // Return results 276 | return rw, mt 277 | } 278 | 279 | // ListFactionOKLink runs the method List of the given controller with the given parameters. 280 | // It returns the response writer so it's possible to inspect the response headers and the media type struct written to the response. 281 | // If ctx is nil then context.Background() is used. 282 | // If service is nil then a default service is created. 283 | func ListFactionOKLink(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.FactionController, ifModifiedSince *string) (http.ResponseWriter, app.GwentapiFactionLinkCollection) { 284 | // Setup service 285 | var ( 286 | logBuf bytes.Buffer 287 | resp interface{} 288 | 289 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 290 | ) 291 | if service == nil { 292 | service = goatest.Service(&logBuf, respSetter) 293 | } else { 294 | logger := log.New(&logBuf, "", log.Ltime) 295 | service.WithLogger(goa.NewLogger(logger)) 296 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 297 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 298 | service.Encoder.Register(newEncoder, "*/*") 299 | } 300 | 301 | // Setup request context 302 | rw := httptest.NewRecorder() 303 | u := &url.URL{ 304 | Path: fmt.Sprintf("/v0/factions"), 305 | } 306 | req, err := http.NewRequest("GET", u.String(), nil) 307 | if err != nil { 308 | panic("invalid test " + err.Error()) // bug 309 | } 310 | if ifModifiedSince != nil { 311 | sliceVal := []string{*ifModifiedSince} 312 | req.Header["If-Modified-Since"] = sliceVal 313 | } 314 | prms := url.Values{} 315 | if ctx == nil { 316 | ctx = context.Background() 317 | } 318 | goaCtx := goa.NewContext(goa.WithAction(ctx, "FactionTest"), rw, req, prms) 319 | listCtx, _err := app.NewListFactionContext(goaCtx, req, service) 320 | if _err != nil { 321 | panic("invalid test data " + _err.Error()) // bug 322 | } 323 | 324 | // Perform action 325 | _err = ctrl.List(listCtx) 326 | 327 | // Validate response 328 | if _err != nil { 329 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 330 | } 331 | if rw.Code != 200 { 332 | t.Errorf("invalid response status code: got %+v, expected 200", rw.Code) 333 | } 334 | var mt app.GwentapiFactionLinkCollection 335 | if resp != nil { 336 | var ok bool 337 | mt, ok = resp.(app.GwentapiFactionLinkCollection) 338 | if !ok { 339 | t.Fatalf("invalid response media: got variable of type %T, value %+v, expected instance of app.GwentapiFactionLinkCollection", resp, resp) 340 | } 341 | _err = mt.Validate() 342 | if _err != nil { 343 | t.Errorf("invalid response media type: %s", _err) 344 | } 345 | } 346 | 347 | // Return results 348 | return rw, mt 349 | } 350 | 351 | // ShowFactionInternalServerError runs the method Show of the given controller with the given parameters. 352 | // It returns the response writer so it's possible to inspect the response headers. 353 | // If ctx is nil then context.Background() is used. 354 | // If service is nil then a default service is created. 355 | func ShowFactionInternalServerError(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.FactionController, factionID string, ifModifiedSince *string) http.ResponseWriter { 356 | // Setup service 357 | var ( 358 | logBuf bytes.Buffer 359 | resp interface{} 360 | 361 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 362 | ) 363 | if service == nil { 364 | service = goatest.Service(&logBuf, respSetter) 365 | } else { 366 | logger := log.New(&logBuf, "", log.Ltime) 367 | service.WithLogger(goa.NewLogger(logger)) 368 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 369 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 370 | service.Encoder.Register(newEncoder, "*/*") 371 | } 372 | 373 | // Setup request context 374 | rw := httptest.NewRecorder() 375 | u := &url.URL{ 376 | Path: fmt.Sprintf("/v0/factions/%v", factionID), 377 | } 378 | req, err := http.NewRequest("GET", u.String(), nil) 379 | if err != nil { 380 | panic("invalid test " + err.Error()) // bug 381 | } 382 | if ifModifiedSince != nil { 383 | sliceVal := []string{*ifModifiedSince} 384 | req.Header["If-Modified-Since"] = sliceVal 385 | } 386 | prms := url.Values{} 387 | prms["factionID"] = []string{fmt.Sprintf("%v", factionID)} 388 | if ctx == nil { 389 | ctx = context.Background() 390 | } 391 | goaCtx := goa.NewContext(goa.WithAction(ctx, "FactionTest"), rw, req, prms) 392 | showCtx, _err := app.NewShowFactionContext(goaCtx, req, service) 393 | if _err != nil { 394 | panic("invalid test data " + _err.Error()) // bug 395 | } 396 | 397 | // Perform action 398 | _err = ctrl.Show(showCtx) 399 | 400 | // Validate response 401 | if _err != nil { 402 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 403 | } 404 | if rw.Code != 500 { 405 | t.Errorf("invalid response status code: got %+v, expected 500", rw.Code) 406 | } 407 | 408 | // Return results 409 | return rw 410 | } 411 | 412 | // ShowFactionNotFound runs the method Show of the given controller with the given parameters. 413 | // It returns the response writer so it's possible to inspect the response headers. 414 | // If ctx is nil then context.Background() is used. 415 | // If service is nil then a default service is created. 416 | func ShowFactionNotFound(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.FactionController, factionID string, ifModifiedSince *string) http.ResponseWriter { 417 | // Setup service 418 | var ( 419 | logBuf bytes.Buffer 420 | resp interface{} 421 | 422 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 423 | ) 424 | if service == nil { 425 | service = goatest.Service(&logBuf, respSetter) 426 | } else { 427 | logger := log.New(&logBuf, "", log.Ltime) 428 | service.WithLogger(goa.NewLogger(logger)) 429 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 430 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 431 | service.Encoder.Register(newEncoder, "*/*") 432 | } 433 | 434 | // Setup request context 435 | rw := httptest.NewRecorder() 436 | u := &url.URL{ 437 | Path: fmt.Sprintf("/v0/factions/%v", factionID), 438 | } 439 | req, err := http.NewRequest("GET", u.String(), nil) 440 | if err != nil { 441 | panic("invalid test " + err.Error()) // bug 442 | } 443 | if ifModifiedSince != nil { 444 | sliceVal := []string{*ifModifiedSince} 445 | req.Header["If-Modified-Since"] = sliceVal 446 | } 447 | prms := url.Values{} 448 | prms["factionID"] = []string{fmt.Sprintf("%v", factionID)} 449 | if ctx == nil { 450 | ctx = context.Background() 451 | } 452 | goaCtx := goa.NewContext(goa.WithAction(ctx, "FactionTest"), rw, req, prms) 453 | showCtx, _err := app.NewShowFactionContext(goaCtx, req, service) 454 | if _err != nil { 455 | panic("invalid test data " + _err.Error()) // bug 456 | } 457 | 458 | // Perform action 459 | _err = ctrl.Show(showCtx) 460 | 461 | // Validate response 462 | if _err != nil { 463 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 464 | } 465 | if rw.Code != 404 { 466 | t.Errorf("invalid response status code: got %+v, expected 404", rw.Code) 467 | } 468 | 469 | // Return results 470 | return rw 471 | } 472 | 473 | // ShowFactionNotModified runs the method Show of the given controller with the given parameters. 474 | // It returns the response writer so it's possible to inspect the response headers. 475 | // If ctx is nil then context.Background() is used. 476 | // If service is nil then a default service is created. 477 | func ShowFactionNotModified(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.FactionController, factionID string, ifModifiedSince *string) http.ResponseWriter { 478 | // Setup service 479 | var ( 480 | logBuf bytes.Buffer 481 | resp interface{} 482 | 483 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 484 | ) 485 | if service == nil { 486 | service = goatest.Service(&logBuf, respSetter) 487 | } else { 488 | logger := log.New(&logBuf, "", log.Ltime) 489 | service.WithLogger(goa.NewLogger(logger)) 490 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 491 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 492 | service.Encoder.Register(newEncoder, "*/*") 493 | } 494 | 495 | // Setup request context 496 | rw := httptest.NewRecorder() 497 | u := &url.URL{ 498 | Path: fmt.Sprintf("/v0/factions/%v", factionID), 499 | } 500 | req, err := http.NewRequest("GET", u.String(), nil) 501 | if err != nil { 502 | panic("invalid test " + err.Error()) // bug 503 | } 504 | if ifModifiedSince != nil { 505 | sliceVal := []string{*ifModifiedSince} 506 | req.Header["If-Modified-Since"] = sliceVal 507 | } 508 | prms := url.Values{} 509 | prms["factionID"] = []string{fmt.Sprintf("%v", factionID)} 510 | if ctx == nil { 511 | ctx = context.Background() 512 | } 513 | goaCtx := goa.NewContext(goa.WithAction(ctx, "FactionTest"), rw, req, prms) 514 | showCtx, _err := app.NewShowFactionContext(goaCtx, req, service) 515 | if _err != nil { 516 | panic("invalid test data " + _err.Error()) // bug 517 | } 518 | 519 | // Perform action 520 | _err = ctrl.Show(showCtx) 521 | 522 | // Validate response 523 | if _err != nil { 524 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 525 | } 526 | if rw.Code != 304 { 527 | t.Errorf("invalid response status code: got %+v, expected 304", rw.Code) 528 | } 529 | 530 | // Return results 531 | return rw 532 | } 533 | 534 | // ShowFactionOK runs the method Show of the given controller with the given parameters. 535 | // It returns the response writer so it's possible to inspect the response headers and the media type struct written to the response. 536 | // If ctx is nil then context.Background() is used. 537 | // If service is nil then a default service is created. 538 | func ShowFactionOK(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.FactionController, factionID string, ifModifiedSince *string) (http.ResponseWriter, *app.GwentapiFaction) { 539 | // Setup service 540 | var ( 541 | logBuf bytes.Buffer 542 | resp interface{} 543 | 544 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 545 | ) 546 | if service == nil { 547 | service = goatest.Service(&logBuf, respSetter) 548 | } else { 549 | logger := log.New(&logBuf, "", log.Ltime) 550 | service.WithLogger(goa.NewLogger(logger)) 551 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 552 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 553 | service.Encoder.Register(newEncoder, "*/*") 554 | } 555 | 556 | // Setup request context 557 | rw := httptest.NewRecorder() 558 | u := &url.URL{ 559 | Path: fmt.Sprintf("/v0/factions/%v", factionID), 560 | } 561 | req, err := http.NewRequest("GET", u.String(), nil) 562 | if err != nil { 563 | panic("invalid test " + err.Error()) // bug 564 | } 565 | if ifModifiedSince != nil { 566 | sliceVal := []string{*ifModifiedSince} 567 | req.Header["If-Modified-Since"] = sliceVal 568 | } 569 | prms := url.Values{} 570 | prms["factionID"] = []string{fmt.Sprintf("%v", factionID)} 571 | if ctx == nil { 572 | ctx = context.Background() 573 | } 574 | goaCtx := goa.NewContext(goa.WithAction(ctx, "FactionTest"), rw, req, prms) 575 | showCtx, _err := app.NewShowFactionContext(goaCtx, req, service) 576 | if _err != nil { 577 | panic("invalid test data " + _err.Error()) // bug 578 | } 579 | 580 | // Perform action 581 | _err = ctrl.Show(showCtx) 582 | 583 | // Validate response 584 | if _err != nil { 585 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 586 | } 587 | if rw.Code != 200 { 588 | t.Errorf("invalid response status code: got %+v, expected 200", rw.Code) 589 | } 590 | var mt *app.GwentapiFaction 591 | if resp != nil { 592 | var ok bool 593 | mt, ok = resp.(*app.GwentapiFaction) 594 | if !ok { 595 | t.Fatalf("invalid response media: got variable of type %T, value %+v, expected instance of app.GwentapiFaction", resp, resp) 596 | } 597 | _err = mt.Validate() 598 | if _err != nil { 599 | t.Errorf("invalid response media type: %s", _err) 600 | } 601 | } 602 | 603 | // Return results 604 | return rw, mt 605 | } 606 | 607 | // ShowFactionOKLink runs the method Show of the given controller with the given parameters. 608 | // It returns the response writer so it's possible to inspect the response headers and the media type struct written to the response. 609 | // If ctx is nil then context.Background() is used. 610 | // If service is nil then a default service is created. 611 | func ShowFactionOKLink(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.FactionController, factionID string, ifModifiedSince *string) (http.ResponseWriter, *app.GwentapiFactionLink) { 612 | // Setup service 613 | var ( 614 | logBuf bytes.Buffer 615 | resp interface{} 616 | 617 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 618 | ) 619 | if service == nil { 620 | service = goatest.Service(&logBuf, respSetter) 621 | } else { 622 | logger := log.New(&logBuf, "", log.Ltime) 623 | service.WithLogger(goa.NewLogger(logger)) 624 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 625 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 626 | service.Encoder.Register(newEncoder, "*/*") 627 | } 628 | 629 | // Setup request context 630 | rw := httptest.NewRecorder() 631 | u := &url.URL{ 632 | Path: fmt.Sprintf("/v0/factions/%v", factionID), 633 | } 634 | req, err := http.NewRequest("GET", u.String(), nil) 635 | if err != nil { 636 | panic("invalid test " + err.Error()) // bug 637 | } 638 | if ifModifiedSince != nil { 639 | sliceVal := []string{*ifModifiedSince} 640 | req.Header["If-Modified-Since"] = sliceVal 641 | } 642 | prms := url.Values{} 643 | prms["factionID"] = []string{fmt.Sprintf("%v", factionID)} 644 | if ctx == nil { 645 | ctx = context.Background() 646 | } 647 | goaCtx := goa.NewContext(goa.WithAction(ctx, "FactionTest"), rw, req, prms) 648 | showCtx, _err := app.NewShowFactionContext(goaCtx, req, service) 649 | if _err != nil { 650 | panic("invalid test data " + _err.Error()) // bug 651 | } 652 | 653 | // Perform action 654 | _err = ctrl.Show(showCtx) 655 | 656 | // Validate response 657 | if _err != nil { 658 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 659 | } 660 | if rw.Code != 200 { 661 | t.Errorf("invalid response status code: got %+v, expected 200", rw.Code) 662 | } 663 | var mt *app.GwentapiFactionLink 664 | if resp != nil { 665 | var ok bool 666 | mt, ok = resp.(*app.GwentapiFactionLink) 667 | if !ok { 668 | t.Fatalf("invalid response media: got variable of type %T, value %+v, expected instance of app.GwentapiFactionLink", resp, resp) 669 | } 670 | _err = mt.Validate() 671 | if _err != nil { 672 | t.Errorf("invalid response media type: %s", _err) 673 | } 674 | } 675 | 676 | // Return results 677 | return rw, mt 678 | } 679 | -------------------------------------------------------------------------------- /app/test/group_testing.go: -------------------------------------------------------------------------------- 1 | // Code generated by goagen v1.2.0, DO NOT EDIT. 2 | // 3 | // API "gwentapi": group TestHelpers 4 | // 5 | // Command: 6 | // $ goagen 7 | // --design=github.com/GwentAPI/gwentapi/design 8 | // --out=$(GOPATH)\src\github.com\GwentAPI\gwentapi 9 | // --version=v1.2.0 10 | 11 | package test 12 | 13 | import ( 14 | "bytes" 15 | "context" 16 | "fmt" 17 | "github.com/GwentAPI/gwentapi/app" 18 | "github.com/goadesign/goa" 19 | "github.com/goadesign/goa/goatest" 20 | "io" 21 | "log" 22 | "net/http" 23 | "net/http/httptest" 24 | "net/url" 25 | ) 26 | 27 | // ListGroupInternalServerError runs the method List of the given controller with the given parameters. 28 | // It returns the response writer so it's possible to inspect the response headers. 29 | // If ctx is nil then context.Background() is used. 30 | // If service is nil then a default service is created. 31 | func ListGroupInternalServerError(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.GroupController, ifModifiedSince *string) http.ResponseWriter { 32 | // Setup service 33 | var ( 34 | logBuf bytes.Buffer 35 | resp interface{} 36 | 37 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 38 | ) 39 | if service == nil { 40 | service = goatest.Service(&logBuf, respSetter) 41 | } else { 42 | logger := log.New(&logBuf, "", log.Ltime) 43 | service.WithLogger(goa.NewLogger(logger)) 44 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 45 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 46 | service.Encoder.Register(newEncoder, "*/*") 47 | } 48 | 49 | // Setup request context 50 | rw := httptest.NewRecorder() 51 | u := &url.URL{ 52 | Path: fmt.Sprintf("/v0/groups"), 53 | } 54 | req, err := http.NewRequest("GET", u.String(), nil) 55 | if err != nil { 56 | panic("invalid test " + err.Error()) // bug 57 | } 58 | if ifModifiedSince != nil { 59 | sliceVal := []string{*ifModifiedSince} 60 | req.Header["If-Modified-Since"] = sliceVal 61 | } 62 | prms := url.Values{} 63 | if ctx == nil { 64 | ctx = context.Background() 65 | } 66 | goaCtx := goa.NewContext(goa.WithAction(ctx, "GroupTest"), rw, req, prms) 67 | listCtx, _err := app.NewListGroupContext(goaCtx, req, service) 68 | if _err != nil { 69 | panic("invalid test data " + _err.Error()) // bug 70 | } 71 | 72 | // Perform action 73 | _err = ctrl.List(listCtx) 74 | 75 | // Validate response 76 | if _err != nil { 77 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 78 | } 79 | if rw.Code != 500 { 80 | t.Errorf("invalid response status code: got %+v, expected 500", rw.Code) 81 | } 82 | 83 | // Return results 84 | return rw 85 | } 86 | 87 | // ListGroupNotFound runs the method List of the given controller with the given parameters. 88 | // It returns the response writer so it's possible to inspect the response headers. 89 | // If ctx is nil then context.Background() is used. 90 | // If service is nil then a default service is created. 91 | func ListGroupNotFound(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.GroupController, ifModifiedSince *string) http.ResponseWriter { 92 | // Setup service 93 | var ( 94 | logBuf bytes.Buffer 95 | resp interface{} 96 | 97 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 98 | ) 99 | if service == nil { 100 | service = goatest.Service(&logBuf, respSetter) 101 | } else { 102 | logger := log.New(&logBuf, "", log.Ltime) 103 | service.WithLogger(goa.NewLogger(logger)) 104 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 105 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 106 | service.Encoder.Register(newEncoder, "*/*") 107 | } 108 | 109 | // Setup request context 110 | rw := httptest.NewRecorder() 111 | u := &url.URL{ 112 | Path: fmt.Sprintf("/v0/groups"), 113 | } 114 | req, err := http.NewRequest("GET", u.String(), nil) 115 | if err != nil { 116 | panic("invalid test " + err.Error()) // bug 117 | } 118 | if ifModifiedSince != nil { 119 | sliceVal := []string{*ifModifiedSince} 120 | req.Header["If-Modified-Since"] = sliceVal 121 | } 122 | prms := url.Values{} 123 | if ctx == nil { 124 | ctx = context.Background() 125 | } 126 | goaCtx := goa.NewContext(goa.WithAction(ctx, "GroupTest"), rw, req, prms) 127 | listCtx, _err := app.NewListGroupContext(goaCtx, req, service) 128 | if _err != nil { 129 | panic("invalid test data " + _err.Error()) // bug 130 | } 131 | 132 | // Perform action 133 | _err = ctrl.List(listCtx) 134 | 135 | // Validate response 136 | if _err != nil { 137 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 138 | } 139 | if rw.Code != 404 { 140 | t.Errorf("invalid response status code: got %+v, expected 404", rw.Code) 141 | } 142 | 143 | // Return results 144 | return rw 145 | } 146 | 147 | // ListGroupNotModified runs the method List of the given controller with the given parameters. 148 | // It returns the response writer so it's possible to inspect the response headers. 149 | // If ctx is nil then context.Background() is used. 150 | // If service is nil then a default service is created. 151 | func ListGroupNotModified(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.GroupController, ifModifiedSince *string) http.ResponseWriter { 152 | // Setup service 153 | var ( 154 | logBuf bytes.Buffer 155 | resp interface{} 156 | 157 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 158 | ) 159 | if service == nil { 160 | service = goatest.Service(&logBuf, respSetter) 161 | } else { 162 | logger := log.New(&logBuf, "", log.Ltime) 163 | service.WithLogger(goa.NewLogger(logger)) 164 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 165 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 166 | service.Encoder.Register(newEncoder, "*/*") 167 | } 168 | 169 | // Setup request context 170 | rw := httptest.NewRecorder() 171 | u := &url.URL{ 172 | Path: fmt.Sprintf("/v0/groups"), 173 | } 174 | req, err := http.NewRequest("GET", u.String(), nil) 175 | if err != nil { 176 | panic("invalid test " + err.Error()) // bug 177 | } 178 | if ifModifiedSince != nil { 179 | sliceVal := []string{*ifModifiedSince} 180 | req.Header["If-Modified-Since"] = sliceVal 181 | } 182 | prms := url.Values{} 183 | if ctx == nil { 184 | ctx = context.Background() 185 | } 186 | goaCtx := goa.NewContext(goa.WithAction(ctx, "GroupTest"), rw, req, prms) 187 | listCtx, _err := app.NewListGroupContext(goaCtx, req, service) 188 | if _err != nil { 189 | panic("invalid test data " + _err.Error()) // bug 190 | } 191 | 192 | // Perform action 193 | _err = ctrl.List(listCtx) 194 | 195 | // Validate response 196 | if _err != nil { 197 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 198 | } 199 | if rw.Code != 304 { 200 | t.Errorf("invalid response status code: got %+v, expected 304", rw.Code) 201 | } 202 | 203 | // Return results 204 | return rw 205 | } 206 | 207 | // ListGroupOK runs the method List of the given controller with the given parameters. 208 | // It returns the response writer so it's possible to inspect the response headers and the media type struct written to the response. 209 | // If ctx is nil then context.Background() is used. 210 | // If service is nil then a default service is created. 211 | func ListGroupOK(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.GroupController, ifModifiedSince *string) (http.ResponseWriter, app.GwentapiGroupCollection) { 212 | // Setup service 213 | var ( 214 | logBuf bytes.Buffer 215 | resp interface{} 216 | 217 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 218 | ) 219 | if service == nil { 220 | service = goatest.Service(&logBuf, respSetter) 221 | } else { 222 | logger := log.New(&logBuf, "", log.Ltime) 223 | service.WithLogger(goa.NewLogger(logger)) 224 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 225 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 226 | service.Encoder.Register(newEncoder, "*/*") 227 | } 228 | 229 | // Setup request context 230 | rw := httptest.NewRecorder() 231 | u := &url.URL{ 232 | Path: fmt.Sprintf("/v0/groups"), 233 | } 234 | req, err := http.NewRequest("GET", u.String(), nil) 235 | if err != nil { 236 | panic("invalid test " + err.Error()) // bug 237 | } 238 | if ifModifiedSince != nil { 239 | sliceVal := []string{*ifModifiedSince} 240 | req.Header["If-Modified-Since"] = sliceVal 241 | } 242 | prms := url.Values{} 243 | if ctx == nil { 244 | ctx = context.Background() 245 | } 246 | goaCtx := goa.NewContext(goa.WithAction(ctx, "GroupTest"), rw, req, prms) 247 | listCtx, _err := app.NewListGroupContext(goaCtx, req, service) 248 | if _err != nil { 249 | panic("invalid test data " + _err.Error()) // bug 250 | } 251 | 252 | // Perform action 253 | _err = ctrl.List(listCtx) 254 | 255 | // Validate response 256 | if _err != nil { 257 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 258 | } 259 | if rw.Code != 200 { 260 | t.Errorf("invalid response status code: got %+v, expected 200", rw.Code) 261 | } 262 | var mt app.GwentapiGroupCollection 263 | if resp != nil { 264 | var ok bool 265 | mt, ok = resp.(app.GwentapiGroupCollection) 266 | if !ok { 267 | t.Fatalf("invalid response media: got variable of type %T, value %+v, expected instance of app.GwentapiGroupCollection", resp, resp) 268 | } 269 | _err = mt.Validate() 270 | if _err != nil { 271 | t.Errorf("invalid response media type: %s", _err) 272 | } 273 | } 274 | 275 | // Return results 276 | return rw, mt 277 | } 278 | 279 | // ListGroupOKLink runs the method List of the given controller with the given parameters. 280 | // It returns the response writer so it's possible to inspect the response headers and the media type struct written to the response. 281 | // If ctx is nil then context.Background() is used. 282 | // If service is nil then a default service is created. 283 | func ListGroupOKLink(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.GroupController, ifModifiedSince *string) (http.ResponseWriter, app.GwentapiGroupLinkCollection) { 284 | // Setup service 285 | var ( 286 | logBuf bytes.Buffer 287 | resp interface{} 288 | 289 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 290 | ) 291 | if service == nil { 292 | service = goatest.Service(&logBuf, respSetter) 293 | } else { 294 | logger := log.New(&logBuf, "", log.Ltime) 295 | service.WithLogger(goa.NewLogger(logger)) 296 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 297 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 298 | service.Encoder.Register(newEncoder, "*/*") 299 | } 300 | 301 | // Setup request context 302 | rw := httptest.NewRecorder() 303 | u := &url.URL{ 304 | Path: fmt.Sprintf("/v0/groups"), 305 | } 306 | req, err := http.NewRequest("GET", u.String(), nil) 307 | if err != nil { 308 | panic("invalid test " + err.Error()) // bug 309 | } 310 | if ifModifiedSince != nil { 311 | sliceVal := []string{*ifModifiedSince} 312 | req.Header["If-Modified-Since"] = sliceVal 313 | } 314 | prms := url.Values{} 315 | if ctx == nil { 316 | ctx = context.Background() 317 | } 318 | goaCtx := goa.NewContext(goa.WithAction(ctx, "GroupTest"), rw, req, prms) 319 | listCtx, _err := app.NewListGroupContext(goaCtx, req, service) 320 | if _err != nil { 321 | panic("invalid test data " + _err.Error()) // bug 322 | } 323 | 324 | // Perform action 325 | _err = ctrl.List(listCtx) 326 | 327 | // Validate response 328 | if _err != nil { 329 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 330 | } 331 | if rw.Code != 200 { 332 | t.Errorf("invalid response status code: got %+v, expected 200", rw.Code) 333 | } 334 | var mt app.GwentapiGroupLinkCollection 335 | if resp != nil { 336 | var ok bool 337 | mt, ok = resp.(app.GwentapiGroupLinkCollection) 338 | if !ok { 339 | t.Fatalf("invalid response media: got variable of type %T, value %+v, expected instance of app.GwentapiGroupLinkCollection", resp, resp) 340 | } 341 | _err = mt.Validate() 342 | if _err != nil { 343 | t.Errorf("invalid response media type: %s", _err) 344 | } 345 | } 346 | 347 | // Return results 348 | return rw, mt 349 | } 350 | 351 | // ShowGroupInternalServerError runs the method Show of the given controller with the given parameters. 352 | // It returns the response writer so it's possible to inspect the response headers. 353 | // If ctx is nil then context.Background() is used. 354 | // If service is nil then a default service is created. 355 | func ShowGroupInternalServerError(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.GroupController, groupID string, ifModifiedSince *string) http.ResponseWriter { 356 | // Setup service 357 | var ( 358 | logBuf bytes.Buffer 359 | resp interface{} 360 | 361 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 362 | ) 363 | if service == nil { 364 | service = goatest.Service(&logBuf, respSetter) 365 | } else { 366 | logger := log.New(&logBuf, "", log.Ltime) 367 | service.WithLogger(goa.NewLogger(logger)) 368 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 369 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 370 | service.Encoder.Register(newEncoder, "*/*") 371 | } 372 | 373 | // Setup request context 374 | rw := httptest.NewRecorder() 375 | u := &url.URL{ 376 | Path: fmt.Sprintf("/v0/groups/%v", groupID), 377 | } 378 | req, err := http.NewRequest("GET", u.String(), nil) 379 | if err != nil { 380 | panic("invalid test " + err.Error()) // bug 381 | } 382 | if ifModifiedSince != nil { 383 | sliceVal := []string{*ifModifiedSince} 384 | req.Header["If-Modified-Since"] = sliceVal 385 | } 386 | prms := url.Values{} 387 | prms["groupID"] = []string{fmt.Sprintf("%v", groupID)} 388 | if ctx == nil { 389 | ctx = context.Background() 390 | } 391 | goaCtx := goa.NewContext(goa.WithAction(ctx, "GroupTest"), rw, req, prms) 392 | showCtx, _err := app.NewShowGroupContext(goaCtx, req, service) 393 | if _err != nil { 394 | panic("invalid test data " + _err.Error()) // bug 395 | } 396 | 397 | // Perform action 398 | _err = ctrl.Show(showCtx) 399 | 400 | // Validate response 401 | if _err != nil { 402 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 403 | } 404 | if rw.Code != 500 { 405 | t.Errorf("invalid response status code: got %+v, expected 500", rw.Code) 406 | } 407 | 408 | // Return results 409 | return rw 410 | } 411 | 412 | // ShowGroupNotFound runs the method Show of the given controller with the given parameters. 413 | // It returns the response writer so it's possible to inspect the response headers. 414 | // If ctx is nil then context.Background() is used. 415 | // If service is nil then a default service is created. 416 | func ShowGroupNotFound(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.GroupController, groupID string, ifModifiedSince *string) http.ResponseWriter { 417 | // Setup service 418 | var ( 419 | logBuf bytes.Buffer 420 | resp interface{} 421 | 422 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 423 | ) 424 | if service == nil { 425 | service = goatest.Service(&logBuf, respSetter) 426 | } else { 427 | logger := log.New(&logBuf, "", log.Ltime) 428 | service.WithLogger(goa.NewLogger(logger)) 429 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 430 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 431 | service.Encoder.Register(newEncoder, "*/*") 432 | } 433 | 434 | // Setup request context 435 | rw := httptest.NewRecorder() 436 | u := &url.URL{ 437 | Path: fmt.Sprintf("/v0/groups/%v", groupID), 438 | } 439 | req, err := http.NewRequest("GET", u.String(), nil) 440 | if err != nil { 441 | panic("invalid test " + err.Error()) // bug 442 | } 443 | if ifModifiedSince != nil { 444 | sliceVal := []string{*ifModifiedSince} 445 | req.Header["If-Modified-Since"] = sliceVal 446 | } 447 | prms := url.Values{} 448 | prms["groupID"] = []string{fmt.Sprintf("%v", groupID)} 449 | if ctx == nil { 450 | ctx = context.Background() 451 | } 452 | goaCtx := goa.NewContext(goa.WithAction(ctx, "GroupTest"), rw, req, prms) 453 | showCtx, _err := app.NewShowGroupContext(goaCtx, req, service) 454 | if _err != nil { 455 | panic("invalid test data " + _err.Error()) // bug 456 | } 457 | 458 | // Perform action 459 | _err = ctrl.Show(showCtx) 460 | 461 | // Validate response 462 | if _err != nil { 463 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 464 | } 465 | if rw.Code != 404 { 466 | t.Errorf("invalid response status code: got %+v, expected 404", rw.Code) 467 | } 468 | 469 | // Return results 470 | return rw 471 | } 472 | 473 | // ShowGroupNotModified runs the method Show of the given controller with the given parameters. 474 | // It returns the response writer so it's possible to inspect the response headers. 475 | // If ctx is nil then context.Background() is used. 476 | // If service is nil then a default service is created. 477 | func ShowGroupNotModified(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.GroupController, groupID string, ifModifiedSince *string) http.ResponseWriter { 478 | // Setup service 479 | var ( 480 | logBuf bytes.Buffer 481 | resp interface{} 482 | 483 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 484 | ) 485 | if service == nil { 486 | service = goatest.Service(&logBuf, respSetter) 487 | } else { 488 | logger := log.New(&logBuf, "", log.Ltime) 489 | service.WithLogger(goa.NewLogger(logger)) 490 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 491 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 492 | service.Encoder.Register(newEncoder, "*/*") 493 | } 494 | 495 | // Setup request context 496 | rw := httptest.NewRecorder() 497 | u := &url.URL{ 498 | Path: fmt.Sprintf("/v0/groups/%v", groupID), 499 | } 500 | req, err := http.NewRequest("GET", u.String(), nil) 501 | if err != nil { 502 | panic("invalid test " + err.Error()) // bug 503 | } 504 | if ifModifiedSince != nil { 505 | sliceVal := []string{*ifModifiedSince} 506 | req.Header["If-Modified-Since"] = sliceVal 507 | } 508 | prms := url.Values{} 509 | prms["groupID"] = []string{fmt.Sprintf("%v", groupID)} 510 | if ctx == nil { 511 | ctx = context.Background() 512 | } 513 | goaCtx := goa.NewContext(goa.WithAction(ctx, "GroupTest"), rw, req, prms) 514 | showCtx, _err := app.NewShowGroupContext(goaCtx, req, service) 515 | if _err != nil { 516 | panic("invalid test data " + _err.Error()) // bug 517 | } 518 | 519 | // Perform action 520 | _err = ctrl.Show(showCtx) 521 | 522 | // Validate response 523 | if _err != nil { 524 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 525 | } 526 | if rw.Code != 304 { 527 | t.Errorf("invalid response status code: got %+v, expected 304", rw.Code) 528 | } 529 | 530 | // Return results 531 | return rw 532 | } 533 | 534 | // ShowGroupOK runs the method Show of the given controller with the given parameters. 535 | // It returns the response writer so it's possible to inspect the response headers and the media type struct written to the response. 536 | // If ctx is nil then context.Background() is used. 537 | // If service is nil then a default service is created. 538 | func ShowGroupOK(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.GroupController, groupID string, ifModifiedSince *string) (http.ResponseWriter, *app.GwentapiGroup) { 539 | // Setup service 540 | var ( 541 | logBuf bytes.Buffer 542 | resp interface{} 543 | 544 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 545 | ) 546 | if service == nil { 547 | service = goatest.Service(&logBuf, respSetter) 548 | } else { 549 | logger := log.New(&logBuf, "", log.Ltime) 550 | service.WithLogger(goa.NewLogger(logger)) 551 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 552 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 553 | service.Encoder.Register(newEncoder, "*/*") 554 | } 555 | 556 | // Setup request context 557 | rw := httptest.NewRecorder() 558 | u := &url.URL{ 559 | Path: fmt.Sprintf("/v0/groups/%v", groupID), 560 | } 561 | req, err := http.NewRequest("GET", u.String(), nil) 562 | if err != nil { 563 | panic("invalid test " + err.Error()) // bug 564 | } 565 | if ifModifiedSince != nil { 566 | sliceVal := []string{*ifModifiedSince} 567 | req.Header["If-Modified-Since"] = sliceVal 568 | } 569 | prms := url.Values{} 570 | prms["groupID"] = []string{fmt.Sprintf("%v", groupID)} 571 | if ctx == nil { 572 | ctx = context.Background() 573 | } 574 | goaCtx := goa.NewContext(goa.WithAction(ctx, "GroupTest"), rw, req, prms) 575 | showCtx, _err := app.NewShowGroupContext(goaCtx, req, service) 576 | if _err != nil { 577 | panic("invalid test data " + _err.Error()) // bug 578 | } 579 | 580 | // Perform action 581 | _err = ctrl.Show(showCtx) 582 | 583 | // Validate response 584 | if _err != nil { 585 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 586 | } 587 | if rw.Code != 200 { 588 | t.Errorf("invalid response status code: got %+v, expected 200", rw.Code) 589 | } 590 | var mt *app.GwentapiGroup 591 | if resp != nil { 592 | var ok bool 593 | mt, ok = resp.(*app.GwentapiGroup) 594 | if !ok { 595 | t.Fatalf("invalid response media: got variable of type %T, value %+v, expected instance of app.GwentapiGroup", resp, resp) 596 | } 597 | _err = mt.Validate() 598 | if _err != nil { 599 | t.Errorf("invalid response media type: %s", _err) 600 | } 601 | } 602 | 603 | // Return results 604 | return rw, mt 605 | } 606 | 607 | // ShowGroupOKLink runs the method Show of the given controller with the given parameters. 608 | // It returns the response writer so it's possible to inspect the response headers and the media type struct written to the response. 609 | // If ctx is nil then context.Background() is used. 610 | // If service is nil then a default service is created. 611 | func ShowGroupOKLink(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.GroupController, groupID string, ifModifiedSince *string) (http.ResponseWriter, *app.GwentapiGroupLink) { 612 | // Setup service 613 | var ( 614 | logBuf bytes.Buffer 615 | resp interface{} 616 | 617 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 618 | ) 619 | if service == nil { 620 | service = goatest.Service(&logBuf, respSetter) 621 | } else { 622 | logger := log.New(&logBuf, "", log.Ltime) 623 | service.WithLogger(goa.NewLogger(logger)) 624 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 625 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 626 | service.Encoder.Register(newEncoder, "*/*") 627 | } 628 | 629 | // Setup request context 630 | rw := httptest.NewRecorder() 631 | u := &url.URL{ 632 | Path: fmt.Sprintf("/v0/groups/%v", groupID), 633 | } 634 | req, err := http.NewRequest("GET", u.String(), nil) 635 | if err != nil { 636 | panic("invalid test " + err.Error()) // bug 637 | } 638 | if ifModifiedSince != nil { 639 | sliceVal := []string{*ifModifiedSince} 640 | req.Header["If-Modified-Since"] = sliceVal 641 | } 642 | prms := url.Values{} 643 | prms["groupID"] = []string{fmt.Sprintf("%v", groupID)} 644 | if ctx == nil { 645 | ctx = context.Background() 646 | } 647 | goaCtx := goa.NewContext(goa.WithAction(ctx, "GroupTest"), rw, req, prms) 648 | showCtx, _err := app.NewShowGroupContext(goaCtx, req, service) 649 | if _err != nil { 650 | panic("invalid test data " + _err.Error()) // bug 651 | } 652 | 653 | // Perform action 654 | _err = ctrl.Show(showCtx) 655 | 656 | // Validate response 657 | if _err != nil { 658 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 659 | } 660 | if rw.Code != 200 { 661 | t.Errorf("invalid response status code: got %+v, expected 200", rw.Code) 662 | } 663 | var mt *app.GwentapiGroupLink 664 | if resp != nil { 665 | var ok bool 666 | mt, ok = resp.(*app.GwentapiGroupLink) 667 | if !ok { 668 | t.Fatalf("invalid response media: got variable of type %T, value %+v, expected instance of app.GwentapiGroupLink", resp, resp) 669 | } 670 | _err = mt.Validate() 671 | if _err != nil { 672 | t.Errorf("invalid response media type: %s", _err) 673 | } 674 | } 675 | 676 | // Return results 677 | return rw, mt 678 | } 679 | -------------------------------------------------------------------------------- /app/test/index_testing.go: -------------------------------------------------------------------------------- 1 | // Code generated by goagen v1.2.0, DO NOT EDIT. 2 | // 3 | // API "gwentapi": index TestHelpers 4 | // 5 | // Command: 6 | // $ goagen 7 | // --design=github.com/GwentAPI/gwentapi/design 8 | // --out=$(GOPATH)\src\github.com\GwentAPI\gwentapi 9 | // --version=v1.2.0 10 | 11 | package test 12 | 13 | import ( 14 | "bytes" 15 | "context" 16 | "fmt" 17 | "github.com/GwentAPI/gwentapi/app" 18 | "github.com/goadesign/goa" 19 | "github.com/goadesign/goa/goatest" 20 | "io" 21 | "log" 22 | "net/http" 23 | "net/http/httptest" 24 | "net/url" 25 | ) 26 | 27 | // ShowIndexNotFound runs the method Show of the given controller with the given parameters. 28 | // It returns the response writer so it's possible to inspect the response headers. 29 | // If ctx is nil then context.Background() is used. 30 | // If service is nil then a default service is created. 31 | func ShowIndexNotFound(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.IndexController) http.ResponseWriter { 32 | // Setup service 33 | var ( 34 | logBuf bytes.Buffer 35 | resp interface{} 36 | 37 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 38 | ) 39 | if service == nil { 40 | service = goatest.Service(&logBuf, respSetter) 41 | } else { 42 | logger := log.New(&logBuf, "", log.Ltime) 43 | service.WithLogger(goa.NewLogger(logger)) 44 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 45 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 46 | service.Encoder.Register(newEncoder, "*/*") 47 | } 48 | 49 | // Setup request context 50 | rw := httptest.NewRecorder() 51 | u := &url.URL{ 52 | Path: fmt.Sprintf("/v0"), 53 | } 54 | req, err := http.NewRequest("GET", u.String(), nil) 55 | if err != nil { 56 | panic("invalid test " + err.Error()) // bug 57 | } 58 | prms := url.Values{} 59 | if ctx == nil { 60 | ctx = context.Background() 61 | } 62 | goaCtx := goa.NewContext(goa.WithAction(ctx, "IndexTest"), rw, req, prms) 63 | showCtx, _err := app.NewShowIndexContext(goaCtx, req, service) 64 | if _err != nil { 65 | panic("invalid test data " + _err.Error()) // bug 66 | } 67 | 68 | // Perform action 69 | _err = ctrl.Show(showCtx) 70 | 71 | // Validate response 72 | if _err != nil { 73 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 74 | } 75 | if rw.Code != 404 { 76 | t.Errorf("invalid response status code: got %+v, expected 404", rw.Code) 77 | } 78 | 79 | // Return results 80 | return rw 81 | } 82 | 83 | // ShowIndexOK runs the method Show of the given controller with the given parameters. 84 | // It returns the response writer so it's possible to inspect the response headers and the media type struct written to the response. 85 | // If ctx is nil then context.Background() is used. 86 | // If service is nil then a default service is created. 87 | func ShowIndexOK(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.IndexController) (http.ResponseWriter, *app.GwentapiResource) { 88 | // Setup service 89 | var ( 90 | logBuf bytes.Buffer 91 | resp interface{} 92 | 93 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 94 | ) 95 | if service == nil { 96 | service = goatest.Service(&logBuf, respSetter) 97 | } else { 98 | logger := log.New(&logBuf, "", log.Ltime) 99 | service.WithLogger(goa.NewLogger(logger)) 100 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 101 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 102 | service.Encoder.Register(newEncoder, "*/*") 103 | } 104 | 105 | // Setup request context 106 | rw := httptest.NewRecorder() 107 | u := &url.URL{ 108 | Path: fmt.Sprintf("/v0"), 109 | } 110 | req, err := http.NewRequest("GET", u.String(), nil) 111 | if err != nil { 112 | panic("invalid test " + err.Error()) // bug 113 | } 114 | prms := url.Values{} 115 | if ctx == nil { 116 | ctx = context.Background() 117 | } 118 | goaCtx := goa.NewContext(goa.WithAction(ctx, "IndexTest"), rw, req, prms) 119 | showCtx, _err := app.NewShowIndexContext(goaCtx, req, service) 120 | if _err != nil { 121 | panic("invalid test data " + _err.Error()) // bug 122 | } 123 | 124 | // Perform action 125 | _err = ctrl.Show(showCtx) 126 | 127 | // Validate response 128 | if _err != nil { 129 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 130 | } 131 | if rw.Code != 200 { 132 | t.Errorf("invalid response status code: got %+v, expected 200", rw.Code) 133 | } 134 | var mt *app.GwentapiResource 135 | if resp != nil { 136 | var ok bool 137 | mt, ok = resp.(*app.GwentapiResource) 138 | if !ok { 139 | t.Fatalf("invalid response media: got variable of type %T, value %+v, expected instance of app.GwentapiResource", resp, resp) 140 | } 141 | _err = mt.Validate() 142 | if _err != nil { 143 | t.Errorf("invalid response media type: %s", _err) 144 | } 145 | } 146 | 147 | // Return results 148 | return rw, mt 149 | } 150 | -------------------------------------------------------------------------------- /app/test/rarity_testing.go: -------------------------------------------------------------------------------- 1 | // Code generated by goagen v1.2.0, DO NOT EDIT. 2 | // 3 | // API "gwentapi": rarity TestHelpers 4 | // 5 | // Command: 6 | // $ goagen 7 | // --design=github.com/GwentAPI/gwentapi/design 8 | // --out=$(GOPATH)\src\github.com\GwentAPI\gwentapi 9 | // --version=v1.2.0 10 | 11 | package test 12 | 13 | import ( 14 | "bytes" 15 | "context" 16 | "fmt" 17 | "github.com/GwentAPI/gwentapi/app" 18 | "github.com/goadesign/goa" 19 | "github.com/goadesign/goa/goatest" 20 | "io" 21 | "log" 22 | "net/http" 23 | "net/http/httptest" 24 | "net/url" 25 | ) 26 | 27 | // ListRarityInternalServerError runs the method List of the given controller with the given parameters. 28 | // It returns the response writer so it's possible to inspect the response headers. 29 | // If ctx is nil then context.Background() is used. 30 | // If service is nil then a default service is created. 31 | func ListRarityInternalServerError(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.RarityController, ifModifiedSince *string) http.ResponseWriter { 32 | // Setup service 33 | var ( 34 | logBuf bytes.Buffer 35 | resp interface{} 36 | 37 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 38 | ) 39 | if service == nil { 40 | service = goatest.Service(&logBuf, respSetter) 41 | } else { 42 | logger := log.New(&logBuf, "", log.Ltime) 43 | service.WithLogger(goa.NewLogger(logger)) 44 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 45 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 46 | service.Encoder.Register(newEncoder, "*/*") 47 | } 48 | 49 | // Setup request context 50 | rw := httptest.NewRecorder() 51 | u := &url.URL{ 52 | Path: fmt.Sprintf("/v0/rarities"), 53 | } 54 | req, err := http.NewRequest("GET", u.String(), nil) 55 | if err != nil { 56 | panic("invalid test " + err.Error()) // bug 57 | } 58 | if ifModifiedSince != nil { 59 | sliceVal := []string{*ifModifiedSince} 60 | req.Header["If-Modified-Since"] = sliceVal 61 | } 62 | prms := url.Values{} 63 | if ctx == nil { 64 | ctx = context.Background() 65 | } 66 | goaCtx := goa.NewContext(goa.WithAction(ctx, "RarityTest"), rw, req, prms) 67 | listCtx, _err := app.NewListRarityContext(goaCtx, req, service) 68 | if _err != nil { 69 | panic("invalid test data " + _err.Error()) // bug 70 | } 71 | 72 | // Perform action 73 | _err = ctrl.List(listCtx) 74 | 75 | // Validate response 76 | if _err != nil { 77 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 78 | } 79 | if rw.Code != 500 { 80 | t.Errorf("invalid response status code: got %+v, expected 500", rw.Code) 81 | } 82 | 83 | // Return results 84 | return rw 85 | } 86 | 87 | // ListRarityNotFound runs the method List of the given controller with the given parameters. 88 | // It returns the response writer so it's possible to inspect the response headers. 89 | // If ctx is nil then context.Background() is used. 90 | // If service is nil then a default service is created. 91 | func ListRarityNotFound(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.RarityController, ifModifiedSince *string) http.ResponseWriter { 92 | // Setup service 93 | var ( 94 | logBuf bytes.Buffer 95 | resp interface{} 96 | 97 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 98 | ) 99 | if service == nil { 100 | service = goatest.Service(&logBuf, respSetter) 101 | } else { 102 | logger := log.New(&logBuf, "", log.Ltime) 103 | service.WithLogger(goa.NewLogger(logger)) 104 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 105 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 106 | service.Encoder.Register(newEncoder, "*/*") 107 | } 108 | 109 | // Setup request context 110 | rw := httptest.NewRecorder() 111 | u := &url.URL{ 112 | Path: fmt.Sprintf("/v0/rarities"), 113 | } 114 | req, err := http.NewRequest("GET", u.String(), nil) 115 | if err != nil { 116 | panic("invalid test " + err.Error()) // bug 117 | } 118 | if ifModifiedSince != nil { 119 | sliceVal := []string{*ifModifiedSince} 120 | req.Header["If-Modified-Since"] = sliceVal 121 | } 122 | prms := url.Values{} 123 | if ctx == nil { 124 | ctx = context.Background() 125 | } 126 | goaCtx := goa.NewContext(goa.WithAction(ctx, "RarityTest"), rw, req, prms) 127 | listCtx, _err := app.NewListRarityContext(goaCtx, req, service) 128 | if _err != nil { 129 | panic("invalid test data " + _err.Error()) // bug 130 | } 131 | 132 | // Perform action 133 | _err = ctrl.List(listCtx) 134 | 135 | // Validate response 136 | if _err != nil { 137 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 138 | } 139 | if rw.Code != 404 { 140 | t.Errorf("invalid response status code: got %+v, expected 404", rw.Code) 141 | } 142 | 143 | // Return results 144 | return rw 145 | } 146 | 147 | // ListRarityNotModified runs the method List of the given controller with the given parameters. 148 | // It returns the response writer so it's possible to inspect the response headers. 149 | // If ctx is nil then context.Background() is used. 150 | // If service is nil then a default service is created. 151 | func ListRarityNotModified(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.RarityController, ifModifiedSince *string) http.ResponseWriter { 152 | // Setup service 153 | var ( 154 | logBuf bytes.Buffer 155 | resp interface{} 156 | 157 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 158 | ) 159 | if service == nil { 160 | service = goatest.Service(&logBuf, respSetter) 161 | } else { 162 | logger := log.New(&logBuf, "", log.Ltime) 163 | service.WithLogger(goa.NewLogger(logger)) 164 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 165 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 166 | service.Encoder.Register(newEncoder, "*/*") 167 | } 168 | 169 | // Setup request context 170 | rw := httptest.NewRecorder() 171 | u := &url.URL{ 172 | Path: fmt.Sprintf("/v0/rarities"), 173 | } 174 | req, err := http.NewRequest("GET", u.String(), nil) 175 | if err != nil { 176 | panic("invalid test " + err.Error()) // bug 177 | } 178 | if ifModifiedSince != nil { 179 | sliceVal := []string{*ifModifiedSince} 180 | req.Header["If-Modified-Since"] = sliceVal 181 | } 182 | prms := url.Values{} 183 | if ctx == nil { 184 | ctx = context.Background() 185 | } 186 | goaCtx := goa.NewContext(goa.WithAction(ctx, "RarityTest"), rw, req, prms) 187 | listCtx, _err := app.NewListRarityContext(goaCtx, req, service) 188 | if _err != nil { 189 | panic("invalid test data " + _err.Error()) // bug 190 | } 191 | 192 | // Perform action 193 | _err = ctrl.List(listCtx) 194 | 195 | // Validate response 196 | if _err != nil { 197 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 198 | } 199 | if rw.Code != 304 { 200 | t.Errorf("invalid response status code: got %+v, expected 304", rw.Code) 201 | } 202 | 203 | // Return results 204 | return rw 205 | } 206 | 207 | // ListRarityOK runs the method List of the given controller with the given parameters. 208 | // It returns the response writer so it's possible to inspect the response headers and the media type struct written to the response. 209 | // If ctx is nil then context.Background() is used. 210 | // If service is nil then a default service is created. 211 | func ListRarityOK(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.RarityController, ifModifiedSince *string) (http.ResponseWriter, app.GwentapiRarityCollection) { 212 | // Setup service 213 | var ( 214 | logBuf bytes.Buffer 215 | resp interface{} 216 | 217 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 218 | ) 219 | if service == nil { 220 | service = goatest.Service(&logBuf, respSetter) 221 | } else { 222 | logger := log.New(&logBuf, "", log.Ltime) 223 | service.WithLogger(goa.NewLogger(logger)) 224 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 225 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 226 | service.Encoder.Register(newEncoder, "*/*") 227 | } 228 | 229 | // Setup request context 230 | rw := httptest.NewRecorder() 231 | u := &url.URL{ 232 | Path: fmt.Sprintf("/v0/rarities"), 233 | } 234 | req, err := http.NewRequest("GET", u.String(), nil) 235 | if err != nil { 236 | panic("invalid test " + err.Error()) // bug 237 | } 238 | if ifModifiedSince != nil { 239 | sliceVal := []string{*ifModifiedSince} 240 | req.Header["If-Modified-Since"] = sliceVal 241 | } 242 | prms := url.Values{} 243 | if ctx == nil { 244 | ctx = context.Background() 245 | } 246 | goaCtx := goa.NewContext(goa.WithAction(ctx, "RarityTest"), rw, req, prms) 247 | listCtx, _err := app.NewListRarityContext(goaCtx, req, service) 248 | if _err != nil { 249 | panic("invalid test data " + _err.Error()) // bug 250 | } 251 | 252 | // Perform action 253 | _err = ctrl.List(listCtx) 254 | 255 | // Validate response 256 | if _err != nil { 257 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 258 | } 259 | if rw.Code != 200 { 260 | t.Errorf("invalid response status code: got %+v, expected 200", rw.Code) 261 | } 262 | var mt app.GwentapiRarityCollection 263 | if resp != nil { 264 | var ok bool 265 | mt, ok = resp.(app.GwentapiRarityCollection) 266 | if !ok { 267 | t.Fatalf("invalid response media: got variable of type %T, value %+v, expected instance of app.GwentapiRarityCollection", resp, resp) 268 | } 269 | _err = mt.Validate() 270 | if _err != nil { 271 | t.Errorf("invalid response media type: %s", _err) 272 | } 273 | } 274 | 275 | // Return results 276 | return rw, mt 277 | } 278 | 279 | // ListRarityOKLink runs the method List of the given controller with the given parameters. 280 | // It returns the response writer so it's possible to inspect the response headers and the media type struct written to the response. 281 | // If ctx is nil then context.Background() is used. 282 | // If service is nil then a default service is created. 283 | func ListRarityOKLink(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.RarityController, ifModifiedSince *string) (http.ResponseWriter, app.GwentapiRarityLinkCollection) { 284 | // Setup service 285 | var ( 286 | logBuf bytes.Buffer 287 | resp interface{} 288 | 289 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 290 | ) 291 | if service == nil { 292 | service = goatest.Service(&logBuf, respSetter) 293 | } else { 294 | logger := log.New(&logBuf, "", log.Ltime) 295 | service.WithLogger(goa.NewLogger(logger)) 296 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 297 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 298 | service.Encoder.Register(newEncoder, "*/*") 299 | } 300 | 301 | // Setup request context 302 | rw := httptest.NewRecorder() 303 | u := &url.URL{ 304 | Path: fmt.Sprintf("/v0/rarities"), 305 | } 306 | req, err := http.NewRequest("GET", u.String(), nil) 307 | if err != nil { 308 | panic("invalid test " + err.Error()) // bug 309 | } 310 | if ifModifiedSince != nil { 311 | sliceVal := []string{*ifModifiedSince} 312 | req.Header["If-Modified-Since"] = sliceVal 313 | } 314 | prms := url.Values{} 315 | if ctx == nil { 316 | ctx = context.Background() 317 | } 318 | goaCtx := goa.NewContext(goa.WithAction(ctx, "RarityTest"), rw, req, prms) 319 | listCtx, _err := app.NewListRarityContext(goaCtx, req, service) 320 | if _err != nil { 321 | panic("invalid test data " + _err.Error()) // bug 322 | } 323 | 324 | // Perform action 325 | _err = ctrl.List(listCtx) 326 | 327 | // Validate response 328 | if _err != nil { 329 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 330 | } 331 | if rw.Code != 200 { 332 | t.Errorf("invalid response status code: got %+v, expected 200", rw.Code) 333 | } 334 | var mt app.GwentapiRarityLinkCollection 335 | if resp != nil { 336 | var ok bool 337 | mt, ok = resp.(app.GwentapiRarityLinkCollection) 338 | if !ok { 339 | t.Fatalf("invalid response media: got variable of type %T, value %+v, expected instance of app.GwentapiRarityLinkCollection", resp, resp) 340 | } 341 | _err = mt.Validate() 342 | if _err != nil { 343 | t.Errorf("invalid response media type: %s", _err) 344 | } 345 | } 346 | 347 | // Return results 348 | return rw, mt 349 | } 350 | 351 | // ShowRarityInternalServerError runs the method Show of the given controller with the given parameters. 352 | // It returns the response writer so it's possible to inspect the response headers. 353 | // If ctx is nil then context.Background() is used. 354 | // If service is nil then a default service is created. 355 | func ShowRarityInternalServerError(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.RarityController, rarityID string, ifModifiedSince *string) http.ResponseWriter { 356 | // Setup service 357 | var ( 358 | logBuf bytes.Buffer 359 | resp interface{} 360 | 361 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 362 | ) 363 | if service == nil { 364 | service = goatest.Service(&logBuf, respSetter) 365 | } else { 366 | logger := log.New(&logBuf, "", log.Ltime) 367 | service.WithLogger(goa.NewLogger(logger)) 368 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 369 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 370 | service.Encoder.Register(newEncoder, "*/*") 371 | } 372 | 373 | // Setup request context 374 | rw := httptest.NewRecorder() 375 | u := &url.URL{ 376 | Path: fmt.Sprintf("/v0/rarities/%v", rarityID), 377 | } 378 | req, err := http.NewRequest("GET", u.String(), nil) 379 | if err != nil { 380 | panic("invalid test " + err.Error()) // bug 381 | } 382 | if ifModifiedSince != nil { 383 | sliceVal := []string{*ifModifiedSince} 384 | req.Header["If-Modified-Since"] = sliceVal 385 | } 386 | prms := url.Values{} 387 | prms["rarityID"] = []string{fmt.Sprintf("%v", rarityID)} 388 | if ctx == nil { 389 | ctx = context.Background() 390 | } 391 | goaCtx := goa.NewContext(goa.WithAction(ctx, "RarityTest"), rw, req, prms) 392 | showCtx, _err := app.NewShowRarityContext(goaCtx, req, service) 393 | if _err != nil { 394 | panic("invalid test data " + _err.Error()) // bug 395 | } 396 | 397 | // Perform action 398 | _err = ctrl.Show(showCtx) 399 | 400 | // Validate response 401 | if _err != nil { 402 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 403 | } 404 | if rw.Code != 500 { 405 | t.Errorf("invalid response status code: got %+v, expected 500", rw.Code) 406 | } 407 | 408 | // Return results 409 | return rw 410 | } 411 | 412 | // ShowRarityNotFound runs the method Show of the given controller with the given parameters. 413 | // It returns the response writer so it's possible to inspect the response headers. 414 | // If ctx is nil then context.Background() is used. 415 | // If service is nil then a default service is created. 416 | func ShowRarityNotFound(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.RarityController, rarityID string, ifModifiedSince *string) http.ResponseWriter { 417 | // Setup service 418 | var ( 419 | logBuf bytes.Buffer 420 | resp interface{} 421 | 422 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 423 | ) 424 | if service == nil { 425 | service = goatest.Service(&logBuf, respSetter) 426 | } else { 427 | logger := log.New(&logBuf, "", log.Ltime) 428 | service.WithLogger(goa.NewLogger(logger)) 429 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 430 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 431 | service.Encoder.Register(newEncoder, "*/*") 432 | } 433 | 434 | // Setup request context 435 | rw := httptest.NewRecorder() 436 | u := &url.URL{ 437 | Path: fmt.Sprintf("/v0/rarities/%v", rarityID), 438 | } 439 | req, err := http.NewRequest("GET", u.String(), nil) 440 | if err != nil { 441 | panic("invalid test " + err.Error()) // bug 442 | } 443 | if ifModifiedSince != nil { 444 | sliceVal := []string{*ifModifiedSince} 445 | req.Header["If-Modified-Since"] = sliceVal 446 | } 447 | prms := url.Values{} 448 | prms["rarityID"] = []string{fmt.Sprintf("%v", rarityID)} 449 | if ctx == nil { 450 | ctx = context.Background() 451 | } 452 | goaCtx := goa.NewContext(goa.WithAction(ctx, "RarityTest"), rw, req, prms) 453 | showCtx, _err := app.NewShowRarityContext(goaCtx, req, service) 454 | if _err != nil { 455 | panic("invalid test data " + _err.Error()) // bug 456 | } 457 | 458 | // Perform action 459 | _err = ctrl.Show(showCtx) 460 | 461 | // Validate response 462 | if _err != nil { 463 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 464 | } 465 | if rw.Code != 404 { 466 | t.Errorf("invalid response status code: got %+v, expected 404", rw.Code) 467 | } 468 | 469 | // Return results 470 | return rw 471 | } 472 | 473 | // ShowRarityNotModified runs the method Show of the given controller with the given parameters. 474 | // It returns the response writer so it's possible to inspect the response headers. 475 | // If ctx is nil then context.Background() is used. 476 | // If service is nil then a default service is created. 477 | func ShowRarityNotModified(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.RarityController, rarityID string, ifModifiedSince *string) http.ResponseWriter { 478 | // Setup service 479 | var ( 480 | logBuf bytes.Buffer 481 | resp interface{} 482 | 483 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 484 | ) 485 | if service == nil { 486 | service = goatest.Service(&logBuf, respSetter) 487 | } else { 488 | logger := log.New(&logBuf, "", log.Ltime) 489 | service.WithLogger(goa.NewLogger(logger)) 490 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 491 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 492 | service.Encoder.Register(newEncoder, "*/*") 493 | } 494 | 495 | // Setup request context 496 | rw := httptest.NewRecorder() 497 | u := &url.URL{ 498 | Path: fmt.Sprintf("/v0/rarities/%v", rarityID), 499 | } 500 | req, err := http.NewRequest("GET", u.String(), nil) 501 | if err != nil { 502 | panic("invalid test " + err.Error()) // bug 503 | } 504 | if ifModifiedSince != nil { 505 | sliceVal := []string{*ifModifiedSince} 506 | req.Header["If-Modified-Since"] = sliceVal 507 | } 508 | prms := url.Values{} 509 | prms["rarityID"] = []string{fmt.Sprintf("%v", rarityID)} 510 | if ctx == nil { 511 | ctx = context.Background() 512 | } 513 | goaCtx := goa.NewContext(goa.WithAction(ctx, "RarityTest"), rw, req, prms) 514 | showCtx, _err := app.NewShowRarityContext(goaCtx, req, service) 515 | if _err != nil { 516 | panic("invalid test data " + _err.Error()) // bug 517 | } 518 | 519 | // Perform action 520 | _err = ctrl.Show(showCtx) 521 | 522 | // Validate response 523 | if _err != nil { 524 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 525 | } 526 | if rw.Code != 304 { 527 | t.Errorf("invalid response status code: got %+v, expected 304", rw.Code) 528 | } 529 | 530 | // Return results 531 | return rw 532 | } 533 | 534 | // ShowRarityOK runs the method Show of the given controller with the given parameters. 535 | // It returns the response writer so it's possible to inspect the response headers and the media type struct written to the response. 536 | // If ctx is nil then context.Background() is used. 537 | // If service is nil then a default service is created. 538 | func ShowRarityOK(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.RarityController, rarityID string, ifModifiedSince *string) (http.ResponseWriter, *app.GwentapiRarity) { 539 | // Setup service 540 | var ( 541 | logBuf bytes.Buffer 542 | resp interface{} 543 | 544 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 545 | ) 546 | if service == nil { 547 | service = goatest.Service(&logBuf, respSetter) 548 | } else { 549 | logger := log.New(&logBuf, "", log.Ltime) 550 | service.WithLogger(goa.NewLogger(logger)) 551 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 552 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 553 | service.Encoder.Register(newEncoder, "*/*") 554 | } 555 | 556 | // Setup request context 557 | rw := httptest.NewRecorder() 558 | u := &url.URL{ 559 | Path: fmt.Sprintf("/v0/rarities/%v", rarityID), 560 | } 561 | req, err := http.NewRequest("GET", u.String(), nil) 562 | if err != nil { 563 | panic("invalid test " + err.Error()) // bug 564 | } 565 | if ifModifiedSince != nil { 566 | sliceVal := []string{*ifModifiedSince} 567 | req.Header["If-Modified-Since"] = sliceVal 568 | } 569 | prms := url.Values{} 570 | prms["rarityID"] = []string{fmt.Sprintf("%v", rarityID)} 571 | if ctx == nil { 572 | ctx = context.Background() 573 | } 574 | goaCtx := goa.NewContext(goa.WithAction(ctx, "RarityTest"), rw, req, prms) 575 | showCtx, _err := app.NewShowRarityContext(goaCtx, req, service) 576 | if _err != nil { 577 | panic("invalid test data " + _err.Error()) // bug 578 | } 579 | 580 | // Perform action 581 | _err = ctrl.Show(showCtx) 582 | 583 | // Validate response 584 | if _err != nil { 585 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 586 | } 587 | if rw.Code != 200 { 588 | t.Errorf("invalid response status code: got %+v, expected 200", rw.Code) 589 | } 590 | var mt *app.GwentapiRarity 591 | if resp != nil { 592 | var ok bool 593 | mt, ok = resp.(*app.GwentapiRarity) 594 | if !ok { 595 | t.Fatalf("invalid response media: got variable of type %T, value %+v, expected instance of app.GwentapiRarity", resp, resp) 596 | } 597 | _err = mt.Validate() 598 | if _err != nil { 599 | t.Errorf("invalid response media type: %s", _err) 600 | } 601 | } 602 | 603 | // Return results 604 | return rw, mt 605 | } 606 | 607 | // ShowRarityOKLink runs the method Show of the given controller with the given parameters. 608 | // It returns the response writer so it's possible to inspect the response headers and the media type struct written to the response. 609 | // If ctx is nil then context.Background() is used. 610 | // If service is nil then a default service is created. 611 | func ShowRarityOKLink(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.RarityController, rarityID string, ifModifiedSince *string) (http.ResponseWriter, *app.GwentapiRarityLink) { 612 | // Setup service 613 | var ( 614 | logBuf bytes.Buffer 615 | resp interface{} 616 | 617 | respSetter goatest.ResponseSetterFunc = func(r interface{}) { resp = r } 618 | ) 619 | if service == nil { 620 | service = goatest.Service(&logBuf, respSetter) 621 | } else { 622 | logger := log.New(&logBuf, "", log.Ltime) 623 | service.WithLogger(goa.NewLogger(logger)) 624 | newEncoder := func(io.Writer) goa.Encoder { return respSetter } 625 | service.Encoder = goa.NewHTTPEncoder() // Make sure the code ends up using this decoder 626 | service.Encoder.Register(newEncoder, "*/*") 627 | } 628 | 629 | // Setup request context 630 | rw := httptest.NewRecorder() 631 | u := &url.URL{ 632 | Path: fmt.Sprintf("/v0/rarities/%v", rarityID), 633 | } 634 | req, err := http.NewRequest("GET", u.String(), nil) 635 | if err != nil { 636 | panic("invalid test " + err.Error()) // bug 637 | } 638 | if ifModifiedSince != nil { 639 | sliceVal := []string{*ifModifiedSince} 640 | req.Header["If-Modified-Since"] = sliceVal 641 | } 642 | prms := url.Values{} 643 | prms["rarityID"] = []string{fmt.Sprintf("%v", rarityID)} 644 | if ctx == nil { 645 | ctx = context.Background() 646 | } 647 | goaCtx := goa.NewContext(goa.WithAction(ctx, "RarityTest"), rw, req, prms) 648 | showCtx, _err := app.NewShowRarityContext(goaCtx, req, service) 649 | if _err != nil { 650 | panic("invalid test data " + _err.Error()) // bug 651 | } 652 | 653 | // Perform action 654 | _err = ctrl.Show(showCtx) 655 | 656 | // Validate response 657 | if _err != nil { 658 | t.Fatalf("controller returned %+v, logs:\n%s", _err, logBuf.String()) 659 | } 660 | if rw.Code != 200 { 661 | t.Errorf("invalid response status code: got %+v, expected 200", rw.Code) 662 | } 663 | var mt *app.GwentapiRarityLink 664 | if resp != nil { 665 | var ok bool 666 | mt, ok = resp.(*app.GwentapiRarityLink) 667 | if !ok { 668 | t.Fatalf("invalid response media: got variable of type %T, value %+v, expected instance of app.GwentapiRarityLink", resp, resp) 669 | } 670 | _err = mt.Validate() 671 | if _err != nil { 672 | t.Errorf("invalid response media type: %s", _err) 673 | } 674 | } 675 | 676 | // Return results 677 | return rw, mt 678 | } 679 | -------------------------------------------------------------------------------- /app/user_types.go: -------------------------------------------------------------------------------- 1 | // Code generated by goagen v1.2.0, DO NOT EDIT. 2 | // 3 | // API "gwentapi": Application User Types 4 | // 5 | // Command: 6 | // $ goagen 7 | // --design=github.com/GwentAPI/gwentapi/design 8 | // --out=$(GOPATH)\src\github.com\GwentAPI\gwentapi 9 | // --version=v1.2.0 10 | 11 | package app 12 | 13 | import ( 14 | "github.com/goadesign/goa" 15 | ) 16 | 17 | // Type of card art 18 | type artType struct { 19 | // Name of the artist 20 | Artist *string `form:"artist,omitempty" json:"artist,omitempty" xml:"artist,omitempty"` 21 | // Href to full size artwork 22 | FullsizeImage *string `form:"fullsizeImage,omitempty" json:"fullsizeImage,omitempty" xml:"fullsizeImage,omitempty"` 23 | // Href to medium size artwork 24 | MediumsizeImage *string `form:"mediumsizeImage,omitempty" json:"mediumsizeImage,omitempty" xml:"mediumsizeImage,omitempty"` 25 | // Href to thumbnail size artwork 26 | ThumbnailImage *string `form:"thumbnailImage,omitempty" json:"thumbnailImage,omitempty" xml:"thumbnailImage,omitempty"` 27 | } 28 | 29 | // Validate validates the artType type instance. 30 | func (ut *artType) Validate() (err error) { 31 | if ut.ThumbnailImage == nil { 32 | err = goa.MergeErrors(err, goa.MissingAttributeError(`request`, "thumbnailImage")) 33 | } 34 | if ut.MediumsizeImage == nil { 35 | err = goa.MergeErrors(err, goa.MissingAttributeError(`request`, "mediumsizeImage")) 36 | } 37 | if ut.FullsizeImage != nil { 38 | if err2 := goa.ValidateFormat(goa.FormatURI, *ut.FullsizeImage); err2 != nil { 39 | err = goa.MergeErrors(err, goa.InvalidFormatError(`request.fullsizeImage`, *ut.FullsizeImage, goa.FormatURI, err2)) 40 | } 41 | } 42 | if ut.MediumsizeImage != nil { 43 | if err2 := goa.ValidateFormat(goa.FormatURI, *ut.MediumsizeImage); err2 != nil { 44 | err = goa.MergeErrors(err, goa.InvalidFormatError(`request.mediumsizeImage`, *ut.MediumsizeImage, goa.FormatURI, err2)) 45 | } 46 | } 47 | if ut.ThumbnailImage != nil { 48 | if err2 := goa.ValidateFormat(goa.FormatURI, *ut.ThumbnailImage); err2 != nil { 49 | err = goa.MergeErrors(err, goa.InvalidFormatError(`request.thumbnailImage`, *ut.ThumbnailImage, goa.FormatURI, err2)) 50 | } 51 | } 52 | return 53 | } 54 | 55 | // Publicize creates ArtType from artType 56 | func (ut *artType) Publicize() *ArtType { 57 | var pub ArtType 58 | if ut.Artist != nil { 59 | pub.Artist = ut.Artist 60 | } 61 | if ut.FullsizeImage != nil { 62 | pub.FullsizeImage = ut.FullsizeImage 63 | } 64 | if ut.MediumsizeImage != nil { 65 | pub.MediumsizeImage = *ut.MediumsizeImage 66 | } 67 | if ut.ThumbnailImage != nil { 68 | pub.ThumbnailImage = *ut.ThumbnailImage 69 | } 70 | return &pub 71 | } 72 | 73 | // Type of card art 74 | type ArtType struct { 75 | // Name of the artist 76 | Artist *string `form:"artist,omitempty" json:"artist,omitempty" xml:"artist,omitempty"` 77 | // Href to full size artwork 78 | FullsizeImage *string `form:"fullsizeImage,omitempty" json:"fullsizeImage,omitempty" xml:"fullsizeImage,omitempty"` 79 | // Href to medium size artwork 80 | MediumsizeImage string `form:"mediumsizeImage" json:"mediumsizeImage" xml:"mediumsizeImage"` 81 | // Href to thumbnail size artwork 82 | ThumbnailImage string `form:"thumbnailImage" json:"thumbnailImage" xml:"thumbnailImage"` 83 | } 84 | 85 | // Validate validates the ArtType type instance. 86 | func (ut *ArtType) Validate() (err error) { 87 | if ut.ThumbnailImage == "" { 88 | err = goa.MergeErrors(err, goa.MissingAttributeError(`type`, "thumbnailImage")) 89 | } 90 | if ut.MediumsizeImage == "" { 91 | err = goa.MergeErrors(err, goa.MissingAttributeError(`type`, "mediumsizeImage")) 92 | } 93 | if ut.FullsizeImage != nil { 94 | if err2 := goa.ValidateFormat(goa.FormatURI, *ut.FullsizeImage); err2 != nil { 95 | err = goa.MergeErrors(err, goa.InvalidFormatError(`type.fullsizeImage`, *ut.FullsizeImage, goa.FormatURI, err2)) 96 | } 97 | } 98 | if err2 := goa.ValidateFormat(goa.FormatURI, ut.MediumsizeImage); err2 != nil { 99 | err = goa.MergeErrors(err, goa.InvalidFormatError(`type.mediumsizeImage`, ut.MediumsizeImage, goa.FormatURI, err2)) 100 | } 101 | if err2 := goa.ValidateFormat(goa.FormatURI, ut.ThumbnailImage); err2 != nil { 102 | err = goa.MergeErrors(err, goa.InvalidFormatError(`type.thumbnailImage`, ut.ThumbnailImage, goa.FormatURI, err2)) 103 | } 104 | return 105 | } 106 | 107 | // Type used to define the associated crafting/milling cost cost 108 | type costType struct { 109 | // Normal cost 110 | Normal *int `form:"normal,omitempty" json:"normal,omitempty" xml:"normal,omitempty"` 111 | // Premium cost 112 | Premium *int `form:"premium,omitempty" json:"premium,omitempty" xml:"premium,omitempty"` 113 | } 114 | 115 | // Validate validates the costType type instance. 116 | func (ut *costType) Validate() (err error) { 117 | if ut.Premium == nil { 118 | err = goa.MergeErrors(err, goa.MissingAttributeError(`request`, "premium")) 119 | } 120 | if ut.Normal == nil { 121 | err = goa.MergeErrors(err, goa.MissingAttributeError(`request`, "normal")) 122 | } 123 | return 124 | } 125 | 126 | // Publicize creates CostType from costType 127 | func (ut *costType) Publicize() *CostType { 128 | var pub CostType 129 | if ut.Normal != nil { 130 | pub.Normal = *ut.Normal 131 | } 132 | if ut.Premium != nil { 133 | pub.Premium = *ut.Premium 134 | } 135 | return &pub 136 | } 137 | 138 | // Type used to define the associated crafting/milling cost cost 139 | type CostType struct { 140 | // Normal cost 141 | Normal int `form:"normal" json:"normal" xml:"normal"` 142 | // Premium cost 143 | Premium int `form:"premium" json:"premium" xml:"premium"` 144 | } 145 | 146 | // Validate validates the CostType type instance. 147 | func (ut *CostType) Validate() (err error) { 148 | 149 | return 150 | } 151 | -------------------------------------------------------------------------------- /card.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/app" 5 | "github.com/GwentAPI/gwentapi/dataLayer/dal" 6 | "github.com/GwentAPI/gwentapi/dataLayer/factory" 7 | "github.com/GwentAPI/gwentapi/dataLayer/models" 8 | "github.com/GwentAPI/gwentapi/helpers" 9 | "github.com/goadesign/goa" 10 | "github.com/goadesign/goa/middleware" 11 | ) 12 | 13 | // CardController implements the card resource. 14 | type CardController struct { 15 | *goa.Controller 16 | } 17 | 18 | // NewCardController creates a card controller. 19 | func NewCardController(service *goa.Service) *CardController { 20 | return &CardController{Controller: service.NewController("CardController")} 21 | } 22 | 23 | // CardFaction runs the cardFaction action. 24 | func (c *CardController) CardFaction(ctx *app.CardFactionCardContext) error { 25 | // CardController_CardFaction: start_implement 26 | dataStore := &dal.DataStore{} 27 | dataStore.GetSession() 28 | // Close the session 29 | defer dataStore.Close() 30 | dc := dal.NewDalCard(dataStore) 31 | df := dal.NewDalFaction(dataStore) 32 | factionUUID, errFactionUUID := helpers.DecodeUUID(ctx.FactionID) 33 | 34 | if errFactionUUID != nil { 35 | return ctx.NotFound() 36 | } 37 | faction, errFaction := df.Fetch(factionUUID) 38 | 39 | collectionCount, err := dc.CountFromFaction(faction.ID) 40 | 41 | if helpers.IsNotFoundError(errFaction) || helpers.IsNotFoundError(err) { 42 | return ctx.NotFound() 43 | } 44 | 45 | limit, offset := helpers.ValidateLimitOffset(collectionCount, ctx.Limit, ctx.Offset) 46 | cards, err := dc.FetchFromFactionPaging(faction.ID, limit, offset) 47 | 48 | if err != nil || errFaction != nil { 49 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Card", "action", "CardFaction", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", err.Error()) 50 | return ctx.InternalServerError() 51 | } 52 | // CardController_CardFaction: end_implement 53 | res, lastModified, _ := factory.CreatePageCard(cards, "factions/"+ctx.FactionID, collectionCount, limit, offset, ctx.Lang) 54 | helpers.LastModified(ctx.ResponseData, lastModified) 55 | if ctx.IfModifiedSince != nil { 56 | if !helpers.IsModified(*ctx.IfModifiedSince, lastModified) { 57 | return ctx.NotModified() 58 | } 59 | } 60 | return ctx.OK(res) 61 | } 62 | 63 | // CardFaction runs the cardFaction action. 64 | func (c *CardController) CardRarity(ctx *app.CardRarityCardContext) error { 65 | // CardController_CardRarity: start_implement 66 | dataStore := &dal.DataStore{} 67 | dataStore.GetSession() 68 | // Close the session 69 | defer dataStore.Close() 70 | dv := dal.NewDalVariation(dataStore) 71 | dr := dal.NewDalRarity(dataStore) 72 | rarityUUID, errRarityUUID := helpers.DecodeUUID(ctx.RarityID) 73 | 74 | if errRarityUUID != nil { 75 | return ctx.NotFound() 76 | } 77 | rarity, errRarity := dr.Fetch(rarityUUID) 78 | 79 | collectionCount, err := dv.CountFromRarity(rarity.ID) 80 | 81 | if helpers.IsNotFoundError(errRarity) || helpers.IsNotFoundError(err) { 82 | return ctx.NotFound() 83 | } 84 | 85 | limit, offset := helpers.ValidateLimitOffset(collectionCount, ctx.Limit, ctx.Offset) 86 | cardIDs, err := dv.FetchCardIDFromRarityPaging(rarity.ID, limit, offset) 87 | 88 | dc := dal.NewDalCard(dataStore) 89 | cards, errCard := dc.FetchFromArray(*cardIDs) 90 | 91 | if err != nil || errRarity != nil || errCard != nil { 92 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Card", "action", "CardRarity", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", err.Error()) 93 | return ctx.InternalServerError() 94 | } 95 | 96 | // CardController_CardRarity: end_implement 97 | res, lastModified, _ := factory.CreatePageCard(cards, "rarities/"+ctx.RarityID, collectionCount, limit, offset, ctx.Lang) 98 | helpers.LastModified(ctx.ResponseData, lastModified) 99 | if ctx.IfModifiedSince != nil { 100 | if !helpers.IsModified(*ctx.IfModifiedSince, lastModified) { 101 | return ctx.NotModified() 102 | } 103 | } 104 | return ctx.OK(res) 105 | } 106 | 107 | // CardLeader runs the cardLeader action. 108 | func (c *CardController) CardLeader(ctx *app.CardLeaderCardContext) error { 109 | // CardController_CardLeader: start_implement 110 | 111 | dataStore := &dal.DataStore{} 112 | dataStore.GetSession() 113 | // Close the session 114 | defer dataStore.Close() 115 | dc := dal.NewDalCard(dataStore) 116 | dg := dal.NewDalGroup(dataStore) 117 | 118 | group, errGroup := dg.FetchWithName("Leader") 119 | collectionCount, err := dc.CountLeader(group.ID) 120 | 121 | if helpers.IsNotFoundError(err) { 122 | return ctx.NotFound() 123 | } 124 | limit, offset := helpers.ValidateLimitOffset(collectionCount, ctx.Limit, ctx.Offset) 125 | cards, err := dc.FetchLeaderPaging(group.ID, limit, offset) 126 | 127 | if helpers.IsNotFoundError(err) { 128 | return ctx.NotFound() 129 | } else if err != nil || errGroup != nil { 130 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Card", "action", "CardLeader", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", err.Error()) 131 | return ctx.InternalServerError() 132 | } 133 | // CardController_CardLeader: end_implement 134 | res, lastModified, _ := factory.CreatePageCard(cards, "leaders", collectionCount, limit, offset, ctx.Lang) 135 | helpers.LastModified(ctx.ResponseData, lastModified) 136 | if ctx.IfModifiedSince != nil { 137 | if !helpers.IsModified(*ctx.IfModifiedSince, lastModified) { 138 | return ctx.NotModified() 139 | } 140 | } 141 | return ctx.OK(res) 142 | } 143 | 144 | // CardVariation runs the cardVariation action. 145 | func (c *CardController) CardVariation(ctx *app.CardVariationCardContext) error { 146 | // CardController_CardVariation: start_implement 147 | dataStore := &dal.DataStore{} 148 | dataStore.GetSession() 149 | // Close the session 150 | defer dataStore.Close() 151 | dc := dal.NewDalVariation(dataStore) 152 | uuid, err := helpers.DecodeUUID(ctx.CardID) 153 | variationUUID, errVariation := helpers.DecodeUUID(ctx.VariationID) 154 | 155 | if err != nil || errVariation != nil { 156 | return ctx.NotFound() 157 | } 158 | 159 | variation, err := dc.Fetch(variationUUID) 160 | 161 | if helpers.IsNotFoundError(err) { 162 | return ctx.NotFound() 163 | } else if err != nil { 164 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Card", "action", "CardVariation", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", err.Error()) 165 | return ctx.InternalServerError() 166 | } 167 | 168 | // CardController_CardVariation: end_implement 169 | res, err := factory.CreateVariation(variation, uuid, dataStore) 170 | if err != nil { 171 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Card", "action", "CardVariation", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", err.Error()) 172 | return ctx.InternalServerError() 173 | } 174 | helpers.LastModified(ctx.ResponseData, variation.Last_Modified) 175 | if ctx.IfModifiedSince != nil { 176 | if !helpers.IsModified(*ctx.IfModifiedSince, variation.Last_Modified) { 177 | return ctx.NotModified() 178 | } 179 | } 180 | return ctx.OK(res) 181 | } 182 | 183 | // CardVariations runs the cardVariations action. 184 | func (c *CardController) CardVariations(ctx *app.CardVariationsCardContext) error { 185 | // CardController_CardVariations: start_implement 186 | dataStore := &dal.DataStore{} 187 | dataStore.GetSession() 188 | // Close the session 189 | defer dataStore.Close() 190 | dc := dal.NewDalCard(dataStore) 191 | dv := dal.NewDalVariation(dataStore) 192 | uuid, err := helpers.DecodeUUID(ctx.CardID) 193 | 194 | if err != nil { 195 | return ctx.NotFound() 196 | } 197 | 198 | card, err := dc.Fetch(uuid) 199 | variations, errVariation := dv.FetchFromCardID(card.ID) 200 | 201 | if helpers.IsNotFoundError(err) || helpers.IsNotFoundError(errVariation) { 202 | return ctx.NotFound() 203 | } else if err != nil { 204 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Card", "action", "CardVariations", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", err.Error()) 205 | return ctx.InternalServerError() 206 | } 207 | 208 | // CardController_CardVariations: end_implement 209 | res, lastModified, errVariation := factory.CreateVariationCollection(variations, card.UUID, dataStore) 210 | if errVariation != nil { 211 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Card", "action", "CardVariations", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", errVariation.Error()) 212 | return ctx.InternalServerError() 213 | } 214 | helpers.LastModified(ctx.ResponseData, lastModified) 215 | if ctx.IfModifiedSince != nil { 216 | if !helpers.IsModified(*ctx.IfModifiedSince, lastModified) { 217 | return ctx.NotModified() 218 | } 219 | } 220 | return ctx.OK(res) 221 | } 222 | 223 | // List runs the list action. 224 | func (c *CardController) List(ctx *app.ListCardContext) error { 225 | // CardController_List: start_implement 226 | dataStore := &dal.DataStore{} 227 | dataStore.GetSession() 228 | // Close the session 229 | defer dataStore.Close() 230 | dc := dal.NewDalCard(dataStore) 231 | 232 | var cards *[]models.Card 233 | var serviceError error 234 | var resultCount int 235 | 236 | if ctx.Name != nil && len(*ctx.Name) >= 3 { 237 | query := dal.CardQuery{Name: *ctx.Name, Lang: ctx.Lang} 238 | cards, resultCount, serviceError = dc.FetchQueryPaging(ctx.Limit, ctx.Offset, query) 239 | } else { 240 | cards, resultCount, serviceError = dc.FetchAllPaging(ctx.Limit, ctx.Offset) 241 | } 242 | 243 | if serviceError != nil { 244 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Card", "action", "List", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", serviceError.Error()) 245 | return ctx.InternalServerError() 246 | } 247 | // CardController_List: end_implement 248 | res, lastModified, _ := factory.CreatePageCard(cards, "", resultCount, ctx.Limit, ctx.Offset, ctx.Lang) 249 | helpers.LastModified(ctx.ResponseData, lastModified) 250 | if ctx.IfModifiedSince != nil { 251 | if !helpers.IsModified(*ctx.IfModifiedSince, lastModified) { 252 | return ctx.NotModified() 253 | } 254 | } 255 | return ctx.OK(res) 256 | } 257 | 258 | // Show runs the show action. 259 | func (c *CardController) Show(ctx *app.ShowCardContext) error { 260 | // CardController_Show: start_implement 261 | dataStore := &dal.DataStore{} 262 | dataStore.GetSession() 263 | // Close the session 264 | defer dataStore.Close() 265 | dc := dal.NewDalCard(dataStore) 266 | uuid, err := helpers.DecodeUUID(ctx.CardID) 267 | 268 | if err != nil { 269 | return ctx.NotFound() 270 | } 271 | 272 | card, err := dc.Fetch(uuid) 273 | 274 | if helpers.IsNotFoundError(err) { 275 | return ctx.NotFound() 276 | } else if err != nil { 277 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Card", "action", "Show", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", err.Error()) 278 | return ctx.InternalServerError() 279 | } 280 | 281 | // CardController_Show: end_implement 282 | res, errFactory := factory.CreateCard(card, dataStore, ctx.Lang) 283 | if errFactory != nil { 284 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Card", "action", "Show", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", errFactory.Error()) 285 | return ctx.InternalServerError() 286 | } 287 | helpers.LastModified(ctx.ResponseData, card.Last_Modified) 288 | if ctx.IfModifiedSince != nil { 289 | if !helpers.IsModified(*ctx.IfModifiedSince, card.Last_Modified) { 290 | return ctx.NotModified() 291 | } 292 | } 293 | return ctx.OK(res) 294 | } 295 | -------------------------------------------------------------------------------- /category.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/app" 5 | "github.com/GwentAPI/gwentapi/dataLayer/dal" 6 | "github.com/GwentAPI/gwentapi/dataLayer/factory" 7 | "github.com/GwentAPI/gwentapi/helpers" 8 | "github.com/goadesign/goa" 9 | "github.com/goadesign/goa/middleware" 10 | "time" 11 | ) 12 | 13 | // CategoryController implements the category resource. 14 | type CategoryController struct { 15 | *goa.Controller 16 | } 17 | 18 | // NewCategoryController creates a category controller. 19 | func NewCategoryController(service *goa.Service) *CategoryController { 20 | return &CategoryController{Controller: service.NewController("CategoryController")} 21 | } 22 | 23 | // List runs the list action. 24 | func (c *CategoryController) List(ctx *app.ListCategoryContext) error { 25 | // CategoryController_List: start_implement 26 | dataStore := &dal.DataStore{} 27 | dataStore.GetSession() 28 | // Close the session 29 | defer dataStore.Close() 30 | dc := dal.NewDalCategory(dataStore) 31 | 32 | categories, err := dc.FetchAll() 33 | 34 | if err != nil { 35 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Category", "action", "List", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", err.Error()) 36 | return ctx.InternalServerError() 37 | } 38 | 39 | res := make(app.GwentapiCategoryCollection, len(*categories)) 40 | 41 | lastModified := time.Time{} 42 | 43 | for i, category := range *categories { 44 | c, _ := factory.CreateCategory(&category) 45 | 46 | if lastModified.Before(category.Last_Modified) { 47 | lastModified = category.Last_Modified 48 | } 49 | 50 | res[i] = c 51 | } 52 | // CategoryController_List: end_implement 53 | helpers.LastModified(ctx.ResponseData, lastModified) 54 | if ctx.IfModifiedSince != nil { 55 | if !helpers.IsModified(*ctx.IfModifiedSince, lastModified) { 56 | return ctx.NotModified() 57 | } 58 | } 59 | return ctx.OK(res) 60 | } 61 | 62 | // Show runs the show action. 63 | func (c *CategoryController) Show(ctx *app.ShowCategoryContext) error { 64 | // CategoryController_Show: start_implement 65 | 66 | dataStore := &dal.DataStore{} 67 | dataStore.GetSession() 68 | // Close the session 69 | defer dataStore.Close() 70 | dc := dal.NewDalCategory(dataStore) 71 | uuid, err := helpers.DecodeUUID(ctx.CategoryID) 72 | 73 | if err != nil { 74 | return ctx.NotFound() 75 | } 76 | 77 | category, err := dc.Fetch(uuid) 78 | 79 | if helpers.IsNotFoundError(err) { 80 | return ctx.NotFound() 81 | } else if err != nil { 82 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Category", "action", "Show", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", err.Error()) 83 | return ctx.InternalServerError() 84 | } 85 | // CategoryController_Show: end_implement 86 | res, _ := factory.CreateCategory(category) 87 | helpers.LastModified(ctx.ResponseData, category.Last_Modified) 88 | if ctx.IfModifiedSince != nil { 89 | if !helpers.IsModified(*ctx.IfModifiedSince, category.Last_Modified) { 90 | return ctx.NotModified() 91 | } 92 | } 93 | return ctx.OK(res) 94 | } 95 | -------------------------------------------------------------------------------- /config.toml: -------------------------------------------------------------------------------- 1 | [database] 2 | 3 | ## Doesn't support multiple hosts or clusters 4 | ## Default to localhost:27017 5 | 6 | ## List of server addresses separated by a comma. 7 | ## The list can be on multiple lines. 8 | 9 | #addrs = ["127.0.0.1:27017"] 10 | 11 | #useSSLProtocol = true 12 | 13 | ## If not specified, default to the "test" database. 14 | 15 | database = "gwentapi" 16 | 17 | ## If authentication is enabled on your mongod comment out these lines. 18 | ## If authenticationDatabase is left empty it is defaulted 19 | ## to the value of "database" if set, otherwise "admin". 20 | 21 | [database.authentication] 22 | #username = "user" 23 | #password = "myPassword" 24 | #authenticationDatabase = "admin" 25 | 26 | [app] 27 | LogInfoFile = "./info.log" 28 | LogErrorFile = "./error.log" 29 | debug = false 30 | verbose = false 31 | 32 | ## The URL where the service is publicly accessible. 33 | ## Every href linking to a resource will point to it. 34 | ## 35 | ## It has no impact on how you access the service 36 | ## from the host machine, which remains localhost:8080 by default. 37 | ## So you still need a proxy server redirecting traffic to the app. 38 | 39 | publicURL = "http://localhost:8080" 40 | 41 | ## Port which the service is listening to 42 | port = ":8080" 43 | 44 | ## Path on the server pointing to the location of the folder 45 | ## containing the artworks for the cards. 46 | ## "./media" by default. 47 | 48 | mediaPath = "./media" 49 | -------------------------------------------------------------------------------- /configuration/config.go: -------------------------------------------------------------------------------- 1 | package configuration 2 | 3 | import ( 4 | "bytes" 5 | "github.com/BurntSushi/toml" 6 | "log" 7 | "os" 8 | "reflect" 9 | ) 10 | 11 | var conf GwentConfig 12 | 13 | const configFilePath string = "config.toml" 14 | 15 | func GetConfig() GwentConfig { 16 | return conf 17 | } 18 | 19 | type GwentConfig struct { 20 | App app 21 | Database database 22 | } 23 | 24 | type database struct { 25 | Addrs []string 26 | Authentication authentication 27 | Database string 28 | UseSSL bool `toml:"useSSLProtocol"` 29 | } 30 | 31 | type authentication struct { 32 | Username string `toml:"username,omitempty"` 33 | Password string `toml:"password,omitempty"` 34 | AuthenticationDatabase string `toml:"authenticationDatabase,omitempty"` 35 | } 36 | 37 | type app struct { 38 | Debug bool 39 | Verbose bool 40 | LogInfoFile string 41 | LogErrorFile string 42 | PublicURL string 43 | Port string 44 | MediaPath string 45 | } 46 | 47 | func NewGwentConfig() GwentConfig { 48 | config := GwentConfig{} 49 | config.App = app{ 50 | LogInfoFile: "./info.log", 51 | LogErrorFile: "./error.log", 52 | Debug: false, 53 | Verbose: false, 54 | PublicURL: "http://localhost:8080", 55 | Port: ":8080", 56 | MediaPath: "./media", 57 | } 58 | config.Database = database{ 59 | Addrs: []string{"127.0.0.1:27017"}, 60 | Database: "gwentapi", 61 | UseSSL: false, 62 | } 63 | return config 64 | } 65 | 66 | func init() { 67 | defaultConfig := NewGwentConfig() 68 | 69 | if _, err := os.Stat(configFilePath); os.IsNotExist(err) { 70 | // File doesn't exists. 71 | log.Println(err) 72 | log.Println("Creating config file with default config values.") 73 | writeConfig(defaultConfig) 74 | // Using default values 75 | conf = defaultConfig 76 | } else { 77 | if userConfig, err := readConfig(configFilePath); err != nil { 78 | // Panicking because the user is using a configured environnement but it failed. 79 | // This is an unwanted state. 80 | log.Fatal("Failed to read config file: ", err) 81 | } else { 82 | conf = *userConfig 83 | } 84 | } 85 | } 86 | 87 | func writeConfig(config GwentConfig) { 88 | handleError := func(err error) { 89 | if err != nil { 90 | log.Println(err) 91 | log.Println("Failed to create config file.") 92 | } 93 | } 94 | 95 | buffer := new(bytes.Buffer) 96 | toml.NewEncoder(buffer).Encode(config) 97 | if file, err := os.Create(configFilePath); err != nil { 98 | handleError(err) 99 | } else { 100 | file.Write(buffer.Bytes()) 101 | file.Sync() 102 | if err := file.Close(); err != nil { 103 | handleError(err) 104 | } 105 | } 106 | } 107 | 108 | func readConfig(path string) (*GwentConfig, error) { 109 | var config *GwentConfig 110 | if _, err := toml.DecodeFile(path, &config); err != nil { 111 | return nil, err 112 | } else { 113 | // For missing variables, if say, it was commented out/deleted in the config file 114 | // we use that function to apply their default values (defined in NewGwentConfig()) 115 | // to the config variable. 116 | config = configApplyDefault(*config) 117 | return config, nil 118 | } 119 | } 120 | 121 | // configApplyDefault returns a pointer to a GwentConfig the values are the same for the given GwentConfig parameter 122 | // but zero value fields utilize the values defined in NewGwentConfig() to initialize default values. 123 | func configApplyDefault(config GwentConfig) *GwentConfig { 124 | defaultConfig := NewGwentConfig() 125 | 126 | setDefaultStruct := func(base, current interface{}) { 127 | s2 := reflect.ValueOf(base).Elem() 128 | s := reflect.ValueOf(current).Elem() 129 | 130 | if s2.Type() != s.Type() { 131 | panic("Underlying interface type doesn't match.") 132 | } 133 | 134 | for i := 0; i < s.NumField(); i++ { 135 | f := s.Field(i) 136 | f2 := s2.Field(i) 137 | 138 | if isZero(f) { 139 | f.Set(reflect.Value(f2)) 140 | } 141 | } 142 | } 143 | // Todo: Make the function be able to handle arbitrary struct without having to call the function twice. 144 | setDefaultStruct(&defaultConfig.Database, &config.Database) 145 | setDefaultStruct(&defaultConfig.App, &config.App) 146 | return &config 147 | } 148 | 149 | // Check if the variable is the zero value of its specific type. 150 | func isZero(v reflect.Value) bool { 151 | switch v.Kind() { 152 | case reflect.Func, reflect.Map, reflect.Slice: 153 | return v.IsNil() 154 | case reflect.Array: 155 | z := true 156 | for i := 0; i < v.Len(); i++ { 157 | z = z && isZero(v.Index(i)) 158 | } 159 | return z 160 | case reflect.Struct: 161 | z := true 162 | for i := 0; i < v.NumField(); i++ { 163 | z = z && isZero(v.Field(i)) 164 | } 165 | return z 166 | } 167 | // Compare other types directly: 168 | z := reflect.Zero(v.Type()) 169 | return v.Interface() == z.Interface() 170 | } 171 | -------------------------------------------------------------------------------- /dataLayer/dal/dalCard.go: -------------------------------------------------------------------------------- 1 | package dal 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/dataLayer/models" 5 | "gopkg.in/mgo.v2" 6 | "gopkg.in/mgo.v2/bson" 7 | "regexp" 8 | ) 9 | 10 | type ( 11 | DalCard struct { 12 | collection *mgo.Collection 13 | } 14 | 15 | CardQuery struct { 16 | Name string 17 | Lang string 18 | } 19 | ) 20 | 21 | func NewDalCard(ds *DataStore) *DalCard { 22 | return &DalCard{ds.Collection("cards")} 23 | } 24 | 25 | func (dc DalCard) Fetch(uuid []byte) (*models.Card, error) { 26 | result := models.Card{} 27 | err := dc.collection.Find(bson.M{"uuid": uuid}).One(&result) 28 | return &result, err 29 | } 30 | 31 | func (dc DalCard) FetchAll() (*[]models.Card, error) { 32 | results := []models.Card{} 33 | err := dc.collection.Find(nil).Sort("name.en-US").All(&results) 34 | return &results, err 35 | } 36 | 37 | func (dc DalCard) FetchAllPaging(limit int, offset int) (*[]models.Card, int, error) { 38 | results := []models.Card{} 39 | query := dc.collection.Find(nil).Limit(limit).Sort("name.en-US").Skip(offset) 40 | err := query.All(&results) 41 | count, _ := dc.collection.Find(nil).Count() 42 | // db driver is bugged 43 | //count, _ := query.Count() 44 | return &results, count, err 45 | } 46 | 47 | func (dc DalCard) FetchQueryPaging(limit int, offset int, cardQuery CardQuery) (*[]models.Card, int, error) { 48 | results := []models.Card{} 49 | pattern := `^` + regexp.QuoteMeta(cardQuery.Name) 50 | fieldToSearch := "name." + cardQuery.Lang 51 | 52 | query := dc.collection.Find(bson.M{fieldToSearch: bson.RegEx{pattern, "i"}}).Limit(limit).Sort(fieldToSearch).Skip(offset) 53 | err := query.All(&results) 54 | count, _ := dc.collection.Find(bson.M{fieldToSearch: bson.RegEx{pattern, "i"}}).Count() 55 | // db driver is bugged 56 | //count, _ := query.Count() 57 | return &results, count, err 58 | } 59 | 60 | func (dc DalCard) FetchLeaderPaging(groupID bson.ObjectId, limit int, offset int) (*[]models.Card, error) { 61 | results := []models.Card{} 62 | err := dc.collection.Find(bson.M{"group_id": groupID}).Limit(limit).Sort("name.en-US").Skip(offset).All(&results) 63 | return &results, err 64 | } 65 | 66 | func (dc DalCard) FetchFromFactionPaging(factionID bson.ObjectId, limit int, offset int) (*[]models.Card, error) { 67 | results := []models.Card{} 68 | err := dc.collection.Find(bson.M{"faction_id": factionID}).Limit(limit).Sort("name.en-US").Skip(offset).All(&results) 69 | return &results, err 70 | } 71 | 72 | func (dc DalCard) CountLeader(groupID bson.ObjectId) (int, error) { 73 | result, err := dc.collection.Find(bson.M{"group_id": groupID}).Count() 74 | return result, err 75 | } 76 | 77 | func (dc DalCard) CountFromFaction(factionID bson.ObjectId) (int, error) { 78 | result, err := dc.collection.Find(bson.M{"faction_id": factionID}).Count() 79 | return result, err 80 | } 81 | 82 | func (dc DalCard) FetchFromArray(cardIDs []bson.ObjectId) (*[]models.Card, error) { 83 | results := []models.Card{} 84 | err := dc.collection.Find(bson.M{"_id": bson.M{"$in": cardIDs}}).Sort("name.en-US").All(&results) 85 | 86 | return &results, err 87 | } 88 | 89 | func (dc DalCard) Count() (int, error) { 90 | result, err := dc.collection.Count() 91 | return result, err 92 | } 93 | -------------------------------------------------------------------------------- /dataLayer/dal/dalCategory.go: -------------------------------------------------------------------------------- 1 | package dal 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/dataLayer/models" 5 | "gopkg.in/mgo.v2" 6 | "gopkg.in/mgo.v2/bson" 7 | ) 8 | 9 | type PageQueryType int 10 | 11 | const ( 12 | AllCards PageQueryType = 1 << iota 13 | RarityFiltered 14 | LeaderFiltered 15 | FactionFiltered 16 | ) 17 | 18 | type ( 19 | DalCategory struct { 20 | collection *mgo.Collection 21 | } 22 | ) 23 | 24 | func NewDalCategory(ds *DataStore) *DalCategory { 25 | return &DalCategory{ds.Collection("categories")} 26 | } 27 | 28 | func (dc DalCategory) Fetch(uuid []byte) (*models.Category, error) { 29 | result := models.Category{} 30 | err := dc.collection.Find(bson.M{"uuid": uuid}).One(&result) 31 | return &result, err 32 | } 33 | 34 | func (dc DalCategory) FetchFromArrayID(categoriesID []bson.ObjectId) (*[]models.Category, error) { 35 | results := []models.Category{} 36 | err := dc.collection.Find(bson.M{"_id": bson.M{"$in": categoriesID}}).All(&results) 37 | return &results, err 38 | } 39 | 40 | func (dc DalCategory) FetchAll() (*[]models.Category, error) { 41 | results := []models.Category{} 42 | err := dc.collection.Find(nil).Sort("name").All(&results) 43 | return &results, err 44 | } 45 | 46 | func (dc DalCategory) FetchAllPaging(limit int, offset int) (*[]models.Category, error) { 47 | results := []models.Category{} 48 | err := dc.collection.Find(nil).Limit(limit).Sort("name").Skip(offset).All(&results) 49 | return &results, err 50 | } 51 | 52 | func (dc DalCategory) Count() (int, error) { 53 | result, err := dc.collection.Count() 54 | return result, err 55 | } 56 | -------------------------------------------------------------------------------- /dataLayer/dal/dalFaction.go: -------------------------------------------------------------------------------- 1 | package dal 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/dataLayer/models" 5 | "gopkg.in/mgo.v2" 6 | "gopkg.in/mgo.v2/bson" 7 | ) 8 | 9 | type ( 10 | DalFaction struct { 11 | collection *mgo.Collection 12 | } 13 | ) 14 | 15 | func NewDalFaction(ds *DataStore) *DalFaction { 16 | return &DalFaction{ds.Collection("factions")} 17 | } 18 | 19 | func (dc DalFaction) Fetch(uuid []byte) (*models.Faction, error) { 20 | result := models.Faction{} 21 | err := dc.collection.Find(bson.M{"uuid": uuid}).One(&result) 22 | return &result, err 23 | } 24 | 25 | func (dc DalFaction) FetchWithName(name string) (*models.Faction, error) { 26 | result := models.Faction{} 27 | err := dc.collection.Find(bson.M{"name": name}).One(&result) 28 | return &result, err 29 | } 30 | 31 | func (dc DalFaction) FetchAll() (*[]models.Faction, error) { 32 | results := []models.Faction{} 33 | err := dc.collection.Find(nil).Sort("name").All(&results) 34 | return &results, err 35 | } 36 | 37 | func (dc DalFaction) FetchAllPaging(limit int, offset int) (*[]models.Faction, error) { 38 | results := []models.Faction{} 39 | err := dc.collection.Find(nil).Limit(limit).Sort("name").Skip(offset).All(&results) 40 | return &results, err 41 | } 42 | 43 | func (dc DalFaction) Count() (int, error) { 44 | result, err := dc.collection.Count() 45 | return result, err 46 | } 47 | -------------------------------------------------------------------------------- /dataLayer/dal/dalGroup.go: -------------------------------------------------------------------------------- 1 | package dal 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/dataLayer/models" 5 | "gopkg.in/mgo.v2" 6 | "gopkg.in/mgo.v2/bson" 7 | ) 8 | 9 | type ( 10 | DalGroup struct { 11 | collection *mgo.Collection 12 | } 13 | ) 14 | 15 | func NewDalGroup(ds *DataStore) *DalGroup { 16 | return &DalGroup{ds.Collection("groups")} 17 | } 18 | 19 | func (dc DalGroup) Fetch(uuid []byte) (*models.Group, error) { 20 | result := models.Group{} 21 | err := dc.collection.Find(bson.M{"uuid": uuid}).One(&result) 22 | return &result, err 23 | } 24 | 25 | func (dc DalGroup) FetchWithName(name string) (*models.Group, error) { 26 | result := models.Group{} 27 | err := dc.collection.Find(bson.M{"name": name}).One(&result) 28 | return &result, err 29 | } 30 | 31 | func (dc DalGroup) FetchAll() (*[]models.Group, error) { 32 | results := []models.Group{} 33 | err := dc.collection.Find(nil).Sort("name").All(&results) 34 | return &results, err 35 | } 36 | 37 | func (dc DalGroup) FetchAllPaging(limit int, offset int) (*[]models.Group, error) { 38 | results := []models.Group{} 39 | err := dc.collection.Find(nil).Limit(limit).Sort("name").Skip(offset).All(&results) 40 | return &results, err 41 | } 42 | 43 | func (dc DalGroup) Count() (int, error) { 44 | result, err := dc.collection.Count() 45 | return result, err 46 | } 47 | -------------------------------------------------------------------------------- /dataLayer/dal/dalRarity.go: -------------------------------------------------------------------------------- 1 | package dal 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/dataLayer/models" 5 | "gopkg.in/mgo.v2" 6 | "gopkg.in/mgo.v2/bson" 7 | ) 8 | 9 | type ( 10 | DalRarity struct { 11 | collection *mgo.Collection 12 | } 13 | ) 14 | 15 | func NewDalRarity(ds *DataStore) *DalRarity { 16 | return &DalRarity{ds.Collection("rarities")} 17 | } 18 | 19 | func (dc DalRarity) Fetch(uuid []byte) (*models.Rarity, error) { 20 | result := models.Rarity{} 21 | err := dc.collection.Find(bson.M{"uuid": uuid}).One(&result) 22 | return &result, err 23 | } 24 | 25 | func (dc DalRarity) FetchWithName(name string) (*models.Rarity, error) { 26 | result := models.Rarity{} 27 | err := dc.collection.Find(bson.M{"name": name}).One(&result) 28 | return &result, err 29 | } 30 | 31 | func (dc DalRarity) FetchAll() (*[]models.Rarity, error) { 32 | results := []models.Rarity{} 33 | err := dc.collection.Find(nil).Sort("name").All(&results) 34 | return &results, err 35 | } 36 | 37 | func (dc DalRarity) FetchAllPaging(limit int, offset int) (*[]models.Rarity, error) { 38 | results := []models.Rarity{} 39 | err := dc.collection.Find(nil).Limit(limit).Sort("name").Skip(offset).All(&results) 40 | return &results, err 41 | } 42 | 43 | func (dc DalRarity) Count() (int, error) { 44 | result, err := dc.collection.Count() 45 | return result, err 46 | } 47 | -------------------------------------------------------------------------------- /dataLayer/dal/dalVariation.go: -------------------------------------------------------------------------------- 1 | package dal 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/dataLayer/models" 5 | "gopkg.in/mgo.v2" 6 | "gopkg.in/mgo.v2/bson" 7 | ) 8 | 9 | type ( 10 | DalVariation struct { 11 | collection *mgo.Collection 12 | } 13 | ) 14 | 15 | func NewDalVariation(ds *DataStore) *DalVariation { 16 | return &DalVariation{ds.Collection("variations")} 17 | } 18 | 19 | func (dc DalVariation) Fetch(uuid []byte) (*models.Variation, error) { 20 | result := models.Variation{} 21 | err := dc.collection.Find(bson.M{"uuid": uuid}).One(&result) 22 | return &result, err 23 | } 24 | 25 | func (dc DalVariation) FetchAll() (*[]models.Variation, error) { 26 | results := []models.Variation{} 27 | err := dc.collection.Find(nil).Sort("card_id").All(&results) 28 | return &results, err 29 | } 30 | 31 | func (dc DalVariation) FetchAllPaging(limit int, offset int) (*[]models.Variation, error) { 32 | results := []models.Variation{} 33 | err := dc.collection.Find(nil).Limit(limit).Sort("card_id").Skip(offset).All(&results) 34 | return &results, err 35 | } 36 | 37 | func (dc DalVariation) Count() (int, error) { 38 | result, err := dc.collection.Count() 39 | return result, err 40 | } 41 | 42 | func (dc DalVariation) FetchFromCardID(cardID bson.ObjectId) (*[]models.Variation, error) { 43 | results := []models.Variation{} 44 | err := dc.collection.Find(bson.M{"card_id": cardID}).All(&results) 45 | return &results, err 46 | } 47 | 48 | func (dc DalVariation) FetchCardIDFromRarityPaging(rarityID bson.ObjectId, limit int, offset int) (*[]bson.ObjectId, error) { 49 | var results []struct { 50 | Card_id bson.ObjectId "card_id,omitempty" 51 | } 52 | err := dc.collection.Find(bson.M{"rarity_id": rarityID}).Select(bson.M{"card_id": 1}).Limit(limit).Skip(offset).All(&results) 53 | 54 | var tmp []bson.ObjectId 55 | for _, v := range results { 56 | tmp = append(tmp, v.Card_id) 57 | } 58 | 59 | return &tmp, err 60 | } 61 | 62 | func (dc DalVariation) CountFromRarity(rarityID bson.ObjectId) (int, error) { 63 | result, err := dc.collection.Find(bson.M{"rarity_id": rarityID}).Count() 64 | return result, err 65 | } 66 | -------------------------------------------------------------------------------- /dataLayer/dal/db.go: -------------------------------------------------------------------------------- 1 | package dal 2 | 3 | import ( 4 | "crypto/tls" 5 | "github.com/GwentAPI/gwentapi/configuration" 6 | "gopkg.in/mgo.v2" 7 | "log" 8 | "net" 9 | "time" 10 | ) 11 | 12 | var mainDataStore *DataStore 13 | 14 | type DataStore struct { 15 | session *mgo.Session 16 | } 17 | 18 | func (ds *DataStore) Collection(colName string) *mgo.Collection { 19 | // Use database name specified in DialWithInfo when parameter is empty 20 | // Fallback to "test" if also empty. 21 | return ds.session.DB("").C(colName) 22 | } 23 | 24 | func InitDBWithInfo(info *mgo.DialInfo) { 25 | 26 | _, err := mgo.DialWithInfo(info) 27 | if err != nil { 28 | panic(err) 29 | } 30 | 31 | //Gwentapi = session.DB("gwentapi") 32 | } 33 | 34 | func (ds *DataStore) GetSession() { 35 | if ds.session == nil { 36 | ds.session = mainDataStore.session.Copy() 37 | } /* else { 38 | ds.session.Copy() 39 | }*/ 40 | // Useless 41 | //return ds.session.Copy() 42 | } 43 | 44 | func (ds *DataStore) Close() { 45 | ds.session.Close() 46 | } 47 | 48 | func ShutDown() { 49 | if mainDataStore != nil && mainDataStore.session != nil { 50 | mainDataStore.session.Close() 51 | } 52 | } 53 | 54 | func init() { 55 | config := configuration.GetConfig() 56 | tlsConfig := &tls.Config{} 57 | 58 | addrs := config.Database.Addrs 59 | 60 | dialInfo := &mgo.DialInfo{ 61 | Addrs: addrs, 62 | Database: config.Database.Database, 63 | Source: config.Database.Authentication.AuthenticationDatabase, 64 | Username: config.Database.Authentication.Username, 65 | Password: config.Database.Authentication.Password, 66 | Timeout: 10 * time.Second, 67 | } 68 | 69 | mainDataStore = &DataStore{} 70 | var err error 71 | 72 | if config.Database.UseSSL { 73 | dialInfo.DialServer = func(addr *mgo.ServerAddr) (net.Conn, error) { 74 | conn, err := tls.Dial("tcp", addr.String(), tlsConfig) 75 | return conn, err 76 | } 77 | } 78 | 79 | log.Println("Attempting to establish a database connection...") 80 | 81 | mainDataStore.session, err = mgo.DialWithInfo(dialInfo) 82 | if err != nil { 83 | log.Fatal("Failed to establish mongoDB connection: ", err) 84 | } 85 | mainDataStore.session.SetMode(mgo.Monotonic, true) 86 | mainDataStore.session.SetSocketTimeout(10 * time.Second) 87 | log.Println("Database connection established.") 88 | } 89 | -------------------------------------------------------------------------------- /dataLayer/factory/FactoryCard.go: -------------------------------------------------------------------------------- 1 | package factory 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/app" 5 | "github.com/GwentAPI/gwentapi/dataLayer/dal" 6 | "github.com/GwentAPI/gwentapi/dataLayer/models" 7 | "github.com/GwentAPI/gwentapi/helpers" 8 | "time" 9 | ) 10 | 11 | func CreateCard(c *models.Card, ds *dal.DataStore, locale string) (*app.GwentapiCard, error) { 12 | uuid := helpers.EncodeUUID(c.UUID) 13 | dalCat := dal.NewDalCategory(ds) 14 | dalV := dal.NewDalVariation(ds) 15 | dalG := dal.NewDalGroup(ds) 16 | dalF := dal.NewDalFaction(ds) 17 | 18 | group, errG := dalG.FetchWithName(c.Group) 19 | if errG != nil { 20 | return nil, errG 21 | } 22 | groupMedia, _ := CreateGroupLink(group) 23 | 24 | faction, errF := dalF.FetchWithName(c.Faction) 25 | if errF != nil { 26 | return nil, errF 27 | } 28 | factionMedia, _ := CreateFactionLink(faction) 29 | 30 | categories, errC := dalCat.FetchFromArrayID(c.Categories_id) 31 | if errC != nil { 32 | return nil, errC 33 | } 34 | categoriesLinkMedia := make(app.GwentapiCategoryLinkCollection, len(*categories)) 35 | for i, category := range *categories { 36 | cl, _ := CreateCategoryLink(&category) 37 | categoriesLinkMedia[i] = cl 38 | } 39 | 40 | variations, errV := dalV.FetchFromCardID(c.ID) 41 | if errV != nil { 42 | return nil, errV 43 | } 44 | variationsLinkMedia := make(app.GwentapiVariationLinkCollection, len(*variations)) 45 | for i, variation := range *variations { 46 | cv, _ := CreateVariationLink(&variation, c.UUID, ds) 47 | variationsLinkMedia[i] = cv 48 | } 49 | 50 | name := c.Name[locale] 51 | flavor := c.Flavor[locale] 52 | info := c.Info[locale] 53 | 54 | result := &app.GwentapiCard{ 55 | Name: name, 56 | Categories: categoriesLinkMedia, 57 | Flavor: &flavor, 58 | Info: &info, 59 | Strength: c.Strength, 60 | Positions: c.Positions, 61 | Faction: factionMedia, 62 | Group: groupMedia, 63 | Variations: variationsLinkMedia, 64 | Href: helpers.CardURL(uuid), 65 | UUID: uuid, 66 | } 67 | 68 | return result, nil 69 | } 70 | 71 | func CreatePageCard(c *[]models.Card, url string, resultCount int, limit int, offset int, locale string) (*app.GwentapiPagecard, time.Time, error) { 72 | results := make(app.GwentapiCardLinkCollection, len(*c)) 73 | lastModified := time.Time{} 74 | 75 | for i, result := range *c { 76 | uuid := helpers.EncodeUUID(result.UUID) 77 | cl := &app.GwentapiCardLink{ 78 | Href: helpers.CardURL(uuid), 79 | Name: result.Name[locale], 80 | } 81 | 82 | if lastModified.Before(result.Last_Modified) { 83 | lastModified = result.Last_Modified 84 | } 85 | 86 | results[i] = cl 87 | } 88 | 89 | prev, next := helpers.GeneratePrevNextPageHref(resultCount, limit, offset, helpers.CardURL(url)) 90 | 91 | page := &app.GwentapiPagecard{ 92 | Count: resultCount, 93 | Next: next, 94 | Previous: prev, 95 | Results: results, 96 | } 97 | return page, lastModified, nil 98 | } 99 | -------------------------------------------------------------------------------- /dataLayer/factory/FactoryCategory.go: -------------------------------------------------------------------------------- 1 | package factory 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/app" 5 | "github.com/GwentAPI/gwentapi/dataLayer/models" 6 | "github.com/GwentAPI/gwentapi/helpers" 7 | ) 8 | 9 | func CreateCategory(c *models.Category) (*app.GwentapiCategory, error) { 10 | uuid := helpers.EncodeUUID(c.UUID) 11 | 12 | result := &app.GwentapiCategory{ 13 | Name: c.Name, 14 | Href: helpers.CategoryURL(uuid), 15 | UUID: uuid, 16 | } 17 | 18 | return result, nil 19 | } 20 | 21 | func CreateCategoryLink(c *models.Category) (*app.GwentapiCategoryLink, error) { 22 | uuid := helpers.EncodeUUID(c.UUID) 23 | categoryLink := &app.GwentapiCategoryLink{ 24 | Href: helpers.CategoryURL(uuid), 25 | Name: c.Name, 26 | } 27 | return categoryLink, nil 28 | } 29 | -------------------------------------------------------------------------------- /dataLayer/factory/FactoryFaction.go: -------------------------------------------------------------------------------- 1 | package factory 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/app" 5 | "github.com/GwentAPI/gwentapi/dataLayer/models" 6 | "github.com/GwentAPI/gwentapi/helpers" 7 | ) 8 | 9 | func CreateFaction(f *models.Faction) (*app.GwentapiFaction, error) { 10 | uuid := helpers.EncodeUUID(f.UUID) 11 | 12 | result := &app.GwentapiFaction{ 13 | Name: f.Name, 14 | Href: helpers.FactionURL(uuid), 15 | UUID: uuid, 16 | } 17 | 18 | return result, nil 19 | } 20 | 21 | func CreateFactionLink(f *models.Faction) (*app.GwentapiFactionLink, error) { 22 | uuid := helpers.EncodeUUID(f.UUID) 23 | factionLink := &app.GwentapiFactionLink{ 24 | Href: helpers.FactionURL(uuid), 25 | Name: f.Name, 26 | } 27 | return factionLink, nil 28 | } 29 | -------------------------------------------------------------------------------- /dataLayer/factory/FactoryGroup.go: -------------------------------------------------------------------------------- 1 | package factory 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/app" 5 | "github.com/GwentAPI/gwentapi/dataLayer/models" 6 | "github.com/GwentAPI/gwentapi/helpers" 7 | ) 8 | 9 | func CreateGroup(g *models.Group) (*app.GwentapiGroup, error) { 10 | uuid := helpers.EncodeUUID(g.UUID) 11 | 12 | result := &app.GwentapiGroup{ 13 | Name: g.Name, 14 | Href: helpers.GroupURL(uuid), 15 | UUID: uuid, 16 | } 17 | 18 | return result, nil 19 | } 20 | 21 | func CreateGroupLink(g *models.Group) (*app.GwentapiGroupLink, error) { 22 | uuid := helpers.EncodeUUID(g.UUID) 23 | groupLink := &app.GwentapiGroupLink{ 24 | Href: helpers.GroupURL(uuid), 25 | Name: g.Name, 26 | } 27 | return groupLink, nil 28 | } 29 | -------------------------------------------------------------------------------- /dataLayer/factory/FactoryRarity.go: -------------------------------------------------------------------------------- 1 | package factory 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/app" 5 | "github.com/GwentAPI/gwentapi/dataLayer/models" 6 | "github.com/GwentAPI/gwentapi/helpers" 7 | ) 8 | 9 | func CreateRarity(r *models.Rarity) (*app.GwentapiRarity, error) { 10 | uuid := helpers.EncodeUUID(r.UUID) 11 | 12 | result := &app.GwentapiRarity{ 13 | Name: r.Name, 14 | Href: helpers.RarityURL(uuid), 15 | UUID: uuid, 16 | } 17 | 18 | return result, nil 19 | } 20 | 21 | func CreateRarityLink(r *models.Rarity) (*app.GwentapiRarityLink, error) { 22 | uuid := helpers.EncodeUUID(r.UUID) 23 | rarityLink := &app.GwentapiRarityLink{ 24 | Href: helpers.RarityURL(uuid), 25 | Name: r.Name, 26 | } 27 | return rarityLink, nil 28 | } 29 | -------------------------------------------------------------------------------- /dataLayer/factory/FactoryVariation.go: -------------------------------------------------------------------------------- 1 | package factory 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/app" 5 | "github.com/GwentAPI/gwentapi/dataLayer/dal" 6 | "github.com/GwentAPI/gwentapi/dataLayer/models" 7 | "github.com/GwentAPI/gwentapi/helpers" 8 | "time" 9 | ) 10 | 11 | func CreateVariation(v *models.Variation, cardID []byte, ds *dal.DataStore) (*app.GwentapiVariation, error) { 12 | variationUuid := helpers.EncodeUUID(v.UUID) 13 | cardUUID := helpers.EncodeUUID(cardID) 14 | dalR := dal.NewDalRarity(ds) 15 | 16 | rarity, err := dalR.FetchWithName(v.Rarity) 17 | if err != nil { 18 | return nil, err 19 | } 20 | rarityMedia, _ := CreateRarityLink(rarity) 21 | 22 | craft := &app.CostType{ 23 | Normal: v.Craft.Normal, 24 | Premium: v.Craft.Premium, 25 | } 26 | 27 | mill := &app.CostType{ 28 | Normal: v.Mill.Normal, 29 | Premium: v.Mill.Premium, 30 | } 31 | 32 | //fullSizeUrl := helpers.MediaURL(v.Art.FullsizeImage) 33 | //thumbnailSizeUrl := helpers.MediaURL(v.Art.ThumbnailImage) 34 | mediumSizeUrl := helpers.MediaURL(v.Art.MediumsizeImage) 35 | 36 | art := &app.ArtType{ 37 | //FullsizeImage: &fullSizeUrl, 38 | MediumsizeImage: mediumSizeUrl, 39 | ThumbnailImage: mediumSizeUrl, 40 | } 41 | 42 | if v.Art.Artist != "" { 43 | artistName := v.Art.Artist 44 | art.Artist = &artistName 45 | } 46 | 47 | result := &app.GwentapiVariation{ 48 | Availability: v.Availability, 49 | Rarity: rarityMedia, 50 | Craft: craft, 51 | Mill: mill, 52 | Art: art, 53 | Href: helpers.VariationURL(cardUUID, variationUuid), 54 | UUID: variationUuid, 55 | } 56 | 57 | return result, nil 58 | } 59 | 60 | func CreateVariationLink(v *models.Variation, cardID []byte, ds *dal.DataStore) (*app.GwentapiVariationLink, error) { 61 | variationUuid := helpers.EncodeUUID(v.UUID) 62 | cardUUID := helpers.EncodeUUID(cardID) 63 | dalR := dal.NewDalRarity(ds) 64 | 65 | rarity, err := dalR.FetchWithName(v.Rarity) 66 | if err != nil { 67 | return nil, err 68 | } 69 | rarityMedia, _ := CreateRarityLink(rarity) 70 | 71 | result := &app.GwentapiVariationLink{ 72 | Availability: v.Availability, 73 | Rarity: rarityMedia, 74 | Href: helpers.VariationURL(cardUUID, variationUuid), 75 | } 76 | 77 | return result, nil 78 | } 79 | 80 | func CreateVariationCollection(v *[]models.Variation, cardID []byte, ds *dal.DataStore) (app.GwentapiVariationCollection, time.Time, error) { 81 | variations := make(app.GwentapiVariationCollection, len(*v)) 82 | lastModified := time.Time{} 83 | 84 | for i, variation := range *v { 85 | v, err := CreateVariation(&variation, cardID, ds) 86 | if err != nil { 87 | return nil, time.Time{}, err 88 | } 89 | if lastModified.Before(variation.Last_Modified) { 90 | lastModified = variation.Last_Modified 91 | } 92 | variations[i] = v 93 | } 94 | 95 | return variations, lastModified, nil 96 | } 97 | -------------------------------------------------------------------------------- /dataLayer/models/card.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "gopkg.in/mgo.v2/bson" 5 | "time" 6 | ) 7 | 8 | type Card struct { 9 | ID bson.ObjectId "_id,omitempty" 10 | Categories []string "categories" 11 | Faction string "faction" 12 | Flavor map[string]string "flavor,omitempty" 13 | Info map[string]string "info,omitempty" 14 | Strength *int "strength" 15 | Name map[string]string "name" 16 | Positions []string "positions" 17 | Faction_id bson.ObjectId "faction_id,omitempty" 18 | Group string "group" 19 | Group_id bson.ObjectId "group_id,omitempty" 20 | Categories_id []bson.ObjectId "categories_id,omitempty" 21 | UUID []byte "uuid" 22 | Last_Modified time.Time "last_modified" 23 | } 24 | -------------------------------------------------------------------------------- /dataLayer/models/category.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "gopkg.in/mgo.v2/bson" 5 | "time" 6 | ) 7 | 8 | type Category struct { 9 | ID bson.ObjectId "_id,omitempty" 10 | Name string 11 | UUID []byte 12 | Last_Modified time.Time "last_modified" 13 | } 14 | -------------------------------------------------------------------------------- /dataLayer/models/faction.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "gopkg.in/mgo.v2/bson" 5 | "time" 6 | ) 7 | 8 | type Faction struct { 9 | ID bson.ObjectId "_id,omitempty" 10 | Name string 11 | UUID []byte 12 | Last_Modified time.Time "last_modified" 13 | } 14 | -------------------------------------------------------------------------------- /dataLayer/models/group.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "gopkg.in/mgo.v2/bson" 5 | "time" 6 | ) 7 | 8 | type Group struct { 9 | ID bson.ObjectId "_id,omitempty" 10 | Name string 11 | UUID []byte 12 | Last_Modified time.Time "last_modified" 13 | } 14 | -------------------------------------------------------------------------------- /dataLayer/models/rarity.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "gopkg.in/mgo.v2/bson" 5 | "time" 6 | ) 7 | 8 | type Rarity struct { 9 | ID bson.ObjectId "_id,omitempty" 10 | Name string 11 | UUID []byte 12 | Last_Modified time.Time "last_modified" 13 | } 14 | -------------------------------------------------------------------------------- /dataLayer/models/variation.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "gopkg.in/mgo.v2/bson" 5 | "time" 6 | ) 7 | 8 | type Variation struct { 9 | ID bson.ObjectId "_id,omitempty" 10 | Card_id bson.ObjectId "card_id,omitempty" 11 | Rarity_id bson.ObjectId "rarity_id,omitempty" 12 | UUID []byte 13 | Availability string 14 | Rarity string 15 | Craft Cost "craft,omitempty" 16 | Mill Cost "mill,omitempty" 17 | Art Art "art,omitempty" 18 | Last_Modified time.Time "last_modified" 19 | } 20 | 21 | type Cost struct { 22 | Normal int 23 | Premium int 24 | } 25 | 26 | type Art struct { 27 | Artist string "artist,omitempty" 28 | FullsizeImage *string "fullsizeImage" 29 | MediumsizeImage string "mediumsizeImage" 30 | ThumbnailImage string "thumbnailImage" 31 | } 32 | -------------------------------------------------------------------------------- /design/api_definition.go: -------------------------------------------------------------------------------- 1 | package design 2 | 3 | import ( 4 | . "github.com/goadesign/goa/design" 5 | . "github.com/goadesign/goa/design/apidsl" 6 | ) 7 | 8 | var _ = API("gwentapi", func() { 9 | Title("Gwent API") 10 | Description("A consumption-only API of all Gwent data") 11 | Version("0.9.1") 12 | Contact(func() { 13 | Name("Tristan S.") 14 | Email("api.gwent@gmail.com") 15 | URL("https://twitter.com/GwentAPI") 16 | }) 17 | License(func() { 18 | Name("The textual information presented through this API about GWENT: The Witcher Card Game is copyrighted by CD Projekt RED") 19 | }) 20 | BasePath("/") 21 | Host("api.gwentapi.com") 22 | Scheme("https") 23 | Produces("application/json") 24 | }) 25 | -------------------------------------------------------------------------------- /design/media_types_definition.go: -------------------------------------------------------------------------------- 1 | package design 2 | 3 | import ( 4 | . "github.com/goadesign/goa/design" 5 | . "github.com/goadesign/goa/design/apidsl" 6 | ) 7 | 8 | var ResourceMedia = MediaType("application/vnd.gwentapi.resource+json", func() { 9 | Description("Listing of all available resource endpoint and a link to the api definition") 10 | ContentType("application/json; charset=utf-8") 11 | Attributes(func() { 12 | Attribute("cards", String, "API href for making requests on cards", func() { 13 | Format("uri") 14 | }) 15 | Attribute("factions", String, "API href for making requests on factions", func() { 16 | Format("uri") 17 | }) 18 | Attribute("rarities", String, "API href for making requests on rarities", func() { 19 | Format("uri") 20 | }) 21 | Attribute("categories", String, "API href for making requests on categories", func() { 22 | Format("uri") 23 | }) 24 | Attribute("groups", String, "API href for making requests on groups", func() { 25 | Format("uri") 26 | }) 27 | Attribute("swagger", String, "Href linking to the swagger definition", func() { 28 | Format("uri") 29 | }) 30 | Attribute("version", String, "Semver of the software that is currently running", func() { 31 | Example("v0.5.5-rc.2") 32 | }) 33 | 34 | Required("cards", "factions", "rarities", "categories", "groups", "swagger", "version") 35 | }) 36 | 37 | View("default", func() { 38 | Attribute("cards") 39 | Attribute("factions") 40 | Attribute("rarities") 41 | Attribute("categories") 42 | Attribute("groups") 43 | Attribute("swagger") 44 | Attribute("version") 45 | }) 46 | }) 47 | 48 | var PageCard = MediaType("application/vnd.gwentapi.pageCard+json", func() { 49 | Description("Paginated card") 50 | ContentType("application/json; charset=utf-8") 51 | Attributes(func() { 52 | Attribute("count", Integer, "Total number of cards stored in the database", func() { 53 | Example(280) 54 | }) 55 | Attribute("previous", String, "Href to the previous page", func() { 56 | Format("uri") 57 | }) 58 | Attribute("next", String, "Href to the next page", func() { 59 | Format("uri") 60 | }) 61 | Attribute("results", CollectionOf(CardMedia), "Results of the page containing cards") 62 | 63 | Required("count", "results") 64 | }) 65 | 66 | Links(func() { 67 | Link("results") 68 | }) 69 | 70 | View("default", func() { 71 | Attribute("count") 72 | Attribute("previous") 73 | Attribute("next") 74 | Attribute("results", func() { 75 | View("link") 76 | }) 77 | }) 78 | }) 79 | 80 | var VariationMedia = MediaType("application/vnd.gwentapi.variation+json", func() { 81 | Description("Variation of a card containing artworks, crafting/milling cost, set availability, and rarity.") 82 | ContentType("application/json; charset=utf-8") 83 | Attributes(func() { 84 | Attribute("uuid", String, "Unique artwork UUID", func() { 85 | Example("pcN4QMTlTAaIOwicgNwtKA") 86 | }) 87 | Attribute("href", String, "API href for making requests on the artwork", func() { 88 | Format("uri") 89 | }) 90 | Attribute("art", ArtType, "Artworks of the card variation.") 91 | Attribute("mill", CostType, "Milling cost of the card variation.") 92 | Attribute("craft", CostType, "Crafting cost of the card variation.") 93 | Attribute("availability", String, "Describe from which set the variation comes from and its general availability", func() { 94 | Example("BaseSet") 95 | }) 96 | Attribute("rarity", RarityMedia, "Rarity of the card") 97 | 98 | Required("uuid", "href", "availability", "rarity") 99 | }) 100 | 101 | //Links(func() { 102 | // Link("card") 103 | //}) 104 | 105 | View("default", func() { 106 | Attribute("uuid") 107 | Attribute("href") 108 | Attribute("art") 109 | Attribute("mill") 110 | Attribute("craft") 111 | Attribute("availability") 112 | Attribute("rarity", func() { 113 | View("link") 114 | }) 115 | }) 116 | 117 | View("link", func() { 118 | Attribute("href") 119 | Attribute("availability") 120 | Attribute("rarity", func() { 121 | View("link") 122 | }) 123 | }) 124 | }) 125 | 126 | var CardMedia = MediaType("application/vnd.gwentapi.card+json", func() { 127 | Description("A card") 128 | ContentType("application/json; charset=utf-8") 129 | Attributes(func() { 130 | Attribute("uuid", String, "Unique card UUID", func() { 131 | Example("oe6UPiaDSNyI-630fYz4LA") 132 | }) 133 | Attribute("href", String, "API href for making requests on the card", func() { 134 | Format("uri") 135 | }) 136 | Attribute("name", String, "Name of the card", func() { 137 | Example("Arachas") 138 | }) 139 | Attribute("group", GroupMedia, "Group of the card") 140 | Attribute("faction", FactionMedia, "Faction of the card") 141 | 142 | Attribute("categories", CollectionOf(CategoryMedia), "Categories of the card") 143 | Attribute("positions", ArrayOf(String), "Positions where the card can be played", func() { 144 | Example([...]string{"Ranged"}) 145 | }) 146 | 147 | Attribute("strength", Integer, "Strength of the card", func() { 148 | Example(3) 149 | }) 150 | Attribute("info", String, "Text of the card detailing its abilities and how it plays", func() { 151 | Example("Deploy: Play all Arachasae from your Deck.") 152 | }) 153 | Attribute("flavor", String, "Flavor text of the card", func() { 154 | Example("Ugly – Nature's Way of saying stay away.") 155 | }) 156 | Attribute("variations", CollectionOf(VariationMedia), "Variations of the card") 157 | 158 | Required("uuid", "href", "name", "group", "faction", "variations") 159 | }) 160 | 161 | Links(func() { 162 | Link("group") 163 | Link("faction") 164 | Link("categories") 165 | Link("variations") 166 | }) 167 | 168 | View("default", func() { 169 | Attribute("uuid") 170 | Attribute("href") 171 | Attribute("name") 172 | Attribute("group", func() { 173 | View("link") 174 | }) 175 | Attribute("faction", func() { 176 | View("link") 177 | }) 178 | Attribute("categories", func() { 179 | View("link") 180 | }) 181 | Attribute("positions") 182 | Attribute("strength") 183 | Attribute("info") 184 | Attribute("flavor") 185 | Attribute("variations", func() { 186 | View("link") 187 | }) 188 | }) 189 | 190 | View("link", func() { 191 | Attribute("name") 192 | Attribute("href") 193 | }) 194 | 195 | }) 196 | 197 | var FactionMedia = MediaType("application/vnd.gwentapi.faction+json", func() { 198 | Description("A card faction") 199 | ContentType("application/json; charset=utf-8") 200 | Attributes(func() { 201 | Attribute("uuid", String, "Unique faction UUID", func() { 202 | Example("9wM9vGWiRzCvEwSLnLfY1w") 203 | }) 204 | Attribute("href", String, "API href for making requests on the faction", func() { 205 | Format("uri") 206 | }) 207 | Attribute("name", String, "Name of the faction", func() { 208 | Example("Monster") 209 | }) 210 | 211 | Required("uuid", "href", "name") 212 | }) 213 | View("default", func() { 214 | Attribute("uuid") 215 | Attribute("href") 216 | Attribute("name") 217 | }) 218 | 219 | View("link", func() { 220 | Attribute("name") 221 | Attribute("href") 222 | }) 223 | }) 224 | 225 | var RarityMedia = MediaType("application/vnd.gwentapi.rarity+json", func() { 226 | Description("A card rarity") 227 | ContentType("application/json; charset=utf-8") 228 | Attributes(func() { 229 | Attribute("uuid", String, "Unique rarity UUID", func() { 230 | Example("TPCvIPOjRjO0s7Jfeo1NtA") 231 | }) 232 | Attribute("href", String, "API href for making requests on the rarity", func() { 233 | Format("uri") 234 | }) 235 | Attribute("name", String, "Name of the rarity", func() { 236 | Example("Common") 237 | }) 238 | 239 | Required("uuid", "href", "name") 240 | }) 241 | 242 | View("default", func() { 243 | Attribute("uuid") 244 | Attribute("href") 245 | Attribute("name") 246 | }) 247 | 248 | View("link", func() { 249 | Attribute("name") 250 | Attribute("href") 251 | }) 252 | }) 253 | 254 | var GroupMedia = MediaType("application/vnd.gwentapi.group+json", func() { 255 | Description("A card group") 256 | ContentType("application/json; charset=utf-8") 257 | Attributes(func() { 258 | Attribute("uuid", String, "Unique group UUID", func() { 259 | Example("GbmwHbkcQniDKJq6rKz-bQ") 260 | }) 261 | Attribute("href", String, "API href for making requests on the group", func() { 262 | Format("uri") 263 | }) 264 | Attribute("name", String, "Name of the group", func() { 265 | Example("Bronze") 266 | }) 267 | 268 | Required("uuid", "href", "name") 269 | }) 270 | 271 | View("default", func() { 272 | Attribute("uuid") 273 | Attribute("href") 274 | Attribute("name") 275 | }) 276 | 277 | View("link", func() { 278 | Attribute("name") 279 | Attribute("href") 280 | }) 281 | }) 282 | 283 | var CategoryMedia = MediaType("application/vnd.gwentapi.category+json", func() { 284 | Description("A card category") 285 | ContentType("application/json; charset=utf-8") 286 | Attributes(func() { 287 | Attribute("uuid", String, "Unique category UUID", func() { 288 | Example("0PcjdpZ6QR2NKutLFGx-oQ") 289 | }) 290 | Attribute("href", String, "API href for making requests on the category", func() { 291 | Format("uri") 292 | }) 293 | Attribute("name", String, "Name of the category", func() { 294 | Example("Insectoid") 295 | }) 296 | 297 | Required("uuid", "href", "name") 298 | }) 299 | 300 | View("default", func() { 301 | Attribute("uuid") 302 | Attribute("href") 303 | Attribute("name") 304 | }) 305 | 306 | View("link", func() { 307 | Attribute("name") 308 | Attribute("href") 309 | }) 310 | }) 311 | -------------------------------------------------------------------------------- /design/resources_definition.go: -------------------------------------------------------------------------------- 1 | package design 2 | 3 | import ( 4 | . "github.com/goadesign/goa/design" 5 | . "github.com/goadesign/goa/design/apidsl" 6 | ) 7 | 8 | var _ = Resource("index", func() { 9 | DefaultMedia(ResourceMedia) 10 | BasePath("/v0") 11 | 12 | Action("show", func() { 13 | Description("Listing of all supported resources endpoint") 14 | Routing(GET("")) 15 | Response(OK) 16 | Response(NotFound) 17 | }) 18 | }) 19 | 20 | var _ = Resource("faction", func() { 21 | 22 | DefaultMedia(FactionMedia) 23 | BasePath("/v0/factions") 24 | 25 | Response(InternalServerError) 26 | Response(NotModified) 27 | 28 | Headers(func() { 29 | Header("If-Modified-Since", func() { 30 | Description("DateTime in RFC1123 format.") 31 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 32 | }) 33 | }) 34 | 35 | Action("list", func() { 36 | Routing(GET("")) 37 | Description("Return all factions.") 38 | 39 | Response(OK, CollectionOf(FactionMedia, func() { 40 | ContentType("application/json; type=collection; charset=utf-8") 41 | }), func() { 42 | Headers(func() { 43 | Header("Last-Modified", func() { 44 | Description("DateTime in RFC1123 format.") 45 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 46 | }) 47 | }) 48 | }) 49 | Response(NotFound) 50 | }) 51 | 52 | Action("show", func() { 53 | Description("Return faction with given id.") 54 | Routing(GET("/:factionID")) 55 | Params(func() { 56 | Param("factionID", String, "Faction ID") 57 | }) 58 | Response(OK, func() { 59 | Headers(func() { 60 | Header("Last-Modified", func() { 61 | Description("DateTime in RFC1123 format.") 62 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 63 | }) 64 | }) 65 | }) 66 | Response(NotFound) 67 | 68 | }) 69 | }) 70 | 71 | var _ = Resource("rarity", func() { 72 | DefaultMedia(RarityMedia) 73 | BasePath("/v0/rarities") 74 | 75 | Response(InternalServerError) 76 | Response(NotModified) 77 | 78 | Headers(func() { 79 | Header("If-Modified-Since", func() { 80 | Description("DateTime in RFC1123 format.") 81 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 82 | }) 83 | }) 84 | 85 | Action("list", func() { 86 | Routing(GET("")) 87 | Description("Return all rarities.") 88 | 89 | Response(OK, CollectionOf(RarityMedia, func() { 90 | ContentType("application/json; type=collection; charset=utf-8") 91 | }), func() { 92 | Headers(func() { 93 | Header("Last-Modified", func() { 94 | Description("DateTime in RFC1123 format.") 95 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 96 | }) 97 | }) 98 | }) 99 | Response(NotFound) 100 | }) 101 | 102 | Action("show", func() { 103 | Description("Return rarity with given id.") 104 | Routing(GET("/:rarityID")) 105 | Params(func() { 106 | Param("rarityID", String, "Rarity ID") 107 | }) 108 | Response(OK, func() { 109 | Headers(func() { 110 | Header("Last-Modified", func() { 111 | Description("DateTime in RFC1123 format.") 112 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 113 | }) 114 | }) 115 | }) 116 | Response(NotFound) 117 | }) 118 | }) 119 | 120 | var _ = Resource("group", func() { 121 | DefaultMedia(GroupMedia) 122 | BasePath("/v0/groups") 123 | 124 | Response(InternalServerError) 125 | Response(NotModified) 126 | 127 | Headers(func() { 128 | Header("If-Modified-Since", func() { 129 | Description("DateTime in RFC1123 format.") 130 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 131 | }) 132 | }) 133 | 134 | Action("list", func() { 135 | Routing(GET("")) 136 | Description("Return all card groups.") 137 | 138 | Response(OK, CollectionOf(GroupMedia, func() { 139 | ContentType("application/json; type=collection; charset=utf-8") 140 | }), func() { 141 | Headers(func() { 142 | Header("Last-Modified", func() { 143 | Description("DateTime in RFC1123 format.") 144 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 145 | }) 146 | }) 147 | }) 148 | Response(NotFound) 149 | }) 150 | 151 | Action("show", func() { 152 | Description("Return card group with given id.") 153 | Routing(GET("/:groupID")) 154 | Params(func() { 155 | Param("groupID", String, "Card group ID") 156 | }) 157 | Response(OK, func() { 158 | Headers(func() { 159 | Header("Last-Modified", func() { 160 | Description("DateTime in RFC1123 format.") 161 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 162 | }) 163 | }) 164 | }) 165 | Response(NotFound) 166 | }) 167 | }) 168 | 169 | var _ = Resource("category", func() { 170 | DefaultMedia(CategoryMedia) 171 | BasePath("/v0/categories") 172 | 173 | Response(InternalServerError) 174 | Response(NotModified) 175 | 176 | Headers(func() { 177 | Header("If-Modified-Since", func() { 178 | Description("DateTime in RFC1123 format.") 179 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 180 | }) 181 | }) 182 | 183 | Action("list", func() { 184 | Routing(GET("")) 185 | Description("Return all card categories.") 186 | 187 | Response(OK, CollectionOf(CategoryMedia, func() { 188 | ContentType("application/json; type=collection; charset=utf-8") 189 | }), func() { 190 | Headers(func() { 191 | Header("Last-Modified", func() { 192 | Description("DateTime in RFC1123 format.") 193 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 194 | }) 195 | }) 196 | }) 197 | Response(NotFound) 198 | }) 199 | 200 | Action("show", func() { 201 | Description("Return card category with given id.") 202 | Routing(GET("/:categoryID")) 203 | Params(func() { 204 | Param("categoryID", String, "Card category ID") 205 | }) 206 | Response(OK, func() { 207 | Headers(func() { 208 | Header("Last-Modified", func() { 209 | Description("DateTime in RFC1123 format.") 210 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 211 | }) 212 | }) 213 | }) 214 | Response(NotFound) 215 | }) 216 | }) 217 | 218 | var _ = Resource("card", func() { 219 | DefaultMedia(CardMedia) 220 | BasePath("/v0/cards") 221 | 222 | Response(InternalServerError) 223 | Response(NotModified) 224 | 225 | Headers(func() { 226 | Header("If-Modified-Since", func() { 227 | Description("DateTime in RFC1123 format.") 228 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 229 | }) 230 | }) 231 | 232 | Params(func() { 233 | Param("lang", String, func() { 234 | Description("Localization of the returned resource") 235 | Enum("en-US", "de-DE", "es-ES", "es-MX", "fr-FR", "it-IT", "ja-JP", "pl-PL", "pt-BR", "ru-RU") 236 | Default("en-US") 237 | }) 238 | }) 239 | 240 | Action("list", func() { 241 | Routing(GET("")) 242 | Description("Return a page of cards.") 243 | Params(func() { 244 | Param("limit", Integer, func() { 245 | Description("Number of cards to receive") 246 | Minimum(1) 247 | Default(20) 248 | }) 249 | Param("offset", Integer, func() { 250 | Description("Offset of the starting count") 251 | Default(0) 252 | Minimum(0) 253 | }) 254 | Param("name", String, func() { 255 | Description("Query to search for cards with the name starting by the entered value") 256 | MinLength(3) 257 | MaxLength(100) 258 | }) 259 | 260 | }) 261 | Response(OK, PageCard, func() { 262 | Headers(func() { 263 | Header("Last-Modified", func() { 264 | Description("DateTime in RFC1123 format.") 265 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 266 | }) 267 | }) 268 | }) 269 | Response(NotFound) 270 | }) 271 | 272 | Action("show", func() { 273 | Description("Return card with given id.") 274 | Routing(GET("/:cardID")) 275 | 276 | Params(func() { 277 | Param("cardID", String, "Card ID") 278 | }) 279 | Response(OK, func() { 280 | Headers(func() { 281 | Header("Last-Modified", func() { 282 | Description("DateTime in RFC1123 format.") 283 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 284 | }) 285 | }) 286 | }) 287 | Response(NotFound) 288 | }) 289 | 290 | Action("cardFaction", func() { 291 | Description("Return all cards with given faction id.") 292 | Routing(GET("/factions/:factionID")) 293 | 294 | Params(func() { 295 | Param("factionID", String, "Faction ID") 296 | Param("limit", Integer, func() { 297 | Description("Number of cards to receive") 298 | Minimum(1) 299 | Default(20) 300 | }) 301 | Param("offset", Integer, func() { 302 | Description("Offset of the starting count") 303 | Default(0) 304 | Minimum(0) 305 | }) 306 | }) 307 | Response(OK, PageCard, func() { 308 | Headers(func() { 309 | Header("Last-Modified", func() { 310 | Description("DateTime in RFC1123 format.") 311 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 312 | }) 313 | }) 314 | }) 315 | Response(NotFound) 316 | }) 317 | 318 | Action("cardRarity", func() { 319 | Description("Return all cards with given rarity id.") 320 | Routing(GET("/rarities/:rarityID")) 321 | 322 | Params(func() { 323 | Param("rarityID", String, "Rarity ID") 324 | Param("limit", Integer, func() { 325 | Description("Number of cards to receive") 326 | Minimum(1) 327 | Default(20) 328 | }) 329 | Param("offset", Integer, func() { 330 | Description("Offset of the starting count") 331 | Default(0) 332 | Minimum(0) 333 | }) 334 | }) 335 | Response(OK, PageCard, func() { 336 | Headers(func() { 337 | Header("Last-Modified", func() { 338 | Description("DateTime in RFC1123 format.") 339 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 340 | }) 341 | }) 342 | }) 343 | Response(NotFound) 344 | }) 345 | 346 | Action("cardLeader", func() { 347 | Description("Return all leader cards.") 348 | Routing(GET("/leaders")) 349 | 350 | Params(func() { 351 | Param("limit", Integer, func() { 352 | Description("Number of cards to receive") 353 | Minimum(1) 354 | Default(20) 355 | }) 356 | Param("offset", Integer, func() { 357 | Description("Offset of the starting count") 358 | Default(0) 359 | Minimum(0) 360 | }) 361 | }) 362 | 363 | Response(OK, PageCard, func() { 364 | Headers(func() { 365 | Header("Last-Modified", func() { 366 | Description("DateTime in RFC1123 format.") 367 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 368 | }) 369 | }) 370 | }) 371 | Response(NotFound) 372 | }) 373 | 374 | Action("cardVariations", func() { 375 | Description("Return the variations of a card with the given id.") 376 | Routing(GET("/:cardID/variations/")) 377 | 378 | Params(func() { 379 | Param("cardID", String, "Card ID") 380 | }) 381 | Response(OK, CollectionOf(VariationMedia, func() { 382 | ContentType("application/json; type=collection; charset=utf-8") 383 | }), func() { 384 | Headers(func() { 385 | Header("Last-Modified", func() { 386 | Description("DateTime in RFC1123 format.") 387 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 388 | }) 389 | }) 390 | }) 391 | Response(NotFound) 392 | }) 393 | 394 | Action("cardVariation", func() { 395 | Description("Return the variation of a given id of a card with the given id.") 396 | Routing(GET("/:cardID/variations/:variationID")) 397 | 398 | Params(func() { 399 | Param("cardID", String, "Card ID") 400 | Param("variationID", String, "Variation ID") 401 | }) 402 | Response(OK, VariationMedia, func() { 403 | Headers(func() { 404 | Header("Last-Modified", func() { 405 | Description("DateTime in RFC1123 format.") 406 | Example("Mon, 02 Jan 2006 15:04:05 GMT") 407 | }) 408 | }) 409 | }) 410 | Response(NotFound) 411 | }) 412 | 413 | }) 414 | -------------------------------------------------------------------------------- /design/types_definition.go: -------------------------------------------------------------------------------- 1 | package design 2 | 3 | import ( 4 | . "github.com/goadesign/goa/design" 5 | . "github.com/goadesign/goa/design/apidsl" 6 | ) 7 | 8 | var ArtType = Type("artType", func() { 9 | Description("Type of card art") 10 | Attribute("fullsizeImage", String, "Href to full size artwork", func() { 11 | Format("uri") 12 | }) 13 | Attribute("artist", String, "Name of the artist", func() { 14 | Example("Marek Madej") 15 | }) 16 | Attribute("mediumsizeImage", String, "Href to medium size artwork", func() { 17 | Format("uri") 18 | }) 19 | Attribute("thumbnailImage", String, "Href to thumbnail size artwork", func() { 20 | Format("uri") 21 | }) 22 | 23 | Required("thumbnailImage", "mediumsizeImage") 24 | }) 25 | 26 | var CostType = Type("costType", func() { 27 | Description("Type used to define the associated crafting/milling cost cost") 28 | Attribute("premium", Integer, "Premium cost", func() { 29 | Example(200) 30 | }) 31 | Attribute("normal", Integer, "Normal cost", func() { 32 | Example(30) 33 | }) 34 | 35 | Required("premium", "normal") 36 | }) 37 | -------------------------------------------------------------------------------- /faction.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/app" 5 | "github.com/GwentAPI/gwentapi/dataLayer/dal" 6 | "github.com/GwentAPI/gwentapi/dataLayer/factory" 7 | "github.com/GwentAPI/gwentapi/helpers" 8 | "github.com/goadesign/goa" 9 | "github.com/goadesign/goa/middleware" 10 | "time" 11 | ) 12 | 13 | // FactionController implements the faction resource. 14 | type FactionController struct { 15 | *goa.Controller 16 | } 17 | 18 | // NewFactionController creates a faction controller. 19 | func NewFactionController(service *goa.Service) *FactionController { 20 | return &FactionController{Controller: service.NewController("FactionController")} 21 | } 22 | 23 | // List runs the list action. 24 | func (c *FactionController) List(ctx *app.ListFactionContext) error { 25 | // FactionController_List: start_implement 26 | dataStore := &dal.DataStore{} 27 | dataStore.GetSession() 28 | // Close the session 29 | defer dataStore.Close() 30 | dc := dal.NewDalFaction(dataStore) 31 | 32 | factions, err := dc.FetchAll() 33 | 34 | if err != nil { 35 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Faction", "action", "List", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", err.Error()) 36 | return ctx.InternalServerError() 37 | } 38 | 39 | res := make(app.GwentapiFactionCollection, len(*factions)) 40 | 41 | lastModified := time.Time{} 42 | 43 | for i, faction := range *factions { 44 | f, _ := factory.CreateFaction(&faction) 45 | 46 | if lastModified.Before(faction.Last_Modified) { 47 | lastModified = faction.Last_Modified 48 | } 49 | 50 | res[i] = f 51 | } 52 | 53 | helpers.LastModified(ctx.ResponseData, lastModified) 54 | if ctx.IfModifiedSince != nil { 55 | if !helpers.IsModified(*ctx.IfModifiedSince, lastModified) { 56 | return ctx.NotModified() 57 | } 58 | } 59 | return ctx.OK(res) 60 | } 61 | 62 | // Show runs the show action. 63 | func (c *FactionController) Show(ctx *app.ShowFactionContext) error { 64 | // FactionController_Show: start_implement 65 | 66 | dataStore := &dal.DataStore{} 67 | dataStore.GetSession() 68 | // Close the session 69 | defer dataStore.Close() 70 | dc := dal.NewDalFaction(dataStore) 71 | uuid, err := helpers.DecodeUUID(ctx.FactionID) 72 | 73 | if err != nil { 74 | return ctx.NotFound() 75 | } 76 | 77 | faction, err := dc.Fetch(uuid) 78 | 79 | if helpers.IsNotFoundError(err) { 80 | return ctx.NotFound() 81 | } else if err != nil { 82 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Faction", "action", "Show", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", err.Error()) 83 | return ctx.InternalServerError() 84 | } 85 | 86 | // FactionController_Show: end_implement 87 | res, _ := factory.CreateFaction(faction) 88 | helpers.LastModified(ctx.ResponseData, faction.Last_Modified) 89 | if ctx.IfModifiedSince != nil { 90 | if !helpers.IsModified(*ctx.IfModifiedSince, faction.Last_Modified) { 91 | return ctx.NotModified() 92 | } 93 | } 94 | return ctx.OK(res) 95 | } 96 | -------------------------------------------------------------------------------- /group.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/app" 5 | "github.com/GwentAPI/gwentapi/dataLayer/dal" 6 | "github.com/GwentAPI/gwentapi/dataLayer/factory" 7 | "github.com/GwentAPI/gwentapi/helpers" 8 | "github.com/goadesign/goa" 9 | "github.com/goadesign/goa/middleware" 10 | "time" 11 | ) 12 | 13 | // GroupController implements the group resource. 14 | type GroupController struct { 15 | *goa.Controller 16 | } 17 | 18 | // NewGroupController creates a group controller. 19 | func NewGroupController(service *goa.Service) *GroupController { 20 | return &GroupController{Controller: service.NewController("GroupController")} 21 | } 22 | 23 | // List runs the list action. 24 | func (c *GroupController) List(ctx *app.ListGroupContext) error { 25 | // GroupController_List: start_implement 26 | 27 | dataStore := &dal.DataStore{} 28 | dataStore.GetSession() 29 | // Close the session 30 | defer dataStore.Close() 31 | dc := dal.NewDalGroup(dataStore) 32 | 33 | groups, err := dc.FetchAll() 34 | 35 | if err != nil { 36 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Group", "action", "List", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", err.Error()) 37 | return ctx.InternalServerError() 38 | } 39 | 40 | res := make(app.GwentapiGroupCollection, len(*groups)) 41 | 42 | lastModified := time.Time{} 43 | for i, group := range *groups { 44 | g, _ := factory.CreateGroup(&group) 45 | 46 | if lastModified.Before(group.Last_Modified) { 47 | lastModified = group.Last_Modified 48 | } 49 | 50 | res[i] = g 51 | } 52 | 53 | // GroupController_List: end_implement 54 | helpers.LastModified(ctx.ResponseData, lastModified) 55 | if ctx.IfModifiedSince != nil { 56 | if !helpers.IsModified(*ctx.IfModifiedSince, lastModified) { 57 | return ctx.NotModified() 58 | } 59 | } 60 | return ctx.OK(res) 61 | } 62 | 63 | // Show runs the show action. 64 | func (c *GroupController) Show(ctx *app.ShowGroupContext) error { 65 | // GroupController_Show: start_implement 66 | 67 | dataStore := &dal.DataStore{} 68 | dataStore.GetSession() 69 | // Close the session 70 | defer dataStore.Close() 71 | dc := dal.NewDalGroup(dataStore) 72 | uuid, err := helpers.DecodeUUID(ctx.GroupID) 73 | 74 | if err != nil { 75 | return ctx.NotFound() 76 | } 77 | 78 | group, err := dc.Fetch(uuid) 79 | 80 | if helpers.IsNotFoundError(err) { 81 | return ctx.NotFound() 82 | } else if err != nil { 83 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Group", "action", "Show", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", err.Error()) 84 | return ctx.InternalServerError() 85 | } 86 | 87 | // GroupController_Show: end_implement 88 | res, _ := factory.CreateGroup(group) 89 | helpers.LastModified(ctx.ResponseData, group.Last_Modified) 90 | if ctx.IfModifiedSince != nil { 91 | if !helpers.IsModified(*ctx.IfModifiedSince, group.Last_Modified) { 92 | return ctx.NotModified() 93 | } 94 | } 95 | return ctx.OK(res) 96 | } 97 | -------------------------------------------------------------------------------- /helpers/full_urls.go: -------------------------------------------------------------------------------- 1 | package helpers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/GwentAPI/gwentapi/app" 6 | "github.com/GwentAPI/gwentapi/configuration" 7 | ) 8 | 9 | var publicURL string 10 | 11 | // CardHref returns the resource href. 12 | func CardURL(cardID interface{}) string { 13 | return publicURL + app.CardHref(cardID) 14 | } 15 | 16 | // FactionHref returns the resource href. 17 | func FactionURL(factionID interface{}) string { 18 | return publicURL + app.FactionHref(factionID) 19 | } 20 | 21 | func VariationURL(cardID interface{}, variationID interface{}) string { 22 | return fmt.Sprintf("%v/v0/cards/%v/variations/%v", publicURL, cardID, variationID) 23 | } 24 | 25 | func CategoryURL(categoryUUID interface{}) string { 26 | return publicURL + app.CategoryHref(categoryUUID) 27 | } 28 | 29 | // GroupHref returns the resource href. 30 | func GroupURL(groupID interface{}) string { 31 | return publicURL + app.GroupHref(groupID) 32 | } 33 | func SwaggerURL() string { 34 | return "https://gwentapi.com/swagger/" 35 | } 36 | 37 | // RarityHref returns the resource href. 38 | func RarityURL(rarityID interface{}) string { 39 | return publicURL + app.RarityHref(rarityID) 40 | } 41 | 42 | // TypeHref returns the resource href. 43 | func MediaURL(filename interface{}) string { 44 | return fmt.Sprintf("%v/media/%v", publicURL, filename) 45 | } 46 | 47 | func init() { 48 | publicURL = configuration.GetConfig().App.PublicURL 49 | } 50 | -------------------------------------------------------------------------------- /helpers/header.go: -------------------------------------------------------------------------------- 1 | package helpers 2 | 3 | import ( 4 | "github.com/goadesign/goa" 5 | "gopkg.in/mgo.v2" 6 | "net/http" 7 | "time" 8 | ) 9 | 10 | func LastModified(data *goa.ResponseData, date time.Time) { 11 | setHeader(data, "Last-Modified", date) 12 | } 13 | 14 | func setHeader(data *goa.ResponseData, header string, value time.Time) { 15 | data.Header().Set(header, value.UTC().Format(http.TimeFormat)) 16 | } 17 | 18 | func IsModified(notModifiedSince string, lastModified time.Time) bool { 19 | // Truncate to the seconds. 20 | lastModified = lastModified.UTC().Truncate(1 * time.Second) 21 | // Try to parse the string to the 3 formats allowed by HTTP/1.1: TimeFormat. 22 | timeIfNotModifiedSince, err := http.ParseTime(notModifiedSince) 23 | return err != nil || lastModified.After(timeIfNotModifiedSince) 24 | } 25 | 26 | func IsNotFoundError(err error) bool { 27 | if err == mgo.ErrNotFound { 28 | return true 29 | } else { 30 | return false 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /helpers/pageHelper.go: -------------------------------------------------------------------------------- 1 | package helpers 2 | 3 | import ( 4 | "strconv" 5 | ) 6 | 7 | func ValidateLimitOffset(count int, limit int, offset int) (int, int) { 8 | if offset < 0 { 9 | offset = 0 10 | } 11 | 12 | if offset > count { 13 | offset = count 14 | } 15 | 16 | if limit < 0 { 17 | limit = 1 18 | } 19 | 20 | if limit > count { 21 | limit = count 22 | } 23 | 24 | return limit, offset 25 | } 26 | 27 | func GeneratePrevNextPageHref(count int, limit int, offset int, href string) (*string, *string) { 28 | var nextHref, prevHref string 29 | var next, prev *string 30 | 31 | if count <= limit { 32 | return nil, nil 33 | } 34 | 35 | nextHref = href + "?limit=" + strconv.Itoa(limit) + "&offset=" 36 | prevHref = nextHref 37 | 38 | prevOffset := offset - limit 39 | nextOffset := offset + limit 40 | 41 | if prevOffset < 0 { 42 | prevOffset = 0 43 | } 44 | 45 | if offset > 0 { 46 | prevHref += strconv.Itoa(prevOffset) 47 | prev = &prevHref 48 | } 49 | 50 | if nextOffset <= count && limit != count { 51 | nextHref += strconv.Itoa(nextOffset) 52 | next = &nextHref 53 | } 54 | 55 | return prev, next 56 | } 57 | -------------------------------------------------------------------------------- /helpers/uuidEncoder.go: -------------------------------------------------------------------------------- 1 | package helpers 2 | 3 | import ( 4 | b64 "encoding/base64" 5 | ) 6 | 7 | func EncodeUUID(uuid []byte) string { 8 | uEnc := b64.RawURLEncoding.EncodeToString(uuid) 9 | return uEnc 10 | } 11 | 12 | func DecodeUUID(uuid string) ([]byte, error) { 13 | uDec, err := b64.RawURLEncoding.DecodeString(uuid) 14 | return uDec, err 15 | } 16 | -------------------------------------------------------------------------------- /index.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/app" 5 | "github.com/GwentAPI/gwentapi/helpers" 6 | "github.com/goadesign/goa" 7 | ) 8 | 9 | // IndexController implements the index resource. 10 | type IndexController struct { 11 | *goa.Controller 12 | } 13 | 14 | // NewIndexController creates a index controller. 15 | func NewIndexController(service *goa.Service) *IndexController { 16 | return &IndexController{Controller: service.NewController("IndexController")} 17 | } 18 | 19 | // Show runs the show action. 20 | func (c *IndexController) Show(ctx *app.ShowIndexContext) error { 21 | // IndexController_Show: start_implement 22 | 23 | // IndexController_Show: end_implement 24 | 25 | res := &app.GwentapiResource{ 26 | Cards: helpers.CardURL(""), 27 | Factions: helpers.FactionURL(""), 28 | Rarities: helpers.RarityURL(""), 29 | Categories: helpers.CategoryURL(""), 30 | Groups: helpers.GroupURL(""), 31 | Swagger: helpers.SwaggerURL(), 32 | Version: version, 33 | } 34 | return ctx.OK(res) 35 | } 36 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | //go:generate goagen bootstrap -d github.com/GwentAPI/gwentapi/design 2 | 3 | package main 4 | 5 | import ( 6 | "context" 7 | "flag" 8 | "fmt" 9 | "github.com/GwentAPI/gwentapi/app" 10 | "github.com/GwentAPI/gwentapi/configuration" 11 | "github.com/GwentAPI/gwentapi/dataLayer/dal" 12 | "github.com/GwentAPI/gwentapi/serverService" 13 | "github.com/goadesign/goa" 14 | "github.com/goadesign/goa/logging/log15" 15 | "github.com/goadesign/goa/middleware" 16 | "github.com/goadesign/goa/middleware/gzip" 17 | log15 "github.com/inconshreveable/log15" 18 | "log" 19 | "os" 20 | "os/signal" 21 | "sync" 22 | "syscall" 23 | ) 24 | 25 | var enableGzip bool = true 26 | var gzipLevel int = -1 27 | 28 | /* 29 | Set this variable with go build with the -ldflags="-X main.version=" parameter. 30 | */ 31 | var version = "undefined" 32 | 33 | func init() { 34 | versionFlag := flag.Bool("v", false, "Prints current version") 35 | flag.Parse() 36 | 37 | if *versionFlag { 38 | fmt.Println(version) 39 | os.Exit(0) 40 | } 41 | } 42 | 43 | func main() { 44 | // Create service 45 | service := goa.New("gwentapi") 46 | 47 | //Create logger 48 | logger := log15.New("module", "app/server") 49 | 50 | config := configuration.GetConfig() 51 | //Logger configuration 52 | logger.SetHandler(log15.MultiHandler( 53 | log15.LvlFilterHandler(log15.LvlInfo, log15.Must.FileHandler(config.App.LogInfoFile, log15.LogfmtFormat())), 54 | log15.LvlFilterHandler(log15.LvlError, log15.Must.FileHandler(config.App.LogErrorFile, log15.LogfmtFormat())))) 55 | 56 | //Inject logger 57 | service.WithLogger(goalog15.New(logger)) 58 | 59 | // Mount middleware 60 | service.Use(middleware.RequestID()) 61 | service.Use(middleware.LogRequest(config.App.Verbose)) 62 | service.Use(middleware.ErrorHandler(service, config.App.Verbose)) 63 | service.Use(middleware.Recover()) 64 | if enableGzip { 65 | service.Use(gzip.Middleware(gzipLevel)) 66 | } 67 | // Mount "card" controller 68 | c := NewCardController(service) 69 | app.MountCardController(service, c) 70 | // Mount "faction" controller 71 | c2 := NewFactionController(service) 72 | app.MountFactionController(service, c2) 73 | // Mount "index" controller 74 | c3 := NewIndexController(service) 75 | app.MountIndexController(service, c3) 76 | // Mount "category" controller 77 | c4 := NewCategoryController(service) 78 | app.MountCategoryController(service, c4) 79 | // Mount "rarity" controller 80 | c6 := NewRarityController(service) 81 | app.MountRarityController(service, c6) 82 | // Mount "group" controller 83 | c8 := NewGroupController(service) 84 | app.MountGroupController(service, c8) 85 | 86 | // Close the main session 87 | defer dal.ShutDown() 88 | 89 | // create a context that we can cancel 90 | ctx, cancel := context.WithCancel(context.Background()) 91 | defer cancel() 92 | 93 | // a WaitGroup for the goroutines to tell us they've stopped 94 | wg := sync.WaitGroup{} 95 | wg.Add(1) 96 | go serverService.StartServer(ctx, &wg, service, config) 97 | 98 | sc := make(chan os.Signal, 1) 99 | signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill) 100 | <-sc 101 | //log.Debug("Received signal: shutting down.") 102 | //log.Debug("Telling goroutines to stop") 103 | cancel() 104 | 105 | wg.Wait() 106 | //log.Debug("All goroutines have told us they've finished.") 107 | log.Println("Server gracefully stopped.") 108 | } 109 | -------------------------------------------------------------------------------- /rarity.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/GwentAPI/gwentapi/app" 5 | "github.com/GwentAPI/gwentapi/dataLayer/dal" 6 | "github.com/GwentAPI/gwentapi/dataLayer/factory" 7 | "github.com/GwentAPI/gwentapi/helpers" 8 | "github.com/goadesign/goa" 9 | "github.com/goadesign/goa/middleware" 10 | "time" 11 | ) 12 | 13 | // RarityController implements the rarity resource. 14 | type RarityController struct { 15 | *goa.Controller 16 | } 17 | 18 | // NewRarityController creates a rarity controller. 19 | func NewRarityController(service *goa.Service) *RarityController { 20 | return &RarityController{Controller: service.NewController("RarityController")} 21 | } 22 | 23 | // List runs the list action. 24 | func (c *RarityController) List(ctx *app.ListRarityContext) error { 25 | // RarityController_List: start_implement 26 | dataStore := &dal.DataStore{} 27 | dataStore.GetSession() 28 | // Close the session 29 | defer dataStore.Close() 30 | dc := dal.NewDalRarity(dataStore) 31 | 32 | rarities, err := dc.FetchAll() 33 | 34 | if err != nil { 35 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Rarity", "action", "List", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", err.Error()) 36 | return ctx.InternalServerError() 37 | } 38 | 39 | res := make(app.GwentapiRarityCollection, len(*rarities)) 40 | 41 | lastModified := time.Time{} 42 | for i, rarity := range *rarities { 43 | r, _ := factory.CreateRarity(&rarity) 44 | 45 | if lastModified.Before(rarity.Last_Modified) { 46 | lastModified = rarity.Last_Modified 47 | } 48 | 49 | res[i] = r 50 | } 51 | 52 | // RarityController_List: end_implement 53 | helpers.LastModified(ctx.ResponseData, lastModified) 54 | if ctx.IfModifiedSince != nil { 55 | if !helpers.IsModified(*ctx.IfModifiedSince, lastModified) { 56 | return ctx.NotModified() 57 | } 58 | } 59 | return ctx.OK(res) 60 | } 61 | 62 | // Show runs the show action. 63 | func (c *RarityController) Show(ctx *app.ShowRarityContext) error { 64 | // RarityController_Show: start_implement 65 | 66 | dataStore := &dal.DataStore{} 67 | dataStore.GetSession() 68 | // Close the session 69 | defer dataStore.Close() 70 | dc := dal.NewDalRarity(dataStore) 71 | uuid, err := helpers.DecodeUUID(ctx.RarityID) 72 | 73 | if err != nil { 74 | return ctx.NotFound() 75 | } 76 | 77 | rarity, err := dc.Fetch(uuid) 78 | 79 | if helpers.IsNotFoundError(err) { 80 | return ctx.NotFound() 81 | } else if err != nil { 82 | ctx.ResponseData.Service.LogError("InternalServerError", "req_id", middleware.ContextRequestID(ctx), "ctrl", "Rarity", "action", "Show", ctx.RequestData.Request.Method, ctx.RequestData.Request.URL, "databaseError", err.Error()) 83 | return ctx.InternalServerError() 84 | } 85 | 86 | // RarityController_Show: end_implement 87 | res, _ := factory.CreateRarity(rarity) 88 | helpers.LastModified(ctx.ResponseData, rarity.Last_Modified) 89 | if ctx.IfModifiedSince != nil { 90 | if !helpers.IsModified(*ctx.IfModifiedSince, rarity.Last_Modified) { 91 | return ctx.NotModified() 92 | } 93 | } 94 | return ctx.OK(res) 95 | } 96 | -------------------------------------------------------------------------------- /serverService/README.md: -------------------------------------------------------------------------------- 1 | ## Experimental socket activated http server 2 | 3 | To use systemd socket activation feature for zero downtime upgrade follow this guide: 4 | 5 | 1. copy the service definition unit file ``gwentapi.service`` 6 | and the socket definition unit file ``gwentapi.socket`` to ``/etc/systemd/system/``. 7 | 8 | 2. Copy the executable and the config file at the location defined by the service unit file: ``/usr/local/bin/`` by default. 9 | 10 | 3. Rename the executable to gwentapi to match the filename in the service unit file. 11 | 12 | 4. Enable the socket and start it 13 | 1. ``systemctl enable gwentapi.socket`` 14 | 2. ``systemctl start gwentapi.socket`` 15 | 16 | This experimental feature is only supported on Linux with systemd. 17 | 18 | ### To upgrade the service 19 | 20 | 1. Replace the executable 21 | 2. Restart the service with systemctl -------------------------------------------------------------------------------- /serverService/gwentapi.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=GwentAPI Service - Restful Gwent service 3 | Requires=network.target 4 | After=multi-user.target 5 | 6 | [Service] 7 | Type=simple 8 | WorkingDirectory=/usr/local/bin/GwentAPI 9 | ExecStart=/usr/local/bin/GwentAPI/gwentapi 10 | 11 | [Install] 12 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /serverService/gwentapi.socket: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=GwentAPI Socket 3 | PartOf=gwentapi.service 4 | 5 | [Socket] 6 | ListenStream=127.0.0.1:8080 7 | 8 | [Install] 9 | WantedBy=sockets.target -------------------------------------------------------------------------------- /serverService/serverCore.go: -------------------------------------------------------------------------------- 1 | package serverService 2 | 3 | import ( 4 | "context" 5 | "github.com/GwentAPI/gwentapi/configuration" 6 | "github.com/goadesign/goa" 7 | "log" 8 | "net/http" 9 | "os" 10 | "sync" 11 | "time" 12 | ) 13 | 14 | func mountMedia(fileSystemPath string, mux *http.ServeMux) { 15 | fs := justFilesFilesystem{http.Dir(fileSystemPath)} 16 | mux.Handle("/media/", http.StripPrefix("/media/", http.FileServer(fs))) 17 | } 18 | 19 | type justFilesFilesystem struct { 20 | Fs http.FileSystem 21 | } 22 | 23 | func (fs justFilesFilesystem) Open(name string) (http.File, error) { 24 | f, err := fs.Fs.Open(name) 25 | 26 | if err != nil { 27 | return nil, err 28 | } 29 | 30 | stat, err := f.Stat() 31 | if stat.IsDir() { 32 | return nil, os.ErrNotExist 33 | } 34 | return f, nil 35 | } 36 | 37 | func StartServer(ctx context.Context, wg *sync.WaitGroup, service *goa.Service, config configuration.GwentConfig) { 38 | defer wg.Done() 39 | 40 | mux := http.NewServeMux() 41 | mountMedia(config.App.MediaPath, mux) 42 | mux.HandleFunc("/", service.Mux.ServeHTTP) 43 | srv := &http.Server{ 44 | ReadTimeout: 10 * time.Second, 45 | WriteTimeout: 10 * time.Second, 46 | IdleTimeout: 30 * time.Second, 47 | Handler: mux, 48 | Addr: config.App.Port, 49 | } 50 | 51 | // Start service 52 | go startService(srv) 53 | <-ctx.Done() 54 | log.Println("Shutdown in progress.") 55 | 56 | // shut down gracefully, but wait no longer than 5 seconds before halting 57 | shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 58 | defer cancel() 59 | 60 | srv.Shutdown(shutdownCtx) 61 | } 62 | -------------------------------------------------------------------------------- /serverService/serverStart.go: -------------------------------------------------------------------------------- 1 | // +build !linux 2 | 3 | package serverService 4 | 5 | import ( 6 | "log" 7 | "net/http" 8 | ) 9 | 10 | func startService(server *http.Server) { 11 | log.Println("Web server is starting.") 12 | if err := server.ListenAndServe(); err != nil { 13 | log.Fatal("Error on startup: ", err) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /serverService/serverStart_linux.go: -------------------------------------------------------------------------------- 1 | package serverService 2 | 3 | import ( 4 | "github.com/coreos/go-systemd/activation" 5 | "log" 6 | "net/http" 7 | ) 8 | 9 | func startService(server *http.Server) { 10 | listeners, err := activation.Listeners(true) 11 | if err != nil { 12 | log.Panic(err) 13 | } 14 | log.Println("Web server is starting.") 15 | // No socket passed from systemd, we aren't running with socket activation. 16 | if len(listeners) == 0 { 17 | // Fallback 18 | if err := server.ListenAndServe(); err != nil { 19 | log.Fatal("Error on startup: ", err) 20 | } 21 | } else { 22 | // Socket activation code 23 | log.Println("Listening to sockets.") 24 | if len(listeners) != 1 { 25 | log.Fatal("Unexpected number of socket activation fds. Number: ", len(listeners)) 26 | } 27 | if err := server.Serve(listeners[0]); err != nil { 28 | log.Fatal("Error starting socket activated web server: ", err) 29 | } 30 | } 31 | } 32 | --------------------------------------------------------------------------------