Skip to content

Commit

Permalink
feat: Collect statistics and serve over API (#13)
Browse files Browse the repository at this point in the history
* Add back linter on push

* Add bbolt to project

* Make it work with the new structure

* Add new helper for ip

* Add middleware for collecting stats

* Add function to collect download asked

* doc: update documentation

* Add skeleton for API

* Review structure a little bit

* Add a proto for CORS custom middleware

* Add visit statistic

* Add unique switch stat

* Add details per switch

* Add ip for unkown switch

* Trigger stats for download game only on existing game

* Add stats about downloads

* Begin to add test for StatsMiddleware

* Add tests for StatsMiddleware

* doc: Add more info

* Add new github Action for testing

* Add tests for API

* Move bytes functions to utils

* Add more tests

* Fix ginkgo workflow

* Another fix for ginkgo

* Install dependencies in CI

* Fix ginkgo workflow

* Fix randomize tests

* New badges

* Another fix for GithubAction

* doc: Cleaner readme

* doc: More spaces
  • Loading branch information
DblK authored Jan 6, 2022
1 parent 6a7ffe0 commit a8c411a
Show file tree
Hide file tree
Showing 26 changed files with 957 additions and 26 deletions.
29 changes: 29 additions & 0 deletions .github/workflows/ginkgo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: test

on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
-
id: vars
run: |
echo ::set-output name=go_version::$(cat go.mod | head -3 | tail -1 | cut -d ' ' -f 2)
echo "Using Go version ${{ steps.vars.outputs.go_version }}"
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: ${{ steps.vars.outputs.go_version }}
- run: go mod tidy && git diff --exit-code go.mod go.sum
- name: Install ginkgo
run: |
go get github.com/onsi/ginkgo/v2/ginkgo
go get github.com/onsi/gomega/...
- name: Print out Ginkgo version
run: ginkgo version
- run: ginkgo -r --randomize-all --randomize-suites --race --trace
2 changes: 1 addition & 1 deletion .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: golangci-lint
on:
# push:
push:
pull_request:
permissions:
contents: read
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@
# TinShop specific
config.yaml
titles.US.en.json
/dist
/dist
stats.db
coverprofile.out
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"cSpell.words": [
"asciicheck",
"bbolt",
"bodyclose",
"dblk",
"deadcode",
Expand Down Expand Up @@ -34,6 +35,7 @@
"ineffassign",
"Infof",
"interfacer",
"itob",
"logrus",
"logutils",
"mitchellh",
Expand Down
23 changes: 12 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
<p align="center">
<p align="center">
<img alt="TinShop" src="./logo.png" width="50%">
</p>
<p align="center">
Your own personal shop right into tinfoil!
</p>

[![golangci-lint](https://github.com/DblK/tinshop/actions/workflows/golangci-lint.yml/badge.svg?event=release)](https://github.com/DblK/tinshop/actions/workflows/golangci-lint.yml)
<div align="center">
<img alt="TinShop" src="./logo.png" width="50%"><br><br>
Your own personal shop right into tinfoil!<br><br>

[![golangci-lint](https://github.com/DblK/tinshop/actions/workflows/golangci-lint.yml/badge.svg?branch=master&event=release)](https://github.com/DblK/tinshop/actions/workflows/golangci-lint.yml)
[![test](https://github.com/DblK/tinshop/actions/workflows/ginkgo.yml/badge.svg?branch=master&event=release)](https://github.com/DblK/tinshop/actions/workflows/ginkgo.yml)
[![GitHub go.mod Go version of a Go module](https://img.shields.io/github/go-mod/go-version/DblK/tinshop.svg)](https://github.com/DblK/tinshop)
[![GoDoc reference example](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/DblK/tinshop)
[![GoReportCard](https://goreportcard.com/badge/github.com/DblK/tinshop)](https://goreportcard.com/report/github.com/DblK/tinshop)
[![GitHub release](https://img.shields.io/github/release/DblK/tinshop.svg)](https://GitHub.com/DblK/tinshop/releases/)
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)
</div>

# Disclaimer

Expand Down Expand Up @@ -48,7 +46,9 @@ Here is the list of all main features so far:
- [X] You can specify custom titledb to be merged with official one
- [X] Auto-watch for mounted directories
- [X] Add filters path for shop
- [X] Simple ticket check in NSP/NSZ
- [X] Simple ticket check in NSP/NSZ (based on titledb file)
- [X] Collect basic statistics
- [X] An API to query information about your shop

## Filtering

Expand Down Expand Up @@ -79,7 +79,8 @@ If you change an interface (or add a new one), do not forget to execute `./updat

## What to launch tests?

You can run `ginkgo -r` for one shot or `ginkgo watch -r` during development.
You can run `ginkgo -r` for one shot or `ginkgo watch -r` during development.
Note: you can add `-cover` to have an idea of the code coverage.
# Roadmap

You can see the [roadmap here](https://github.com/DblK/tinshop/projects/1).
Expand Down
30 changes: 30 additions & 0 deletions api/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package api

import (
"encoding/json"
"log"
"net/http"

"github.com/DblK/tinshop/repository"
)

type endpoint struct {
}

// New returns a new api
func New() repository.API {
return &endpoint{}
}

func (e *endpoint) Stats(w http.ResponseWriter, stats repository.StatsSummary) {
jsonResponse, jsonError := json.Marshal(stats)

if jsonError != nil {
log.Println("[API] Unable to encode JSON")
w.WriteHeader(http.StatusInternalServerError)
return
}

w.WriteHeader(http.StatusOK)
_, _ = w.Write(jsonResponse)
}
13 changes: 13 additions & 0 deletions api/api_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package api_test

import (
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

func TestApi(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Api Suite")
}
42 changes: 42 additions & 0 deletions api/api_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package api_test

import (
"net/http"
"net/http/httptest"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"github.com/DblK/tinshop/api"
"github.com/DblK/tinshop/repository"
)

var _ = Describe("Api", func() {
var (
myAPI repository.API
writer *httptest.ResponseRecorder
)
BeforeEach(func() {
myAPI = api.New()
})
Describe("Stats", func() {
It("Test with empty stats", func() {
emptyStats := &repository.StatsSummary{}
writer = httptest.NewRecorder()

myAPI.Stats(writer, *emptyStats)
Expect(writer.Code).To(Equal(http.StatusOK))
Expect(writer.Body.String()).To(Equal("{}"))
})
It("Test with some stats", func() {
emptyStats := &repository.StatsSummary{
Visit: 42,
}
writer = httptest.NewRecorder()

myAPI.Stats(writer, *emptyStats)
Expect(writer.Code).To(Equal(http.StatusOK))
Expect(writer.Body.String()).To(Equal("{\"visit\":42}"))
})
})
})
76 changes: 65 additions & 11 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,11 @@ var _ = Describe("Config", func() {
})
})
Context("Security for Blacklist/Whitelist tests", func() {
var myConfig = config.File{}
var myConfig config.File

BeforeEach(func() {
myConfig = config.File{}
})

Describe("Blacklist tests", func() { //nolint:dupl
It("With empty blacklist", func() {
Expand Down Expand Up @@ -206,7 +210,12 @@ var _ = Describe("Config", func() {
})
})
Context("Security for theme", func() {
var myConfig = config.File{}
var myConfig config.File

BeforeEach(func() {
myConfig = config.File{}
})

Describe("IsBannedTheme", func() {
It("should not be banned if empty config", func() {
Expect(myConfig.IsBannedTheme("myTheme")).To(BeFalse())
Expand All @@ -226,7 +235,12 @@ var _ = Describe("Config", func() {
})
})
Describe("Protocol", func() {
var myConfig = config.File{}
var myConfig config.File

BeforeEach(func() {
myConfig = config.File{}
})

It("Test with empty object", func() {
Expect(myConfig.Protocol()).To(BeEmpty())
})
Expand All @@ -236,7 +250,12 @@ var _ = Describe("Config", func() {
})
})
Describe("Host", func() {
var myConfig = config.File{}
var myConfig config.File

BeforeEach(func() {
myConfig = config.File{}
})

It("Test with empty object", func() {
Expect(myConfig.Host()).To(BeEmpty())
})
Expand All @@ -246,7 +265,12 @@ var _ = Describe("Config", func() {
})
})
Describe("Port", func() {
var myConfig = config.File{}
var myConfig config.File

BeforeEach(func() {
myConfig = config.File{}
})

It("Test with empty object", func() {
Expect(myConfig.Port()).To(Equal(0))
})
Expand All @@ -256,7 +280,12 @@ var _ = Describe("Config", func() {
})
})
Describe("ShopTitle", func() {
var myConfig = config.File{}
var myConfig config.File

BeforeEach(func() {
myConfig = config.File{}
})

It("Test with empty object", func() {
Expect(myConfig.ShopTitle()).To(BeEmpty())
})
Expand All @@ -266,7 +295,12 @@ var _ = Describe("Config", func() {
})
})
Describe("DebugNfs", func() {
var myConfig = config.File{}
var myConfig config.File

BeforeEach(func() {
myConfig = config.File{}
})

It("Test with empty object", func() {
Expect(myConfig.DebugNfs()).To(BeFalse())
})
Expand All @@ -276,7 +310,12 @@ var _ = Describe("Config", func() {
})
})
Describe("VerifyNSP", func() {
var myConfig = config.File{}
var myConfig config.File

BeforeEach(func() {
myConfig = config.File{}
})

It("Test with empty object", func() {
Expect(myConfig.VerifyNSP()).To(BeFalse())
})
Expand All @@ -286,7 +325,12 @@ var _ = Describe("Config", func() {
})
})
Describe("DebugNoSecurity", func() {
var myConfig = config.File{}
var myConfig config.File

BeforeEach(func() {
myConfig = config.File{}
})

It("Test with empty object", func() {
Expect(myConfig.DebugNoSecurity()).To(BeFalse())
})
Expand All @@ -296,7 +340,12 @@ var _ = Describe("Config", func() {
})
})
Describe("DebugTicket", func() {
var myConfig = config.File{}
var myConfig config.File

BeforeEach(func() {
myConfig = config.File{}
})

It("Test with empty object", func() {
Expect(myConfig.DebugTicket()).To(BeFalse())
})
Expand All @@ -306,7 +355,12 @@ var _ = Describe("Config", func() {
})
})
Describe("BannedTheme", func() {
var myConfig = config.File{}
var myConfig config.File

BeforeEach(func() {
myConfig = config.File{}
})

It("Test with empty object", func() {
Expect(myConfig.BannedTheme()).To(HaveLen(0))
})
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ require (
github.com/onsi/gomega v1.17.0
github.com/spf13/viper v1.10.1
github.com/vmware/go-nfs-client v0.0.0-20190605212624-d43b92724c1b
go.etcd.io/bbolt v1.3.6
gopkg.in/fsnotify.v1 v1.4.7
)

Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs=
Expand Down Expand Up @@ -529,6 +531,7 @@ golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down
Loading

0 comments on commit a8c411a

Please sign in to comment.