From f07fd1ab7ded6d479156710208543121e32ee2d4 Mon Sep 17 00:00:00 2001 From: fengzhida Date: Fri, 5 May 2023 20:27:33 +0800 Subject: [PATCH] init clean-arch --- .dockerignore | 7 + .gitignore | 21 +++ .idea/.gitignore | 8 ++ .idea/docker-mariadb-clean-arch.iml | 9 ++ .idea/modules.xml | 8 ++ Dockerfile | 30 ++++ Makefile | 12 ++ README.md | 193 ++++++++++++++++++++++++++ assets/CleanArchitecture.jpg | Bin 0 -> 107444 bytes assets/SystemArchitecture.png | Bin 0 -> 34573 bytes cmd/docker-mariadb-clean-arch/main.go | 7 + docker-compose.yml | 36 +++++ go.mod | 29 ++++ go.sum | 108 ++++++++++++++ internal/auth/handler.go | 136 ++++++++++++++++++ internal/auth/middleware.go | 54 +++++++ internal/city/domain.go | 47 +++++++ internal/city/handler.go | 178 ++++++++++++++++++++++++ internal/city/middleware.go | 42 ++++++ internal/city/repository.go | 158 +++++++++++++++++++++ internal/city/service.go | 50 +++++++ internal/infrastructure/fiber.go | 81 +++++++++++ internal/infrastructure/mariadb.go | 23 +++ internal/misc/handler.go | 22 +++ internal/user/domain.go | 30 ++++ internal/user/handler.go | 171 +++++++++++++++++++++++ internal/user/middleware.go | 42 ++++++ internal/user/repository.go | 140 +++++++++++++++++++ internal/user/service.go | 52 +++++++ scripts/e2e-testing.sh | 84 +++++++++++ scripts/migrations.sql | 46 ++++++ 31 files changed, 1824 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/docker-mariadb-clean-arch.iml create mode 100644 .idea/modules.xml create mode 100644 Dockerfile create mode 100644 Makefile create mode 100644 README.md create mode 100644 assets/CleanArchitecture.jpg create mode 100644 assets/SystemArchitecture.png create mode 100644 cmd/docker-mariadb-clean-arch/main.go create mode 100644 docker-compose.yml create mode 100644 go.mod create mode 100644 go.sum create mode 100644 internal/auth/handler.go create mode 100644 internal/auth/middleware.go create mode 100644 internal/city/domain.go create mode 100644 internal/city/handler.go create mode 100644 internal/city/middleware.go create mode 100644 internal/city/repository.go create mode 100644 internal/city/service.go create mode 100644 internal/infrastructure/fiber.go create mode 100644 internal/infrastructure/mariadb.go create mode 100644 internal/misc/handler.go create mode 100644 internal/user/domain.go create mode 100644 internal/user/handler.go create mode 100644 internal/user/middleware.go create mode 100644 internal/user/repository.go create mode 100644 internal/user/service.go create mode 100644 scripts/e2e-testing.sh create mode 100644 scripts/migrations.sql diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..8772780 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +.git +.vscode +assets +.dockerignore +.gitignore +Dockerfile +README.md \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa36b22 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# IDE +.vscode + +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Output from 'e2e-testing.sh' +cookie.txt diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..1c2fda5 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/docker-mariadb-clean-arch.iml b/.idea/docker-mariadb-clean-arch.iml new file mode 100644 index 0000000..338a266 --- /dev/null +++ b/.idea/docker-mariadb-clean-arch.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..4926257 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..eadeb59 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +# Get Go image from DockerHub. +FROM golang:1.16.6 AS api + +# Set working directory. +WORKDIR /compiler + +# Copy dependency locks so we can cache. +COPY go.mod go.sum . + +# Get all of our dependencies. +RUN go mod download + +# Copy all of our remaining application. +COPY . . + +# Build our application. +RUN CGO_ENABLED=0 GOOS=linux go build -o docker-mariadb-clean-arch ./cmd/docker-mariadb-clean-arch/main.go + +# Use 'scratch' image for super-mini build. +FROM scratch AS prod + +# Set working directory for this stage. +WORKDIR /production + +# Copy our compiled executable from the last stage. +COPY --from=api /compiler/docker-mariadb-clean-arch . + +# Run application and expose port 8080. +EXPOSE 8080 +CMD ["./docker-mariadb-clean-arch"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..edf1167 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +.PHONY: start +start: + docker-compose up -d --build + +.PHONY: stop +stop: + docker-compose rm -v --force --stop + docker image rm docker-mariadb-clean-arch:latest + +.PHONY: test +test: + sh ./scripts/e2e-testing.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..4dcec90 --- /dev/null +++ b/README.md @@ -0,0 +1,193 @@ +# Docker MariaDB Clean Architecture + +A slightly complex REST application with Fiber to showcase Clean Architecture with MariaDB as a dependency with Docker. + +## Prerequisites + +- Docker Compose for running the application. +- Shell that supports `sh`, `make`, and `curl` for end-to-end testing. UNIX systems or WSL should work fine. +- Postman if you want to test this API with GUI. + +## Application + +This application is a slightly complex example of a REST API that have four major endpoints. A public user can access the `User`, `Auth`, and `Misc` major endpoints, but they cannot access the `City` endpoint (as it is protected). If one wants to access said endpoint, they have to log in first via the `Auth` endpoint, and only after that they can access the `City` endpoint. + +This application uses MariaDB as a database (dockerized), and JWT as an authentication mechanism. This application also showcases how to perform 1-to-many relational mapping in Clean Architecture (one user can have multiple cities), and also the implementation of `JOIN` SQL clause in Go in general. + +## Clean Architecture + +![Clean Architecture](./assets/CleanArchitecture.jpg) + +Clean Architecture is a concept introduced by Robert C. Martin or also known as Uncle Bob. Simply put, the purpose of this architecture is to perform complete separation of concerns. Systems made this way can be independent of frameworks, testable (easy to write unit tests), independent of UI, independent of database, and independent of any external agency. When you use this architecture, it is simple to change the UI, the database, or the business logic. + +One thing that you should keep in mind when using this architecture is about Dependency Rule. In Clean Architecture, source code dependency can only point inwards. This means that the 'inner circle' of the system cannot know at all about the outside world. For example, in the diagram above, use-cases knows about entities, but entities cannot know about use-cases. Data formats used in outer circle should not be used by an inner circle. + +Because of this, when you change something that is located the innermost of the circle (entities for example), usually you have to change the outer circles. However, if you change something that is not the innermost of the circle (controllers for example), you do not need to change the use-cases and the entities (you may have to change the frameworks and drivers as they are dependent on each other). + +If you want to learn more about Clean Architecture, please see the articles that I have attached below as references. + +## System Architecture + +For the sake of clearness, here is the diagram that showcases the system architecture of this API. + +![System Architecture](./assets/SystemArchitecture.png) + +Please refer to below table for terminologies / filenames for each layers that are used in this application. The project structure is referred from [this project](https://github.com/golang-standards/project-layout). In the `internal` package, there are packages that are grouped according to their functional responsibilities. If you open the package, you will see the files that represents the Clean Architecture layers. + +For the dependency graph, it is straightforward: handler/middleware depends on service, service depends on repository, and repository depends on domain and the database (via dependency injection). All of the layers are implemented with the said infrastructure (Fiber, MariaDB, and Authentication Service) in above image. + +I have slightly modified the layers in this application to conform to my own taste of Clean Architecture. + +| Architecture Layer | Equivalent Layer | Filename | +| :-----------------: | :--------------------: | :------------------------------: | +| External Interfaces | Presenters and Drivers | `middleware.go` and `handler.go` | +| Controllers | Business Logic | `service.go` | +| Use Cases | Repositories | `repository.go` | +| Entities | Entities | `domain.go` | + +Basically, a request will have to go through `handler.go` (and `middleware.go`) first. After that, the program will call a repository or a use-case that is requested with `service.go`. That controller (`service.go`) will call `repository.go` that conforms to the `domain.go` in order to fulfill the request that the `service.go` asked for. The result of the request will be returned back to the user by `handler.go`. + +In short: + +- `handler.go` and `middleware.go` is used to receive and send requests. +- `service.go` is business-logic or controller (some might have different opinions, but this is my subjective opinion). +- `repository.go` is used to interact to the database (use-case). +- `domain.go` is the 'shape' of the data models that the program use. + +For the sake of completeness, here are the functional responsibilities of the project structure. + +- `internal/auth` is used to manage authentication. +- `internal/city` is used to manage cities. This endpoint **is protected**. +- `internal/infrastructure` is used to manage infrastructure of the application, such as MariaDB and Fiber. +- `internal/misc` is used to manage miscellaneous endpoints. +- `internal/user` is used to manage users. This endpoint is **not protected**. + +Please refer to the code itself for further details. I commented everything in the code, so I hope it is clear enough! + +## API Endpoints / Features + +This API is divided into four 'major endpoints', which are miscellaneous, users, authentication, and cities. + +### Miscellaneous + +Endpoints classified here are miscellaneous endpoints. + +- `GET /api/v1` for health check. + +### Users + +Endpoints classified here are endpoints to perform operation on 'User' domain. + +- `GET /api/v1/users` to get all users. +- `POST /api/v1/users` to create a user. +- `GET /api/v1/users/` to get a user. +- `PUT /api/v1/users/` to update a user. +- `DELETE /api/v1/users/` to delete a user. + +### Authentication + +Endpoints classified here are endpoints to perform authentication. In my opinion, this is framework-layer / implementation detail, so there is no 'domain' regarding this endpoint and you can use this endpoint as an enhancement to other endpoints. Authentication in this API is done using JSON Web Tokens. + +- `POST /api/v1/auth/login` to log in as the user with ID of 1 in the database. Will return JWT and said JWT will be stored in a cookie. +- `POST /api/v1/auth/logout` to log out. This route removes the JWT from the cookie. +- `GET /api/v1/auth/private` to access a private route which displays information about the current (valid) JWT. + +### Cities + +Endpoints classified here are endpoints to perform operation on `City` domain. **Endpoints here are protected via JWT in the cookie**, so if you are going to use this endpoint, make sure you are logged in first (or at least have a valid JWT). + +- `GET /api/v1/cities` to get all cities. +- `POST /api/v1/cities` to create a new city. +- `GET /api/v1/cities/` to get a city. +- `PUT /api/v1/cities/` to update a city. +- `DELETE /api/v1/cities/` to delete a city. + +## Installation + +In order to run this application, you just need to do the following commands. + +- Clone the repository. + +```bash +git clone git@github.com:gofiber/recipes.git +``` + +- Switch to this repository. + +```bash +cd recipes/docker-mariadb-clean-arch +``` + +- Run immediately with Docker. After you run this command, migration script will be automatically run to populate your dockerized MariaDB. + +```bash +make start +``` + +- Test with Postman (set the request URL to `localhost:8080`) or with the created end-to-end testing script. Keep in mind that the end-to-end script is only available for the first run. If you are trying to run it the second time, you might not be able to get all of the perfect results (because of the auto-increment in the MariaDB). Please run `make stop` and `make start` first if you want to run the test suite again. + +```bash +make test +``` + +- Teardown or stop the container. This will also delete the Docker volume created and will also delete the created image. + +```bash +make stop +``` + +You're done! + +## FAQ + +Some frequently asked questions that I found scattered on the Internet. Keep in mind that the answers are mostly subjective. + +**Q: Is this the right way to do Clean Architecture?** + +A: Nope. There are many ways to perform clean architecture - this example being one of them. Some projects might be better than this example. + +**Q: Why is authentication an implementation detail?** + +A: Authentication is an implementation detail because it does not interact with the use-case or the repository / interface layer. Authentication is a bit strange that it can be implemented in any other routes as a middleware. Keep in mind that this is my subjective opinion. + +**Q: Is this the recommended way to structure Fiber projects?** + +A: Nope. Just like any other Gophers, I recommend you to start your project by using a single `main.go` file. Some projects do not require complicated architectures. After you start seeing the need to branch out, I recommend you to [split your code based on functional responsibilities](https://rakyll.org/style-packages/). If you need an even more strict structure, then you can try to adapt Clean Architecture or any other architectures that you see fit, such as Onion, Hexagonal, etcetera. + +**Q: Is this only for Fiber?** + +A: Nope. You can simply adjust `handler.go` and `middleware.go` files in order to change the external interfaces / presenters and drivers layer to something else. You can use `net/http`, `gin-gonic`, `echo`, and many more. If you want to change or add your database, you just need to adjust the `repository.go` file accordingly. If you want to change your business logic, simply change the `service.go` file. As long as you the separation of concerns is done well, you should have no need to change a lot of things. + +**Q: Is this production-ready?** + +A: I try to make this as production-ready as possible 😉 + +## Improvements + +Several further improvements that could be implemented in this project: + +- Add more tests and mocks, especially unit tests (Clean Architecture is the best for performing unit tests). +- Add more API endpoints. +- Add a caching mechanism to the repository layer, such as Redis. +- Add transaction support. +- Maybe try to integrate S3 backend to the repository layer (MinIO is a good choice). +- Maybe add a `domain` folder in the `internal` package where we can leave the entities there? + +## Discussion + +Feel free to create an issue in this repository (or maybe ask in Fiber's Discord Server) in order to discuss this together! + +## References + +Thanks to articles and their writers that I have read and found inspiration in! + +- [Clean Architecture by Angad Sharma](https://medium.com/gdg-vit/clean-architecture-the-right-way-d83b81ecac6) +- [Clean Architecture by Uncle Bob](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) +- [Clean Architecture with Go by Elton Minetto](https://dev.to/eminetto/clean-architecture-using-golang-5791) +- [Clean Architecture with Go Part 2 by Elton Minetto](https://dev.to/eminetto/clean-architecture-2-years-later-4een) +- [Creating Clean Architecture using Go by @namkount](https://hackernoon.com/creating-clean-architecture-using-golang-9h5i3wgr) +- [Dive to Clean Architecture with Go by Kenta Takeuchi](https://dev.to/bmf_san/dive-to-clean-architecture-with-golang-cd4) +- [Go and Clean Architecture by Reshef Sharvit](https://itnext.io/golang-and-clean-architecture-19ae9aae5683) +- [Go Microservices with Clean Architecture by Jin Feng](https://medium.com/@jfeng45/go-microservice-with-clean-architecture-application-design-68f48802c8f) +- [Go Project Layout Repository](https://github.com/golang-standards/project-layout) +- [Trying Clean Architecture on Go by Imam Tumorang](https://hackernoon.com/golang-clean-archithecture-efd6d7c43047) diff --git a/assets/CleanArchitecture.jpg b/assets/CleanArchitecture.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3cd44fb58d87e5fd2fe1f0a75533f132bb163c61 GIT binary patch literal 107444 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

rCqv;@~gH@sYFHHT-Cg9JB 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

%@!pDS~Yf#TW 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�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 JJT!g%e*laTgd6|> literal 0 HcmV?d00001 diff --git a/cmd/docker-mariadb-clean-arch/main.go b/cmd/docker-mariadb-clean-arch/main.go new file mode 100644 index 0000000..df6a64a --- /dev/null +++ b/cmd/docker-mariadb-clean-arch/main.go @@ -0,0 +1,7 @@ +package main + +import "bill-go-fiber/internal/infrastructure" + +func main() { + infrastructure.Run() +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..8596224 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,36 @@ +version: "3.9" +services: + fiber-application: + restart: always + image: docker-mariadb-clean-arch:latest + build: + context: . + dockerfile: Dockerfile + target: prod + ports: + - 8080:8080 + environment: + - API_USERID=1 + - API_USERNAME=fiber + - API_PASSWORD=fiber + - JWT_SECRET=fiber + networks: + - application + depends_on: + - mariadb + command: ./docker-mariadb-clean-arch + + mariadb: + image: mariadb:10.6.3 + restart: always + volumes: + - ./scripts/migrations.sql:/docker-entrypoint-initdb.d/1.sql + expose: + - 3306 + environment: + - MARIADB_ALLOW_EMPTY_ROOT_PASSWORD=true + networks: + - application + +networks: + application: diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f86e58b --- /dev/null +++ b/go.mod @@ -0,0 +1,29 @@ +module bill-go-fiber + +go 1.20 + +require ( + github.com/go-sql-driver/mysql v1.7.1 + github.com/gofiber/fiber/v2 v2.44.0 + github.com/gofiber/jwt/v2 v2.2.7 + github.com/golang-jwt/jwt v3.2.2+incompatible +) + +require ( + github.com/andybalholm/brotli v1.0.5 // indirect + github.com/golang-jwt/jwt/v4 v4.0.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/klauspost/compress v1.16.3 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.18 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/philhofer/fwd v1.1.2 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 // indirect + github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect + github.com/tinylib/msgp v1.1.8 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.45.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + golang.org/x/sys v0.7.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..de7b1a1 --- /dev/null +++ b/go.sum @@ -0,0 +1,108 @@ +github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/gofiber/fiber/v2 v2.17.0/go.mod h1:iftruuHGkRYGEXVISmdD7HTYWyfS2Bh+Dkfq4n/1Owg= +github.com/gofiber/fiber/v2 v2.44.0 h1:Z90bEvPcJM5GFJnu1py0E1ojoerkyew3iiNJ78MQCM8= +github.com/gofiber/fiber/v2 v2.44.0/go.mod h1:VTMtb/au8g01iqvHyaCzftuM/xmZgKOZCtFzz6CdV9w= +github.com/gofiber/jwt/v2 v2.2.7 h1:MgXZV+ak+FiRVepD3btHBxWcyxlFzTDGXJv78dU1sIE= +github.com/gofiber/jwt/v2 v2.2.7/go.mod h1:yaOHLccYXJidk1HX/EiIdIL+Z1xmY2wnIv6hgViw384= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= +github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= +github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 h1:rmMl4fXJhKMNWl+K+r/fq4FbbKI+Ia2m9hYBLm2h4G4= +github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94/go.mod h1:90zrgN3D/WJsDd1iXHT96alCoN2KJo6/4x1DZC3wZs8= +github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4= +github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk= +github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g= +github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= +github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= +github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.26.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA= +github.com/valyala/fasthttp v1.45.0 h1:zPkkzpIn8tdHZUrVa6PzYd0i5verqiPSkgTd3bSUcpA= +github.com/valyala/fasthttp v1.45.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= +github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +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= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +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.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/auth/handler.go b/internal/auth/handler.go new file mode 100644 index 0000000..84f166e --- /dev/null +++ b/internal/auth/handler.go @@ -0,0 +1,136 @@ +package auth + +import ( + "os" + "time" + + "github.com/gofiber/fiber/v2" + "github.com/golang-jwt/jwt" +) + +// Create an authentication handler. Leave this empty, as we have no domains nor use-cases. +// In my opinion, authentication is an implementation detail (framework layer). +type AuthHandler struct{} + +// Creates a new authentication handler. +func NewAuthHandler(authRoute fiber.Router) { + handler := &AuthHandler{} + + // Declare routing for specific routes. + authRoute.Post("/login", handler.signInUser) + authRoute.Post("/logout", handler.signOutUser) + authRoute.Get("/private", JWTMiddleware(), handler.privateRoute) +} + +// Signs in a user and gives them a JWT. +func (h *AuthHandler) signInUser(c *fiber.Ctx) error { + // Create a struct so the request body can be mapped here. + type loginRequest struct { + Username string `json:"username"` + Password string `json:"password"` + } + + // Create a struct for our custom JWT payload. + type jwtClaims struct { + UserID string `json:"uid"` + User string `json:"user"` + jwt.StandardClaims + } + + // Get request body. + request := &loginRequest{} + if err := c.BodyParser(request); err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + // If both username and password are incorrect, do not allow access. + if request.Username != os.Getenv("API_USERNAME") || request.Password != os.Getenv("API_PASSWORD") { + return c.Status(fiber.StatusUnauthorized).JSON(&fiber.Map{ + "status": "fail", + "message": "Wrong username or password!", + }) + } + + // Send back JWT as a cookie. + token := jwt.NewWithClaims(jwt.SigningMethodHS256, &jwtClaims{ + os.Getenv("API_USERID"), + os.Getenv("API_USERNAME"), + jwt.StandardClaims{ + Audience: "bill-go-fiber-users", + ExpiresAt: time.Now().Add(time.Hour * 24).Unix(), + Issuer: "bill-go-fiber", + }, + }) + signedToken, err := token.SignedString([]byte(os.Getenv("JWT_SECRET"))) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + c.Cookie(&fiber.Cookie{ + Name: "jwt", + Value: signedToken, + Path: "/", + Expires: time.Now().Add(time.Hour * 24), + Secure: false, + HTTPOnly: true, + }) + + // Send also response. + return c.Status(fiber.StatusOK).JSON(&fiber.Map{ + "status": "success", + "token": signedToken, + }) +} + +// Logs out user and removes their JWT. +func (h *AuthHandler) signOutUser(c *fiber.Ctx) error { + c.Cookie(&fiber.Cookie{ + Name: "jwt", + Value: "loggedOut", + Path: "/", + Expires: time.Now().Add(time.Second * 10), + Secure: false, + HTTPOnly: true, + }) + + return c.Status(fiber.StatusOK).JSON(&fiber.Map{ + "status": "success", + "message": "Logged out successfully!", + }) +} + +// A single private route that only logged in users can access. +func (h *AuthHandler) privateRoute(c *fiber.Ctx) error { + // Give form to our output response. + type jwtResponse struct { + UserID interface{} `json:"uid"` + User interface{} `json:"user"` + Iss interface{} `json:"iss"` + Aud interface{} `json:"aud"` + Exp interface{} `json:"exp"` + } + + // Prepare our variables to be displayed. + jwtData := c.Locals("user").(*jwt.Token) + claims := jwtData.Claims.(jwt.MapClaims) + + // Shape output response. + jwtResp := &jwtResponse{ + UserID: claims["uid"], + User: claims["user"], + Iss: claims["iss"], + Aud: claims["aud"], + Exp: claims["exp"], + } + + return c.Status(fiber.StatusOK).JSON(&fiber.Map{ + "status": "success", + "message": "Welcome to the private route!", + "jwtData": jwtResp, + }) +} diff --git a/internal/auth/middleware.go b/internal/auth/middleware.go new file mode 100644 index 0000000..2b61b3d --- /dev/null +++ b/internal/auth/middleware.go @@ -0,0 +1,54 @@ +package auth + +import ( + "os" + "strconv" + + "github.com/gofiber/fiber/v2" + jwtware "github.com/gofiber/jwt/v2" + "github.com/golang-jwt/jwt" +) + +// JWT error message. +func jwtError(c *fiber.Ctx, err error) error { + if err.Error() == "Missing or malformed JWT" { + return c.Status(fiber.StatusBadRequest).JSON(&fiber.Map{ + "status": "error", + "message": "Missing or malformed JWT!", + }) + } + + return c.Status(fiber.StatusUnauthorized).JSON(&fiber.Map{ + "status": "error", + "message": "Invalid or expired JWT!", + }) +} + +// Guards a specific endpoint in the API. +func JWTMiddleware() fiber.Handler { + return jwtware.New(jwtware.Config{ + ErrorHandler: jwtError, + SigningKey: []byte(os.Getenv("JWT_SECRET")), + SigningMethod: "HS256", + TokenLookup: "cookie:jwt", + }) +} + +// Gets user data (their ID) from the JWT middleware. Should be executed after calling 'JWTMiddleware()'. +func GetDataFromJWT(c *fiber.Ctx) error { + // Get userID from the previous route. + jwtData := c.Locals("user").(*jwt.Token) + claims := jwtData.Claims.(jwt.MapClaims) + parsedUserID := claims["uid"].(string) + userID, err := strconv.Atoi(parsedUserID) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + // Go to next. + c.Locals("currentUser", userID) + return c.Next() +} diff --git a/internal/city/domain.go b/internal/city/domain.go new file mode 100644 index 0000000..c739e0d --- /dev/null +++ b/internal/city/domain.go @@ -0,0 +1,47 @@ +package city + +import ( + "bill-go-fiber/internal/user" + "context" +) + +// Represents 'cities' object. +type City struct { + ID int `json:"id"` + Name string `json:"name"` + Created int64 `json:"created"` + Modified int64 `json:"modified"` + User int `json:"user"` +} + +// Represents our 1-to-many relationship, User to Cities. +// In other words, a single user can have many cities. +// This is used for the presentation layer only. +type CityAndUser struct { + ID int `json:"id"` + Name string `json:"name"` + Created int64 `json:"created"` + Modified int64 `json:"modified"` + User user.User `json:"user"` +} + +// Our repository will implement these methods. +type CityRepository interface { + GetCities(ctx context.Context) (*[]CityAndUser, error) + GetCity(ctx context.Context, cityID int) (*CityAndUser, error) + CreateCity(ctx context.Context, city *City) error + UpdateCity(ctx context.Context, cityID int, city *City) error + DeleteCity(ctx context.Context, cityID int) error +} + +// Our use-case or service will implement these methods. +// Method names does not matter - I intentionally changed the names here so they are different from the repository. +// Usually, 'services' should be as close as possible to a business use-case / problem. +// Some methods will also take 'userID' as an argument - because we need it to fill the 'User' value in the struct. +type CityService interface { + FetchCities(ctx context.Context) (*[]CityAndUser, error) + FetchCity(ctx context.Context, cityID int) (*CityAndUser, error) + BuildCity(ctx context.Context, city *City, userID int) error + ModifyCity(ctx context.Context, cityID int, city *City, userID int) error + DestroyCity(ctx context.Context, cityID int) error +} diff --git a/internal/city/handler.go b/internal/city/handler.go new file mode 100644 index 0000000..03684a2 --- /dev/null +++ b/internal/city/handler.go @@ -0,0 +1,178 @@ +package city + +import ( + "bill-go-fiber/internal/auth" + "context" + + "github.com/gofiber/fiber/v2" +) + +// We will inject our dependency - the service - here. +type CityHandler struct { + cityService CityService +} + +// Creates a new handler. +func NewCityHandler(cityRoute fiber.Router, cs CityService) { + // Create a handler based on our created service / use-case. + handler := &CityHandler{ + cityService: cs, + } + + // We will restrict this route with our JWT middleware. + // You can inject other middlewares if you see fit here. + cityRoute.Use(auth.JWTMiddleware(), auth.GetDataFromJWT) + + // Routing for general routes. + cityRoute.Get("", handler.getCities) + cityRoute.Post("", handler.createCity) + + // Routing for specific routes. + cityRoute.Get("/:cityID", handler.getCity) + cityRoute.Put("/:cityID", handler.checkIfCityExistsMiddleware, handler.updateCity) + cityRoute.Delete("/:cityID", handler.checkIfCityExistsMiddleware, handler.deleteCity) +} + +// Handler to get all cities. +func (h *CityHandler) getCities(c *fiber.Ctx) error { + // Create cancellable context. + customContext, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Get all cities. + cities, err := h.cityService.FetchCities(customContext) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + // Return results. + return c.Status(fiber.StatusOK).JSON(&fiber.Map{ + "status": "success", + "data": cities, + }) +} + +// Get one city. +func (h *CityHandler) getCity(c *fiber.Ctx) error { + // Create cancellable context. + customContext, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Fetch parameter. + targetedCityID, err := c.ParamsInt("cityID") + if err != nil { + return c.Status(fiber.StatusBadRequest).JSON(&fiber.Map{ + "status": "fail", + "message": "Please specify a valid city ID!", + }) + } + + // Get one city. + city, err := h.cityService.FetchCity(customContext, targetedCityID) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + // Return results. + return c.Status(fiber.StatusOK).JSON(&fiber.Map{ + "status": "success", + "data": city, + }) +} + +// Creates a single city. +func (h *CityHandler) createCity(c *fiber.Ctx) error { + // Initialize variables. + city := &City{} + currentUserID := c.Locals("currentUser").(int) + + // Create cancellable context. + customContext, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Parse request body. + if err := c.BodyParser(city); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + // Create one city. + err := h.cityService.BuildCity(customContext, city, currentUserID) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + // Return result. + return c.Status(fiber.StatusCreated).JSON(&fiber.Map{ + "status": "success", + "message": "City has been created successfully!", + }) +} + +// Updates a single city. +func (h *CityHandler) updateCity(c *fiber.Ctx) error { + // Initialize variables. + city := &City{} + currentUserID := c.Locals("currentUser").(int) + targetedCityID := c.Locals("cityID").(int) + + // Create cancellable context. + customContext, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Parse request body. + if err := c.BodyParser(city); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + // Update one city. + err := h.cityService.ModifyCity(customContext, targetedCityID, city, currentUserID) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + // Return result. + return c.Status(fiber.StatusOK).JSON(&fiber.Map{ + "status": "success", + "message": "City has been updated successfully!", + }) +} + +// Deletes a single city. +func (h *CityHandler) deleteCity(c *fiber.Ctx) error { + // Initialize previous city ID. + targetedCityID := c.Locals("cityID").(int) + + // Create cancellable context. + customContext, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Delete one city. + err := h.cityService.DestroyCity(customContext, targetedCityID) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + // Return 204 No Content. + return c.SendStatus(fiber.StatusNoContent) +} diff --git a/internal/city/middleware.go b/internal/city/middleware.go new file mode 100644 index 0000000..2a5c5f6 --- /dev/null +++ b/internal/city/middleware.go @@ -0,0 +1,42 @@ +package city + +import ( + "context" + + "github.com/gofiber/fiber/v2" +) + +// If city does not exist, do not allow one to access the API. +func (h *CityHandler) checkIfCityExistsMiddleware(c *fiber.Ctx) error { + // Create a new customized context. + customContext, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Fetch parameter. + targetedCityID, err := c.ParamsInt("cityID") + if err != nil { + return c.Status(fiber.StatusBadRequest).JSON(&fiber.Map{ + "status": "fail", + "message": "Please specify a valid city ID!", + }) + } + + // Check if city exists. + searchedCity, err := h.cityService.FetchCity(customContext, targetedCityID) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + if searchedCity == nil { + return c.Status(fiber.StatusBadRequest).JSON(&fiber.Map{ + "status": "fail", + "message": "There is no city with this ID!", + }) + } + + // Store in locals for further processing in the real handler. + c.Locals("cityID", targetedCityID) + return c.Next() +} diff --git a/internal/city/repository.go b/internal/city/repository.go new file mode 100644 index 0000000..33f5bf7 --- /dev/null +++ b/internal/city/repository.go @@ -0,0 +1,158 @@ +package city + +import ( + "context" + "database/sql" +) + +// Queries that we will use. +const ( + QUERY_GET_CITIES = "SELECT c.id, c.name, c.created, c.modified, u.id, u.name, u.address, u.created, u.modified FROM cities AS c JOIN users AS u ON (c.user = u.id)" + QUERY_GET_CITY = "SELECT c.id, c.name, c.created, c.modified, u.id, u.name, u.address, u.created, u.modified FROM cities AS c JOIN users AS u ON (c.user = u.id) WHERE c.id = ?" + QUERY_CREATE_CITY = "INSERT INTO cities (name, created, modified, user) VALUES (?, ?, ?, ?)" + QUERY_UPDATE_CITY = "UPDATE cities SET name = ?, modified = ?, user = ? WHERE id = ?" + QUERY_DELETE_CITY = "DELETE FROM cities WHERE id = ?" +) + +// Represents that we will use MariaDB in order to implement the methods. +type mariaDBRepository struct { + mariadb *sql.DB +} + +// Create a new repository with MariaDB as the driver. +func NewCityRepository(mariaDBConnection *sql.DB) CityRepository { + return &mariaDBRepository{ + mariadb: mariaDBConnection, + } +} + +// Gets all cities in the database. +func (r *mariaDBRepository) GetCities(ctx context.Context) (*[]CityAndUser, error) { + // Initialize variables. + var cities []CityAndUser + + // Fetches all cities. + res, err := r.mariadb.QueryContext(ctx, QUERY_GET_CITIES) + if err != nil { + return nil, err + } + defer res.Close() + + // Scan all of the cities from the results. + for res.Next() { + city := &CityAndUser{} + err = res.Scan( + &city.ID, + &city.Name, + &city.Created, + &city.Modified, + &city.User.ID, + &city.User.Name, + &city.User.Address, + &city.User.Created, + &city.User.Modified, + ) + if err != nil && err == sql.ErrNoRows { + return nil, nil + } + if err != nil { + return nil, err + } + cities = append(cities, *city) + } + + return &cities, nil +} + +// Gets a single city in the database. +func (r *mariaDBRepository) GetCity(ctx context.Context, cityID int) (*CityAndUser, error) { + // Initialize variable. + city := &CityAndUser{} + + // Prepare SQL to get one city. + stmt, err := r.mariadb.PrepareContext(ctx, QUERY_GET_CITY) + if err != nil { + return nil, err + } + defer stmt.Close() + + // Get one city and insert it to the 'city' struct. + // If it's empty, return null. + err = stmt.QueryRowContext(ctx, cityID).Scan( + &city.ID, + &city.Name, + &city.Created, + &city.Modified, + &city.User.ID, + &city.User.Name, + &city.User.Address, + &city.User.Created, + &city.User.Modified, + ) + if err != nil && err == sql.ErrNoRows { + return nil, nil + } + if err != nil { + return nil, err + } + + // Return result. + return city, nil +} + +// Creates a single city in the database. +func (r *mariaDBRepository) CreateCity(ctx context.Context, city *City) error { + // Prepare context to be used. + stmt, err := r.mariadb.PrepareContext(ctx, QUERY_CREATE_CITY) + if err != nil { + return err + } + defer stmt.Close() + + // Insert one city. + _, err = stmt.ExecContext(ctx, city.Name, city.Created, city.Modified, city.User) + if err != nil { + return err + } + + // Return empty. + return nil +} + +// Updates a single city in the database. +func (r *mariaDBRepository) UpdateCity(ctx context.Context, cityID int, city *City) error { + // Prepare context to be used. + stmt, err := r.mariadb.PrepareContext(ctx, QUERY_UPDATE_CITY) + if err != nil { + return err + } + defer stmt.Close() + + // Update one city. + _, err = stmt.ExecContext(ctx, city.Name, city.Modified, city.User, cityID) + if err != nil { + return err + } + + // Return empty. + return nil +} + +// Deletes a single city in the database. +func (r *mariaDBRepository) DeleteCity(ctx context.Context, cityID int) error { + // Prepare context to be used. + stmt, err := r.mariadb.PrepareContext(ctx, QUERY_DELETE_CITY) + if err != nil { + return err + } + defer stmt.Close() + + // Delete one city. + _, err = stmt.ExecContext(ctx, cityID) + if err != nil { + return err + } + + // Return empty. + return nil +} diff --git a/internal/city/service.go b/internal/city/service.go new file mode 100644 index 0000000..4178af2 --- /dev/null +++ b/internal/city/service.go @@ -0,0 +1,50 @@ +package city + +import ( + "context" + "time" +) + +// Implementation of the repository in this service. +type cityService struct { + cityReposiory CityRepository +} + +// Create a new 'service' or 'use-case' for 'User' entity. +func NewCityService(r CityRepository) CityService { + return &cityService{ + cityReposiory: r, + } +} + +// Implementation of 'FetchCities'. +func (s *cityService) FetchCities(ctx context.Context) (*[]CityAndUser, error) { + return s.cityReposiory.GetCities(ctx) +} + +// Implementation of 'FetchCity'. +func (s *cityService) FetchCity(ctx context.Context, cityID int) (*CityAndUser, error) { + return s.cityReposiory.GetCity(ctx, cityID) +} + +// Implementation of 'BuildCity'. +// Our business logic is to set our default variables here. +func (s *cityService) BuildCity(ctx context.Context, city *City, userID int) error { + city.Created = time.Now().Unix() + city.Modified = time.Now().Unix() + city.User = userID + return s.cityReposiory.CreateCity(ctx, city) +} + +// Implementation of 'ModifyCity'. +// Same as above, our business logic is to set our default variables. +func (s *cityService) ModifyCity(ctx context.Context, cityID int, city *City, userID int) error { + city.Modified = time.Now().Unix() + city.User = userID + return s.cityReposiory.UpdateCity(ctx, cityID, city) +} + +// Implementation of 'DestroyCity'. +func (s *cityService) DestroyCity(ctx context.Context, cityID int) error { + return s.cityReposiory.DeleteCity(ctx, cityID) +} diff --git a/internal/infrastructure/fiber.go b/internal/infrastructure/fiber.go new file mode 100644 index 0000000..39a4fda --- /dev/null +++ b/internal/infrastructure/fiber.go @@ -0,0 +1,81 @@ +package infrastructure + +import ( + "bill-go-fiber/internal/auth" + "bill-go-fiber/internal/city" + "bill-go-fiber/internal/misc" + "bill-go-fiber/internal/user" + "fmt" + "log" + + _ "github.com/go-sql-driver/mysql" + "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/middleware/compress" + "github.com/gofiber/fiber/v2/middleware/cors" + "github.com/gofiber/fiber/v2/middleware/etag" + "github.com/gofiber/fiber/v2/middleware/favicon" + "github.com/gofiber/fiber/v2/middleware/limiter" + "github.com/gofiber/fiber/v2/middleware/logger" + "github.com/gofiber/fiber/v2/middleware/recover" + "github.com/gofiber/fiber/v2/middleware/requestid" +) + +// Run our Fiber webserver. +func Run() { + // Try to connect to our database as the initial part. + mariadb, err := ConnectToMariaDB() + if err != nil { + log.Fatal("Database connection error: $s", err) + } + + // Creates a new Fiber instance. + app := fiber.New(fiber.Config{ + AppName: "Docker MariaDB Clean Arch", + ServerHeader: "Fiber", + }) + + // Use global middlewares. + app.Use(cors.New()) + app.Use(compress.New()) + app.Use(etag.New()) + app.Use(favicon.New()) + app.Use(limiter.New(limiter.Config{ + Max: 100, + LimitReached: func(c *fiber.Ctx) error { + return c.Status(fiber.StatusTooManyRequests).JSON(&fiber.Map{ + "status": "fail", + "message": "You have requested too many in a single time-frame! Please wait another minute!", + }) + }, + })) + app.Use(logger.New()) + app.Use(recover.New()) + app.Use(requestid.New()) + + // Create repositories. + cityRepository := city.NewCityRepository(mariadb) + userRepository := user.NewUserRepository(mariadb) + + // Create all of our services. + cityService := city.NewCityService(cityRepository) + userService := user.NewUserService(userRepository) + + // Prepare our endpoints for the API. + misc.NewMiscHandler(app.Group("/api/v1")) + auth.NewAuthHandler(app.Group("/api/v1/auth")) + city.NewCityHandler(app.Group("/api/v1/cities"), cityService) + user.NewUserHandler(app.Group("/api/v1/users"), userService) + + // Prepare an endpoint for 'Not Found'. + app.All("*", func(c *fiber.Ctx) error { + errorMessage := fmt.Sprintf("Route '%s' does not exist in this API!", c.OriginalURL()) + + return c.Status(fiber.StatusNotFound).JSON(&fiber.Map{ + "status": "fail", + "message": errorMessage, + }) + }) + + // Listen to port 8080. + log.Fatal(app.Listen(":8080")) +} diff --git a/internal/infrastructure/mariadb.go b/internal/infrastructure/mariadb.go new file mode 100644 index 0000000..03b71ec --- /dev/null +++ b/internal/infrastructure/mariadb.go @@ -0,0 +1,23 @@ +package infrastructure + +import ( + "database/sql" + "time" +) + +// This function is used to connect to MariaDB. +func ConnectToMariaDB() (*sql.DB, error) { + // Connect to MariaDB. + db, err := sql.Open("mysql", "root:@tcp(mariadb:3306)/fiber_dmca") + if err != nil { + return nil, err + } + + // Set up important parts as was told by the documentation. + db.SetConnMaxLifetime(time.Minute * 3) + db.SetMaxOpenConns(10) + db.SetMaxIdleConns(10) + + // Return our database instance. + return db, nil +} diff --git a/internal/misc/handler.go b/internal/misc/handler.go new file mode 100644 index 0000000..7956597 --- /dev/null +++ b/internal/misc/handler.go @@ -0,0 +1,22 @@ +package misc + +import "github.com/gofiber/fiber/v2" + +// Create a handler. Leave this empty, as we have no domains nor use-cases. +type MiscHandler struct{} + +// Represents a new handler. +func NewMiscHandler(miscRoute fiber.Router) { + handler := &MiscHandler{} + + // Declare routing. + miscRoute.Get("", handler.healthCheck) +} + +// Check for the health of the API. +func (h *MiscHandler) healthCheck(c *fiber.Ctx) error { + return c.Status(fiber.StatusOK).JSON(&fiber.Map{ + "status": "success", + "message": "Hello World!", + }) +} diff --git a/internal/user/domain.go b/internal/user/domain.go new file mode 100644 index 0000000..26d2ac7 --- /dev/null +++ b/internal/user/domain.go @@ -0,0 +1,30 @@ +package user + +import "context" + +// Represents the 'User' object. +type User struct { + ID int `json:"id"` + Name string `json:"name"` + Address string `json:"address"` + Created int64 `json:"created"` + Modified int64 `json:"modified"` +} + +// Our repository will implement these methods. +type UserRepository interface { + GetUsers(ctx context.Context) (*[]User, error) + GetUser(ctx context.Context, userID int) (*User, error) + CreateUser(ctx context.Context, user *User) error + UpdateUser(ctx context.Context, userID int, user *User) error + DeleteUser(ctx context.Context, userID int) error +} + +// Our use-case or service will implement these methods. +type UserService interface { + GetUsers(ctx context.Context) (*[]User, error) + GetUser(ctx context.Context, userID int) (*User, error) + CreateUser(ctx context.Context, user *User) error + UpdateUser(ctx context.Context, userID int, user *User) error + DeleteUser(ctx context.Context, userID int) error +} diff --git a/internal/user/handler.go b/internal/user/handler.go new file mode 100644 index 0000000..c5a1b2b --- /dev/null +++ b/internal/user/handler.go @@ -0,0 +1,171 @@ +package user + +import ( + "context" + + "github.com/gofiber/fiber/v2" +) + +// Represents our handler with our use-case / service. +type UserHandler struct { + userService UserService +} + +// Creates a new handler. +func NewUserHandler(userRoute fiber.Router, us UserService) { + // Create a handler based on our created service / use-case. + handler := &UserHandler{ + userService: us, + } + + // Declare routing endpoints for general routes. + userRoute.Get("", handler.getUsers) + userRoute.Post("", handler.createUser) + + // Declare routing endpoints for specific routes. + userRoute.Get("/:userID", handler.getUser) + userRoute.Put("/:userID", handler.checkIfUserExistsMiddleware, handler.updateUser) + userRoute.Delete("/:userID", handler.checkIfUserExistsMiddleware, handler.deleteUser) +} + +// Gets all users. +func (h *UserHandler) getUsers(c *fiber.Ctx) error { + // Create cancellable context. + customContext, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Get all users. + users, err := h.userService.GetUsers(customContext) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + // Return results. + return c.Status(fiber.StatusOK).JSON(&fiber.Map{ + "status": "success", + "data": users, + }) +} + +// Gets a single user. +func (h *UserHandler) getUser(c *fiber.Ctx) error { + // Create cancellable context. + customContext, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Fetch parameter. + targetedUserID, err := c.ParamsInt("userID") + if err != nil { + return c.Status(fiber.StatusBadRequest).JSON(&fiber.Map{ + "status": "fail", + "message": "Please specify a valid user ID!", + }) + } + + // Get one user. + user, err := h.userService.GetUser(customContext, targetedUserID) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + // Return results. + return c.Status(fiber.StatusOK).JSON(&fiber.Map{ + "status": "success", + "data": user, + }) +} + +// Creates a single user. +func (h *UserHandler) createUser(c *fiber.Ctx) error { + // Initialize variables. + user := &User{} + + // Create cancellable context. + customContext, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Parse request body. + if err := c.BodyParser(user); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + // Create one user. + err := h.userService.CreateUser(customContext, user) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + // Return result. + return c.Status(fiber.StatusCreated).JSON(&fiber.Map{ + "status": "success", + "message": "User has been created successfully!", + }) +} + +// Updates a single user. +func (h *UserHandler) updateUser(c *fiber.Ctx) error { + // Initialize variables. + user := &User{} + targetedUserID := c.Locals("userID").(int) + + // Create cancellable context. + customContext, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Parse request body. + if err := c.BodyParser(user); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + // Update one user. + err := h.userService.UpdateUser(customContext, targetedUserID, user) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + // Return result. + return c.Status(fiber.StatusOK).JSON(&fiber.Map{ + "status": "success", + "message": "User has been updated successfully!", + }) +} + +// Deletes a single user. +func (h *UserHandler) deleteUser(c *fiber.Ctx) error { + // Initialize previous user ID. + targetedUserID := c.Locals("userID").(int) + + // Create cancellable context. + customContext, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Delete one user. + err := h.userService.DeleteUser(customContext, targetedUserID) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + + // Return 204 No Content. + return c.SendStatus(fiber.StatusNoContent) +} diff --git a/internal/user/middleware.go b/internal/user/middleware.go new file mode 100644 index 0000000..1fe9c1a --- /dev/null +++ b/internal/user/middleware.go @@ -0,0 +1,42 @@ +package user + +import ( + "context" + + "github.com/gofiber/fiber/v2" +) + +// If user does not exist, do not allow one to access the API. +func (h *UserHandler) checkIfUserExistsMiddleware(c *fiber.Ctx) error { + // Create a new customized context. + customContext, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Fetch parameter. + targetedUserID, err := c.ParamsInt("userID") + if err != nil { + return c.Status(fiber.StatusBadRequest).JSON(&fiber.Map{ + "status": "fail", + "message": "Please specify a valid user ID!", + }) + } + + // Check if user exists. + searchedUser, err := h.userService.GetUser(customContext, targetedUserID) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{ + "status": "fail", + "message": err.Error(), + }) + } + if searchedUser == nil { + return c.Status(fiber.StatusBadRequest).JSON(&fiber.Map{ + "status": "fail", + "message": "There is no user with this ID!", + }) + } + + // Store in locals for further processing in the real handler. + c.Locals("userID", targetedUserID) + return c.Next() +} diff --git a/internal/user/repository.go b/internal/user/repository.go new file mode 100644 index 0000000..14e45fa --- /dev/null +++ b/internal/user/repository.go @@ -0,0 +1,140 @@ +package user + +import ( + "context" + "database/sql" +) + +// Queries that we will use. +const ( + QUERY_GET_USERS = "SELECT * FROM users" + QUERY_GET_USER = "SELECT * FROM users WHERE id = ?" + QUERY_CREATE_USER = "INSERT INTO users (name, address, created, modified) VALUES (?, ?, ?, ?)" + QUERY_UPDATE_USER = "UPDATE users SET name = ?, address = ?, modified = ? WHERE id = ?" + QUERY_DELETE_USER = "DELETE FROM users WHERE id = ?" +) + +// Represents that we will use MariaDB in order to implement the methods. +type mariaDBRepository struct { + mariadb *sql.DB +} + +// Create a new repository with MariaDB as the driver. +func NewUserRepository(mariaDBConnection *sql.DB) UserRepository { + return &mariaDBRepository{ + mariadb: mariaDBConnection, + } +} + +// Gets all users in the database. +func (r *mariaDBRepository) GetUsers(ctx context.Context) (*[]User, error) { + // Initialize variables. + var users []User + + // Get all users. + res, err := r.mariadb.QueryContext(ctx, QUERY_GET_USERS) + if err != nil { + return nil, err + } + defer res.Close() + + // Scan all of the results to the 'users' array. + // If it's empty, return null. + for res.Next() { + user := &User{} + err = res.Scan(&user.ID, &user.Name, &user.Address, &user.Created, &user.Modified) + if err != nil && err == sql.ErrNoRows { + return nil, nil + } + if err != nil { + return nil, err + } + users = append(users, *user) + } + + // Return all of our users. + return &users, nil +} + +// Gets a single user in the database. +func (r *mariaDBRepository) GetUser(ctx context.Context, userID int) (*User, error) { + // Initialize variable. + user := &User{} + + // Prepare SQL to get one user. + stmt, err := r.mariadb.PrepareContext(ctx, QUERY_GET_USER) + if err != nil { + return nil, err + } + defer stmt.Close() + + // Get one user and insert it to the 'user' struct. + // If it's empty, return null. + err = stmt.QueryRowContext(ctx, userID).Scan(&user.ID, &user.Name, &user.Address, &user.Created, &user.Modified) + if err != nil && err == sql.ErrNoRows { + return nil, nil + } + if err != nil { + return nil, err + } + + // Return result. + return user, nil +} + +// Creates a single user in the database. +func (r *mariaDBRepository) CreateUser(ctx context.Context, user *User) error { + // Prepare context to be used. + stmt, err := r.mariadb.PrepareContext(ctx, QUERY_CREATE_USER) + if err != nil { + return err + } + defer stmt.Close() + + // Insert one user. + _, err = stmt.ExecContext(ctx, user.Name, user.Address, user.Created, user.Modified) + if err != nil { + return err + } + + // Return empty. + return nil +} + +// Updates a single user in the database. +func (r *mariaDBRepository) UpdateUser(ctx context.Context, userID int, user *User) error { + // Prepare context to be used. + stmt, err := r.mariadb.PrepareContext(ctx, QUERY_UPDATE_USER) + if err != nil { + return err + } + defer stmt.Close() + + // Update one user. + _, err = stmt.ExecContext(ctx, user.Name, user.Address, user.Modified, userID) + if err != nil { + return err + } + + // Return empty. + return nil +} + +// Deletes a single user in the database. +func (r *mariaDBRepository) DeleteUser(ctx context.Context, userID int) error { + // Prepare context to be used. + stmt, err := r.mariadb.PrepareContext(ctx, QUERY_DELETE_USER) + if err != nil { + return err + } + defer stmt.Close() + + // Delete one user. + _, err = stmt.ExecContext(ctx, userID) + if err != nil { + return err + } + + // Return empty. + return nil +} diff --git a/internal/user/service.go b/internal/user/service.go new file mode 100644 index 0000000..b379063 --- /dev/null +++ b/internal/user/service.go @@ -0,0 +1,52 @@ +package user + +import ( + "context" + "time" +) + +// Implementation of the repository in this service. +type userService struct { + userRepository UserRepository +} + +// Create a new 'service' or 'use-case' for 'User' entity. +func NewUserService(r UserRepository) UserService { + return &userService{ + userRepository: r, + } +} + +// Implementation of 'GetUsers'. +func (s *userService) GetUsers(ctx context.Context) (*[]User, error) { + return s.userRepository.GetUsers(ctx) +} + +// Implementation of 'GetUser'. +func (s *userService) GetUser(ctx context.Context, userID int) (*User, error) { + return s.userRepository.GetUser(ctx, userID) +} + +// Implementation of 'CreateUser'. +func (s *userService) CreateUser(ctx context.Context, user *User) error { + // Set default value of 'Created' and 'Modified'. + user.Created = time.Now().Unix() + user.Modified = time.Now().Unix() + + // Pass to the repository layer. + return s.userRepository.CreateUser(ctx, user) +} + +// Implementation of 'UpdateUser'. +func (s *userService) UpdateUser(ctx context.Context, userID int, user *User) error { + // Set value for 'Modified' attribute. + user.Modified = time.Now().Unix() + + // Pass to the repository layer. + return s.userRepository.UpdateUser(ctx, userID, user) +} + +// Implementation of 'DeleteUser'. +func (s *userService) DeleteUser(ctx context.Context, userID int) error { + return s.userRepository.DeleteUser(ctx, userID) +} diff --git a/scripts/e2e-testing.sh b/scripts/e2e-testing.sh new file mode 100644 index 0000000..b8cf2d3 --- /dev/null +++ b/scripts/e2e-testing.sh @@ -0,0 +1,84 @@ +#!/bin/bash +# Declare variables. +API_URL=http://localhost:8080 + +# Introduction to the script. +echo "Welcome to 'docker-mariadb-clean-arch' application!" +echo "Before running the end-to-end tests, please ensure that you have run 'make start'!"; echo + +# Testing '/api/v1'. +echo +echo "Running end-to-end testing..." +echo "Testing GET route '/api/v1'..." +curl $API_URL/api/v1; echo + +# Testing '/api/v1/users'. +echo +echo "Testing GET route '/api/v1/users'..." +curl $API_URL/api/v1/users; echo +echo +echo "Testing POST route '/api/v1/users'..." +curl -X POST -H 'Content-Type: application/json' -d '{"name":"Lucy Heartfilia","address":"Shinhotaka, Japan"}' $API_URL/api/v1/users; echo + +# Testing '/api/v1/users/:userID'. +echo +echo "Using 'userID' with value of 11 (the one created beforehand)." +echo "Testing GET route '/api/v1/users/:userID'..." +curl $API_URL/api/v1/users/11; echo +echo +echo "Testing PUT route '/api/v1/users/:userID'..." +curl -X PUT -H 'Content-Type: application/json' -d '{"name":"Mirajane Strauss","address":"Osaka, Japan"}' $API_URL/api/v1/users/11; echo +echo +echo "Testing GET route after PUT '/api/v1/users/:userID'..." +curl $API_URL/api/v1/users/11; echo +echo +echo "Testing DELETE route '/api/v1/users/:userID'..." +curl -X DELETE $API_URL/api/v1/users/11; echo +echo +echo "Testing GET route after DELETE '/api/v1/users/:userID'..." +curl $API_URL/api/v1/users/11; echo + +# Testing '/api/v1/auth/login'. +echo +echo "Testing POST route '/api/v1/auth/login'..." +curl -X POST -H 'Content-Type: application/json' -d '{"username":"fiber","password":"fiber"}' -c cookie.txt $API_URL/api/v1/auth/login; echo + +# Testing '/api/v1/auth/private'. +echo +echo "Testing GET route '/api/v1/auth/private'..." +curl -b cookie.txt $API_URL/api/v1/auth/private; echo + +# Testing '/api/v1/cities'. +echo +echo "Testing GET route '/api/v1/cities'..." +curl -b cookie.txt $API_URL/api/v1/cities; echo +echo +echo "Testing POST route '/api/v1/cities'..." +curl -b cookie.txt -X POST -H 'Content-Type: application/json' -d '{"name":"Kyoto"}' $API_URL/api/v1/cities; echo + +# Testing '/api/v1/cities/:cityID'. +echo +echo "Using 'cityID' with value of 6 (the one created beforehand)." +echo "Testing GET route '/api/v1/cities/:cityID'..." +curl -b cookie.txt $API_URL/api/v1/cities/6; echo +echo +echo "Testing PUT route '/api/v1/cities/:cityID'..." +curl -b cookie.txt -X PUT -H 'Content-Type: application/json' -d '{"name":"Osaka"}' $API_URL/api/v1/cities/6; echo +echo +echo "Testing GET route after PUT '/api/v1/cities/:cityID'..." +curl -b cookie.txt $API_URL/api/v1/cities/6; echo +echo +echo "Testing DELETE route '/api/v1/cities/:cityID'..." +curl -b cookie.txt -X DELETE $API_URL/api/v1/cities/6; echo +echo +echo "Testing GET route after DELETE '/api/v1/cities/:cityID'..." +curl -b cookie.txt $API_URL/api/v1/cities/6; echo + +# Testing '/api/v1/auth/logout'. +echo +echo "Testing POST route '/api/v1/auth/logout'..." +curl -X POST $API_URL/api/v1/auth/logout; echo + +# Finish end-to-end testing. +rm cookie.txt +echo "Finished testing the application!" diff --git a/scripts/migrations.sql b/scripts/migrations.sql new file mode 100644 index 0000000..ce06cbc --- /dev/null +++ b/scripts/migrations.sql @@ -0,0 +1,46 @@ +-- In this script, 'dmca' stands for 'Docker MariaDB Clean Arch'. +DROP DATABASE IF EXISTS fiber_dmca; +CREATE DATABASE IF NOT EXISTS fiber_dmca; +USE fiber_dmca; + +-- Create a sample table. +CREATE TABLE users ( + id INT NOT NULL AUTO_INCREMENT, + name VARCHAR(255) NOT NULL, + address VARCHAR(255) NOT NULL, + created VARCHAR(255) NOT NULL, + modified VARCHAR(255) NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB CHARACTER SET utf8; + +-- Populate table with 10 users. +INSERT INTO users VALUES +(1, 'Sayu Ogiwara', 'Hokkaido, Japan', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), +(2, 'Chizuru Ichinose', 'Tokyo, Japan', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), +(3, 'Asagi Aiba', 'Kyoto, Japan', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), +(4, 'Rin Tohsaka', 'Kobe, Japan', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), +(5, 'Mai Sakurajima', 'Fujisawa, Japan', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), +(6, 'Aki Adagaki', 'Fukuoka, Japan', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), +(7, 'Asuna Yuuki', 'Shinagawa, Japan', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), +(8, 'Ruka Sarashina', 'Gotenba, Japan', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), +(9, 'Miyuki Shiba', 'Nagano, Japan', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()), +(10, 'Fumino Furuhashi', 'Niigata, Japan', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()); + +-- Create another sample table. +CREATE TABLE cities ( + id INT NOT NULL AUTO_INCREMENT, + name VARCHAR(255) NOT NULL, + created VARCHAR(255) NOT NULL, + modified VARCHAR(255) NOT NULL, + user INT NOT NULL, + PRIMARY KEY (id), + FOREIGN KEY (user) REFERENCES users (id) +) ENGINE=InnoDB CHARACTER SET utf8; + +-- Create five data samples. +INSERT INTO cities VALUES +(1, 'Hokkaido', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), 1), +(2, 'Tokyo', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), 1), +(3, 'Kyoto', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), 1), +(4, 'Osaka', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), 2), +(5, 'Fukuoka', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), 3);