Skip to content

Commit

Permalink
Add Swagger doc generation
Browse files Browse the repository at this point in the history
Add Swagger docs for the APIs and standardizing the API patterns.
  • Loading branch information
StevenWeathers committed Oct 30, 2021
1 parent 2b9ae2e commit 1634df0
Show file tree
Hide file tree
Showing 34 changed files with 2,285 additions and 1,250 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ packrd/
*-packr.go
pkged.go
thunderdome-planning-poker*
swaggerdocs/
6 changes: 6 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ jobs:
dep ensure
fi
- name: Install swag
run: go install github.com/swaggo/swag/cmd/swag@latest

- name: Generate swagger docs
run: swag init -g api/api.go -o swaggerdocs

# - name: Test
# run: go test

Expand Down
1 change: 1 addition & 0 deletions .github/workflows/goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ jobs:
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- run: go install github.com/swaggo/swag/cmd/swag@latest
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
node_modules/
dist/
release/
swaggerdocs/
# how static assets get bundled
*-packr.go
packrd/
Expand Down
11 changes: 10 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ GOCMD=go
NPMCMD=npm
NPMBUILD=$(NPMCMD) run build
GOBUILD=$(GOCMD) build
SWAGGERGEN=swag init -g api/api.go -o swaggerdocs
SWAGGERDOCS=swaggerdocs
GOFMT=gofmt
BINARY_NAME=thunderdome-planning-poker
BINARY_UNIX=$(BINARY_NAME)_unix
Expand All @@ -17,9 +19,11 @@ DOCKER_BUILD_VERSION=--build-arg BUILD_VERSION=${VERSION_TAG}
all: build
build-deps:
$(NPMBUILD)
$(SWAGGERGEN)

build:
$(NPMBUILD)
$(SWAGGERGEN)
$(GOBUILD) -o $(BINARY_NAME) -v

clean:
Expand All @@ -31,6 +35,7 @@ clean:
rm -rf dist
rm -rf release
rm -rf pkged*.go
rm -rf $(SWAGGERDOCS)

format:
$(GOFMT) -s -w datasrc.go
Expand All @@ -42,17 +47,21 @@ format:

# Cross compilation
build-linux:
$(SWAGGERGEN)
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GOBUILD) -o $(BINARY_UNIX) -v

build-windows:
$(SWAGGERGEN)
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 $(GOBUILD) -o $(BINARY_WINDOWS) -v

dev:
$(NPMBUILD)
$(SWAGGERGEN)
$(GOBUILD) -o $(BINARY_NAME) -v

SMTP_SECURE="false" DB_HOST="localhost" APP_DOMAIN=".127.0.0.1" COOKIE_SECURE="false" ./$(BINARY_NAME) live
dev-go:
dev-go:
$(SWAGGERGEN)
$(GOBUILD) -o $(BINARY_NAME) -v

SMTP_SECURE="false" DB_HOST="localhost" APP_DOMAIN=".127.0.0.1" COOKIE_SECURE="false" ./$(BINARY_NAME) live
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ DB_NAME=
### Install dependencies
```
go get
go install github.com/swaggo/swag/cmd/swag@latest
npm install
```

Expand All @@ -213,6 +214,7 @@ npm run build

### Build for current OS
```
swag init -g api/api.go -o swaggerdocs
go build
```

Expand Down
226 changes: 226 additions & 0 deletions api/admin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
package api

import (
"log"
"net/http"
"strconv"
"strings"

"github.com/gorilla/mux"
)

// handleAppStats gets the applications stats
// @Summary Get Application Stats
// @Description get application stats such as count of registered warriors
// @Tags admin
// @Produce json
// @Success 200
// @Router /admin/stats [get]
func (a *api) handleAppStats() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
AppStats, err := a.db.GetAppStats()

if err != nil {
http.NotFound(w, r)
return
}

ActiveBattleUserCount := 0
for _, s := range h.arenas {
ActiveBattleUserCount = ActiveBattleUserCount + len(s)
}

AppStats.ActiveBattleCount = len(h.arenas)
AppStats.ActiveBattleUserCount = ActiveBattleUserCount

a.respondWithJSON(w, http.StatusOK, AppStats)
}
}

// handleGetRegisteredUsers gets a list of registered users
// @Summary Get Registered Users
// @Description get list of registered users
// @Tags admin
// @Produce json
// @Param limit path int false "Max number of results to return"
// @Param offset path int false "Starting point to return rows from, should be multiplied by limit or 0"
// @Success 200
// @Router /admin/warriors/{limit}/{offset} [get]
func (a *api) handleGetRegisteredUsers() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
Limit, _ := strconv.Atoi(vars["limit"])
Offset, _ := strconv.Atoi(vars["offset"])

Users := a.db.GetRegisteredUsers(Limit, Offset)

a.respondWithJSON(w, http.StatusOK, Users)
}
}

// handleUserCreate registers a new authenticated user
// @Summary Create Registered User
// @Description Create a registered user
// @Tags admin
// @Produce json
// @Success 200
// @Router /admin/warrior [post]
func (a *api) handleUserCreate() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
keyVal := a.getJSONRequestBody(r, w)

UserName, UserEmail, UserPassword, accountErr := ValidateUserAccount(
keyVal["warriorName"].(string),
strings.ToLower(keyVal["warriorEmail"].(string)),
keyVal["warriorPassword1"].(string),
keyVal["warriorPassword2"].(string),
)

if accountErr != nil {
w.WriteHeader(http.StatusBadRequest)
return
}

newUser, VerifyID, err := a.db.CreateUserRegistered(UserName, UserEmail, UserPassword, "")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}

a.email.SendWelcome(UserName, UserEmail, VerifyID)

a.respondWithJSON(w, http.StatusOK, newUser)
}
}

// handleAdminUserDelete attempts to delete a users account
func (a *api) handleAdminUserDelete() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
UserID := vars["id"]

User, UserErr := a.db.GetUser(UserID)
if UserErr != nil {
log.Println("error finding user : " + UserErr.Error() + "\n")
w.WriteHeader(http.StatusInternalServerError)
return
}

updateErr := a.db.DeleteUser(UserID)
if updateErr != nil {
log.Println("error attempting to delete user : " + updateErr.Error() + "\n")
w.WriteHeader(http.StatusInternalServerError)
return
}

a.email.SendDeleteConfirmation(User.UserName, User.UserEmail)

return
}
}

// handleUserPromote handles promoting a user to admin
// @Summary Promotes User
// @Description Promotes a user to admin
// @Description Grants read and write access to administrative information
// @Tags admin
// @Produce json
// @Success 200
// @Router /admin/promote [post]
func (a *api) handleUserPromote() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
keyVal := a.getJSONRequestBody(r, w)

err := a.db.PromoteUser(keyVal["warriorId"].(string))
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}

return
}
}

// handleUserDemote handles demoting a user to registered
// @Summary Demote User
// @Description Demotes a user from admin to registered
// @Tags admin
// @Produce json
// @Success 200
// @Router /admin/demote [post]
func (a *api) handleUserDemote() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
keyVal := a.getJSONRequestBody(r, w)

err := a.db.DemoteUser(keyVal["warriorId"].(string))
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}

return
}
}

// handleGetOrganizations gets a list of organizations
// @Summary Get Organizations
// @Description get a list of organizations
// @Tags admin
// @Produce json
// @Param limit path int false "Max number of results to return"
// @Param offset path int false "Starting point to return rows from, should be multiplied by limit or 0"
// @Success 200
// @Router /admin/organizations/{limit}/{offset} [get]
func (a *api) handleGetOrganizations() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
Limit, _ := strconv.Atoi(vars["limit"])
Offset, _ := strconv.Atoi(vars["offset"])

Organizations := a.db.OrganizationList(Limit, Offset)

a.respondWithJSON(w, http.StatusOK, Organizations)
}
}

// handleGetTeams gets a list of teams
// @Summary Get Teams
// @Description get a list of teams
// @Tags admin
// @Produce json
// @Param limit path int false "Max number of results to return"
// @Param offset path int false "Starting point to return rows from, should be multiplied by limit or 0"
// @Success 200
// @Router /admin/teams/{limit}/{offset} [get]
func (a *api) handleGetTeams() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
Limit, _ := strconv.Atoi(vars["limit"])
Offset, _ := strconv.Atoi(vars["offset"])

Teams := a.db.TeamList(Limit, Offset)

a.respondWithJSON(w, http.StatusOK, Teams)
}
}

// handleGetAPIKeys gets a list of APIKeys
// @Summary Get API Keys
// @Description get a list of users API Keys
// @Tags admin
// @Produce json
// @Param limit path int false "Max number of results to return"
// @Param offset path int false "Starting point to return rows from, should be multiplied by limit or 0"
// @Success 200
// @Router /admin/apikeys/{limit}/{offset} [get]
func (a *api) handleGetAPIKeys() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
Limit, _ := strconv.Atoi(vars["limit"])
Offset, _ := strconv.Atoi(vars["offset"])

Teams := a.db.GetAPIKeys(Limit, Offset)

a.respondWithJSON(w, http.StatusOK, Teams)
}
}
Loading

0 comments on commit 1634df0

Please sign in to comment.