aboutsummaryrefslogtreecommitdiffhomepage
path: root/backend/api/handler.go
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2024-08-08 20:00:06 +0900
committernsfisis <nsfisis@gmail.com>2024-08-08 20:00:06 +0900
commitef1577a212d1b5c6f908a59b943a512d33d312fe (patch)
tree7c91a689aaea376985ec579d71c1169fdc2ee47a /backend/api/handler.go
parent205cb5e21b960852a06fa28baaa03dbbd6aa835f (diff)
downloadphperkaigi-2025-albatross-ef1577a212d1b5c6f908a59b943a512d33d312fe.tar.gz
phperkaigi-2025-albatross-ef1577a212d1b5c6f908a59b943a512d33d312fe.tar.zst
phperkaigi-2025-albatross-ef1577a212d1b5c6f908a59b943a512d33d312fe.zip
feat(backend/worker): enable `revive` in `golangci-lint`
Diffstat (limited to 'backend/api/handler.go')
-rw-r--r--backend/api/handler.go147
1 files changed, 147 insertions, 0 deletions
diff --git a/backend/api/handler.go b/backend/api/handler.go
new file mode 100644
index 0000000..57d7464
--- /dev/null
+++ b/backend/api/handler.go
@@ -0,0 +1,147 @@
+package api
+
+import (
+ "context"
+ "errors"
+ "net/http"
+
+ "github.com/jackc/pgx/v5"
+ "github.com/labstack/echo/v4"
+
+ "github.com/nsfisis/iosdc-japan-2024-albatross/backend/auth"
+ "github.com/nsfisis/iosdc-japan-2024-albatross/backend/db"
+)
+
+type Handler struct {
+ q *db.Queries
+ hubs GameHubsInterface
+}
+
+type GameHubsInterface interface {
+ StartGame(gameID int) error
+}
+
+func (h *Handler) PostLogin(ctx context.Context, request PostLoginRequestObject) (PostLoginResponseObject, error) {
+ username := request.Body.Username
+ password := request.Body.Password
+ userID, err := auth.Login(ctx, h.q, username, password)
+ if err != nil {
+ return PostLogin401JSONResponse{
+ UnauthorizedJSONResponse: UnauthorizedJSONResponse{
+ Message: "Invalid username or password",
+ },
+ }, nil
+ }
+
+ user, err := h.q.GetUserByID(ctx, int32(userID))
+ if err != nil {
+ return PostLogin401JSONResponse{
+ UnauthorizedJSONResponse: UnauthorizedJSONResponse{
+ Message: "Invalid username or password",
+ },
+ }, nil
+ }
+
+ jwt, err := auth.NewJWT(&user)
+ if err != nil {
+ return nil, echo.NewHTTPError(http.StatusInternalServerError, err.Error())
+ }
+
+ return PostLogin200JSONResponse{
+ Token: jwt,
+ }, nil
+}
+
+func (h *Handler) GetToken(_ context.Context, _ GetTokenRequestObject, user *auth.JWTClaims) (GetTokenResponseObject, error) {
+ newToken, err := auth.NewShortLivedJWT(user)
+ if err != nil {
+ return nil, echo.NewHTTPError(http.StatusInternalServerError, err.Error())
+ }
+ return GetToken200JSONResponse{
+ Token: newToken,
+ }, nil
+}
+
+func (h *Handler) GetGames(ctx context.Context, _ GetGamesRequestObject, user *auth.JWTClaims) (GetGamesResponseObject, error) {
+ gameRows, err := h.q.ListGamesForPlayer(ctx, int32(user.UserID))
+ if err != nil {
+ return nil, echo.NewHTTPError(http.StatusInternalServerError, err.Error())
+ }
+ games := make([]Game, len(gameRows))
+ for i, row := range gameRows {
+ var startedAt *int
+ if row.StartedAt.Valid {
+ startedAtTimestamp := int(row.StartedAt.Time.Unix())
+ startedAt = &startedAtTimestamp
+ }
+ var problem *Problem
+ if row.ProblemID != nil {
+ if row.Title == nil || row.Description == nil {
+ panic("inconsistent data")
+ }
+ problem = &Problem{
+ ProblemID: int(*row.ProblemID),
+ Title: *row.Title,
+ Description: *row.Description,
+ }
+ }
+ games[i] = Game{
+ GameID: int(row.GameID),
+ GameType: GameGameType(row.GameType),
+ State: GameState(row.State),
+ DisplayName: row.DisplayName,
+ DurationSeconds: int(row.DurationSeconds),
+ StartedAt: startedAt,
+ Problem: problem,
+ }
+ }
+ return GetGames200JSONResponse{
+ Games: games,
+ }, nil
+}
+
+func (h *Handler) GetGame(ctx context.Context, request GetGameRequestObject, user *auth.JWTClaims) (GetGameResponseObject, error) {
+ // TODO: check user permission
+ gameID := request.GameID
+ row, err := h.q.GetGameByID(ctx, int32(gameID))
+ if err != nil {
+ if errors.Is(err, pgx.ErrNoRows) {
+ return GetGame404JSONResponse{
+ NotFoundJSONResponse: NotFoundJSONResponse{
+ Message: "Game not found",
+ },
+ }, nil
+ }
+ return nil, echo.NewHTTPError(http.StatusInternalServerError, err.Error())
+ }
+ var startedAt *int
+ if row.StartedAt.Valid {
+ startedAtTimestamp := int(row.StartedAt.Time.Unix())
+ startedAt = &startedAtTimestamp
+ }
+ var problem *Problem
+ if row.ProblemID != nil {
+ if row.Title == nil || row.Description == nil {
+ panic("inconsistent data")
+ }
+ if user.IsAdmin || (GameState(row.State) != Closed && GameState(row.State) != WaitingEntries) {
+ problem = &Problem{
+ ProblemID: int(*row.ProblemID),
+ Title: *row.Title,
+ Description: *row.Description,
+ }
+ }
+ }
+ game := Game{
+ GameID: int(row.GameID),
+ GameType: GameGameType(row.GameType),
+ State: GameState(row.State),
+ DisplayName: row.DisplayName,
+ DurationSeconds: int(row.DurationSeconds),
+ StartedAt: startedAt,
+ Problem: problem,
+ }
+ return GetGame200JSONResponse{
+ Game: game,
+ }, nil
+}