├── .gitignore ├── README.md ├── choreography ├── README.md ├── docker-compose.yml ├── gateway │ └── krakend.json ├── svc_auth │ ├── .dockerignore │ ├── .env.example │ ├── .gitignore │ ├── Dockerfile │ ├── LICENSE │ ├── Makefile │ ├── docker-compose.yml │ ├── go.mod │ ├── src │ │ ├── app │ │ │ └── v1 │ │ │ │ ├── api │ │ │ │ ├── authorization │ │ │ │ │ ├── controller │ │ │ │ │ │ └── authorization.go │ │ │ │ │ ├── entity │ │ │ │ │ │ └── http.go │ │ │ │ │ └── service │ │ │ │ │ │ └── authorization.go │ │ │ │ ├── client │ │ │ │ │ ├── controller │ │ │ │ │ │ └── client.go │ │ │ │ │ ├── entity │ │ │ │ │ │ ├── database.go │ │ │ │ │ │ └── http.go │ │ │ │ │ ├── repository │ │ │ │ │ │ └── client.go │ │ │ │ │ └── service │ │ │ │ │ │ └── client.go │ │ │ │ ├── health │ │ │ │ │ ├── controller │ │ │ │ │ │ └── health.go │ │ │ │ │ ├── entity │ │ │ │ │ │ └── http.go │ │ │ │ │ └── service │ │ │ │ │ │ └── health.go │ │ │ │ ├── login │ │ │ │ │ ├── controller │ │ │ │ │ │ └── login.go │ │ │ │ │ ├── entity │ │ │ │ │ │ ├── general.go │ │ │ │ │ │ └── http.go │ │ │ │ │ └── service │ │ │ │ │ │ └── login.go │ │ │ │ └── token │ │ │ │ │ ├── controller │ │ │ │ │ └── token.go │ │ │ │ │ ├── entity │ │ │ │ │ ├── general.go │ │ │ │ │ └── http.go │ │ │ │ │ └── service │ │ │ │ │ └── token.go │ │ │ │ ├── routes │ │ │ │ ├── authorization.go │ │ │ │ ├── client.go │ │ │ │ ├── docs.go │ │ │ │ ├── health.go │ │ │ │ ├── login.go │ │ │ │ ├── routes.go │ │ │ │ └── token.go │ │ │ │ └── swagger │ │ │ │ └── docs │ │ │ │ ├── docs.go │ │ │ │ ├── swagger.json │ │ │ │ └── swagger.yaml │ │ ├── config │ │ │ └── server_configuration.go │ │ ├── main.go │ │ ├── middleware │ │ │ ├── auth.go │ │ │ ├── cors_middleware.go │ │ │ └── middleware.go │ │ ├── router │ │ │ └── router.go │ │ └── utils │ │ │ ├── database │ │ │ └── database.go │ │ │ ├── kafka │ │ │ ├── consumer.go │ │ │ ├── kafka.go │ │ │ └── producer.go │ │ │ ├── logger │ │ │ └── logger.go │ │ │ ├── openssl │ │ │ └── openssl.go │ │ │ ├── redis │ │ │ └── redis.go │ │ │ ├── requester │ │ │ └── requester.go │ │ │ └── rest │ │ │ ├── rest.go │ │ │ └── rest_test.go │ └── watcher.conf ├── svc_order │ ├── .dockerignore │ ├── .env.example │ ├── .gitignore │ ├── Dockerfile │ ├── README.md │ ├── docker-compose.yml │ ├── go.mod │ ├── migration │ │ ├── 20200410210842_tb_order_type.down.sql │ │ ├── 20200410210842_tb_order_type.up.sql │ │ ├── 20200410210900_tb_order_status.down.sql │ │ ├── 20200410210900_tb_order_status.up.sql │ │ ├── 20200410210904_tb_orders.down.sql │ │ └── 20200410210904_tb_orders.up.sql │ ├── src │ │ ├── app │ │ │ ├── v1 │ │ │ │ ├── consumer │ │ │ │ │ ├── command.go │ │ │ │ │ └── controller │ │ │ │ │ │ └── consumer.go │ │ │ │ ├── entity │ │ │ │ │ ├── api.go │ │ │ │ │ ├── database.go │ │ │ │ │ └── logger.go │ │ │ │ ├── event │ │ │ │ │ └── event.go │ │ │ │ └── repository │ │ │ │ │ └── order.go │ │ │ └── v2 │ │ │ │ ├── api │ │ │ │ └── order │ │ │ │ │ ├── controller │ │ │ │ │ └── order.go │ │ │ │ │ ├── entity │ │ │ │ │ ├── database.go │ │ │ │ │ ├── event.go │ │ │ │ │ └── http.go │ │ │ │ │ ├── event │ │ │ │ │ └── event.go │ │ │ │ │ ├── repository │ │ │ │ │ └── order.go │ │ │ │ │ └── service │ │ │ │ │ └── order.go │ │ │ │ ├── routes │ │ │ │ ├── docs.go │ │ │ │ ├── order.go │ │ │ │ └── routes.go │ │ │ │ ├── swagger │ │ │ │ └── docs │ │ │ │ │ ├── docs.go │ │ │ │ │ ├── swagger.json │ │ │ │ │ └── swagger.yaml │ │ │ │ ├── utility │ │ │ │ ├── rest │ │ │ │ │ ├── rest.go │ │ │ │ │ └── rest_test.go │ │ │ │ └── str_process │ │ │ │ │ └── str_process.go │ │ │ │ └── worker │ │ │ │ ├── consumer │ │ │ │ ├── command.go │ │ │ │ └── controller │ │ │ │ │ └── consumer.go │ │ │ │ ├── entity │ │ │ │ ├── api.go │ │ │ │ ├── database.go │ │ │ │ └── logger.go │ │ │ │ ├── event │ │ │ │ └── event.go │ │ │ │ └── repository │ │ │ │ └── order.go │ │ ├── config │ │ │ └── config.go │ │ ├── docker-compose.yml │ │ ├── main.go │ │ ├── middleware │ │ │ ├── auth.go │ │ │ ├── cors_middleware.go │ │ │ └── middleware.go │ │ ├── router │ │ │ └── router.go │ │ ├── utils │ │ │ ├── database │ │ │ │ └── database.go │ │ │ ├── kafka │ │ │ │ ├── consumer.go │ │ │ │ ├── kafka.go │ │ │ │ └── producer.go │ │ │ └── logger │ │ │ │ └── logger.go │ │ └── worker │ │ │ └── worker.go │ └── watcher.conf ├── svc_payment │ ├── .dockerignore │ ├── .env.example │ ├── .gitignore │ ├── Dockerfile │ ├── README.md │ ├── docker-compose.yml │ ├── go.mod │ ├── migration │ │ ├── 20200410210429_tb_payment_status.down.sql │ │ ├── 20200410210429_tb_payment_status.up.sql │ │ ├── 20200410210433_tb_payment_model.down.sql │ │ ├── 20200410210433_tb_payment_model.up.sql │ │ ├── 20200410210436_tb_payment.down.sql │ │ └── 20200410210436_tb_payment.up.sql │ └── src │ │ ├── app │ │ └── v2 │ │ │ ├── api │ │ │ └── payment │ │ │ │ ├── controller │ │ │ │ └── payment.go │ │ │ │ ├── entity │ │ │ │ ├── database.go │ │ │ │ ├── event.go │ │ │ │ ├── general.go │ │ │ │ └── http.go │ │ │ │ ├── event │ │ │ │ └── event.go │ │ │ │ ├── repository │ │ │ │ └── payment.go │ │ │ │ └── service │ │ │ │ └── payment.go │ │ │ ├── routes │ │ │ ├── docs.go │ │ │ ├── payment.go │ │ │ └── routes.go │ │ │ ├── swagger │ │ │ └── docs │ │ │ │ ├── docs.go │ │ │ │ ├── swagger.json │ │ │ │ └── swagger.yaml │ │ │ ├── utility │ │ │ ├── rest │ │ │ │ ├── rest.go │ │ │ │ └── rest_test.go │ │ │ └── str_process │ │ │ │ └── str_process.go │ │ │ └── worker │ │ │ ├── consumer │ │ │ ├── command.go │ │ │ └── controller │ │ │ │ └── consumer.go │ │ │ ├── entity │ │ │ ├── api.go │ │ │ ├── database.go │ │ │ └── logger.go │ │ │ ├── event │ │ │ └── event.go │ │ │ ├── repository │ │ │ └── payment.go │ │ │ └── task │ │ │ └── task.go │ │ ├── config │ │ └── config.go │ │ ├── main.go │ │ ├── middleware │ │ ├── auth.go │ │ ├── cors_middleware.go │ │ └── middleware.go │ │ ├── router │ │ └── router.go │ │ ├── utils │ │ ├── database │ │ │ ├── read │ │ │ │ └── read.go │ │ │ └── write │ │ │ │ └── write.go │ │ ├── kafka │ │ │ ├── consumer.go │ │ │ ├── kafka.go │ │ │ └── producer.go │ │ └── logger │ │ │ └── logger.go │ │ └── worker │ │ └── worker.go └── svc_user │ ├── .dockerignore │ ├── .env.example │ ├── .gitignore │ ├── Dockerfile │ ├── LICENSE │ ├── Makefile │ ├── docker-compose.yml │ ├── go.mod │ ├── migration │ ├── 20200406010818_tb_roles.down.sql │ ├── 20200406010818_tb_roles.up.sql │ ├── 20200417000223_tb_users.down.sql │ ├── 20200417000223_tb_users.up.sql │ ├── 20200417000304_tb_login.down.sql │ └── 20200417000304_tb_login.up.sql │ ├── src │ ├── app │ │ └── v1 │ │ │ ├── api │ │ │ ├── health │ │ │ │ ├── controller │ │ │ │ │ └── health.go │ │ │ │ ├── entity │ │ │ │ │ └── http.go │ │ │ │ └── service │ │ │ │ │ └── health.go │ │ │ ├── login │ │ │ │ ├── controller │ │ │ │ │ └── login.go │ │ │ │ ├── entity │ │ │ │ │ ├── database.go │ │ │ │ │ ├── event.go │ │ │ │ │ └── http.go │ │ │ │ ├── event │ │ │ │ │ └── event.go │ │ │ │ ├── repository │ │ │ │ │ └── login.go │ │ │ │ └── service │ │ │ │ │ └── login.go │ │ │ └── user │ │ │ │ ├── controller │ │ │ │ └── user.go │ │ │ │ ├── entity │ │ │ │ ├── database.go │ │ │ │ ├── event.go │ │ │ │ └── http.go │ │ │ │ ├── event │ │ │ │ └── event.go │ │ │ │ ├── repository │ │ │ │ └── user.go │ │ │ │ └── service │ │ │ │ └── user.go │ │ │ ├── routes │ │ │ ├── docs.go │ │ │ ├── health.go │ │ │ ├── login.go │ │ │ ├── routes.go │ │ │ └── user.go │ │ │ ├── swagger │ │ │ └── docs │ │ │ │ ├── docs.go │ │ │ │ ├── swagger.json │ │ │ │ └── swagger.yaml │ │ │ └── worker │ │ │ ├── consumer │ │ │ ├── command.go │ │ │ └── controller │ │ │ │ └── consumer.go │ │ │ ├── entity │ │ │ ├── api.go │ │ │ ├── database.go │ │ │ └── logger.go │ │ │ ├── event │ │ │ └── event.go │ │ │ └── repository │ │ │ ├── login.go │ │ │ └── users.go │ ├── config │ │ └── server_configuration.go │ ├── main.go │ ├── middleware │ │ ├── auth.go │ │ ├── cors_middleware.go │ │ └── middleware.go │ ├── router │ │ └── router.go │ ├── utils │ │ ├── crypto │ │ │ └── crypto.go │ │ ├── database │ │ │ └── database.go │ │ ├── kafka │ │ │ ├── consumer.go │ │ │ ├── kafka.go │ │ │ └── producer.go │ │ ├── logger │ │ │ └── logger.go │ │ ├── requester │ │ │ └── requester.go │ │ ├── rest │ │ │ ├── rest.go │ │ │ └── rest_test.go │ │ └── str_process │ │ │ └── str_process.go │ └── worker │ │ └── worker.go │ └── watcher.conf ├── dependecies ├── database │ ├── choreography │ │ └── docker-compose.yml │ └── orchestration │ │ └── docker-compose.yml ├── kafka │ └── docker-compose.yml ├── krakend │ ├── choreography │ │ ├── docker-compose.yml │ │ └── etc │ │ │ └── krakend.json │ └── orchestration │ │ ├── docker-compose.yml │ │ └── etc │ │ └── krakend.json ├── logger │ └── docker-compose.yml └── redis │ └── docker-compose.yml ├── docs └── choreography │ ├── api │ └── api_layer.json │ ├── architecture.png │ ├── concept.png │ ├── event.png │ ├── order │ ├── create.png │ └── get.png │ ├── payment │ └── payment.png │ └── user │ ├── create.png │ └── get.png ├── license └── orchestration ├── README.md ├── docker-compose.yml ├── orchestrator ├── .dockerignore ├── .env.example ├── .gitignore ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── docker-compose.yml ├── go.mod ├── src │ ├── app │ │ └── v1 │ │ │ ├── api │ │ │ ├── health │ │ │ │ ├── controller │ │ │ │ │ └── health.go │ │ │ │ ├── entity │ │ │ │ │ └── http.go │ │ │ │ └── service │ │ │ │ │ └── health.go │ │ │ ├── login │ │ │ │ ├── controller │ │ │ │ │ └── user.go │ │ │ │ ├── entity │ │ │ │ │ ├── event.go │ │ │ │ │ └── http.go │ │ │ │ ├── event │ │ │ │ │ └── event.go │ │ │ │ └── service │ │ │ │ │ └── user.go │ │ │ ├── order │ │ │ │ ├── controller │ │ │ │ │ └── order.go │ │ │ │ ├── entity │ │ │ │ │ ├── event.go │ │ │ │ │ └── http.go │ │ │ │ ├── event │ │ │ │ │ └── event.go │ │ │ │ └── service │ │ │ │ │ └── order.go │ │ │ ├── payment │ │ │ │ ├── controller │ │ │ │ │ └── payment.go │ │ │ │ ├── entity │ │ │ │ │ ├── event.go │ │ │ │ │ ├── general.go │ │ │ │ │ └── http.go │ │ │ │ ├── event │ │ │ │ │ └── event.go │ │ │ │ └── service │ │ │ │ │ ├── consumer.go │ │ │ │ │ └── payment.go │ │ │ └── user │ │ │ │ ├── controller │ │ │ │ └── user.go │ │ │ │ ├── entity │ │ │ │ ├── event.go │ │ │ │ └── http.go │ │ │ │ ├── event │ │ │ │ └── event.go │ │ │ │ └── service │ │ │ │ └── user.go │ │ │ ├── routes │ │ │ ├── docs.go │ │ │ ├── health.go │ │ │ ├── order.go │ │ │ ├── payment.go │ │ │ ├── routes.go │ │ │ └── user.go │ │ │ ├── swagger │ │ │ └── docs │ │ │ │ ├── docs.go │ │ │ │ ├── swagger.json │ │ │ │ └── swagger.yaml │ │ │ └── utility │ │ │ ├── kafka │ │ │ ├── consumer.go │ │ │ ├── kafka.go │ │ │ └── producer.go │ │ │ ├── logger │ │ │ └── logger.go │ │ │ ├── rest │ │ │ ├── rest.go │ │ │ └── rest_test.go │ │ │ └── str_process │ │ │ └── str_process.go │ ├── config │ │ └── server_configuration.go │ ├── main.go │ ├── middleware │ │ ├── auth.go │ │ ├── cors_middleware.go │ │ └── middleware.go │ └── router │ │ └── router.go └── watcher.conf ├── order ├── .dockerignore ├── .env.example ├── .gitignore ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── docker-compose.yml ├── go.mod ├── src │ ├── app │ │ └── v1 │ │ │ ├── api │ │ │ └── health │ │ │ │ ├── controller │ │ │ │ └── health.go │ │ │ │ ├── entity │ │ │ │ └── http.go │ │ │ │ └── service │ │ │ │ └── health.go │ │ │ ├── routes │ │ │ ├── docs.go │ │ │ ├── health.go │ │ │ └── routes.go │ │ │ ├── swagger │ │ │ └── docs │ │ │ │ ├── docs.go │ │ │ │ ├── swagger.json │ │ │ │ └── swagger.yaml │ │ │ └── utility │ │ │ ├── kafka │ │ │ ├── consumer.go │ │ │ ├── kafka.go │ │ │ └── producer.go │ │ │ ├── logger │ │ │ └── logger.go │ │ │ ├── rest │ │ │ ├── rest.go │ │ │ └── rest_test.go │ │ │ └── str_process │ │ │ └── str_process.go │ ├── config │ │ └── server_configuration.go │ ├── main.go │ ├── middleware │ │ ├── auth.go │ │ ├── cors_middleware.go │ │ └── middleware.go │ └── router │ │ └── router.go └── watcher.conf ├── payment ├── .dockerignore ├── .env.example ├── .gitignore ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── docker-compose.yml ├── go.mod ├── src │ ├── app │ │ └── v1 │ │ │ ├── api │ │ │ ├── health │ │ │ │ ├── controller │ │ │ │ │ └── health.go │ │ │ │ ├── entity │ │ │ │ │ └── http.go │ │ │ │ └── service │ │ │ │ │ └── health.go │ │ │ ├── login │ │ │ │ ├── controller │ │ │ │ │ └── user.go │ │ │ │ ├── entity │ │ │ │ │ ├── event.go │ │ │ │ │ └── http.go │ │ │ │ ├── event │ │ │ │ │ └── event.go │ │ │ │ └── service │ │ │ │ │ └── user.go │ │ │ ├── order │ │ │ │ ├── controller │ │ │ │ │ └── order.go │ │ │ │ ├── entity │ │ │ │ │ ├── event.go │ │ │ │ │ └── http.go │ │ │ │ ├── event │ │ │ │ │ └── event.go │ │ │ │ └── service │ │ │ │ │ └── order.go │ │ │ ├── payment │ │ │ │ ├── controller │ │ │ │ │ └── payment.go │ │ │ │ ├── entity │ │ │ │ │ ├── event.go │ │ │ │ │ ├── general.go │ │ │ │ │ └── http.go │ │ │ │ ├── event │ │ │ │ │ └── event.go │ │ │ │ └── service │ │ │ │ │ ├── consumer.go │ │ │ │ │ └── payment.go │ │ │ └── user │ │ │ │ ├── controller │ │ │ │ └── user.go │ │ │ │ ├── entity │ │ │ │ ├── event.go │ │ │ │ └── http.go │ │ │ │ ├── event │ │ │ │ └── event.go │ │ │ │ └── service │ │ │ │ └── user.go │ │ │ ├── routes │ │ │ ├── docs.go │ │ │ ├── health.go │ │ │ ├── order.go │ │ │ ├── payment.go │ │ │ ├── routes.go │ │ │ └── user.go │ │ │ ├── swagger │ │ │ └── docs │ │ │ │ ├── docs.go │ │ │ │ ├── swagger.json │ │ │ │ └── swagger.yaml │ │ │ └── utility │ │ │ ├── kafka │ │ │ ├── consumer.go │ │ │ ├── kafka.go │ │ │ └── producer.go │ │ │ ├── logger │ │ │ └── logger.go │ │ │ ├── rest │ │ │ ├── rest.go │ │ │ └── rest_test.go │ │ │ └── str_process │ │ │ └── str_process.go │ ├── config │ │ └── server_configuration.go │ ├── main.go │ ├── middleware │ │ ├── auth.go │ │ ├── cors_middleware.go │ │ └── middleware.go │ └── router │ │ └── router.go └── watcher.conf └── user ├── .dockerignore ├── .env.example ├── .gitignore ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── docker-compose.yml ├── go.mod ├── src ├── app │ └── v1 │ │ ├── api │ │ ├── health │ │ │ ├── controller │ │ │ │ └── health.go │ │ │ ├── entity │ │ │ │ └── http.go │ │ │ └── service │ │ │ │ └── health.go │ │ ├── login │ │ │ ├── controller │ │ │ │ └── user.go │ │ │ ├── entity │ │ │ │ ├── event.go │ │ │ │ └── http.go │ │ │ ├── event │ │ │ │ └── event.go │ │ │ └── service │ │ │ │ └── user.go │ │ ├── order │ │ │ ├── controller │ │ │ │ └── order.go │ │ │ ├── entity │ │ │ │ ├── event.go │ │ │ │ └── http.go │ │ │ ├── event │ │ │ │ └── event.go │ │ │ └── service │ │ │ │ └── order.go │ │ ├── payment │ │ │ ├── controller │ │ │ │ └── payment.go │ │ │ ├── entity │ │ │ │ ├── event.go │ │ │ │ ├── general.go │ │ │ │ └── http.go │ │ │ ├── event │ │ │ │ └── event.go │ │ │ └── service │ │ │ │ ├── consumer.go │ │ │ │ └── payment.go │ │ └── user │ │ │ ├── controller │ │ │ └── user.go │ │ │ ├── entity │ │ │ ├── event.go │ │ │ └── http.go │ │ │ ├── event │ │ │ └── event.go │ │ │ └── service │ │ │ └── user.go │ │ ├── routes │ │ ├── docs.go │ │ ├── health.go │ │ ├── order.go │ │ ├── payment.go │ │ ├── routes.go │ │ └── user.go │ │ ├── swagger │ │ └── docs │ │ │ ├── docs.go │ │ │ ├── swagger.json │ │ │ └── swagger.yaml │ │ └── utility │ │ ├── kafka │ │ ├── consumer.go │ │ ├── kafka.go │ │ └── producer.go │ │ ├── logger │ │ └── logger.go │ │ ├── rest │ │ ├── rest.go │ │ └── rest_test.go │ │ └── str_process │ │ └── str_process.go ├── config │ └── server_configuration.go ├── main.go ├── middleware │ ├── auth.go │ ├── cors_middleware.go │ └── middleware.go └── router │ └── router.go └── watcher.conf /.gitignore: -------------------------------------------------------------------------------- 1 | # MAC OS CACHE 2 | .DS_Store 3 | 4 | # BINARY 5 | *.out 6 | *.exe 7 | *.exe~ 8 | *.dll 9 | *.so 10 | *.dylib 11 | 12 | # TEST 13 | *.test 14 | 15 | # ENV FOLDER 16 | .env 17 | env 18 | 19 | 20 | # Misc 21 | .idea 22 | src/.DS_Store 23 | go-pckg/* 24 | src/vendor/* 25 | coverage.out 26 | mydb 27 | 28 | main 29 | vendor 30 | .tmp 31 | tmp 32 | 33 | # qa_test 34 | /qa_test/reports/* 35 | /qa_test/node_modules 36 | /qa_test/package-lock.json 37 | /qa_test/.nyc_output 38 | 39 | # go sum 40 | database/data 41 | logger/mongo 42 | mongo 43 | 44 | choreography/data 45 | orchestration/data 46 | dependecies/database/choreography/data/ 47 | dependecies/database/orchestration/data/ 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SAGAS PATTERN 2 | Sagas pattern example my version, this project written in golang 3 | 4 | ## Tree 5 | ``` 6 | . 7 | ├── choreography 8 | │   ├── README.md 9 | │   ├── data 10 | │   ├── docker-compose.yml 11 | │   ├── svc_api 12 | │   ├── svc_order 13 | │   ├── svc_payment 14 | │   └── svc_users 15 | ├── dependecies 16 | │   ├── consul 17 | │   ├── database 18 | │   ├── kafka 19 | │   ├── krakend 20 | │   └── logger 21 | ├── docs 22 | │   ├── choreography 23 | │   └── orchestration 24 | └── orchestration 25 | ├── README.md 26 | ├── data 27 | ├── docker-compose.yml 28 | ├── orchestrator 29 | ├── order 30 | ├── payment 31 | └── user 32 | ``` 33 | 34 | ## Dependencies 35 | For the complete development needed, you can look for it in the dependencies 36 | 37 | ## Instalation 38 | ### API-Gateway (Krakend) 39 | ### Kafka Broker 40 | ### Database 41 | ### Cinlog History Logger 42 | -------------------------------------------------------------------------------- /choreography/svc_auth/.dockerignore: -------------------------------------------------------------------------------- 1 | 2 | mydb 3 | .env 4 | tmp -------------------------------------------------------------------------------- /choreography/svc_auth/.gitignore: -------------------------------------------------------------------------------- 1 | # MAC OS CACHE 2 | .DS_Store 3 | 4 | # BINARY 5 | *.out 6 | *.exe 7 | *.exe~ 8 | *.dll 9 | *.so 10 | *.dylib 11 | 12 | # TEST 13 | *.test 14 | 15 | # ENV FOLDER 16 | .env 17 | env 18 | 19 | 20 | # Misc 21 | .idea 22 | src/.DS_Store 23 | go-pckg/* 24 | src/vendor/* 25 | coverage.out 26 | mydb 27 | 28 | main 29 | vendor 30 | .tmp 31 | tmp 32 | 33 | # qa_test 34 | /qa_test/reports/* 35 | /qa_test/node_modules 36 | /qa_test/package-lock.json 37 | /qa_test/.nyc_output 38 | 39 | # go sum 40 | go.sum 41 | db-init 42 | mongo 43 | secret 44 | -------------------------------------------------------------------------------- /choreography/svc_auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:latest AS builder 2 | 3 | WORKDIR /app 4 | COPY . . 5 | 6 | RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o main -ldflags '-w -s' src/main.go 7 | 8 | ############################ 9 | # STEP 2 build a small image 10 | ############################ 11 | FROM scratch 12 | 13 | COPY --from=builder /app /usr/bin -------------------------------------------------------------------------------- /choreography/svc_auth/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Sofyan Saputra 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /choreography/svc_auth/Makefile: -------------------------------------------------------------------------------- 1 | # Build And Development 2 | test: 3 | @go test -v -cover ./... 4 | 5 | depend: 6 | @go get github.com/ralali/event-api 7 | 8 | devel: 9 | @air -c watcher.conf 10 | 11 | build: 12 | @go build -o bgin src/main.go 13 | 14 | run: 15 | @go run src/main.go 16 | 17 | production: 18 | @go run src/main.go -e production 19 | 20 | docker-stop: 21 | @docker-compose down 22 | 23 | docker-image: 24 | @docker build . -t bigevent_api 25 | 26 | docker-run: 27 | @docker-compose up 28 | 29 | .PHONY: test depend build run stop docker docker-stop docker-image docker-run devel 30 | -------------------------------------------------------------------------------- /choreography/svc_auth/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | svc_auth: 4 | image: meongbego/svc_auths 5 | restart: always 6 | ports: 7 | - 80:80 8 | environment: 9 | - SERVER_ADDRESS=0.0.0.0 10 | - SERVER_PORT=80 11 | - SERVER_TIMEZONE=Asia/Jakarta 12 | - APP_NAME=gateway 13 | - KAFKA_HOST=localhost 14 | - KAFKA_PORT=9092 15 | - SWAGGER_SERVER_ADDRESS=http://0.0.0.0 16 | - LOGGER_URL=logger:3000 17 | command: /usr/bin/main -e production 18 | 19 | -------------------------------------------------------------------------------- /choreography/svc_auth/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/sofyan48/svc_auth 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/Shopify/sarama v1.26.3 7 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 8 | github.com/dgrijalva/jwt-go v3.2.0+incompatible 9 | github.com/garyburd/redigo v1.6.0 10 | github.com/gin-gonic/gin v1.6.3 11 | github.com/google/uuid v1.1.1 12 | github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a 13 | github.com/jinzhu/gorm v1.9.12 14 | github.com/joho/godotenv v1.3.0 15 | github.com/sofyan48/go-cinlog v1.0.0 16 | github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 17 | github.com/swaggo/gin-swagger v1.2.0 18 | github.com/swaggo/swag v1.6.5 19 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d 20 | gopkg.in/oauth2.v3 v3.12.0 21 | ) 22 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/api/authorization/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | // AuhtorizerClientResponse ... 4 | type AuhtorizerClientResponse struct { 5 | Expire interface{} `json:"expire_at"` 6 | Issuer interface{} `json:"issuer"` 7 | Secret interface{} `json:"secret"` 8 | Session *AuhtorizerClientResponseSession `json:"session"` 9 | } 10 | 11 | // AuhtorizerClientResponseSession ... 12 | type AuhtorizerClientResponseSession struct { 13 | Level string `json:"level"` 14 | } 15 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/api/client/controller/client.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/sofyan48/svc_auth/src/app/v1/api/client/entity" 8 | "github.com/sofyan48/svc_auth/src/app/v1/api/client/service" 9 | "github.com/sofyan48/svc_auth/src/utils/rest" 10 | ) 11 | 12 | // ClientController ... 13 | type ClientController struct { 14 | Service service.ClientServiceInterface 15 | } 16 | 17 | // ClientControllerHandler ... 18 | func ClientControllerHandler() *ClientController { 19 | return &ClientController{ 20 | Service: service.ClientServiceHandler(), 21 | } 22 | } 23 | 24 | // ClientControllerInterface ... 25 | type ClientControllerInterface interface { 26 | PostClient(context *gin.Context) 27 | } 28 | 29 | // PostClient .. 30 | func (ctrl *ClientController) PostClient(context *gin.Context) { 31 | payload := &entity.ClientRequest{} 32 | err := context.ShouldBind(payload) 33 | if err != nil { 34 | rest.ResponseMessages(context, http.StatusBadRequest, "Bad Request") 35 | return 36 | } 37 | result, err := ctrl.Service.CreateClient(payload) 38 | if err != nil { 39 | rest.ResponseMessages(context, http.StatusInternalServerError, err.Error()) 40 | return 41 | } 42 | rest.ResponseData(context, http.StatusOK, result) 43 | return 44 | } 45 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/api/client/entity/database.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // Clients ... 6 | type Clients struct { 7 | ID int64 `gorm:"column:id_client;primary_key" json:"id_client"` 8 | ClientName string `gorm:"column:client_name" json:"client_name"` 9 | ClientKey string `gorm:"column:client_key" json:"client_key"` 10 | ClientSecret string `gorm:"column:client_secret" json:"client_secret"` 11 | ClientPrivateKey string `gorm:"column:client_private_key" json:"client_private_key"` 12 | ClientPUblicKey string `gorm:"column:client_public_key" json:"client_public_key"` 13 | IsActive bool `gorm:"column:is_active" json:"is_active"` 14 | IsFirtsParty bool `gorm:"column:is_first_party" json:"is_first_party"` 15 | RedirectUrls string `gorm:"column:redirect_url" json:"redirect_url"` 16 | CreatedAt *time.Time `gorm:"column:created_at;default:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" json:"created_at"` 17 | UpdatedAt *time.Time `gorm:"column:update_at;default:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" json:"updated_at"` 18 | DeletedAt *time.Time `gorm:"column:deleted_at" json:"deleted_at"` 19 | } 20 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/api/client/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // ClientRequest ... 6 | type ClientRequest struct { 7 | ClientName string `json:"client_name"` 8 | IsFirstParty bool `json:"is_first_party"` 9 | RedirectURIs string `json:"redirect_url"` 10 | } 11 | 12 | // ClientResponses ... 13 | type ClientResponses struct { 14 | ID int64 `gorm:"column:id_client;primary_key" json:"id_client"` 15 | ClientName string `gorm:"column:client_name" json:"client_name"` 16 | ClientKey string `gorm:"column:client_key" json:"client_key"` 17 | ClientSecret string `gorm:"column:client_secret" json:"client_secret"` 18 | ClientPUblicKey string `gorm:"column:client_public_key" json:"client_public_key"` 19 | IsActive bool `gorm:"column:is_active" json:"is_active"` 20 | IsFirtsParty bool `gorm:"column:is_first_party" json:"is_first_party"` 21 | RedirectUrls string `gorm:"column:redirect_url" json:"redirect_url"` 22 | CreatedAt *time.Time `gorm:"column:created_at;default:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" json:"created_at"` 23 | UpdatedAt *time.Time `gorm:"column:update_at;default:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" json:"updated_at"` 24 | DeletedAt *time.Time `gorm:"column:deleted_at" json:"deleted_at"` 25 | } 26 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/api/health/controller/health.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/sofyan48/svc_auth/src/app/v1/api/health/service" 8 | "github.com/sofyan48/svc_auth/src/utils/rest" 9 | ) 10 | 11 | // HealthController types 12 | type HealthController struct { 13 | Service service.HealthServiceInterface 14 | } 15 | 16 | // HealthControllerHandler ... 17 | func HealthControllerHandler() *HealthController { 18 | return &HealthController{ 19 | Service: service.HealthServiceHandler(), 20 | } 21 | } 22 | 23 | // HealthControllerInterface ... 24 | type HealthControllerInterface interface { 25 | Health(context *gin.Context) 26 | } 27 | 28 | // Health params 29 | // @contex: gin Context 30 | func (ctrl *HealthController) Health(context *gin.Context) { 31 | data := ctrl.Service.HealthService() 32 | rest.ResponseData(context, http.StatusOK, data) 33 | return 34 | } 35 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/api/health/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // HealtResponse ... 6 | type HealtResponse struct { 7 | Status string `json:"status"` 8 | CreatedAt *time.Time `json:"created_at"` 9 | } 10 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/api/health/service/health.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/sofyan48/svc_auth/src/app/v1/api/health/entity" 7 | ) 8 | 9 | // HealthService ... 10 | type HealthService struct{} 11 | 12 | // HealthServiceHandler ... 13 | func HealthServiceHandler() *HealthService { 14 | return &HealthService{} 15 | } 16 | 17 | // HealthServiceInterface ... 18 | type HealthServiceInterface interface { 19 | HealthService() *entity.HealtResponse 20 | } 21 | 22 | // HealthService ... 23 | func (service *HealthService) HealthService() *entity.HealtResponse { 24 | now := time.Now() 25 | result := &entity.HealtResponse{} 26 | result.Status = "OK" 27 | result.CreatedAt = &now 28 | return result 29 | } 30 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/api/login/controller/login.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/sofyan48/svc_auth/src/app/v1/api/login/entity" 8 | "github.com/sofyan48/svc_auth/src/app/v1/api/login/service" 9 | "github.com/sofyan48/svc_auth/src/utils/rest" 10 | ) 11 | 12 | // LoginController ... 13 | type LoginController struct { 14 | Service service.LoginServiceInterface 15 | } 16 | 17 | // LoginControllerHandler ... 18 | func LoginControllerHandler() *LoginController { 19 | return &LoginController{ 20 | Service: service.LoginServiceHandler(), 21 | } 22 | } 23 | 24 | // LoginControllerInterface ... 25 | type LoginControllerInterface interface { 26 | PostLoginClient(context *gin.Context) 27 | } 28 | 29 | // PostLoginClient ... 30 | func (handler *LoginController) PostLoginClient(context *gin.Context) { 31 | payload := &entity.LoginRequest{} 32 | err := context.ShouldBind(payload) 33 | if err != nil { 34 | rest.ResponseMessages(context, http.StatusBadRequest, "Bad Request") 35 | return 36 | } 37 | result, err := handler.Service.PostLogin(payload, context) 38 | 39 | if err != nil { 40 | rest.ResponseMessages(context, http.StatusInternalServerError, err.Error()) 41 | return 42 | } 43 | rest.ResponseData(context, http.StatusOK, result) 44 | } 45 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/api/login/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | type LoginResponse struct { 4 | Type string `json:"token_type"` 5 | AccessToken string `json:"access_token"` 6 | Expires int64 `json:"expires_at"` 7 | Refresh string `json:"refresh_token"` 8 | } 9 | 10 | type LoginRequest struct { 11 | Username string `json:"username"` 12 | Password string `json:"password"` 13 | } 14 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/api/token/controller/token.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/sofyan48/svc_auth/src/app/v1/api/token/entity" 8 | "github.com/sofyan48/svc_auth/src/app/v1/api/token/service" 9 | "github.com/sofyan48/svc_auth/src/utils/rest" 10 | ) 11 | 12 | // TokenController ... 13 | type TokenController struct { 14 | Service service.TokenServiceInterface 15 | } 16 | 17 | // TokenControllerHandler ... 18 | func TokenControllerHandler() *TokenController { 19 | return &TokenController{ 20 | Service: service.TokenServiceHandler(), 21 | } 22 | } 23 | 24 | // TokenControllerInterface ... 25 | type TokenControllerInterface interface { 26 | PostTokenClient(context *gin.Context) 27 | } 28 | 29 | // PostTokenClient ... 30 | func (handler *TokenController) PostTokenClient(context *gin.Context) { 31 | payload := &entity.ClientCredentialRequest{} 32 | err := context.ShouldBind(payload) 33 | if err != nil { 34 | rest.ResponseMessages(context, http.StatusBadRequest, "Bad Request") 35 | return 36 | } 37 | result, err := handler.Service.ClientCredential(payload) 38 | if err != nil { 39 | rest.ResponseMessages(context, http.StatusInternalServerError, err.Error()) 40 | return 41 | } 42 | rest.ResponseData(context, http.StatusOK, result) 43 | } 44 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/api/token/entity/general.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "github.com/dgrijalva/jwt-go" 4 | 5 | type AuthDataModels struct { 6 | Level string `json:"level"` 7 | } 8 | 9 | type Claims struct { 10 | Session string `json:"session"` 11 | jwt.StandardClaims 12 | } 13 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/api/token/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | // ClientCredentialRequest ... 4 | type ClientCredentialRequest struct { 5 | ClientKey string `json:"client_key"` 6 | ClientSecret string `json:"client_secret"` 7 | } 8 | 9 | type ClientCredentialResponse struct { 10 | Type string `json:"token_type"` 11 | AccessToken string `json:"access_token"` 12 | Expires int64 `json:"expires_at"` 13 | } 14 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/routes/authorization.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // AUTHROUTES ... 6 | const AUTHROUTES = VERSION + "/authorization" 7 | 8 | func (rLoader *V1RouterLoader) initAuthService(router *gin.Engine) { 9 | group := router.Group(AUTHROUTES) 10 | group.GET("/client", rLoader.Authorizer.PostClaimsClient) 11 | group.GET("/user", rLoader.Authorizer.PostClaimsUser) 12 | } 13 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/routes/client.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // CLIENTROUTES ... 6 | const CLIENTROUTES = VERSION + "/client" 7 | 8 | func (rLoader *V1RouterLoader) initClient(router *gin.Engine) { 9 | group := router.Group(CLIENTROUTES) 10 | group.POST("", rLoader.Client.PostClient) 11 | } 12 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/routes/docs.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | swaggerFiles "github.com/swaggo/files" 6 | ginSwagger "github.com/swaggo/gin-swagger" 7 | 8 | _ "github.com/sofyan48/svc_auth/src/app/v1/swagger/docs" 9 | ) 10 | 11 | // DOCROUTES ... 12 | const DOCROUTES = VERSION + "/docs" 13 | 14 | func (rLoader *V1RouterLoader) initDocs(router *gin.Engine) { 15 | group := router.Group(DOCROUTES) 16 | url := ginSwagger.URL("swagger/doc.json") 17 | group.GET("/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url)) 18 | } 19 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/routes/health.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // HEALTHROUTES ... 8 | const HEALTHROUTES = VERSION + "/health" 9 | 10 | func (rLoader *V1RouterLoader) initHealth(router *gin.Engine) { 11 | group := router.Group(HEALTHROUTES) 12 | group.GET("", rLoader.Health.Health) 13 | } 14 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/routes/login.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // CLIENTROUTES ... 6 | const LOGINROUTES = VERSION + "/login" 7 | 8 | func (rLoader *V1RouterLoader) initLogin(router *gin.Engine) { 9 | group := router.Group(LOGINROUTES) 10 | group.POST("", rLoader.Middleware.AuthToken(), rLoader.Login.PostLoginClient) 11 | } 12 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/routes/token.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // TOKENROUTES ... 6 | const TOKENROUTES = VERSION + "/token" 7 | 8 | func (rLoader *V1RouterLoader) initToken(router *gin.Engine) { 9 | group := router.Group(TOKENROUTES) 10 | group.POST("/client", rLoader.Token.PostTokenClient) 11 | } 12 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/swagger/docs/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "contact": {}, 5 | "license": {} 6 | }, 7 | "paths": {} 8 | } -------------------------------------------------------------------------------- /choreography/svc_auth/src/app/v1/swagger/docs/swagger.yaml: -------------------------------------------------------------------------------- 1 | info: 2 | contact: {} 3 | license: {} 4 | paths: {} 5 | swagger: "2.0" 6 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/config/server_configuration.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/joho/godotenv" 8 | "github.com/sofyan48/svc_auth/src/middleware" 9 | ) 10 | 11 | // SetupEngine server router configuration 12 | func SetupEngine(env string) *gin.Engine { 13 | configEnvironment(env) 14 | defaultMiddleware := middleware.DefaultMiddlewareHandler() 15 | // configEnvironment(env) 16 | router := gin.Default() 17 | router.Use(defaultMiddleware.CORSMiddleware()) 18 | return router 19 | } 20 | 21 | // ConfigEnvironment ... 22 | func configEnvironment(env string) { 23 | switch env { 24 | case "development": 25 | err := godotenv.Load() 26 | if err != nil { 27 | log.Fatal("Error loading .env file") 28 | } 29 | case "production": 30 | gin.SetMode(gin.ReleaseMode) 31 | log.Println("Engine Running") 32 | default: 33 | err := godotenv.Load() 34 | if err != nil { 35 | log.Fatal("Error loading .env file") 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/sofyan48/svc_auth/src/config" 9 | 10 | apiRouter "github.com/sofyan48/svc_auth/src/router" 11 | ) 12 | 13 | func main() { 14 | environment := flag.String("e", "development", "") 15 | flag.Usage = func() { 16 | fmt.Println("Usage: server -e {mode}") 17 | os.Exit(1) 18 | } 19 | flag.Parse() 20 | startApp(*environment) 21 | } 22 | 23 | func startApp(env string) { 24 | router := config.SetupEngine(env) 25 | apiRouter.LoadRouter(router) 26 | serverHost := os.Getenv("SERVER_ADDRESS") 27 | serverPort := os.Getenv("SERVER_PORT") 28 | serverString := fmt.Sprintf("%s:%s", serverHost, serverPort) 29 | router.Run(serverString) 30 | } 31 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/middleware/cors_middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // CORSMiddleware Implementing CORS 8 | // return: gin HandlerFunc 9 | func (m *DefaultMiddleware) CORSMiddleware() gin.HandlerFunc { 10 | return func(c *gin.Context) { 11 | c.Writer.Header().Set("Access-Control-Allow-Origin", "*") 12 | c.Writer.Header().Set("Access-Control-Max-Age", "86400") 13 | c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE") 14 | c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") 15 | c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length") 16 | c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") 17 | if c.Request.Method == "OPTIONS" { 18 | c.AbortWithStatus(200) 19 | } else { 20 | c.Next() 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/middleware/middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/sofyan48/svc_auth/src/app/v1/api/client/repository" 6 | "github.com/sofyan48/svc_auth/src/utils/redis" 7 | ) 8 | 9 | // DefaultMiddleware types 10 | type DefaultMiddleware struct { 11 | Client repository.ClientRepositoryInterface 12 | Redis redis.RedisLibInterface 13 | } 14 | 15 | func DefaultMiddlewareHandler() *DefaultMiddleware { 16 | return &DefaultMiddleware{ 17 | Client: repository.ClientRepositoryHandler(), 18 | Redis: redis.RedisLibHandler(), 19 | } 20 | } 21 | 22 | type DefaultMiddlewareInterface interface { 23 | CORSMiddleware() gin.HandlerFunc 24 | GetToken(context *gin.Context) string 25 | AuthToken() gin.HandlerFunc 26 | GetSessionClaim(ctx *gin.Context) (map[string]interface{}, error) 27 | GetSessionClaimByToken(token string) (map[string]interface{}, error) 28 | } 29 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/router/router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | v1 "github.com/sofyan48/svc_auth/src/app/v1/routes" 6 | ) 7 | 8 | // LoadRouter params 9 | // @routers: gin.Engine 10 | func LoadRouter(routers *gin.Engine) { 11 | version1 := v1.V1RouterLoaderHandler() 12 | version1.V1Routes(routers) 13 | } 14 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/utils/kafka/consumer.go: -------------------------------------------------------------------------------- 1 | package kafka 2 | 3 | import ( 4 | "log" 5 | "os" 6 | 7 | "github.com/Shopify/sarama" 8 | ) 9 | 10 | // InitConsumer ... 11 | func (kafka *KafkaLibrary) InitConsumer(group string) (sarama.ConsumerGroup, error) { 12 | configKafka := kafka.initConsumerConfig("", "") 13 | kafkaHost := os.Getenv("KAFKA_HOST") 14 | kafkaPort := os.Getenv("KAFKA_PORT") 15 | version, err := sarama.ParseKafkaVersion(os.Getenv("KAFKA_VERSION")) 16 | if err != nil { 17 | log.Panicf("Error parsing Kafka version: %v", err) 18 | } 19 | configKafka.Version = version 20 | return sarama.NewConsumerGroup([]string{kafkaHost + ":" + kafkaPort}, group, configKafka) 21 | } 22 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/utils/rest/rest.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // Respons types 8 | type Respons struct { 9 | Status int `json:"status"` 10 | Meta interface{} `json:"meta"` 11 | Results interface{} `json:"results"` 12 | } 13 | 14 | // ResponseList params 15 | // @context: *gin.Context 16 | // status: int 17 | // payload: interface{} 18 | func ResponseList(context *gin.Context, status int, payload, meta interface{}) { 19 | var res Respons 20 | res.Status = status 21 | res.Results = payload 22 | res.Meta = meta 23 | context.JSON(status, res) 24 | return 25 | } 26 | 27 | // ResponseData params 28 | // @context: *gin.Context 29 | // status: int 30 | // payload: interface{} 31 | func ResponseData(context *gin.Context, status int, payload interface{}) { 32 | context.JSON(status, payload) 33 | return 34 | } 35 | 36 | // ResponseMessages params 37 | // @context: *gin.Context 38 | // status: int 39 | // msg: string 40 | func ResponseMessages(context *gin.Context, status int, msg string) { 41 | context.JSON(status, gin.H{ 42 | "messages": msg, 43 | }) 44 | return 45 | } 46 | -------------------------------------------------------------------------------- /choreography/svc_auth/src/utils/rest/rest_test.go: -------------------------------------------------------------------------------- 1 | package rest 2 | -------------------------------------------------------------------------------- /choreography/svc_auth/watcher.conf: -------------------------------------------------------------------------------- 1 | root = "." 2 | watch_dir = "src" 3 | tmp_dir = "tmp" 4 | 5 | [build] 6 | cmd = "go build -o ./tmp/main src/main.go" 7 | bin = "tmp/main" 8 | log = "air_errors.log" 9 | include_ext = ["go", "tpl", "tmpl", "html"] 10 | exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules", "migration", "secret"] 11 | delay = 1500 # ms 12 | 13 | [log] 14 | time = false 15 | 16 | [color] 17 | main = "magenta" 18 | watcher = "cyan" 19 | build = "yellow" 20 | runner = "green" 21 | # app = "white" -------------------------------------------------------------------------------- /choreography/svc_order/.dockerignore: -------------------------------------------------------------------------------- 1 | go.sum 2 | .env -------------------------------------------------------------------------------- /choreography/svc_order/.env.example: -------------------------------------------------------------------------------- 1 | #################################################################### 2 | # SERVICE CONFIGURATION 3 | #################################################################### 4 | APP_NAME=users 5 | KAFKA_HOST=127.0.0.1 6 | KAFKA_PORT=9092 7 | 8 | #################################################################### 9 | # DATABASE CONFIGURATION 10 | #################################################################### 11 | DB_USER=root 12 | DB_PASSWORD= 13 | DB_HOST=localhost 14 | DB_PORT=26257 15 | DB_NAME=user 16 | ######################## READ DATABASE ############################# 17 | DB_USER_READ=root 18 | DB_PASSWORD_READ= 19 | DB_HOST_READ=localhost 20 | DB_PORT_READ=26257 21 | DB_NAME_READ=user 22 | 23 | #################################################################### 24 | # LOGGER CONFIGURATION 25 | #################################################################### 26 | LOGGER_URL=localhost:3000 27 | 28 | -------------------------------------------------------------------------------- /choreography/svc_order/.gitignore: -------------------------------------------------------------------------------- 1 | # MAC OS CACHE 2 | .DS_Store 3 | 4 | # BINARY 5 | *.out 6 | *.exe 7 | *.exe~ 8 | *.dll 9 | *.so 10 | *.dylib 11 | 12 | # TEST 13 | *.test 14 | 15 | # ENV FOLDER 16 | .env 17 | env 18 | 19 | 20 | # Misc 21 | .idea 22 | src/.DS_Store 23 | go-pckg/* 24 | src/vendor/* 25 | coverage.out 26 | mydb 27 | 28 | main 29 | vendor 30 | .tmp 31 | tmp 32 | 33 | # qa_test 34 | /qa_test/reports/* 35 | /qa_test/node_modules 36 | /qa_test/package-lock.json 37 | /qa_test/.nyc_output 38 | 39 | # go sum 40 | database/data 41 | logger/mongo 42 | mongo 43 | go.sum -------------------------------------------------------------------------------- /choreography/svc_order/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:latest AS builder 2 | 3 | WORKDIR /app 4 | COPY . . 5 | 6 | RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o main -ldflags '-w -s' src/main.go 7 | 8 | ############################ 9 | # STEP 2 build a small image 10 | ############################ 11 | FROM scratch 12 | 13 | COPY --from=builder /app /usr/bin -------------------------------------------------------------------------------- /choreography/svc_order/README.md: -------------------------------------------------------------------------------- 1 | # ORDER SAGA EXAMPLE SERVICE 2 | 3 | ## Getting Started -------------------------------------------------------------------------------- /choreography/svc_order/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/sofyan48/svc_order 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/Shopify/sarama v1.26.1 7 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 8 | github.com/gin-gonic/gin v1.6.3 9 | github.com/google/uuid v1.1.1 10 | github.com/hashicorp/consul/api v1.4.0 11 | github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a 12 | github.com/jinzhu/gorm v1.9.12 13 | github.com/joho/godotenv v1.3.0 14 | github.com/sofyan48/go-cinlog v1.0.0 15 | github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 16 | github.com/swaggo/gin-swagger v1.2.0 17 | github.com/swaggo/swag v1.6.5 18 | ) 19 | -------------------------------------------------------------------------------- /choreography/svc_order/migration/20200410210842_tb_order_type.down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE `tb_order_type`; -------------------------------------------------------------------------------- /choreography/svc_order/migration/20200410210842_tb_order_type.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE tb_order_type ( 2 | id_order_type INT8 NOT NULL DEFAULT unique_rowid(), 3 | order_type VARCHAR NOT NULL, 4 | created_at DATE NOT NULL DEFAULT now():::DATE, 5 | updated_at DATE NOT NULL DEFAULT now():::DATE, 6 | deleted_at DATE NULL, 7 | CONSTRAINT "primary" PRIMARY KEY (id_order_type ASC), 8 | FAMILY "primary" (id_order_type, order_type, created_at, updated_at, deleted_at) 9 | ); -------------------------------------------------------------------------------- /choreography/svc_order/migration/20200410210900_tb_order_status.down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE `tb_order_status`; -------------------------------------------------------------------------------- /choreography/svc_order/migration/20200410210900_tb_order_status.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE tb_order_status ( 2 | id_order_status INT8 NOT NULL DEFAULT unique_rowid(), 3 | nm_status_order VARCHAR NOT NULL, 4 | created_at DATE NOT NULL DEFAULT now():::DATE, 5 | updated_at DATE NOT NULL DEFAULT now():::DATE, 6 | deleted_at DATE NULL, 7 | CONSTRAINT "primary" PRIMARY KEY (id_order_status ASC), 8 | FAMILY "primary" (id_order_status, nm_status_order, created_at, updated_at, deleted_at) 9 | ); 10 | -------------------------------------------------------------------------------- /choreography/svc_order/migration/20200410210904_tb_orders.down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE `tb_orders`; -------------------------------------------------------------------------------- /choreography/svc_order/migration/20200410210904_tb_orders.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE tb_orders ( 2 | id_order INT8 NOT NULL DEFAULT unique_rowid(), 3 | uuid VARCHAR NOT NULL, 4 | order_number VARCHAR NOT NULL, 5 | user_uuid VARCHAR NOT NULL, 6 | id_order_type INT8 NOT NULL, 7 | id_order_status INT8 NOT NULL, 8 | created_at DATE NOT NULL DEFAULT now():::DATE, 9 | updated_at DATE NOT NULL DEFAULT now():::DATE, 10 | deleted_at DATE NULL, 11 | CONSTRAINT tb_orders_pk PRIMARY KEY (id_order ASC), 12 | UNIQUE INDEX tb_orders_un_uuid (uuid ASC), 13 | INDEX tb_orders_auto_index_tb_orders_fk (id_order_type ASC), 14 | INDEX tb_orders_auto_index_tb_orders_fk_payment_model (id_order_status ASC), 15 | FAMILY "primary" (id_order, uuid, order_number, user_uuid, id_order_type, id_order_status, created_at, updated_at, deleted_at) 16 | ); -------------------------------------------------------------------------------- /choreography/svc_order/src/app/v1/entity/api.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // OrderPayload Mapping 6 | type OrderPayload struct { 7 | OrderNumber string `json:"order_number"` 8 | UserUUID string `json:"uuid_user"` 9 | IDOrderType string `json:"id_order_type"` 10 | IDPaymentModel string `json:"id_payment_model"` 11 | } 12 | 13 | // OrderResponse Mapping 14 | type OrderResponse struct { 15 | UUID string `json:"uuid"` 16 | OrderNumber string `json:"order_number"` 17 | UserUUID string `json:"uuid_user"` 18 | IDOrderType string `json:"id_order_type"` 19 | IDOrderStatus string `json:"id_order_status"` 20 | CreatedAt *time.Time `gorm:"column:created_at;default:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" json:"created_at"` 21 | UpdatedAt *time.Time `gorm:"column:updated_at;default:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" json:"updated_at"` 22 | DeletedAt *time.Time `gorm:"column:deleted_at" json:"deleted_at"` 23 | } 24 | 25 | // StateFullFormatKafka ... 26 | type StateFullFormatKafka struct { 27 | UUID string `json:"__uuid" bson:"__uuid"` 28 | Action string `json:"__action" bson:"__action"` 29 | Data map[string]string `json:"data" bson:"data"` 30 | CreatedAt *time.Time `json:"created_at" bson:"created_at"` 31 | } 32 | -------------------------------------------------------------------------------- /choreography/svc_order/src/app/v1/entity/logger.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // LoggerEventHistory ... 6 | type LoggerEventHistory struct { 7 | UUID string `json:"__uuid"` 8 | Action string `json:"__action"` 9 | Offset uint64 `json:"__offset"` 10 | History []LoggerHistory `json:"history"` 11 | Status string `json:"status"` 12 | CreatedAt *time.Time `json:"created_at"` 13 | UpdateAt *time.Time `json:"update_at"` 14 | } 15 | 16 | // LoggerHistory ... 17 | type LoggerHistory struct { 18 | Data map[string]interface{} `json:"data"` 19 | } 20 | -------------------------------------------------------------------------------- /choreography/svc_order/src/app/v2/api/order/entity/event.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // OrderEvent ... 8 | type OrderEvent struct { 9 | UUID string `json:"__uuid" ` 10 | Action string `json:"__action"` 11 | Offset int64 `json:"__offset"` 12 | Data map[string]interface{} `json:"data"` 13 | Status string `json:"status"` 14 | CreatedAt *time.Time `json:"created_at"` 15 | } 16 | -------------------------------------------------------------------------------- /choreography/svc_order/src/app/v2/api/order/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // OrderRequest ... 6 | type OrderRequest struct { 7 | OrderNumber string `json:"order_number"` 8 | UserUUID string `json:"uuid_user"` 9 | IDOrderType string `json:"id_order_type"` 10 | IDOrderStatus string `json:"id_order_status"` 11 | IDPaymentStatus string `json:"id_payment_status"` 12 | IDPaymentModel string `json:"id_payment_model"` 13 | InquiryNumber string `json:"inquiry_number"` 14 | PaymentOrder string `json:"payment_order"` 15 | NMBank string `json:"nm_bank"` 16 | } 17 | 18 | // OrderResponses ... 19 | type OrderResponses struct { 20 | UUID string `json:"uuid"` 21 | CreatedAt *time.Time `json:"created_at"` 22 | Event *OrderEvent `json:"event"` 23 | } 24 | 25 | // Pagination ... 26 | type Pagination struct { 27 | Limit int `form:"limit" json:"limit"` 28 | Page int `form:"page" json:"page"` 29 | } 30 | -------------------------------------------------------------------------------- /choreography/svc_order/src/app/v2/api/order/event/event.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | "github.com/sofyan48/svc_order/src/app/v2/api/order/entity" 6 | "github.com/sofyan48/svc_order/src/utils/kafka" 7 | ) 8 | 9 | // ORDEREVENT ... 10 | const ORDEREVENT = "order" 11 | 12 | // OrderEvent ... 13 | type OrderEvent struct { 14 | Kafka kafka.KafkaLibraryInterface 15 | } 16 | 17 | // OrderEventHandler ... 18 | func OrderEventHandler() *OrderEvent { 19 | return &OrderEvent{ 20 | Kafka: kafka.KafkaLibraryHandler(), 21 | } 22 | } 23 | 24 | // OrderEventInterface ... 25 | type OrderEventInterface interface { 26 | OrderCreateEvent(data *entity.OrderEvent) (*entity.OrderEvent, error) 27 | } 28 | 29 | // OrderCreateEvent ... 30 | func (event *OrderEvent) OrderCreateEvent(data *entity.OrderEvent) (*entity.OrderEvent, error) { 31 | format := event.Kafka.GetStateFull() 32 | format.Action = data.Action 33 | format.CreatedAt = data.CreatedAt 34 | format.Data = data.Data 35 | format.UUID = uuid.New().String() 36 | data.UUID = format.UUID 37 | go event.Kafka.SendEvent(ORDEREVENT, format) 38 | data.Status = "QUEUE" 39 | return data, nil 40 | } 41 | -------------------------------------------------------------------------------- /choreography/svc_order/src/app/v2/routes/docs.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | swaggerFiles "github.com/swaggo/files" 6 | ginSwagger "github.com/swaggo/gin-swagger" 7 | 8 | _ "github.com/sofyan48/svc_order/src/app/v2/swagger/docs" 9 | ) 10 | 11 | // DOCROUTES ... 12 | const DOCROUTES = VERSION + "/docs" 13 | 14 | func (rLoader *V2RouterLoader) initDocs(router *gin.Engine) { 15 | group := router.Group(DOCROUTES) 16 | url := ginSwagger.URL("swagger/doc.json") 17 | group.GET("/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url)) 18 | } 19 | -------------------------------------------------------------------------------- /choreography/svc_order/src/app/v2/routes/order.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // ORDERROUTES ... 6 | const ORDERROUTES = VERSION + "/order" 7 | 8 | func (rLoader *V2RouterLoader) initOrder(router *gin.Engine) { 9 | group := router.Group(ORDERROUTES) 10 | group.POST("", rLoader.Order.OrderCreate) 11 | group.GET("/get/:uuid", rLoader.Order.GetOrderData) 12 | group.GET("/list", rLoader.Order.ListOrder) 13 | group.PUT(":uuid", rLoader.Order.UpdateOrder) 14 | group.DELETE(":uuid", rLoader.Order.DeleteOrder) 15 | } 16 | -------------------------------------------------------------------------------- /choreography/svc_order/src/app/v2/routes/routes.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | order "github.com/sofyan48/svc_order/src/app/v2/api/order/controller" 6 | "github.com/sofyan48/svc_order/src/middleware" 7 | ) 8 | 9 | // VERSION ... 10 | const VERSION = "v2" 11 | 12 | // V2RouterLoader types 13 | type V2RouterLoader struct { 14 | Middleware middleware.DefaultMiddleware 15 | Order order.OrderControllerInterface 16 | } 17 | 18 | // V2RouterLoaderHandler ... 19 | func V2RouterLoaderHandler() *V2RouterLoader { 20 | return &V2RouterLoader{ 21 | Order: order.OrderControllerHandler(), 22 | } 23 | } 24 | 25 | // V2RouterLoaderInterface ... 26 | type V2RouterLoaderInterface interface { 27 | V2Routes(router *gin.Engine) 28 | } 29 | 30 | // V2Routes Params 31 | // @router: gin.Engine 32 | func (rLoader *V2RouterLoader) V2Routes(router *gin.Engine) { 33 | rLoader.initDocs(router) 34 | rLoader.initOrder(router) 35 | } 36 | -------------------------------------------------------------------------------- /choreography/svc_order/src/app/v2/swagger/docs/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "contact": {}, 5 | "license": {} 6 | }, 7 | "paths": {} 8 | } -------------------------------------------------------------------------------- /choreography/svc_order/src/app/v2/swagger/docs/swagger.yaml: -------------------------------------------------------------------------------- 1 | info: 2 | contact: {} 3 | license: {} 4 | paths: {} 5 | swagger: "2.0" 6 | -------------------------------------------------------------------------------- /choreography/svc_order/src/app/v2/utility/rest/rest.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // Respons types 8 | type Respons struct { 9 | Status int `json:"status"` 10 | Meta interface{} `json:"meta"` 11 | Results interface{} `json:"results"` 12 | } 13 | 14 | // ResponseList params 15 | // @context: *gin.Context 16 | // status: int 17 | // payload: interface{} 18 | func ResponseList(context *gin.Context, status int, payload, meta interface{}) { 19 | var res Respons 20 | res.Status = status 21 | res.Results = payload 22 | res.Meta = meta 23 | context.JSON(status, res) 24 | return 25 | } 26 | 27 | // ResponseData params 28 | // @context: *gin.Context 29 | // status: int 30 | // payload: interface{} 31 | func ResponseData(context *gin.Context, status int, payload interface{}) { 32 | context.JSON(status, payload) 33 | return 34 | } 35 | 36 | // ResponseMessages params 37 | // @context: *gin.Context 38 | // status: int 39 | // msg: string 40 | func ResponseMessages(context *gin.Context, status int, msg string) { 41 | context.JSON(status, gin.H{ 42 | "messages": msg, 43 | }) 44 | return 45 | } 46 | -------------------------------------------------------------------------------- /choreography/svc_order/src/app/v2/utility/rest/rest_test.go: -------------------------------------------------------------------------------- 1 | package rest 2 | -------------------------------------------------------------------------------- /choreography/svc_order/src/app/v2/worker/entity/api.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // OrderPayload Mapping 6 | type OrderPayload struct { 7 | OrderNumber string `json:"order_number"` 8 | UserUUID string `json:"uuid_user"` 9 | IDOrderType string `json:"id_order_type"` 10 | IDPaymentModel string `json:"id_payment_model"` 11 | } 12 | 13 | // OrderResponse Mapping 14 | type OrderResponse struct { 15 | UUID string `json:"uuid"` 16 | OrderNumber string `json:"order_number"` 17 | UserUUID string `json:"uuid_user"` 18 | IDOrderType string `json:"id_order_type"` 19 | IDOrderStatus string `json:"id_order_status"` 20 | CreatedAt *time.Time `gorm:"column:created_at;default:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" json:"created_at"` 21 | UpdatedAt *time.Time `gorm:"column:updated_at;default:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" json:"updated_at"` 22 | DeletedAt *time.Time `gorm:"column:deleted_at" json:"deleted_at"` 23 | } 24 | 25 | // StateFullFormatKafka ... 26 | type StateFullFormatKafka struct { 27 | UUID string `json:"__uuid" bson:"__uuid"` 28 | Action string `json:"__action" bson:"__action"` 29 | Data map[string]string `json:"data" bson:"data"` 30 | CreatedAt *time.Time `json:"created_at" bson:"created_at"` 31 | } 32 | -------------------------------------------------------------------------------- /choreography/svc_order/src/app/v2/worker/entity/logger.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // LoggerEventHistory ... 6 | type LoggerEventHistory struct { 7 | UUID string `json:"__uuid"` 8 | Action string `json:"__action"` 9 | Offset uint64 `json:"__offset"` 10 | History []LoggerHistory `json:"history"` 11 | Status string `json:"status"` 12 | CreatedAt *time.Time `json:"created_at"` 13 | UpdateAt *time.Time `json:"update_at"` 14 | } 15 | 16 | // LoggerHistory ... 17 | type LoggerHistory struct { 18 | Data map[string]interface{} `json:"data"` 19 | } 20 | -------------------------------------------------------------------------------- /choreography/svc_order/src/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/joho/godotenv" 8 | "github.com/sofyan48/svc_order/src/middleware" 9 | ) 10 | 11 | // SetupEngine server router configuration 12 | func SetupEngine(env string) *gin.Engine { 13 | defaultMiddleware := middleware.DefaultMiddleware{} 14 | configEnvironment(env) 15 | router := gin.Default() 16 | router.Use(defaultMiddleware.CORSMiddleware()) 17 | return router 18 | } 19 | 20 | // configEnvironment ... 21 | func configEnvironment(env string) { 22 | switch env { 23 | case "development": 24 | err := godotenv.Load() 25 | if err != nil { 26 | log.Fatal("Error loading .env file") 27 | } 28 | case "production": 29 | gin.SetMode(gin.ReleaseMode) 30 | log.Println("Engine Running") 31 | default: 32 | err := godotenv.Load() 33 | if err != nil { 34 | log.Fatal("Error loading .env file") 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /choreography/svc_order/src/docker-compose.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sofyan48/sagas-pattern/32edb51805f64a4d4ca5e4f112cb5504fd02131a/choreography/svc_order/src/docker-compose.yml -------------------------------------------------------------------------------- /choreography/svc_order/src/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/sofyan48/svc_order/src/config" 9 | "github.com/sofyan48/svc_order/src/router" 10 | "github.com/sofyan48/svc_order/src/worker" 11 | ) 12 | 13 | func main() { 14 | environment := flag.String("e", "development", "") 15 | flag.Usage = func() { 16 | fmt.Println("Usage: server -e {mode}") 17 | os.Exit(1) 18 | } 19 | flag.Parse() 20 | startApp(*environment) 21 | } 22 | 23 | func startApp(env string) { 24 | engine := config.SetupEngine(env) 25 | 26 | go worker.LoadWorker() 27 | 28 | serverHost := os.Getenv("SERVER_ADDRESS") 29 | serverPort := os.Getenv("SERVER_PORT") 30 | serverString := fmt.Sprintf("%s:%s", serverHost, serverPort) 31 | router.LoadRouter(engine) 32 | engine.Run(serverString) 33 | } 34 | -------------------------------------------------------------------------------- /choreography/svc_order/src/middleware/auth.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | -------------------------------------------------------------------------------- /choreography/svc_order/src/middleware/cors_middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // CORSMiddleware Implementing CORS 8 | // return: gin HandlerFunc 9 | func (m *DefaultMiddleware) CORSMiddleware() gin.HandlerFunc { 10 | return func(c *gin.Context) { 11 | c.Writer.Header().Set("Access-Control-Allow-Origin", "*") 12 | c.Writer.Header().Set("Access-Control-Max-Age", "86400") 13 | c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE") 14 | c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") 15 | c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length") 16 | c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") 17 | if c.Request.Method == "OPTIONS" { 18 | c.AbortWithStatus(200) 19 | } else { 20 | c.Next() 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /choreography/svc_order/src/middleware/middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | // DefaultMiddleware types 4 | type DefaultMiddleware struct { 5 | } 6 | -------------------------------------------------------------------------------- /choreography/svc_order/src/router/router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | v2 "github.com/sofyan48/svc_order/src/app/v2/routes" 6 | ) 7 | 8 | // LoadRouter params 9 | // @routers: gin.Engine 10 | func LoadRouter(routers *gin.Engine) { 11 | version2 := v2.V2RouterLoaderHandler() 12 | version2.V2Routes(routers) 13 | } 14 | -------------------------------------------------------------------------------- /choreography/svc_order/src/utils/kafka/consumer.go: -------------------------------------------------------------------------------- 1 | package kafka 2 | 3 | import ( 4 | "log" 5 | "os" 6 | 7 | "github.com/Shopify/sarama" 8 | ) 9 | 10 | // InitConsumer ... 11 | func (kafka *KafkaLibrary) InitConsumer(group string) (sarama.ConsumerGroup, error) { 12 | configKafka := kafka.initConsumerConfig("", "") 13 | kafkaHost := os.Getenv("KAFKA_HOST") 14 | kafkaPort := os.Getenv("KAFKA_PORT") 15 | version, err := sarama.ParseKafkaVersion(os.Getenv("KAFKA_VERSION")) 16 | if err != nil { 17 | log.Panicf("Error parsing Kafka version: %v", err) 18 | } 19 | configKafka.Version = version 20 | return sarama.NewConsumerGroup([]string{kafkaHost + ":" + kafkaPort}, group, configKafka) 21 | } 22 | -------------------------------------------------------------------------------- /choreography/svc_order/src/worker/worker.go: -------------------------------------------------------------------------------- 1 | package worker 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/sofyan48/svc_order/src/app/v2/worker/consumer" 7 | ) 8 | 9 | // LoadWorker ... 10 | func LoadWorker() { 11 | // V1ConsumerWorker := consumer.V1OrderEventsHandler() 12 | // V1ConsumerWorker.Consume(os.Getenv("APP_NAME"), os.Getenv("APP_NAME")) 13 | V2ConsumerWorker := consumer.V2OrderEventsHandler() 14 | V2ConsumerWorker.Consume(os.Getenv("APP_NAME"), os.Getenv("APP_NAME")) 15 | } 16 | -------------------------------------------------------------------------------- /choreography/svc_order/watcher.conf: -------------------------------------------------------------------------------- 1 | root = "." 2 | watch_dir = "src" 3 | tmp_dir = "tmp" 4 | 5 | [build] 6 | cmd = "go build -o ./tmp/main src/main.go" 7 | bin = "tmp/main" 8 | log = "air_errors.log" 9 | include_ext = ["go", "tpl", "tmpl", "html"] 10 | exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules", "migration"] 11 | delay = 1500 # ms 12 | 13 | [log] 14 | time = false 15 | 16 | [color] 17 | main = "magenta" 18 | watcher = "cyan" 19 | build = "yellow" 20 | runner = "green" 21 | # app = "white" -------------------------------------------------------------------------------- /choreography/svc_payment/.dockerignore: -------------------------------------------------------------------------------- 1 | go.sum 2 | .env -------------------------------------------------------------------------------- /choreography/svc_payment/.env.example: -------------------------------------------------------------------------------- 1 | #################################################################### 2 | # SERVICE CONFIGURATION 3 | #################################################################### 4 | SERVER_ADDRESS=0.0.0.0 5 | SERVER_PORT=8000 6 | SERVER_TIMEZONE=Asia/Jakarta 7 | SECRET_KEY=xXbxnad!!sadsa 8 | APP_NAME=payment 9 | KAFKA_HOST=127.0.0.1 10 | KAFKA_PORT=9092 11 | 12 | #################################################################### 13 | # DATABASE CONFIGURATION 14 | #################################################################### 15 | DB_USER=root 16 | DB_PASSWORD= 17 | DB_HOST=localhost 18 | DB_PORT=26257 19 | DB_NAME=user 20 | ######################## READ DATABASE ############################# 21 | DB_USER_READ=root 22 | DB_PASSWORD_READ= 23 | DB_HOST_READ=localhost 24 | DB_PORT_READ=26257 25 | DB_NAME_READ=user 26 | 27 | #################################################################### 28 | # LOGGER CONFIGURATION 29 | #################################################################### 30 | LOGGER_URL=localhost:3000 31 | 32 | -------------------------------------------------------------------------------- /choreography/svc_payment/.gitignore: -------------------------------------------------------------------------------- 1 | # MAC OS CACHE 2 | .DS_Store 3 | 4 | # BINARY 5 | *.out 6 | *.exe 7 | *.exe~ 8 | *.dll 9 | *.so 10 | *.dylib 11 | 12 | # TEST 13 | *.test 14 | 15 | # ENV FOLDER 16 | .env 17 | env 18 | 19 | 20 | # Misc 21 | .idea 22 | src/.DS_Store 23 | go-pckg/* 24 | src/vendor/* 25 | coverage.out 26 | mydb 27 | 28 | main 29 | vendor 30 | .tmp 31 | tmp 32 | 33 | # qa_test 34 | /qa_test/reports/* 35 | /qa_test/node_modules 36 | /qa_test/package-lock.json 37 | /qa_test/.nyc_output 38 | 39 | # go sum 40 | database/data 41 | logger/mongo 42 | mongo 43 | go.sum -------------------------------------------------------------------------------- /choreography/svc_payment/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:latest AS builder 2 | 3 | WORKDIR /app 4 | COPY . . 5 | 6 | RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o main -ldflags '-w -s' src/main.go 7 | 8 | ############################ 9 | # STEP 2 build a small image 10 | ############################ 11 | FROM scratch 12 | 13 | COPY --from=builder /app /usr/bin -------------------------------------------------------------------------------- /choreography/svc_payment/README.md: -------------------------------------------------------------------------------- 1 | # PAYMENT SAGA EXAMPLE SERVICE 2 | 3 | ## Getting Started -------------------------------------------------------------------------------- /choreography/svc_payment/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/sofyan48/svc_payment 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/Shopify/sarama v1.26.1 7 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 8 | github.com/gin-gonic/gin v1.6.3 9 | github.com/google/uuid v1.1.1 10 | github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a 11 | github.com/jinzhu/gorm v1.9.12 12 | github.com/joho/godotenv v1.3.0 13 | github.com/sofyan48/go-cinlog v1.0.0 14 | github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 15 | github.com/swaggo/gin-swagger v1.2.0 16 | github.com/swaggo/swag v1.6.5 17 | ) 18 | -------------------------------------------------------------------------------- /choreography/svc_payment/migration/20200410210429_tb_payment_status.down.sql: -------------------------------------------------------------------------------- 1 | DROP table `tb_payment_status`; -------------------------------------------------------------------------------- /choreography/svc_payment/migration/20200410210429_tb_payment_status.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE tb_payment_status ( 2 | id_payment_status INT8 NOT NULL DEFAULT unique_rowid(), 3 | nm_payment_status VARCHAR NOT NULL, 4 | created_at DATE NOT NULL DEFAULT now():::DATE, 5 | updated_at DATE NOT NULL DEFAULT now():::DATE, 6 | deleted_at DATE NULL, 7 | CONSTRAINT tb_payment_status_pk PRIMARY KEY (id_payment_status ASC), 8 | FAMILY "primary" (id_payment_status, nm_payment_status, created_at, updated_at, deleted_at) 9 | ); -------------------------------------------------------------------------------- /choreography/svc_payment/migration/20200410210433_tb_payment_model.down.sql: -------------------------------------------------------------------------------- 1 | DROP table `tb_payment_model`; -------------------------------------------------------------------------------- /choreography/svc_payment/migration/20200410210433_tb_payment_model.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE tb_payment_model ( 2 | id_payment_model INT8 NOT NULL DEFAULT unique_rowid(), 3 | nm_payment_model VARCHAR NOT NULL, 4 | created_at DATE NOT NULL DEFAULT now():::DATE, 5 | updated_at DATE NOT NULL DEFAULT now():::DATE, 6 | deleted_at DATE NULL, 7 | CONSTRAINT "primary" PRIMARY KEY (id_payment_model ASC), 8 | FAMILY "primary" (id_payment_model, nm_payment_model, created_at, updated_at, deleted_at) 9 | ); -------------------------------------------------------------------------------- /choreography/svc_payment/migration/20200410210436_tb_payment.down.sql: -------------------------------------------------------------------------------- 1 | DROP table `tb_payment`; -------------------------------------------------------------------------------- /choreography/svc_payment/src/app/v2/api/payment/entity/event.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // PaymentEvent ... 8 | type PaymentEvent struct { 9 | UUID string `json:"__uuid" ` 10 | Action string `json:"__action"` 11 | Offset int64 `json:"__offset"` 12 | Data map[string]interface{} `json:"data"` 13 | Status string `json:"status"` 14 | CreatedAt *time.Time `json:"created_at"` 15 | } 16 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/app/v2/api/payment/entity/general.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | // Pagination .. 4 | type Pagination struct { 5 | Limit int `json:"limit" form:"limit"` 6 | Page int `json:"page" form:"page"` 7 | } 8 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/app/v2/api/payment/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // PaymentRequest ... 6 | type PaymentRequest struct { 7 | UUIDOrder string `json:"uuid_order"` 8 | UUIDUser string `json:"uuid_user"` 9 | IDPaymentStatus string `json:"id_payment_status"` 10 | IDPaymentModel string `json:"id_payment_model"` 11 | InquiryNumber string `json:"inquiry_number"` 12 | BankAccountNumber string `json:"bank_account_number"` 13 | NMBank string `json:"nm_bank"` 14 | PaymentTotal int `json:"payment_total"` 15 | } 16 | 17 | // PaymentPaidRequest ... 18 | type PaymentPaidRequest struct { 19 | PaymentTotal int `json:"payment_total"` 20 | PaymentStatus string `json:"payment_status"` 21 | BankAccountNumber string `json:"bank_account_number"` 22 | } 23 | 24 | // PaymentResponses ... 25 | type PaymentResponses struct { 26 | UUID string `json:"uuid"` 27 | CreatedAt *time.Time `json:"created_at"` 28 | Event *PaymentEvent `json:"event"` 29 | } 30 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/app/v2/routes/docs.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | swaggerFiles "github.com/swaggo/files" 6 | ginSwagger "github.com/swaggo/gin-swagger" 7 | 8 | _ "github.com/sofyan48/svc_payment/src/app/v2/swagger/docs" 9 | ) 10 | 11 | // DOCROUTES ... 12 | const DOCROUTES = VERSION + "/docs" 13 | 14 | func (rLoader *V2RouterLoader) initDocs(router *gin.Engine) { 15 | group := router.Group(DOCROUTES) 16 | url := ginSwagger.URL("swagger/doc.json") 17 | group.GET("/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url)) 18 | } 19 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/app/v2/routes/payment.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // PAYMENTROUTES ... 6 | const PAYMENTROUTES = VERSION + "/payment" 7 | 8 | func (rLoader *V2RouterLoader) initPayment(router *gin.Engine) { 9 | group := router.Group(PAYMENTROUTES) 10 | group.POST("", rLoader.Payment.PaymentCreate) 11 | group.GET("/get/:uuid", rLoader.Payment.GetPaymentData) 12 | group.PUT(":uuid", rLoader.Payment.UpdatePaidPayment) 13 | group.DELETE(":uuid", rLoader.Payment.DeletePayment) 14 | group.GET("list", rLoader.Payment.ListPayment) 15 | } 16 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/app/v2/routes/routes.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | 6 | payment "github.com/sofyan48/svc_payment/src/app/v2/api/payment/controller" 7 | "github.com/sofyan48/svc_payment/src/middleware" 8 | ) 9 | 10 | // VERSION ... 11 | const VERSION = "v2" 12 | 13 | // V2RouterLoader types 14 | type V2RouterLoader struct { 15 | Middleware middleware.DefaultMiddleware 16 | Payment payment.PaymentControllerInterface 17 | } 18 | 19 | // V2RouterLoaderHandler ... 20 | func V2RouterLoaderHandler() *V2RouterLoader { 21 | return &V2RouterLoader{ 22 | Payment: payment.PaymentControllerHandler(), 23 | } 24 | } 25 | 26 | // V2RouterLoaderInterface ... 27 | type V2RouterLoaderInterface interface { 28 | V2Routes(router *gin.Engine) 29 | } 30 | 31 | // V2Routes Params 32 | // @router: gin.Engine 33 | func (rLoader *V2RouterLoader) V2Routes(router *gin.Engine) { 34 | rLoader.initDocs(router) 35 | rLoader.initPayment(router) 36 | } 37 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/app/v2/swagger/docs/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "contact": {}, 5 | "license": {} 6 | }, 7 | "paths": {} 8 | } -------------------------------------------------------------------------------- /choreography/svc_payment/src/app/v2/swagger/docs/swagger.yaml: -------------------------------------------------------------------------------- 1 | info: 2 | contact: {} 3 | license: {} 4 | paths: {} 5 | swagger: "2.0" 6 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/app/v2/utility/rest/rest.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // Respons types 8 | type Respons struct { 9 | Status int `json:"status"` 10 | Meta interface{} `json:"meta"` 11 | Results interface{} `json:"results"` 12 | } 13 | 14 | // ResponseList params 15 | // @context: *gin.Context 16 | // status: int 17 | // payload: interface{} 18 | func ResponseList(context *gin.Context, status int, payload, meta interface{}) { 19 | var res Respons 20 | res.Status = status 21 | res.Results = payload 22 | res.Meta = meta 23 | context.JSON(status, res) 24 | return 25 | } 26 | 27 | // ResponseData params 28 | // @context: *gin.Context 29 | // status: int 30 | // payload: interface{} 31 | func ResponseData(context *gin.Context, status int, payload interface{}) { 32 | context.JSON(status, payload) 33 | return 34 | } 35 | 36 | // ResponseMessages params 37 | // @context: *gin.Context 38 | // status: int 39 | // msg: string 40 | func ResponseMessages(context *gin.Context, status int, msg string) { 41 | context.JSON(status, gin.H{ 42 | "messages": msg, 43 | }) 44 | return 45 | } 46 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/app/v2/utility/rest/rest_test.go: -------------------------------------------------------------------------------- 1 | package rest 2 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/app/v2/worker/entity/logger.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // LoggerEventHistory ... 6 | type LoggerEventHistory struct { 7 | UUID string `json:"__uuid"` 8 | Action string `json:"__action"` 9 | Offset uint64 `json:"__offset"` 10 | History []LoggerHistory `json:"history"` 11 | Status string `json:"status"` 12 | CreatedAt *time.Time `json:"created_at"` 13 | UpdateAt *time.Time `json:"update_at"` 14 | } 15 | 16 | // LoggerHistory ... 17 | type LoggerHistory struct { 18 | Data map[string]interface{} `json:"data"` 19 | } 20 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/joho/godotenv" 8 | "github.com/sofyan48/svc_payment/src/middleware" 9 | ) 10 | 11 | // SetupEngine server router configuration 12 | func SetupEngine(env string) *gin.Engine { 13 | defaultMiddleware := middleware.DefaultMiddleware{} 14 | configEnvironment(env) 15 | router := gin.Default() 16 | router.Use(defaultMiddleware.CORSMiddleware()) 17 | return router 18 | } 19 | 20 | // configEnvironment ... 21 | func configEnvironment(env string) { 22 | switch env { 23 | case "development": 24 | err := godotenv.Load() 25 | if err != nil { 26 | log.Fatal("Error loading .env file") 27 | } 28 | case "production": 29 | gin.SetMode(gin.ReleaseMode) 30 | log.Println("Engine Running") 31 | default: 32 | err := godotenv.Load() 33 | if err != nil { 34 | log.Fatal("Error loading .env file") 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/sofyan48/svc_payment/src/config" 9 | "github.com/sofyan48/svc_payment/src/router" 10 | "github.com/sofyan48/svc_payment/src/worker" 11 | ) 12 | 13 | // func main() { 14 | // environment := flag.String("e", "development", "") 15 | // flag.Usage = func() { 16 | // fmt.Println("Usage: server -e {mode}") 17 | // os.Exit(1) 18 | // } 19 | // flag.Parse() 20 | // config.ConfigEnvironment(*environment) 21 | // // worker.LoadCron() 22 | // worker.LoadWorker() 23 | // } 24 | 25 | func main() { 26 | environment := flag.String("e", "development", "") 27 | flag.Usage = func() { 28 | fmt.Println("Usage: server -e {mode}") 29 | os.Exit(1) 30 | } 31 | flag.Parse() 32 | startApp(*environment) 33 | } 34 | 35 | func startApp(env string) { 36 | engine := config.SetupEngine(env) 37 | 38 | go worker.LoadWorker() 39 | // go worker.LoadCron() 40 | serverHost := os.Getenv("SERVER_ADDRESS") 41 | serverPort := os.Getenv("SERVER_PORT") 42 | serverString := fmt.Sprintf("%s:%s", serverHost, serverPort) 43 | router.LoadRouter(engine) 44 | engine.Run(serverString) 45 | } 46 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/middleware/auth.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/middleware/cors_middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // CORSMiddleware Implementing CORS 8 | // return: gin HandlerFunc 9 | func (m *DefaultMiddleware) CORSMiddleware() gin.HandlerFunc { 10 | return func(c *gin.Context) { 11 | c.Writer.Header().Set("Access-Control-Allow-Origin", "*") 12 | c.Writer.Header().Set("Access-Control-Max-Age", "86400") 13 | c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE") 14 | c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") 15 | c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length") 16 | c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") 17 | if c.Request.Method == "OPTIONS" { 18 | c.AbortWithStatus(200) 19 | } else { 20 | c.Next() 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/middleware/middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | // DefaultMiddleware types 4 | type DefaultMiddleware struct { 5 | } 6 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/router/router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | v2 "github.com/sofyan48/svc_payment/src/app/v2/routes" 6 | ) 7 | 8 | // LoadRouter params 9 | // @routers: gin.Engine 10 | func LoadRouter(routers *gin.Engine) { 11 | version2 := v2.V2RouterLoaderHandler() 12 | version2.V2Routes(routers) 13 | } 14 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/utils/database/read/read.go: -------------------------------------------------------------------------------- 1 | package read 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | 8 | "github.com/jinzhu/gorm" 9 | _ "github.com/jinzhu/gorm/dialects/postgres" 10 | ) 11 | 12 | // DB Global Connetction 13 | var DBRead *gorm.DB 14 | 15 | // DBInit Initialization Connection 16 | // return connection, error 17 | func DBInit(dbhost, dbport, dbuser, dbname string) (*gorm.DB, error) { 18 | var ( 19 | configDB = fmt.Sprintf( 20 | "postgresql://%s@%s:%s/%s?sslmode=disable", 21 | dbuser, dbhost, dbport, dbname) 22 | ) 23 | 24 | DB, err := gorm.Open("postgres", configDB) 25 | if err != nil { 26 | log.Println(fmt.Sprintf("failed to connect to database: %v", err)) 27 | return nil, err 28 | } 29 | return DB, nil 30 | } 31 | 32 | // GetConnection function 33 | // return connection 34 | func GetConnection() *gorm.DB { 35 | dbhost := os.Getenv("DB_HOST_READ") 36 | dbport := os.Getenv("DB_PORT_READ") 37 | dbuser := os.Getenv("DB_USER_READ") 38 | // dbpass := os.Getenv("DB_PASSWORD") 39 | dbname := os.Getenv("DB_NAME_READ") 40 | if DBRead == nil { 41 | log.Println("No Active Connection Found") 42 | DBRead, _ = DBInit(dbhost, dbport, dbuser, dbname) 43 | } 44 | return DBRead 45 | } 46 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/utils/database/write/write.go: -------------------------------------------------------------------------------- 1 | package write 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | 8 | "github.com/jinzhu/gorm" 9 | _ "github.com/jinzhu/gorm/dialects/postgres" 10 | ) 11 | 12 | // TransactionDB Global Connection ... 13 | var TransactionDB *gorm.DB 14 | 15 | // DBInit Initialization Connection 16 | // return connection, error 17 | func DBInit(dbhost, dbport, dbuser, dbname string) (*gorm.DB, error) { 18 | var ( 19 | configDB = fmt.Sprintf( 20 | "postgresql://%s@%s:%s/%s?sslmode=disable", 21 | dbuser, dbhost, dbport, dbname) 22 | ) 23 | 24 | DB, err := gorm.Open("postgres", configDB) 25 | if err != nil { 26 | log.Println(fmt.Sprintf("failed to connect to database: %v", err)) 27 | return nil, err 28 | } 29 | return DB, nil 30 | } 31 | 32 | // GetTransactionConnection function 33 | // return DB.Begin() 34 | func GetTransactionConnection() *gorm.DB { 35 | dbhost := os.Getenv("DB_HOST") 36 | dbport := os.Getenv("DB_PORT") 37 | dbuser := os.Getenv("DB_USER") 38 | // dbpass := os.Getenv("DB_PASSWORD") 39 | dbname := os.Getenv("DB_NAME") 40 | if TransactionDB == nil { 41 | log.Println("No Active Connection Found") 42 | TransactionDB, _ = DBInit(dbhost, dbport, dbuser, dbname) 43 | } 44 | return TransactionDB 45 | } 46 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/utils/kafka/consumer.go: -------------------------------------------------------------------------------- 1 | package kafka 2 | 3 | import ( 4 | "log" 5 | "os" 6 | 7 | "github.com/Shopify/sarama" 8 | ) 9 | 10 | // InitConsumer ... 11 | func (kafka *KafkaLibrary) InitConsumer(group string) (sarama.ConsumerGroup, error) { 12 | configKafka := kafka.initConsumerConfig("", "") 13 | kafkaHost := os.Getenv("KAFKA_HOST") 14 | kafkaPort := os.Getenv("KAFKA_PORT") 15 | version, err := sarama.ParseKafkaVersion(os.Getenv("KAFKA_VERSION")) 16 | if err != nil { 17 | log.Panicf("Error parsing Kafka version: %v", err) 18 | } 19 | configKafka.Version = version 20 | return sarama.NewConsumerGroup([]string{kafkaHost + ":" + kafkaPort}, group, configKafka) 21 | } 22 | -------------------------------------------------------------------------------- /choreography/svc_payment/src/worker/worker.go: -------------------------------------------------------------------------------- 1 | package worker 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/sofyan48/svc_payment/src/app/v2/worker/consumer" 7 | "github.com/sofyan48/svc_payment/src/app/v2/worker/task" 8 | ) 9 | 10 | // LoadWorker ... 11 | func LoadWorker() { 12 | V2ConsumerWorker := consumer.V1OrderEventsHandler() 13 | V2ConsumerWorker.Consume(os.Getenv("APP_NAME"), os.Getenv("APP_NAME")) 14 | } 15 | 16 | // LoadCron ... 17 | func LoadCron() { 18 | V1Cron := task.TaskCronHandler() 19 | go V1Cron.Every2Minutes() 20 | } 21 | -------------------------------------------------------------------------------- /choreography/svc_user/.dockerignore: -------------------------------------------------------------------------------- 1 | 2 | mydb 3 | .env 4 | tmp 5 | go.sum -------------------------------------------------------------------------------- /choreography/svc_user/.gitignore: -------------------------------------------------------------------------------- 1 | # MAC OS CACHE 2 | .DS_Store 3 | 4 | # BINARY 5 | *.out 6 | *.exe 7 | *.exe~ 8 | *.dll 9 | *.so 10 | *.dylib 11 | 12 | # TEST 13 | *.test 14 | 15 | # ENV FOLDER 16 | .env 17 | env 18 | 19 | 20 | # Misc 21 | .idea 22 | src/.DS_Store 23 | go-pckg/* 24 | src/vendor/* 25 | coverage.out 26 | mydb 27 | 28 | main 29 | vendor 30 | .tmp 31 | tmp 32 | 33 | # qa_test 34 | /qa_test/reports/* 35 | /qa_test/node_modules 36 | /qa_test/package-lock.json 37 | /qa_test/.nyc_output 38 | 39 | # go sum 40 | go.sum 41 | db-init 42 | mongo 43 | -------------------------------------------------------------------------------- /choreography/svc_user/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:latest AS builder 2 | 3 | WORKDIR /app 4 | COPY . . 5 | 6 | RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o main -ldflags '-w -s' src/main.go 7 | 8 | ############################ 9 | # STEP 2 build a small image 10 | ############################ 11 | FROM scratch 12 | 13 | COPY --from=builder /app /usr/bin -------------------------------------------------------------------------------- /choreography/svc_user/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Sofyan Saputra 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /choreography/svc_user/Makefile: -------------------------------------------------------------------------------- 1 | # Build And Development 2 | test: 3 | @go test -v -cover ./... 4 | 5 | depend: 6 | @go get github.com/ralali/event-api 7 | 8 | devel: 9 | @air -c watcher.conf 10 | 11 | build: 12 | @go build -o bgin src/main.go 13 | 14 | run: 15 | @go run src/main.go 16 | 17 | production: 18 | @go run src/main.go -e production 19 | 20 | docker-stop: 21 | @docker-compose down 22 | 23 | docker-image: 24 | @docker build . -t bigevent_api 25 | 26 | docker-run: 27 | @docker-compose up 28 | 29 | .PHONY: test depend build run stop docker docker-stop docker-image docker-run devel 30 | -------------------------------------------------------------------------------- /choreography/svc_user/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | svc_user: 4 | image: meongbego/svc_users 5 | restart: always 6 | ports: 7 | - 80:80 8 | environment: 9 | - SERVER_ADDRESS=0.0.0.0 10 | - SERVER_PORT=80 11 | - SERVER_TIMEZONE=Asia/Jakarta 12 | - APP_NAME=gateway 13 | - KAFKA_HOST=localhost 14 | - KAFKA_PORT=9092 15 | - SWAGGER_SERVER_ADDRESS=http://0.0.0.0 16 | - LOGGER_URL=logger:3000 17 | command: /usr/bin/main -e production 18 | 19 | -------------------------------------------------------------------------------- /choreography/svc_user/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/sofyan48/svc_user 2 | 3 | go 1.13 4 | 5 | require ( 6 | cloud.google.com/go v0.54.0 // indirect 7 | github.com/Shopify/sarama v1.26.1 8 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 9 | github.com/apache/thrift v0.13.0 // indirect 10 | github.com/gin-gonic/gin v1.5.0 11 | github.com/google/uuid v1.1.1 12 | github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a 13 | github.com/jinzhu/gorm v1.9.12 14 | github.com/joho/godotenv v1.3.0 15 | github.com/openzipkin/zipkin-go v0.1.6 // indirect 16 | github.com/sofyan48/go-cinlog v1.0.0 17 | github.com/stretchr/testify v1.5.1 18 | github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 19 | github.com/swaggo/gin-swagger v1.2.0 20 | github.com/swaggo/swag v1.6.3 21 | go.mongodb.org/mongo-driver v1.3.1 22 | golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72 23 | ) 24 | -------------------------------------------------------------------------------- /choreography/svc_user/migration/20200406010818_tb_roles.down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE `tb_roles`; -------------------------------------------------------------------------------- /choreography/svc_user/migration/20200406010818_tb_roles.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE tb_roles ( 2 | id_roles INT8 NOT NULL DEFAULT unique_rowid(), 3 | nm_roles VARCHAR(50) NULL, 4 | acl STRING NOT NULL, 5 | created_at DATE NULL DEFAULT now():::DATE, 6 | update_at DATE NOT NULL, 7 | deleted_at DATE NULL, 8 | CONSTRAINT tb_roles_pk PRIMARY KEY (id_roles ASC), 9 | FAMILY "primary" (id_roles, nm_roles, acl, created_at, update_at, deleted_at) 10 | ); -------------------------------------------------------------------------------- /choreography/svc_user/migration/20200417000223_tb_users.down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE `tb_users`; -------------------------------------------------------------------------------- /choreography/svc_user/migration/20200417000223_tb_users.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE tb_users ( 2 | id_user INT8 NOT NULL DEFAULT unique_rowid(), 3 | first_name VARCHAR(50) NOT NULL, 4 | last_name VARCHAR(50) NULL, 5 | handphone VARCHAR(14) NOT NULL, 6 | address STRING NOT NULL, 7 | site_profil VARCHAR(50) NULL, 8 | email VARCHAR(100) NOT NULL, 9 | city VARCHAR(100) NULL, 10 | province VARCHAR(100) NULL, 11 | created_at DATE NOT NULL, 12 | updated_at DATE NOT NULL, 13 | deleted_at DATE NULL, 14 | district VARCHAR(100) NULL, 15 | CONSTRAINT tb_users_pk PRIMARY KEY (id_user ASC), 16 | UNIQUE INDEX tb_users_un1 (site_profil ASC), 17 | FAMILY "primary" (id_user, first_name, last_name, handphone, address, site_profil, email, city, province, created_at, updated_at, deleted_at, district) 18 | ); 19 | -------------------------------------------------------------------------------- /choreography/svc_user/migration/20200417000304_tb_login.down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE `tb_login`; -------------------------------------------------------------------------------- /choreography/svc_user/migration/20200417000304_tb_login.up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE tb_login ( 2 | id INT8 NOT NULL DEFAULT unique_rowid(), 3 | id_user INT8 NOT NULL, 4 | username VARCHAR NOT NULL, 5 | password STRING NOT NULL, 6 | id_roles INT8 NOT NULL, 7 | created_at TIMESTAMPTZ NOT NULL DEFAULT now():::TIMESTAMPTZ, 8 | update_at TIMESTAMPTZ NOT NULL DEFAULT now():::TIMESTAMPTZ, 9 | deleted_at TIMESTAMPTZ NULL, 10 | CONSTRAINT tb_login_pk PRIMARY KEY (id ASC), 11 | CONSTRAINT tb_login_fk FOREIGN KEY (id_user) REFERENCES tb_users(id_user) ON DELETE CASCADE ON UPDATE CASCADE, 12 | CONSTRAINT tb_login_fk_1 FOREIGN KEY (id_roles) REFERENCES tb_roles(id_roles) ON DELETE CASCADE ON UPDATE CASCADE, 13 | INDEX tb_login_auto_index_tb_login_fk (id_user ASC), 14 | INDEX tb_login_auto_index_tb_login_fk_1 (id_roles ASC), 15 | FAMILY "primary" (id, id_user, username, password, id_roles, created_at, update_at, deleted_at) 16 | ); 17 | -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/api/health/controller/health.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/sofyan48/svc_user/src/app/v1/api/health/service" 8 | "github.com/sofyan48/svc_user/src/utils/rest" 9 | ) 10 | 11 | // HealthController types 12 | type HealthController struct { 13 | Service service.HealthServiceInterface 14 | } 15 | 16 | // HealthControllerHandler ... 17 | func HealthControllerHandler() *HealthController { 18 | return &HealthController{ 19 | Service: service.HealthServiceHandler(), 20 | } 21 | } 22 | 23 | // HealthControllerInterface ... 24 | type HealthControllerInterface interface { 25 | Health(context *gin.Context) 26 | } 27 | 28 | // Health params 29 | // @contex: gin Context 30 | func (ctrl *HealthController) Health(context *gin.Context) { 31 | data := ctrl.Service.HealthService() 32 | rest.ResponseData(context, http.StatusOK, data) 33 | return 34 | } 35 | -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/api/health/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // HealtResponse ... 6 | type HealtResponse struct { 7 | Status string `json:"status"` 8 | CreatedAt *time.Time `json:"created_at"` 9 | } 10 | -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/api/health/service/health.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/sofyan48/svc_user/src/app/v1/api/health/entity" 7 | ) 8 | 9 | // HealthService ... 10 | type HealthService struct{} 11 | 12 | // HealthServiceHandler ... 13 | func HealthServiceHandler() *HealthService { 14 | return &HealthService{} 15 | } 16 | 17 | // HealthServiceInterface ... 18 | type HealthServiceInterface interface { 19 | HealthService() *entity.HealtResponse 20 | } 21 | 22 | // HealthService ... 23 | func (service *HealthService) HealthService() *entity.HealtResponse { 24 | now := time.Now() 25 | result := &entity.HealtResponse{} 26 | result.Status = "OK" 27 | result.CreatedAt = &now 28 | return result 29 | } 30 | -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/api/login/entity/database.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // Login ... 6 | type Login struct { 7 | IDUser string `gorm:"column:id_user" json:"id_user"` 8 | Username string `gorm:"column:username" json:"username"` 9 | Password string `gorm:"column:password" json:"password"` 10 | IDRoles string `gorm:"column:id_roles" json:"id_roles"` 11 | CreatedAt *time.Time `gorm:"column:created_at;default:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" json:"created_at"` 12 | UpdatedAt *time.Time `gorm:"column:update_at;default:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" json:"update_at"` 13 | DeletedAt *time.Time `gorm:"column:deleted_at" json:"deleted_at"` 14 | } 15 | -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/api/login/entity/event.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // UserEvent ... 8 | type UserLoginEvent struct { 9 | UUID string `json:"__uuid" ` 10 | Action string `json:"__action"` 11 | Offset int64 `json:"__offset"` 12 | Data map[string]interface{} `json:"data"` 13 | Status string `json:"status"` 14 | CreatedAt *time.Time `json:"created_at"` 15 | } 16 | -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/api/login/event/event.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | "github.com/sofyan48/svc_user/src/app/v1/api/login/entity" 6 | "github.com/sofyan48/svc_user/src/utils/kafka" 7 | ) 8 | 9 | // LOGINEVENT ... 10 | const LOGINEVENT = "users" 11 | 12 | // LoginEvent ... 13 | type LoginEvent struct { 14 | Kafka kafka.KafkaLibraryInterface 15 | } 16 | 17 | // LoginEventHandler ... 18 | func LoginEventHandler() *LoginEvent { 19 | return &LoginEvent{ 20 | Kafka: kafka.KafkaLibraryHandler(), 21 | } 22 | } 23 | 24 | // LoginEventInterface ... 25 | type LoginEventInterface interface { 26 | LoginCreateEvent(data *entity.UserLoginEvent) (*entity.UserLoginEvent, error) 27 | } 28 | 29 | // LoginCreateEvent ... 30 | func (event *LoginEvent) LoginCreateEvent(data *entity.UserLoginEvent) (*entity.UserLoginEvent, error) { 31 | format := event.Kafka.GetStateFull() 32 | format.Action = data.Action 33 | format.CreatedAt = data.CreatedAt 34 | format.Data = data.Data 35 | format.UUID = uuid.New().String() 36 | data.UUID = format.UUID 37 | go event.Kafka.SendEvent(LOGINEVENT, format) 38 | data.Status = "QUEUE" 39 | return data, nil 40 | } 41 | -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/api/user/entity/event.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // UserEvent ... 8 | type UserEvent struct { 9 | UUID string `json:"__uuid" ` 10 | Action string `json:"__action"` 11 | Offset int64 `json:"__offset"` 12 | Data map[string]interface{} `json:"data"` 13 | Status string `json:"status"` 14 | CreatedAt *time.Time `json:"created_at"` 15 | } 16 | -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/api/user/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // UserRequest ... 6 | type UserRequest struct { 7 | FirstName string `json:"first_name"` 8 | LastName string `json:"last_name"` 9 | Email string `json:"email"` 10 | PhoneNumber string `json:"handphone"` 11 | Address string `json:"address"` 12 | City string `json:"city"` 13 | Province string `json:"province"` 14 | District string `json:"district"` 15 | } 16 | 17 | // UserResponses ... 18 | type UserResponses struct { 19 | UUID string `json:"uuid"` 20 | CreatedAt *time.Time `json:"created_at"` 21 | Event *UserEvent `json:"event"` 22 | } 23 | -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/api/user/event/event.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | "github.com/sofyan48/svc_user/src/app/v1/api/user/entity" 6 | "github.com/sofyan48/svc_user/src/utils/kafka" 7 | ) 8 | 9 | // USEREVENT ... 10 | const USEREVENT = "users" 11 | 12 | // UserEvent ... 13 | type UserEvent struct { 14 | Kafka kafka.KafkaLibraryInterface 15 | } 16 | 17 | // UserEventHandler ... 18 | func UserEventHandler() *UserEvent { 19 | return &UserEvent{ 20 | Kafka: kafka.KafkaLibraryHandler(), 21 | } 22 | } 23 | 24 | // UserEventInterface ... 25 | type UserEventInterface interface { 26 | UserCreateEvent(data *entity.UserEvent) (*entity.UserEvent, error) 27 | } 28 | 29 | // UserCreateEvent ... 30 | func (event *UserEvent) UserCreateEvent(data *entity.UserEvent) (*entity.UserEvent, error) { 31 | format := event.Kafka.GetStateFull() 32 | format.Action = data.Action 33 | format.CreatedAt = data.CreatedAt 34 | format.Data = data.Data 35 | format.UUID = uuid.New().String() 36 | data.UUID = format.UUID 37 | go event.Kafka.SendEvent(USEREVENT, format) 38 | data.Status = "QUEUE" 39 | return data, nil 40 | } 41 | -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/routes/docs.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | swaggerFiles "github.com/swaggo/files" 6 | ginSwagger "github.com/swaggo/gin-swagger" 7 | 8 | _ "github.com/sofyan48/svc_user/src/app/v1/swagger/docs" 9 | ) 10 | 11 | // DOCROUTES ... 12 | const DOCROUTES = VERSION + "/docs" 13 | 14 | func (rLoader *V1RouterLoader) initDocs(router *gin.Engine) { 15 | group := router.Group(DOCROUTES) 16 | url := ginSwagger.URL("swagger/doc.json") 17 | group.GET("/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url)) 18 | } 19 | -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/routes/health.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // HEALTHROUTES ... 8 | const HEALTHROUTES = VERSION + "/health" 9 | 10 | func (rLoader *V1RouterLoader) initHealth(router *gin.Engine) { 11 | group := router.Group(HEALTHROUTES) 12 | group.GET("", rLoader.Health.Health) 13 | } 14 | -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/routes/login.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // LOGINROUTES ... 6 | const LOGINROUTES = VERSION + "/login" 7 | 8 | func (rLoader *V1RouterLoader) initLogin(router *gin.Engine) { 9 | group := router.Group(LOGINROUTES) 10 | group.POST("", rLoader.Login.PostCreateLogin) 11 | group.GET("/get", rLoader.Middleware.AuthToken(""), rLoader.Login.GetByUsername) 12 | group.GET("/list", rLoader.Middleware.AuthToken(""), rLoader.Login.GetList) 13 | group.POST("/session", rLoader.Middleware.AuthToken(""), rLoader.Login.PostSessionData) 14 | // group.PUT(":uuid", rLoader.User.UpdateUser) 15 | // group.DELETE(":uuid") 16 | } 17 | -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/routes/routes.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | health "github.com/sofyan48/svc_user/src/app/v1/api/health/controller" 6 | login "github.com/sofyan48/svc_user/src/app/v1/api/login/controller" 7 | user "github.com/sofyan48/svc_user/src/app/v1/api/user/controller" 8 | "github.com/sofyan48/svc_user/src/middleware" 9 | ) 10 | 11 | // VERSION ... 12 | const VERSION = "v1" 13 | 14 | // V1RouterLoader types 15 | type V1RouterLoader struct { 16 | Middleware middleware.DefaultMiddleware 17 | Health health.HealthControllerInterface 18 | User user.UserControllerInterface 19 | Login login.LoginControllerInterface 20 | } 21 | 22 | // V1RouterLoaderHandler ... 23 | func V1RouterLoaderHandler() *V1RouterLoader { 24 | return &V1RouterLoader{ 25 | Health: health.HealthControllerHandler(), 26 | User: user.UserControllerHandler(), 27 | Login: login.LoginControllerHandler(), 28 | } 29 | } 30 | 31 | // V1RouterLoaderInterface ... 32 | type V1RouterLoaderInterface interface { 33 | V1Routes(router *gin.Engine) 34 | } 35 | 36 | // V1Routes Params 37 | // @router: gin.Engine 38 | func (rLoader *V1RouterLoader) V1Routes(router *gin.Engine) { 39 | rLoader.initDocs(router) 40 | rLoader.initHealth(router) 41 | rLoader.initUser(router) 42 | rLoader.initLogin(router) 43 | } 44 | -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/routes/user.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // USERROUTES ... 6 | const USERROUTES = VERSION + "/user" 7 | 8 | func (rLoader *V1RouterLoader) initUser(router *gin.Engine) { 9 | group := router.Group(USERROUTES) 10 | group.POST("", rLoader.User.UserCreate) 11 | group.GET(":uuid", rLoader.Middleware.AuthToken(""), rLoader.User.GetUserData) 12 | group.PUT(":uuid", rLoader.Middleware.AuthToken(""), rLoader.User.UpdateUser) 13 | // group.DELETE(":uuid") 14 | } 15 | -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/swagger/docs/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "contact": {}, 5 | "license": {} 6 | }, 7 | "paths": {} 8 | } -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/swagger/docs/swagger.yaml: -------------------------------------------------------------------------------- 1 | info: 2 | contact: {} 3 | license: {} 4 | paths: {} 5 | swagger: "2.0" 6 | -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/worker/entity/logger.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // LoggerEventHistory ... 6 | type LoggerEventHistory struct { 7 | UUID string `json:"__uuid"` 8 | Action string `json:"__action"` 9 | Offset uint64 `json:"__offset"` 10 | History []LoggerHistory `json:"history"` 11 | Status string `json:"status"` 12 | CreatedAt *time.Time `json:"created_at"` 13 | UpdateAt *time.Time `json:"update_at"` 14 | } 15 | 16 | // LoggerHistory ... 17 | type LoggerHistory struct { 18 | Data map[string]interface{} `json:"data"` 19 | } 20 | -------------------------------------------------------------------------------- /choreography/svc_user/src/app/v1/worker/repository/login.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "github.com/jinzhu/gorm" 5 | "github.com/sofyan48/svc_user/src/app/v1/worker/entity" 6 | ) 7 | 8 | // UpdateLoginByID params 9 | // @id: int 10 | // @loginData: entity Login 11 | // return error 12 | func (repository *UserRepository) UpdateLoginByID(id int, loginData *entity.Login, trx *gorm.DB) error { 13 | query := trx.Table("tb_login") 14 | query = query.Where("id=?", id) 15 | query = query.Updates(loginData) 16 | query.Scan(&loginData) 17 | return query.Error 18 | } 19 | 20 | // InsertLogin params 21 | // @loginData: entity Login 22 | // return error 23 | func (repository *UserRepository) InsertLogin(loginData *entity.Login, trx *gorm.DB) error { 24 | query := trx.Table("tb_login") 25 | query = query.Create(loginData) 26 | query.Scan(&loginData) 27 | return query.Error 28 | } 29 | -------------------------------------------------------------------------------- /choreography/svc_user/src/config/server_configuration.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/joho/godotenv" 8 | "github.com/sofyan48/svc_user/src/middleware" 9 | ) 10 | 11 | // SetupEngine server router configuration 12 | func SetupEngine(env string) *gin.Engine { 13 | defaultMiddleware := middleware.DefaultMiddlewareHandler() 14 | configEnvironment(env) 15 | router := gin.Default() 16 | router.Use(defaultMiddleware.CORSMiddleware()) 17 | return router 18 | } 19 | 20 | // ConfigEnvironment ... 21 | func configEnvironment(env string) { 22 | switch env { 23 | case "development": 24 | err := godotenv.Load() 25 | if err != nil { 26 | log.Fatal("Error loading .env file") 27 | } 28 | case "production": 29 | gin.SetMode(gin.ReleaseMode) 30 | log.Println("Engine Running") 31 | default: 32 | err := godotenv.Load() 33 | if err != nil { 34 | log.Fatal("Error loading .env file") 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /choreography/svc_user/src/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/sofyan48/svc_user/src/config" 9 | 10 | apiRouter "github.com/sofyan48/svc_user/src/router" 11 | "github.com/sofyan48/svc_user/src/worker" 12 | ) 13 | 14 | func main() { 15 | environment := flag.String("e", "development", "") 16 | flag.Usage = func() { 17 | fmt.Println("Usage: server -e {mode}") 18 | os.Exit(1) 19 | } 20 | flag.Parse() 21 | startApp(*environment) 22 | } 23 | 24 | func startApp(env string) { 25 | router := config.SetupEngine(env) 26 | apiRouter.LoadRouter(router) 27 | go worker.LoadWorker() 28 | serverHost := os.Getenv("SERVER_ADDRESS") 29 | serverPort := os.Getenv("SERVER_PORT") 30 | serverString := fmt.Sprintf("%s:%s", serverHost, serverPort) 31 | router.Run(serverString) 32 | } 33 | -------------------------------------------------------------------------------- /choreography/svc_user/src/middleware/auth.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "net/http" 5 | "os" 6 | 7 | "github.com/gin-gonic/gin" 8 | "github.com/sofyan48/svc_user/src/utils/requester" 9 | ) 10 | 11 | // GetToken params 12 | // @context: *gin.Context 13 | // return gin.HandlerFunc 14 | func (m *DefaultMiddleware) GetToken(context *gin.Context) string { 15 | token := context.Request.Header["Authorization"] 16 | if len(token) < 1 { 17 | context.JSON(http.StatusUnauthorized, gin.H{ 18 | "message": "Token Not Compatible", 19 | }) 20 | context.Abort() 21 | return "event" 22 | } 23 | return token[0] 24 | } 25 | 26 | // AuthToken ... 27 | func (m *DefaultMiddleware) AuthToken(target string) gin.HandlerFunc { 28 | return func(ctx *gin.Context) { 29 | tokenString := m.GetToken(ctx) 30 | uriOauth := os.Getenv("OAUTH_URL") + "/v1/authorization/client" 31 | if target != "" { 32 | uriOauth = os.Getenv("OAUTH_URL") + "/v1/authorization/" + target 33 | } 34 | requesters := requester.RequesterHandler() 35 | _, err := requesters.GET(uriOauth, tokenString) 36 | if err != nil { 37 | ctx.JSON(http.StatusUnauthorized, gin.H{ 38 | "message": "Token Not Valid", 39 | }) 40 | ctx.Abort() 41 | } 42 | ctx.Next() 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /choreography/svc_user/src/middleware/cors_middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // CORSMiddleware Implementing CORS 8 | // return: gin HandlerFunc 9 | func (m *DefaultMiddleware) CORSMiddleware() gin.HandlerFunc { 10 | return func(c *gin.Context) { 11 | c.Writer.Header().Set("Access-Control-Allow-Origin", "*") 12 | c.Writer.Header().Set("Access-Control-Max-Age", "86400") 13 | c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE") 14 | c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") 15 | c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length") 16 | c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") 17 | if c.Request.Method == "OPTIONS" { 18 | c.AbortWithStatus(200) 19 | } else { 20 | c.Next() 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /choreography/svc_user/src/middleware/middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/sofyan48/svc_user/src/utils/requester" 6 | ) 7 | 8 | // DefaultMiddleware types 9 | type DefaultMiddleware struct { 10 | Requester requester.RequesterInterface 11 | } 12 | 13 | // DefaultMiddlewareHandler ... 14 | func DefaultMiddlewareHandler() *DefaultMiddleware { 15 | return &DefaultMiddleware{ 16 | Requester: requester.RequesterHandler(), 17 | } 18 | } 19 | 20 | // DefaultMiddlewareInterface ... 21 | type DefaultMiddlewareInterface interface { 22 | GetToken(context *gin.Context) string 23 | AuthToken() gin.HandlerFunc 24 | CORSMiddleware() gin.HandlerFunc 25 | } 26 | -------------------------------------------------------------------------------- /choreography/svc_user/src/router/router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | v1 "github.com/sofyan48/svc_user/src/app/v1/routes" 6 | ) 7 | 8 | // LoadRouter params 9 | // @routers: gin.Engine 10 | func LoadRouter(routers *gin.Engine) { 11 | version1 := v1.V1RouterLoaderHandler() 12 | version1.V1Routes(routers) 13 | } 14 | -------------------------------------------------------------------------------- /choreography/svc_user/src/utils/crypto/crypto.go: -------------------------------------------------------------------------------- 1 | package crypto 2 | 3 | import "golang.org/x/crypto/bcrypt" 4 | 5 | type Crypto struct{} 6 | 7 | func CryptoHandler() *Crypto { 8 | return &Crypto{} 9 | } 10 | 11 | type CryptoInterface interface { 12 | HashPassword(password string) (string, error) 13 | CheckPasswordHash(password, hash string) bool 14 | } 15 | 16 | // HashPassword params 17 | // @password: string 18 | // return string, error 19 | func (crp *Crypto) HashPassword(password string) (string, error) { 20 | bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) 21 | return string(bytes), err 22 | } 23 | 24 | // CheckPasswordHash params 25 | // @password: string 26 | // @hash: string 27 | // return bool 28 | func (crp *Crypto) CheckPasswordHash(password, hash string) bool { 29 | err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) 30 | return err == nil 31 | } 32 | -------------------------------------------------------------------------------- /choreography/svc_user/src/utils/kafka/consumer.go: -------------------------------------------------------------------------------- 1 | package kafka 2 | 3 | import ( 4 | "log" 5 | "os" 6 | 7 | "github.com/Shopify/sarama" 8 | ) 9 | 10 | // InitConsumer ... 11 | func (kafka *KafkaLibrary) InitConsumer(group string) (sarama.ConsumerGroup, error) { 12 | configKafka := kafka.initConsumerConfig("", "") 13 | kafkaHost := os.Getenv("KAFKA_HOST") 14 | kafkaPort := os.Getenv("KAFKA_PORT") 15 | version, err := sarama.ParseKafkaVersion(os.Getenv("KAFKA_VERSION")) 16 | if err != nil { 17 | log.Panicf("Error parsing Kafka version: %v", err) 18 | } 19 | configKafka.Version = version 20 | return sarama.NewConsumerGroup([]string{kafkaHost + ":" + kafkaPort}, group, configKafka) 21 | } 22 | -------------------------------------------------------------------------------- /choreography/svc_user/src/utils/rest/rest.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // Respons types 8 | type Respons struct { 9 | Status int `json:"status"` 10 | Meta interface{} `json:"meta"` 11 | Results interface{} `json:"results"` 12 | } 13 | 14 | // ResponseList params 15 | // @context: *gin.Context 16 | // status: int 17 | // payload: interface{} 18 | func ResponseList(context *gin.Context, status int, payload, meta interface{}) { 19 | var res Respons 20 | res.Status = status 21 | res.Results = payload 22 | res.Meta = meta 23 | context.JSON(status, res) 24 | return 25 | } 26 | 27 | // ResponseData params 28 | // @context: *gin.Context 29 | // status: int 30 | // payload: interface{} 31 | func ResponseData(context *gin.Context, status int, payload interface{}) { 32 | context.JSON(status, payload) 33 | return 34 | } 35 | 36 | // ResponseMessages params 37 | // @context: *gin.Context 38 | // status: int 39 | // msg: string 40 | func ResponseMessages(context *gin.Context, status int, msg string) { 41 | context.JSON(status, gin.H{ 42 | "messages": msg, 43 | }) 44 | return 45 | } 46 | -------------------------------------------------------------------------------- /choreography/svc_user/src/utils/rest/rest_test.go: -------------------------------------------------------------------------------- 1 | package rest 2 | -------------------------------------------------------------------------------- /choreography/svc_user/src/worker/worker.go: -------------------------------------------------------------------------------- 1 | package worker 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/sofyan48/svc_user/src/app/v1/worker/consumer" 7 | ) 8 | 9 | // LoadWorker ... 10 | func LoadWorker() { 11 | V1ConsumerWorker := consumer.V1ConsumerEventsHandler() 12 | V1ConsumerWorker.Consume(os.Getenv("APP_NAME"), os.Getenv("APP_NAME")) 13 | } 14 | -------------------------------------------------------------------------------- /choreography/svc_user/watcher.conf: -------------------------------------------------------------------------------- 1 | root = "." 2 | watch_dir = "src" 3 | tmp_dir = "tmp" 4 | 5 | [build] 6 | cmd = "go build -o ./tmp/main src/main.go" 7 | bin = "tmp/main" 8 | log = "air_errors.log" 9 | include_ext = ["go", "tpl", "tmpl", "html"] 10 | exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules", "mydb"] 11 | delay = 1500 # ms 12 | 13 | [log] 14 | time = false 15 | 16 | [color] 17 | main = "magenta" 18 | watcher = "cyan" 19 | build = "yellow" 20 | runner = "green" 21 | # app = "white" -------------------------------------------------------------------------------- /dependecies/kafka/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | zookeeper: 4 | image: confluentinc/cp-zookeeper:5.4.0 5 | hostname: zookeeper 6 | container_name: zookeeper 7 | ports: 8 | - "2181:2181" 9 | environment: 10 | ZOOKEEPER_CLIENT_PORT: 2181 11 | ZOOKEEPER_TICK_TIME: 2000 12 | 13 | broker: 14 | image: confluentinc/cp-kafka:5.4.0 15 | hostname: broker 16 | container_name: broker 17 | depends_on: 18 | - zookeeper 19 | ports: 20 | - "29092:29092" 21 | - "9092:9092" 22 | environment: 23 | KAFKA_BROKER_ID: 1 24 | KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181' 25 | KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT 26 | KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://broker:29092,PLAINTEXT_HOST://broker:9092 27 | KAFKA_ADVERTISED_HOST_NAME: 0.0.0.0 28 | KAFKA_ADVERTISED: 0.0.0.0 29 | KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 30 | KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0 -------------------------------------------------------------------------------- /dependecies/krakend/choreography/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | jaeger: 4 | image: jaegertracing/all-in-one:latest 5 | ports: 6 | - "16686:16686" 7 | - "14268:14268" 8 | networks: 9 | choreo_net: 10 | aliases: 11 | - jaeger 12 | kraken_designer: 13 | image: devopsfaith/krakendesigner:latest 14 | ports: 15 | - 8787:80 16 | networks: 17 | choreo_net: 18 | aliases: 19 | - kraken_designer 20 | krakend_ce: 21 | image: devopsfaith/krakend:1.1.1 22 | volumes: 23 | - ./etc/:/etc/krakend 24 | ports: 25 | - "1234:1234" 26 | - "8080:8080" 27 | - "8090:8090" 28 | depends_on: 29 | - jaeger 30 | networks: 31 | choreo_net: 32 | aliases: 33 | - krakend_ce 34 | networks: 35 | choreo_net: 36 | driver: bridge -------------------------------------------------------------------------------- /dependecies/krakend/orchestration/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | jaeger: 4 | image: jaegertracing/all-in-one:latest 5 | ports: 6 | - "16686:16686" 7 | - "14268:14268" 8 | kraken_designer: 9 | image: devopsfaith/krakendesigner:latest 10 | ports: 11 | - 8787:80 12 | krakend_ce: 13 | image: devopsfaith/krakend:1.1.1 14 | volumes: 15 | - ./etc/:/etc/krakend 16 | ports: 17 | - "1234:1234" 18 | - "8080:8080" 19 | - "8090:8090" 20 | depends_on: 21 | - jaeger -------------------------------------------------------------------------------- /dependecies/krakend/orchestration/etc/krakend.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "extra_config": { 4 | "github_com/devopsfaith/krakend-cors": { 5 | "allow_origins": [ 6 | "*" 7 | ], 8 | "expose_headers": [ 9 | "Content-Length" 10 | ], 11 | "max_age": "12h", 12 | "allow_methods": [ 13 | "POST" 14 | ] 15 | } 16 | }, 17 | "timeout": "3000ms", 18 | "cache_ttl": "300s", 19 | "output_encoding": "json", 20 | "name": "order", 21 | "port": 8080, 22 | "endpoints": [ 23 | { 24 | "endpoint": "/v1/order/{uuid}", 25 | "method": "GET", 26 | "extra_config": {}, 27 | "output_encoding": "json", 28 | "concurrent_calls": 1, 29 | "backend": [ 30 | { 31 | "url_pattern": "/v1/order/{uuid}", 32 | "host": [ 33 | "172.17.0.1" 34 | ] 35 | } 36 | ] 37 | } 38 | ] 39 | } -------------------------------------------------------------------------------- /dependecies/logger/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | mongo: 4 | image: mongo 5 | ports: 6 | - 27017:27017 7 | volumes: 8 | - ./mongo:/data/db 9 | networks: 10 | choreo_net: 11 | aliases: 12 | - mongo 13 | logger: 14 | image: meongbego/cinlog 15 | restart: always 16 | ports: 17 | - 3000:3000 18 | environment: 19 | - GIN_MODE=release 20 | - SERVER_ADDRESS=0.0.0.0 21 | - SERVER_PORT=3000 22 | - SERVER_TIMEZONE=Asia/Jakarta 23 | - MONGO_HOST=mongo 24 | - MONGO_PORT=27017 25 | - MONGO_DATABASE=logger 26 | - MONGO_USER= 27 | - MONGO_PASSWORD= 28 | - LOGGER_DRIVER=mongo 29 | command: ./main -e production 30 | tty: true 31 | depends_on: 32 | - mongo 33 | networks: 34 | choreo_net: 35 | aliases: 36 | - logger 37 | 38 | networks: 39 | choreo_net: 40 | driver: bridge -------------------------------------------------------------------------------- /dependecies/redis/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.2" 2 | services: 3 | redis: 4 | image: redis 5 | command: ["redis-server"] 6 | ports: 7 | - "6379:6379" 8 | networks: 9 | choreo_net: 10 | aliases: 11 | - redis 12 | 13 | networks: 14 | choreo_net: 15 | driver: bridge -------------------------------------------------------------------------------- /docs/choreography/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sofyan48/sagas-pattern/32edb51805f64a4d4ca5e4f112cb5504fd02131a/docs/choreography/architecture.png -------------------------------------------------------------------------------- /docs/choreography/concept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sofyan48/sagas-pattern/32edb51805f64a4d4ca5e4f112cb5504fd02131a/docs/choreography/concept.png -------------------------------------------------------------------------------- /docs/choreography/event.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sofyan48/sagas-pattern/32edb51805f64a4d4ca5e4f112cb5504fd02131a/docs/choreography/event.png -------------------------------------------------------------------------------- /docs/choreography/order/create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sofyan48/sagas-pattern/32edb51805f64a4d4ca5e4f112cb5504fd02131a/docs/choreography/order/create.png -------------------------------------------------------------------------------- /docs/choreography/order/get.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sofyan48/sagas-pattern/32edb51805f64a4d4ca5e4f112cb5504fd02131a/docs/choreography/order/get.png -------------------------------------------------------------------------------- /docs/choreography/payment/payment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sofyan48/sagas-pattern/32edb51805f64a4d4ca5e4f112cb5504fd02131a/docs/choreography/payment/payment.png -------------------------------------------------------------------------------- /docs/choreography/user/create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sofyan48/sagas-pattern/32edb51805f64a4d4ca5e4f112cb5504fd02131a/docs/choreography/user/create.png -------------------------------------------------------------------------------- /docs/choreography/user/get.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sofyan48/sagas-pattern/32edb51805f64a4d4ca5e4f112cb5504fd02131a/docs/choreography/user/get.png -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sofyan48/sagas-pattern/32edb51805f64a4d4ca5e4f112cb5504fd02131a/license -------------------------------------------------------------------------------- /orchestration/README.md: -------------------------------------------------------------------------------- 1 | # ORCHESTRATION PATTERN 2 | 3 | ## Concept Orchestration Pattern 4 | ### Service Comunication 5 | 6 | ### Architecture 7 | 8 | ### Event Communication 9 | 10 | ## Service 11 | ### Orchestration 12 | - svc_user (User Service) 13 | - svc_api (API Layer) 14 | - svc_order (Order Service) 15 | - svc_payment (Payment Service) 16 | 17 | ## Dependecies 18 | - database (cockroachdb) 19 | - mongodb 20 | - cinlog (Logger History, support storage mongo, elasticsearch and AWS S3) 21 | - krakend (API Gateway) 22 | 23 | ## Getting Started 24 | ### Setting environment -------------------------------------------------------------------------------- /orchestration/orchestrator/.dockerignore: -------------------------------------------------------------------------------- 1 | 2 | mydb 3 | .env 4 | tmp -------------------------------------------------------------------------------- /orchestration/orchestrator/.env.example: -------------------------------------------------------------------------------- 1 | #################################################################### 2 | # SERVER CONFIGURATION 3 | #################################################################### 4 | SERVER_ADDRESS=0.0.0.0 5 | SERVER_PORT=5000 6 | SERVER_TIMEZONE=Asia/Jakarta 7 | SECRET_KEY=xXbxnad!!sadsa 8 | 9 | 10 | #################################################################### 11 | # KAFKA CONFIGURATION 12 | #################################################################### 13 | KAFKA_HOST=127.0.0.1 14 | KAFKA_PORT=9092 15 | 16 | #################################################################### 17 | # SWAGGER CONFIGURATION 18 | #################################################################### 19 | SWAGGER_SERVER_ADDRESS=http://localhost:3000 20 | 21 | 22 | #################################################################### 23 | # LOGGER CONFIGURATION 24 | #################################################################### 25 | LOGGER_URL=localhost:3000 26 | -------------------------------------------------------------------------------- /orchestration/orchestrator/.gitignore: -------------------------------------------------------------------------------- 1 | # MAC OS CACHE 2 | .DS_Store 3 | 4 | # BINARY 5 | *.out 6 | *.exe 7 | *.exe~ 8 | *.dll 9 | *.so 10 | *.dylib 11 | 12 | # TEST 13 | *.test 14 | 15 | # ENV FOLDER 16 | .env 17 | env 18 | 19 | 20 | # Misc 21 | .idea 22 | src/.DS_Store 23 | go-pckg/* 24 | src/vendor/* 25 | coverage.out 26 | mydb 27 | 28 | main 29 | vendor 30 | .tmp 31 | tmp 32 | 33 | # qa_test 34 | /qa_test/reports/* 35 | /qa_test/node_modules 36 | /qa_test/package-lock.json 37 | /qa_test/.nyc_output 38 | 39 | # go sum 40 | go.sum 41 | db-init 42 | mongo 43 | -------------------------------------------------------------------------------- /orchestration/orchestrator/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:latest AS builder 2 | 3 | WORKDIR /app 4 | COPY . . 5 | 6 | RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o main -ldflags '-w -s' src/main.go 7 | 8 | ############################ 9 | # STEP 2 build a small image 10 | ############################ 11 | FROM scratch 12 | 13 | COPY --from=builder /app /usr/bin -------------------------------------------------------------------------------- /orchestration/orchestrator/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Sofyan Saputra 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /orchestration/orchestrator/Makefile: -------------------------------------------------------------------------------- 1 | # Build And Development 2 | test: 3 | @go test -v -cover ./... 4 | 5 | depend: 6 | @go get github.com/ralali/event-api 7 | 8 | devel: 9 | @air -c watcher.conf 10 | 11 | build: 12 | @go build -o bgin src/main.go 13 | 14 | run: 15 | @go run src/main.go 16 | 17 | production: 18 | @go run src/main.go -e production 19 | 20 | docker-stop: 21 | @docker-compose down 22 | 23 | docker-image: 24 | @docker build . -t bigevent_api 25 | 26 | docker-run: 27 | @docker-compose up 28 | 29 | .PHONY: test depend build run stop docker docker-stop docker-image docker-run devel 30 | -------------------------------------------------------------------------------- /orchestration/orchestrator/README.md: -------------------------------------------------------------------------------- 1 | # API LAYER SAGA EXAMPLE CHOREOGRAPHY SERVICE 2 | 3 | ## Getting Started 4 | 5 | ### Local 6 | Run local in stage : 7 | - development 8 | - production 9 | ``` 10 | go run src/main.go -e $stage 11 | ``` 12 | default stage in production 13 | 14 | ### Dockerizing 15 | In docker app default execute production stage 16 | ``` 17 | docker-compose up 18 | ``` 19 | -------------------------------------------------------------------------------- /orchestration/orchestrator/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | svc_gateway: 4 | image: meongbego/svc_gateway 5 | restart: always 6 | ports: 7 | - 80:80 8 | environment: 9 | - SERVER_ADDRESS=0.0.0.0 10 | - SERVER_PORT=80 11 | - SERVER_TIMEZONE=Asia/Jakarta 12 | - APP_NAME=gateway 13 | - KAFKA_HOST=localhost 14 | - KAFKA_PORT=9092 15 | - SWAGGER_SERVER_ADDRESS=http://0.0.0.0 16 | - LOGGER_URL=logger:3000 17 | command: /usr/bin/main -e production 18 | 19 | -------------------------------------------------------------------------------- /orchestration/orchestrator/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/sofyan48/orchestrator 2 | 3 | go 1.13 4 | 5 | require ( 6 | cloud.google.com/go v0.54.0 // indirect 7 | github.com/Shopify/sarama v1.26.1 8 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 9 | github.com/apache/thrift v0.13.0 // indirect 10 | github.com/gin-gonic/gin v1.5.0 11 | github.com/google/uuid v1.1.1 12 | github.com/jinzhu/gorm v1.9.12 13 | github.com/joho/godotenv v1.3.0 14 | github.com/openzipkin/zipkin-go v0.1.6 // indirect 15 | github.com/sofyan48/go-cinlog v1.0.0 16 | github.com/stretchr/testify v1.5.1 17 | github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 18 | github.com/swaggo/gin-swagger v1.2.0 19 | github.com/swaggo/swag v1.6.3 20 | go.mongodb.org/mongo-driver v1.3.1 21 | golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72 22 | ) 23 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/api/health/controller/health.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/sofyan48/orchestrator/src/app/v1/api/health/service" 8 | "github.com/sofyan48/orchestrator/src/app/v1/utility/rest" 9 | ) 10 | 11 | // HealthController types 12 | type HealthController struct { 13 | Service service.HealthServiceInterface 14 | } 15 | 16 | // HealthControllerHandler ... 17 | func HealthControllerHandler() *HealthController { 18 | return &HealthController{ 19 | Service: service.HealthServiceHandler(), 20 | } 21 | } 22 | 23 | // HealthControllerInterface ... 24 | type HealthControllerInterface interface { 25 | Health(context *gin.Context) 26 | } 27 | 28 | // Health params 29 | // @contex: gin Context 30 | func (ctrl *HealthController) Health(context *gin.Context) { 31 | data := ctrl.Service.HealthService() 32 | rest.ResponseData(context, http.StatusOK, data) 33 | return 34 | } 35 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/api/health/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // HealtResponse ... 6 | type HealtResponse struct { 7 | Status string `json:"status"` 8 | CreatedAt *time.Time `json:"created_at"` 9 | } 10 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/api/health/service/health.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/sofyan48/orchestrator/src/app/v1/api/health/entity" 7 | ) 8 | 9 | // HealthService ... 10 | type HealthService struct{} 11 | 12 | // HealthServiceHandler ... 13 | func HealthServiceHandler() *HealthService { 14 | return &HealthService{} 15 | } 16 | 17 | // HealthServiceInterface ... 18 | type HealthServiceInterface interface { 19 | HealthService() *entity.HealtResponse 20 | } 21 | 22 | // HealthService ... 23 | func (service *HealthService) HealthService() *entity.HealtResponse { 24 | now := time.Now() 25 | result := &entity.HealtResponse{} 26 | result.Status = "OK" 27 | result.CreatedAt = &now 28 | return result 29 | } 30 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/api/login/entity/event.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // UserEvent ... 8 | type UserEvent struct { 9 | UUID string `json:"__uuid" ` 10 | Action string `json:"__action"` 11 | Offset int64 `json:"__offset"` 12 | Data map[string]interface{} `json:"data"` 13 | Status string `json:"status"` 14 | CreatedAt *time.Time `json:"created_at"` 15 | } 16 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/api/login/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // UserRequest ... 6 | type UserRequest struct { 7 | FirstName string `json:"first_name"` 8 | LastName string `json:"last_name"` 9 | Email string `json:"email"` 10 | PhoneNumber string `json:"handphone"` 11 | Address string `json:"address"` 12 | City string `json:"city"` 13 | Province string `json:"province"` 14 | District string `json:"district"` 15 | } 16 | 17 | // UserResponses ... 18 | type UserResponses struct { 19 | UUID string `json:"uuid"` 20 | CreatedAt *time.Time `json:"created_at"` 21 | Event *UserEvent `json:"event"` 22 | } 23 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/api/login/event/event.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | "github.com/sofyan48/orchestrator/src/app/v1/api/user/entity" 6 | "github.com/sofyan48/orchestrator/src/app/v1/utility/kafka" 7 | ) 8 | 9 | // USEREVENT ... 10 | const USEREVENT = "users" 11 | 12 | // UserEvent ... 13 | type UserEvent struct { 14 | Kafka kafka.KafkaLibraryInterface 15 | } 16 | 17 | // UserEventHandler ... 18 | func UserEventHandler() *UserEvent { 19 | return &UserEvent{ 20 | Kafka: kafka.KafkaLibraryHandler(), 21 | } 22 | } 23 | 24 | // UserEventInterface ... 25 | type UserEventInterface interface { 26 | UserCreateEvent(data *entity.UserEvent) (*entity.UserEvent, error) 27 | } 28 | 29 | // UserCreateEvent ... 30 | func (event *UserEvent) UserCreateEvent(data *entity.UserEvent) (*entity.UserEvent, error) { 31 | format := event.Kafka.GetStateFull() 32 | format.Action = data.Action 33 | format.CreatedAt = data.CreatedAt 34 | format.Data = data.Data 35 | format.UUID = uuid.New().String() 36 | data.UUID = format.UUID 37 | go event.Kafka.SendEvent(USEREVENT, format) 38 | data.Status = "QUEUE" 39 | return data, nil 40 | } 41 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/api/order/entity/event.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // OrderEvent ... 8 | type OrderEvent struct { 9 | UUID string `json:"__uuid" ` 10 | Action string `json:"__action"` 11 | Offset int64 `json:"__offset"` 12 | Data map[string]interface{} `json:"data"` 13 | Status string `json:"status"` 14 | CreatedAt *time.Time `json:"created_at"` 15 | } 16 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/api/order/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // OrderRequest ... 6 | type OrderRequest struct { 7 | OrderNumber string `json:"order_number"` 8 | UserUUID string `json:"uuid_user"` 9 | IDOrderType string `json:"id_order_type"` 10 | IDOrderStatus string `json:"id_order_status"` 11 | IDPaymentStatus string `json:"id_payment_status"` 12 | IDPaymentModel string `json:"id_payment_model"` 13 | InquiryNumber string `json:"inquiry_number"` 14 | PaymentOrder string `json:"payment_order"` 15 | NMBank string `json:"nm_bank"` 16 | } 17 | 18 | // OrderResponses ... 19 | type OrderResponses struct { 20 | UUID string `json:"uuid"` 21 | CreatedAt *time.Time `json:"created_at"` 22 | Event *OrderEvent `json:"event"` 23 | } 24 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/api/order/event/event.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | "github.com/sofyan48/orchestrator/src/app/v1/api/order/entity" 6 | "github.com/sofyan48/orchestrator/src/app/v1/utility/kafka" 7 | ) 8 | 9 | // ORDEREVENT ... 10 | const ORDEREVENT = "order" 11 | 12 | // OrderEvent ... 13 | type OrderEvent struct { 14 | Kafka kafka.KafkaLibraryInterface 15 | } 16 | 17 | // OrderEventHandler ... 18 | func OrderEventHandler() *OrderEvent { 19 | return &OrderEvent{ 20 | Kafka: kafka.KafkaLibraryHandler(), 21 | } 22 | } 23 | 24 | // OrderEventInterface ... 25 | type OrderEventInterface interface { 26 | OrderCreateEvent(data *entity.OrderEvent) (*entity.OrderEvent, error) 27 | } 28 | 29 | // OrderCreateEvent ... 30 | func (event *OrderEvent) OrderCreateEvent(data *entity.OrderEvent) (*entity.OrderEvent, error) { 31 | format := event.Kafka.GetStateFull() 32 | format.Action = data.Action 33 | format.CreatedAt = data.CreatedAt 34 | format.Data = data.Data 35 | format.UUID = uuid.New().String() 36 | data.UUID = format.UUID 37 | go event.Kafka.SendEvent(ORDEREVENT, format) 38 | data.Status = "QUEUE" 39 | return data, nil 40 | } 41 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/api/payment/entity/event.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // PaymentEvent ... 8 | type PaymentEvent struct { 9 | UUID string `json:"__uuid" ` 10 | Action string `json:"__action"` 11 | Offset int64 `json:"__offset"` 12 | Data map[string]interface{} `json:"data"` 13 | Status string `json:"status"` 14 | CreatedAt *time.Time `json:"created_at"` 15 | } 16 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/api/payment/entity/general.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | // Pagination .. 4 | type Pagination struct { 5 | Limit int `json:"limit" form:"limit"` 6 | Page int `json:"page" form:"page"` 7 | } 8 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/api/payment/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // PaymentRequest ... 6 | type PaymentRequest struct { 7 | UUIDOrder string `json:"uuid_order"` 8 | UUIDUser string `json:"uuid_user"` 9 | IDPaymentStatus string `json:"id_payment_status"` 10 | IDPaymentModel string `json:"id_payment_model"` 11 | InquiryNumber string `json:"inquiry_number"` 12 | BankAccountNumber string `json:"bank_account_number"` 13 | NMBank string `json:"nm_bank"` 14 | PaymentTotal int `json:"payment_total"` 15 | } 16 | 17 | // PaymentPaidRequest ... 18 | type PaymentPaidRequest struct { 19 | PaymentTotal int `json:"payment_total"` 20 | PaymentStatus string `json:"payment_status"` 21 | BankAccountNumber string `json:"bank_account_number"` 22 | } 23 | 24 | // PaymentResponses ... 25 | type PaymentResponses struct { 26 | UUID string `json:"uuid"` 27 | CreatedAt *time.Time `json:"created_at"` 28 | Event *PaymentEvent `json:"event"` 29 | } 30 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/api/user/entity/event.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // UserEvent ... 8 | type UserEvent struct { 9 | UUID string `json:"__uuid" ` 10 | Action string `json:"__action"` 11 | Offset int64 `json:"__offset"` 12 | Data map[string]interface{} `json:"data"` 13 | Status string `json:"status"` 14 | CreatedAt *time.Time `json:"created_at"` 15 | } 16 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/api/user/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // UserRequest ... 6 | type UserRequest struct { 7 | FirstName string `json:"first_name"` 8 | LastName string `json:"last_name"` 9 | Email string `json:"email"` 10 | PhoneNumber string `json:"handphone"` 11 | Address string `json:"address"` 12 | City string `json:"city"` 13 | Province string `json:"province"` 14 | District string `json:"district"` 15 | } 16 | 17 | // UserResponses ... 18 | type UserResponses struct { 19 | UUID string `json:"uuid"` 20 | CreatedAt *time.Time `json:"created_at"` 21 | Event *UserEvent `json:"event"` 22 | } 23 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/api/user/event/event.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | "github.com/sofyan48/orchestrator/src/app/v1/api/user/entity" 6 | "github.com/sofyan48/orchestrator/src/app/v1/utility/kafka" 7 | ) 8 | 9 | // USEREVENT ... 10 | const USEREVENT = "users" 11 | 12 | // UserEvent ... 13 | type UserEvent struct { 14 | Kafka kafka.KafkaLibraryInterface 15 | } 16 | 17 | // UserEventHandler ... 18 | func UserEventHandler() *UserEvent { 19 | return &UserEvent{ 20 | Kafka: kafka.KafkaLibraryHandler(), 21 | } 22 | } 23 | 24 | // UserEventInterface ... 25 | type UserEventInterface interface { 26 | UserCreateEvent(data *entity.UserEvent) (*entity.UserEvent, error) 27 | } 28 | 29 | // UserCreateEvent ... 30 | func (event *UserEvent) UserCreateEvent(data *entity.UserEvent) (*entity.UserEvent, error) { 31 | format := event.Kafka.GetStateFull() 32 | format.Action = data.Action 33 | format.CreatedAt = data.CreatedAt 34 | format.Data = data.Data 35 | format.UUID = uuid.New().String() 36 | data.UUID = format.UUID 37 | go event.Kafka.SendEvent(USEREVENT, format) 38 | data.Status = "QUEUE" 39 | return data, nil 40 | } 41 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/routes/docs.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | swaggerFiles "github.com/swaggo/files" 6 | ginSwagger "github.com/swaggo/gin-swagger" 7 | 8 | _ "github.com/sofyan48/orchestrator/src/app/v1/swagger/docs" 9 | ) 10 | 11 | // DOCROUTES ... 12 | const DOCROUTES = VERSION + "/docs" 13 | 14 | func (rLoader *V1RouterLoader) initDocs(router *gin.Engine) { 15 | group := router.Group(DOCROUTES) 16 | url := ginSwagger.URL("swagger/doc.json") 17 | group.GET("/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url)) 18 | } 19 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/routes/health.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // HEALTHROUTES ... 8 | const HEALTHROUTES = VERSION + "/health" 9 | 10 | func (rLoader *V1RouterLoader) initHealth(router *gin.Engine) { 11 | group := router.Group(HEALTHROUTES) 12 | group.GET("", rLoader.Health.Health) 13 | } 14 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/routes/order.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // ORDERROUTES ... 6 | const ORDERROUTES = VERSION + "/order" 7 | 8 | func (rLoader *V1RouterLoader) initOrder(router *gin.Engine) { 9 | group := router.Group(ORDERROUTES) 10 | group.POST("", rLoader.Order.OrderCreate) 11 | group.GET(":uuid", rLoader.Order.GetOrderData) 12 | group.PUT(":uuid", rLoader.Order.UpdateOrder) 13 | group.DELETE(":uuid", rLoader.Order.DeleteOrder) 14 | } 15 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/routes/payment.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // PAYMENTROUTES ... 6 | const PAYMENTROUTES = VERSION + "/payment" 7 | 8 | func (rLoader *V1RouterLoader) initPayment(router *gin.Engine) { 9 | group := router.Group(PAYMENTROUTES) 10 | group.POST("", rLoader.Payment.PaymentCreate) 11 | group.GET("/get/:uuid", rLoader.Payment.GetPaymentData) 12 | group.PUT(":uuid", rLoader.Payment.UpdatePaidPayment) 13 | group.DELETE(":uuid", rLoader.Payment.DeletePayment) 14 | group.GET("list", rLoader.Payment.ListPayment) 15 | } 16 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/routes/user.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // USERROUTES ... 6 | const USERROUTES = VERSION + "/user" 7 | 8 | func (rLoader *V1RouterLoader) initUser(router *gin.Engine) { 9 | group := router.Group(USERROUTES) 10 | group.POST("", rLoader.User.UserCreate) 11 | group.GET(":uuid", rLoader.User.GetUserData) 12 | group.PUT(":uuid", rLoader.User.UpdateUser) 13 | group.DELETE(":uuid") 14 | } 15 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/swagger/docs/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "contact": {}, 5 | "license": {} 6 | }, 7 | "paths": {} 8 | } -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/swagger/docs/swagger.yaml: -------------------------------------------------------------------------------- 1 | info: 2 | contact: {} 3 | license: {} 4 | paths: {} 5 | swagger: "2.0" 6 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/utility/kafka/consumer.go: -------------------------------------------------------------------------------- 1 | package kafka 2 | 3 | import ( 4 | "log" 5 | "os" 6 | 7 | "github.com/Shopify/sarama" 8 | ) 9 | 10 | // InitConsumer ... 11 | func (kafka *KafkaLibrary) InitConsumer(group string) (sarama.ConsumerGroup, error) { 12 | configKafka := kafka.initConsumerConfig("", "") 13 | kafkaHost := os.Getenv("KAFKA_HOST") 14 | kafkaPort := os.Getenv("KAFKA_PORT") 15 | version, err := sarama.ParseKafkaVersion(os.Getenv("KAFKA_VERSION")) 16 | if err != nil { 17 | log.Panicf("Error parsing Kafka version: %v", err) 18 | } 19 | configKafka.Version = version 20 | return sarama.NewConsumerGroup([]string{kafkaHost + ":" + kafkaPort}, group, configKafka) 21 | } 22 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/utility/rest/rest.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // Respons types 8 | type Respons struct { 9 | Status int `json:"status"` 10 | Meta interface{} `json:"meta"` 11 | Results interface{} `json:"results"` 12 | } 13 | 14 | // ResponseList params 15 | // @context: *gin.Context 16 | // status: int 17 | // payload: interface{} 18 | func ResponseList(context *gin.Context, status int, payload, meta interface{}) { 19 | var res Respons 20 | res.Status = status 21 | res.Results = payload 22 | res.Meta = meta 23 | context.JSON(status, res) 24 | return 25 | } 26 | 27 | // ResponseData params 28 | // @context: *gin.Context 29 | // status: int 30 | // payload: interface{} 31 | func ResponseData(context *gin.Context, status int, payload interface{}) { 32 | context.JSON(status, payload) 33 | return 34 | } 35 | 36 | // ResponseMessages params 37 | // @context: *gin.Context 38 | // status: int 39 | // msg: string 40 | func ResponseMessages(context *gin.Context, status int, msg string) { 41 | context.JSON(status, gin.H{ 42 | "messages": msg, 43 | }) 44 | return 45 | } 46 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/app/v1/utility/rest/rest_test.go: -------------------------------------------------------------------------------- 1 | package rest 2 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/config/server_configuration.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/joho/godotenv" 8 | "github.com/sofyan48/orchestrator/src/middleware" 9 | ) 10 | 11 | // SetupEngine server router configuration 12 | func SetupEngine(env string) *gin.Engine { 13 | defaultMiddleware := middleware.DefaultMiddleware{} 14 | configEnvironment(env) 15 | router := gin.Default() 16 | router.Use(defaultMiddleware.CORSMiddleware()) 17 | return router 18 | } 19 | 20 | // ConfigEnvironment ... 21 | func configEnvironment(env string) { 22 | switch env { 23 | case "development": 24 | err := godotenv.Load() 25 | if err != nil { 26 | log.Fatal("Error loading .env file") 27 | } 28 | case "production": 29 | gin.SetMode(gin.ReleaseMode) 30 | log.Println("Engine Running") 31 | default: 32 | err := godotenv.Load() 33 | if err != nil { 34 | log.Fatal("Error loading .env file") 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/sofyan48/orchestrator/src/config" 9 | 10 | apiRouter "github.com/sofyan48/orchestrator/src/router" 11 | ) 12 | 13 | func main() { 14 | environment := flag.String("e", "development", "") 15 | flag.Usage = func() { 16 | fmt.Println("Usage: server -e {mode}") 17 | os.Exit(1) 18 | } 19 | flag.Parse() 20 | startApp(*environment) 21 | } 22 | 23 | func startApp(env string) { 24 | router := config.SetupEngine(env) 25 | apiRouter.LoadRouter(router) 26 | serverHost := os.Getenv("SERVER_ADDRESS") 27 | serverPort := os.Getenv("SERVER_PORT") 28 | serverString := fmt.Sprintf("%s:%s", serverHost, serverPort) 29 | router.Run(serverString) 30 | } 31 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/middleware/auth.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/middleware/cors_middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // CORSMiddleware Implementing CORS 8 | // return: gin HandlerFunc 9 | func (m *DefaultMiddleware) CORSMiddleware() gin.HandlerFunc { 10 | return func(c *gin.Context) { 11 | c.Writer.Header().Set("Access-Control-Allow-Origin", "*") 12 | c.Writer.Header().Set("Access-Control-Max-Age", "86400") 13 | c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE") 14 | c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") 15 | c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length") 16 | c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") 17 | if c.Request.Method == "OPTIONS" { 18 | c.AbortWithStatus(200) 19 | } else { 20 | c.Next() 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/middleware/middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | // DefaultMiddleware types 4 | type DefaultMiddleware struct { 5 | } 6 | -------------------------------------------------------------------------------- /orchestration/orchestrator/src/router/router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | v1 "github.com/sofyan48/orchestrator/src/app/v1/routes" 6 | ) 7 | 8 | // LoadRouter params 9 | // @routers: gin.Engine 10 | func LoadRouter(routers *gin.Engine) { 11 | version1 := v1.V1RouterLoaderHandler() 12 | version1.V1Routes(routers) 13 | } 14 | -------------------------------------------------------------------------------- /orchestration/orchestrator/watcher.conf: -------------------------------------------------------------------------------- 1 | root = "." 2 | watch_dir = "src" 3 | tmp_dir = "tmp" 4 | 5 | [build] 6 | cmd = "go build -o ./tmp/main src/main.go" 7 | bin = "tmp/main" 8 | log = "air_errors.log" 9 | include_ext = ["go", "tpl", "tmpl", "html"] 10 | exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules", "mydb"] 11 | delay = 1500 # ms 12 | 13 | [log] 14 | time = false 15 | 16 | [color] 17 | main = "magenta" 18 | watcher = "cyan" 19 | build = "yellow" 20 | runner = "green" 21 | # app = "white" -------------------------------------------------------------------------------- /orchestration/order/.dockerignore: -------------------------------------------------------------------------------- 1 | 2 | mydb 3 | .env 4 | tmp -------------------------------------------------------------------------------- /orchestration/order/.env.example: -------------------------------------------------------------------------------- 1 | #################################################################### 2 | # SERVER CONFIGURATION 3 | #################################################################### 4 | SERVER_ADDRESS=0.0.0.0 5 | SERVER_PORT=5000 6 | SERVER_TIMEZONE=Asia/Jakarta 7 | SECRET_KEY=xXbxnad!!sadsa 8 | 9 | 10 | #################################################################### 11 | # KAFKA CONFIGURATION 12 | #################################################################### 13 | KAFKA_HOST=127.0.0.1 14 | KAFKA_PORT=9092 15 | 16 | #################################################################### 17 | # SWAGGER CONFIGURATION 18 | #################################################################### 19 | SWAGGER_SERVER_ADDRESS=http://localhost:3000 20 | 21 | 22 | #################################################################### 23 | # LOGGER CONFIGURATION 24 | #################################################################### 25 | LOGGER_URL=localhost:3000 26 | -------------------------------------------------------------------------------- /orchestration/order/.gitignore: -------------------------------------------------------------------------------- 1 | # MAC OS CACHE 2 | .DS_Store 3 | 4 | # BINARY 5 | *.out 6 | *.exe 7 | *.exe~ 8 | *.dll 9 | *.so 10 | *.dylib 11 | 12 | # TEST 13 | *.test 14 | 15 | # ENV FOLDER 16 | .env 17 | env 18 | 19 | 20 | # Misc 21 | .idea 22 | src/.DS_Store 23 | go-pckg/* 24 | src/vendor/* 25 | coverage.out 26 | mydb 27 | 28 | main 29 | vendor 30 | .tmp 31 | tmp 32 | 33 | # qa_test 34 | /qa_test/reports/* 35 | /qa_test/node_modules 36 | /qa_test/package-lock.json 37 | /qa_test/.nyc_output 38 | 39 | # go sum 40 | go.sum 41 | db-init 42 | mongo 43 | -------------------------------------------------------------------------------- /orchestration/order/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:latest AS builder 2 | 3 | WORKDIR /app 4 | COPY . . 5 | 6 | RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o main -ldflags '-w -s' src/main.go 7 | 8 | ############################ 9 | # STEP 2 build a small image 10 | ############################ 11 | FROM scratch 12 | 13 | COPY --from=builder /app /usr/bin -------------------------------------------------------------------------------- /orchestration/order/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Sofyan Saputra 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /orchestration/order/Makefile: -------------------------------------------------------------------------------- 1 | # Build And Development 2 | test: 3 | @go test -v -cover ./... 4 | 5 | depend: 6 | @go get github.com/ralali/event-api 7 | 8 | devel: 9 | @air -c watcher.conf 10 | 11 | build: 12 | @go build -o bgin src/main.go 13 | 14 | run: 15 | @go run src/main.go 16 | 17 | production: 18 | @go run src/main.go -e production 19 | 20 | docker-stop: 21 | @docker-compose down 22 | 23 | docker-image: 24 | @docker build . -t bigevent_api 25 | 26 | docker-run: 27 | @docker-compose up 28 | 29 | .PHONY: test depend build run stop docker docker-stop docker-image docker-run devel 30 | -------------------------------------------------------------------------------- /orchestration/order/README.md: -------------------------------------------------------------------------------- 1 | # ORDER SERVICE LAYER SAGA EXAMPLE CHOREOGRAPHY SERVICE 2 | 3 | ## Getting Started 4 | 5 | ### Local 6 | Run local in stage : 7 | - development 8 | - production 9 | ``` 10 | go run src/main.go -e $stage 11 | ``` 12 | default stage in production 13 | 14 | ### Dockerizing 15 | In docker app default execute production stage 16 | ``` 17 | docker-compose up 18 | ``` 19 | -------------------------------------------------------------------------------- /orchestration/order/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | svc_gateway: 4 | image: meongbego/svc_gateway 5 | restart: always 6 | ports: 7 | - 80:80 8 | environment: 9 | - SERVER_ADDRESS=0.0.0.0 10 | - SERVER_PORT=80 11 | - SERVER_TIMEZONE=Asia/Jakarta 12 | - APP_NAME=gateway 13 | - KAFKA_HOST=localhost 14 | - KAFKA_PORT=9092 15 | - SWAGGER_SERVER_ADDRESS=http://0.0.0.0 16 | - LOGGER_URL=logger:3000 17 | command: /usr/bin/main -e production 18 | 19 | -------------------------------------------------------------------------------- /orchestration/order/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/sofyan48/order 2 | 3 | go 1.13 4 | 5 | require ( 6 | cloud.google.com/go v0.54.0 // indirect 7 | github.com/Shopify/sarama v1.26.1 8 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 9 | github.com/apache/thrift v0.13.0 // indirect 10 | github.com/gin-gonic/gin v1.5.0 11 | github.com/google/uuid v1.1.1 12 | github.com/jinzhu/gorm v1.9.12 13 | github.com/joho/godotenv v1.3.0 14 | github.com/openzipkin/zipkin-go v0.1.6 // indirect 15 | github.com/sofyan48/go-cinlog v1.0.0 16 | github.com/stretchr/testify v1.5.1 17 | github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 18 | github.com/swaggo/gin-swagger v1.2.0 19 | github.com/swaggo/swag v1.6.3 20 | go.mongodb.org/mongo-driver v1.3.1 21 | golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72 22 | ) 23 | -------------------------------------------------------------------------------- /orchestration/order/src/app/v1/api/health/controller/health.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/sofyan48/order/src/app/v1/api/health/service" 8 | "github.com/sofyan48/order/src/app/v1/utility/rest" 9 | ) 10 | 11 | // HealthController types 12 | type HealthController struct { 13 | Service service.HealthServiceInterface 14 | } 15 | 16 | // HealthControllerHandler ... 17 | func HealthControllerHandler() *HealthController { 18 | return &HealthController{ 19 | Service: service.HealthServiceHandler(), 20 | } 21 | } 22 | 23 | // HealthControllerInterface ... 24 | type HealthControllerInterface interface { 25 | Health(context *gin.Context) 26 | } 27 | 28 | // Health params 29 | // @contex: gin Context 30 | func (ctrl *HealthController) Health(context *gin.Context) { 31 | data := ctrl.Service.HealthService() 32 | rest.ResponseData(context, http.StatusOK, data) 33 | return 34 | } 35 | -------------------------------------------------------------------------------- /orchestration/order/src/app/v1/api/health/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // HealtResponse ... 6 | type HealtResponse struct { 7 | Status string `json:"status"` 8 | CreatedAt *time.Time `json:"created_at"` 9 | } 10 | -------------------------------------------------------------------------------- /orchestration/order/src/app/v1/api/health/service/health.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/sofyan48/order/src/app/v1/api/health/entity" 7 | ) 8 | 9 | // HealthService ... 10 | type HealthService struct{} 11 | 12 | // HealthServiceHandler ... 13 | func HealthServiceHandler() *HealthService { 14 | return &HealthService{} 15 | } 16 | 17 | // HealthServiceInterface ... 18 | type HealthServiceInterface interface { 19 | HealthService() *entity.HealtResponse 20 | } 21 | 22 | // HealthService ... 23 | func (service *HealthService) HealthService() *entity.HealtResponse { 24 | now := time.Now() 25 | result := &entity.HealtResponse{} 26 | result.Status = "OK" 27 | result.CreatedAt = &now 28 | return result 29 | } 30 | -------------------------------------------------------------------------------- /orchestration/order/src/app/v1/routes/docs.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | swaggerFiles "github.com/swaggo/files" 6 | ginSwagger "github.com/swaggo/gin-swagger" 7 | 8 | _ "github.com/sofyan48/order/src/app/v1/swagger/docs" 9 | ) 10 | 11 | // DOCROUTES ... 12 | const DOCROUTES = VERSION + "/docs" 13 | 14 | func (rLoader *V1RouterLoader) initDocs(router *gin.Engine) { 15 | group := router.Group(DOCROUTES) 16 | url := ginSwagger.URL("swagger/doc.json") 17 | group.GET("/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url)) 18 | } 19 | -------------------------------------------------------------------------------- /orchestration/order/src/app/v1/routes/health.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // HEALTHROUTES ... 8 | const HEALTHROUTES = VERSION + "/health" 9 | 10 | func (rLoader *V1RouterLoader) initHealth(router *gin.Engine) { 11 | group := router.Group(HEALTHROUTES) 12 | group.GET("", rLoader.Health.Health) 13 | } 14 | -------------------------------------------------------------------------------- /orchestration/order/src/app/v1/routes/routes.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | health "github.com/sofyan48/order/src/app/v1/api/health/controller" 6 | 7 | "github.com/sofyan48/order/src/middleware" 8 | ) 9 | 10 | // VERSION ... 11 | const VERSION = "v1" 12 | 13 | // V1RouterLoader types 14 | type V1RouterLoader struct { 15 | Middleware middleware.DefaultMiddleware 16 | Health health.HealthControllerInterface 17 | } 18 | 19 | // V1RouterLoaderHandler ... 20 | func V1RouterLoaderHandler() *V1RouterLoader { 21 | return &V1RouterLoader{ 22 | Health: health.HealthControllerHandler(), 23 | } 24 | } 25 | 26 | // V1RouterLoaderInterface ... 27 | type V1RouterLoaderInterface interface { 28 | V1Routes(router *gin.Engine) 29 | } 30 | 31 | // V1Routes Params 32 | // @router: gin.Engine 33 | func (rLoader *V1RouterLoader) V1Routes(router *gin.Engine) { 34 | rLoader.initDocs(router) 35 | rLoader.initHealth(router) 36 | } 37 | -------------------------------------------------------------------------------- /orchestration/order/src/app/v1/swagger/docs/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "contact": {}, 5 | "license": {} 6 | }, 7 | "paths": {} 8 | } -------------------------------------------------------------------------------- /orchestration/order/src/app/v1/swagger/docs/swagger.yaml: -------------------------------------------------------------------------------- 1 | info: 2 | contact: {} 3 | license: {} 4 | paths: {} 5 | swagger: "2.0" 6 | -------------------------------------------------------------------------------- /orchestration/order/src/app/v1/utility/kafka/consumer.go: -------------------------------------------------------------------------------- 1 | package kafka 2 | 3 | import ( 4 | "log" 5 | "os" 6 | 7 | "github.com/Shopify/sarama" 8 | ) 9 | 10 | // InitConsumer ... 11 | func (kafka *KafkaLibrary) InitConsumer(group string) (sarama.ConsumerGroup, error) { 12 | configKafka := kafka.initConsumerConfig("", "") 13 | kafkaHost := os.Getenv("KAFKA_HOST") 14 | kafkaPort := os.Getenv("KAFKA_PORT") 15 | version, err := sarama.ParseKafkaVersion(os.Getenv("KAFKA_VERSION")) 16 | if err != nil { 17 | log.Panicf("Error parsing Kafka version: %v", err) 18 | } 19 | configKafka.Version = version 20 | return sarama.NewConsumerGroup([]string{kafkaHost + ":" + kafkaPort}, group, configKafka) 21 | } 22 | -------------------------------------------------------------------------------- /orchestration/order/src/app/v1/utility/rest/rest.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // Respons types 8 | type Respons struct { 9 | Status int `json:"status"` 10 | Meta interface{} `json:"meta"` 11 | Results interface{} `json:"results"` 12 | } 13 | 14 | // ResponseList params 15 | // @context: *gin.Context 16 | // status: int 17 | // payload: interface{} 18 | func ResponseList(context *gin.Context, status int, payload, meta interface{}) { 19 | var res Respons 20 | res.Status = status 21 | res.Results = payload 22 | res.Meta = meta 23 | context.JSON(status, res) 24 | return 25 | } 26 | 27 | // ResponseData params 28 | // @context: *gin.Context 29 | // status: int 30 | // payload: interface{} 31 | func ResponseData(context *gin.Context, status int, payload interface{}) { 32 | context.JSON(status, payload) 33 | return 34 | } 35 | 36 | // ResponseMessages params 37 | // @context: *gin.Context 38 | // status: int 39 | // msg: string 40 | func ResponseMessages(context *gin.Context, status int, msg string) { 41 | context.JSON(status, gin.H{ 42 | "messages": msg, 43 | }) 44 | return 45 | } 46 | -------------------------------------------------------------------------------- /orchestration/order/src/app/v1/utility/rest/rest_test.go: -------------------------------------------------------------------------------- 1 | package rest 2 | -------------------------------------------------------------------------------- /orchestration/order/src/config/server_configuration.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/joho/godotenv" 8 | "github.com/sofyan48/order/src/middleware" 9 | ) 10 | 11 | // SetupEngine server router configuration 12 | func SetupEngine(env string) *gin.Engine { 13 | defaultMiddleware := middleware.DefaultMiddleware{} 14 | configEnvironment(env) 15 | router := gin.Default() 16 | router.Use(defaultMiddleware.CORSMiddleware()) 17 | return router 18 | } 19 | 20 | // ConfigEnvironment ... 21 | func configEnvironment(env string) { 22 | switch env { 23 | case "development": 24 | err := godotenv.Load() 25 | if err != nil { 26 | log.Fatal("Error loading .env file") 27 | } 28 | case "production": 29 | gin.SetMode(gin.ReleaseMode) 30 | log.Println("Engine Running") 31 | default: 32 | err := godotenv.Load() 33 | if err != nil { 34 | log.Fatal("Error loading .env file") 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /orchestration/order/src/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/sofyan48/order/src/config" 9 | 10 | apiRouter "github.com/sofyan48/order/src/router" 11 | ) 12 | 13 | func main() { 14 | environment := flag.String("e", "development", "") 15 | flag.Usage = func() { 16 | fmt.Println("Usage: server -e {mode}") 17 | os.Exit(1) 18 | } 19 | flag.Parse() 20 | startApp(*environment) 21 | } 22 | 23 | func startApp(env string) { 24 | router := config.SetupEngine(env) 25 | apiRouter.LoadRouter(router) 26 | serverHost := os.Getenv("SERVER_ADDRESS") 27 | serverPort := os.Getenv("SERVER_PORT") 28 | serverString := fmt.Sprintf("%s:%s", serverHost, serverPort) 29 | router.Run(serverString) 30 | } 31 | -------------------------------------------------------------------------------- /orchestration/order/src/middleware/auth.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | -------------------------------------------------------------------------------- /orchestration/order/src/middleware/cors_middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // CORSMiddleware Implementing CORS 8 | // return: gin HandlerFunc 9 | func (m *DefaultMiddleware) CORSMiddleware() gin.HandlerFunc { 10 | return func(c *gin.Context) { 11 | c.Writer.Header().Set("Access-Control-Allow-Origin", "*") 12 | c.Writer.Header().Set("Access-Control-Max-Age", "86400") 13 | c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE") 14 | c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") 15 | c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length") 16 | c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") 17 | if c.Request.Method == "OPTIONS" { 18 | c.AbortWithStatus(200) 19 | } else { 20 | c.Next() 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /orchestration/order/src/middleware/middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | // DefaultMiddleware types 4 | type DefaultMiddleware struct { 5 | } 6 | -------------------------------------------------------------------------------- /orchestration/order/src/router/router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | v1 "github.com/sofyan48/order/src/app/v1/routes" 6 | ) 7 | 8 | // LoadRouter params 9 | // @routers: gin.Engine 10 | func LoadRouter(routers *gin.Engine) { 11 | version1 := v1.V1RouterLoaderHandler() 12 | version1.V1Routes(routers) 13 | } 14 | -------------------------------------------------------------------------------- /orchestration/order/watcher.conf: -------------------------------------------------------------------------------- 1 | root = "." 2 | watch_dir = "src" 3 | tmp_dir = "tmp" 4 | 5 | [build] 6 | cmd = "go build -o ./tmp/main src/main.go" 7 | bin = "tmp/main" 8 | log = "air_errors.log" 9 | include_ext = ["go", "tpl", "tmpl", "html"] 10 | exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules", "mydb"] 11 | delay = 1500 # ms 12 | 13 | [log] 14 | time = false 15 | 16 | [color] 17 | main = "magenta" 18 | watcher = "cyan" 19 | build = "yellow" 20 | runner = "green" 21 | # app = "white" -------------------------------------------------------------------------------- /orchestration/payment/.dockerignore: -------------------------------------------------------------------------------- 1 | 2 | mydb 3 | .env 4 | tmp -------------------------------------------------------------------------------- /orchestration/payment/.env.example: -------------------------------------------------------------------------------- 1 | #################################################################### 2 | # SERVER CONFIGURATION 3 | #################################################################### 4 | SERVER_ADDRESS=0.0.0.0 5 | SERVER_PORT=5000 6 | SERVER_TIMEZONE=Asia/Jakarta 7 | SECRET_KEY=xXbxnad!!sadsa 8 | 9 | 10 | #################################################################### 11 | # KAFKA CONFIGURATION 12 | #################################################################### 13 | KAFKA_HOST=127.0.0.1 14 | KAFKA_PORT=9092 15 | 16 | #################################################################### 17 | # SWAGGER CONFIGURATION 18 | #################################################################### 19 | SWAGGER_SERVER_ADDRESS=http://localhost:3000 20 | 21 | 22 | #################################################################### 23 | # LOGGER CONFIGURATION 24 | #################################################################### 25 | LOGGER_URL=localhost:3000 26 | -------------------------------------------------------------------------------- /orchestration/payment/.gitignore: -------------------------------------------------------------------------------- 1 | # MAC OS CACHE 2 | .DS_Store 3 | 4 | # BINARY 5 | *.out 6 | *.exe 7 | *.exe~ 8 | *.dll 9 | *.so 10 | *.dylib 11 | 12 | # TEST 13 | *.test 14 | 15 | # ENV FOLDER 16 | .env 17 | env 18 | 19 | 20 | # Misc 21 | .idea 22 | src/.DS_Store 23 | go-pckg/* 24 | src/vendor/* 25 | coverage.out 26 | mydb 27 | 28 | main 29 | vendor 30 | .tmp 31 | tmp 32 | 33 | # qa_test 34 | /qa_test/reports/* 35 | /qa_test/node_modules 36 | /qa_test/package-lock.json 37 | /qa_test/.nyc_output 38 | 39 | # go sum 40 | go.sum 41 | db-init 42 | mongo 43 | -------------------------------------------------------------------------------- /orchestration/payment/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:latest AS builder 2 | 3 | WORKDIR /app 4 | COPY . . 5 | 6 | RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o main -ldflags '-w -s' src/main.go 7 | 8 | ############################ 9 | # STEP 2 build a small image 10 | ############################ 11 | FROM scratch 12 | 13 | COPY --from=builder /app /usr/bin -------------------------------------------------------------------------------- /orchestration/payment/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Sofyan Saputra 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /orchestration/payment/Makefile: -------------------------------------------------------------------------------- 1 | # Build And Development 2 | test: 3 | @go test -v -cover ./... 4 | 5 | depend: 6 | @go get github.com/ralali/event-api 7 | 8 | devel: 9 | @air -c watcher.conf 10 | 11 | build: 12 | @go build -o bgin src/main.go 13 | 14 | run: 15 | @go run src/main.go 16 | 17 | production: 18 | @go run src/main.go -e production 19 | 20 | docker-stop: 21 | @docker-compose down 22 | 23 | docker-image: 24 | @docker build . -t bigevent_api 25 | 26 | docker-run: 27 | @docker-compose up 28 | 29 | .PHONY: test depend build run stop docker docker-stop docker-image docker-run devel 30 | -------------------------------------------------------------------------------- /orchestration/payment/README.md: -------------------------------------------------------------------------------- 1 | # PAYMENT LAYER SAGA EXAMPLE CHOREOGRAPHY SERVICE 2 | 3 | ## Getting Started 4 | 5 | ### Local 6 | Run local in stage : 7 | - development 8 | - production 9 | ``` 10 | go run src/main.go -e $stage 11 | ``` 12 | default stage in production 13 | 14 | ### Dockerizing 15 | In docker app default execute production stage 16 | ``` 17 | docker-compose up 18 | ``` 19 | -------------------------------------------------------------------------------- /orchestration/payment/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | svc_gateway: 4 | image: meongbego/svc_gateway 5 | restart: always 6 | ports: 7 | - 80:80 8 | environment: 9 | - SERVER_ADDRESS=0.0.0.0 10 | - SERVER_PORT=80 11 | - SERVER_TIMEZONE=Asia/Jakarta 12 | - APP_NAME=gateway 13 | - KAFKA_HOST=localhost 14 | - KAFKA_PORT=9092 15 | - SWAGGER_SERVER_ADDRESS=http://0.0.0.0 16 | - LOGGER_URL=logger:3000 17 | command: /usr/bin/main -e production 18 | 19 | -------------------------------------------------------------------------------- /orchestration/payment/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/sofyan48/payment 2 | 3 | go 1.13 4 | 5 | require ( 6 | cloud.google.com/go v0.54.0 // indirect 7 | github.com/Shopify/sarama v1.26.1 8 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 9 | github.com/apache/thrift v0.13.0 // indirect 10 | github.com/gin-gonic/gin v1.5.0 11 | github.com/google/uuid v1.1.1 12 | github.com/jinzhu/gorm v1.9.12 13 | github.com/joho/godotenv v1.3.0 14 | github.com/openzipkin/zipkin-go v0.1.6 // indirect 15 | github.com/sofyan48/go-cinlog v1.0.0 16 | github.com/stretchr/testify v1.5.1 17 | github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 18 | github.com/swaggo/gin-swagger v1.2.0 19 | github.com/swaggo/swag v1.6.3 20 | go.mongodb.org/mongo-driver v1.3.1 21 | golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72 22 | ) 23 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/api/health/controller/health.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/sofyan48/payment/src/app/v1/api/health/service" 8 | "github.com/sofyan48/payment/src/app/v1/utility/rest" 9 | ) 10 | 11 | // HealthController types 12 | type HealthController struct { 13 | Service service.HealthServiceInterface 14 | } 15 | 16 | // HealthControllerHandler ... 17 | func HealthControllerHandler() *HealthController { 18 | return &HealthController{ 19 | Service: service.HealthServiceHandler(), 20 | } 21 | } 22 | 23 | // HealthControllerInterface ... 24 | type HealthControllerInterface interface { 25 | Health(context *gin.Context) 26 | } 27 | 28 | // Health params 29 | // @contex: gin Context 30 | func (ctrl *HealthController) Health(context *gin.Context) { 31 | data := ctrl.Service.HealthService() 32 | rest.ResponseData(context, http.StatusOK, data) 33 | return 34 | } 35 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/api/health/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // HealtResponse ... 6 | type HealtResponse struct { 7 | Status string `json:"status"` 8 | CreatedAt *time.Time `json:"created_at"` 9 | } 10 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/api/health/service/health.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/sofyan48/payment/src/app/v1/api/health/entity" 7 | ) 8 | 9 | // HealthService ... 10 | type HealthService struct{} 11 | 12 | // HealthServiceHandler ... 13 | func HealthServiceHandler() *HealthService { 14 | return &HealthService{} 15 | } 16 | 17 | // HealthServiceInterface ... 18 | type HealthServiceInterface interface { 19 | HealthService() *entity.HealtResponse 20 | } 21 | 22 | // HealthService ... 23 | func (service *HealthService) HealthService() *entity.HealtResponse { 24 | now := time.Now() 25 | result := &entity.HealtResponse{} 26 | result.Status = "OK" 27 | result.CreatedAt = &now 28 | return result 29 | } 30 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/api/login/entity/event.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // UserEvent ... 8 | type UserEvent struct { 9 | UUID string `json:"__uuid" ` 10 | Action string `json:"__action"` 11 | Offset int64 `json:"__offset"` 12 | Data map[string]interface{} `json:"data"` 13 | Status string `json:"status"` 14 | CreatedAt *time.Time `json:"created_at"` 15 | } 16 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/api/login/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // UserRequest ... 6 | type UserRequest struct { 7 | FirstName string `json:"first_name"` 8 | LastName string `json:"last_name"` 9 | Email string `json:"email"` 10 | PhoneNumber string `json:"handphone"` 11 | Address string `json:"address"` 12 | City string `json:"city"` 13 | Province string `json:"province"` 14 | District string `json:"district"` 15 | } 16 | 17 | // UserResponses ... 18 | type UserResponses struct { 19 | UUID string `json:"uuid"` 20 | CreatedAt *time.Time `json:"created_at"` 21 | Event *UserEvent `json:"event"` 22 | } 23 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/api/login/event/event.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | "github.com/sofyan48/payment/src/app/v1/api/user/entity" 6 | "github.com/sofyan48/payment/src/app/v1/utility/kafka" 7 | ) 8 | 9 | // USEREVENT ... 10 | const USEREVENT = "users" 11 | 12 | // UserEvent ... 13 | type UserEvent struct { 14 | Kafka kafka.KafkaLibraryInterface 15 | } 16 | 17 | // UserEventHandler ... 18 | func UserEventHandler() *UserEvent { 19 | return &UserEvent{ 20 | Kafka: kafka.KafkaLibraryHandler(), 21 | } 22 | } 23 | 24 | // UserEventInterface ... 25 | type UserEventInterface interface { 26 | UserCreateEvent(data *entity.UserEvent) (*entity.UserEvent, error) 27 | } 28 | 29 | // UserCreateEvent ... 30 | func (event *UserEvent) UserCreateEvent(data *entity.UserEvent) (*entity.UserEvent, error) { 31 | format := event.Kafka.GetStateFull() 32 | format.Action = data.Action 33 | format.CreatedAt = data.CreatedAt 34 | format.Data = data.Data 35 | format.UUID = uuid.New().String() 36 | data.UUID = format.UUID 37 | go event.Kafka.SendEvent(USEREVENT, format) 38 | data.Status = "QUEUE" 39 | return data, nil 40 | } 41 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/api/order/entity/event.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // OrderEvent ... 8 | type OrderEvent struct { 9 | UUID string `json:"__uuid" ` 10 | Action string `json:"__action"` 11 | Offset int64 `json:"__offset"` 12 | Data map[string]interface{} `json:"data"` 13 | Status string `json:"status"` 14 | CreatedAt *time.Time `json:"created_at"` 15 | } 16 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/api/order/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // OrderRequest ... 6 | type OrderRequest struct { 7 | OrderNumber string `json:"order_number"` 8 | UserUUID string `json:"uuid_user"` 9 | IDOrderType string `json:"id_order_type"` 10 | IDOrderStatus string `json:"id_order_status"` 11 | IDPaymentStatus string `json:"id_payment_status"` 12 | IDPaymentModel string `json:"id_payment_model"` 13 | InquiryNumber string `json:"inquiry_number"` 14 | PaymentOrder string `json:"payment_order"` 15 | NMBank string `json:"nm_bank"` 16 | } 17 | 18 | // OrderResponses ... 19 | type OrderResponses struct { 20 | UUID string `json:"uuid"` 21 | CreatedAt *time.Time `json:"created_at"` 22 | Event *OrderEvent `json:"event"` 23 | } 24 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/api/order/event/event.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | "github.com/sofyan48/payment/src/app/v1/api/order/entity" 6 | "github.com/sofyan48/payment/src/app/v1/utility/kafka" 7 | ) 8 | 9 | // ORDEREVENT ... 10 | const ORDEREVENT = "order" 11 | 12 | // OrderEvent ... 13 | type OrderEvent struct { 14 | Kafka kafka.KafkaLibraryInterface 15 | } 16 | 17 | // OrderEventHandler ... 18 | func OrderEventHandler() *OrderEvent { 19 | return &OrderEvent{ 20 | Kafka: kafka.KafkaLibraryHandler(), 21 | } 22 | } 23 | 24 | // OrderEventInterface ... 25 | type OrderEventInterface interface { 26 | OrderCreateEvent(data *entity.OrderEvent) (*entity.OrderEvent, error) 27 | } 28 | 29 | // OrderCreateEvent ... 30 | func (event *OrderEvent) OrderCreateEvent(data *entity.OrderEvent) (*entity.OrderEvent, error) { 31 | format := event.Kafka.GetStateFull() 32 | format.Action = data.Action 33 | format.CreatedAt = data.CreatedAt 34 | format.Data = data.Data 35 | format.UUID = uuid.New().String() 36 | data.UUID = format.UUID 37 | go event.Kafka.SendEvent(ORDEREVENT, format) 38 | data.Status = "QUEUE" 39 | return data, nil 40 | } 41 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/api/payment/entity/event.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // PaymentEvent ... 8 | type PaymentEvent struct { 9 | UUID string `json:"__uuid" ` 10 | Action string `json:"__action"` 11 | Offset int64 `json:"__offset"` 12 | Data map[string]interface{} `json:"data"` 13 | Status string `json:"status"` 14 | CreatedAt *time.Time `json:"created_at"` 15 | } 16 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/api/payment/entity/general.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | // Pagination .. 4 | type Pagination struct { 5 | Limit int `json:"limit" form:"limit"` 6 | Page int `json:"page" form:"page"` 7 | } 8 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/api/payment/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // PaymentRequest ... 6 | type PaymentRequest struct { 7 | UUIDOrder string `json:"uuid_order"` 8 | UUIDUser string `json:"uuid_user"` 9 | IDPaymentStatus string `json:"id_payment_status"` 10 | IDPaymentModel string `json:"id_payment_model"` 11 | InquiryNumber string `json:"inquiry_number"` 12 | BankAccountNumber string `json:"bank_account_number"` 13 | NMBank string `json:"nm_bank"` 14 | PaymentTotal int `json:"payment_total"` 15 | } 16 | 17 | // PaymentPaidRequest ... 18 | type PaymentPaidRequest struct { 19 | PaymentTotal int `json:"payment_total"` 20 | PaymentStatus string `json:"payment_status"` 21 | BankAccountNumber string `json:"bank_account_number"` 22 | } 23 | 24 | // PaymentResponses ... 25 | type PaymentResponses struct { 26 | UUID string `json:"uuid"` 27 | CreatedAt *time.Time `json:"created_at"` 28 | Event *PaymentEvent `json:"event"` 29 | } 30 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/api/user/entity/event.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // UserEvent ... 8 | type UserEvent struct { 9 | UUID string `json:"__uuid" ` 10 | Action string `json:"__action"` 11 | Offset int64 `json:"__offset"` 12 | Data map[string]interface{} `json:"data"` 13 | Status string `json:"status"` 14 | CreatedAt *time.Time `json:"created_at"` 15 | } 16 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/api/user/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // UserRequest ... 6 | type UserRequest struct { 7 | FirstName string `json:"first_name"` 8 | LastName string `json:"last_name"` 9 | Email string `json:"email"` 10 | PhoneNumber string `json:"handphone"` 11 | Address string `json:"address"` 12 | City string `json:"city"` 13 | Province string `json:"province"` 14 | District string `json:"district"` 15 | } 16 | 17 | // UserResponses ... 18 | type UserResponses struct { 19 | UUID string `json:"uuid"` 20 | CreatedAt *time.Time `json:"created_at"` 21 | Event *UserEvent `json:"event"` 22 | } 23 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/api/user/event/event.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | "github.com/sofyan48/payment/src/app/v1/api/user/entity" 6 | "github.com/sofyan48/payment/src/app/v1/utility/kafka" 7 | ) 8 | 9 | // USEREVENT ... 10 | const USEREVENT = "users" 11 | 12 | // UserEvent ... 13 | type UserEvent struct { 14 | Kafka kafka.KafkaLibraryInterface 15 | } 16 | 17 | // UserEventHandler ... 18 | func UserEventHandler() *UserEvent { 19 | return &UserEvent{ 20 | Kafka: kafka.KafkaLibraryHandler(), 21 | } 22 | } 23 | 24 | // UserEventInterface ... 25 | type UserEventInterface interface { 26 | UserCreateEvent(data *entity.UserEvent) (*entity.UserEvent, error) 27 | } 28 | 29 | // UserCreateEvent ... 30 | func (event *UserEvent) UserCreateEvent(data *entity.UserEvent) (*entity.UserEvent, error) { 31 | format := event.Kafka.GetStateFull() 32 | format.Action = data.Action 33 | format.CreatedAt = data.CreatedAt 34 | format.Data = data.Data 35 | format.UUID = uuid.New().String() 36 | data.UUID = format.UUID 37 | go event.Kafka.SendEvent(USEREVENT, format) 38 | data.Status = "QUEUE" 39 | return data, nil 40 | } 41 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/routes/docs.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | swaggerFiles "github.com/swaggo/files" 6 | ginSwagger "github.com/swaggo/gin-swagger" 7 | 8 | _ "github.com/sofyan48/payment/src/app/v1/swagger/docs" 9 | ) 10 | 11 | // DOCROUTES ... 12 | const DOCROUTES = VERSION + "/docs" 13 | 14 | func (rLoader *V1RouterLoader) initDocs(router *gin.Engine) { 15 | group := router.Group(DOCROUTES) 16 | url := ginSwagger.URL("swagger/doc.json") 17 | group.GET("/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url)) 18 | } 19 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/routes/health.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // HEALTHROUTES ... 8 | const HEALTHROUTES = VERSION + "/health" 9 | 10 | func (rLoader *V1RouterLoader) initHealth(router *gin.Engine) { 11 | group := router.Group(HEALTHROUTES) 12 | group.GET("", rLoader.Health.Health) 13 | } 14 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/routes/order.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // ORDERROUTES ... 6 | const ORDERROUTES = VERSION + "/order" 7 | 8 | func (rLoader *V1RouterLoader) initOrder(router *gin.Engine) { 9 | group := router.Group(ORDERROUTES) 10 | group.POST("", rLoader.Order.OrderCreate) 11 | group.GET(":uuid", rLoader.Order.GetOrderData) 12 | group.PUT(":uuid", rLoader.Order.UpdateOrder) 13 | group.DELETE(":uuid", rLoader.Order.DeleteOrder) 14 | } 15 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/routes/payment.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // PAYMENTROUTES ... 6 | const PAYMENTROUTES = VERSION + "/payment" 7 | 8 | func (rLoader *V1RouterLoader) initPayment(router *gin.Engine) { 9 | group := router.Group(PAYMENTROUTES) 10 | group.POST("", rLoader.Payment.PaymentCreate) 11 | group.GET("/get/:uuid", rLoader.Payment.GetPaymentData) 12 | group.PUT(":uuid", rLoader.Payment.UpdatePaidPayment) 13 | group.DELETE(":uuid", rLoader.Payment.DeletePayment) 14 | group.GET("list", rLoader.Payment.ListPayment) 15 | } 16 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/routes/user.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // USERROUTES ... 6 | const USERROUTES = VERSION + "/user" 7 | 8 | func (rLoader *V1RouterLoader) initUser(router *gin.Engine) { 9 | group := router.Group(USERROUTES) 10 | group.POST("", rLoader.User.UserCreate) 11 | group.GET(":uuid", rLoader.User.GetUserData) 12 | group.PUT(":uuid", rLoader.User.UpdateUser) 13 | group.DELETE(":uuid") 14 | } 15 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/swagger/docs/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "contact": {}, 5 | "license": {} 6 | }, 7 | "paths": {} 8 | } -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/swagger/docs/swagger.yaml: -------------------------------------------------------------------------------- 1 | info: 2 | contact: {} 3 | license: {} 4 | paths: {} 5 | swagger: "2.0" 6 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/utility/kafka/consumer.go: -------------------------------------------------------------------------------- 1 | package kafka 2 | 3 | import ( 4 | "log" 5 | "os" 6 | 7 | "github.com/Shopify/sarama" 8 | ) 9 | 10 | // InitConsumer ... 11 | func (kafka *KafkaLibrary) InitConsumer(group string) (sarama.ConsumerGroup, error) { 12 | configKafka := kafka.initConsumerConfig("", "") 13 | kafkaHost := os.Getenv("KAFKA_HOST") 14 | kafkaPort := os.Getenv("KAFKA_PORT") 15 | version, err := sarama.ParseKafkaVersion(os.Getenv("KAFKA_VERSION")) 16 | if err != nil { 17 | log.Panicf("Error parsing Kafka version: %v", err) 18 | } 19 | configKafka.Version = version 20 | return sarama.NewConsumerGroup([]string{kafkaHost + ":" + kafkaPort}, group, configKafka) 21 | } 22 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/utility/rest/rest.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // Respons types 8 | type Respons struct { 9 | Status int `json:"status"` 10 | Meta interface{} `json:"meta"` 11 | Results interface{} `json:"results"` 12 | } 13 | 14 | // ResponseList params 15 | // @context: *gin.Context 16 | // status: int 17 | // payload: interface{} 18 | func ResponseList(context *gin.Context, status int, payload, meta interface{}) { 19 | var res Respons 20 | res.Status = status 21 | res.Results = payload 22 | res.Meta = meta 23 | context.JSON(status, res) 24 | return 25 | } 26 | 27 | // ResponseData params 28 | // @context: *gin.Context 29 | // status: int 30 | // payload: interface{} 31 | func ResponseData(context *gin.Context, status int, payload interface{}) { 32 | context.JSON(status, payload) 33 | return 34 | } 35 | 36 | // ResponseMessages params 37 | // @context: *gin.Context 38 | // status: int 39 | // msg: string 40 | func ResponseMessages(context *gin.Context, status int, msg string) { 41 | context.JSON(status, gin.H{ 42 | "messages": msg, 43 | }) 44 | return 45 | } 46 | -------------------------------------------------------------------------------- /orchestration/payment/src/app/v1/utility/rest/rest_test.go: -------------------------------------------------------------------------------- 1 | package rest 2 | -------------------------------------------------------------------------------- /orchestration/payment/src/config/server_configuration.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/joho/godotenv" 8 | "github.com/sofyan48/payment/src/middleware" 9 | ) 10 | 11 | // SetupEngine server router configuration 12 | func SetupEngine(env string) *gin.Engine { 13 | defaultMiddleware := middleware.DefaultMiddleware{} 14 | configEnvironment(env) 15 | router := gin.Default() 16 | router.Use(defaultMiddleware.CORSMiddleware()) 17 | return router 18 | } 19 | 20 | // ConfigEnvironment ... 21 | func configEnvironment(env string) { 22 | switch env { 23 | case "development": 24 | err := godotenv.Load() 25 | if err != nil { 26 | log.Fatal("Error loading .env file") 27 | } 28 | case "production": 29 | gin.SetMode(gin.ReleaseMode) 30 | log.Println("Engine Running") 31 | default: 32 | err := godotenv.Load() 33 | if err != nil { 34 | log.Fatal("Error loading .env file") 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /orchestration/payment/src/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/sofyan48/payment/src/config" 9 | 10 | apiRouter "github.com/sofyan48/payment/src/router" 11 | ) 12 | 13 | func main() { 14 | environment := flag.String("e", "development", "") 15 | flag.Usage = func() { 16 | fmt.Println("Usage: server -e {mode}") 17 | os.Exit(1) 18 | } 19 | flag.Parse() 20 | startApp(*environment) 21 | } 22 | 23 | func startApp(env string) { 24 | router := config.SetupEngine(env) 25 | apiRouter.LoadRouter(router) 26 | serverHost := os.Getenv("SERVER_ADDRESS") 27 | serverPort := os.Getenv("SERVER_PORT") 28 | serverString := fmt.Sprintf("%s:%s", serverHost, serverPort) 29 | router.Run(serverString) 30 | } 31 | -------------------------------------------------------------------------------- /orchestration/payment/src/middleware/auth.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | -------------------------------------------------------------------------------- /orchestration/payment/src/middleware/cors_middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // CORSMiddleware Implementing CORS 8 | // return: gin HandlerFunc 9 | func (m *DefaultMiddleware) CORSMiddleware() gin.HandlerFunc { 10 | return func(c *gin.Context) { 11 | c.Writer.Header().Set("Access-Control-Allow-Origin", "*") 12 | c.Writer.Header().Set("Access-Control-Max-Age", "86400") 13 | c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE") 14 | c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") 15 | c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length") 16 | c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") 17 | if c.Request.Method == "OPTIONS" { 18 | c.AbortWithStatus(200) 19 | } else { 20 | c.Next() 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /orchestration/payment/src/middleware/middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | // DefaultMiddleware types 4 | type DefaultMiddleware struct { 5 | } 6 | -------------------------------------------------------------------------------- /orchestration/payment/src/router/router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | v1 "github.com/sofyan48/payment/src/app/v1/routes" 6 | ) 7 | 8 | // LoadRouter params 9 | // @routers: gin.Engine 10 | func LoadRouter(routers *gin.Engine) { 11 | version1 := v1.V1RouterLoaderHandler() 12 | version1.V1Routes(routers) 13 | } 14 | -------------------------------------------------------------------------------- /orchestration/payment/watcher.conf: -------------------------------------------------------------------------------- 1 | root = "." 2 | watch_dir = "src" 3 | tmp_dir = "tmp" 4 | 5 | [build] 6 | cmd = "go build -o ./tmp/main src/main.go" 7 | bin = "tmp/main" 8 | log = "air_errors.log" 9 | include_ext = ["go", "tpl", "tmpl", "html"] 10 | exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules", "mydb"] 11 | delay = 1500 # ms 12 | 13 | [log] 14 | time = false 15 | 16 | [color] 17 | main = "magenta" 18 | watcher = "cyan" 19 | build = "yellow" 20 | runner = "green" 21 | # app = "white" -------------------------------------------------------------------------------- /orchestration/user/.dockerignore: -------------------------------------------------------------------------------- 1 | 2 | mydb 3 | .env 4 | tmp -------------------------------------------------------------------------------- /orchestration/user/.env.example: -------------------------------------------------------------------------------- 1 | #################################################################### 2 | # SERVER CONFIGURATION 3 | #################################################################### 4 | SERVER_ADDRESS=0.0.0.0 5 | SERVER_PORT=5000 6 | SERVER_TIMEZONE=Asia/Jakarta 7 | SECRET_KEY=xXbxnad!!sadsa 8 | 9 | 10 | #################################################################### 11 | # KAFKA CONFIGURATION 12 | #################################################################### 13 | KAFKA_HOST=127.0.0.1 14 | KAFKA_PORT=9092 15 | 16 | #################################################################### 17 | # SWAGGER CONFIGURATION 18 | #################################################################### 19 | SWAGGER_SERVER_ADDRESS=http://localhost:3000 20 | 21 | 22 | #################################################################### 23 | # LOGGER CONFIGURATION 24 | #################################################################### 25 | LOGGER_URL=localhost:3000 26 | -------------------------------------------------------------------------------- /orchestration/user/.gitignore: -------------------------------------------------------------------------------- 1 | # MAC OS CACHE 2 | .DS_Store 3 | 4 | # BINARY 5 | *.out 6 | *.exe 7 | *.exe~ 8 | *.dll 9 | *.so 10 | *.dylib 11 | 12 | # TEST 13 | *.test 14 | 15 | # ENV FOLDER 16 | .env 17 | env 18 | 19 | 20 | # Misc 21 | .idea 22 | src/.DS_Store 23 | go-pckg/* 24 | src/vendor/* 25 | coverage.out 26 | mydb 27 | 28 | main 29 | vendor 30 | .tmp 31 | tmp 32 | 33 | # qa_test 34 | /qa_test/reports/* 35 | /qa_test/node_modules 36 | /qa_test/package-lock.json 37 | /qa_test/.nyc_output 38 | 39 | # go sum 40 | go.sum 41 | db-init 42 | mongo 43 | -------------------------------------------------------------------------------- /orchestration/user/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:latest AS builder 2 | 3 | WORKDIR /app 4 | COPY . . 5 | 6 | RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o main -ldflags '-w -s' src/main.go 7 | 8 | ############################ 9 | # STEP 2 build a small image 10 | ############################ 11 | FROM scratch 12 | 13 | COPY --from=builder /app /usr/bin -------------------------------------------------------------------------------- /orchestration/user/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Sofyan Saputra 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /orchestration/user/Makefile: -------------------------------------------------------------------------------- 1 | # Build And Development 2 | test: 3 | @go test -v -cover ./... 4 | 5 | depend: 6 | @go get github.com/ralali/event-api 7 | 8 | devel: 9 | @air -c watcher.conf 10 | 11 | build: 12 | @go build -o bgin src/main.go 13 | 14 | run: 15 | @go run src/main.go 16 | 17 | production: 18 | @go run src/main.go -e production 19 | 20 | docker-stop: 21 | @docker-compose down 22 | 23 | docker-image: 24 | @docker build . -t bigevent_api 25 | 26 | docker-run: 27 | @docker-compose up 28 | 29 | .PHONY: test depend build run stop docker docker-stop docker-image docker-run devel 30 | -------------------------------------------------------------------------------- /orchestration/user/README.md: -------------------------------------------------------------------------------- 1 | # USER SERVICE SAGA EXAMPLE CHOREOGRAPHY SERVICE 2 | 3 | ## Getting Started 4 | 5 | ### Local 6 | Run local in stage : 7 | - development 8 | - production 9 | ``` 10 | go run src/main.go -e $stage 11 | ``` 12 | default stage in production 13 | 14 | ### Dockerizing 15 | In docker app default execute production stage 16 | ``` 17 | docker-compose up 18 | ``` 19 | -------------------------------------------------------------------------------- /orchestration/user/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | svc_gateway: 4 | image: meongbego/svc_gateway 5 | restart: always 6 | ports: 7 | - 80:80 8 | environment: 9 | - SERVER_ADDRESS=0.0.0.0 10 | - SERVER_PORT=80 11 | - SERVER_TIMEZONE=Asia/Jakarta 12 | - APP_NAME=gateway 13 | - KAFKA_HOST=localhost 14 | - KAFKA_PORT=9092 15 | - SWAGGER_SERVER_ADDRESS=http://0.0.0.0 16 | - LOGGER_URL=logger:3000 17 | command: /usr/bin/main -e production 18 | 19 | -------------------------------------------------------------------------------- /orchestration/user/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/sofyan48/user 2 | 3 | go 1.13 4 | 5 | require ( 6 | cloud.google.com/go v0.54.0 // indirect 7 | github.com/Shopify/sarama v1.26.1 8 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 9 | github.com/apache/thrift v0.13.0 // indirect 10 | github.com/gin-gonic/gin v1.5.0 11 | github.com/google/uuid v1.1.1 12 | github.com/jinzhu/gorm v1.9.12 13 | github.com/joho/godotenv v1.3.0 14 | github.com/openzipkin/zipkin-go v0.1.6 // indirect 15 | github.com/sofyan48/go-cinlog v1.0.0 16 | github.com/stretchr/testify v1.5.1 17 | github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 18 | github.com/swaggo/gin-swagger v1.2.0 19 | github.com/swaggo/swag v1.6.3 20 | go.mongodb.org/mongo-driver v1.3.1 21 | golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72 22 | ) 23 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/api/health/controller/health.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/sofyan48/user/src/app/v1/api/health/service" 8 | "github.com/sofyan48/user/src/app/v1/utility/rest" 9 | ) 10 | 11 | // HealthController types 12 | type HealthController struct { 13 | Service service.HealthServiceInterface 14 | } 15 | 16 | // HealthControllerHandler ... 17 | func HealthControllerHandler() *HealthController { 18 | return &HealthController{ 19 | Service: service.HealthServiceHandler(), 20 | } 21 | } 22 | 23 | // HealthControllerInterface ... 24 | type HealthControllerInterface interface { 25 | Health(context *gin.Context) 26 | } 27 | 28 | // Health params 29 | // @contex: gin Context 30 | func (ctrl *HealthController) Health(context *gin.Context) { 31 | data := ctrl.Service.HealthService() 32 | rest.ResponseData(context, http.StatusOK, data) 33 | return 34 | } 35 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/api/health/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // HealtResponse ... 6 | type HealtResponse struct { 7 | Status string `json:"status"` 8 | CreatedAt *time.Time `json:"created_at"` 9 | } 10 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/api/health/service/health.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/sofyan48/user/src/app/v1/api/health/entity" 7 | ) 8 | 9 | // HealthService ... 10 | type HealthService struct{} 11 | 12 | // HealthServiceHandler ... 13 | func HealthServiceHandler() *HealthService { 14 | return &HealthService{} 15 | } 16 | 17 | // HealthServiceInterface ... 18 | type HealthServiceInterface interface { 19 | HealthService() *entity.HealtResponse 20 | } 21 | 22 | // HealthService ... 23 | func (service *HealthService) HealthService() *entity.HealtResponse { 24 | now := time.Now() 25 | result := &entity.HealtResponse{} 26 | result.Status = "OK" 27 | result.CreatedAt = &now 28 | return result 29 | } 30 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/api/login/entity/event.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // UserEvent ... 8 | type UserEvent struct { 9 | UUID string `json:"__uuid" ` 10 | Action string `json:"__action"` 11 | Offset int64 `json:"__offset"` 12 | Data map[string]interface{} `json:"data"` 13 | Status string `json:"status"` 14 | CreatedAt *time.Time `json:"created_at"` 15 | } 16 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/api/login/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // UserRequest ... 6 | type UserRequest struct { 7 | FirstName string `json:"first_name"` 8 | LastName string `json:"last_name"` 9 | Email string `json:"email"` 10 | PhoneNumber string `json:"handphone"` 11 | Address string `json:"address"` 12 | City string `json:"city"` 13 | Province string `json:"province"` 14 | District string `json:"district"` 15 | } 16 | 17 | // UserResponses ... 18 | type UserResponses struct { 19 | UUID string `json:"uuid"` 20 | CreatedAt *time.Time `json:"created_at"` 21 | Event *UserEvent `json:"event"` 22 | } 23 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/api/login/event/event.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | "github.com/sofyan48/user/src/app/v1/api/user/entity" 6 | "github.com/sofyan48/user/src/app/v1/utility/kafka" 7 | ) 8 | 9 | // USEREVENT ... 10 | const USEREVENT = "users" 11 | 12 | // UserEvent ... 13 | type UserEvent struct { 14 | Kafka kafka.KafkaLibraryInterface 15 | } 16 | 17 | // UserEventHandler ... 18 | func UserEventHandler() *UserEvent { 19 | return &UserEvent{ 20 | Kafka: kafka.KafkaLibraryHandler(), 21 | } 22 | } 23 | 24 | // UserEventInterface ... 25 | type UserEventInterface interface { 26 | UserCreateEvent(data *entity.UserEvent) (*entity.UserEvent, error) 27 | } 28 | 29 | // UserCreateEvent ... 30 | func (event *UserEvent) UserCreateEvent(data *entity.UserEvent) (*entity.UserEvent, error) { 31 | format := event.Kafka.GetStateFull() 32 | format.Action = data.Action 33 | format.CreatedAt = data.CreatedAt 34 | format.Data = data.Data 35 | format.UUID = uuid.New().String() 36 | data.UUID = format.UUID 37 | go event.Kafka.SendEvent(USEREVENT, format) 38 | data.Status = "QUEUE" 39 | return data, nil 40 | } 41 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/api/order/entity/event.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // OrderEvent ... 8 | type OrderEvent struct { 9 | UUID string `json:"__uuid" ` 10 | Action string `json:"__action"` 11 | Offset int64 `json:"__offset"` 12 | Data map[string]interface{} `json:"data"` 13 | Status string `json:"status"` 14 | CreatedAt *time.Time `json:"created_at"` 15 | } 16 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/api/order/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // OrderRequest ... 6 | type OrderRequest struct { 7 | OrderNumber string `json:"order_number"` 8 | UserUUID string `json:"uuid_user"` 9 | IDOrderType string `json:"id_order_type"` 10 | IDOrderStatus string `json:"id_order_status"` 11 | IDPaymentStatus string `json:"id_payment_status"` 12 | IDPaymentModel string `json:"id_payment_model"` 13 | InquiryNumber string `json:"inquiry_number"` 14 | PaymentOrder string `json:"payment_order"` 15 | NMBank string `json:"nm_bank"` 16 | } 17 | 18 | // OrderResponses ... 19 | type OrderResponses struct { 20 | UUID string `json:"uuid"` 21 | CreatedAt *time.Time `json:"created_at"` 22 | Event *OrderEvent `json:"event"` 23 | } 24 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/api/order/event/event.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | "github.com/sofyan48/user/src/app/v1/api/order/entity" 6 | "github.com/sofyan48/user/src/app/v1/utility/kafka" 7 | ) 8 | 9 | // ORDEREVENT ... 10 | const ORDEREVENT = "order" 11 | 12 | // OrderEvent ... 13 | type OrderEvent struct { 14 | Kafka kafka.KafkaLibraryInterface 15 | } 16 | 17 | // OrderEventHandler ... 18 | func OrderEventHandler() *OrderEvent { 19 | return &OrderEvent{ 20 | Kafka: kafka.KafkaLibraryHandler(), 21 | } 22 | } 23 | 24 | // OrderEventInterface ... 25 | type OrderEventInterface interface { 26 | OrderCreateEvent(data *entity.OrderEvent) (*entity.OrderEvent, error) 27 | } 28 | 29 | // OrderCreateEvent ... 30 | func (event *OrderEvent) OrderCreateEvent(data *entity.OrderEvent) (*entity.OrderEvent, error) { 31 | format := event.Kafka.GetStateFull() 32 | format.Action = data.Action 33 | format.CreatedAt = data.CreatedAt 34 | format.Data = data.Data 35 | format.UUID = uuid.New().String() 36 | data.UUID = format.UUID 37 | go event.Kafka.SendEvent(ORDEREVENT, format) 38 | data.Status = "QUEUE" 39 | return data, nil 40 | } 41 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/api/payment/entity/event.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // PaymentEvent ... 8 | type PaymentEvent struct { 9 | UUID string `json:"__uuid" ` 10 | Action string `json:"__action"` 11 | Offset int64 `json:"__offset"` 12 | Data map[string]interface{} `json:"data"` 13 | Status string `json:"status"` 14 | CreatedAt *time.Time `json:"created_at"` 15 | } 16 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/api/payment/entity/general.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | // Pagination .. 4 | type Pagination struct { 5 | Limit int `json:"limit" form:"limit"` 6 | Page int `json:"page" form:"page"` 7 | } 8 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/api/payment/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // PaymentRequest ... 6 | type PaymentRequest struct { 7 | UUIDOrder string `json:"uuid_order"` 8 | UUIDUser string `json:"uuid_user"` 9 | IDPaymentStatus string `json:"id_payment_status"` 10 | IDPaymentModel string `json:"id_payment_model"` 11 | InquiryNumber string `json:"inquiry_number"` 12 | BankAccountNumber string `json:"bank_account_number"` 13 | NMBank string `json:"nm_bank"` 14 | PaymentTotal int `json:"payment_total"` 15 | } 16 | 17 | // PaymentPaidRequest ... 18 | type PaymentPaidRequest struct { 19 | PaymentTotal int `json:"payment_total"` 20 | PaymentStatus string `json:"payment_status"` 21 | BankAccountNumber string `json:"bank_account_number"` 22 | } 23 | 24 | // PaymentResponses ... 25 | type PaymentResponses struct { 26 | UUID string `json:"uuid"` 27 | CreatedAt *time.Time `json:"created_at"` 28 | Event *PaymentEvent `json:"event"` 29 | } 30 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/api/user/entity/event.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // UserEvent ... 8 | type UserEvent struct { 9 | UUID string `json:"__uuid" ` 10 | Action string `json:"__action"` 11 | Offset int64 `json:"__offset"` 12 | Data map[string]interface{} `json:"data"` 13 | Status string `json:"status"` 14 | CreatedAt *time.Time `json:"created_at"` 15 | } 16 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/api/user/entity/http.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "time" 4 | 5 | // UserRequest ... 6 | type UserRequest struct { 7 | FirstName string `json:"first_name"` 8 | LastName string `json:"last_name"` 9 | Email string `json:"email"` 10 | PhoneNumber string `json:"handphone"` 11 | Address string `json:"address"` 12 | City string `json:"city"` 13 | Province string `json:"province"` 14 | District string `json:"district"` 15 | } 16 | 17 | // UserResponses ... 18 | type UserResponses struct { 19 | UUID string `json:"uuid"` 20 | CreatedAt *time.Time `json:"created_at"` 21 | Event *UserEvent `json:"event"` 22 | } 23 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/api/user/event/event.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "github.com/google/uuid" 5 | "github.com/sofyan48/user/src/app/v1/api/user/entity" 6 | "github.com/sofyan48/user/src/app/v1/utility/kafka" 7 | ) 8 | 9 | // USEREVENT ... 10 | const USEREVENT = "users" 11 | 12 | // UserEvent ... 13 | type UserEvent struct { 14 | Kafka kafka.KafkaLibraryInterface 15 | } 16 | 17 | // UserEventHandler ... 18 | func UserEventHandler() *UserEvent { 19 | return &UserEvent{ 20 | Kafka: kafka.KafkaLibraryHandler(), 21 | } 22 | } 23 | 24 | // UserEventInterface ... 25 | type UserEventInterface interface { 26 | UserCreateEvent(data *entity.UserEvent) (*entity.UserEvent, error) 27 | } 28 | 29 | // UserCreateEvent ... 30 | func (event *UserEvent) UserCreateEvent(data *entity.UserEvent) (*entity.UserEvent, error) { 31 | format := event.Kafka.GetStateFull() 32 | format.Action = data.Action 33 | format.CreatedAt = data.CreatedAt 34 | format.Data = data.Data 35 | format.UUID = uuid.New().String() 36 | data.UUID = format.UUID 37 | go event.Kafka.SendEvent(USEREVENT, format) 38 | data.Status = "QUEUE" 39 | return data, nil 40 | } 41 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/routes/docs.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | swaggerFiles "github.com/swaggo/files" 6 | ginSwagger "github.com/swaggo/gin-swagger" 7 | 8 | _ "github.com/sofyan48/user/src/app/v1/swagger/docs" 9 | ) 10 | 11 | // DOCROUTES ... 12 | const DOCROUTES = VERSION + "/docs" 13 | 14 | func (rLoader *V1RouterLoader) initDocs(router *gin.Engine) { 15 | group := router.Group(DOCROUTES) 16 | url := ginSwagger.URL("swagger/doc.json") 17 | group.GET("/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url)) 18 | } 19 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/routes/health.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // HEALTHROUTES ... 8 | const HEALTHROUTES = VERSION + "/health" 9 | 10 | func (rLoader *V1RouterLoader) initHealth(router *gin.Engine) { 11 | group := router.Group(HEALTHROUTES) 12 | group.GET("", rLoader.Health.Health) 13 | } 14 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/routes/order.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // ORDERROUTES ... 6 | const ORDERROUTES = VERSION + "/order" 7 | 8 | func (rLoader *V1RouterLoader) initOrder(router *gin.Engine) { 9 | group := router.Group(ORDERROUTES) 10 | group.POST("", rLoader.Order.OrderCreate) 11 | group.GET(":uuid", rLoader.Order.GetOrderData) 12 | group.PUT(":uuid", rLoader.Order.UpdateOrder) 13 | group.DELETE(":uuid", rLoader.Order.DeleteOrder) 14 | } 15 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/routes/payment.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // PAYMENTROUTES ... 6 | const PAYMENTROUTES = VERSION + "/payment" 7 | 8 | func (rLoader *V1RouterLoader) initPayment(router *gin.Engine) { 9 | group := router.Group(PAYMENTROUTES) 10 | group.POST("", rLoader.Payment.PaymentCreate) 11 | group.GET("/get/:uuid", rLoader.Payment.GetPaymentData) 12 | group.PUT(":uuid", rLoader.Payment.UpdatePaidPayment) 13 | group.DELETE(":uuid", rLoader.Payment.DeletePayment) 14 | group.GET("list", rLoader.Payment.ListPayment) 15 | } 16 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/routes/user.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | // USERROUTES ... 6 | const USERROUTES = VERSION + "/user" 7 | 8 | func (rLoader *V1RouterLoader) initUser(router *gin.Engine) { 9 | group := router.Group(USERROUTES) 10 | group.POST("", rLoader.User.UserCreate) 11 | group.GET(":uuid", rLoader.User.GetUserData) 12 | group.PUT(":uuid", rLoader.User.UpdateUser) 13 | group.DELETE(":uuid") 14 | } 15 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/swagger/docs/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "contact": {}, 5 | "license": {} 6 | }, 7 | "paths": {} 8 | } -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/swagger/docs/swagger.yaml: -------------------------------------------------------------------------------- 1 | info: 2 | contact: {} 3 | license: {} 4 | paths: {} 5 | swagger: "2.0" 6 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/utility/kafka/consumer.go: -------------------------------------------------------------------------------- 1 | package kafka 2 | 3 | import ( 4 | "log" 5 | "os" 6 | 7 | "github.com/Shopify/sarama" 8 | ) 9 | 10 | // InitConsumer ... 11 | func (kafka *KafkaLibrary) InitConsumer(group string) (sarama.ConsumerGroup, error) { 12 | configKafka := kafka.initConsumerConfig("", "") 13 | kafkaHost := os.Getenv("KAFKA_HOST") 14 | kafkaPort := os.Getenv("KAFKA_PORT") 15 | version, err := sarama.ParseKafkaVersion(os.Getenv("KAFKA_VERSION")) 16 | if err != nil { 17 | log.Panicf("Error parsing Kafka version: %v", err) 18 | } 19 | configKafka.Version = version 20 | return sarama.NewConsumerGroup([]string{kafkaHost + ":" + kafkaPort}, group, configKafka) 21 | } 22 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/utility/rest/rest.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // Respons types 8 | type Respons struct { 9 | Status int `json:"status"` 10 | Meta interface{} `json:"meta"` 11 | Results interface{} `json:"results"` 12 | } 13 | 14 | // ResponseList params 15 | // @context: *gin.Context 16 | // status: int 17 | // payload: interface{} 18 | func ResponseList(context *gin.Context, status int, payload, meta interface{}) { 19 | var res Respons 20 | res.Status = status 21 | res.Results = payload 22 | res.Meta = meta 23 | context.JSON(status, res) 24 | return 25 | } 26 | 27 | // ResponseData params 28 | // @context: *gin.Context 29 | // status: int 30 | // payload: interface{} 31 | func ResponseData(context *gin.Context, status int, payload interface{}) { 32 | context.JSON(status, payload) 33 | return 34 | } 35 | 36 | // ResponseMessages params 37 | // @context: *gin.Context 38 | // status: int 39 | // msg: string 40 | func ResponseMessages(context *gin.Context, status int, msg string) { 41 | context.JSON(status, gin.H{ 42 | "messages": msg, 43 | }) 44 | return 45 | } 46 | -------------------------------------------------------------------------------- /orchestration/user/src/app/v1/utility/rest/rest_test.go: -------------------------------------------------------------------------------- 1 | package rest 2 | -------------------------------------------------------------------------------- /orchestration/user/src/config/server_configuration.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/joho/godotenv" 8 | "github.com/sofyan48/user/src/middleware" 9 | ) 10 | 11 | // SetupEngine server router configuration 12 | func SetupEngine(env string) *gin.Engine { 13 | defaultMiddleware := middleware.DefaultMiddleware{} 14 | configEnvironment(env) 15 | router := gin.Default() 16 | router.Use(defaultMiddleware.CORSMiddleware()) 17 | return router 18 | } 19 | 20 | // ConfigEnvironment ... 21 | func configEnvironment(env string) { 22 | switch env { 23 | case "development": 24 | err := godotenv.Load() 25 | if err != nil { 26 | log.Fatal("Error loading .env file") 27 | } 28 | case "production": 29 | gin.SetMode(gin.ReleaseMode) 30 | log.Println("Engine Running") 31 | default: 32 | err := godotenv.Load() 33 | if err != nil { 34 | log.Fatal("Error loading .env file") 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /orchestration/user/src/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/sofyan48/user/src/config" 9 | 10 | apiRouter "github.com/sofyan48/user/src/router" 11 | ) 12 | 13 | func main() { 14 | environment := flag.String("e", "development", "") 15 | flag.Usage = func() { 16 | fmt.Println("Usage: server -e {mode}") 17 | os.Exit(1) 18 | } 19 | flag.Parse() 20 | startApp(*environment) 21 | } 22 | 23 | func startApp(env string) { 24 | router := config.SetupEngine(env) 25 | apiRouter.LoadRouter(router) 26 | serverHost := os.Getenv("SERVER_ADDRESS") 27 | serverPort := os.Getenv("SERVER_PORT") 28 | serverString := fmt.Sprintf("%s:%s", serverHost, serverPort) 29 | router.Run(serverString) 30 | } 31 | -------------------------------------------------------------------------------- /orchestration/user/src/middleware/auth.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | -------------------------------------------------------------------------------- /orchestration/user/src/middleware/cors_middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // CORSMiddleware Implementing CORS 8 | // return: gin HandlerFunc 9 | func (m *DefaultMiddleware) CORSMiddleware() gin.HandlerFunc { 10 | return func(c *gin.Context) { 11 | c.Writer.Header().Set("Access-Control-Allow-Origin", "*") 12 | c.Writer.Header().Set("Access-Control-Max-Age", "86400") 13 | c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE") 14 | c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") 15 | c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length") 16 | c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") 17 | if c.Request.Method == "OPTIONS" { 18 | c.AbortWithStatus(200) 19 | } else { 20 | c.Next() 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /orchestration/user/src/middleware/middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | // DefaultMiddleware types 4 | type DefaultMiddleware struct { 5 | } 6 | -------------------------------------------------------------------------------- /orchestration/user/src/router/router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | v1 "github.com/sofyan48/user/src/app/v1/routes" 6 | ) 7 | 8 | // LoadRouter params 9 | // @routers: gin.Engine 10 | func LoadRouter(routers *gin.Engine) { 11 | version1 := v1.V1RouterLoaderHandler() 12 | version1.V1Routes(routers) 13 | } 14 | -------------------------------------------------------------------------------- /orchestration/user/watcher.conf: -------------------------------------------------------------------------------- 1 | root = "." 2 | watch_dir = "src" 3 | tmp_dir = "tmp" 4 | 5 | [build] 6 | cmd = "go build -o ./tmp/main src/main.go" 7 | bin = "tmp/main" 8 | log = "air_errors.log" 9 | include_ext = ["go", "tpl", "tmpl", "html"] 10 | exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules", "mydb"] 11 | delay = 1500 # ms 12 | 13 | [log] 14 | time = false 15 | 16 | [color] 17 | main = "magenta" 18 | watcher = "cyan" 19 | build = "yellow" 20 | runner = "green" 21 | # app = "white" --------------------------------------------------------------------------------