diff --git a/docs/docs.go b/docs/docs.go index bf64d22..2b8d3c7 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -16,19 +16,298 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { - "/": { + "/cure": { "get": { - "description": "Home page", + "description": "Cures a zombie or infected human", "produces": [ - "application/json" + "text/plain" + ], + "summary": "Cure", + "parameters": [ + { + "type": "string", + "description": "Target ID", + "name": "target", + "in": "path", + "required": true + } ], - "summary": "Home", "responses": { "200": { "description": "OK" + }, + "401": { + "description": "User is not logged in", + "schema": { + "type": "string" + } + }, + "403": { + "description": "No cures available", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Target does not exist", + "schema": { + "type": "string" + } + }, + "409": { + "description": "Target is not a zombie", + "schema": { + "type": "string" + } } } } + }, + "/kill": { + "get": { + "description": "Kills a zombie if user is authenticated as a human. Gives zombie target the stunned state", + "produces": [ + "text/plain" + ], + "summary": "Kill", + "parameters": [ + { + "type": "string", + "description": "Target ID", + "name": "target", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + }, + "401": { + "description": "User is not logged in", + "schema": { + "type": "string" + } + }, + "403": { + "description": "Killer is not a human", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Target does not exist", + "schema": { + "type": "string" + } + }, + "409": { + "description": "Target is not a zombie", + "schema": { + "type": "string" + } + } + } + } + }, + "/login": { + "post": { + "description": "Login", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "Login", + "parameters": [ + { + "description": "Player login", + "name": "info", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/main.Login" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/main.Player" + } + }, + "400": { + "description": "Bad Request" + }, + "403": { + "description": "Forbidden" + } + } + } + }, + "/me": { + "get": { + "description": "Shows user information", + "produces": [ + "application/json" + ], + "summary": "Me", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/main.Player" + } + }, + "401": { + "description": "User is not logged in", + "schema": { + "type": "string" + } + } + } + } + }, + "/revive": { + "get": { + "description": "Revives a stunned zombie", + "produces": [ + "text/plain" + ], + "summary": "Revive", + "parameters": [ + { + "type": "string", + "description": "Target ID", + "name": "target", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + }, + "401": { + "description": "User is not logged in", + "schema": { + "type": "string" + } + }, + "403": { + "description": "No revives available", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Target does not exist", + "schema": { + "type": "string" + } + }, + "409": { + "description": "Target is not stunned", + "schema": { + "type": "string" + } + } + } + } + }, + "/tag": { + "get": { + "description": "Tag a human as a zombie. Gives target the infected state if user is a zombie or core zombie.", + "produces": [ + "text/plain" + ], + "summary": "Tag", + "parameters": [ + { + "type": "string", + "description": "Target ID", + "name": "target", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + }, + "401": { + "description": "User is not logged in", + "schema": { + "type": "string" + } + }, + "403": { + "description": "Tagger is not a zombie", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Target does not exist", + "schema": { + "type": "string" + } + }, + "409": { + "description": "Target is not human", + "schema": { + "type": "string" + } + } + } + } + } + }, + "definitions": { + "main.Login": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "password": { + "type": "string" + } + } + }, + "main.Player": { + "type": "object", + "properties": { + "cures": { + "type": "integer" + }, + "extensions": { + "type": "integer" + }, + "id": { + "type": "string" + }, + "kills": { + "type": "integer" + }, + "last_kill": { + "type": "string" + }, + "last_tagged": { + "type": "string" + }, + "name": { + "type": "string" + }, + "revives": { + "type": "integer" + }, + "state": { + "type": "integer" + } + } } } }` diff --git a/docs/swagger.json b/docs/swagger.json index e0a6c33..12cb543 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -8,19 +8,298 @@ }, "basePath": "/", "paths": { - "/": { + "/cure": { "get": { - "description": "Home page", + "description": "Cures a zombie or infected human", "produces": [ - "application/json" + "text/plain" + ], + "summary": "Cure", + "parameters": [ + { + "type": "string", + "description": "Target ID", + "name": "target", + "in": "path", + "required": true + } ], - "summary": "Home", "responses": { "200": { "description": "OK" + }, + "401": { + "description": "User is not logged in", + "schema": { + "type": "string" + } + }, + "403": { + "description": "No cures available", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Target does not exist", + "schema": { + "type": "string" + } + }, + "409": { + "description": "Target is not a zombie", + "schema": { + "type": "string" + } } } } + }, + "/kill": { + "get": { + "description": "Kills a zombie if user is authenticated as a human. Gives zombie target the stunned state", + "produces": [ + "text/plain" + ], + "summary": "Kill", + "parameters": [ + { + "type": "string", + "description": "Target ID", + "name": "target", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + }, + "401": { + "description": "User is not logged in", + "schema": { + "type": "string" + } + }, + "403": { + "description": "Killer is not a human", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Target does not exist", + "schema": { + "type": "string" + } + }, + "409": { + "description": "Target is not a zombie", + "schema": { + "type": "string" + } + } + } + } + }, + "/login": { + "post": { + "description": "Login", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "Login", + "parameters": [ + { + "description": "Player login", + "name": "info", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/main.Login" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/main.Player" + } + }, + "400": { + "description": "Bad Request" + }, + "403": { + "description": "Forbidden" + } + } + } + }, + "/me": { + "get": { + "description": "Shows user information", + "produces": [ + "application/json" + ], + "summary": "Me", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/main.Player" + } + }, + "401": { + "description": "User is not logged in", + "schema": { + "type": "string" + } + } + } + } + }, + "/revive": { + "get": { + "description": "Revives a stunned zombie", + "produces": [ + "text/plain" + ], + "summary": "Revive", + "parameters": [ + { + "type": "string", + "description": "Target ID", + "name": "target", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + }, + "401": { + "description": "User is not logged in", + "schema": { + "type": "string" + } + }, + "403": { + "description": "No revives available", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Target does not exist", + "schema": { + "type": "string" + } + }, + "409": { + "description": "Target is not stunned", + "schema": { + "type": "string" + } + } + } + } + }, + "/tag": { + "get": { + "description": "Tag a human as a zombie. Gives target the infected state if user is a zombie or core zombie.", + "produces": [ + "text/plain" + ], + "summary": "Tag", + "parameters": [ + { + "type": "string", + "description": "Target ID", + "name": "target", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + }, + "401": { + "description": "User is not logged in", + "schema": { + "type": "string" + } + }, + "403": { + "description": "Tagger is not a zombie", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Target does not exist", + "schema": { + "type": "string" + } + }, + "409": { + "description": "Target is not human", + "schema": { + "type": "string" + } + } + } + } + } + }, + "definitions": { + "main.Login": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "password": { + "type": "string" + } + } + }, + "main.Player": { + "type": "object", + "properties": { + "cures": { + "type": "integer" + }, + "extensions": { + "type": "integer" + }, + "id": { + "type": "string" + }, + "kills": { + "type": "integer" + }, + "last_kill": { + "type": "string" + }, + "last_tagged": { + "type": "string" + }, + "name": { + "type": "string" + }, + "revives": { + "type": "integer" + }, + "state": { + "type": "integer" + } + } } } } \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 3bd97e2..ab3484e 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1,4 +1,33 @@ basePath: / +definitions: + main.Login: + properties: + name: + type: string + password: + type: string + type: object + main.Player: + properties: + cures: + type: integer + extensions: + type: integer + id: + type: string + kills: + type: integer + last_kill: + type: string + last_tagged: + type: string + name: + type: string + revives: + type: integer + state: + type: integer + type: object info: contact: {} description: This is the Swagger documentation for DCU Games Society's 2022 Humans @@ -6,13 +35,169 @@ info: title: DCU Games Society Humans Vs Zombies version: "1.0" paths: - /: + /cure: get: - description: Home page + description: Cures a zombie or infected human + parameters: + - description: Target ID + in: path + name: target + required: true + type: string + produces: + - text/plain + responses: + "200": + description: OK + "401": + description: User is not logged in + schema: + type: string + "403": + description: No cures available + schema: + type: string + "404": + description: Target does not exist + schema: + type: string + "409": + description: Target is not a zombie + schema: + type: string + summary: Cure + /kill: + get: + description: Kills a zombie if user is authenticated as a human. Gives zombie + target the stunned state + parameters: + - description: Target ID + in: path + name: target + required: true + type: string + produces: + - text/plain + responses: + "200": + description: OK + "401": + description: User is not logged in + schema: + type: string + "403": + description: Killer is not a human + schema: + type: string + "404": + description: Target does not exist + schema: + type: string + "409": + description: Target is not a zombie + schema: + type: string + summary: Kill + /login: + post: + consumes: + - application/json + description: Login + parameters: + - description: Player login + in: body + name: info + required: true + schema: + $ref: '#/definitions/main.Login' produces: - application/json responses: "200": description: OK - summary: Home + schema: + $ref: '#/definitions/main.Player' + "400": + description: Bad Request + "403": + description: Forbidden + summary: Login + /me: + get: + description: Shows user information + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/main.Player' + "401": + description: User is not logged in + schema: + type: string + summary: Me + /revive: + get: + description: Revives a stunned zombie + parameters: + - description: Target ID + in: path + name: target + required: true + type: string + produces: + - text/plain + responses: + "200": + description: OK + "401": + description: User is not logged in + schema: + type: string + "403": + description: No revives available + schema: + type: string + "404": + description: Target does not exist + schema: + type: string + "409": + description: Target is not stunned + schema: + type: string + summary: Revive + /tag: + get: + description: Tag a human as a zombie. Gives target the infected state if user + is a zombie or core zombie. + parameters: + - description: Target ID + in: path + name: target + required: true + type: string + produces: + - text/plain + responses: + "200": + description: OK + "401": + description: User is not logged in + schema: + type: string + "403": + description: Tagger is not a zombie + schema: + type: string + "404": + description: Target does not exist + schema: + type: string + "409": + description: Target is not human + schema: + type: string + summary: Tag swagger: "2.0" diff --git a/go.mod b/go.mod index 105f294..7e81314 100644 --- a/go.mod +++ b/go.mod @@ -14,14 +14,19 @@ require ( github.com/go-openapi/jsonreference v0.20.0 // indirect github.com/go-openapi/spec v0.20.7 // indirect github.com/go-openapi/swag v0.22.3 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/securecookie v1.1.1 // indirect + github.com/gorilla/sessions v1.2.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-sqlite3 v1.14.16 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe // indirect github.com/swaggo/swag v1.8.7 // indirect github.com/urfave/cli/v2 v2.23.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect + golang.org/x/crypto v0.1.0 // indirect golang.org/x/net v0.1.0 // indirect golang.org/x/sys v0.1.0 // indirect golang.org/x/tools v0.2.0 // indirect diff --git a/go.sum b/go.sum index dd74b60..ac7532c 100644 --- a/go.sum +++ b/go.sum @@ -24,8 +24,14 @@ github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyr github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= +github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -38,6 +44,8 @@ github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= @@ -63,6 +71,8 @@ github.com/urfave/cli/v2 v2.23.0 h1:pkly7gKIeYv3olPAeNajNpLjeJrmTPYCoZWaV+2VfvE= github.com/urfave/cli/v2 v2.23.0/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= diff --git a/main.go b/main.go index 1a36f51..a113c17 100644 --- a/main.go +++ b/main.go @@ -1,17 +1,71 @@ package main import ( + "database/sql" "encoding/json" + //"errors" "fmt" "log" "net/http" "time" "github.com/gorilla/mux" + "github.com/gorilla/sessions" "github.com/swaggo/http-swagger" + + _ "github.com/mattn/go-sqlite3" _ "games.dcu.ie/hvz/v2/docs" ) +var store = sessions.NewCookieStore([]byte("wuhcwe789cui")) +var db *sql.DB + +func get_all_players() []Player { + rows, _ := db.Query("SELECT id FROM players") + players := []Player{} + var t_player Player + var id string + for rows.Next() { + rows.Scan(&id) + t_player, _ = get_player(id) + players = append(players, t_player) + } + return players +} + +func get_player(id string) (Player, error) { + tmp_player := Player{} + var last_tagged string + var last_kill string + time_format := time.RFC3339 + row := db.QueryRow("SELECT * FROM players WHERE id = ?", id) + err := row.Scan(&tmp_player.Id, &tmp_player.Name, &tmp_player.password, &tmp_player.State, &last_tagged, &tmp_player.Kills, &last_kill, &tmp_player.Cures, &tmp_player.Revives, &tmp_player.Extensions) + tmp_player.Last_tagged, _ = time.Parse(time_format, last_tagged) + tmp_player.Last_kill, _ = time.Parse(time_format, last_kill) + if err != nil { + return Player{}, err + } + return tmp_player, nil +} + +func save_player(player Player) { + tmp_id := "" + row := db.QueryRow("SELECT id FROM players WHERE id = ?", player.Id) + err := row.Scan(&tmp_id) + var statement *sql.Stmt + if err != nil { + statement, _ = db.Prepare("INSERT INTO players (id, name, password, state, last_tagged, kills, last_kill, cures, revives, extensions) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") + last_tagged, _ := player.Last_tagged.MarshalText() + last_kill, _ := player.Last_kill.MarshalText() + statement.Exec(player.Id, player.Name, player.password, player.State, last_tagged, player.Kills, last_kill, player.Cures, player.Revives, player.Extensions) + } else { + statement, err = db.Prepare("UPDATE players SET id = ?, name = ?, password = ?, state = ?, last_tagged = ?, kills = ?, last_kill = ?, cures = ?, revives = ?, extensions = ? WHERE id = ?") + last_tagged, _ := player.Last_tagged.MarshalText() + last_kill, _ := player.Last_kill.MarshalText() + statement.Exec(player.Id, player.Name, player.password, player.State, last_tagged, player.Kills, last_kill, player.Cures, player.Revives, player.Extensions, player.Id) + } +} + // @title DCU Games Society Humans Vs Zombies // @version 1.0 // @description This is the Swagger documentation for DCU Games Society's 2022 Humans Vs Zombies event. @@ -19,33 +73,255 @@ import ( // @host // @BasePath / func handleRequests() { - myRouter := mux.NewRouter().StrictSlash(true) - myRouter.HandleFunc("/", homePage) - myRouter.PathPrefix("/docs/").Handler(httpSwagger.WrapHandler) + router := mux.NewRouter().StrictSlash(false) + router.Path("/me").Methods(http.MethodGet).HandlerFunc(me) + router.Path("/login").Methods(http.MethodPost).HandlerFunc(login) + router.Path("/tag/{target}").Methods(http.MethodGet).HandlerFunc(tag) + router.Path("/kill/{target}").Methods(http.MethodGet).HandlerFunc(kill) + router.Path("/cure/{target}").Methods(http.MethodGet).HandlerFunc(cure) + router.Path("/revive/{target}").Methods(http.MethodGet).HandlerFunc(revive) + router.PathPrefix("/docs/").Handler(httpSwagger.WrapHandler) - log.Fatal(http.ListenAndServe(":8000", myRouter)) + log.Fatal(http.ListenAndServe(":8000", router)) } -// @Summary Home -// @Description Home page +// @Summary Login +// @Description Login // @Produce json -// @Success 200 -// @Router / [get] -func homePage(w http.ResponseWriter, r *http.Request) { - player := Player{ - id: 0, - name: "Malachy Byrne", - state: 4, - pin: "1234", - infection_time: time.Now(), - kills: 0, - last_kill: time.Now(), +// @Accept json +// @Param info body Login true "Player login" +// @Success 200 {object} Player +// @Failure 400 +// @Failure 403 +// @Router /login [post] +func login(w http.ResponseWriter, r *http.Request) { + l := Login{} + + if err := json.NewDecoder(r.Body).Decode(&l); err != nil { + fmt.Println(err) + http.Error(w, "Error decoding response object", http.StatusBadRequest) + return } - fmt.Println(player) - w.Header().Set("Content-Type", "application/json") + + players := get_all_players() + for _, player := range players { + if (player.Name == l.Name && player.login(l.Pass)) { + session, _ := store.Get(r, "session") + session.Values["userID"] = player.Id + session.Save(r, w) + http.Redirect(w, r, "/me", http.StatusFound) + return + } + } + http.Error(w, "Username or password incorrect", http.StatusForbidden) +} + +// @Summary Tag +// @Description Tag a human as a zombie. Gives target the infected state if user is a zombie or core zombie. +// @Produce plain +// @Param target path string true "Target ID" +// @Success 200 +// @Failure 401 {string} string "User is not logged in" +// @Failure 403 {string} string "Tagger is not a zombie" +// @Failure 404 {string} string "Target does not exist" +// @Failure 409 {string} string "Target is not human" +// @Router /tag [get] +func tag(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + target_id := vars["target"] + + sess, _ := store.Get(r, "session") + id, ok := sess.Values["userID"] + if !ok { + http.Error(w, "User not logged in", http.StatusUnauthorized) + return + } + + player, _ := get_player(id.(string)) + if (player.State != CoreZombie && player.State != Zombie) { + http.Error(w, "Tagger is not a zombie", http.StatusForbidden) + return + } + + target, err := get_player(target_id) + if (err != nil) { + http.Error(w, "Target not found", http.StatusNotFound) + return + } + if (target.State != Human) { + http.Error(w, "Target not human", http.StatusConflict) + return + } + target.State = InfectedHuman + target.Last_tagged = time.Now() + player.Last_kill = time.Now() + player.Kills += 1 + save_player(target) + save_player(player) + fmt.Fprintf(w, "Successfully tagged target") +} + +// @Summary Kill +// @Description Kills a zombie if user is authenticated as a human. Gives zombie target the stunned state +// @Produce plain +// @Param target path string true "Target ID" +// @Success 200 +// @Failure 401 {string} string "User is not logged in" +// @Failure 403 {string} string "Killer is not a human" +// @Failure 404 {string} string "Target does not exist" +// @Failure 409 {string} string "Target is not a zombie" +// @Router /kill [get] +func kill(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + target_id := vars["target"] + + sess, _ := store.Get(r, "session") + id, ok := sess.Values["userID"] + if !ok { + http.Error(w, "User not logged in", http.StatusUnauthorized) + return + } + + tagger, _ := get_player(id.(string)) + if (tagger.State != Human) { + http.Error(w, "Killer is not a human", http.StatusForbidden) + return + } + + target, err := get_player(target_id) + if err != nil { + http.Error(w, "Target not found", http.StatusNotFound) + return + } + if (target.State != Zombie && target.State != CoreZombie) { + http.Error(w, "Target not a zombie", http.StatusConflict) + } + + target.State = StunnedZombie + target.Last_tagged = time.Now() + tagger.Last_kill = time.Now() + tagger.Kills += 1 + save_player(target) + save_player(tagger) + fmt.Fprintln(w, "Successfully killed target") +} + +// @Summary Me +// @Description Shows user information +// @Produce json +// @Success 200 {object} Player +// @Failure 401 {string} string "User is not logged in" +// @Router /me [get] +func me (w http.ResponseWriter, r *http.Request) { + sess, _ := store.Get(r, "session") + id, ok := sess.Values["userID"] + if !ok { + http.Error(w, "User not logged in", http.StatusUnauthorized) + return + } + + player, _ := get_player(id.(string)) json.NewEncoder(w).Encode(player) } +// @Summary Cure +// @Description Cures a zombie or infected human +// @Produce plain +// @Success 200 +// @Failure 401 {string} string "User is not logged in" +// @Failure 403 {string} string "No cures available" +// @Failure 404 {string} string "Target does not exist" +// @Failure 409 {string} string "Target is not a zombie" +// @Param target path string true "Target ID" +// @Router /cure [get] +func cure(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + target_id := vars["target"] + + sess, _ := store.Get(r, "session") + id, ok := sess.Values["userID"] + if !ok { + http.Error(w, "User not logged in", http.StatusUnauthorized) + return + } + + target, err := get_player(target_id) + if err != nil { + http.Error(w, "Target does not exist", http.StatusNotFound) + return + } + + player, _ := get_player(id.(string)) + if player.Cures == 0 { + http.Error(w, "Not enough cures", http.StatusForbidden) + return + } + + if (target.State != Zombie && target.State != StunnedZombie && target.State != InfectedHuman) { + http.Error(w, "Target is not a zombie", http.StatusConflict) + return + } + + target.State = Human + player.Cures -= 1 + save_player(target) + save_player(player) +} + +// @Summary Revive +// @Description Revives a stunned zombie +// @Produce plain +// @Success 200 +// @Failure 401 {string} string "User is not logged in" +// @Failure 403 {string} string "No revives available" +// @Failure 404 {string} string "Target does not exist" +// @Failure 409 {string} string "Target is not stunned" +// @Param target path string true "Target ID" +// @Router /revive [get] +func revive(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + target_id := vars["target"] + + sess, _ := store.Get(r, "session") + id, ok := sess.Values["userID"] + if !ok { + http.Error(w, "User not logged in", http.StatusUnauthorized) + return + } + + target, err := get_player(target_id) + if err != nil { + http.Error(w, "Target does not exist", http.StatusNotFound) + return + } + + player, _ := get_player(id.(string)) + if player.Revives == 0 { + http.Error(w, "Not enough revives", http.StatusForbidden) + return + } + + if (target.State != StunnedZombie) { + http.Error(w, "Target is not stunned", http.StatusConflict) + return + } + + target.State = Zombie + player.Revives -= 1 + save_player(target) + save_player(player) +} + func main() { + db, _ = sql.Open("sqlite3", "players.db") + statement, err := db.Prepare("CREATE TABLE IF NOT EXISTS players (id VARCHAR(7) PRIMARY KEY, name VARCHAR(64), password varchar(128), state INTEGER, last_tagged VARCHAR(25), kills INTEGER, last_kill VARCHAR(25), cures INTEGER, revives INTEGER, extensions INTEGER)") + + if err != nil { + fmt.Println(err) + } else { + fmt.Println("table created successfully") + } + statement.Exec() + handleRequests() } diff --git a/types.go b/types.go index 2158491..87bbfc1 100644 --- a/types.go +++ b/types.go @@ -1,25 +1,70 @@ package main import ( + "fmt" "time" + + "golang.org/x/crypto/bcrypt" + "github.com/google/uuid" ) type State int const ( - CoreZombie State = iota + 1 + CoreZombie State = iota Zombie + StunnedZombie InfectedHuman Human Dead ) type Player struct { - id int `json:"id"` - name string `json:"name"` - state State `json:"state"` - pin string `json:"pin"` - infection_time time.Time `json:"infection_time"` - kills int `json:"kills"` - last_kill time.Time `json:"last_kill"` + Id string `json:"id"` + Name string `json:"name"` + password string + State State `json:"state"` + Last_tagged time.Time `json:"last_tagged"` + Kills int `json:"kills"` + Last_kill time.Time `json:"last_kill"` + Cures int `json:"cures"` + Revives int `json:"revives"` + Extensions int `json:"extensions"` +} + +type Login struct { + Name string `json:"name"` + Pass string `json:"password"` +} + +func gen_pass(password string) (string) { + password_bytes := []byte(password) + + hashed_bytes, _ := bcrypt.GenerateFromPassword(password_bytes, bcrypt.MinCost) + + return string(hashed_bytes) +} + +func new_player(name string, password string, state State) (Player) { + new_player := Player{ + Id: uuid.New().String()[0:7], + Name: name, + password: gen_pass(password), + State: state, + Kills: 0, + Cures: 3, + Revives: 3, + Extensions: 3, + } + return new_player +} + +func (p *Player) login (password string) (bool) { + succ := bcrypt.CompareHashAndPassword([]byte(p.password), []byte(password)) + if (succ == nil) { + return true + } else { + fmt.Println(succ) + return false + } }