diff --git a/api/v1/openapi.yaml b/api/v1/openapi.yaml index 54711ad..4ebef8d 100644 --- a/api/v1/openapi.yaml +++ b/api/v1/openapi.yaml @@ -57,6 +57,26 @@ paths: "500": $ref: "#/components/responses/InternalError" + /v1/trainings/by-slug/{trainingSlug}: + get: + summary: Get a training by slug + operationId: getTrainingBySlug + tags: + - Trainings + parameters: + - $ref: "#/components/parameters/TrainingSlug" + responses: + "200": + description: A training + content: + application/json: + schema: + $ref: "#/components/schemas/GetTrainingResponse" + "404": + $ref: "#/components/responses/NotFoundError" + "500": + $ref: "#/components/responses/InternalError" + /v1/trainings/{trainingID}: get: summary: Get a training by ID @@ -484,6 +504,7 @@ components: schema: $ref: "#/components/schemas/TrainingDateID" description: Training Date ID + TrainingDateAttendeeID: in: path name: trainingDateAttendeeID @@ -492,6 +513,14 @@ components: $ref: "#/components/schemas/TrainingDateAttendeeID" description: Training Date Attendee ID + TrainingSlug: + in: path + name: trainingSlug + required: true + schema: + type: string + description: Training slug + schemas: CreateTrainingRequest: $ref: "#/components/schemas/NewTraining" diff --git a/internal/server/api.gen.go b/internal/server/api.gen.go index 40a5116..0d363d9 100644 --- a/internal/server/api.gen.go +++ b/internal/server/api.gen.go @@ -216,6 +216,9 @@ type UpdateTrainingRequest = NewTraining // UpdateTrainingResponse defines model for UpdateTrainingResponse. type UpdateTrainingResponse = Training +// TrainingSlug defines model for TrainingSlug. +type TrainingSlug = string + // InternalError Schema that carries the details of an error in an HTTP response. See https://datatracker.ietf.org/doc/html/rfc7807 for more information. type InternalError = ProblemDetails @@ -257,6 +260,9 @@ type ServerInterface interface { // Create a new training // (POST /v1/trainings) CreateTraining(c *fiber.Ctx) error + // Get a training by slug + // (GET /v1/trainings/by-slug/{trainingSlug}) + GetTrainingBySlug(c *fiber.Ctx, trainingSlug TrainingSlug) error // List all upcoming dates of all trainings // (GET /v1/trainings/upcoming-dates) ListAllUpcomingTrainingDates(c *fiber.Ctx) error @@ -332,6 +338,22 @@ func (siw *ServerInterfaceWrapper) CreateTraining(c *fiber.Ctx) error { return siw.Handler.CreateTraining(c) } +// GetTrainingBySlug operation middleware +func (siw *ServerInterfaceWrapper) GetTrainingBySlug(c *fiber.Ctx) error { + + var err error + + // ------------- Path parameter "trainingSlug" ------------- + var trainingSlug TrainingSlug + + err = runtime.BindStyledParameterWithOptions("simple", "trainingSlug", c.Params("trainingSlug"), &trainingSlug, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Invalid format for parameter trainingSlug: %w", err).Error()) + } + + return siw.Handler.GetTrainingBySlug(c, trainingSlug) +} + // ListAllUpcomingTrainingDates operation middleware func (siw *ServerInterfaceWrapper) ListAllUpcomingTrainingDates(c *fiber.Ctx) error { @@ -763,6 +785,8 @@ func RegisterHandlersWithOptions(router fiber.Router, si ServerInterface, option router.Post(options.BaseURL+"/v1/trainings", wrapper.CreateTraining) + router.Get(options.BaseURL+"/v1/trainings/by-slug/:trainingSlug", wrapper.GetTrainingBySlug) + router.Get(options.BaseURL+"/v1/trainings/upcoming-dates", wrapper.ListAllUpcomingTrainingDates) router.Delete(options.BaseURL+"/v1/trainings/:trainingID", wrapper.DeleteTraining) @@ -873,6 +897,45 @@ func (response CreateTraining500ApplicationProblemPlusJSONResponse) VisitCreateT return ctx.JSON(&response) } +type GetTrainingBySlugRequestObject struct { + TrainingSlug TrainingSlug `json:"trainingSlug"` +} + +type GetTrainingBySlugResponseObject interface { + VisitGetTrainingBySlugResponse(ctx *fiber.Ctx) error +} + +type GetTrainingBySlug200JSONResponse GetTrainingResponse + +func (response GetTrainingBySlug200JSONResponse) VisitGetTrainingBySlugResponse(ctx *fiber.Ctx) error { + ctx.Response().Header.Set("Content-Type", "application/json") + ctx.Status(200) + + return ctx.JSON(&response) +} + +type GetTrainingBySlug404ApplicationProblemPlusJSONResponse struct { + NotFoundErrorApplicationProblemPlusJSONResponse +} + +func (response GetTrainingBySlug404ApplicationProblemPlusJSONResponse) VisitGetTrainingBySlugResponse(ctx *fiber.Ctx) error { + ctx.Response().Header.Set("Content-Type", "application/problem+json") + ctx.Status(404) + + return ctx.JSON(&response) +} + +type GetTrainingBySlug500ApplicationProblemPlusJSONResponse struct { + InternalErrorApplicationProblemPlusJSONResponse +} + +func (response GetTrainingBySlug500ApplicationProblemPlusJSONResponse) VisitGetTrainingBySlugResponse(ctx *fiber.Ctx) error { + ctx.Response().Header.Set("Content-Type", "application/problem+json") + ctx.Status(500) + + return ctx.JSON(&response) +} + type ListAllUpcomingTrainingDatesRequestObject struct { } @@ -1668,6 +1731,9 @@ type StrictServerInterface interface { // Create a new training // (POST /v1/trainings) CreateTraining(ctx context.Context, request CreateTrainingRequestObject) (CreateTrainingResponseObject, error) + // Get a training by slug + // (GET /v1/trainings/by-slug/{trainingSlug}) + GetTrainingBySlug(ctx context.Context, request GetTrainingBySlugRequestObject) (GetTrainingBySlugResponseObject, error) // List all upcoming dates of all trainings // (GET /v1/trainings/upcoming-dates) ListAllUpcomingTrainingDates(ctx context.Context, request ListAllUpcomingTrainingDatesRequestObject) (ListAllUpcomingTrainingDatesResponseObject, error) @@ -1793,6 +1859,33 @@ func (sh *strictHandler) CreateTraining(ctx *fiber.Ctx) error { return nil } +// GetTrainingBySlug operation middleware +func (sh *strictHandler) GetTrainingBySlug(ctx *fiber.Ctx, trainingSlug TrainingSlug) error { + var request GetTrainingBySlugRequestObject + + request.TrainingSlug = trainingSlug + + handler := func(ctx *fiber.Ctx, request interface{}) (interface{}, error) { + return sh.ssi.GetTrainingBySlug(ctx.UserContext(), request.(GetTrainingBySlugRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "GetTrainingBySlug") + } + + response, err := handler(ctx, request) + + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } else if validResponse, ok := response.(GetTrainingBySlugResponseObject); ok { + if err := validResponse.VisitGetTrainingBySlugResponse(ctx); err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + } else if response != nil { + return fmt.Errorf("unexpected response type: %T", response) + } + return nil +} + // ListAllUpcomingTrainingDates operation middleware func (sh *strictHandler) ListAllUpcomingTrainingDates(ctx *fiber.Ctx) error { var request ListAllUpcomingTrainingDatesRequestObject @@ -2338,45 +2431,45 @@ func (sh *strictHandler) ListTrainingUpcomingDates(ctx *fiber.Ctx, trainingID Tr // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/+xczXLjuBF+FRSSW2hRk92t3dIpjj3ZdWUzdjx2Dpn4AJMtETMkwAFAe1QuPUlOeZfk", - "vVIASIqkQJH6s2StTqORwMbX/41G0y844EnKGTAl8egFp0SQBBQI8787QSijbHJJFJwrBSwEuLrUv4Qg", - "A0FTRTnDo3Id0gtRsRJdXWIPU70gJSrCHmYkATzCyk3WwwK+ZlRAiEdKZOBhGUSQEL3f7wWM8Qj/zp/D", - "9e2v0m9BOZt5NQa6gffBuyWcDXxLsXXB2gIkA2emqciUMwlG+1dMgWAkfi8EF/qLgDMFTOmPJE1jGhAN", - "1U8Ff4wh+cNnqXG/9Nz6xj51CYrQWNrt6wIo9kdgAMw8fMWeSEzDK5Zman+oDAZENYg5tA9c/YVnLNwX", - "rA9cobEGUECaFTZgdHkhgChwecotfM1AGpyp4CkIRa36NQzCpvqjmqba4KQSlE00t5AQGutfxlwkROFR", - "/o23uJTKjyoLc0mEMCZZrPBoTGIJ5epHzmMgTC+3tu3YMo04a/mFS2qlsPDjrOoYnyxxr8RqSXolpxVS", - "DyU2/vgZAqX3WSZD6zZG2XF8PcajT8sV+gGeXYTwzGuq4ZHGcbd50EA/iyMic1JhP3FHRN4Q2nOxXbdm", - "KK7qgYbYs4zNEdTBL8r/wamBVuslYShASqfBBCQlAVXTmgFTpn7CHk4oo0mW4NG7EgFlCiZgvDwkCmpP", - "mS8cVh+SqXSSJ98s+R+6tqLymsW0ZvIVVcTcxhO3Qxhz6GszUhGh7mhSZ0zRxMFYQ48593MKOeMV9BWo", - "XqmUigoKtP0cbmNHczjYalbttuY+5tpqqpvbSi0VOAyiPagKGuiPWgwKEtlXEqXx5BSJEGRqjCnOJr3j", - "cG4rVfRzSN0GsZExbGQIbSHNcO+2hZ9BuYLjBc+YqjLSzMGZTZytYWq4aA8NZJaGS5wtmE7Z7HWyWUP8", - "byu2VcC/KT/8lUp1Hsf3acATyiZV9mWVkTIcNmO1ykGuEi5z7SxES1U7/q3Jce0YaPG5nL25txaEy8Dd", - "UljVTfrsuNlOXTsUGt79TutTd1Gu+sapVFi7VGjGxtMB4QgPCG11x6mX0dXLuCksoOEUSVFwLvpEJgSw", - "wMgQmLbKT/jin3/FHn5/f4s9fP/xsrJT/pyHv51N+Fn+ZcIZTAcXBaHKj2cpCb6QiUVEVIRHeEJVTB4H", - "CREgo6+DgCd+9NWfTiahIJLGPs27g76hWrQvK2XvfJucK7ccao21hSbsR+MMSEVEoYAIQUEiFQEK7QOI", - "jxFhtuWGKNOff7m7u0FFH3WAPgKgSKlUjnw/JIooQYIvIAYU1HjAxcQPeeBHKol9MQ5+/Gn4IxpzgRIu", - "AFFmLZJyNviXjXe1XGAgLEI+R1GWEHYmgITkMQYE39KYMEMHyRQCOqYBUhypiErEg1xQoHnRrOUdyoHT", - "AZhUhFnLae56f3uFBIzBEjMSo9pX6LgQWrn5aptKRVTm0M1dBFbadgEKeAhoAgwEURCix6mhzAWdUIYk", - "iCcQRri9+a4EW0VVDD1kLbMkIWLaoIk0QSdv9ot1hNlBulkk6l8LNkqReoURVTTr8pJqQXLwFX4z7R/+", - "Waoth50O37s7fLvI23+1F9yn4dLmckUwTd4a+Eg7DG/J/eqS0q+eU4vT36B2kTpPrDRJuVAr5NX0y8RX", - "peu2gLwh0wSY6hBTmptDh4jMsi7xrCuW8s52FyJZF9TOAJVlXb/QUTh7U3FFVirqvOub9x+why+ub2+u", - "b8/v3i8Wes584/Y8azSnq8hNyvdlMjw1b18jfyxq4HQVecSdBpe631K7vo7/dBW5cX+xKdA3cwUyM8f4", - "MS9mlEhg7CBPo5iS5E9P/LOCIDLlhy4+5iNn/+Cf1X//HUTob0TA//6DPZwJ/VTR4Xh+fh4sPK1jBA0g", - "F09O6UbwVFBQREwr52us6cpf/o7Ob66wh59ASHsiHg7eDYZ6IU+BkZTiEf5uMBwMtZaIiozQ/Kd3ZVVk", - "vpiAYU0L1rj9VYhH9c49boy8/XE4XDK7tdrMlvuKwDG6dY5iKpVpGZS4Zh7+wWJxbVFi9uszemboy3Yg", - "ck4RieMKWQ8romXzCc9F8GDrFoeo6tft+ZAhSPVnHk63Jib3kESjnadEBrMFXb3bGYh2ZZVTmYF5JNSa", - "+r6fppqzi9vQsQWOCGLwXOq5Rc0zr+4ifpZfkZ2Vt5qtHtN2ZbprB+q8qnWo6Nfcm6qmjwpekeXVaO37", - "btnXxzq36pV1RE3Asq8SX+b3vzNbO8dgK8O6Fi/N9xVnro56tySr+ZJavnlYUPr3S8aXLaBwjyK3rCMy", - "t4bHqZ2qdkdDpxdUBh62LLzteYxrKMOZcFTlAnpPSvkZVH+NpJlDI/USbHOlbD+3uavuXrltuDMQPXJb", - "Zh7ZMLftya4su31Na2k49bvzYjMZHmZcaJ+8WZI+S/kdTMacJ8quUqdfRXtpewYHFzbax9z3WhbXuh7L", - "wodxwAOuj1HRKlsvIMy/sl2YFcqujS3O67266BCtWKxpaR1ixWaAbVa2HYTwd1LsdXnmwYX0RvHXQ7k9", - "KsB96XfXdePKCWC4UyB9E8BxFZGdJrpO4vBJMXTdu8gsx7SPKJJ1j6L3jWloLtADqFdLMPWadVn50b9w", - "Le9pjyLidb+fvPfSd+GGvTMCFvrfTi28J2tur6BL/nYSEf3y3bc+dV3tfbrjLfLcrw06DNEsOMzw6Kr9", - "5p6S628H9vTi/rMjK57e9hR2V3uiOu+yxvmv1MbBHgRLhJufCI9AoTsPN6unvEONL1s5ZL5Nk3mNY+pa", - "RdvwVQCtXLQd4fm1lxvsKM361aH5FR1tPpj/W3e5VV5beMvOR0qeire7jsAdc04WmwEuvl/ZO4t3NVb0", - "zPxFkJNb9nxH5i37ZGoZ+m05ZFoa+OreuMJ8nfOvVryJeQL339l4M3MFjim8zjlKTcW8TmyV0mCTByRG", - "ITxBzFPrL2ZtbVZ65PuxXhdxqUbfDYdDo698sybF68JaJCKPPFO1GcF8nHqOb/Yw+38AAAD//5Sh0RPV", - "VQAA", + "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", } // GetSwagger returns the content of the embedded swagger specification file