From 58ce1742bc4f7d519e957843431472a6f6fddb55 Mon Sep 17 00:00:00 2001 From: Alder Whiteford Date: Tue, 20 Feb 2024 19:06:08 -0500 Subject: [PATCH] Add Swagger Docs for All Endpoints (#230) Co-authored-by: Alder Whiteford Co-authored-by: Garrett Ladley <92384606+garrettladley@users.noreply.github.com> Co-authored-by: garrettladley --- backend/go.mod | 13 +- backend/go.sum | 31 +- backend/src/controllers/auth.go | 59 +- backend/src/controllers/category.go | 74 +- backend/src/controllers/category_tag.go | 29 + backend/src/controllers/club.go | 71 + backend/src/controllers/club_contact.go | 29 + backend/src/controllers/club_event.go | 15 + backend/src/controllers/club_follower.go | 15 + backend/src/controllers/club_member.go | 16 + backend/src/controllers/club_tag.go | 65 +- backend/src/controllers/contact.go | 42 + backend/src/controllers/event.go | 143 + backend/src/controllers/tag.go | 74 +- backend/src/controllers/user.go | 85 +- backend/src/controllers/user_follower.go | 44 + backend/src/controllers/user_member.go | 44 + backend/src/controllers/user_tag.go | 30 + backend/src/docs/docs.go | 3591 ++++++++++++++++++++-- backend/src/docs/swagger.json | 3591 ++++++++++++++++++++-- backend/src/docs/swagger.yaml | 2676 ++++++++++++++-- backend/src/main.go | 2 +- backend/src/services/auth.go | 20 +- backend/src/utilities/response.go | 5 + go.work.sum | 16 +- 25 files changed, 9761 insertions(+), 1019 deletions(-) diff --git a/backend/go.mod b/backend/go.mod index e563947be..927710835 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -30,16 +30,14 @@ require ( require ( github.com/KyleBanks/depth v1.2.1 // indirect - github.com/PuerkitoBio/purell v1.1.1 // indirect - github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/andybalholm/brotli v1.0.5 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.19.6 // indirect - github.com/go-openapi/spec v0.20.4 // indirect - github.com/go-openapi/swag v0.19.15 // indirect + github.com/go-openapi/jsonpointer v0.20.2 // indirect + github.com/go-openapi/jsonreference v0.20.4 // indirect + github.com/go-openapi/spec v0.20.14 // indirect + github.com/go-openapi/swag v0.22.9 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -76,8 +74,7 @@ require ( golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/net v0.21.0 // indirect golang.org/x/sys v0.17.0 // indirect - golang.org/x/tools v0.13.0 // indirect + golang.org/x/tools v0.18.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index cf4c4794a..a3809af3d 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -1,16 +1,11 @@ github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/awnumar/memcall v0.2.0 h1:sRaogqExTOOkkNwO9pzJsL8jrOV29UuUW7teRMfbqtI= github.com/awnumar/memcall v0.2.0/go.mod h1:S911igBPR9CThzd/hYQQmTc9SWNu3ZHIlCGaWsWsoJo= github.com/awnumar/memguard v0.22.4 h1:1PLgKcgGPeExPHL8dCOWGVjIbQUBgJv9OL0F/yE1PqQ= github.com/awnumar/memguard v0.22.4/go.mod h1:+APmZGThMBWjnMlKiSM1X7MVpbIVewen2MTkqWkA/zE= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -77,11 +72,8 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= @@ -106,7 +98,6 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -134,7 +125,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -160,39 +150,26 @@ golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= +golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/postgres v1.5.6 h1:ydr9xEd5YAM0vxVDY0X139dyzNz10spDiDlC7+ibLeU= diff --git a/backend/src/controllers/auth.go b/backend/src/controllers/auth.go index e6d0d7401..e46bf507f 100644 --- a/backend/src/controllers/auth.go +++ b/backend/src/controllers/auth.go @@ -24,14 +24,17 @@ func NewAuthController(authService services.AuthServiceInterface, authSettings c // Me godoc // -// @Summary Gets the current user -// @Description Returns the current user +// @Summary Retrieve the current user given an auth session +// @Description Returns the current user associated with an auth session // @ID get-current-user -// @Tags user +// @Tags auth // @Produce json -// @Success 200 {object} models.User -// @Failure 401 {string} string "failed to get current user" -// @Router /api/v1/auth/me [get] +// @Success 200 {object} models.User +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /auth/me [get] func (a *AuthController) Me(c *fiber.Ctx) error { claims, err := auth.From(c) if err != nil { @@ -50,14 +53,15 @@ func (a *AuthController) Me(c *fiber.Ctx) error { // @Summary Logs in a user // @Description Logs in a user // @ID login-user -// @Tags user +// @Tags auth // @Accept json // @Produce json -// @Param userBody body []string true "User Body" -// @Success 200 {object} string "success" -// @Failure 400 {string} string "failed to parse body" -// @Failure 401 {string} string "failed to login user" -// @Router /api/v1/auth/login [post] +// @Param loginBody body models.LoginUserResponseBody true "Login Body" +// @Success 200 {object} utilities.SuccessResponse +// @Failure 400 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /auth/login [post] func (a *AuthController) Login(c *fiber.Ctx) error { var userBody models.LoginUserResponseBody @@ -87,12 +91,14 @@ func (a *AuthController) Login(c *fiber.Ctx) error { // @Summary Refreshes a user's access token // @Description Refreshes a user's access token // @ID refresh-user -// @Tags user +// @Tags auth // @Accept json // @Produce json -// @Success 200 {object} string "success" -// @Failure 401 {string} string "failed to refresh access token" -// @Router /api/v1/auth/refresh [get] +// @Success 200 {object} utilities.SuccessResponse +// @Failure 400 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /auth/refresh [get] func (a *AuthController) Refresh(c *fiber.Ctx) error { // Extract token values from cookies refreshTokenValue := c.Cookies("refresh_token") @@ -124,12 +130,11 @@ func (a *AuthController) Refresh(c *fiber.Ctx) error { // @Summary Logs out a user // @Description Logs out a user // @ID logout-user -// @Tags user +// @Tags auth // @Accept json // @Produce json -// @Success 200 {object} string -// @Failure 401 {string} string "failed to logout user" -// @Router /api/v1/auth/logout [get] +// @Success 200 {object} utilities.SuccessResponse +// @Router /auth/logout [get] func (a *AuthController) Logout(c *fiber.Ctx) error { // Extract token values from cookies accessTokenValue := c.Cookies("access_token") @@ -151,14 +156,16 @@ func (a *AuthController) Logout(c *fiber.Ctx) error { // @Summary Updates a user's password // @Description Updates a user's password // @ID update-password -// @Tags user +// @Tags auth // @Accept json // @Produce json -// @Param userBody body []string true "User Body" -// @Success 200 {object} string "success" -// @Failure 400 {string} string "failed to parse body" -// @Failure 401 {string} string "failed to update password" -// @Router /api/v1/auth/update-password [post] +// @Param userBody body models.UpdatePasswordRequestBody true "User Body" +// @Success 200 {object} utilities.SuccessResponse +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /auth/update-password [post] func (a *AuthController) UpdatePassword(c *fiber.Ctx) error { var userBody models.UpdatePasswordRequestBody diff --git a/backend/src/controllers/category.go b/backend/src/controllers/category.go index 3458e34bb..e43a6f85e 100644 --- a/backend/src/controllers/category.go +++ b/backend/src/controllers/category.go @@ -20,17 +20,19 @@ func NewCategoryController(categoryService services.CategoryServiceInterface) *C // CreateCategory godoc // -// @Summary Create a category -// @Description Creates a category that is used to group tags +// @Summary Creates a category +// @Description Creates a category // @ID create-category // @Tags category +// @Accept json // @Produce json +// @Param categoryBody body models.CategoryRequestBody true "Category Body" // @Success 201 {object} models.Category -// @Failure 400 {string} string "failed to process the request" -// @Failure 400 {string} string "failed to validate data" -// @Failure 400 {string} string "category with that name already exists" -// @Failure 500 {string} string "failed to create category" -// @Router /api/v1/category/ [post] +// @Failure 400 {string} errors.Error +// @Failure 401 {string} errors.Error +// @Failure 404 {string} errors.Error +// @Failure 500 {string} errors.Error +// @Router /category/ [post] func (cat *CategoryController) CreateCategory(c *fiber.Ctx) error { var categoryBody models.CategoryRequestBody @@ -49,13 +51,17 @@ func (cat *CategoryController) CreateCategory(c *fiber.Ctx) error { // GetCategories godoc // // @Summary Retrieve all categories -// @Description Retrieves all existing categories +// @Description Retrieves all categories // @ID get-categories // @Tags category // @Produce json -// @Success 200 {object} []models.Category -// @Failure 500 {string} string "unable to retrieve categories" -// @Router /api/v1/category/ [get] +// @Param limit query int false "Limit" +// @Param page query int false "Page" +// @Success 200 {object} []models.Category +// @Failure 400 {string} errors.Error +// @Failure 404 {string} errors.Error +// @Failure 500 {string} errors.Error +// @Router /category/ [get] func (cat *CategoryController) GetCategories(c *fiber.Ctx) error { defaultLimit := 10 defaultPage := 1 @@ -71,16 +77,16 @@ func (cat *CategoryController) GetCategories(c *fiber.Ctx) error { // GetCategory godoc // // @Summary Retrieve a category -// @Description Retrieve a category by its ID +// @Description Retrieves a category // @ID get-category // @Tags category // @Produce json -// @Param id path string true "Category ID" -// @Success 200 {object} models.Category -// @Failure 400 {string} string "failed to validate id" -// @Failure 404 {string} string "faied to find category" -// @Failure 500 {string} string "failed to retrieve category" -// @Router /api/v1/category/{id} [get] +// @Param categoryID path string true "Category ID" +// @Success 200 {object} models.Category +// @Failure 400 {string} errors.Error +// @Failure 404 {string} errors.Error +// @Failure 500 {string} errors.Error +// @Router /category/{categoryID} [get] func (cat *CategoryController) GetCategory(c *fiber.Ctx) error { category, err := cat.categoryService.GetCategory(c.Params("categoryID")) if err != nil { @@ -92,17 +98,18 @@ func (cat *CategoryController) GetCategory(c *fiber.Ctx) error { // DeleteCategory godoc // -// @Summary Delete a category -// @Description Delete a category by ID +// @Summary Deletes a category +// @Description Deletes a category // @ID delete-category // @Tags category // @Produce json -// @Param id path string true "Category ID" -// @Success 204 {string} string "no content" -// @Failure 400 {string} string "failed to validate id" -// @Failure 404 {string} string "failed to find category" -// @Failure 500 {string} string "failed to delete category" -// @Router /api/v1/category/{id} [delete] +// @Param categoryID path string true "Category ID" +// @Success 204 {string} utilities.SuccessResponse +// @Failure 400 {string} errors.Error +// @Failure 401 {string} errors.Error +// @Failure 404 {string} errors.Error +// @Failure 500 {string} errors.Error +// @Router /category/{categoryID} [delete] func (cat *CategoryController) DeleteCategory(c *fiber.Ctx) error { if err := cat.categoryService.DeleteCategory(c.Params("categoryID")); err != nil { return err.FiberError(c) @@ -117,13 +124,16 @@ func (cat *CategoryController) DeleteCategory(c *fiber.Ctx) error { // @Description Updates a category // @ID update-category // @Tags category +// @Accept json // @Produce json -// @Param id path string true "Category ID" -// @Success 200 {object} models.Category -// @Failure 400 {string} string "failed to validate id" -// @Failure 404 {string} string "failed to find category" -// @Failure 500 {string} string "failed to update category" -// @Router /api/v1/category/{id} [patch] +// @Param categoryID path string true "Category ID" +// @Param categoryBody body models.CategoryRequestBody true "Category Body" +// @Success 200 {object} models.Category +// @Failure 400 {string} errors.Error +// @Failure 401 {string} errors.Error +// @Failure 404 {string} errors.Error +// @Failure 500 {string} errors.Error +// @Router /category/{categoryID} [put] func (cat *CategoryController) UpdateCategory(c *fiber.Ctx) error { var category models.CategoryRequestBody diff --git a/backend/src/controllers/category_tag.go b/backend/src/controllers/category_tag.go index 65c189ae6..2fa0df394 100644 --- a/backend/src/controllers/category_tag.go +++ b/backend/src/controllers/category_tag.go @@ -16,6 +16,21 @@ func NewCategoryTagController(categoryTagService services.CategoryTagServiceInte return &CategoryTagController{categoryTagService: categoryTagService} } +// GetTagsByCategory godoc +// +// @Summary Retrieve all tags by category +// @Description Retrieves all tags associated with a category +// @ID get-tags-by-category +// @Tags category-tag +// @Produce json +// @Param categoryID path string true "Category ID" +// @Param limit query int false "Limit" +// @Param page query int false "Page" +// @Success 200 {object} []models.Tag +// @Failure 400 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /category/{categoryID}/tags [get] func (ct *CategoryTagController) GetTagsByCategory(c *fiber.Ctx) error { defaultLimit := 10 defaultPage := 1 @@ -28,6 +43,20 @@ func (ct *CategoryTagController) GetTagsByCategory(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(&tags) } +// GetTagByCategory godoc +// +// @Summary Retrieve a tag by category +// @Description Retrieves a tag associated with a category +// @ID get-tag-by-category +// @Tags category-tag +// @Produce json +// @Param categoryID path string true "Category ID" +// @Param tagID path string true "Tag ID" +// @Success 200 {object} models.Tag +// @Failure 400 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /category/{categoryID}/tags/{tagID} [get] func (ct *CategoryTagController) GetTagByCategory(c *fiber.Ctx) error { tag, err := ct.categoryTagService.GetTagByCategory(c.Params("categoryID"), c.Params("tagID")) if err != nil { diff --git a/backend/src/controllers/club.go b/backend/src/controllers/club.go index ac4518c48..7a0c7275f 100644 --- a/backend/src/controllers/club.go +++ b/backend/src/controllers/club.go @@ -15,6 +15,19 @@ func NewClubController(clubService services.ClubServiceInterface) *ClubControlle return &ClubController{clubService: clubService} } +// GetAllClubs godoc +// +// @Summary Retrieve all clubs +// @Description Retrieves all clubs +// @ID get-all-clubs +// @Tags club +// @Produce json +// @Param limit query int false "Limit" +// @Param page query int false "Page" +// @Success 200 {object} []models.Club +// @Failure 400 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /club/ [get] func (cl *ClubController) GetAllClubs(c *fiber.Ctx) error { var queryParams models.ClubQueryParams @@ -33,6 +46,21 @@ func (cl *ClubController) GetAllClubs(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(clubs) } +// CreateClub godoc +// +// @Summary Create a club +// @Description Creates a club +// @ID create-club +// @Tags club +// @Accept json +// @Produce json +// @Param club body models.CreateClubRequestBody true "Club" +// @Success 201 {object} models.Club +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /club/ [post] func (cl *ClubController) CreateClub(c *fiber.Ctx) error { var clubBody models.CreateClubRequestBody if err := c.BodyParser(&clubBody); err != nil { @@ -47,6 +75,19 @@ func (cl *ClubController) CreateClub(c *fiber.Ctx) error { return c.Status(fiber.StatusCreated).JSON(club) } +// GetClub godoc +// +// @Summary Retrieve a club +// @Description Retrieves a club +// @ID get-club +// @Tags club +// @Produce json +// @Param clubID path string true "Club ID" +// @Success 200 {object} models.Club +// @Failure 400 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /club/{clubID} [get] func (cl *ClubController) GetClub(c *fiber.Ctx) error { club, err := cl.clubService.GetClub(c.Params("clubID")) if err != nil { @@ -56,6 +97,22 @@ func (cl *ClubController) GetClub(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(club) } +// UpdateClub godoc +// +// @Summary Update a club +// @Description Updates a club +// @ID update-club +// @Tags club +// @Accept json +// @Produce json +// @Param clubID path string true "Club ID" +// @Param club body models.UpdateClubRequestBody true "Club" +// @Success 200 {object} models.Club +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /club/{clubID} [put] func (cl *ClubController) UpdateClub(c *fiber.Ctx) error { var clubBody models.UpdateClubRequestBody @@ -71,6 +128,20 @@ func (cl *ClubController) UpdateClub(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(updatedClub) } +// DeleteClub godoc +// +// @Summary Delete a club +// @Description Deletes a club +// @ID delete-club +// @Tags club +// @Produce json +// @Param clubID path string true "Club ID" +// @Success 204 {string} utilities.SuccessResponse +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /club/{clubID} [delete] func (cl *ClubController) DeleteClub(c *fiber.Ctx) error { err := cl.clubService.DeleteClub(c.Params("clubID")) if err != nil { diff --git a/backend/src/controllers/club_contact.go b/backend/src/controllers/club_contact.go index f23ddf2e0..ac59a8285 100644 --- a/backend/src/controllers/club_contact.go +++ b/backend/src/controllers/club_contact.go @@ -15,6 +15,19 @@ func NewClubContactController(clubContactService services.ClubContactServiceInte return &ClubContactController{clubContactService: clubContactService} } +// GetClubContacts godoc +// +// @Summary Retrieve all contacts for a club +// @Description Retrieves all contacts associated with a club +// @ID get-contacts-by-club +// @Tags club-contact +// @Produce json +// @Param clubID path string true "Club ID" +// @Success 200 {object} []models.Contact +// @Failure 400 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /club/{clubID}/contacts [get] func (cc *ClubContactController) GetClubContacts(c *fiber.Ctx) error { contacts, err := cc.clubContactService.GetClubContacts(c.Params("clubID")) if err != nil { @@ -24,6 +37,22 @@ func (cc *ClubContactController) GetClubContacts(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(contacts) } +// PostContact godoc +// +// @Summary Creates a contact +// @Description Creates a contact +// @ID create-contact +// @Tags club-contact +// @Accept json +// @Produce json +// @Param clubID path string true "Club ID" +// @Param contactBody body models.PutContactRequestBody true "Contact Body" +// @Success 201 {object} models.Contact +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /club/{clubID}/contacts [post] func (cc *ClubContactController) PutContact(c *fiber.Ctx) error { var contactBody models.PutContactRequestBody diff --git a/backend/src/controllers/club_event.go b/backend/src/controllers/club_event.go index 41e6607d3..16ae9294f 100644 --- a/backend/src/controllers/club_event.go +++ b/backend/src/controllers/club_event.go @@ -15,6 +15,21 @@ func NewClubEventController(clubEventService services.ClubEventServiceInterface) return &ClubEventController{clubEventService: clubEventService} } +// GetClubEvents godoc +// +// @Summary Retrieve all events for a club +// @Description Retrieves all events associated with a club +// @ID get-events-by-club +// @Tags club-event +// @Produce json +// @Param clubID path string true "Club ID" +// @Param limit query int false "Limit" +// @Param page query int false "Page" +// @Success 200 {object} []models.Event +// @Failure 400 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /club/{clubID}/events [get] func (cl *ClubEventController) GetClubEvents(c *fiber.Ctx) error { defaultLimit := 10 defaultPage := 1 diff --git a/backend/src/controllers/club_follower.go b/backend/src/controllers/club_follower.go index 76239e150..5c94da7bf 100644 --- a/backend/src/controllers/club_follower.go +++ b/backend/src/controllers/club_follower.go @@ -15,6 +15,21 @@ func NewClubFollowerController(clubFollowerService services.ClubFollowerServiceI return &ClubFollowerController{clubFollowerService: clubFollowerService} } +// GetClubFollowers godoc +// +// @Summary Retrieve all followers for a club +// @Description Retrieves all followers associated with a club +// @ID get-followers-by-club +// @Tags club-follower +// @Produce json +// @Param clubID path string true "Club ID" +// @Param limit query int false "Limit" +// @Param page query int false "Page" +// @Success 200 {object} []models.User +// @Failure 400 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /club/{clubID}/followers [get] func (cf *ClubFollowerController) GetClubFollowers(c *fiber.Ctx) error { defaultLimit := 10 defaultPage := 1 diff --git a/backend/src/controllers/club_member.go b/backend/src/controllers/club_member.go index 7201ebf11..c6afc2ac4 100644 --- a/backend/src/controllers/club_member.go +++ b/backend/src/controllers/club_member.go @@ -15,6 +15,22 @@ func NewClubMemberController(clubMemberService services.ClubMemberServiceInterfa return &ClubMemberController{clubMemberService: clubMemberService} } +// GetClubMembers godoc +// +// @Summary Retrieve all members for a club +// @Description Retrieves all members associated with a club +// @ID get-members-by-club +// @Tags club-member +// @Produce json +// @Param clubID path string true "Club ID" +// @Param limit query int false "Limit" +// @Param page query int false "Page" +// @Success 200 {object} []models.User +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /club/{clubID}/members [get] func (cm *ClubMemberController) GetClubMembers(c *fiber.Ctx) error { defaultLimit := 10 defaultPage := 1 diff --git a/backend/src/controllers/club_tag.go b/backend/src/controllers/club_tag.go index e958f1a7b..fc15c0164 100644 --- a/backend/src/controllers/club_tag.go +++ b/backend/src/controllers/club_tag.go @@ -17,18 +17,20 @@ func NewClubTagController(clubTagService services.ClubTagServiceInterface) *Club // CreateClubTags godoc // -// @Summary Create Club Tags -// @Description Adds Tags to a Club +// @Summary Create club tags +// @Description Creates tags for a club // @ID create-club-tags -// @Tags club -// @Accept json +// @Tags club-tag +// @Accept json // @Produce json +// @Param clubID path string true "Club ID" +// @Param clubTagsBody body models.CreateClubTagsRequestBody true "Club Tags Body" // @Success 201 {object} []models.Tag -// @Failure 404 {string} string "club not found" -// @Failure 400 {string} string "invalid request body" -// @Failure 400 {string} string "failed to validate id" -// @Failure 500 {string} string "database error" -// @Router /api/v1/clubs/:id/tags [post] +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /club/{clubID}/tags [post] func (l *ClubTagController) CreateClubTags(c *fiber.Ctx) error { var clubTagsBody models.CreateClubTagsRequestBody if err := c.BodyParser(&clubTagsBody); err != nil { @@ -45,17 +47,17 @@ func (l *ClubTagController) CreateClubTags(c *fiber.Ctx) error { // GetClubTags godoc // -// @Summary Get Club Tags -// @Description Retrieves the tags for a club -// @ID get-club-tags -// @Tags club +// @Summary Retrieve all tags for a club +// @Description Retrieves all tags associated with a club +// @ID get-tags-by-club +// @Tags club-tag // @Produce json -// @Success 200 {object} []models.Tag -// @Failure 404 {string} string "club not found" -// @Failure 400 {string} string "invalid request body" -// @Failure 400 {string} string "failed to validate id" -// @Failure 500 {string} string "database error" -// @Router /api/v1/clubs/:id/tags [get] +// @Param clubID path string true "Club ID" +// @Success 200 {object} []models.Tag +// @Failure 400 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /club/{clubID}/tags [get] func (l *ClubTagController) GetClubTags(c *fiber.Ctx) error { clubTags, err := l.clubTagService.GetClubTags(c.Params("clubID")) if err != nil { @@ -65,18 +67,21 @@ func (l *ClubTagController) GetClubTags(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(clubTags) } -// DeleteClubTags godoc +// DeleteClubTag godoc // -// @Summary Delete Club Tags -// @Description Deletes the tags for a club -// @ID delete-club-tags -// @Tags club -// @Success 204 -// @Failure 404 {string} string "club not found" -// @Failure 400 {string} string "invalid request body" -// @Failure 400 {string} string "failed to validate id" -// @Failure 500 {string} string "database error" -// @Router /api/v1/clubs/:id/tags/:tagId [delete] +// @Summary Delete a tag for a club +// @Description Deletes a tag associated with a club +// @ID delete-tag-by-club +// @Tags club-tag +// @Produce json +// @Param clubID path string true "Club ID" +// @Param tagID path string true "Tag ID" +// @Success 204 {string} utilites.SuccessResponse +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /club/{clubID}/tags/{tagID} [delete] func (l *ClubTagController) DeleteClubTag(c *fiber.Ctx) error { err := l.clubTagService.DeleteClubTag(c.Params("clubID"), c.Params("tagID")) if err != nil { diff --git a/backend/src/controllers/contact.go b/backend/src/controllers/contact.go index 4ce650882..b343bd0c2 100644 --- a/backend/src/controllers/contact.go +++ b/backend/src/controllers/contact.go @@ -15,6 +15,20 @@ func NewContactController(contactService services.ContactServiceInterface) *Cont return &ContactController{contactService: contactService} } +// CreateContact godoc +// +// @Summary Creates a contact +// @Description Creates a contact +// @ID create-contact +// @Tags contact +// @Accept json +// @Produce json +// @Param contactBody body models.Contact true "Contact Body" +// @Success 201 {object} models.Contact +// @Failure 400 {string} errors.Error +// @Failure 404 {string} errors.Error +// @Failure 500 {string} errors.Error +// @Router /contact/ [post] func (co *ContactController) GetContact(c *fiber.Ctx) error { contact, err := co.contactService.GetContact(c.Params("contactID")) if err != nil { @@ -24,6 +38,20 @@ func (co *ContactController) GetContact(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(contact) } +// GetContacts godoc +// +// @Summary Retrieve all contacts +// @Description Retrieves all contacts +// @ID get-contacts +// @Tags contact +// @Produce json +// @Param limit query int false "Limit" +// @Param page query int false "Page" +// @Success 200 {object} []models.Contact +// @Failure 400 {string} errors.Error +// @Failure 404 {string} errors.Error +// @Failure 500 {string} errors.Error +// @Router /contact/ [get] func (co *ContactController) GetContacts(c *fiber.Ctx) error { defaultLimit := 10 defaultPage := 1 @@ -36,6 +64,20 @@ func (co *ContactController) GetContacts(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(contacts) } +// CreateContact godoc +// +// @Summary Creates a contact +// @Description Creates a contact +// @ID create-contact +// @Tags contact +// @Accept json +// @Produce json +// @Param contactBody body models.Contact true "Contact Body" +// @Success 201 {object} models.Contact +// @Failure 400 {string} errors.Error +// @Failure 404 {string} errors.Error +// @Failure 500 {string} errors.Error +// @Router /contact/ [post] func (co *ContactController) DeleteContact(c *fiber.Ctx) error { err := co.contactService.DeleteContact(c.Params("contactID")) if err != nil { diff --git a/backend/src/controllers/event.go b/backend/src/controllers/event.go index 40c99c002..0148a594b 100644 --- a/backend/src/controllers/event.go +++ b/backend/src/controllers/event.go @@ -17,6 +17,20 @@ func NewEventController(eventService services.EventServiceInterface) *EventContr return &EventController{eventService: eventService} } +// GetAllEvents godoc +// +// @Summary Retrieve all events +// @Description Retrieves all events +// @ID get-all-events +// @Tags event +// @Produce json +// @Param limit query int false "Limit" +// @Param page query int false "Page" +// @Success 200 {object} []models.Event +// @Failure 400 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /event/ [get] func (e *EventController) GetAllEvents(c *fiber.Ctx) error { defaultLimit := 10 defaultPage := 1 @@ -29,6 +43,19 @@ func (e *EventController) GetAllEvents(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(events) } +// GetEvent godoc +// +// @Summary Retrieve an event +// @Description Retrieves an event +// @ID get-event +// @Tags event +// @Produce json +// @Param eventID path string true "Event ID" +// @Success 200 {object} models.Event +// @Failure 400 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /event/{eventID} [get] func (e *EventController) GetEvent(c *fiber.Ctx) error { event, err := e.eventService.GetEvent(c.Params("eventID")) if err != nil { @@ -38,6 +65,19 @@ func (e *EventController) GetEvent(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(event) } +// GetSeriesByEventID godoc +// +// @Summary Retrieve all series by event +// @Description Retrieves all series associated with an event +// @ID get-series-by-event +// @Tags event +// @Produce json +// @Param eventID path string true "Event ID" +// @Success 200 {object} []models.Series +// @Failure 400 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /event/{eventID}/series [get] func (e *EventController) GetSeriesByEventID(c *fiber.Ctx) error { events, err := e.eventService.GetSeriesByEventID(c.Params("eventID")) if err != nil { @@ -47,6 +87,19 @@ func (e *EventController) GetSeriesByEventID(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(events) } +// GetSeriesByID godoc +// +// @Summary Retrieve a series by ID +// @Description Retrieves a series by ID +// @ID get-series-by-id +// @Tags event +// @Produce json +// @Param seriesID path string true "Series ID" +// @Success 200 {object} models.Series +// @Failure 400 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /series/{seriesID} [get] func (e *EventController) GetSeriesByID(c *fiber.Ctx) error { events, err := e.eventService.GetSeriesByID(c.Params("seriesID")) if err != nil { @@ -56,6 +109,21 @@ func (e *EventController) GetSeriesByID(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(events) } +// CreateEvent godoc +// +// @Summary Create an event +// @Description Creates an event +// @ID create-event +// @Tags event +// @Accept json +// @Produce json +// @Param event body models.CreateEventRequestBody true "Event Body" +// @Success 201 {object} models.Event +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /event/ [post] func (e *EventController) CreateEvent(c *fiber.Ctx) error { var eventBody models.CreateEventRequestBody if err := c.BodyParser(&eventBody); err != nil { @@ -70,6 +138,22 @@ func (e *EventController) CreateEvent(c *fiber.Ctx) error { return c.Status(fiber.StatusCreated).JSON(event) } +// CreateSeries godoc +// +// @Summary Create a series +// @Description Creates a series +// @ID create-series +// @Tags event +// @Accept json +// @Produce json +// @Param eventID path string true "Event ID" +// @Param seriesBody body models.CreateSeriesRequestBody true "Series Body" +// @Success 201 {object} models.Series +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /event/{eventID}/series [post] func (e *EventController) UpdateEvent(c *fiber.Ctx) error { var eventBody models.UpdateEventRequestBody if err := c.BodyParser(&eventBody); err != nil { @@ -84,6 +168,23 @@ func (e *EventController) UpdateEvent(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(updatedEvent) } +// UpdateSeriesByID godoc +// +// @Summary Update a series by ID +// @Description Updates a series by ID +// @ID update-series-by-id +// @Tags event +// @Accept json +// @Produce json +// @Param eventID path string true "Event ID" +// @Param seriesID path string true "Series ID" +// @Param seriesBody body models.UpdateSeriesRequestBody true "Series Body" +// @Success 200 {object} models.Series +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /event/{eventID}/series/{seriesID} [put] func (e *EventController) UpdateSeriesByID(c *fiber.Ctx) error { var seriesBody models.UpdateSeriesRequestBody if err := c.BodyParser(&seriesBody); err != nil { @@ -98,6 +199,20 @@ func (e *EventController) UpdateSeriesByID(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(updatedSeries) } +// DeleteSeriesByID godoc +// +// @Summary Delete a series by ID +// @Description Deletes a series by ID +// @ID delete-series-by-id +// @Tags event +// @Produce json +// @Param seriesID path string true "Series ID" +// @Success 204 {string} utilities.SuccessResponse +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /series/{seriesID} [delete] func (e *EventController) DeleteSeriesByID(c *fiber.Ctx) error { if err := e.eventService.DeleteSeriesByID(c.Params("seriesID")); err != nil { return err.FiberError(c) @@ -106,6 +221,20 @@ func (e *EventController) DeleteSeriesByID(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusNoContent) } +// DeleteSeriesByEventID godoc +// +// @Summary Delete all series by event +// @Description Deletes all series associated with an event +// @ID delete-series-by-event +// @Tags event +// @Produce json +// @Param eventID path string true "Event ID" +// @Success 204 {string} utilities.SuccessResponse +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /event/{eventID}/series [delete] func (e *EventController) DeleteSeriesByEventID(c *fiber.Ctx) error { if err := e.eventService.DeleteSeriesByEventID(c.Params("eventID")); err != nil { return err.FiberError(c) @@ -114,6 +243,20 @@ func (e *EventController) DeleteSeriesByEventID(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusNoContent) } +// DeleteEvent godoc +// +// @Summary Delete an event +// @Description Deletes an event +// @ID delete-event +// @Tags event +// @Produce json +// @Param eventID path string true "Event ID" +// @Success 204 {string} utilities.SuccessResponse +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /event/{eventID} [delete] func (l *EventController) DeleteEvent(c *fiber.Ctx) error { if err := l.eventService.DeleteEvent(c.Params("eventID")); err != nil { return err.FiberError(c) diff --git a/backend/src/controllers/tag.go b/backend/src/controllers/tag.go index 9dccea98c..647d7f6ea 100644 --- a/backend/src/controllers/tag.go +++ b/backend/src/controllers/tag.go @@ -16,19 +16,23 @@ func NewTagController(tagService services.TagServiceInterface) *TagController { return &TagController{tagService: tagService} } -// CreateTag godoc +// GetAllTags godoc + +// CreateTag creates a new tag. // -// @Summary Creates a tag -// @Description Creates a tag -// @ID create-tag +// @Summary Retrieve all tags +// @Description Retrieves all tags +// @ID get-all-tags // @Tags tag -// @Accept json // @Produce json -// @Success 201 {object} models.Tag -// @Failure 400 {string} string "failed to process the request" -// @Failure 400 {string} string "failed to validate the data" -// @Failure 500 {string} string "failed to create tag" -// @Router /api/v1/tags/ [post] +// @Param limit query int false "Limit" +// @Param page query int false "Page" +// @Success 200 {object} []models.Tag +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /tags [get] func (t *TagController) CreateTag(c *fiber.Ctx) error { var tagBody models.TagRequestBody @@ -46,17 +50,17 @@ func (t *TagController) CreateTag(c *fiber.Ctx) error { // GetTag godoc // -// @Summary Gets a tag -// @Description Returns a tag +// @Summary Retrieve a tag +// @Description Retrieves a tag // @ID get-tag // @Tags tag // @Produce json -// @Param id path int true "Tag ID" -// @Success 200 {object} models.Tag -// @Failure 400 {string} string "failed to validate id" -// @Failure 404 {string} string "faied to find tag" -// @Failure 500 {string} string "failed to retrieve tag" -// @Router /api/v1/tags/{id} [get] +// @Param tagID path string true "Tag ID" +// @Success 200 {object} models.Tag +// @Failure 400 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /tags/{tagID} [get] func (t *TagController) GetTag(c *fiber.Ctx) error { tag, err := t.tagService.GetTag(c.Params("tagID")) if err != nil { @@ -68,20 +72,20 @@ func (t *TagController) GetTag(c *fiber.Ctx) error { // UpdateTag godoc // -// @Summary Updates a tag +// @Summary Update a tag // @Description Updates a tag // @ID update-tag // @Tags tag // @Accept json // @Produce json -// @Param id path int true "Tag ID" -// @Success 200 {object} models.Tag -// @Failure 400 {string} string "failed to process the request" -// @Failure 400 {string} string "failed to validate id" -// @Failure 400 {string} string "failed to validate the data" -// @Failure 404 {string} string "failed to find tag" -// @Failure 500 {string} string "failed to update tag" -// @Router /api/v1/tags/{id} [patch] +// @Param tagID path string true "Tag ID" +// @Param tag body models.TagRequestBody true "Tag" +// @Success 200 {object} models.Tag +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /tags/{tagID} [put] func (t *TagController) UpdateTag(c *fiber.Ctx) error { var tagBody models.TagRequestBody @@ -99,16 +103,18 @@ func (t *TagController) UpdateTag(c *fiber.Ctx) error { // DeleteTag godoc // -// @Summary Deletes a tag +// @Summary Delete a tag // @Description Deletes a tag // @ID delete-tag // @Tags tag -// @Param id path int true "Tag ID" -// @Success 204 {string} string "no content" -// @Failure 400 {string} string "failed to validate id" -// @Failure 404 {string} string "tag not found" -// @Failure 500 {string} string "failed to delete tag" -// @Router /api/v1/tags/{id} [delete] +// @Produce json +// @Param tagID path string true "Tag ID" +// @Success 204 {string} utilities.SuccessResponse +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /tags/{tagID} [delete] func (t *TagController) DeleteTag(c *fiber.Ctx) error { err := t.tagService.DeleteTag(c.Params("tagID")) if err != nil { diff --git a/backend/src/controllers/user.go b/backend/src/controllers/user.go index b6784be79..f2002be72 100644 --- a/backend/src/controllers/user.go +++ b/backend/src/controllers/user.go @@ -18,18 +18,21 @@ func NewUserController(userService services.UserServiceInterface) *UserControlle return &UserController{userService: userService} } -// Create User godoc +// CreateUser godoc // -// @Summary Creates a User +// @Summary Create a user // @Description Creates a user // @ID create-user // @Tags user -// @Accept json +// @Accept json // @Produce json +// @Param userBody body models.CreateUserRequestBody true "User Body" // @Success 201 {object} models.User -// @Failure 400 {string} string "failed to create user" -// @Failure 500 {string} string "internal server error" -// @Router /api/v1/users/ [post] +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /user/ [post] func (u *UserController) CreateUser(c *fiber.Ctx) error { var userBody models.CreateUserRequestBody @@ -45,16 +48,19 @@ func (u *UserController) CreateUser(c *fiber.Ctx) error { return c.Status(fiber.StatusCreated).JSON(user) } -// GetAllUsers godoc +// GetUsers godoc // -// @Summary Gets all users -// @Description Returns all users -// @ID get-all-users +// @Summary Retrieve all users +// @Description Retrieves all users +// @ID get-users // @Tags user // @Produce json -// @Success 200 {object} []models.User -// @Failure 500 {string} string "failed to get all users" -// @Router /api/v1/users/ [get] +// @Param limit query int false "Limit" +// @Param page query int false "Page" +// @Success 200 {object} []models.User +// @Failure 401 {object} errors.Error +// @Failure 400 {object} errors.Error +// @Failure 500 {object} errors.Error func (u *UserController) GetUsers(c *fiber.Ctx) error { defaultLimit := 10 defaultPage := 1 @@ -69,17 +75,18 @@ func (u *UserController) GetUsers(c *fiber.Ctx) error { // GetUser godoc // -// @Summary Gets a user -// @Description Returns a user -// @ID get-user-by-id +// @Summary Retrieve a user +// @Description Retrieves a user +// @ID get-user // @Tags user // @Produce json -// @Param id path string true "User ID" -// @Success 200 {object} models.User -// @Failure 404 {string} string "user not found" -// @Failure 400 {string} string "failed to validate id" -// @Failure 500 {string} string "failed to get user" -// @Router /api/v1/users/{id} [get] +// @Param userID path string true "User ID" +// @Success 200 {object} models.User +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /user/{userID} [get] func (u *UserController) GetUser(c *fiber.Ctx) error { user, err := u.userService.GetUser(c.Params("userID")) if err != nil { @@ -91,19 +98,20 @@ func (u *UserController) GetUser(c *fiber.Ctx) error { // UpdateUser godoc // -// @Summary Updates a user +// @Summary Update a user // @Description Updates a user -// @ID update-user-by-id +// @ID update-user // @Tags user +// @Accept json // @Produce json -// @Param id path string true "User ID" +// @Param userID path string true "User ID" +// @Param userBody body models.UpdateUserRequestBody true "User Body" // @Success 200 {object} models.User -// @Failure 404 {string} string "user not found" -// @Failure 400 {string} string "invalid request body" -// @Failure 400 {string} string "failed to validate id" -// @Failure 500 {string} string "database error" -// @Failure 500 {string} string "failed to hash password" -// @Router /api/v1/users/{id} [patch] +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /user/{userID} [put] func (u *UserController) UpdateUser(c *fiber.Ctx) error { var user models.UpdateUserRequestBody @@ -122,15 +130,18 @@ func (u *UserController) UpdateUser(c *fiber.Ctx) error { // DeleteUser godoc // -// @Summary Deletes the given userID -// @Description Returns nil +// @Summary Delete a user +// @Description Deletes a user // @ID delete-user // @Tags user // @Produce json -// @Param id path string true "User ID" -// @Success 204 {string} string "no content" -// @Failure 500 {string} string "failed to get all users" -// @Router /api/v1/users/{id} [delete] +// @Param userID path string true "User ID" +// @Success 204 {string} utilities.SuccessResponse +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /user/{userID} [delete] func (u *UserController) DeleteUser(c *fiber.Ctx) error { err := u.userService.DeleteUser(c.Params("userID")) if err != nil { diff --git a/backend/src/controllers/user_follower.go b/backend/src/controllers/user_follower.go index 67c0ff36e..fe7c25980 100644 --- a/backend/src/controllers/user_follower.go +++ b/backend/src/controllers/user_follower.go @@ -13,6 +13,21 @@ func NewUserFollowerController(userFollowerService services.UserFollowerServiceI return &UserFollowerController{userFollowerService: userFollowerService} } +// CreateFollowing godoc +// +// @Summary Follow a club +// @Description Follow a club +// @ID create-following +// @Tags user-follower +// @Accept json +// @Produce json +// @Param userID path string true "User ID" +// @Param clubID path string true "Club ID" +// @Success 201 {object} utilities.SuccessResponse +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /user/{userID}/following/{clubID} [post] func (uf *UserFollowerController) CreateFollowing(c *fiber.Ctx) error { err := uf.userFollowerService.CreateFollowing(c.Params("userID"), c.Params("clubID")) if err != nil { @@ -21,6 +36,21 @@ func (uf *UserFollowerController) CreateFollowing(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusCreated) } +// DeleteFollowing godoc +// +// @Summary Unfollow a club +// @Description Unfollow a club +// @ID delete-following +// @Tags user-follower +// @Accept json +// @Produce json +// @Param userID path string true "User ID" +// @Param clubID path string true "Club ID" +// @Success 204 {object} utilities.SuccessResponse +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /user/{userID}/following/{clubID} [delete] func (uf *UserFollowerController) DeleteFollowing(c *fiber.Ctx) error { err := uf.userFollowerService.DeleteFollowing(c.Params("userID"), c.Params("clubID")) if err != nil { @@ -29,6 +59,20 @@ func (uf *UserFollowerController) DeleteFollowing(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusNoContent) } +// GetAllFollowing godoc +// +// @Summary Retrieve all clubs a user is following +// @Description Retrieves all clubs a user is following +// @ID get-following +// @Tags user-follower +// @Produce json +// @Param userID path string true "User ID" +// @Success 200 {object} []models.Club +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /user/{userID}/following [get] func (uf *UserFollowerController) GetAllFollowing(c *fiber.Ctx) error { clubs, err := uf.userFollowerService.GetFollowing(c.Params("userID")) if err != nil { diff --git a/backend/src/controllers/user_member.go b/backend/src/controllers/user_member.go index 17a492d23..d91a61f51 100644 --- a/backend/src/controllers/user_member.go +++ b/backend/src/controllers/user_member.go @@ -13,6 +13,21 @@ func NewUserMemberController(clubMemberService services.UserMemberServiceInterfa return &UserMemberController{clubMemberService: clubMemberService} } +// CreateMembership godoc +// +// @Summary Join a club +// @Description Join a club +// @ID create-membership +// @Tags user-member +// @Accept json +// @Produce json +// @Param userID path string true "User ID" +// @Param clubID path string true "Club ID" +// @Success 201 {object} utilities.SuccessResponse +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /user/{userID}/membership/{clubID} [post] func (um *UserMemberController) CreateMembership(c *fiber.Ctx) error { err := um.clubMemberService.CreateMembership(c.Params("userID"), c.Params("clubID")) if err != nil { @@ -22,6 +37,21 @@ func (um *UserMemberController) CreateMembership(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusCreated) } +// DeleteMembership godoc +// +// @Summary Leave a club +// @Description Leave a club +// @ID delete-membership +// @Tags user-member +// @Accept json +// @Produce json +// @Param userID path string true "User ID" +// @Param clubID path string true "Club ID" +// @Success 204 {object} utilities.SuccessResponse +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /user/{userID}/membership/{clubID} [delete] func (um *UserMemberController) DeleteMembership(c *fiber.Ctx) error { err := um.clubMemberService.DeleteMembership(c.Params("userID"), c.Params("clubID")) if err != nil { @@ -31,6 +61,20 @@ func (um *UserMemberController) DeleteMembership(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusNoContent) } +// GetMembership godoc +// +// @Summary Retrieve all clubs a user is a member of +// @Description Retrieves all clubs a user is a member of +// @ID get-membership +// @Tags user-member +// @Produce json +// @Param userID path string true "User ID" +// @Success 200 {object} []models.Club +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /user/{userID}/membership [get] func (um *UserMemberController) GetMembership(c *fiber.Ctx) error { followers, err := um.clubMemberService.GetMembership(c.Params("userID")) if err != nil { diff --git a/backend/src/controllers/user_tag.go b/backend/src/controllers/user_tag.go index 228baa77a..3612a0d40 100644 --- a/backend/src/controllers/user_tag.go +++ b/backend/src/controllers/user_tag.go @@ -15,6 +15,20 @@ func NewUserTagController(userTagService services.UserTagServiceInterface) *User return &UserTagController{userTagService: userTagService} } +// GetUserTags godoc +// +// @Summary Retrieve all tags for a user +// @Description Retrieves all tags associated with a user +// @ID get-tags-by-user +// @Tags user-tag +// @Produce json +// @Param userID path string true "User ID" +// @Success 200 {object} []models.Tag +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /user/{userID}/tags [get] func (ut *UserTagController) GetUserTags(c *fiber.Ctx) error { tags, err := ut.userTagService.GetUserTags(c.Params("userID")) if err != nil { @@ -23,6 +37,22 @@ func (ut *UserTagController) GetUserTags(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(&tags) } +// CreateUserTags godoc +// +// @Summary Create user tags +// @Description Creates tags for a user +// @ID create-user-tags +// @Tags user-tag +// @Accept json +// @Produce json +// @Param userID path string true "User ID" +// @Param userTagsBody body models.CreateUserTagsBody true "User Tags Body" +// @Success 201 {object} []models.Tag +// @Failure 400 {object} errors.Error +// @Failure 401 {object} errors.Error +// @Failure 404 {object} errors.Error +// @Failure 500 {object} errors.Error +// @Router /user/{userID}/tags [post] func (ut *UserTagController) CreateUserTags(c *fiber.Ctx) error { var requestBody models.CreateUserTagsBody if err := c.BodyParser(&requestBody); err != nil { diff --git a/backend/src/docs/docs.go b/backend/src/docs/docs.go index 553b46008..2fd8e351f 100644 --- a/backend/src/docs/docs.go +++ b/backend/src/docs/docs.go @@ -18,7 +18,7 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { - "/api/v1/auth/login": { + "/auth/login": { "post": { "description": "Logs in a user", "consumes": [ @@ -28,47 +28,50 @@ const docTemplate = `{ "application/json" ], "tags": [ - "user" + "auth" ], "summary": "Logs in a user", "operationId": "login-user", "parameters": [ { - "description": "User Body", - "name": "userBody", + "description": "Login Body", + "name": "loginBody", "in": "body", "required": true, "schema": { - "type": "array", - "items": { - "type": "string" - } + "$ref": "#/definitions/models.LoginUserResponseBody" } } ], "responses": { "200": { - "description": "success", + "description": "OK", "schema": { - "type": "string" + "$ref": "#/definitions/utilities.SuccessResponse" } }, "400": { - "description": "failed to parse body", + "description": "Bad Request", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } }, - "401": { - "description": "failed to login user", + "404": { + "description": "Not Found", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" } } } } }, - "/api/v1/auth/logout": { + "/auth/logout": { "get": { "description": "Logs out a user", "consumes": [ @@ -78,7 +81,7 @@ const docTemplate = `{ "application/json" ], "tags": [ - "user" + "auth" ], "summary": "Logs out a user", "operationId": "logout-user", @@ -86,28 +89,22 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "type": "string" - } - }, - "401": { - "description": "failed to logout user", - "schema": { - "type": "string" + "$ref": "#/definitions/utilities.SuccessResponse" } } } } }, - "/api/v1/auth/me": { + "/auth/me": { "get": { - "description": "Returns the current user", + "description": "Returns the current user associated with an auth session", "produces": [ "application/json" ], "tags": [ - "user" + "auth" ], - "summary": "Gets the current user", + "summary": "Retrieve the current user given an auth session", "operationId": "get-current-user", "responses": { "200": { @@ -116,16 +113,34 @@ const docTemplate = `{ "$ref": "#/definitions/models.User" } }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, "401": { - "description": "failed to get current user", + "description": "Unauthorized", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" } } } } }, - "/api/v1/auth/refresh": { + "/auth/refresh": { "get": { "description": "Refreshes a user's access token", "consumes": [ @@ -135,29 +150,100 @@ const docTemplate = `{ "application/json" ], "tags": [ - "user" + "auth" ], "summary": "Refreshes a user's access token", "operationId": "refresh-user", "responses": { "200": { - "description": "success", + "description": "OK", "schema": { - "type": "string" + "$ref": "#/definitions/utilities.SuccessResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/auth/update-password": { + "post": { + "description": "Updates a user's password", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Updates a user's password", + "operationId": "update-password", + "parameters": [ + { + "description": "User Body", + "name": "userBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.UpdatePasswordRequestBody" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/utilities.SuccessResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" } }, "401": { - "description": "failed to refresh access token", + "description": "Unauthorized", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" } } } } }, - "/api/v1/category/": { + "/category/": { "get": { - "description": "Retrieves all existing categories", + "description": "Retrieves all categories", "produces": [ "application/json" ], @@ -166,6 +252,20 @@ const docTemplate = `{ ], "summary": "Retrieve all categories", "operationId": "get-categories", + "parameters": [ + { + "type": "integer", + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" + } + ], "responses": { "200": { "description": "OK", @@ -176,8 +276,20 @@ const docTemplate = `{ } } }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + }, "500": { - "description": "unable to retrieve categories", + "description": "Internal Server Error", "schema": { "type": "string" } @@ -185,15 +297,29 @@ const docTemplate = `{ } }, "post": { - "description": "Creates a category that is used to group tags", + "description": "Creates a category", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ "category" ], - "summary": "Create a category", + "summary": "Creates a category", "operationId": "create-category", + "parameters": [ + { + "description": "Category Body", + "name": "categoryBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.CategoryRequestBody" + } + } + ], "responses": { "201": { "description": "Created", @@ -202,13 +328,25 @@ const docTemplate = `{ } }, "400": { - "description": "category with that name already exists", + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", "schema": { "type": "string" } }, "500": { - "description": "failed to create category", + "description": "Internal Server Error", "schema": { "type": "string" } @@ -216,9 +354,9 @@ const docTemplate = `{ } } }, - "/api/v1/category/{id}": { + "/category/{categoryID}": { "get": { - "description": "Retrieve a category by its ID", + "description": "Retrieves a category", "produces": [ "application/json" ], @@ -231,7 +369,7 @@ const docTemplate = `{ { "type": "string", "description": "Category ID", - "name": "id", + "name": "categoryID", "in": "path", "required": true } @@ -244,111 +382,135 @@ const docTemplate = `{ } }, "400": { - "description": "failed to validate id", + "description": "Bad Request", "schema": { "type": "string" } }, "404": { - "description": "faied to find category", + "description": "Not Found", "schema": { "type": "string" } }, "500": { - "description": "failed to retrieve category", + "description": "Internal Server Error", "schema": { "type": "string" } } } }, - "delete": { - "description": "Delete a category by ID", + "put": { + "description": "Updates a category", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ "category" ], - "summary": "Delete a category", - "operationId": "delete-category", + "summary": "Updates a category", + "operationId": "update-category", "parameters": [ { "type": "string", "description": "Category ID", - "name": "id", + "name": "categoryID", "in": "path", "required": true + }, + { + "description": "Category Body", + "name": "categoryBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.CategoryRequestBody" + } } ], "responses": { - "204": { - "description": "no content", + "200": { + "description": "OK", "schema": { - "type": "string" + "$ref": "#/definitions/models.Category" } }, "400": { - "description": "failed to validate id", + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized", "schema": { "type": "string" } }, "404": { - "description": "failed to find category", + "description": "Not Found", "schema": { "type": "string" } }, "500": { - "description": "failed to delete category", + "description": "Internal Server Error", "schema": { "type": "string" } } } }, - "patch": { - "description": "Updates a category", + "delete": { + "description": "Deletes a category", "produces": [ "application/json" ], "tags": [ "category" ], - "summary": "Updates a category", - "operationId": "update-category", + "summary": "Deletes a category", + "operationId": "delete-category", "parameters": [ { "type": "string", "description": "Category ID", - "name": "id", + "name": "categoryID", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", + "204": { + "description": "No Content", "schema": { - "$ref": "#/definitions/models.Category" + "type": "string" } }, "400": { - "description": "failed to validate id", + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized", "schema": { "type": "string" } }, "404": { - "description": "failed to find category", + "description": "Not Found", "schema": { "type": "string" } }, "500": { - "description": "failed to update category", + "description": "Internal Server Error", "schema": { "type": "string" } @@ -356,58 +518,92 @@ const docTemplate = `{ } } }, - "/api/v1/tags/": { - "post": { - "description": "Creates a tag", - "consumes": [ - "application/json" - ], + "/category/{categoryID}/tags": { + "get": { + "description": "Retrieves all tags associated with a category", "produces": [ "application/json" ], "tags": [ - "tag" + "category-tag" + ], + "summary": "Retrieve all tags by category", + "operationId": "get-tags-by-category", + "parameters": [ + { + "type": "string", + "description": "Category ID", + "name": "categoryID", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" + } ], - "summary": "Creates a tag", - "operationId": "create-tag", "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/models.Tag" + "type": "array", + "items": { + "$ref": "#/definitions/models.Tag" + } } }, "400": { - "description": "failed to validate the data", + "description": "Bad Request", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" } }, "500": { - "description": "failed to create tag", + "description": "Internal Server Error", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } } } } }, - "/api/v1/tags/{id}": { + "/category/{categoryID}/tags/{tagID}": { "get": { - "description": "Returns a tag", + "description": "Retrieves a tag associated with a category", "produces": [ "application/json" ], "tags": [ - "tag" + "category-tag" ], - "summary": "Gets a tag", - "operationId": "get-tag", + "summary": "Retrieve a tag by category", + "operationId": "get-tag-by-category", "parameters": [ { - "type": "integer", + "type": "string", + "description": "Category ID", + "name": "categoryID", + "in": "path", + "required": true + }, + { + "type": "string", "description": "Tag ID", - "name": "id", + "name": "tagID", "in": "path", "required": true } @@ -420,70 +616,77 @@ const docTemplate = `{ } }, "400": { - "description": "failed to validate id", + "description": "Bad Request", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } }, "404": { - "description": "faied to find tag", + "description": "Not Found", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } }, "500": { - "description": "failed to retrieve tag", + "description": "Internal Server Error", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } } } - }, - "delete": { - "description": "Deletes a tag", + } + }, + "/club/": { + "get": { + "description": "Retrieves all clubs", + "produces": [ + "application/json" + ], "tags": [ - "tag" + "club" ], - "summary": "Deletes a tag", - "operationId": "delete-tag", + "summary": "Retrieve all clubs", + "operationId": "get-all-clubs", "parameters": [ { "type": "integer", - "description": "Tag ID", - "name": "id", - "in": "path", - "required": true + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" } ], "responses": { - "204": { - "description": "no content", + "200": { + "description": "OK", "schema": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/models.Club" + } } }, "400": { - "description": "failed to validate id", - "schema": { - "type": "string" - } - }, - "404": { - "description": "tag not found", + "description": "Bad Request", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } }, "500": { - "description": "failed to delete tag", + "description": "Internal Server Error", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } } } }, - "patch": { - "description": "Updates a tag", + "post": { + "description": "Creates a club", "consumes": [ "application/json" ], @@ -491,16 +694,72 @@ const docTemplate = `{ "application/json" ], "tags": [ - "tag" + "club" ], - "summary": "Updates a tag", - "operationId": "update-tag", + "summary": "Create a club", + "operationId": "create-club", "parameters": [ { - "type": "integer", - "description": "Tag ID", - "name": "id", - "in": "path", + "description": "Club", + "name": "club", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.CreateClubRequestBody" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/models.Club" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/club/{clubID}": { + "get": { + "description": "Retrieves a club", + "produces": [ + "application/json" + ], + "tags": [ + "club" + ], + "summary": "Retrieve a club", + "operationId": "get-club", + "parameters": [ + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", "required": true } ], @@ -508,61 +767,198 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Tag" + "$ref": "#/definitions/models.Club" } }, "400": { - "description": "failed to validate the data", + "description": "Bad Request", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } }, "404": { - "description": "failed to find tag", + "description": "Not Found", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "put": { + "description": "Updates a club", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "club" + ], + "summary": "Update a club", + "operationId": "update-club", + "parameters": [ + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + }, + { + "description": "Club", + "name": "club", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.UpdateClubRequestBody" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.Club" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" } }, "500": { - "description": "failed to update tag", + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "delete": { + "description": "Deletes a club", + "produces": [ + "application/json" + ], + "tags": [ + "club" + ], + "summary": "Delete a club", + "operationId": "delete-club", + "parameters": [ + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", "schema": { "type": "string" } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } } } } }, - "/api/v1/users/": { + "/club/{clubID}/contacts": { "get": { - "description": "Returns all users", + "description": "Retrieves all contacts associated with a club", "produces": [ "application/json" ], "tags": [ - "user" + "club-contact" + ], + "summary": "Retrieve all contacts for a club", + "operationId": "get-contacts-by-club", + "parameters": [ + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + } ], - "summary": "Gets all users", - "operationId": "get-all-users", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/models.User" + "$ref": "#/definitions/models.Contact" } } }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, "500": { - "description": "failed to get all users", + "description": "Internal Server Error", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } } } }, "post": { - "description": "Creates a user", + "description": "Creates a contact", "consumes": [ "application/json" ], @@ -570,222 +966,2726 @@ const docTemplate = `{ "application/json" ], "tags": [ - "user" + "club-contact" + ], + "summary": "Creates a contact", + "operationId": "create-contact", + "parameters": [ + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + }, + { + "description": "Contact Body", + "name": "contactBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.PutContactRequestBody" + } + } ], - "summary": "Creates a User", - "operationId": "create-user", "responses": { "201": { "description": "Created", "schema": { - "$ref": "#/definitions/models.User" + "$ref": "#/definitions/models.Contact" } }, "400": { - "description": "failed to create user", + "description": "Bad Request", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" } }, "500": { - "description": "internal server error", + "description": "Internal Server Error", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } } } } }, - "/api/v1/users/{id}": { + "/club/{clubID}/events": { "get": { - "description": "Returns a user", + "description": "Retrieves all events associated with a club", "produces": [ "application/json" ], "tags": [ - "user" + "club-event" ], - "summary": "Gets a user", - "operationId": "get-user-by-id", + "summary": "Retrieve all events for a club", + "operationId": "get-events-by-club", "parameters": [ { "type": "string", - "description": "User ID", - "name": "id", + "description": "Club ID", + "name": "clubID", "in": "path", "required": true + }, + { + "type": "integer", + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.User" + "type": "array", + "items": { + "$ref": "#/definitions/models.Event" + } } }, "400": { - "description": "failed to validate id", + "description": "Bad Request", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } }, "404": { - "description": "user not found", + "description": "Not Found", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } }, "500": { - "description": "failed to get user", + "description": "Internal Server Error", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } } } - }, - "delete": { - "description": "Returns nil", + } + }, + "/club/{clubID}/followers": { + "get": { + "description": "Retrieves all followers associated with a club", "produces": [ "application/json" ], "tags": [ - "user" + "club-follower" ], - "summary": "Deletes the given userID", - "operationId": "delete-user", + "summary": "Retrieve all followers for a club", + "operationId": "get-followers-by-club", "parameters": [ { "type": "string", - "description": "User ID", - "name": "id", + "description": "Club ID", + "name": "clubID", "in": "path", "required": true + }, + { + "type": "integer", + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" } ], "responses": { - "204": { - "description": "no content", + "200": { + "description": "OK", "schema": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/models.User" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" } }, "500": { - "description": "failed to get all users", + "description": "Internal Server Error", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } } } - }, - "patch": { - "description": "Updates a user", + } + }, + "/club/{clubID}/members": { + "get": { + "description": "Retrieves all members associated with a club", "produces": [ "application/json" ], "tags": [ - "user" + "club-member" ], - "summary": "Updates a user", - "operationId": "update-user-by-id", + "summary": "Retrieve all members for a club", + "operationId": "get-members-by-club", "parameters": [ { "type": "string", - "description": "User ID", - "name": "id", + "description": "Club ID", + "name": "clubID", "in": "path", "required": true + }, + { + "type": "integer", + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.User" + "type": "array", + "items": { + "$ref": "#/definitions/models.User" + } } }, "400": { - "description": "failed to validate id", + "description": "Bad Request", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" } }, "404": { - "description": "user not found", + "description": "Not Found", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } }, "500": { - "description": "failed to hash password", + "description": "Internal Server Error", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } } } } - } - }, - "definitions": { - "models.Category": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "created_at": { - "type": "string", - "example": "2023-09-20T16:34:50Z" - }, - "id": { - "type": "string", + }, + "/club/{clubID}/tags": { + "get": { + "description": "Retrieves all tags associated with a club", + "produces": [ + "application/json" + ], + "tags": [ + "club-tag" + ], + "summary": "Retrieve all tags for a club", + "operationId": "get-tags-by-club", + "parameters": [ + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Tag" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "post": { + "description": "Creates tags for a club", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "club-tag" + ], + "summary": "Create club tags", + "operationId": "create-club-tags", + "parameters": [ + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + }, + { + "description": "Club Tags Body", + "name": "clubTagsBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.CreateClubTagsRequestBody" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Tag" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/club/{clubID}/tags/{tagID}": { + "delete": { + "description": "Deletes a tag associated with a club", + "produces": [ + "application/json" + ], + "tags": [ + "club-tag" + ], + "summary": "Delete a tag for a club", + "operationId": "delete-tag-by-club", + "parameters": [ + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Tag ID", + "name": "tagID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/contact/": { + "get": { + "description": "Retrieves all contacts", + "produces": [ + "application/json" + ], + "tags": [ + "contact" + ], + "summary": "Retrieve all contacts", + "operationId": "get-contacts", + "parameters": [ + { + "type": "integer", + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Contact" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "description": "Creates a contact", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "contact" + ], + "summary": "Creates a contact", + "operationId": "create-contact", + "parameters": [ + { + "description": "Contact Body", + "name": "contactBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.Contact" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/models.Contact" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/event/": { + "get": { + "description": "Retrieves all events", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Retrieve all events", + "operationId": "get-all-events", + "parameters": [ + { + "type": "integer", + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Event" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "post": { + "description": "Creates an event", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Create an event", + "operationId": "create-event", + "parameters": [ + { + "description": "Event Body", + "name": "event", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.CreateEventRequestBody" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/models.Event" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/event/{eventID}": { + "get": { + "description": "Retrieves an event", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Retrieve an event", + "operationId": "get-event", + "parameters": [ + { + "type": "string", + "description": "Event ID", + "name": "eventID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.Event" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "delete": { + "description": "Deletes an event", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Delete an event", + "operationId": "delete-event", + "parameters": [ + { + "type": "string", + "description": "Event ID", + "name": "eventID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/event/{eventID}/series": { + "get": { + "description": "Retrieves all series associated with an event", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Retrieve all series by event", + "operationId": "get-series-by-event", + "parameters": [ + { + "type": "string", + "description": "Event ID", + "name": "eventID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Series" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "post": { + "description": "Creates a series", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Create a series", + "operationId": "create-series", + "parameters": [ + { + "type": "string", + "description": "Event ID", + "name": "eventID", + "in": "path", + "required": true + }, + { + "description": "Series Body", + "name": "seriesBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.CreateSeriesRequestBody" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/models.Series" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "delete": { + "description": "Deletes all series associated with an event", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Delete all series by event", + "operationId": "delete-series-by-event", + "parameters": [ + { + "type": "string", + "description": "Event ID", + "name": "eventID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/event/{eventID}/series/{seriesID}": { + "put": { + "description": "Updates a series by ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Update a series by ID", + "operationId": "update-series-by-id", + "parameters": [ + { + "type": "string", + "description": "Event ID", + "name": "eventID", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Series ID", + "name": "seriesID", + "in": "path", + "required": true + }, + { + "description": "Series Body", + "name": "seriesBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.UpdateSeriesRequestBody" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.Series" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/series/{seriesID}": { + "get": { + "description": "Retrieves a series by ID", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Retrieve a series by ID", + "operationId": "get-series-by-id", + "parameters": [ + { + "type": "string", + "description": "Series ID", + "name": "seriesID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.Series" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "delete": { + "description": "Deletes a series by ID", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Delete a series by ID", + "operationId": "delete-series-by-id", + "parameters": [ + { + "type": "string", + "description": "Series ID", + "name": "seriesID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/tags": { + "get": { + "description": "Retrieves all tags", + "produces": [ + "application/json" + ], + "tags": [ + "tag" + ], + "summary": "Retrieve all tags", + "operationId": "get-all-tags", + "parameters": [ + { + "type": "integer", + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Tag" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/tags/{tagID}": { + "get": { + "description": "Retrieves a tag", + "produces": [ + "application/json" + ], + "tags": [ + "tag" + ], + "summary": "Retrieve a tag", + "operationId": "get-tag", + "parameters": [ + { + "type": "string", + "description": "Tag ID", + "name": "tagID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.Tag" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "put": { + "description": "Updates a tag", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "tag" + ], + "summary": "Update a tag", + "operationId": "update-tag", + "parameters": [ + { + "type": "string", + "description": "Tag ID", + "name": "tagID", + "in": "path", + "required": true + }, + { + "description": "Tag", + "name": "tag", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.TagRequestBody" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.Tag" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "delete": { + "description": "Deletes a tag", + "produces": [ + "application/json" + ], + "tags": [ + "tag" + ], + "summary": "Delete a tag", + "operationId": "delete-tag", + "parameters": [ + { + "type": "string", + "description": "Tag ID", + "name": "tagID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/user/": { + "post": { + "description": "Creates a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user" + ], + "summary": "Create a user", + "operationId": "create-user", + "parameters": [ + { + "description": "User Body", + "name": "userBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.CreateUserRequestBody" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/models.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/user/{userID}": { + "get": { + "description": "Retrieves a user", + "produces": [ + "application/json" + ], + "tags": [ + "user" + ], + "summary": "Retrieve a user", + "operationId": "get-user", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "put": { + "description": "Updates a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user" + ], + "summary": "Update a user", + "operationId": "update-user", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + }, + { + "description": "User Body", + "name": "userBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.UpdateUserRequestBody" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "delete": { + "description": "Deletes a user", + "produces": [ + "application/json" + ], + "tags": [ + "user" + ], + "summary": "Delete a user", + "operationId": "delete-user", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/user/{userID}/following": { + "get": { + "description": "Retrieves all clubs a user is following", + "produces": [ + "application/json" + ], + "tags": [ + "user-follower" + ], + "summary": "Retrieve all clubs a user is following", + "operationId": "get-following", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Club" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/user/{userID}/following/{clubID}": { + "post": { + "description": "Follow a club", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user-follower" + ], + "summary": "Follow a club", + "operationId": "create-following", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/utilities.SuccessResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "delete": { + "description": "Unfollow a club", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user-follower" + ], + "summary": "Unfollow a club", + "operationId": "delete-following", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "$ref": "#/definitions/utilities.SuccessResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/user/{userID}/membership": { + "get": { + "description": "Retrieves all clubs a user is a member of", + "produces": [ + "application/json" + ], + "tags": [ + "user-member" + ], + "summary": "Retrieve all clubs a user is a member of", + "operationId": "get-membership", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Club" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/user/{userID}/membership/{clubID}": { + "post": { + "description": "Join a club", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user-member" + ], + "summary": "Join a club", + "operationId": "create-membership", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/utilities.SuccessResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "delete": { + "description": "Leave a club", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user-member" + ], + "summary": "Leave a club", + "operationId": "delete-membership", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "$ref": "#/definitions/utilities.SuccessResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/user/{userID}/tags": { + "get": { + "description": "Retrieves all tags associated with a user", + "produces": [ + "application/json" + ], + "tags": [ + "user-tag" + ], + "summary": "Retrieve all tags for a user", + "operationId": "get-tags-by-user", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Tag" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "post": { + "description": "Creates tags for a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user-tag" + ], + "summary": "Create user tags", + "operationId": "create-user-tags", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + }, + { + "description": "User Tags Body", + "name": "userTagsBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.CreateUserTagsBody" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Tag" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + } + }, + "definitions": { + "errors.Error": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "statusCode": { + "type": "integer" + } + } + }, + "models.Category": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "created_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + }, + "id": { + "type": "string", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "name": { + "type": "string", + "maxLength": 255 + }, + "updated_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + } + } + }, + "models.CategoryRequestBody": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "maxLength": 255 + } + } + }, + "models.Club": { + "type": "object", + "required": [ + "application_link", + "description", + "is_recruiting", + "name", + "num_members", + "preview", + "recruitment_cycle", + "recruitment_type" + ], + "properties": { + "application_link": { + "type": "string", + "maxLength": 255 + }, + "created_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + }, + "description": { + "description": "MongoDB URL", + "type": "string", + "maxLength": 255 + }, + "id": { + "type": "string", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "is_recruiting": { + "type": "boolean" + }, + "logo": { + "description": "S3 URL", + "type": "string", + "maxLength": 255 + }, + "name": { + "type": "string", + "maxLength": 255 + }, + "num_members": { + "type": "integer", + "minimum": 1 + }, + "preview": { + "type": "string", + "maxLength": 255 + }, + "recruitment_cycle": { + "maxLength": 255, + "enum": [ + "fall", + "spring", + "fallSpring", + "always" + ], + "allOf": [ + { + "$ref": "#/definitions/models.RecruitmentCycle" + } + ] + }, + "recruitment_type": { + "maxLength": 255, + "enum": [ + "unrestricted", + "tryout", + "application" + ], + "allOf": [ + { + "$ref": "#/definitions/models.RecruitmentType" + } + ] + }, + "tags": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Tag" + } + }, + "updated_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + } + } + }, + "models.College": { + "type": "string", + "enum": [ + "CAMD", + "DMSB", + "KCCS", + "CE", + "BCHS", + "SL", + "CPS", + "CS", + "CSSH" + ], + "x-enum-comments": { + "BCHS": "Bouvé College of Health Sciences", + "CAMD": "College of Arts, Media and Design", + "CE": "College of Engineering", + "CPS": "College of Professional Studies", + "CS": "College of Science", + "CSSH": "College of Social Sciences and Humanities", + "DMSB": "D'Amore-McKim School of Business", + "KCCS": "Khoury College of Computer Sciences", + "SL": "School of Law" + }, + "x-enum-varnames": [ + "CAMD", + "DMSB", + "KCCS", + "CE", + "BCHS", + "SL", + "CPS", + "CS", + "CSSH" + ] + }, + "models.Contact": { + "type": "object", + "required": [ + "content", + "type" + ], + "properties": { + "content": { + "type": "string", + "maxLength": 255 + }, + "created_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + }, + "id": { + "type": "string", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "type": { + "maxLength": 255, + "enum": [ + "facebook", + "instagram", + "twitter", + "linkedin", + "youtube", + "github", + "slack", + "discord", + "email", + "customSite" + ], + "allOf": [ + { + "$ref": "#/definitions/models.ContactType" + } + ] + }, + "updated_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + } + } + }, + "models.ContactType": { + "type": "string", + "enum": [ + "facebook", + "instagram", + "twitter", + "linkedin", + "youtube", + "github", + "slack", + "discord", + "email", + "customSite" + ], + "x-enum-varnames": [ + "Facebook", + "Instagram", + "Twitter", + "LinkedIn", + "YouTube", + "GitHub", + "Slack", + "Discord", + "Email", + "CustomSite" + ] + }, + "models.CreateClubRequestBody": { + "type": "object", + "required": [ + "application_link", + "description", + "is_recruiting", + "name", + "preview", + "recruitment_cycle", + "recruitment_type", + "user_id" + ], + "properties": { + "application_link": { + "type": "string", + "maxLength": 255 + }, + "description": { + "description": "MongoDB URL", + "type": "string", + "maxLength": 255 + }, + "is_recruiting": { + "type": "boolean" + }, + "logo": { + "description": "S3 URL", + "type": "string", + "maxLength": 255 + }, + "name": { + "type": "string", + "maxLength": 255 + }, + "preview": { + "type": "string", + "maxLength": 255 + }, + "recruitment_cycle": { + "maxLength": 255, + "enum": [ + "fall", + "spring", + "fallSpring", + "always" + ], + "allOf": [ + { + "$ref": "#/definitions/models.RecruitmentCycle" + } + ] + }, + "recruitment_type": { + "maxLength": 255, + "enum": [ + "unrestricted", + "tryout", + "application" + ], + "allOf": [ + { + "$ref": "#/definitions/models.RecruitmentType" + } + ] + }, + "user_id": { + "type": "string" + } + } + }, + "models.CreateClubTagsRequestBody": { + "type": "object", + "required": [ + "tags" + ], + "properties": { + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "models.CreateEventRequestBody": { + "type": "object", + "required": [ + "content", + "end_time", + "event_type", + "is_recurring", + "location", + "name", + "preview", + "start_time" + ], + "properties": { + "content": { + "type": "string", + "maxLength": 255 + }, + "end_time": { + "type": "string" + }, + "event_type": { + "maxLength": 255, + "allOf": [ + { + "$ref": "#/definitions/models.EventType" + } + ] + }, + "is_recurring": { + "type": "boolean" + }, + "location": { + "type": "string", + "maxLength": 255 + }, + "name": { + "type": "string", + "maxLength": 255 + }, + "preview": { + "type": "string", + "maxLength": 255 + }, + "series": { + "description": "TODO validate if isRecurring, then series is required", + "allOf": [ + { + "$ref": "#/definitions/models.CreateSeriesRequestBody" + } + ] + }, + "start_time": { + "type": "string" + } + } + }, + "models.CreateSeriesRequestBody": { + "type": "object", + "properties": { + "day_of_month": { + "type": "integer", + "maximum": 31, + "minimum": 1 + }, + "day_of_week": { + "type": "integer", + "maximum": 7, + "minimum": 1 + }, + "max_occurrences": { + "type": "integer", + "minimum": 2 + }, + "recurring_type": { + "maxLength": 255, + "allOf": [ + { + "$ref": "#/definitions/models.RecurringType" + } + ] + }, + "separation_count": { + "type": "integer", + "minimum": 0 + }, + "week_of_month": { + "type": "integer", + "maximum": 5, + "minimum": 1 + } + } + }, + "models.CreateUserRequestBody": { + "type": "object", + "required": [ + "college", + "email", + "first_name", + "last_name", + "nuid", + "password", + "year" + ], + "properties": { + "college": { + "enum": [ + "CAMD", + "DMSB", + "KCCS", + "CE", + "BCHS", + "SL", + "CPS", + "CS", + "CSSH" + ], + "allOf": [ + { + "$ref": "#/definitions/models.College" + } + ] + }, + "email": { + "type": "string", + "maxLength": 255 + }, + "first_name": { + "type": "string", + "maxLength": 255 + }, + "last_name": { + "type": "string", + "maxLength": 255 + }, + "nuid": { + "type": "string" + }, + "password": { + "type": "string" + }, + "year": { + "maximum": 6, + "minimum": 1, + "allOf": [ + { + "$ref": "#/definitions/models.Year" + } + ] + } + } + }, + "models.CreateUserTagsBody": { + "type": "object", + "required": [ + "tags" + ], + "properties": { + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "models.Event": { + "type": "object", + "required": [ + "content", + "end_time", + "event_type", + "location", + "name", + "preview", + "start_time" + ], + "properties": { + "content": { + "type": "string", + "maxLength": 255 + }, + "created_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + }, + "end_time": { + "type": "string" + }, + "event_type": { + "maxLength": 255, + "allOf": [ + { + "$ref": "#/definitions/models.EventType" + } + ] + }, + "id": { + "type": "string", "example": "123e4567-e89b-12d3-a456-426614174000" }, + "is_recurring": { + "type": "boolean" + }, + "location": { + "type": "string", + "maxLength": 255 + }, "name": { "type": "string", "maxLength": 255 }, + "preview": { + "type": "string", + "maxLength": 255 + }, + "start_time": { + "type": "string" + }, "updated_at": { "type": "string", "example": "2023-09-20T16:34:50Z" } } }, - "models.College": { + "models.EventType": { "type": "string", "enum": [ - "CAMD", - "DMSB", - "KCCS", - "CE", - "BCHS", - "SL", - "CPS", - "CS", - "CSSH" + "open", + "membersOnly" ], - "x-enum-comments": { - "BCHS": "Bouvé College of Health Sciences", - "CAMD": "College of Arts, Media and Design", - "CE": "College of Engineering", - "CPS": "College of Professional Studies", - "CS": "College of Science", - "CSSH": "College of Social Sciences and Humanities", - "DMSB": "D'Amore-McKim School of Business", - "KCCS": "Khoury College of Computer Sciences", - "SL": "School of Law" - }, "x-enum-varnames": [ - "CAMD", - "DMSB", - "KCCS", - "CE", - "BCHS", - "SL", - "CPS", - "CS", - "CSSH" + "Open", + "MembersOnly" + ] + }, + "models.LoginUserResponseBody": { + "type": "object", + "required": [ + "email" + ], + "properties": { + "email": { + "type": "string" + }, + "password": { + "type": "string", + "maxLength": 255, + "minLength": 8 + } + } + }, + "models.PutContactRequestBody": { + "type": "object", + "required": [ + "content", + "type" + ], + "properties": { + "content": { + "type": "string", + "maxLength": 255 + }, + "type": { + "maxLength": 255, + "enum": [ + "facebook", + "instagram", + "twitter", + "linkedin", + "youtube", + "github", + "slack", + "discord", + "email", + "customSite" + ], + "allOf": [ + { + "$ref": "#/definitions/models.ContactType" + } + ] + } + } + }, + "models.RecruitmentCycle": { + "type": "string", + "enum": [ + "fall", + "spring", + "fallSpring", + "always" + ], + "x-enum-varnames": [ + "Fall", + "Spring", + "FallSpring", + "Always" ] }, + "models.RecruitmentType": { + "type": "string", + "enum": [ + "unrestricted", + "tryout", + "application" + ], + "x-enum-varnames": [ + "Unrestricted", + "Tryout", + "Application" + ] + }, + "models.RecurringType": { + "type": "string", + "enum": [ + "daily", + "weekly", + "monthly" + ], + "x-enum-varnames": [ + "Daily", + "Weekly", + "Monthly" + ] + }, + "models.Series": { + "type": "object", + "properties": { + "created_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + }, + "day_of_month": { + "type": "integer", + "maximum": 31, + "minimum": 1 + }, + "day_of_week": { + "type": "integer", + "maximum": 7, + "minimum": 1 + }, + "events": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Event" + } + }, + "id": { + "type": "string", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "max_occurrences": { + "type": "integer", + "minimum": 1 + }, + "recurring_type": { + "maxLength": 255, + "allOf": [ + { + "$ref": "#/definitions/models.RecurringType" + } + ] + }, + "separation_count": { + "type": "integer", + "minimum": 0 + }, + "updated_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + }, + "week_of_month": { + "type": "integer", + "maximum": 5, + "minimum": 1 + } + } + }, "models.Tag": { "type": "object", "required": [ @@ -814,6 +3714,182 @@ const docTemplate = `{ } } }, + "models.TagRequestBody": { + "type": "object", + "required": [ + "category_id", + "name" + ], + "properties": { + "category_id": { + "type": "string" + }, + "name": { + "type": "string", + "maxLength": 255 + } + } + }, + "models.UpdateClubRequestBody": { + "type": "object", + "required": [ + "application_link", + "recruitment_cycle", + "recruitment_type" + ], + "properties": { + "application_link": { + "type": "string", + "maxLength": 255 + }, + "description": { + "description": "MongoDB URL", + "type": "string", + "maxLength": 255 + }, + "is_recruiting": { + "type": "boolean" + }, + "logo": { + "description": "S3 URL", + "type": "string", + "maxLength": 255 + }, + "name": { + "type": "string", + "maxLength": 255 + }, + "preview": { + "type": "string", + "maxLength": 255 + }, + "recruitment_cycle": { + "maxLength": 255, + "enum": [ + "fall", + "spring", + "fallSpring", + "always" + ], + "allOf": [ + { + "$ref": "#/definitions/models.RecruitmentCycle" + } + ] + }, + "recruitment_type": { + "maxLength": 255, + "enum": [ + "unrestricted", + "tryout", + "application" + ], + "allOf": [ + { + "$ref": "#/definitions/models.RecruitmentType" + } + ] + } + } + }, + "models.UpdatePasswordRequestBody": { + "type": "object", + "required": [ + "new_password", + "old_password" + ], + "properties": { + "new_password": { + "type": "string" + }, + "old_password": { + "type": "string" + } + } + }, + "models.UpdateSeriesRequestBody": { + "type": "object", + "properties": { + "day_of_month": { + "type": "integer", + "maximum": 31, + "minimum": 1 + }, + "day_of_week": { + "type": "integer", + "maximum": 7, + "minimum": 1 + }, + "max_occurrences": { + "type": "integer", + "minimum": 2 + }, + "recurring_type": { + "maxLength": 255, + "allOf": [ + { + "$ref": "#/definitions/models.RecurringType" + } + ] + }, + "separation_count": { + "type": "integer", + "minimum": 0 + }, + "week_of_month": { + "type": "integer", + "maximum": 5, + "minimum": 1 + } + } + }, + "models.UpdateUserRequestBody": { + "type": "object", + "properties": { + "college": { + "enum": [ + "CAMD", + "DMSB", + "KCCS", + "CE", + "BCHS", + "SL", + "CPS", + "CS", + "CSSH" + ], + "allOf": [ + { + "$ref": "#/definitions/models.College" + } + ] + }, + "email": { + "type": "string", + "maxLength": 255 + }, + "first_name": { + "type": "string", + "maxLength": 255 + }, + "last_name": { + "type": "string", + "maxLength": 255 + }, + "nuid": { + "type": "string" + }, + "year": { + "maximum": 6, + "minimum": 1, + "allOf": [ + { + "$ref": "#/definitions/models.Year" + } + ] + } + } + }, "models.User": { "type": "object", "required": [ @@ -826,6 +3902,12 @@ const docTemplate = `{ "year" ], "properties": { + "clubs_followed": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Club" + } + }, "college": { "maxLength": 255, "allOf": [ @@ -858,14 +3940,10 @@ const docTemplate = `{ "type": "string" }, "role": { + "type": "string", "enum": [ "super", "student" - ], - "allOf": [ - { - "$ref": "#/definitions/models.UserRole" - } ] }, "updated_at": { @@ -883,17 +3961,6 @@ const docTemplate = `{ } } }, - "models.UserRole": { - "type": "string", - "enum": [ - "super", - "student" - ], - "x-enum-varnames": [ - "Super", - "Student" - ] - }, "models.Year": { "type": "integer", "enum": [ @@ -912,6 +3979,14 @@ const docTemplate = `{ "Fifth", "Graduate" ] + }, + "utilities.SuccessResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } } } }` diff --git a/backend/src/docs/swagger.json b/backend/src/docs/swagger.json index bf6e5b07c..ed347770f 100644 --- a/backend/src/docs/swagger.json +++ b/backend/src/docs/swagger.json @@ -12,7 +12,7 @@ "host": "127.0.0.1:8080", "basePath": "/api/v1", "paths": { - "/api/v1/auth/login": { + "/auth/login": { "post": { "description": "Logs in a user", "consumes": [ @@ -22,47 +22,50 @@ "application/json" ], "tags": [ - "user" + "auth" ], "summary": "Logs in a user", "operationId": "login-user", "parameters": [ { - "description": "User Body", - "name": "userBody", + "description": "Login Body", + "name": "loginBody", "in": "body", "required": true, "schema": { - "type": "array", - "items": { - "type": "string" - } + "$ref": "#/definitions/models.LoginUserResponseBody" } } ], "responses": { "200": { - "description": "success", + "description": "OK", "schema": { - "type": "string" + "$ref": "#/definitions/utilities.SuccessResponse" } }, "400": { - "description": "failed to parse body", + "description": "Bad Request", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } }, - "401": { - "description": "failed to login user", + "404": { + "description": "Not Found", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" } } } } }, - "/api/v1/auth/logout": { + "/auth/logout": { "get": { "description": "Logs out a user", "consumes": [ @@ -72,7 +75,7 @@ "application/json" ], "tags": [ - "user" + "auth" ], "summary": "Logs out a user", "operationId": "logout-user", @@ -80,28 +83,22 @@ "200": { "description": "OK", "schema": { - "type": "string" - } - }, - "401": { - "description": "failed to logout user", - "schema": { - "type": "string" + "$ref": "#/definitions/utilities.SuccessResponse" } } } } }, - "/api/v1/auth/me": { + "/auth/me": { "get": { - "description": "Returns the current user", + "description": "Returns the current user associated with an auth session", "produces": [ "application/json" ], "tags": [ - "user" + "auth" ], - "summary": "Gets the current user", + "summary": "Retrieve the current user given an auth session", "operationId": "get-current-user", "responses": { "200": { @@ -110,16 +107,34 @@ "$ref": "#/definitions/models.User" } }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, "401": { - "description": "failed to get current user", + "description": "Unauthorized", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" } } } } }, - "/api/v1/auth/refresh": { + "/auth/refresh": { "get": { "description": "Refreshes a user's access token", "consumes": [ @@ -129,29 +144,100 @@ "application/json" ], "tags": [ - "user" + "auth" ], "summary": "Refreshes a user's access token", "operationId": "refresh-user", "responses": { "200": { - "description": "success", + "description": "OK", "schema": { - "type": "string" + "$ref": "#/definitions/utilities.SuccessResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/auth/update-password": { + "post": { + "description": "Updates a user's password", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Updates a user's password", + "operationId": "update-password", + "parameters": [ + { + "description": "User Body", + "name": "userBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.UpdatePasswordRequestBody" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/utilities.SuccessResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" } }, "401": { - "description": "failed to refresh access token", + "description": "Unauthorized", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" } } } } }, - "/api/v1/category/": { + "/category/": { "get": { - "description": "Retrieves all existing categories", + "description": "Retrieves all categories", "produces": [ "application/json" ], @@ -160,6 +246,20 @@ ], "summary": "Retrieve all categories", "operationId": "get-categories", + "parameters": [ + { + "type": "integer", + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" + } + ], "responses": { "200": { "description": "OK", @@ -170,8 +270,20 @@ } } }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + }, "500": { - "description": "unable to retrieve categories", + "description": "Internal Server Error", "schema": { "type": "string" } @@ -179,15 +291,29 @@ } }, "post": { - "description": "Creates a category that is used to group tags", + "description": "Creates a category", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ "category" ], - "summary": "Create a category", + "summary": "Creates a category", "operationId": "create-category", + "parameters": [ + { + "description": "Category Body", + "name": "categoryBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.CategoryRequestBody" + } + } + ], "responses": { "201": { "description": "Created", @@ -196,13 +322,25 @@ } }, "400": { - "description": "category with that name already exists", + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", "schema": { "type": "string" } }, "500": { - "description": "failed to create category", + "description": "Internal Server Error", "schema": { "type": "string" } @@ -210,9 +348,9 @@ } } }, - "/api/v1/category/{id}": { + "/category/{categoryID}": { "get": { - "description": "Retrieve a category by its ID", + "description": "Retrieves a category", "produces": [ "application/json" ], @@ -225,7 +363,7 @@ { "type": "string", "description": "Category ID", - "name": "id", + "name": "categoryID", "in": "path", "required": true } @@ -238,111 +376,135 @@ } }, "400": { - "description": "failed to validate id", + "description": "Bad Request", "schema": { "type": "string" } }, "404": { - "description": "faied to find category", + "description": "Not Found", "schema": { "type": "string" } }, "500": { - "description": "failed to retrieve category", + "description": "Internal Server Error", "schema": { "type": "string" } } } }, - "delete": { - "description": "Delete a category by ID", + "put": { + "description": "Updates a category", + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ "category" ], - "summary": "Delete a category", - "operationId": "delete-category", + "summary": "Updates a category", + "operationId": "update-category", "parameters": [ { "type": "string", "description": "Category ID", - "name": "id", + "name": "categoryID", "in": "path", "required": true + }, + { + "description": "Category Body", + "name": "categoryBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.CategoryRequestBody" + } } ], "responses": { - "204": { - "description": "no content", + "200": { + "description": "OK", "schema": { - "type": "string" + "$ref": "#/definitions/models.Category" } }, "400": { - "description": "failed to validate id", + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized", "schema": { "type": "string" } }, "404": { - "description": "failed to find category", + "description": "Not Found", "schema": { "type": "string" } }, "500": { - "description": "failed to delete category", + "description": "Internal Server Error", "schema": { "type": "string" } } } }, - "patch": { - "description": "Updates a category", + "delete": { + "description": "Deletes a category", "produces": [ "application/json" ], "tags": [ "category" ], - "summary": "Updates a category", - "operationId": "update-category", + "summary": "Deletes a category", + "operationId": "delete-category", "parameters": [ { "type": "string", "description": "Category ID", - "name": "id", + "name": "categoryID", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", + "204": { + "description": "No Content", "schema": { - "$ref": "#/definitions/models.Category" + "type": "string" } }, "400": { - "description": "failed to validate id", + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized", "schema": { "type": "string" } }, "404": { - "description": "failed to find category", + "description": "Not Found", "schema": { "type": "string" } }, "500": { - "description": "failed to update category", + "description": "Internal Server Error", "schema": { "type": "string" } @@ -350,58 +512,92 @@ } } }, - "/api/v1/tags/": { - "post": { - "description": "Creates a tag", - "consumes": [ - "application/json" - ], + "/category/{categoryID}/tags": { + "get": { + "description": "Retrieves all tags associated with a category", "produces": [ "application/json" ], "tags": [ - "tag" + "category-tag" + ], + "summary": "Retrieve all tags by category", + "operationId": "get-tags-by-category", + "parameters": [ + { + "type": "string", + "description": "Category ID", + "name": "categoryID", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" + } ], - "summary": "Creates a tag", - "operationId": "create-tag", "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/models.Tag" + "type": "array", + "items": { + "$ref": "#/definitions/models.Tag" + } } }, "400": { - "description": "failed to validate the data", + "description": "Bad Request", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" } }, "500": { - "description": "failed to create tag", + "description": "Internal Server Error", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } } } } }, - "/api/v1/tags/{id}": { + "/category/{categoryID}/tags/{tagID}": { "get": { - "description": "Returns a tag", + "description": "Retrieves a tag associated with a category", "produces": [ "application/json" ], "tags": [ - "tag" + "category-tag" ], - "summary": "Gets a tag", - "operationId": "get-tag", + "summary": "Retrieve a tag by category", + "operationId": "get-tag-by-category", "parameters": [ { - "type": "integer", + "type": "string", + "description": "Category ID", + "name": "categoryID", + "in": "path", + "required": true + }, + { + "type": "string", "description": "Tag ID", - "name": "id", + "name": "tagID", "in": "path", "required": true } @@ -414,70 +610,77 @@ } }, "400": { - "description": "failed to validate id", + "description": "Bad Request", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } }, "404": { - "description": "faied to find tag", + "description": "Not Found", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } }, "500": { - "description": "failed to retrieve tag", + "description": "Internal Server Error", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } } } - }, - "delete": { - "description": "Deletes a tag", + } + }, + "/club/": { + "get": { + "description": "Retrieves all clubs", + "produces": [ + "application/json" + ], "tags": [ - "tag" + "club" ], - "summary": "Deletes a tag", - "operationId": "delete-tag", + "summary": "Retrieve all clubs", + "operationId": "get-all-clubs", "parameters": [ { "type": "integer", - "description": "Tag ID", - "name": "id", - "in": "path", - "required": true + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" } ], "responses": { - "204": { - "description": "no content", + "200": { + "description": "OK", "schema": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/models.Club" + } } }, "400": { - "description": "failed to validate id", - "schema": { - "type": "string" - } - }, - "404": { - "description": "tag not found", + "description": "Bad Request", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } }, "500": { - "description": "failed to delete tag", + "description": "Internal Server Error", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } } } }, - "patch": { - "description": "Updates a tag", + "post": { + "description": "Creates a club", "consumes": [ "application/json" ], @@ -485,16 +688,72 @@ "application/json" ], "tags": [ - "tag" + "club" ], - "summary": "Updates a tag", - "operationId": "update-tag", + "summary": "Create a club", + "operationId": "create-club", "parameters": [ { - "type": "integer", - "description": "Tag ID", - "name": "id", - "in": "path", + "description": "Club", + "name": "club", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.CreateClubRequestBody" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/models.Club" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/club/{clubID}": { + "get": { + "description": "Retrieves a club", + "produces": [ + "application/json" + ], + "tags": [ + "club" + ], + "summary": "Retrieve a club", + "operationId": "get-club", + "parameters": [ + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", "required": true } ], @@ -502,61 +761,198 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Tag" + "$ref": "#/definitions/models.Club" } }, "400": { - "description": "failed to validate the data", + "description": "Bad Request", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } }, "404": { - "description": "failed to find tag", + "description": "Not Found", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "put": { + "description": "Updates a club", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "club" + ], + "summary": "Update a club", + "operationId": "update-club", + "parameters": [ + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + }, + { + "description": "Club", + "name": "club", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.UpdateClubRequestBody" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.Club" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" } }, "500": { - "description": "failed to update tag", + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "delete": { + "description": "Deletes a club", + "produces": [ + "application/json" + ], + "tags": [ + "club" + ], + "summary": "Delete a club", + "operationId": "delete-club", + "parameters": [ + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", "schema": { "type": "string" } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } } } } }, - "/api/v1/users/": { + "/club/{clubID}/contacts": { "get": { - "description": "Returns all users", + "description": "Retrieves all contacts associated with a club", "produces": [ "application/json" ], "tags": [ - "user" + "club-contact" + ], + "summary": "Retrieve all contacts for a club", + "operationId": "get-contacts-by-club", + "parameters": [ + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + } ], - "summary": "Gets all users", - "operationId": "get-all-users", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/models.User" + "$ref": "#/definitions/models.Contact" } } }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, "500": { - "description": "failed to get all users", + "description": "Internal Server Error", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } } } }, "post": { - "description": "Creates a user", + "description": "Creates a contact", "consumes": [ "application/json" ], @@ -564,222 +960,2726 @@ "application/json" ], "tags": [ - "user" + "club-contact" + ], + "summary": "Creates a contact", + "operationId": "create-contact", + "parameters": [ + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + }, + { + "description": "Contact Body", + "name": "contactBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.PutContactRequestBody" + } + } ], - "summary": "Creates a User", - "operationId": "create-user", "responses": { "201": { "description": "Created", "schema": { - "$ref": "#/definitions/models.User" + "$ref": "#/definitions/models.Contact" } }, "400": { - "description": "failed to create user", + "description": "Bad Request", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" } }, "500": { - "description": "internal server error", + "description": "Internal Server Error", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } } } } }, - "/api/v1/users/{id}": { + "/club/{clubID}/events": { "get": { - "description": "Returns a user", + "description": "Retrieves all events associated with a club", "produces": [ "application/json" ], "tags": [ - "user" + "club-event" ], - "summary": "Gets a user", - "operationId": "get-user-by-id", + "summary": "Retrieve all events for a club", + "operationId": "get-events-by-club", "parameters": [ { "type": "string", - "description": "User ID", - "name": "id", + "description": "Club ID", + "name": "clubID", "in": "path", "required": true + }, + { + "type": "integer", + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.User" + "type": "array", + "items": { + "$ref": "#/definitions/models.Event" + } } }, "400": { - "description": "failed to validate id", + "description": "Bad Request", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } }, "404": { - "description": "user not found", + "description": "Not Found", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } }, "500": { - "description": "failed to get user", + "description": "Internal Server Error", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } } } - }, - "delete": { - "description": "Returns nil", + } + }, + "/club/{clubID}/followers": { + "get": { + "description": "Retrieves all followers associated with a club", "produces": [ "application/json" ], "tags": [ - "user" + "club-follower" ], - "summary": "Deletes the given userID", - "operationId": "delete-user", + "summary": "Retrieve all followers for a club", + "operationId": "get-followers-by-club", "parameters": [ { "type": "string", - "description": "User ID", - "name": "id", + "description": "Club ID", + "name": "clubID", "in": "path", "required": true + }, + { + "type": "integer", + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" } ], "responses": { - "204": { - "description": "no content", + "200": { + "description": "OK", "schema": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/definitions/models.User" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" } }, "500": { - "description": "failed to get all users", + "description": "Internal Server Error", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } } } - }, - "patch": { - "description": "Updates a user", + } + }, + "/club/{clubID}/members": { + "get": { + "description": "Retrieves all members associated with a club", "produces": [ "application/json" ], "tags": [ - "user" + "club-member" ], - "summary": "Updates a user", - "operationId": "update-user-by-id", + "summary": "Retrieve all members for a club", + "operationId": "get-members-by-club", "parameters": [ { "type": "string", - "description": "User ID", - "name": "id", + "description": "Club ID", + "name": "clubID", "in": "path", "required": true + }, + { + "type": "integer", + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.User" + "type": "array", + "items": { + "$ref": "#/definitions/models.User" + } } }, "400": { - "description": "failed to validate id", + "description": "Bad Request", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" } }, "404": { - "description": "user not found", + "description": "Not Found", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } }, "500": { - "description": "failed to hash password", + "description": "Internal Server Error", "schema": { - "type": "string" + "$ref": "#/definitions/errors.Error" } } } } - } - }, - "definitions": { - "models.Category": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "created_at": { - "type": "string", - "example": "2023-09-20T16:34:50Z" - }, - "id": { - "type": "string", + }, + "/club/{clubID}/tags": { + "get": { + "description": "Retrieves all tags associated with a club", + "produces": [ + "application/json" + ], + "tags": [ + "club-tag" + ], + "summary": "Retrieve all tags for a club", + "operationId": "get-tags-by-club", + "parameters": [ + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Tag" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "post": { + "description": "Creates tags for a club", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "club-tag" + ], + "summary": "Create club tags", + "operationId": "create-club-tags", + "parameters": [ + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + }, + { + "description": "Club Tags Body", + "name": "clubTagsBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.CreateClubTagsRequestBody" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Tag" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/club/{clubID}/tags/{tagID}": { + "delete": { + "description": "Deletes a tag associated with a club", + "produces": [ + "application/json" + ], + "tags": [ + "club-tag" + ], + "summary": "Delete a tag for a club", + "operationId": "delete-tag-by-club", + "parameters": [ + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Tag ID", + "name": "tagID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/contact/": { + "get": { + "description": "Retrieves all contacts", + "produces": [ + "application/json" + ], + "tags": [ + "contact" + ], + "summary": "Retrieve all contacts", + "operationId": "get-contacts", + "parameters": [ + { + "type": "integer", + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Contact" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "description": "Creates a contact", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "contact" + ], + "summary": "Creates a contact", + "operationId": "create-contact", + "parameters": [ + { + "description": "Contact Body", + "name": "contactBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.Contact" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/models.Contact" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/event/": { + "get": { + "description": "Retrieves all events", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Retrieve all events", + "operationId": "get-all-events", + "parameters": [ + { + "type": "integer", + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Event" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "post": { + "description": "Creates an event", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Create an event", + "operationId": "create-event", + "parameters": [ + { + "description": "Event Body", + "name": "event", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.CreateEventRequestBody" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/models.Event" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/event/{eventID}": { + "get": { + "description": "Retrieves an event", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Retrieve an event", + "operationId": "get-event", + "parameters": [ + { + "type": "string", + "description": "Event ID", + "name": "eventID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.Event" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "delete": { + "description": "Deletes an event", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Delete an event", + "operationId": "delete-event", + "parameters": [ + { + "type": "string", + "description": "Event ID", + "name": "eventID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/event/{eventID}/series": { + "get": { + "description": "Retrieves all series associated with an event", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Retrieve all series by event", + "operationId": "get-series-by-event", + "parameters": [ + { + "type": "string", + "description": "Event ID", + "name": "eventID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Series" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "post": { + "description": "Creates a series", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Create a series", + "operationId": "create-series", + "parameters": [ + { + "type": "string", + "description": "Event ID", + "name": "eventID", + "in": "path", + "required": true + }, + { + "description": "Series Body", + "name": "seriesBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.CreateSeriesRequestBody" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/models.Series" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "delete": { + "description": "Deletes all series associated with an event", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Delete all series by event", + "operationId": "delete-series-by-event", + "parameters": [ + { + "type": "string", + "description": "Event ID", + "name": "eventID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/event/{eventID}/series/{seriesID}": { + "put": { + "description": "Updates a series by ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Update a series by ID", + "operationId": "update-series-by-id", + "parameters": [ + { + "type": "string", + "description": "Event ID", + "name": "eventID", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Series ID", + "name": "seriesID", + "in": "path", + "required": true + }, + { + "description": "Series Body", + "name": "seriesBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.UpdateSeriesRequestBody" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.Series" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/series/{seriesID}": { + "get": { + "description": "Retrieves a series by ID", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Retrieve a series by ID", + "operationId": "get-series-by-id", + "parameters": [ + { + "type": "string", + "description": "Series ID", + "name": "seriesID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.Series" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "delete": { + "description": "Deletes a series by ID", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Delete a series by ID", + "operationId": "delete-series-by-id", + "parameters": [ + { + "type": "string", + "description": "Series ID", + "name": "seriesID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/tags": { + "get": { + "description": "Retrieves all tags", + "produces": [ + "application/json" + ], + "tags": [ + "tag" + ], + "summary": "Retrieve all tags", + "operationId": "get-all-tags", + "parameters": [ + { + "type": "integer", + "description": "Limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page", + "name": "page", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Tag" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/tags/{tagID}": { + "get": { + "description": "Retrieves a tag", + "produces": [ + "application/json" + ], + "tags": [ + "tag" + ], + "summary": "Retrieve a tag", + "operationId": "get-tag", + "parameters": [ + { + "type": "string", + "description": "Tag ID", + "name": "tagID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.Tag" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "put": { + "description": "Updates a tag", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "tag" + ], + "summary": "Update a tag", + "operationId": "update-tag", + "parameters": [ + { + "type": "string", + "description": "Tag ID", + "name": "tagID", + "in": "path", + "required": true + }, + { + "description": "Tag", + "name": "tag", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.TagRequestBody" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.Tag" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "delete": { + "description": "Deletes a tag", + "produces": [ + "application/json" + ], + "tags": [ + "tag" + ], + "summary": "Delete a tag", + "operationId": "delete-tag", + "parameters": [ + { + "type": "string", + "description": "Tag ID", + "name": "tagID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/user/": { + "post": { + "description": "Creates a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user" + ], + "summary": "Create a user", + "operationId": "create-user", + "parameters": [ + { + "description": "User Body", + "name": "userBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.CreateUserRequestBody" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/models.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/user/{userID}": { + "get": { + "description": "Retrieves a user", + "produces": [ + "application/json" + ], + "tags": [ + "user" + ], + "summary": "Retrieve a user", + "operationId": "get-user", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "put": { + "description": "Updates a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user" + ], + "summary": "Update a user", + "operationId": "update-user", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + }, + { + "description": "User Body", + "name": "userBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.UpdateUserRequestBody" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.User" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "delete": { + "description": "Deletes a user", + "produces": [ + "application/json" + ], + "tags": [ + "user" + ], + "summary": "Delete a user", + "operationId": "delete-user", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/user/{userID}/following": { + "get": { + "description": "Retrieves all clubs a user is following", + "produces": [ + "application/json" + ], + "tags": [ + "user-follower" + ], + "summary": "Retrieve all clubs a user is following", + "operationId": "get-following", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Club" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/user/{userID}/following/{clubID}": { + "post": { + "description": "Follow a club", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user-follower" + ], + "summary": "Follow a club", + "operationId": "create-following", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/utilities.SuccessResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "delete": { + "description": "Unfollow a club", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user-follower" + ], + "summary": "Unfollow a club", + "operationId": "delete-following", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "$ref": "#/definitions/utilities.SuccessResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/user/{userID}/membership": { + "get": { + "description": "Retrieves all clubs a user is a member of", + "produces": [ + "application/json" + ], + "tags": [ + "user-member" + ], + "summary": "Retrieve all clubs a user is a member of", + "operationId": "get-membership", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Club" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/user/{userID}/membership/{clubID}": { + "post": { + "description": "Join a club", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user-member" + ], + "summary": "Join a club", + "operationId": "create-membership", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/utilities.SuccessResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "delete": { + "description": "Leave a club", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user-member" + ], + "summary": "Leave a club", + "operationId": "delete-membership", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Club ID", + "name": "clubID", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content", + "schema": { + "$ref": "#/definitions/utilities.SuccessResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, + "/user/{userID}/tags": { + "get": { + "description": "Retrieves all tags associated with a user", + "produces": [ + "application/json" + ], + "tags": [ + "user-tag" + ], + "summary": "Retrieve all tags for a user", + "operationId": "get-tags-by-user", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Tag" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + }, + "post": { + "description": "Creates tags for a user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "user-tag" + ], + "summary": "Create user tags", + "operationId": "create-user-tags", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "userID", + "in": "path", + "required": true + }, + { + "description": "User Tags Body", + "name": "userTagsBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/models.CreateUserTagsBody" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Tag" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/errors.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + } + }, + "definitions": { + "errors.Error": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "statusCode": { + "type": "integer" + } + } + }, + "models.Category": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "created_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + }, + "id": { + "type": "string", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "name": { + "type": "string", + "maxLength": 255 + }, + "updated_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + } + } + }, + "models.CategoryRequestBody": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "maxLength": 255 + } + } + }, + "models.Club": { + "type": "object", + "required": [ + "application_link", + "description", + "is_recruiting", + "name", + "num_members", + "preview", + "recruitment_cycle", + "recruitment_type" + ], + "properties": { + "application_link": { + "type": "string", + "maxLength": 255 + }, + "created_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + }, + "description": { + "description": "MongoDB URL", + "type": "string", + "maxLength": 255 + }, + "id": { + "type": "string", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "is_recruiting": { + "type": "boolean" + }, + "logo": { + "description": "S3 URL", + "type": "string", + "maxLength": 255 + }, + "name": { + "type": "string", + "maxLength": 255 + }, + "num_members": { + "type": "integer", + "minimum": 1 + }, + "preview": { + "type": "string", + "maxLength": 255 + }, + "recruitment_cycle": { + "maxLength": 255, + "enum": [ + "fall", + "spring", + "fallSpring", + "always" + ], + "allOf": [ + { + "$ref": "#/definitions/models.RecruitmentCycle" + } + ] + }, + "recruitment_type": { + "maxLength": 255, + "enum": [ + "unrestricted", + "tryout", + "application" + ], + "allOf": [ + { + "$ref": "#/definitions/models.RecruitmentType" + } + ] + }, + "tags": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Tag" + } + }, + "updated_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + } + } + }, + "models.College": { + "type": "string", + "enum": [ + "CAMD", + "DMSB", + "KCCS", + "CE", + "BCHS", + "SL", + "CPS", + "CS", + "CSSH" + ], + "x-enum-comments": { + "BCHS": "Bouvé College of Health Sciences", + "CAMD": "College of Arts, Media and Design", + "CE": "College of Engineering", + "CPS": "College of Professional Studies", + "CS": "College of Science", + "CSSH": "College of Social Sciences and Humanities", + "DMSB": "D'Amore-McKim School of Business", + "KCCS": "Khoury College of Computer Sciences", + "SL": "School of Law" + }, + "x-enum-varnames": [ + "CAMD", + "DMSB", + "KCCS", + "CE", + "BCHS", + "SL", + "CPS", + "CS", + "CSSH" + ] + }, + "models.Contact": { + "type": "object", + "required": [ + "content", + "type" + ], + "properties": { + "content": { + "type": "string", + "maxLength": 255 + }, + "created_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + }, + "id": { + "type": "string", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "type": { + "maxLength": 255, + "enum": [ + "facebook", + "instagram", + "twitter", + "linkedin", + "youtube", + "github", + "slack", + "discord", + "email", + "customSite" + ], + "allOf": [ + { + "$ref": "#/definitions/models.ContactType" + } + ] + }, + "updated_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + } + } + }, + "models.ContactType": { + "type": "string", + "enum": [ + "facebook", + "instagram", + "twitter", + "linkedin", + "youtube", + "github", + "slack", + "discord", + "email", + "customSite" + ], + "x-enum-varnames": [ + "Facebook", + "Instagram", + "Twitter", + "LinkedIn", + "YouTube", + "GitHub", + "Slack", + "Discord", + "Email", + "CustomSite" + ] + }, + "models.CreateClubRequestBody": { + "type": "object", + "required": [ + "application_link", + "description", + "is_recruiting", + "name", + "preview", + "recruitment_cycle", + "recruitment_type", + "user_id" + ], + "properties": { + "application_link": { + "type": "string", + "maxLength": 255 + }, + "description": { + "description": "MongoDB URL", + "type": "string", + "maxLength": 255 + }, + "is_recruiting": { + "type": "boolean" + }, + "logo": { + "description": "S3 URL", + "type": "string", + "maxLength": 255 + }, + "name": { + "type": "string", + "maxLength": 255 + }, + "preview": { + "type": "string", + "maxLength": 255 + }, + "recruitment_cycle": { + "maxLength": 255, + "enum": [ + "fall", + "spring", + "fallSpring", + "always" + ], + "allOf": [ + { + "$ref": "#/definitions/models.RecruitmentCycle" + } + ] + }, + "recruitment_type": { + "maxLength": 255, + "enum": [ + "unrestricted", + "tryout", + "application" + ], + "allOf": [ + { + "$ref": "#/definitions/models.RecruitmentType" + } + ] + }, + "user_id": { + "type": "string" + } + } + }, + "models.CreateClubTagsRequestBody": { + "type": "object", + "required": [ + "tags" + ], + "properties": { + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "models.CreateEventRequestBody": { + "type": "object", + "required": [ + "content", + "end_time", + "event_type", + "is_recurring", + "location", + "name", + "preview", + "start_time" + ], + "properties": { + "content": { + "type": "string", + "maxLength": 255 + }, + "end_time": { + "type": "string" + }, + "event_type": { + "maxLength": 255, + "allOf": [ + { + "$ref": "#/definitions/models.EventType" + } + ] + }, + "is_recurring": { + "type": "boolean" + }, + "location": { + "type": "string", + "maxLength": 255 + }, + "name": { + "type": "string", + "maxLength": 255 + }, + "preview": { + "type": "string", + "maxLength": 255 + }, + "series": { + "description": "TODO validate if isRecurring, then series is required", + "allOf": [ + { + "$ref": "#/definitions/models.CreateSeriesRequestBody" + } + ] + }, + "start_time": { + "type": "string" + } + } + }, + "models.CreateSeriesRequestBody": { + "type": "object", + "properties": { + "day_of_month": { + "type": "integer", + "maximum": 31, + "minimum": 1 + }, + "day_of_week": { + "type": "integer", + "maximum": 7, + "minimum": 1 + }, + "max_occurrences": { + "type": "integer", + "minimum": 2 + }, + "recurring_type": { + "maxLength": 255, + "allOf": [ + { + "$ref": "#/definitions/models.RecurringType" + } + ] + }, + "separation_count": { + "type": "integer", + "minimum": 0 + }, + "week_of_month": { + "type": "integer", + "maximum": 5, + "minimum": 1 + } + } + }, + "models.CreateUserRequestBody": { + "type": "object", + "required": [ + "college", + "email", + "first_name", + "last_name", + "nuid", + "password", + "year" + ], + "properties": { + "college": { + "enum": [ + "CAMD", + "DMSB", + "KCCS", + "CE", + "BCHS", + "SL", + "CPS", + "CS", + "CSSH" + ], + "allOf": [ + { + "$ref": "#/definitions/models.College" + } + ] + }, + "email": { + "type": "string", + "maxLength": 255 + }, + "first_name": { + "type": "string", + "maxLength": 255 + }, + "last_name": { + "type": "string", + "maxLength": 255 + }, + "nuid": { + "type": "string" + }, + "password": { + "type": "string" + }, + "year": { + "maximum": 6, + "minimum": 1, + "allOf": [ + { + "$ref": "#/definitions/models.Year" + } + ] + } + } + }, + "models.CreateUserTagsBody": { + "type": "object", + "required": [ + "tags" + ], + "properties": { + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "models.Event": { + "type": "object", + "required": [ + "content", + "end_time", + "event_type", + "location", + "name", + "preview", + "start_time" + ], + "properties": { + "content": { + "type": "string", + "maxLength": 255 + }, + "created_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + }, + "end_time": { + "type": "string" + }, + "event_type": { + "maxLength": 255, + "allOf": [ + { + "$ref": "#/definitions/models.EventType" + } + ] + }, + "id": { + "type": "string", "example": "123e4567-e89b-12d3-a456-426614174000" }, + "is_recurring": { + "type": "boolean" + }, + "location": { + "type": "string", + "maxLength": 255 + }, "name": { "type": "string", "maxLength": 255 }, + "preview": { + "type": "string", + "maxLength": 255 + }, + "start_time": { + "type": "string" + }, "updated_at": { "type": "string", "example": "2023-09-20T16:34:50Z" } } }, - "models.College": { + "models.EventType": { "type": "string", "enum": [ - "CAMD", - "DMSB", - "KCCS", - "CE", - "BCHS", - "SL", - "CPS", - "CS", - "CSSH" + "open", + "membersOnly" ], - "x-enum-comments": { - "BCHS": "Bouvé College of Health Sciences", - "CAMD": "College of Arts, Media and Design", - "CE": "College of Engineering", - "CPS": "College of Professional Studies", - "CS": "College of Science", - "CSSH": "College of Social Sciences and Humanities", - "DMSB": "D'Amore-McKim School of Business", - "KCCS": "Khoury College of Computer Sciences", - "SL": "School of Law" - }, "x-enum-varnames": [ - "CAMD", - "DMSB", - "KCCS", - "CE", - "BCHS", - "SL", - "CPS", - "CS", - "CSSH" + "Open", + "MembersOnly" + ] + }, + "models.LoginUserResponseBody": { + "type": "object", + "required": [ + "email" + ], + "properties": { + "email": { + "type": "string" + }, + "password": { + "type": "string", + "maxLength": 255, + "minLength": 8 + } + } + }, + "models.PutContactRequestBody": { + "type": "object", + "required": [ + "content", + "type" + ], + "properties": { + "content": { + "type": "string", + "maxLength": 255 + }, + "type": { + "maxLength": 255, + "enum": [ + "facebook", + "instagram", + "twitter", + "linkedin", + "youtube", + "github", + "slack", + "discord", + "email", + "customSite" + ], + "allOf": [ + { + "$ref": "#/definitions/models.ContactType" + } + ] + } + } + }, + "models.RecruitmentCycle": { + "type": "string", + "enum": [ + "fall", + "spring", + "fallSpring", + "always" + ], + "x-enum-varnames": [ + "Fall", + "Spring", + "FallSpring", + "Always" ] }, + "models.RecruitmentType": { + "type": "string", + "enum": [ + "unrestricted", + "tryout", + "application" + ], + "x-enum-varnames": [ + "Unrestricted", + "Tryout", + "Application" + ] + }, + "models.RecurringType": { + "type": "string", + "enum": [ + "daily", + "weekly", + "monthly" + ], + "x-enum-varnames": [ + "Daily", + "Weekly", + "Monthly" + ] + }, + "models.Series": { + "type": "object", + "properties": { + "created_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + }, + "day_of_month": { + "type": "integer", + "maximum": 31, + "minimum": 1 + }, + "day_of_week": { + "type": "integer", + "maximum": 7, + "minimum": 1 + }, + "events": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Event" + } + }, + "id": { + "type": "string", + "example": "123e4567-e89b-12d3-a456-426614174000" + }, + "max_occurrences": { + "type": "integer", + "minimum": 1 + }, + "recurring_type": { + "maxLength": 255, + "allOf": [ + { + "$ref": "#/definitions/models.RecurringType" + } + ] + }, + "separation_count": { + "type": "integer", + "minimum": 0 + }, + "updated_at": { + "type": "string", + "example": "2023-09-20T16:34:50Z" + }, + "week_of_month": { + "type": "integer", + "maximum": 5, + "minimum": 1 + } + } + }, "models.Tag": { "type": "object", "required": [ @@ -808,6 +3708,182 @@ } } }, + "models.TagRequestBody": { + "type": "object", + "required": [ + "category_id", + "name" + ], + "properties": { + "category_id": { + "type": "string" + }, + "name": { + "type": "string", + "maxLength": 255 + } + } + }, + "models.UpdateClubRequestBody": { + "type": "object", + "required": [ + "application_link", + "recruitment_cycle", + "recruitment_type" + ], + "properties": { + "application_link": { + "type": "string", + "maxLength": 255 + }, + "description": { + "description": "MongoDB URL", + "type": "string", + "maxLength": 255 + }, + "is_recruiting": { + "type": "boolean" + }, + "logo": { + "description": "S3 URL", + "type": "string", + "maxLength": 255 + }, + "name": { + "type": "string", + "maxLength": 255 + }, + "preview": { + "type": "string", + "maxLength": 255 + }, + "recruitment_cycle": { + "maxLength": 255, + "enum": [ + "fall", + "spring", + "fallSpring", + "always" + ], + "allOf": [ + { + "$ref": "#/definitions/models.RecruitmentCycle" + } + ] + }, + "recruitment_type": { + "maxLength": 255, + "enum": [ + "unrestricted", + "tryout", + "application" + ], + "allOf": [ + { + "$ref": "#/definitions/models.RecruitmentType" + } + ] + } + } + }, + "models.UpdatePasswordRequestBody": { + "type": "object", + "required": [ + "new_password", + "old_password" + ], + "properties": { + "new_password": { + "type": "string" + }, + "old_password": { + "type": "string" + } + } + }, + "models.UpdateSeriesRequestBody": { + "type": "object", + "properties": { + "day_of_month": { + "type": "integer", + "maximum": 31, + "minimum": 1 + }, + "day_of_week": { + "type": "integer", + "maximum": 7, + "minimum": 1 + }, + "max_occurrences": { + "type": "integer", + "minimum": 2 + }, + "recurring_type": { + "maxLength": 255, + "allOf": [ + { + "$ref": "#/definitions/models.RecurringType" + } + ] + }, + "separation_count": { + "type": "integer", + "minimum": 0 + }, + "week_of_month": { + "type": "integer", + "maximum": 5, + "minimum": 1 + } + } + }, + "models.UpdateUserRequestBody": { + "type": "object", + "properties": { + "college": { + "enum": [ + "CAMD", + "DMSB", + "KCCS", + "CE", + "BCHS", + "SL", + "CPS", + "CS", + "CSSH" + ], + "allOf": [ + { + "$ref": "#/definitions/models.College" + } + ] + }, + "email": { + "type": "string", + "maxLength": 255 + }, + "first_name": { + "type": "string", + "maxLength": 255 + }, + "last_name": { + "type": "string", + "maxLength": 255 + }, + "nuid": { + "type": "string" + }, + "year": { + "maximum": 6, + "minimum": 1, + "allOf": [ + { + "$ref": "#/definitions/models.Year" + } + ] + } + } + }, "models.User": { "type": "object", "required": [ @@ -820,6 +3896,12 @@ "year" ], "properties": { + "clubs_followed": { + "type": "array", + "items": { + "$ref": "#/definitions/models.Club" + } + }, "college": { "maxLength": 255, "allOf": [ @@ -852,14 +3934,10 @@ "type": "string" }, "role": { + "type": "string", "enum": [ "super", "student" - ], - "allOf": [ - { - "$ref": "#/definitions/models.UserRole" - } ] }, "updated_at": { @@ -877,17 +3955,6 @@ } } }, - "models.UserRole": { - "type": "string", - "enum": [ - "super", - "student" - ], - "x-enum-varnames": [ - "Super", - "Student" - ] - }, "models.Year": { "type": "integer", "enum": [ @@ -906,6 +3973,14 @@ "Fifth", "Graduate" ] + }, + "utilities.SuccessResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } } } } \ No newline at end of file diff --git a/backend/src/docs/swagger.yaml b/backend/src/docs/swagger.yaml index b409375dd..27aa97ecd 100644 --- a/backend/src/docs/swagger.yaml +++ b/backend/src/docs/swagger.yaml @@ -1,5 +1,12 @@ basePath: /api/v1 definitions: + errors.Error: + properties: + message: + type: string + statusCode: + type: integer + type: object models.Category: properties: created_at: @@ -17,6 +24,78 @@ definitions: required: - name type: object + models.CategoryRequestBody: + properties: + name: + maxLength: 255 + type: string + required: + - name + type: object + models.Club: + properties: + application_link: + maxLength: 255 + type: string + created_at: + example: "2023-09-20T16:34:50Z" + type: string + description: + description: MongoDB URL + maxLength: 255 + type: string + id: + example: 123e4567-e89b-12d3-a456-426614174000 + type: string + is_recruiting: + type: boolean + logo: + description: S3 URL + maxLength: 255 + type: string + name: + maxLength: 255 + type: string + num_members: + minimum: 1 + type: integer + preview: + maxLength: 255 + type: string + recruitment_cycle: + allOf: + - $ref: '#/definitions/models.RecruitmentCycle' + enum: + - fall + - spring + - fallSpring + - always + maxLength: 255 + recruitment_type: + allOf: + - $ref: '#/definitions/models.RecruitmentType' + enum: + - unrestricted + - tryout + - application + maxLength: 255 + tags: + items: + $ref: '#/definitions/models.Tag' + type: array + updated_at: + example: "2023-09-20T16:34:50Z" + type: string + required: + - application_link + - description + - is_recruiting + - name + - num_members + - preview + - recruitment_cycle + - recruitment_type + type: object models.College: enum: - CAMD @@ -49,9 +128,10 @@ definitions: - CPS - CS - CSSH - models.Tag: + models.Contact: properties: - category_id: + content: + maxLength: 255 type: string created_at: example: "2023-09-20T16:34:50Z" @@ -59,47 +139,201 @@ definitions: id: example: 123e4567-e89b-12d3-a456-426614174000 type: string - name: + type: + allOf: + - $ref: '#/definitions/models.ContactType' + enum: + - facebook + - instagram + - twitter + - linkedin + - youtube + - github + - slack + - discord + - email + - customSite maxLength: 255 - type: string updated_at: example: "2023-09-20T16:34:50Z" type: string required: - - category_id + - content + - type + type: object + models.ContactType: + enum: + - facebook + - instagram + - twitter + - linkedin + - youtube + - github + - slack + - discord + - email + - customSite + type: string + x-enum-varnames: + - Facebook + - Instagram + - Twitter + - LinkedIn + - YouTube + - GitHub + - Slack + - Discord + - Email + - CustomSite + models.CreateClubRequestBody: + properties: + application_link: + maxLength: 255 + type: string + description: + description: MongoDB URL + maxLength: 255 + type: string + is_recruiting: + type: boolean + logo: + description: S3 URL + maxLength: 255 + type: string + name: + maxLength: 255 + type: string + preview: + maxLength: 255 + type: string + recruitment_cycle: + allOf: + - $ref: '#/definitions/models.RecruitmentCycle' + enum: + - fall + - spring + - fallSpring + - always + maxLength: 255 + recruitment_type: + allOf: + - $ref: '#/definitions/models.RecruitmentType' + enum: + - unrestricted + - tryout + - application + maxLength: 255 + user_id: + type: string + required: + - application_link + - description + - is_recruiting - name + - preview + - recruitment_cycle + - recruitment_type + - user_id type: object - models.User: + models.CreateClubTagsRequestBody: properties: - college: + tags: + items: + type: string + type: array + required: + - tags + type: object + models.CreateEventRequestBody: + properties: + content: + maxLength: 255 + type: string + end_time: + type: string + event_type: allOf: - - $ref: '#/definitions/models.College' + - $ref: '#/definitions/models.EventType' maxLength: 255 - created_at: - example: "2023-09-20T16:34:50Z" + is_recurring: + type: boolean + location: + maxLength: 255 + type: string + name: + maxLength: 255 + type: string + preview: + maxLength: 255 + type: string + series: + allOf: + - $ref: '#/definitions/models.CreateSeriesRequestBody' + description: TODO validate if isRecurring, then series is required + start_time: type: string + required: + - content + - end_time + - event_type + - is_recurring + - location + - name + - preview + - start_time + type: object + models.CreateSeriesRequestBody: + properties: + day_of_month: + maximum: 31 + minimum: 1 + type: integer + day_of_week: + maximum: 7 + minimum: 1 + type: integer + max_occurrences: + minimum: 2 + type: integer + recurring_type: + allOf: + - $ref: '#/definitions/models.RecurringType' + maxLength: 255 + separation_count: + minimum: 0 + type: integer + week_of_month: + maximum: 5 + minimum: 1 + type: integer + type: object + models.CreateUserRequestBody: + properties: + college: + allOf: + - $ref: '#/definitions/models.College' + enum: + - CAMD + - DMSB + - KCCS + - CE + - BCHS + - SL + - CPS + - CS + - CSSH email: maxLength: 255 type: string first_name: maxLength: 255 type: string - id: - example: 123e4567-e89b-12d3-a456-426614174000 - type: string last_name: maxLength: 255 type: string nuid: type: string - role: - allOf: - - $ref: '#/definitions/models.UserRole' - enum: - - super - - student - updated_at: - example: "2023-09-20T16:34:50Z" + password: type: string year: allOf: @@ -112,137 +346,1571 @@ definitions: - first_name - last_name - nuid - - role + - password - year type: object - models.UserRole: + models.CreateUserTagsBody: + properties: + tags: + items: + type: string + type: array + required: + - tags + type: object + models.Event: + properties: + content: + maxLength: 255 + type: string + created_at: + example: "2023-09-20T16:34:50Z" + type: string + end_time: + type: string + event_type: + allOf: + - $ref: '#/definitions/models.EventType' + maxLength: 255 + id: + example: 123e4567-e89b-12d3-a456-426614174000 + type: string + is_recurring: + type: boolean + location: + maxLength: 255 + type: string + name: + maxLength: 255 + type: string + preview: + maxLength: 255 + type: string + start_time: + type: string + updated_at: + example: "2023-09-20T16:34:50Z" + type: string + required: + - content + - end_time + - event_type + - location + - name + - preview + - start_time + type: object + models.EventType: enum: - - super - - student + - open + - membersOnly type: string x-enum-varnames: - - Super - - Student - models.Year: + - Open + - MembersOnly + models.LoginUserResponseBody: + properties: + email: + type: string + password: + maxLength: 255 + minLength: 8 + type: string + required: + - email + type: object + models.PutContactRequestBody: + properties: + content: + maxLength: 255 + type: string + type: + allOf: + - $ref: '#/definitions/models.ContactType' + enum: + - facebook + - instagram + - twitter + - linkedin + - youtube + - github + - slack + - discord + - email + - customSite + maxLength: 255 + required: + - content + - type + type: object + models.RecruitmentCycle: enum: - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - type: integer + - fall + - spring + - fallSpring + - always + type: string x-enum-varnames: - - First - - Second - - Third - - Fourth - - Fifth - - Graduate -host: 127.0.0.1:8080 -info: - contact: - email: generatesac@gmail.com - name: David Oduneye and Garrett Ladley - description: Backend Server for SAC App - title: SAC API - version: "1.0" -paths: - /api/v1/auth/login: - post: - consumes: - - application/json - description: Logs in a user - operationId: login-user - parameters: - - description: User Body - in: body - name: userBody - required: true - schema: - items: - type: string - type: array - produces: - - application/json - responses: - "200": - description: success - schema: - type: string - "400": - description: failed to parse body - schema: - type: string - "401": - description: failed to login user - schema: - type: string - summary: Logs in a user - tags: - - user - /api/v1/auth/logout: - get: - consumes: - - application/json - description: Logs out a user - operationId: logout-user - produces: - - application/json - responses: - "200": - description: OK - schema: - type: string - "401": - description: failed to logout user - schema: - type: string - summary: Logs out a user - tags: - - user - /api/v1/auth/me: - get: - description: Returns the current user - operationId: get-current-user - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/models.User' - "401": - description: failed to get current user - schema: - type: string - summary: Gets the current user - tags: - - user - /api/v1/auth/refresh: + - Fall + - Spring + - FallSpring + - Always + models.RecruitmentType: + enum: + - unrestricted + - tryout + - application + type: string + x-enum-varnames: + - Unrestricted + - Tryout + - Application + models.RecurringType: + enum: + - daily + - weekly + - monthly + type: string + x-enum-varnames: + - Daily + - Weekly + - Monthly + models.Series: + properties: + created_at: + example: "2023-09-20T16:34:50Z" + type: string + day_of_month: + maximum: 31 + minimum: 1 + type: integer + day_of_week: + maximum: 7 + minimum: 1 + type: integer + events: + items: + $ref: '#/definitions/models.Event' + type: array + id: + example: 123e4567-e89b-12d3-a456-426614174000 + type: string + max_occurrences: + minimum: 1 + type: integer + recurring_type: + allOf: + - $ref: '#/definitions/models.RecurringType' + maxLength: 255 + separation_count: + minimum: 0 + type: integer + updated_at: + example: "2023-09-20T16:34:50Z" + type: string + week_of_month: + maximum: 5 + minimum: 1 + type: integer + type: object + models.Tag: + properties: + category_id: + type: string + created_at: + example: "2023-09-20T16:34:50Z" + type: string + id: + example: 123e4567-e89b-12d3-a456-426614174000 + type: string + name: + maxLength: 255 + type: string + updated_at: + example: "2023-09-20T16:34:50Z" + type: string + required: + - category_id + - name + type: object + models.TagRequestBody: + properties: + category_id: + type: string + name: + maxLength: 255 + type: string + required: + - category_id + - name + type: object + models.UpdateClubRequestBody: + properties: + application_link: + maxLength: 255 + type: string + description: + description: MongoDB URL + maxLength: 255 + type: string + is_recruiting: + type: boolean + logo: + description: S3 URL + maxLength: 255 + type: string + name: + maxLength: 255 + type: string + preview: + maxLength: 255 + type: string + recruitment_cycle: + allOf: + - $ref: '#/definitions/models.RecruitmentCycle' + enum: + - fall + - spring + - fallSpring + - always + maxLength: 255 + recruitment_type: + allOf: + - $ref: '#/definitions/models.RecruitmentType' + enum: + - unrestricted + - tryout + - application + maxLength: 255 + required: + - application_link + - recruitment_cycle + - recruitment_type + type: object + models.UpdatePasswordRequestBody: + properties: + new_password: + type: string + old_password: + type: string + required: + - new_password + - old_password + type: object + models.UpdateSeriesRequestBody: + properties: + day_of_month: + maximum: 31 + minimum: 1 + type: integer + day_of_week: + maximum: 7 + minimum: 1 + type: integer + max_occurrences: + minimum: 2 + type: integer + recurring_type: + allOf: + - $ref: '#/definitions/models.RecurringType' + maxLength: 255 + separation_count: + minimum: 0 + type: integer + week_of_month: + maximum: 5 + minimum: 1 + type: integer + type: object + models.UpdateUserRequestBody: + properties: + college: + allOf: + - $ref: '#/definitions/models.College' + enum: + - CAMD + - DMSB + - KCCS + - CE + - BCHS + - SL + - CPS + - CS + - CSSH + email: + maxLength: 255 + type: string + first_name: + maxLength: 255 + type: string + last_name: + maxLength: 255 + type: string + nuid: + type: string + year: + allOf: + - $ref: '#/definitions/models.Year' + maximum: 6 + minimum: 1 + type: object + models.User: + properties: + clubs_followed: + items: + $ref: '#/definitions/models.Club' + type: array + college: + allOf: + - $ref: '#/definitions/models.College' + maxLength: 255 + created_at: + example: "2023-09-20T16:34:50Z" + type: string + email: + maxLength: 255 + type: string + first_name: + maxLength: 255 + type: string + id: + example: 123e4567-e89b-12d3-a456-426614174000 + type: string + last_name: + maxLength: 255 + type: string + nuid: + type: string + role: + enum: + - super + - student + type: string + updated_at: + example: "2023-09-20T16:34:50Z" + type: string + year: + allOf: + - $ref: '#/definitions/models.Year' + maximum: 6 + minimum: 1 + required: + - college + - email + - first_name + - last_name + - nuid + - role + - year + type: object + models.Year: + enum: + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + type: integer + x-enum-varnames: + - First + - Second + - Third + - Fourth + - Fifth + - Graduate + utilities.SuccessResponse: + properties: + message: + type: string + type: object +host: 127.0.0.1:8080 +info: + contact: + email: generatesac@gmail.com + name: David Oduneye and Garrett Ladley + description: Backend Server for SAC App + title: SAC API + version: "1.0" +paths: + /auth/login: + post: + consumes: + - application/json + description: Logs in a user + operationId: login-user + parameters: + - description: Login Body + in: body + name: loginBody + required: true + schema: + $ref: '#/definitions/models.LoginUserResponseBody' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/utilities.SuccessResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Logs in a user + tags: + - auth + /auth/logout: + get: + consumes: + - application/json + description: Logs out a user + operationId: logout-user + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/utilities.SuccessResponse' + summary: Logs out a user + tags: + - auth + /auth/me: + get: + description: Returns the current user associated with an auth session + operationId: get-current-user + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/models.User' + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Retrieve the current user given an auth session + tags: + - auth + /auth/refresh: + get: + consumes: + - application/json + description: Refreshes a user's access token + operationId: refresh-user + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/utilities.SuccessResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Refreshes a user's access token + tags: + - auth + /auth/update-password: + post: + consumes: + - application/json + description: Updates a user's password + operationId: update-password + parameters: + - description: User Body + in: body + name: userBody + required: true + schema: + $ref: '#/definitions/models.UpdatePasswordRequestBody' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/utilities.SuccessResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Updates a user's password + tags: + - auth + /category/: + get: + description: Retrieves all categories + operationId: get-categories + parameters: + - description: Limit + in: query + name: limit + type: integer + - description: Page + in: query + name: page + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/models.Category' + type: array + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + summary: Retrieve all categories + tags: + - category + post: + consumes: + - application/json + description: Creates a category + operationId: create-category + parameters: + - description: Category Body + in: body + name: categoryBody + required: true + schema: + $ref: '#/definitions/models.CategoryRequestBody' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/models.Category' + "400": + description: Bad Request + schema: + type: string + "401": + description: Unauthorized + schema: + type: string + "404": + description: Not Found + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + summary: Creates a category + tags: + - category + /category/{categoryID}: + delete: + description: Deletes a category + operationId: delete-category + parameters: + - description: Category ID + in: path + name: categoryID + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + schema: + type: string + "400": + description: Bad Request + schema: + type: string + "401": + description: Unauthorized + schema: + type: string + "404": + description: Not Found + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + summary: Deletes a category + tags: + - category + get: + description: Retrieves a category + operationId: get-category + parameters: + - description: Category ID + in: path + name: categoryID + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/models.Category' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + summary: Retrieve a category + tags: + - category + put: + consumes: + - application/json + description: Updates a category + operationId: update-category + parameters: + - description: Category ID + in: path + name: categoryID + required: true + type: string + - description: Category Body + in: body + name: categoryBody + required: true + schema: + $ref: '#/definitions/models.CategoryRequestBody' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/models.Category' + "400": + description: Bad Request + schema: + type: string + "401": + description: Unauthorized + schema: + type: string + "404": + description: Not Found + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + summary: Updates a category + tags: + - category + /category/{categoryID}/tags: + get: + description: Retrieves all tags associated with a category + operationId: get-tags-by-category + parameters: + - description: Category ID + in: path + name: categoryID + required: true + type: string + - description: Limit + in: query + name: limit + type: integer + - description: Page + in: query + name: page + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/models.Tag' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Retrieve all tags by category + tags: + - category-tag + /category/{categoryID}/tags/{tagID}: + get: + description: Retrieves a tag associated with a category + operationId: get-tag-by-category + parameters: + - description: Category ID + in: path + name: categoryID + required: true + type: string + - description: Tag ID + in: path + name: tagID + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/models.Tag' + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Retrieve a tag by category + tags: + - category-tag + /club/: + get: + description: Retrieves all clubs + operationId: get-all-clubs + parameters: + - description: Limit + in: query + name: limit + type: integer + - description: Page + in: query + name: page + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/models.Club' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Retrieve all clubs + tags: + - club + post: + consumes: + - application/json + description: Creates a club + operationId: create-club + parameters: + - description: Club + in: body + name: club + required: true + schema: + $ref: '#/definitions/models.CreateClubRequestBody' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/models.Club' + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Create a club + tags: + - club + /club/{clubID}: + delete: + description: Deletes a club + operationId: delete-club + parameters: + - description: Club ID + in: path + name: clubID + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + schema: + type: string + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Delete a club + tags: + - club + get: + description: Retrieves a club + operationId: get-club + parameters: + - description: Club ID + in: path + name: clubID + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/models.Club' + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Retrieve a club + tags: + - club + put: + consumes: + - application/json + description: Updates a club + operationId: update-club + parameters: + - description: Club ID + in: path + name: clubID + required: true + type: string + - description: Club + in: body + name: club + required: true + schema: + $ref: '#/definitions/models.UpdateClubRequestBody' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/models.Club' + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Update a club + tags: + - club + /club/{clubID}/contacts: + get: + description: Retrieves all contacts associated with a club + operationId: get-contacts-by-club + parameters: + - description: Club ID + in: path + name: clubID + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/models.Contact' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Retrieve all contacts for a club + tags: + - club-contact + post: + consumes: + - application/json + description: Creates a contact + operationId: create-contact + parameters: + - description: Club ID + in: path + name: clubID + required: true + type: string + - description: Contact Body + in: body + name: contactBody + required: true + schema: + $ref: '#/definitions/models.PutContactRequestBody' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/models.Contact' + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Creates a contact + tags: + - club-contact + /club/{clubID}/events: + get: + description: Retrieves all events associated with a club + operationId: get-events-by-club + parameters: + - description: Club ID + in: path + name: clubID + required: true + type: string + - description: Limit + in: query + name: limit + type: integer + - description: Page + in: query + name: page + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/models.Event' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Retrieve all events for a club + tags: + - club-event + /club/{clubID}/followers: + get: + description: Retrieves all followers associated with a club + operationId: get-followers-by-club + parameters: + - description: Club ID + in: path + name: clubID + required: true + type: string + - description: Limit + in: query + name: limit + type: integer + - description: Page + in: query + name: page + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/models.User' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Retrieve all followers for a club + tags: + - club-follower + /club/{clubID}/members: + get: + description: Retrieves all members associated with a club + operationId: get-members-by-club + parameters: + - description: Club ID + in: path + name: clubID + required: true + type: string + - description: Limit + in: query + name: limit + type: integer + - description: Page + in: query + name: page + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/models.User' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Retrieve all members for a club + tags: + - club-member + /club/{clubID}/tags: + get: + description: Retrieves all tags associated with a club + operationId: get-tags-by-club + parameters: + - description: Club ID + in: path + name: clubID + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/models.Tag' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Retrieve all tags for a club + tags: + - club-tag + post: + consumes: + - application/json + description: Creates tags for a club + operationId: create-club-tags + parameters: + - description: Club ID + in: path + name: clubID + required: true + type: string + - description: Club Tags Body + in: body + name: clubTagsBody + required: true + schema: + $ref: '#/definitions/models.CreateClubTagsRequestBody' + produces: + - application/json + responses: + "201": + description: Created + schema: + items: + $ref: '#/definitions/models.Tag' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Create club tags + tags: + - club-tag + /club/{clubID}/tags/{tagID}: + delete: + description: Deletes a tag associated with a club + operationId: delete-tag-by-club + parameters: + - description: Club ID + in: path + name: clubID + required: true + type: string + - description: Tag ID + in: path + name: tagID + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + schema: + type: string + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Delete a tag for a club + tags: + - club-tag + /contact/: get: + description: Retrieves all contacts + operationId: get-contacts + parameters: + - description: Limit + in: query + name: limit + type: integer + - description: Page + in: query + name: page + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/models.Contact' + type: array + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + summary: Retrieve all contacts + tags: + - contact + post: consumes: - application/json - description: Refreshes a user's access token - operationId: refresh-user + description: Creates a contact + operationId: create-contact + parameters: + - description: Contact Body + in: body + name: contactBody + required: true + schema: + $ref: '#/definitions/models.Contact' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/models.Contact' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + summary: Creates a contact + tags: + - contact + /event/: + get: + description: Retrieves all events + operationId: get-all-events + parameters: + - description: Limit + in: query + name: limit + type: integer + - description: Page + in: query + name: page + type: integer produces: - application/json responses: "200": - description: success + description: OK + schema: + items: + $ref: '#/definitions/models.Event' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Retrieve all events + tags: + - event + post: + consumes: + - application/json + description: Creates an event + operationId: create-event + parameters: + - description: Event Body + in: body + name: event + required: true + schema: + $ref: '#/definitions/models.CreateEventRequestBody' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/models.Event' + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Create an event + tags: + - event + /event/{eventID}: + delete: + description: Deletes an event + operationId: delete-event + parameters: + - description: Event ID + in: path + name: eventID + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content schema: type: string + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' "401": - description: failed to refresh access token + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Delete an event + tags: + - event + get: + description: Retrieves an event + operationId: get-event + parameters: + - description: Event ID + in: path + name: eventID + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/models.Event' + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Retrieve an event + tags: + - event + /event/{eventID}/series: + delete: + description: Deletes all series associated with an event + operationId: delete-series-by-event + parameters: + - description: Event ID + in: path + name: eventID + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content schema: type: string - summary: Refreshes a user's access token + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Delete all series by event tags: - - user - /api/v1/category/: + - event get: - description: Retrieves all existing categories - operationId: get-categories + description: Retrieves all series associated with an event + operationId: get-series-by-event + parameters: + - description: Event ID + in: path + name: eventID + required: true + type: string produces: - application/json responses: @@ -250,75 +1918,266 @@ paths: description: OK schema: items: - $ref: '#/definitions/models.Category' + $ref: '#/definitions/models.Series' type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' "500": - description: unable to retrieve categories + description: Internal Server Error schema: - type: string - summary: Retrieve all categories + $ref: '#/definitions/errors.Error' + summary: Retrieve all series by event tags: - - category + - event post: - description: Creates a category that is used to group tags - operationId: create-category + consumes: + - application/json + description: Creates a series + operationId: create-series + parameters: + - description: Event ID + in: path + name: eventID + required: true + type: string + - description: Series Body + in: body + name: seriesBody + required: true + schema: + $ref: '#/definitions/models.CreateSeriesRequestBody' produces: - application/json responses: "201": description: Created schema: - $ref: '#/definitions/models.Category' + $ref: '#/definitions/models.Series' "400": - description: category with that name already exists + description: Bad Request schema: - type: string + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Create a series + tags: + - event + /event/{eventID}/series/{seriesID}: + put: + consumes: + - application/json + description: Updates a series by ID + operationId: update-series-by-id + parameters: + - description: Event ID + in: path + name: eventID + required: true + type: string + - description: Series ID + in: path + name: seriesID + required: true + type: string + - description: Series Body + in: body + name: seriesBody + required: true + schema: + $ref: '#/definitions/models.UpdateSeriesRequestBody' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/models.Series' + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' "500": - description: failed to create category + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Update a series by ID + tags: + - event + /series/{seriesID}: + delete: + description: Deletes a series by ID + operationId: delete-series-by-id + parameters: + - description: Series ID + in: path + name: seriesID + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content schema: type: string - summary: Create a category + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Delete a series by ID tags: - - category - /api/v1/category/{id}: + - event + get: + description: Retrieves a series by ID + operationId: get-series-by-id + parameters: + - description: Series ID + in: path + name: seriesID + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/models.Series' + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Retrieve a series by ID + tags: + - event + /tags: + get: + description: Retrieves all tags + operationId: get-all-tags + parameters: + - description: Limit + in: query + name: limit + type: integer + - description: Page + in: query + name: page + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/models.Tag' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Retrieve all tags + tags: + - tag + /tags/{tagID}: delete: - description: Delete a category by ID - operationId: delete-category + description: Deletes a tag + operationId: delete-tag parameters: - - description: Category ID + - description: Tag ID in: path - name: id + name: tagID required: true type: string produces: - application/json responses: "204": - description: no content + description: No Content schema: type: string "400": - description: failed to validate id + description: Bad Request schema: - type: string + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' "404": - description: failed to find category + description: Not Found schema: - type: string + $ref: '#/definitions/errors.Error' "500": - description: failed to delete category + description: Internal Server Error schema: - type: string - summary: Delete a category + $ref: '#/definitions/errors.Error' + summary: Delete a tag tags: - - category + - tag get: - description: Retrieve a category by its ID - operationId: get-category + description: Retrieves a tag + operationId: get-tag parameters: - - description: Category ID + - description: Tag ID in: path - name: id + name: tagID required: true type: string produces: @@ -327,175 +2186,228 @@ paths: "200": description: OK schema: - $ref: '#/definitions/models.Category' + $ref: '#/definitions/models.Tag' "400": - description: failed to validate id + description: Bad Request schema: - type: string + $ref: '#/definitions/errors.Error' "404": - description: faied to find category + description: Not Found schema: - type: string + $ref: '#/definitions/errors.Error' "500": - description: failed to retrieve category + description: Internal Server Error schema: - type: string - summary: Retrieve a category + $ref: '#/definitions/errors.Error' + summary: Retrieve a tag tags: - - category - patch: - description: Updates a category - operationId: update-category + - tag + put: + consumes: + - application/json + description: Updates a tag + operationId: update-tag parameters: - - description: Category ID + - description: Tag ID in: path - name: id + name: tagID required: true type: string + - description: Tag + in: body + name: tag + required: true + schema: + $ref: '#/definitions/models.TagRequestBody' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/models.Category' + $ref: '#/definitions/models.Tag' "400": - description: failed to validate id + description: Bad Request schema: - type: string + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' "404": - description: failed to find category + description: Not Found schema: - type: string + $ref: '#/definitions/errors.Error' "500": - description: failed to update category + description: Internal Server Error schema: - type: string - summary: Updates a category + $ref: '#/definitions/errors.Error' + summary: Update a tag tags: - - category - /api/v1/tags/: + - tag + /user/: post: consumes: - application/json - description: Creates a tag - operationId: create-tag + description: Creates a user + operationId: create-user + parameters: + - description: User Body + in: body + name: userBody + required: true + schema: + $ref: '#/definitions/models.CreateUserRequestBody' produces: - application/json responses: "201": description: Created schema: - $ref: '#/definitions/models.Tag' + $ref: '#/definitions/models.User' "400": - description: failed to validate the data + description: Bad Request schema: - type: string + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' "500": - description: failed to create tag + description: Internal Server Error schema: - type: string - summary: Creates a tag + $ref: '#/definitions/errors.Error' + summary: Create a user tags: - - tag - /api/v1/tags/{id}: + - user + /user/{userID}: delete: - description: Deletes a tag - operationId: delete-tag + description: Deletes a user + operationId: delete-user parameters: - - description: Tag ID + - description: User ID in: path - name: id + name: userID required: true - type: integer + type: string + produces: + - application/json responses: "204": - description: no content + description: No Content schema: type: string "400": - description: failed to validate id + description: Bad Request schema: - type: string + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' "404": - description: tag not found + description: Not Found schema: - type: string + $ref: '#/definitions/errors.Error' "500": - description: failed to delete tag + description: Internal Server Error schema: - type: string - summary: Deletes a tag + $ref: '#/definitions/errors.Error' + summary: Delete a user tags: - - tag + - user get: - description: Returns a tag - operationId: get-tag + description: Retrieves a user + operationId: get-user parameters: - - description: Tag ID + - description: User ID in: path - name: id + name: userID required: true - type: integer + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/models.Tag' + $ref: '#/definitions/models.User' "400": - description: failed to validate id + description: Bad Request schema: - type: string + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' "404": - description: faied to find tag + description: Not Found schema: - type: string + $ref: '#/definitions/errors.Error' "500": - description: failed to retrieve tag + description: Internal Server Error schema: - type: string - summary: Gets a tag + $ref: '#/definitions/errors.Error' + summary: Retrieve a user tags: - - tag - patch: + - user + put: consumes: - application/json - description: Updates a tag - operationId: update-tag + description: Updates a user + operationId: update-user parameters: - - description: Tag ID + - description: User ID in: path - name: id + name: userID required: true - type: integer + type: string + - description: User Body + in: body + name: userBody + required: true + schema: + $ref: '#/definitions/models.UpdateUserRequestBody' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/models.Tag' + $ref: '#/definitions/models.User' "400": - description: failed to validate the data + description: Bad Request schema: - type: string + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' "404": - description: failed to find tag + description: Not Found schema: - type: string + $ref: '#/definitions/errors.Error' "500": - description: failed to update tag + description: Internal Server Error schema: - type: string - summary: Updates a tag + $ref: '#/definitions/errors.Error' + summary: Update a user tags: - - tag - /api/v1/users/: + - user + /user/{userID}/following: get: - description: Returns all users - operationId: get-all-users + description: Retrieves all clubs a user is following + operationId: get-following + parameters: + - description: User ID + in: path + name: userID + required: true + type: string produces: - application/json responses: @@ -503,69 +2415,227 @@ paths: description: OK schema: items: - $ref: '#/definitions/models.User' + $ref: '#/definitions/models.Club' type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' "500": - description: failed to get all users + description: Internal Server Error schema: - type: string - summary: Gets all users + $ref: '#/definitions/errors.Error' + summary: Retrieve all clubs a user is following tags: - - user + - user-follower + /user/{userID}/following/{clubID}: + delete: + consumes: + - application/json + description: Unfollow a club + operationId: delete-following + parameters: + - description: User ID + in: path + name: userID + required: true + type: string + - description: Club ID + in: path + name: clubID + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + schema: + $ref: '#/definitions/utilities.SuccessResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Unfollow a club + tags: + - user-follower post: consumes: - application/json - description: Creates a user - operationId: create-user + description: Follow a club + operationId: create-following + parameters: + - description: User ID + in: path + name: userID + required: true + type: string + - description: Club ID + in: path + name: clubID + required: true + type: string produces: - application/json responses: "201": description: Created schema: - $ref: '#/definitions/models.User' + $ref: '#/definitions/utilities.SuccessResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Follow a club + tags: + - user-follower + /user/{userID}/membership: + get: + description: Retrieves all clubs a user is a member of + operationId: get-membership + parameters: + - description: User ID + in: path + name: userID + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/models.Club' + type: array "400": - description: failed to create user + description: Bad Request schema: - type: string + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' "500": - description: internal server error + description: Internal Server Error schema: - type: string - summary: Creates a User + $ref: '#/definitions/errors.Error' + summary: Retrieve all clubs a user is a member of tags: - - user - /api/v1/users/{id}: + - user-member + /user/{userID}/membership/{clubID}: delete: - description: Returns nil - operationId: delete-user + consumes: + - application/json + description: Leave a club + operationId: delete-membership parameters: - description: User ID in: path - name: id + name: userID + required: true + type: string + - description: Club ID + in: path + name: clubID required: true type: string produces: - application/json responses: "204": - description: no content + description: No Content schema: - type: string + $ref: '#/definitions/utilities.SuccessResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' "500": - description: failed to get all users + description: Internal Server Error schema: - type: string - summary: Deletes the given userID + $ref: '#/definitions/errors.Error' + summary: Leave a club tags: - - user + - user-member + post: + consumes: + - application/json + description: Join a club + operationId: create-membership + parameters: + - description: User ID + in: path + name: userID + required: true + type: string + - description: Club ID + in: path + name: clubID + required: true + type: string + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/utilities.SuccessResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' + "404": + description: Not Found + schema: + $ref: '#/definitions/errors.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/errors.Error' + summary: Join a club + tags: + - user-member + /user/{userID}/tags: get: - description: Returns a user - operationId: get-user-by-id + description: Retrieves all tags associated with a user + operationId: get-tags-by-user parameters: - description: User ID in: path - name: id + name: userID required: true type: string produces: @@ -574,51 +2644,71 @@ paths: "200": description: OK schema: - $ref: '#/definitions/models.User' + items: + $ref: '#/definitions/models.Tag' + type: array "400": - description: failed to validate id + description: Bad Request schema: - type: string + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' "404": - description: user not found + description: Not Found schema: - type: string + $ref: '#/definitions/errors.Error' "500": - description: failed to get user + description: Internal Server Error schema: - type: string - summary: Gets a user + $ref: '#/definitions/errors.Error' + summary: Retrieve all tags for a user tags: - - user - patch: - description: Updates a user - operationId: update-user-by-id + - user-tag + post: + consumes: + - application/json + description: Creates tags for a user + operationId: create-user-tags parameters: - description: User ID in: path - name: id + name: userID required: true type: string + - description: User Tags Body + in: body + name: userTagsBody + required: true + schema: + $ref: '#/definitions/models.CreateUserTagsBody' produces: - application/json responses: - "200": - description: OK + "201": + description: Created schema: - $ref: '#/definitions/models.User' + items: + $ref: '#/definitions/models.Tag' + type: array "400": - description: failed to validate id + description: Bad Request schema: - type: string + $ref: '#/definitions/errors.Error' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/errors.Error' "404": - description: user not found + description: Not Found schema: - type: string + $ref: '#/definitions/errors.Error' "500": - description: failed to hash password + description: Internal Server Error schema: - type: string - summary: Updates a user + $ref: '#/definitions/errors.Error' + summary: Create user tags tags: - - user + - user-tag swagger: "2.0" diff --git a/backend/src/main.go b/backend/src/main.go index 0caa30d84..552082ab6 100644 --- a/backend/src/main.go +++ b/backend/src/main.go @@ -7,13 +7,13 @@ import ( "github.com/GenerateNU/sac/backend/src/config" "github.com/GenerateNU/sac/backend/src/database" + _ "github.com/GenerateNU/sac/backend/src/docs" "github.com/GenerateNU/sac/backend/src/server" ) // @title SAC API // @version 1.0 // @description Backend Server for SAC App - // @contact.name David Oduneye and Garrett Ladley // @contact.email generatesac@gmail.com // @host 127.0.0.1:8080 diff --git a/backend/src/services/auth.go b/backend/src/services/auth.go index a78e6bb28..6ced8fbf9 100644 --- a/backend/src/services/auth.go +++ b/backend/src/services/auth.go @@ -37,7 +37,7 @@ func (a *AuthService) Me(id string) (*models.User, *errors.Error) { user, err := transactions.GetUser(a.DB, *idAsUint) if err != nil { - return nil, &errors.UserNotFound + return nil, err } return user, nil @@ -50,15 +50,11 @@ func (a *AuthService) Login(userBody models.LoginUserResponseBody) (*models.User user, err := transactions.GetUserByEmail(a.DB, userBody.Email) if err != nil { - return nil, &errors.UserNotFound + return nil, err } correct, passwordErr := auth.ComparePasswordAndHash(userBody.Password, user.PasswordHash) - if passwordErr != nil { - return nil, &errors.FailedToValidateUser - } - - if !correct { + if passwordErr != nil || !correct { return nil, &errors.FailedToValidateUser } @@ -73,7 +69,7 @@ func (a *AuthService) GetRole(id string) (*models.UserRole, *errors.Error) { user, err := transactions.GetUser(a.DB, *idAsUint) if err != nil { - return nil, &errors.UserNotFound + return nil, err } role := user.Role @@ -94,15 +90,11 @@ func (a *AuthService) UpdatePassword(id string, userBody models.UpdatePasswordRe passwordHash, err := transactions.GetUserPasswordHash(a.DB, *idAsUint) if err != nil { - return &errors.UserNotFound + return err } correct, passwordErr := auth.ComparePasswordAndHash(userBody.OldPassword, passwordHash) - if passwordErr != nil { - return &errors.FailedToValidateUser - } - - if !correct { + if passwordErr != nil || !correct { return &errors.FailedToValidateUser } diff --git a/backend/src/utilities/response.go b/backend/src/utilities/response.go index 790993135..f3b95efda 100644 --- a/backend/src/utilities/response.go +++ b/backend/src/utilities/response.go @@ -2,6 +2,11 @@ package utilities import "github.com/gofiber/fiber/v2" +// For swagger docs: +type SuccessResponse struct { + Message string `json:"message"` +} + func FiberMessage(c *fiber.Ctx, statusCode int, response string) error { return c.Status(statusCode).JSON(fiber.Map{"message": response}) } diff --git a/go.work.sum b/go.work.sum index 40ee2ee9f..899195f9d 100644 --- a/go.work.sum +++ b/go.work.sum @@ -14,6 +14,10 @@ cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB/ cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/GenerateNU/sac/backend v0.0.0-20240208151800-c7c93bbd1bb7/go.mod h1:x3FsVBrEq6k60rGtxaOLg3UJ35BIOh6pyjRdGdte5bo= github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= @@ -30,6 +34,14 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumC github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= +github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= +github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= +github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= +github.com/go-openapi/spec v0.20.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do= +github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw= +github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE= +github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/garrettladley/mattress v0.2.2/go.mod h1:OWKIRc9wC3gtD3Ng/nUuNEiR1TJvRYLmn/KZYw9nl5Q= @@ -91,7 +103,6 @@ github.com/nats-io/nkeys v0.4.6 h1:IzVe95ru2CT6ta874rt9saQRkWfe2nFj1NtvYSLqMzY= github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= @@ -146,6 +157,7 @@ golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -193,6 +205,8 @@ google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9Y google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/postgres v1.5.4 h1:Iyrp9Meh3GmbSuyIAGyjkN+n9K+GHX9b9MqsTL4EJCo= gorm.io/driver/postgres v1.5.4/go.mod h1:Bgo89+h0CRcdA33Y6frlaHHVuTdOf87pmyzwW9C/BH0=