From d3152635543dce7e0e8cc33d6c7d71fee0f30502 Mon Sep 17 00:00:00 2001 From: Reza Hidayat Date: Sat, 25 Nov 2023 20:14:42 +0700 Subject: [PATCH] update readme.md --- .env | 7 -- README.md | 3 +- cmd/server/main.go | 100 --------------- common/jwt.go | 12 -- ...20231120141232_create_users_table.down.sql | 5 - .../20231120141232_create_users_table.up.sql | 9 -- ..._add_several_field_in_users_table.down.sql | 8 -- ...05_add_several_field_in_users_table.up.sql | 7 -- .../20231117204623_create_users_table.sql | 15 --- db/users.sql | 10 -- entity/user.go | 37 ------ entity/weather.go | 4 - go.mod | 38 ------ go.sum | 87 ------------- internal/builder/builder.go | 25 ---- internal/config/config.go | 59 --------- internal/http/binder/binder.go | 36 ------ internal/http/handler/auth.handler.go | 53 -------- internal/http/handler/user.handler.go | 116 ------------------ internal/http/router/routes.go | 52 -------- internal/http/server/echo.go | 56 --------- internal/http/validator/validator.go | 48 -------- internal/repository/user.repository.go | 68 ---------- internal/service/login.service.go | 44 ------- internal/service/token.service.go | 47 ------- internal/service/user.service.go | 51 -------- 26 files changed, 2 insertions(+), 995 deletions(-) delete mode 100644 .env delete mode 100644 cmd/server/main.go delete mode 100644 common/jwt.go delete mode 100644 db/migration-golang/20231120141232_create_users_table.down.sql delete mode 100644 db/migration-golang/20231120141232_create_users_table.up.sql delete mode 100644 db/migration-golang/20231123141605_add_several_field_in_users_table.down.sql delete mode 100644 db/migration-golang/20231123141605_add_several_field_in_users_table.up.sql delete mode 100644 db/migrations/20231117204623_create_users_table.sql delete mode 100644 db/users.sql delete mode 100644 entity/user.go delete mode 100644 entity/weather.go delete mode 100644 go.mod delete mode 100644 go.sum delete mode 100644 internal/builder/builder.go delete mode 100644 internal/config/config.go delete mode 100644 internal/http/binder/binder.go delete mode 100644 internal/http/handler/auth.handler.go delete mode 100644 internal/http/handler/user.handler.go delete mode 100644 internal/http/router/routes.go delete mode 100644 internal/http/server/echo.go delete mode 100644 internal/http/validator/validator.go delete mode 100644 internal/repository/user.repository.go delete mode 100644 internal/service/login.service.go delete mode 100644 internal/service/token.service.go delete mode 100644 internal/service/user.service.go diff --git a/.env b/.env deleted file mode 100644 index 3c14277..0000000 --- a/.env +++ /dev/null @@ -1,7 +0,0 @@ -PORT=8080 -POSTGRES_HOST=localhost -POSTGRES_PORT=5432 -POSTGRES_USER=postgres -POSTGRES_PASSWORD=mysecretpassword -POSTGRES_DATABASE=weather-app -JWT_SECRET_KEY="akusayangmantanku" \ No newline at end of file diff --git a/README.md b/README.md index 26f0343..3db59d3 100644 --- a/README.md +++ b/README.md @@ -57,4 +57,5 @@ Proyek ini akan berlangsung selama 2 sprint (2 minggu) dengan penilaian secara b - [x] [Figma](https://www.figma.com/file/BdDlFZ7u3E6upQlSwUcOax/Code-Challenge-Project-Based?type=whiteboard&node-id=0-1&t=Le6Pdip9Patyl5DV-0) - [x] [PPT Document](https://docs.google.com/presentation/d/1vvOwCKjysLxORL7GOtOJbgiW3XAVuYsRK0ccUa8VOzA/edit#slide=id.g21e0640a876_0_25) -- [x] [Desain Aplikasi](https://www.figma.com/file/1MtWn0HIt9SidftaQIlrXG/Project-Coding-Challenge-References?type=design&node-id=0-4&mode=design&t=dC1tZcf7zlIMfZBL-0) \ No newline at end of file +- [x] [Desain Aplikasi](https://www.figma.com/file/1MtWn0HIt9SidftaQIlrXG/Project-Coding-Challenge-References?type=design&node-id=0-4&mode=design&t=dC1tZcf7zlIMfZBL-0) +- [x] [Notion](https://www.notion.so/kumal/Projek-Pemesanan-Tiket-89ef1e2e0d1b4067ba48316fb64fe673?pvs=4) \ No newline at end of file diff --git a/cmd/server/main.go b/cmd/server/main.go deleted file mode 100644 index fa73f0e..0000000 --- a/cmd/server/main.go +++ /dev/null @@ -1,100 +0,0 @@ -package main - -import ( - "context" - "fmt" - "log" - "os" - "os/signal" - "strings" - "time" - - "github.com/labstack/echo/v4" - "github.com/zhikariz/weather-app/internal/builder" - "github.com/zhikariz/weather-app/internal/config" - "github.com/zhikariz/weather-app/internal/http/binder" - "github.com/zhikariz/weather-app/internal/http/server" - "github.com/zhikariz/weather-app/internal/http/validator" - "gorm.io/driver/postgres" - "gorm.io/gorm" - "gorm.io/gorm/logger" -) - -func main() { - cfg, err := config.NewConfig(".env") - checkError(err) - - splash() - - db, err := buildGormDB(cfg.Postgres) - checkError(err) - - publicRoutes := builder.BuildPublicRoutes(cfg, db) - privateRoutes := builder.BuildPrivateRoutes(cfg, db) - - echoBinder := &echo.DefaultBinder{} - formValidator := validator.NewFormValidator() - customBinder := binder.NewBinder(echoBinder, formValidator) - - srv := server.NewServer( - cfg, - customBinder, - publicRoutes, - privateRoutes, - ) - - runServer(srv, cfg.Port) - - waitForShutdown(srv) -} - -func runServer(srv *server.Server, port string) { - go func() { - err := srv.Start(fmt.Sprintf(":%s", port)) - log.Fatal(err) - }() -} - -func waitForShutdown(srv *server.Server) { - quit := make(chan os.Signal, 1) - signal.Notify(quit, os.Interrupt) - - <-quit - - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - - go func() { - if err := srv.Shutdown(ctx); err != nil { - srv.Logger.Fatal(err) - } - }() -} - -func buildGormDB(cfg config.PostgresConfig) (*gorm.DB, error) { - dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Jakarta", cfg.Host, cfg.User, cfg.Password, cfg.Database, cfg.Port) - return gorm.Open(postgres.Open(dsn), &gorm.Config{ - Logger: logger.Default.LogMode(logger.Info), - }) -} - -func splash() { - colorReset := "\033[0m" - - splashText := ` - - __ __ __ .__ _____ -/ \ / \ ____ _____ _/ |_| |__ ___________ / _ \ ______ ______ -\ \/\/ // __ \\__ \\ __\ | \_/ __ \_ __ \/ /_\ \\____ \\____ \ - \ /\ ___/ / __ \| | | Y \ ___/| | \/ | \ |_> > |_> > - \__/\ / \___ >____ /__| |___| /\___ >__| \____|__ / __/| __/ - \/ \/ \/ \/ \/ \/|__| |__| -` - fmt.Println(colorReset, strings.TrimSpace(splashText)) -} - -func checkError(err error) { - if err != nil { - panic(err) - } -} diff --git a/common/jwt.go b/common/jwt.go deleted file mode 100644 index b5c1f60..0000000 --- a/common/jwt.go +++ /dev/null @@ -1,12 +0,0 @@ -package common - -import ( - "github.com/golang-jwt/jwt/v5" -) - -type JwtCustomClaims struct { - ID int64 `json:"id"` - Name string `json:"name"` - Email string `json:"email"` - jwt.RegisteredClaims -} diff --git a/db/migration-golang/20231120141232_create_users_table.down.sql b/db/migration-golang/20231120141232_create_users_table.down.sql deleted file mode 100644 index 07f389a..0000000 --- a/db/migration-golang/20231120141232_create_users_table.down.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -DROP TABLE IF EXISTS "public"."users"; - -COMMIT; \ No newline at end of file diff --git a/db/migration-golang/20231120141232_create_users_table.up.sql b/db/migration-golang/20231120141232_create_users_table.up.sql deleted file mode 100644 index f9d3962..0000000 --- a/db/migration-golang/20231120141232_create_users_table.up.sql +++ /dev/null @@ -1,9 +0,0 @@ -BEGIN; -CREATE TABLE IF NOT EXISTS "public"."users" ( - "id" SERIAL NOT NULL PRIMARY KEY, - "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, - "created_at" timestamptz (6) NOT NULL, - "updated_at" timestamptz (6) NOT NULL, - "deleted_at" timestamptz (6) -); -COMMIT; \ No newline at end of file diff --git a/db/migration-golang/20231123141605_add_several_field_in_users_table.down.sql b/db/migration-golang/20231123141605_add_several_field_in_users_table.down.sql deleted file mode 100644 index 4c001ce..0000000 --- a/db/migration-golang/20231123141605_add_several_field_in_users_table.down.sql +++ /dev/null @@ -1,8 +0,0 @@ -BEGIN; - - -ALTER TABLE "public"."users" -DROP COLUMN IF EXISTS email, -DROP COLUMN IF EXISTS password; - -COMMIT; \ No newline at end of file diff --git a/db/migration-golang/20231123141605_add_several_field_in_users_table.up.sql b/db/migration-golang/20231123141605_add_several_field_in_users_table.up.sql deleted file mode 100644 index 4c7a81a..0000000 --- a/db/migration-golang/20231123141605_add_several_field_in_users_table.up.sql +++ /dev/null @@ -1,7 +0,0 @@ -BEGIN; - -ALTER TABLE "public"."users" -ADD COLUMN email VARCHAR(255), -ADD COLUMN password VARCHAR(255); - -COMMIT; \ No newline at end of file diff --git a/db/migrations/20231117204623_create_users_table.sql b/db/migrations/20231117204623_create_users_table.sql deleted file mode 100644 index 7f4b766..0000000 --- a/db/migrations/20231117204623_create_users_table.sql +++ /dev/null @@ -1,15 +0,0 @@ --- +goose Up --- +goose StatementBegin -CREATE TABLE IF NOT EXISTS "public"."users" ( - "id" SERIAL NOT NULL PRIMARY KEY, - "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, - "created_at" timestamptz (6) NOT NULL, - "updated_at" timestamptz (6) NOT NULL, - "deleted_at" timestamptz (6) -); --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -DROP TABLE IF EXISTS "public"."users"; --- +goose StatementEnd \ No newline at end of file diff --git a/db/users.sql b/db/users.sql deleted file mode 100644 index fe81376..0000000 --- a/db/users.sql +++ /dev/null @@ -1,10 +0,0 @@ -CREATE TABLE - "public"."users" ( - "id" SERIAL NOT NULL, - "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, - "created_at" timestamptz (6) NOT NULL, - "updated_at" timestamptz (6) NOT NULL, - "deleted_at" timestamptz (6) - ); - -ALTER TABLE "public"."users" ADD CONSTRAINT "users_pkey" PRIMARY KEY ("id"); \ No newline at end of file diff --git a/entity/user.go b/entity/user.go deleted file mode 100644 index 86c5e20..0000000 --- a/entity/user.go +++ /dev/null @@ -1,37 +0,0 @@ -package entity - -import ( - "time" - - "gorm.io/gorm" -) - -type User struct { - ID int64 `json:"id"` - Name string `json:"name"` - Email string `json:"email"` - Password string `json:"-"` - CreatedAt time.Time `json:"-"` - UpdatedAt time.Time `json:"-"` - DeletedAt gorm.DeletedAt `json:"-"` -} - -func NewUser(name, email, password string) *User { - return &User{ - Name: name, - Email: email, - Password: password, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - } -} - -func UpdateUser(id int64, name, email, password string) *User { - return &User{ - ID: id, - Name: name, - Email: email, - Password: password, - UpdatedAt: time.Now(), - } -} diff --git a/entity/weather.go b/entity/weather.go deleted file mode 100644 index d634b6b..0000000 --- a/entity/weather.go +++ /dev/null @@ -1,4 +0,0 @@ -package entity - -type Weather struct { -} diff --git a/go.mod b/go.mod deleted file mode 100644 index 22e6882..0000000 --- a/go.mod +++ /dev/null @@ -1,38 +0,0 @@ -module github.com/zhikariz/weather-app - -go 1.20 - -require ( - github.com/caarlos0/env/v6 v6.10.1 - github.com/creasty/defaults v1.7.0 - github.com/go-playground/validator/v10 v10.16.0 - github.com/joho/godotenv v1.5.1 - github.com/labstack/echo-jwt/v4 v4.2.0 - github.com/labstack/echo/v4 v4.11.2 - gorm.io/driver/postgres v1.5.4 - gorm.io/gorm v1.25.5 -) - -require ( - github.com/gabriel-vasile/mimetype v1.4.2 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/golang-jwt/jwt v3.2.2+incompatible // indirect - github.com/golang-jwt/jwt/v5 v5.0.0 // indirect - github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/jackc/pgx/v5 v5.4.3 // indirect - github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.5 // indirect - github.com/labstack/gommon v0.4.0 // indirect - github.com/leodido/go-urn v1.2.4 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect - github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasttemplate v1.2.2 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - golang.org/x/time v0.3.0 // indirect -) diff --git a/go.sum b/go.sum deleted file mode 100644 index 28f5603..0000000 --- a/go.sum +++ /dev/null @@ -1,87 +0,0 @@ -github.com/caarlos0/env/v6 v6.10.1 h1:t1mPSxNpei6M5yAeu1qtRdPAK29Nbcf/n3G7x+b3/II= -github.com/caarlos0/env/v6 v6.10.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc= -github.com/creasty/defaults v1.7.0 h1:eNdqZvc5B509z18lD8yc212CAqJNvfT1Jq6L8WowdBA= -github.com/creasty/defaults v1.7.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= -github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE= -github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= -github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= -github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= -github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= -github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= -github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= -github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= -github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= -github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/labstack/echo-jwt/v4 v4.2.0 h1:odSISV9JgcSCuhgQSV/6Io3i7nUmfM/QkBeR5GVJj5c= -github.com/labstack/echo-jwt/v4 v4.2.0/go.mod h1:MA2RqdXdEn4/uEglx0HcUOgQSyBaTh5JcaHIan3biwU= -github.com/labstack/echo/v4 v4.11.2 h1:T+cTLQxWCDfqDEoydYm5kCobjmHwOwcv4OJAPHilmdE= -github.com/labstack/echo/v4 v4.11.2/go.mod h1:UcGuQ8V6ZNRmSweBIJkPvGfwCMIlFmiqrPqiEBfPYws= -github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= -github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= -github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= -github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/postgres v1.5.4 h1:Iyrp9Meh3GmbSuyIAGyjkN+n9K+GHX9b9MqsTL4EJCo= -gorm.io/driver/postgres v1.5.4/go.mod h1:Bgo89+h0CRcdA33Y6frlaHHVuTdOf87pmyzwW9C/BH0= -gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= -gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= diff --git a/internal/builder/builder.go b/internal/builder/builder.go deleted file mode 100644 index be59d09..0000000 --- a/internal/builder/builder.go +++ /dev/null @@ -1,25 +0,0 @@ -package builder - -import ( - "github.com/zhikariz/weather-app/internal/config" - "github.com/zhikariz/weather-app/internal/http/handler" - "github.com/zhikariz/weather-app/internal/http/router" - "github.com/zhikariz/weather-app/internal/repository" - "github.com/zhikariz/weather-app/internal/service" - "gorm.io/gorm" -) - -func BuildPublicRoutes(cfg *config.Config, db *gorm.DB) []*router.Route { - userRepository := repository.NewUserRepository(db) - loginService := service.NewLoginService(userRepository) - tokenService := service.NewTokenService(cfg) - authHandler := handler.NewAuthHandler(loginService, tokenService) - return router.PublicRoutes(authHandler) -} - -func BuildPrivateRoutes(cfg *config.Config, db *gorm.DB) []*router.Route { - userRepository := repository.NewUserRepository(db) - userService := service.NewUserService(userRepository) - userHandler := handler.NewUserHandler(userService) - return router.PrivateRoutes(userHandler) -} diff --git a/internal/config/config.go b/internal/config/config.go deleted file mode 100644 index 4f76170..0000000 --- a/internal/config/config.go +++ /dev/null @@ -1,59 +0,0 @@ -package config - -import ( - "errors" - - "github.com/caarlos0/env/v6" - "github.com/joho/godotenv" -) - -// Config is a config -type Config struct { - Port string `env:"PORT" envDefault:"8080"` - Postgres PostgresConfig `envPrefix:"POSTGRES_"` - JWT JwtConfig `envPrefix:"JWT_"` -} - -// JwtConfig is a config for jwt -type JwtConfig struct { - SecretKey string `env:"SECRET_KEY"` -} - -// PostgresConfig is a config for postgres -type PostgresConfig struct { - Host string `env:"HOST" envDefault:"localhost"` - Port string `env:"PORT" envDefault:"5432"` - User string `env:"USER" envDefault:"postgres"` - Password string `env:"PASSWORD" envDefault:"postgres"` - Database string `env:"DATABASE" envDefault:"postgres"` -} - -// NewConfig creates a new config -func NewConfig(envPath string) (*Config, error) { - cfg, err := parseConfig(envPath) - if err != nil { - return nil, err - } - return cfg, nil -} - -// parseConfig parses the configuration file located at envPath and returns a -// Config struct and an error if any. It uses the godotenv package to load the -// environment variables from the file and the env package to parse them into -// the Config struct. -// -// envPath: The path to the environment file. -// Returns: A pointer to the Config struct and an error. -func parseConfig(envPath string) (*Config, error) { - err := godotenv.Load(envPath) - if err != nil { - return nil, errors.New("failed to load env") - } - - cfg := &Config{} - err = env.Parse(cfg) - if err != nil { - return nil, errors.New("failed to parse config") - } - return cfg, nil -} diff --git a/internal/http/binder/binder.go b/internal/http/binder/binder.go deleted file mode 100644 index 318275d..0000000 --- a/internal/http/binder/binder.go +++ /dev/null @@ -1,36 +0,0 @@ -package binder - -import ( - "github.com/creasty/defaults" - "github.com/go-playground/validator/v10" - "github.com/labstack/echo/v4" - internalValidator "github.com/zhikariz/weather-app/internal/http/validator" -) - -type Binder struct { - defaultBinder *echo.DefaultBinder - *internalValidator.FormValidator -} - -func NewBinder( - dbr *echo.DefaultBinder, - vdr *internalValidator.FormValidator) *Binder { - return &Binder{dbr, vdr} -} - -func (b *Binder) Bind(i interface{}, c echo.Context) error { - if err := b.defaultBinder.Bind(i, c); err != nil { - return err - } - - if err := defaults.Set(i); err != nil { - return err - } - - if err := b.Validate(i); err != nil { - errs := err.(validator.ValidationErrors) - return errs - } - - return nil -} diff --git a/internal/http/handler/auth.handler.go b/internal/http/handler/auth.handler.go deleted file mode 100644 index 6b344a1..0000000 --- a/internal/http/handler/auth.handler.go +++ /dev/null @@ -1,53 +0,0 @@ -package handler - -import ( - "net/http" - - "github.com/labstack/echo/v4" - "github.com/zhikariz/weather-app/internal/http/validator" - "github.com/zhikariz/weather-app/internal/service" -) - -type AuthHandler struct { - loginService service.LoginUseCase - tokenService service.TokenUseCase -} - -func NewAuthHandler( - loginService service.LoginUseCase, - tokenService service.TokenUseCase, -) *AuthHandler { - return &AuthHandler{ - loginService: loginService, - tokenService: tokenService, - } -} - -func (h *AuthHandler) Login(ctx echo.Context) error { - var input struct { - Email string `json:"email" validate:"required"` - Password string `json:"password" validate:"required"` - } - - if err := ctx.Bind(&input); err != nil { - return ctx.JSON(http.StatusBadRequest, validator.ValidatorErrors(err)) - } - - user, err := h.loginService.Login(ctx.Request().Context(), input.Email, input.Password) - - if err != nil { - return ctx.JSON(http.StatusUnprocessableEntity, err) - } - - accessToken, err := h.tokenService.GenerateAccessToken(ctx.Request().Context(), user) - - if err != nil { - return ctx.JSON(http.StatusUnprocessableEntity, err) - } - - data := map[string]string{ - "access_token": accessToken, - } - - return ctx.JSON(http.StatusOK, data) -} diff --git a/internal/http/handler/user.handler.go b/internal/http/handler/user.handler.go deleted file mode 100644 index 4b90f76..0000000 --- a/internal/http/handler/user.handler.go +++ /dev/null @@ -1,116 +0,0 @@ -package handler - -import ( - "errors" - "fmt" - "net/http" - - "github.com/golang-jwt/jwt/v5" - "github.com/labstack/echo/v4" - "github.com/zhikariz/weather-app/common" - "github.com/zhikariz/weather-app/entity" - "github.com/zhikariz/weather-app/internal/http/validator" - "github.com/zhikariz/weather-app/internal/service" -) - -type UserHandler struct { - userService service.UserUseCase -} - -func NewUserHandler(userService service.UserUseCase) *UserHandler { - return &UserHandler{userService} -} - -func (h *UserHandler) GetAllUsers(ctx echo.Context) error { - // Parse the token - userClaim := ctx.Get("user").(*jwt.Token) - claims := userClaim.Claims.(*common.JwtCustomClaims) - - if claims.Email == "helmi@ganteng.com" { - return ctx.JSON(http.StatusForbidden, errors.New("you don't have permission to access this resource")) - } - - fmt.Println(claims.Email) - - users, err := h.userService.FindAll(ctx.Request().Context()) - if err != nil { - return ctx.JSON(http.StatusUnprocessableEntity, err) - } - return ctx.JSON(http.StatusOK, users) -} - -func (h *UserHandler) CreateUser(ctx echo.Context) error { - var input struct { - Name string `json:"name" validate:"required"` - Email string `json:"email" validate:"required"` - Password string `json:"password" validate:"required"` - } - - if err := ctx.Bind(&input); err != nil { - return ctx.JSON(http.StatusBadRequest, validator.ValidatorErrors(err)) - } - - user := entity.NewUser(input.Name, input.Email, input.Password) - err := h.userService.Create(ctx.Request().Context(), user) - if err != nil { - return ctx.JSON(http.StatusUnprocessableEntity, err) - } - - return ctx.JSON(http.StatusCreated, user) -} - -func (h *UserHandler) UpdateUser(ctx echo.Context) error { - var input struct { - ID int64 `param:"id" validate:"required"` - Name string `json:"name" validate:"required"` - Email string `json:"email" validate:"required"` - Password string `json:"password" validate:"required"` - } - - if err := ctx.Bind(&input); err != nil { - return ctx.JSON(http.StatusBadRequest, validator.ValidatorErrors(err)) - } - - user := entity.UpdateUser(input.ID, input.Name, input.Email, input.Password) - - err := h.userService.Update(ctx.Request().Context(), user) - if err != nil { - return ctx.JSON(http.StatusUnprocessableEntity, err) - } - - return ctx.JSON(http.StatusOK, user) -} - -func (h *UserHandler) DeleteUser(ctx echo.Context) error { - var input struct { - ID int64 `param:"id" validate:"required"` - } - - if err := ctx.Bind(&input); err != nil { - return ctx.JSON(http.StatusBadRequest, validator.ValidatorErrors(err)) - } - - err := h.userService.Delete(ctx.Request().Context(), input.ID) - if err != nil { - return ctx.JSON(http.StatusUnprocessableEntity, err) - } - - return ctx.NoContent(http.StatusNoContent) -} - -func (h *UserHandler) GetUserByID(ctx echo.Context) error { - var input struct { - ID int64 `param:"id" validate:"required"` - } - - if err := ctx.Bind(&input); err != nil { - return ctx.JSON(http.StatusBadRequest, validator.ValidatorErrors(err)) - } - - user, err := h.userService.FindByID(ctx.Request().Context(), input.ID) - if err != nil { - return ctx.JSON(http.StatusUnprocessableEntity, err) - } - - return ctx.JSON(http.StatusOK, user) -} diff --git a/internal/http/router/routes.go b/internal/http/router/routes.go deleted file mode 100644 index 1281abf..0000000 --- a/internal/http/router/routes.go +++ /dev/null @@ -1,52 +0,0 @@ -package router - -import ( - "github.com/labstack/echo/v4" - "github.com/zhikariz/weather-app/internal/http/handler" -) - -type Route struct { - Method string - Path string - Handler echo.HandlerFunc -} - -func PublicRoutes(authHandler *handler.AuthHandler) []*Route { - return []*Route{ - { - Method: echo.POST, - Path: "/login", - Handler: authHandler.Login, - }, - } -} - -func PrivateRoutes(userHandler *handler.UserHandler) []*Route { - return []*Route{ - { - Method: echo.GET, - Path: "/users", - Handler: userHandler.GetAllUsers, - }, - { - Method: echo.GET, - Path: "/users/:id", - Handler: userHandler.GetUserByID, - }, - { - Method: echo.POST, - Path: "/users", - Handler: userHandler.CreateUser, - }, - { - Method: echo.PUT, - Path: "/users/:id", - Handler: userHandler.UpdateUser, - }, - { - Method: echo.DELETE, - Path: "/users/:id", - Handler: userHandler.DeleteUser, - }, - } -} diff --git a/internal/http/server/echo.go b/internal/http/server/echo.go deleted file mode 100644 index e328be6..0000000 --- a/internal/http/server/echo.go +++ /dev/null @@ -1,56 +0,0 @@ -package server - -import ( - "github.com/golang-jwt/jwt/v5" - echojwt "github.com/labstack/echo-jwt/v4" - "github.com/labstack/echo/v4" - "github.com/labstack/echo/v4/middleware" - "github.com/zhikariz/weather-app/common" - "github.com/zhikariz/weather-app/internal/config" - "github.com/zhikariz/weather-app/internal/http/binder" - "github.com/zhikariz/weather-app/internal/http/router" -) - -type Server struct { - *echo.Echo -} - -func NewServer( - cfg *config.Config, - binder *binder.Binder, - publicRoutes, privateRoutes []*router.Route) *Server { - e := echo.New() - e.HideBanner = true - e.Binder = binder - - e.Use( - middleware.Logger(), - middleware.Recover(), - middleware.CORS(), - ) - - v1 := e.Group("/api/v1") - - for _, public := range publicRoutes { - v1.Add(public.Method, public.Path, public.Handler) - } - - for _, private := range privateRoutes { - v1.Add(private.Method, private.Path, private.Handler, JWTProtected(cfg.JWT.SecretKey)) - } - - e.GET("/ping", func(c echo.Context) error { - return c.String(200, "pong") - }) - - return &Server{e} -} - -func JWTProtected(secretKey string) echo.MiddlewareFunc { - return echojwt.WithConfig(echojwt.Config{ - NewClaimsFunc: func(c echo.Context) jwt.Claims { - return new(common.JwtCustomClaims) - }, - SigningKey: []byte(secretKey), - }) -} diff --git a/internal/http/validator/validator.go b/internal/http/validator/validator.go deleted file mode 100644 index d82963b..0000000 --- a/internal/http/validator/validator.go +++ /dev/null @@ -1,48 +0,0 @@ -package validator - -import ( - "fmt" - "reflect" - "strings" - - "github.com/go-playground/validator/v10" -) - -type FormValidator struct { - validator *validator.Validate -} - -func (fv *FormValidator) Validate(i interface{}) error { - return fv.validator.Struct(i) -} - -func NewFormValidator() *FormValidator { - validate := validator.New(validator.WithRequiredStructEnabled()) - - validate.RegisterTagNameFunc(func(fld reflect.StructField) string { - name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] - if name == "-" { - return "" - } - return name - }) - - return &FormValidator{validate} -} - -func ValidatorErrors(err error) map[string]string { - fields := map[string]string{} - - if castedObject, ok := err.(validator.ValidationErrors); ok { - for _, err := range castedObject { - switch err.Tag() { - case "required": - fields[err.Field()] = fmt.Sprintf("field %s harus di isi", err.Field()) - default: - fields[err.Field()] = fmt.Sprintf("%s error with tag %s should be %s", err.Field(), err.Tag(), err.Param()) - } - } - } - - return fields -} diff --git a/internal/repository/user.repository.go b/internal/repository/user.repository.go deleted file mode 100644 index 381d218..0000000 --- a/internal/repository/user.repository.go +++ /dev/null @@ -1,68 +0,0 @@ -package repository - -import ( - "context" - "errors" - - "github.com/zhikariz/weather-app/entity" - "gorm.io/gorm" -) - -type UserRepository struct { - db *gorm.DB -} - -func NewUserRepository(db *gorm.DB) *UserRepository { - return &UserRepository{ - db: db, - } -} - -func (r *UserRepository) FindAll(ctx context.Context) ([]*entity.User, error) { - users := make([]*entity.User, 0) - err := r.db.WithContext(ctx).Find(&users).Error // SELECT * FROM users - if err != nil { - return nil, err - } - return users, nil -} - -func (r *UserRepository) Create(ctx context.Context, user *entity.User) error { - if err := r.db.WithContext(ctx).Create(&user).Error; err != nil { - return err - } - return nil -} - -func (r *UserRepository) Update(ctx context.Context, user *entity.User) error { - if err := r.db.WithContext(ctx). - Model(&entity.User{}). - Where("id = ?", user.ID). - Updates(&user).Error; err != nil { - return err - } - return nil -} - -func (r *UserRepository) Delete(ctx context.Context, id int64) error { - if err := r.db.WithContext(ctx).Delete(&entity.User{}, id).Error; err != nil { - return err - } - return nil -} - -func (r *UserRepository) FindByID(ctx context.Context, id int64) (*entity.User, error) { - user := new(entity.User) - if err := r.db.WithContext(ctx).First(&user, id).Error; err != nil { - return nil, err - } - return user, nil -} - -func (r *UserRepository) FindByEmail(ctx context.Context, email string) (*entity.User, error) { - user := new(entity.User) - if err := r.db.WithContext(ctx).Where("email = ?", email).First(&user).Error; err != nil { - return nil, errors.New("user with that email not found") - } - return user, nil -} diff --git a/internal/service/login.service.go b/internal/service/login.service.go deleted file mode 100644 index a05eb76..0000000 --- a/internal/service/login.service.go +++ /dev/null @@ -1,44 +0,0 @@ -package service - -import ( - "context" - "errors" - - "github.com/zhikariz/weather-app/entity" -) - -type LoginUseCase interface { - Login(ctx context.Context, email, password string) (*entity.User, error) -} - -type LoginRepository interface { - FindByEmail(ctx context.Context, email string) (*entity.User, error) -} - -type LoginService struct { - repo LoginRepository -} - -func NewLoginService(repo LoginRepository) *LoginService { - return &LoginService{ - repo: repo, - } -} - -func (s *LoginService) Login(ctx context.Context, email, password string) (*entity.User, error) { - user, err := s.repo.FindByEmail(ctx, email) - - if err != nil { - return nil, err - } - - if user == nil { - return nil, errors.New("user with that email not found") - } - - if user.Password != password { - return nil, errors.New("incorrect login credentials") - } - - return user, nil -} diff --git a/internal/service/token.service.go b/internal/service/token.service.go deleted file mode 100644 index 1e450b5..0000000 --- a/internal/service/token.service.go +++ /dev/null @@ -1,47 +0,0 @@ -package service - -import ( - "context" - "time" - - "github.com/golang-jwt/jwt/v5" - "github.com/zhikariz/weather-app/common" - "github.com/zhikariz/weather-app/entity" - "github.com/zhikariz/weather-app/internal/config" -) - -type TokenUseCase interface { - GenerateAccessToken(ctx context.Context, user *entity.User) (string, error) -} - -type TokenService struct { - cfg *config.Config -} - -func NewTokenService(cfg *config.Config) *TokenService { - return &TokenService{ - cfg: cfg, - } -} - -func (s *TokenService) GenerateAccessToken(ctx context.Context, user *entity.User) (string, error) { - expiredTime := time.Now().Local().Add(10 * time.Minute) - claims := common.JwtCustomClaims{ - ID: user.ID, - Name: user.Name, - Email: user.Email, - RegisteredClaims: jwt.RegisteredClaims{ - ExpiresAt: jwt.NewNumericDate(expiredTime), - }, - } - - token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - - encodedToken, err := token.SignedString([]byte(s.cfg.JWT.SecretKey)) - - if err != nil { - return "", err - } - - return encodedToken, nil -} diff --git a/internal/service/user.service.go b/internal/service/user.service.go deleted file mode 100644 index b5a056d..0000000 --- a/internal/service/user.service.go +++ /dev/null @@ -1,51 +0,0 @@ -package service - -import ( - "context" - - "github.com/zhikariz/weather-app/entity" -) - -type UserUseCase interface { - FindAll(ctx context.Context) ([]*entity.User, error) - Create(ctx context.Context, user *entity.User) error - Update(ctx context.Context, user *entity.User) error - Delete(ctx context.Context, id int64) error - FindByID(ctx context.Context, id int64) (*entity.User, error) -} - -type UserRepository interface { - FindAll(ctx context.Context) ([]*entity.User, error) - Create(ctx context.Context, user *entity.User) error - Update(ctx context.Context, user *entity.User) error - Delete(ctx context.Context, id int64) error - FindByID(ctx context.Context, id int64) (*entity.User, error) -} - -type UserService struct { - repository UserRepository -} - -func NewUserService(repository UserRepository) *UserService { - return &UserService{repository} -} - -func (s *UserService) FindAll(ctx context.Context) ([]*entity.User, error) { - return s.repository.FindAll(ctx) -} - -func (s *UserService) Create(ctx context.Context, user *entity.User) error { - return s.repository.Create(ctx, user) -} - -func (s *UserService) Update(ctx context.Context, user *entity.User) error { - return s.repository.Update(ctx, user) -} - -func (s *UserService) Delete(ctx context.Context, id int64) error { - return s.repository.Delete(ctx, id) -} - -func (s *UserService) FindByID(ctx context.Context, id int64) (*entity.User, error) { - return s.repository.FindByID(ctx, id) -}