diff --git a/docs/docs.go b/docs/docs.go index 1969790..ab6a9c7 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -64,6 +64,52 @@ const docTemplate = `{ } } }, + "/account/get_account": { + "get": { + "description": "This endpoint gets a multiplayer account's info.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "account" + ], + "summary": "Gets an account", + "parameters": [ + { + "description": "account acquisition request body", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/account.GetAccountArgs" + } + } + ], + "responses": { + "200": { + "description": "Account successfully retrieved", + "schema": { + "$ref": "#/definitions/account.Account" + } + }, + "400": { + "description": "Bad Request", + "schema": {} + }, + "403": { + "description": "Forbidden", + "schema": {} + }, + "500": { + "description": "Internal Server Error", + "schema": {} + } + } + } + }, "/game/create_game": { "post": { "description": "This endpoint creates a new multiplayer game, optionally protected by a password.", @@ -202,6 +248,16 @@ const docTemplate = `{ "Impossible" ] }, + "account.GetAccountArgs": { + "description": "Structure for the account acquisition request payload.", + "type": "object", + "properties": { + "account_id": { + "description": "The account ID for the account that will be retrieved.", + "type": "integer" + } + } + }, "game.CreateGameArgs": { "description": "Structure for the game creation request payload.", "type": "object", diff --git a/docs/swagger.json b/docs/swagger.json index 8f630d8..54036fc 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -55,6 +55,52 @@ } } }, + "/account/get_account": { + "get": { + "description": "This endpoint gets a multiplayer account's info.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "account" + ], + "summary": "Gets an account", + "parameters": [ + { + "description": "account acquisition request body", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/account.GetAccountArgs" + } + } + ], + "responses": { + "200": { + "description": "Account successfully retrieved", + "schema": { + "$ref": "#/definitions/account.Account" + } + }, + "400": { + "description": "Bad Request", + "schema": {} + }, + "403": { + "description": "Forbidden", + "schema": {} + }, + "500": { + "description": "Internal Server Error", + "schema": {} + } + } + } + }, "/game/create_game": { "post": { "description": "This endpoint creates a new multiplayer game, optionally protected by a password.", @@ -193,6 +239,16 @@ "Impossible" ] }, + "account.GetAccountArgs": { + "description": "Structure for the account acquisition request payload.", + "type": "object", + "properties": { + "account_id": { + "description": "The account ID for the account that will be retrieved.", + "type": "integer" + } + } + }, "game.CreateGameArgs": { "description": "Structure for the game creation request payload.", "type": "object", diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 0f9d42a..60142ba 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -47,6 +47,13 @@ definitions: - Hard - Very_Hard - Impossible + account.GetAccountArgs: + description: Structure for the account acquisition request payload. + properties: + account_id: + description: The account ID for the account that will be retrieved. + type: integer + type: object game.CreateGameArgs: description: Structure for the game creation request payload. properties: @@ -108,6 +115,37 @@ paths: summary: Create a new account tags: - account + /account/get_account: + get: + consumes: + - application/json + description: This endpoint gets a multiplayer account's info. + parameters: + - description: account acquisition request body + in: body + name: body + required: true + schema: + $ref: '#/definitions/account.GetAccountArgs' + produces: + - application/json + responses: + "200": + description: Account successfully retrieved + schema: + $ref: '#/definitions/account.Account' + "400": + description: Bad Request + schema: {} + "403": + description: Forbidden + schema: {} + "500": + description: Internal Server Error + schema: {} + summary: Gets an account + tags: + - account /game/create_game: post: consumes: diff --git a/internal/account/account_handler.go b/internal/account/account_handler.go index e32ebc0..5cc9dae 100644 --- a/internal/account/account_handler.go +++ b/internal/account/account_handler.go @@ -5,10 +5,18 @@ import ( "net/http" ) -func AccountHandler(w http.ResponseWriter, r *http.Request, db *sql.DB) { +func CreateAccountHandler(w http.ResponseWriter, r *http.Request, db *sql.DB) { if err := CreateAccount(w, r, db); err != nil { // Handle the error, e.g., log it and send an appropriate response to the client http.Error(w, err.Error(), http.StatusInternalServerError) return } } + +func GetAccountHandler(w http.ResponseWriter, r *http.Request, db *sql.DB) { + if err := GetAccount(w, r, db); err != nil { + // Handle the error, e.g., log it and send an appropriate response to the client + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } +} diff --git a/internal/account/get_account.go b/internal/account/get_account.go new file mode 100644 index 0000000..21373f5 --- /dev/null +++ b/internal/account/get_account.go @@ -0,0 +1,87 @@ +package account + +import ( + "database/sql" + "encoding/json" + "errors" + "fmt" + "net/http" +) + +// GetAccountArgs represents the expected structure of the request body for getting an account. +// +// @Description Structure for the account acquisition request payload. +type GetAccountArgs struct { + // The account ID for the account that will be retrieved. + AccountId int64 `json:"account_id"` +} + +// GetAccount gets an account by the account ID. +// +// @Summary Gets an account +// @Description This endpoint gets a multiplayer account's info. +// @Tags account +// @Accept json +// @Produce json +// @Param body body GetAccountArgs true "account acquisition request body" +// +// @Success 200 {object} account.Account "Account successfully retrieved" +// +// @Failure 400 {object} error "Bad Request" +// @Failure 403 {object} error "Forbidden" +// @Failure 500 {object} error "Internal Server Error" +// @Router /account/get_account [get] +func GetAccount(w http.ResponseWriter, r *http.Request, db *sql.DB) error { + + if r.Method != "GET" { + return errors.New("invalid request; request must be a GET request") + } + + decoder := json.NewDecoder(r.Body) + decoder.DisallowUnknownFields() + + argsGotten := GetAccountArgs{} + err := decoder.Decode(&argsGotten) + + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + + return errors.New("an error occurred while decoding the request body:" + err.Error()) + } + + // TODO add sqlx so we don't have to manually provision row results from .Scan + var ( + name string + info string + location string + email string + experienceLevel int + ) + + if err := db.QueryRow("SELECT name, info, location, email, experience_level FROM account WHERE id = $1", argsGotten.AccountId). + Scan(&name, &info, &location, &email, &experienceLevel); err != nil { + if err == sql.ErrNoRows { + return fmt.Errorf("no account exists with the ID %d", argsGotten.AccountId) + } + return fmt.Errorf("an error occurred while getting the account with the ID %d: %v", argsGotten.AccountId, err) + } + + // Now assemble the variables into the Account struct + account := Account{ + Name: name, + Info: info, + Location: location, + Email: email, + ExperienceLevel: ExperienceLevel(experienceLevel), + } + + accountBytes, err := json.Marshal(account) + if err != nil { + return fmt.Errorf("Error marshalling struct: %v", err) + } + + w.Write(accountBytes) + + fmt.Println("Successfully got account!") + return nil +} diff --git a/main.go b/main.go index b7f9868..2d76061 100644 --- a/main.go +++ b/main.go @@ -109,7 +109,11 @@ func main() { })) mux.Handle("/account/create_account", tollbooth.LimitFuncHandler(tollboothLimiterMinute, func(w http.ResponseWriter, r *http.Request) { - account.AccountHandler(w, r, db) + account.CreateAccountHandler(w, r, db) + })) + + mux.Handle("/account/get_account", tollbooth.LimitFuncHandler(tollboothLimiter, func(w http.ResponseWriter, r *http.Request) { + account.GetAccountHandler(w, r, db) })) mux.Handle("/health", tollbooth.LimitFuncHandler(tollboothLimiterHealth, health.HealthCheckHandler))