diff --git a/.env-example b/.env-example deleted file mode 100644 index 9d0cb0e..0000000 --- a/.env-example +++ /dev/null @@ -1,80 +0,0 @@ -####################################### -###### App ###### -####################################### -APP_NAME=GoCondor -APP_ENV=local # local | testing | production -APP_DEBUG_MODE=true -App_HTTP_HOST=localhost -App_HTTP_PORT=80 -App_USE_HTTPS=false -App_USE_LETSENCRYPT=false -APP_LETSENCRYPT_EMAIL=mail@example.com -App_HTTPS_HOSTS=example.com, www.example.com -App_REDIRECT_HTTP_TO_HTTPS=false -App_CERT_FILE_PATH=tls/server.crt -App_KEY_FILE_PATH=tls/server.key - -####################################### -###### JWT ###### -####################################### -JWT_SECRET=dkfTgonmgaAdlgkw -JWT_LIFESPAN_MINUTES=10080 # expires after 7 days - -####################################### -###### DATABASE ###### -####################################### -DB_DRIVER=mysql # mysql | postgres | sqlite -#_____ MYSQL _____# -MYSQL_HOST=db-host-here -MYSQL_DB_NAME=db-name-here -MYSQL_PORT=3306 -MYSQL_USERNAME=db-user-here -MYSQL_PASSWORD=db-password-here -MYSQL_CHARSET=utf8mb4 - -#_____ postgres _____# -POSTGRES_HOST=localhost -POSTGRES_USER=user -POSTGRES_PASSWORD=secret -POSTGRES_DB_NAME=db_test -POSTGRES_PORT=5432 -POSTGRES_SSL_MODE=disable -POSTGRES_TIMEZONE=Asia/Dubai - -#_____ SQLITE _____# -SQLITE_DB_PATH=storage/sqlite/db.sqlite - -####################################### -###### CACHE ###### -####################################### -CACHE_DRIVER=redis -REDIS_HOST=localhost -REDIS_PORT=6379 -REDIS_PASSWORD= -REDIS_DB=0 - -####################################### -###### Emails ###### -####################################### -EMAILS_DRIVER=smtp # smtp | sparkpost | sendgrid | mailgun -#_____ SMTP _____# -SMTP_HOST= -SMTP_PORT=25 -SMTP_USERNAME= -SMTP_PASSWORD= -SMTP_TLS_SKIP_VERIFY_HOST=true # (set true for development only!) - -#_____ sparkpost _____# -SPARKPOST_BASE_URL=https://api.sparkpost.com -SPARKPOST_API_VERSION=1 -SPARKPOST_API_KEY=sparkpost-api-key-here # the api key - -#_____ sendgrid _____# -SENDGRID_HOST=https://api.sendgrid.com -SENDGRID_ENDPOINT=/v3/mail/send -SENDGRID_API_KEY=sendgrid-api-key-here # the api key - -#_____ mailgun _____# -MAILGUN_DOMAIN=your-domain.com # your domain -MAILGUN_API_KEY=mailgun-api-key-here # the api key -MAILGUN_TLS_SKIP_VERIFY_HOST=true # (set true for development only!) diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 0a2b8bd..0000000 --- a/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -.air.toml -tmp/* -logs/* -!logs/.gitkeep -tls/* -!tls/.gitkeep -.DS_Store \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 73f99e6..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2021 Harran Ali - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/README.md b/README.md index 4e35c2e..e69de29 100644 --- a/README.md +++ b/README.md @@ -1,20 +0,0 @@ -## Example Todo App using Goffee framework -This repository contains the code for an example todo app using [Goffee framework](https://git.smarteching.com/goffee) - -### How to run locally? -1- Clone the repository -2- Next add your database credentials (mysql) to the `.env` file -3- `cd` into the project dir and run `go mod tidy` to install any missing dependency -4- Run the app using Goffee's cli tool [Goffee](https://git.smarteching.com/goffee/goffee) -```bash - goffee run:dev -``` -if [Goffee](https://git.smarteching.com/goffee/goffee) is not installed you can install it by executing the following command -```bash -go install git.smarteching.com/goffee/goffee@latest - -``` - -All routers are defined in the file `routes.go` - -All request controllers are defined in the directory `controllers/` \ No newline at end of file diff --git a/config/cache.go b/config/cache.go deleted file mode 100644 index 5606b38..0000000 --- a/config/cache.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2023 Harran Ali . All rights reserved. -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package config - -import "git.smarteching.com/goffee/core" - -// Retrieve the main config for the cache -func GetCacheConfig() core.CacheConfig { - //##################################### - //# Main configuration for cache ##### - //##################################### - - return core.CacheConfig{ - // For enabling and disabling the cache - // set to true to enable it, set to false to disable - EnableCache: true, - } -} diff --git a/config/dotenvfile.go b/config/dotenvfile.go deleted file mode 100644 index 58a6f8b..0000000 --- a/config/dotenvfile.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2023 Harran Ali . All rights reserved. -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package config - -import "git.smarteching.com/goffee/core" - -// Retrieve the main config for controlling the .env file -func GetEnvFileConfig() core.EnvFileConfig { - //######################################################### - //# Main configuration for controlling the .env file ##### - //######################################################### - - return core.EnvFileConfig{ - // Set to true to read the environment variables from the .env file and then - // inject them into the os environment, please keep in mind this will override any - // variables previously set in the os envrionment - // set to false to ignore the .env file - UseDotEnvFile: true, - } -} diff --git a/config/gorm.go b/config/gorm.go deleted file mode 100644 index b99e81e..0000000 --- a/config/gorm.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2023 Harran Ali . All rights reserved. -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package config - -import "git.smarteching.com/goffee/core" - -// Retrieve the main config for the GORM -func GetGormConfig() core.GormConfig { - //##################################### - //# Main configuration for GORM ##### - //##################################### - - return core.GormConfig{ - // For enabling and disabling the GORM - // set to true to enable it, set to false to disable - EnableGorm: true, - } -} diff --git a/config/request.go b/config/request.go deleted file mode 100644 index f0cc166..0000000 --- a/config/request.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2023 Harran Ali . All rights reserved. -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package config - -import "git.smarteching.com/goffee/core" - -// Retrieve the main config for the HTTP request -func GetRequestConfig() core.RequestConfig { - //##################################### - //# Main configuration for gorm ##### - //##################################### - - return core.RequestConfig{ - // Set the max file upload size - MaxUploadFileSize: 20000000, // ~20MB - } -} diff --git a/events/.gitkeep b/events/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/events/event-names.go b/events/event-names.go deleted file mode 100644 index 0e5f431..0000000 --- a/events/event-names.go +++ /dev/null @@ -1,6 +0,0 @@ -package events - -// event names -const USER_REGISTERED = "user-registered" -const USER_PASSWORD_RESET_REQUESTED = "user-password-reset-requested" -const PASSWORD_CHANGED = "password-changed" diff --git a/events/eventjobs/.gitkeep b/events/eventjobs/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/events/eventjobs/send-password-changed-email.go b/events/eventjobs/send-password-changed-email.go deleted file mode 100644 index 2a44f5d..0000000 --- a/events/eventjobs/send-password-changed-email.go +++ /dev/null @@ -1,31 +0,0 @@ -package eventjobs - -import ( - "fmt" - - "git.smarteching.com/goffee/core" - "git.smarteching.com/goffee/todoapp/models" -) - -var SendPasswordChangedEmail core.EventJob = func(event *core.Event, c *core.Context) { - go func() { - mailer := c.GetMailer() - logger := c.GetLogger() - - user, ok := event.Payload["user"].(models.User) - if !ok { - logger.Error("[SendPasswordChangedEmail job] invalid user") - return - } - mailer.SetFrom(core.EmailAddress{Name: "GoCondor", Address: "mail@example.com"}) - mailer.SetTo([]core.EmailAddress{ - { - Name: user.Name, Address: user.Email, - }, - }) - mailer.SetSubject("Password Changed") - body := fmt.Sprintf("Hi %v, \nYour password have been changed. \nThanks.", user.Name) - mailer.SetPlainTextBody(body) - mailer.Send() - }() -} diff --git a/events/eventjobs/send-reset-password-email.go b/events/eventjobs/send-reset-password-email.go deleted file mode 100644 index 2b23efd..0000000 --- a/events/eventjobs/send-reset-password-email.go +++ /dev/null @@ -1,38 +0,0 @@ -package eventjobs - -import ( - "fmt" - "os" - - "git.smarteching.com/goffee/core" - "git.smarteching.com/goffee/todoapp/models" -) - -var SendResetPasswordEmail core.EventJob = func(event *core.Event, c *core.Context) { - go func() { - mailer := c.GetMailer() - logger := c.GetLogger() - - user, ok := event.Payload["user"].(models.User) - if !ok { - logger.Error("[SendResetPasswordEmail job] invalid user") - return - } - mailer.SetFrom(core.EmailAddress{Name: "Goffee", Address: "mail@example.com"}) - mailer.SetTo([]core.EmailAddress{ - { - Name: user.Name, Address: user.Email, - }, - }) - - mailer.SetSubject("Reset Password Link") - hostname, err := os.Hostname() - if err != nil { - c.GetLogger().Error(err.Error()) - } - resetPasswordLink := fmt.Sprintf("%v/reset-password/code/%v", hostname, c.CastToString(event.Payload["code"])) - body := fmt.Sprintf("Hi %v,
Click the link below to reset your password
Reset Password.
Thanks.", user.Name, resetPasswordLink) - mailer.SetHTMLBody(body) - mailer.Send() - }() -} diff --git a/events/eventjobs/send-welcome-email.go b/events/eventjobs/send-welcome-email.go deleted file mode 100644 index aeefc3f..0000000 --- a/events/eventjobs/send-welcome-email.go +++ /dev/null @@ -1,31 +0,0 @@ -package eventjobs - -import ( - "fmt" - - "git.smarteching.com/goffee/core" - "git.smarteching.com/goffee/todoapp/models" -) - -var SendWelcomeEmail core.EventJob = func(event *core.Event, c *core.Context) { - go func() { - mailer := c.GetMailer() - logger := c.GetLogger() - - user, ok := event.Payload["user"].(models.User) - if !ok { - logger.Error("[SenEmail job] invalid user") - return - } - mailer.SetFrom(core.EmailAddress{Name: "GoCondor", Address: "mail@example.com"}) - mailer.SetTo([]core.EmailAddress{ - { - Name: user.Name, Address: user.Email, - }, - }) - mailer.SetSubject("Welcome To GoCondor") - body := fmt.Sprintf("Hi %v, \nWelcome to GoCondor \nYour account have been created successfully. \nThanks.", user.Name) - mailer.SetPlainTextBody(body) - mailer.Send() - }() -} diff --git a/events/eventjobs/test-job.go b/events/eventjobs/test-job.go deleted file mode 100644 index e4d0d8c..0000000 --- a/events/eventjobs/test-job.go +++ /dev/null @@ -1,9 +0,0 @@ -package eventjobs - -import ( - "git.smarteching.com/goffee/core" -) - -var TestEvent core.EventJob = func(event *core.Event, c *core.Context) { - c.GetLogger().Info("hello from event test job") -} diff --git a/go.mod b/go.mod deleted file mode 100644 index 2b2020c..0000000 --- a/go.mod +++ /dev/null @@ -1,43 +0,0 @@ -module git.smarteching.com/goffee/todoapp - -go 1.23.1 - -require ( - git.smarteching.com/goffee/core v1.7.2 - github.com/google/uuid v1.6.0 - github.com/joho/godotenv v1.5.1 - github.com/julienschmidt/httprouter v1.3.0 - gorm.io/gorm v1.25.12 -) - -require ( - github.com/SparkPost/gosparkpost v0.2.0 // indirect - github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/go-chi/chi/v5 v5.0.8 // indirect - github.com/go-ozzo/ozzo-validation v3.6.0+incompatible // indirect - github.com/go-sql-driver/mysql v1.7.0 // indirect - github.com/golang-jwt/jwt/v5 v5.0.0 // indirect - github.com/harranali/mailing v1.2.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.3.1 // indirect - github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.5 // indirect - github.com/json-iterator/go v1.1.10 // indirect - github.com/mailgun/mailgun-go/v4 v4.10.0 // indirect - github.com/mattn/go-sqlite3 v1.14.17 // indirect - github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect - github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/redis/go-redis/v9 v9.0.5 // indirect - github.com/sendgrid/rest v2.6.9+incompatible // indirect - github.com/sendgrid/sendgrid-go v3.12.0+incompatible // indirect - golang.org/x/crypto v0.11.0 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/text v0.14.0 // indirect - gorm.io/driver/mysql v1.5.1 // indirect - gorm.io/driver/postgres v1.5.2 // indirect - gorm.io/driver/sqlite v1.5.2 // indirect -) diff --git a/go.sum b/go.sum deleted file mode 100644 index f62fce7..0000000 --- a/go.sum +++ /dev/null @@ -1,115 +0,0 @@ -git.smarteching.com/goffee/core v1.7.2 h1:3rha+OSi1UFqHkEZwyBKuFy0pOYt60HiHpEPQFEkJlk= -git.smarteching.com/goffee/core v1.7.2/go.mod h1:QQNIHVN6qjJBtq42WCQMrLYN9oFE3wm26SLU8ZxNTec= -github.com/SparkPost/gosparkpost v0.2.0 h1:yzhHQT7cE+rqzd5tANNC74j+2x3lrPznqPJrxC1yR8s= -github.com/SparkPost/gosparkpost v0.2.0/go.mod h1:S9WKcGeou7cbPpx0kTIgo8Q69WZvUmVeVzbD+djalJ4= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/brianvoe/gofakeit/v6 v6.21.0 h1:tNkm9yxEbpuPK8Bx39tT4sSc5i9SUGiciLdNix+VDQY= -github.com/brianvoe/gofakeit/v6 v6.21.0/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8= -github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao= -github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= -github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y= -github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= -github.com/buger/jsonparser v1.0.0/go.mod h1:tgcrVJ81GPSF0mz+0nu1Xaz0fazGPrmmJfJtxjbHhUQ= -github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a/go.mod h1:2GxOXOlEPAMFPfp014mK1SWq8G8BN8o7/dfYqJrVGn8= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -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/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= -github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= -github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= -github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= -github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y= -github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= -github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= -github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-ozzo/ozzo-validation v3.6.0+incompatible h1:msy24VGS42fKO9K1vLz82/GeYW1cILu7Nuuj1N3BBkE= -github.com/go-ozzo/ozzo-validation v3.6.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU= -github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= -github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/gogs/chardet v0.0.0-20150115103509-2404f7772561/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14= -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/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/harranali/mailing v1.2.0 h1:ihIyJwB8hyRVcdk+v465wk1PHMrSrgJqo/kMd+gZClY= -github.com/harranali/mailing v1.2.0/go.mod h1:4a5N3yG98pZKluMpmcYlTtll7bisvOfGQEMIng3VQk4= -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.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU= -github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= -github.com/jaytaylor/html2text v0.0.0-20190408195923-01ec452cbe43/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= -github.com/jhillyerd/enmime v0.8.0/go.mod h1:MBHs3ugk03NGjMM6PuRynlKf+HA5eSillZ+TRCm73AE= -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/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/mailgun/mailgun-go/v4 v4.10.0 h1:e5LVsxpqjOYRyaOWifrJORoLQZTYDP+g4ljfmf9G2zE= -github.com/mailgun/mailgun-go/v4 v4.10.0/go.mod h1:L9s941Lgk7iB3TgywTPz074pK2Ekkg4kgbnAaAyJ2z8= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= -github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -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/redis/go-redis/v9 v9.0.5 h1:CuQcn5HIEeK7BgElubPP8CGtE0KakrnbBSTLjathl5o= -github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= -github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= -github.com/sendgrid/rest v2.6.9+incompatible h1:1EyIcsNdn9KIisLW50MKwmSRSK+ekueiEMJ7NEoxJo0= -github.com/sendgrid/rest v2.6.9+incompatible/go.mod h1:kXX7q3jZtJXK5c5qK83bSGMdV6tsOE70KbHoqJls4lE= -github.com/sendgrid/sendgrid-go v3.12.0+incompatible h1:/N2vx18Fg1KmQOh6zESc5FJB8pYwt5QFBDflYPh1KVg= -github.com/sendgrid/sendgrid-go v3.12.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8= -github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -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.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw= -gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o= -gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0= -gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8= -gorm.io/driver/sqlite v1.5.2 h1:TpQ+/dqCY4uCigCFyrfnrJnrW9zjpelWVoEVNy5qJkc= -gorm.io/driver/sqlite v1.5.2/go.mod h1:qxAuCol+2r6PannQDpOP1FP6ag3mKi4esLnB/jHed+4= -gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= -gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= -gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= diff --git a/handlers/authentication.go b/handlers/authentication.go deleted file mode 100644 index 7e24f15..0000000 --- a/handlers/authentication.go +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright 2023 Harran Ali . All rights reserved. -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package handlers - -import ( - "encoding/json" - "errors" - "net/http" - "strconv" - "strings" - "time" - - "git.smarteching.com/goffee/core" - "git.smarteching.com/goffee/todoapp/events" - "git.smarteching.com/goffee/todoapp/models" - "git.smarteching.com/goffee/todoapp/utils" - "github.com/google/uuid" - "gorm.io/gorm" -) - -func Signup(c *core.Context) *core.Response { - name := c.GetRequestParam("name") - email := c.GetRequestParam("email") - password := c.GetRequestParam("password") - // check if email exists - var user models.User - res := c.GetGorm().Where("email = ?", c.CastToString(email)).First(&user) - if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) { - c.GetLogger().Error(res.Error.Error()) - return c.Response.SetStatusCode(http.StatusInternalServerError).Json(c.MapToJson(map[string]string{ - "message": "internal error", - })) - } - if res.Error == nil { - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(c.MapToJson(map[string]string{ - "message": "email already exists in the database", - })) - } - - // validation data - data := map[string]interface{}{ - "name": name, - "email": email, - "password": password, - } - // validation rules - rules := map[string]interface{}{ - "name": "required|alphaNumeric", - "email": "required|email", - "password": "required|length:6,10", - } - // validate - v := c.GetValidator().Validate(data, rules) - if v.Failed() { - c.GetLogger().Error(v.GetErrorMessagesJson()) - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(v.GetErrorMessagesJson()) - } - - //hash the password - passwordHashed, err := c.GetHashing().HashPassword(c.CastToString(password)) - if err != nil { - c.GetLogger().Error(err.Error()) - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(c.MapToJson(map[string]interface{}{ - "message": err.Error(), - })) - } - // store the record in db - user = models.User{ - Name: c.CastToString(name), - Email: c.CastToString(email), - Password: passwordHashed, - } - res = c.GetGorm().Create(&user) - if res.Error != nil { - c.GetLogger().Error(res.Error.Error()) - return c.Response.SetStatusCode(http.StatusInternalServerError).Json(c.MapToJson(map[string]string{ - "message": res.Error.Error(), - })) - } - - token, err := c.GetJWT().GenerateToken(map[string]interface{}{ - "userID": user.ID, - }) - - if err != nil { - c.GetLogger().Error(err.Error()) - return c.Response.SetStatusCode(http.StatusInternalServerError).Json(c.MapToJson(map[string]string{ - "message": "internal server error", - })) - } - - // cache the token - userAgent := c.GetUserAgent() - hashedCacheKey := utils.CreateAuthTokenHashedCacheKey(user.ID, userAgent) - err = c.GetCache().Set(hashedCacheKey, token) - if err != nil { - c.GetLogger().Error(err.Error()) - return c.Response.SetStatusCode(http.StatusInternalServerError).Json(c.MapToJson(map[string]interface{}{ - "message": "internal server error", - })) - } - - // fire user registered event - err = c.GetEventsManager().Fire(&core.Event{Name: events.USER_REGISTERED, Payload: map[string]interface{}{ - "user": user, - }}) - if err != nil { - c.GetLogger().Error(err.Error()) - return c.Response.SetStatusCode(http.StatusInternalServerError).Json(c.MapToJson(map[string]string{ - "message": "internal server error", - })) - } - - return c.Response.Json(c.MapToJson(map[string]string{ - "token": token, - })) -} - -func Signin(c *core.Context) *core.Response { - email := c.GetRequestParam("email") - password := c.GetRequestParam("password") - - data := map[string]interface{}{ - "email": email, - "password": password, - } - rules := map[string]interface{}{ - "email": "required|email", - "password": "required", - } - v := c.GetValidator().Validate(data, rules) - - if v.Failed() { - c.GetLogger().Error(v.GetErrorMessagesJson()) - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(v.GetErrorMessagesJson()) - } - - var user models.User - res := c.GetGorm().Where("email = ?", c.CastToString(email)).First(&user) - if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) { - c.GetLogger().Error(res.Error.Error()) - return c.Response.SetStatusCode(http.StatusInternalServerError).Json(c.MapToJson(map[string]string{ - "message": "internal server error", - })) - } - - if res.Error != nil && errors.Is(res.Error, gorm.ErrRecordNotFound) { - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(c.MapToJson(map[string]string{ - "message": "invalid email or password", - })) - } - - ok, err := c.GetHashing().CheckPasswordHash(user.Password, c.CastToString(password)) - if err != nil { - c.GetLogger().Error(err.Error()) - return c.Response.SetStatusCode(http.StatusInternalServerError).Json(c.MapToJson(map[string]string{ - "message": err.Error(), - })) - } - - if !ok { - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(c.MapToJson(map[string]string{ - "message": "invalid email or password", - })) - } - - token, err := c.GetJWT().GenerateToken(map[string]interface{}{ - "userID": user.ID, - }) - - if err != nil { - c.GetLogger().Error(err.Error()) - return c.Response.SetStatusCode(http.StatusInternalServerError).Json(c.MapToJson(map[string]string{ - "message": "internal server error", - })) - } - // cache the token - userAgent := c.GetUserAgent() - hashedCacheKey := utils.CreateAuthTokenHashedCacheKey(user.ID, userAgent) - err = c.GetCache().Set(hashedCacheKey, token) - if err != nil { - c.GetLogger().Error(err.Error()) - return c.Response.SetStatusCode(http.StatusInternalServerError).Json(c.MapToJson(map[string]interface{}{ - "message": "internal server error", - })) - } - - return c.Response.Json(c.MapToJson(map[string]string{ - "token": token, - })) -} - -func ResetPasswordRequest(c *core.Context) *core.Response { - email := c.GetRequestParam("email") - - // validation data - data := map[string]interface{}{ - "email": email, - } - // validation rules - rules := map[string]interface{}{ - "email": "required|email", - } - // validate - v := c.GetValidator().Validate(data, rules) - if v.Failed() { - c.GetLogger().Error(v.GetErrorMessagesJson()) - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(v.GetErrorMessagesJson()) - } - - // check email in the database - var user models.User - res := c.GetGorm().Where("email = ?", c.CastToString(email)).First(&user) - if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) { - c.GetLogger().Error(res.Error.Error()) - return c.Response.SetStatusCode(http.StatusInternalServerError).Json(c.MapToJson(map[string]string{ - "message": "internal server error", - })) - } - if res.Error != nil && errors.Is(res.Error, gorm.ErrRecordNotFound) { - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(c.MapToJson(map[string]string{ - "message": "email not found in our database", - })) - } - - // generate the link - expiresAt := time.Now().Add(time.Hour * 3).Unix() - linkCodeData := map[string]string{ - "userID": c.CastToString(user.ID), - "expiresAt": c.CastToString(expiresAt), - } - code := uuid.NewString() - c.GetCache().SetWithExpiration(code, c.MapToJson(linkCodeData), time.Hour*3) - err := c.GetEventsManager().Fire(&core.Event{Name: events.USER_PASSWORD_RESET_REQUESTED, Payload: map[string]interface{}{ - "user": user, - "code": code, - }}) - if err != nil { - c.GetLogger().Error(err.Error()) - return c.Response.SetStatusCode(http.StatusInternalServerError).Json(c.MapToJson(map[string]string{ - "message": "internal server error", - })) - } - - return c.Response.Json(c.MapToJson(map[string]string{ - "message": "reset password email sent successfully", - })) -} - -func SetNewPassword(c *core.Context) *core.Response { - urlCode := c.CastToString(c.GetPathParam("code")) - linkCodeDataStr, err := c.GetCache().Get(urlCode) - if err != nil { - c.GetLogger().Error(err.Error()) - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(c.MapToJson(map[string]string{ - "message": "invalid link", - })) - } - var linkCode map[string]interface{} - json.Unmarshal([]byte(linkCodeDataStr), &linkCode) - expiresAtUnix, err := strconv.ParseInt(c.CastToString(linkCode["expiresAt"]), 10, 64) - if err != nil { - c.GetLogger().Error(err.Error()) - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(c.MapToJson(map[string]string{ - "message": "invalid link", - })) - } - expiresAt := time.Unix(expiresAtUnix, 0) - if time.Now().After(expiresAt) { - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(c.MapToJson(map[string]string{ - "message": "invalid link", - })) - } - userID, err := strconv.ParseUint(c.CastToString(linkCode["userID"]), 10, 64) - if err != nil { - c.GetLogger().Error(err.Error()) - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(c.MapToJson(map[string]string{ - "message": "invalid link", - })) - } - - oldPassword := c.CastToString(c.GetRequestParam("old_password")) - newPassword := c.CastToString(c.GetRequestParam("new_password")) - newPasswordConfirm := c.CastToString(c.GetRequestParam("new_password_confirm")) - - // validation data - data := map[string]interface{}{ - "old_password": oldPassword, - "new_password": newPassword, - "new_password_confirm": newPasswordConfirm, - } - // validation rules - rules := map[string]interface{}{ - "old_password": "required|length:6,10", - "new_password": "required|length:6,10", - "new_password_confirm": "required|length:6,10", - } - // validate - v := c.GetValidator().Validate(data, rules) - if v.Failed() { - c.GetLogger().Error(v.GetErrorMessagesJson()) - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(v.GetErrorMessagesJson()) - } - - var user models.User - res := c.GetGorm().Where("id = ?", userID).First(&user) - if res.Error != nil { - c.GetLogger().Error(res.Error.Error()) - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(c.MapToJson(map[string]string{ - "message": "invalid link", - })) - } - - SamePassword, err := c.GetHashing().CheckPasswordHash(user.Password, oldPassword) - if err != nil { - c.GetLogger().Error(err.Error()) - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(c.MapToJson(map[string]string{ - "message": "invalid link", - })) - } - - if !SamePassword { - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(c.MapToJson(map[string]string{ - "message": "the old password is incorrect", - })) - } - - if newPassword != newPasswordConfirm { - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(c.MapToJson(map[string]string{ - "message": "new password does not match new password confirmation", - })) - } - - hashedNewPassword, err := c.GetHashing().HashPassword(newPassword) - if err != nil { - c.GetLogger().Error(err.Error()) - return c.Response.SetStatusCode(http.StatusUnprocessableEntity).Json(c.MapToJson(map[string]string{ - "message": "invalid password", - })) - } - - user.Password = hashedNewPassword - c.GetGorm().Save(&user) - - err = c.GetEventsManager().Fire(&core.Event{Name: events.PASSWORD_CHANGED, Payload: map[string]interface{}{ - "user": user, - }}) - - if err != nil { - c.GetLogger().Error(err.Error()) - return c.Response.SetStatusCode(http.StatusInternalServerError).Json(c.MapToJson(map[string]string{ - "message": "internal server error", - })) - } - - return c.Response.Json(c.MapToJson(map[string]string{ - "message": "password changed successfully", - })) -} - -func Signout(c *core.Context) *core.Response { - tokenRaw := c.GetHeader("Authorization") - token := strings.TrimSpace(strings.Replace(tokenRaw, "Bearer", "", 1)) - if token == "" { - return c.Response.SetStatusCode(http.StatusUnauthorized).Json(c.MapToJson(map[string]interface{}{ - "message": "unauthorized", - })) - } - payload, err := c.GetJWT().DecodeToken(token) - if err != nil { - return c.Response.SetStatusCode(http.StatusUnauthorized).Json(c.MapToJson(map[string]interface{}{ - "message": "unauthorized", - })) - } - userAgent := c.GetUserAgent() - hashedCacheKey := utils.CreateAuthTokenHashedCacheKey(uint(c.CastToInt(payload["userID"])), userAgent) - - err = c.GetCache().Delete(hashedCacheKey) - if err != nil { - return c.Response.SetStatusCode(http.StatusInternalServerError).Json(c.MapToJson(map[string]interface{}{ - "message": "internal error", - })) - } - - return c.Response.SetStatusCode(http.StatusOK).Json(c.MapToJson(map[string]interface{}{ - "message": "signed out successfully", - })) -} diff --git a/handlers/home.go b/handlers/home.go deleted file mode 100644 index 6ea5bb2..0000000 --- a/handlers/home.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2023 Harran Ali . All rights reserved. -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package handlers - -import ( - "git.smarteching.com/goffee/core" -) - -// Show home page -func WelcomeHome(c *core.Context) *core.Response { - message := "{\"message\": \"Welcome to GoCondor\"}" - return c.Response.Json(message) -} - -// Show dashboard -func WelcomeToDashboard(c *core.Context) *core.Response { - message := "{\"message\": \"Welcome to Dashboard\"}" - return c.Response.Json(message) -} diff --git a/handlers/todos.go b/handlers/todos.go deleted file mode 100644 index 2fee068..0000000 --- a/handlers/todos.go +++ /dev/null @@ -1,131 +0,0 @@ -package handlers - -import ( - "encoding/json" - "strconv" - - "git.smarteching.com/goffee/core" - "git.smarteching.com/goffee/todoapp/models" -) - -func ListTodos(c *core.Context) *core.Response { - var todos []models.Todo - result := c.GetGorm().Find(&todos) - if result.Error != nil { - return c.Response.SetStatusCode(500).Json(c.MapToJson(map[string]string{"message": result.Error.Error()})) - } - todosJson, err := json.Marshal(todos) - if err != nil { - return c.Response.Json(c.MapToJson(map[string]string{"message": err.Error()})) - } - - return c.Response.Json(string(todosJson)) -} - -func CreateTodos(c *core.Context) *core.Response { - title := c.CastToString(c.GetRequestParam("title")) - body := c.CastToString(c.GetRequestParam("body")) - isDone := c.CastToString(c.GetRequestParam("isDone")) - v := c.GetValidator().Validate(map[string]interface{}{ - "title": title, - "body": body, - "isDone": isDone, - }, map[string]interface{}{ - "title": "required", - "body": "required", - }) - if v.Failed() { - return c.Response.Json(v.GetErrorMessagesJson()) - } - result := c.GetGorm().Create(&models.Todo{ - Title: title, - Body: body, - IsDone: false, - }) - if result.Error != nil { - return c.Response.SetStatusCode(500).Json(c.MapToJson(map[string]string{ - "message": result.Error.Error(), - })) - } - - return c.Response.Json(c.MapToJson(map[string]string{ - "message": "created successfully", - })) -} - -func ShowTodo(c *core.Context) *core.Response { - todoID := c.CastToString(c.GetPathParam("id")) - var todo models.Todo - result := c.GetGorm().First(&todo, todoID) - if result.Error != nil { - return c.Response.SetStatusCode(500).Json(c.MapToJson(map[string]string{"message": result.Error.Error()})) - } - todoJson, err := json.Marshal(todo) - if err != nil { - return c.Response.Json(c.MapToJson(map[string]string{"message": err.Error()})) - } - - return c.Response.Json(string(todoJson)) -} - -func DeleteTodo(c *core.Context) *core.Response { - todoID := c.CastToString(c.GetPathParam("id")) - var todo models.Todo - result := c.GetGorm().Delete(&todo, todoID) - if result.Error != nil { - return c.Response.SetStatusCode(500).Json(c.MapToJson(map[string]string{"message": result.Error.Error()})) - } - - return c.Response.Json(c.MapToJson(map[string]string{"message": "record deleted successfully"})) -} - -func UpdateTodo(c *core.Context) *core.Response { - var title string = "" - var body string = "" - var data map[string]interface{} = map[string]interface{}{} - var rules map[string]interface{} = map[string]interface{}{} - todoID := c.GetPathParam("id") - var todo models.Todo - result := c.GetGorm().First(&todo, todoID) - if result.Error != nil { - return c.Response.Json(c.MapToJson(map[string]string{"message": result.Error.Error()})) - } - if c.RequestParamExists("title") { - title = c.CastToString(c.GetRequestParam("title")) - data["title"] = title - } - if c.RequestParamExists("body") { - body = c.CastToString(c.GetRequestParam("body")) - data["body"] = body - } - if c.RequestParamExists("isDone") { - isDoneStr := c.CastToString(c.GetRequestParam("isDone")) - data["isDone"] = isDoneStr - rules["isDone"] = "in:true,false" - } - v := c.GetValidator().Validate(data, rules) - if v.Failed() { - return c.Response.Json(v.GetErrorMessagesJson()) - } - if c.RequestParamExists("title") { - todo.Title = title - } - if c.RequestParamExists("body") { - todo.Body = body - } - if c.RequestParamExists("isDone") { - isDoneStr := c.CastToString(c.GetRequestParam("isDone")) - isDone, err := strconv.ParseBool(isDoneStr) - if err != nil { - return c.Response.Json(c.MapToJson(map[string]string{"message": err.Error()})) - } - todo.IsDone = isDone - } - c.GetGorm().Save(&todo) - todoJson, err := json.Marshal(todo) - if err != nil { - return c.Response.Json(c.MapToJson(map[string]string{"message": err.Error()})) - } - - return c.Response.Json(string(todoJson)) -} diff --git a/main.go b/main.go deleted file mode 100644 index f969e60..0000000 --- a/main.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2023 Harran Ali . All rights reserved. -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package main - -import ( - "log" - "os" - "path" - - "git.smarteching.com/goffee/core" - "git.smarteching.com/goffee/core/env" - "git.smarteching.com/goffee/core/logger" - "git.smarteching.com/goffee/todoapp/config" - "github.com/joho/godotenv" - "github.com/julienschmidt/httprouter" -) - -// The main function -func main() { - app := core.New() - basePath, err := os.Getwd() - if err != nil { - log.Fatal("error getting current working dir") - } - app.SetBasePath(basePath) - app.MakeDirs("logs", "storage", "storage/sqlite", "tls") - // Handle the reading of the .env file - if config.GetEnvFileConfig().UseDotEnvFile { - envVars, err := godotenv.Read(".env") - if err != nil { - log.Fatal("Error loading .env file") - } - env.SetEnvVars(envVars) - } - // Handle the logs - app.SetLogsDriver(&logger.LogFileDriver{ - FilePath: path.Join(basePath, "logs/app.log"), - }) - app.SetRequestConfig(config.GetRequestConfig()) - app.SetGormConfig(config.GetGormConfig()) - app.SetCacheConfig(config.GetCacheConfig()) - app.Bootstrap() - registerGlobalMiddlewares() - registerRoutes() - registerEvents() - if config.GetGormConfig().EnableGorm == true { - RunAutoMigrations() - } - app.Run(httprouter.New()) -} diff --git a/middlewares/another-example-middleware.go.go b/middlewares/another-example-middleware.go.go deleted file mode 100644 index 2fdb6f6..0000000 --- a/middlewares/another-example-middleware.go.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2023 Harran Ali . All rights reserved. -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package middlewares - -import ( - "fmt" - - "git.smarteching.com/goffee/core" -) - -// Another example middleware -var AnotherExampleMiddleware core.Middleware = func(c *core.Context) { - fmt.Println("another example middleware!") - c.Next() -} diff --git a/middlewares/auth-check.go b/middlewares/auth-check.go deleted file mode 100644 index fde3c4c..0000000 --- a/middlewares/auth-check.go +++ /dev/null @@ -1,69 +0,0 @@ -package middlewares - -import ( - "errors" - "net/http" - "strings" - - "git.smarteching.com/goffee/core" - "git.smarteching.com/goffee/todoapp/models" - "git.smarteching.com/goffee/todoapp/utils" - "gorm.io/gorm" -) - -var AuthCheck core.Middleware = func(c *core.Context) { - tokenRaw := c.GetHeader("Authorization") - token := strings.TrimSpace(strings.Replace(tokenRaw, "Bearer", "", 1)) - if token == "" { - c.Response.SetStatusCode(http.StatusUnauthorized).Json(c.MapToJson(map[string]interface{}{ - "message": "unauthorized", - })).ForceSendResponse() - return - } - payload, err := c.GetJWT().DecodeToken(token) - if err != nil { - c.Response.SetStatusCode(http.StatusUnauthorized).Json(c.MapToJson(map[string]interface{}{ - "message": "unauthorized", - })).ForceSendResponse() - return - } - userAgent := c.GetUserAgent() - hashedCacheKey := utils.CreateAuthTokenHashedCacheKey(uint(c.CastToInt(payload["userID"])), userAgent) - - cachedToken, err := c.GetCache().Get(hashedCacheKey) - if err != nil { - // user signed out - c.Response.SetStatusCode(http.StatusUnauthorized).Json(c.MapToJson(map[string]interface{}{ - "message": "unauthorized", - })).ForceSendResponse() - return - } - if cachedToken != token { - // using old token replaced with new one after recent signin - c.Response.SetStatusCode(http.StatusUnauthorized).Json(c.MapToJson(map[string]interface{}{ - "message": "unauthorized", - })).ForceSendResponse() - return - } - - var user models.User - res := c.GetGorm().Where("id = ?", payload["userID"]).First(&user) - if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) { - // error with the database - c.GetLogger().Error(res.Error.Error()) - c.Response.SetStatusCode(http.StatusInternalServerError).Json(c.MapToJson(map[string]interface{}{ - "message": "internal error", - })).ForceSendResponse() - return - } - - if res.Error != nil && errors.Is(res.Error, gorm.ErrRecordNotFound) { - // user record is not found (deleted) - c.Response.SetStatusCode(http.StatusUnauthorized).Json(c.MapToJson(map[string]interface{}{ - "message": "unauthorized", - })).ForceSendResponse() - return - } - - c.Next() -} diff --git a/middlewares/example-middleware.go b/middlewares/example-middleware.go deleted file mode 100644 index 457e494..0000000 --- a/middlewares/example-middleware.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2023 Harran Ali . All rights reserved. -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package middlewares - -import ( - "fmt" - - "git.smarteching.com/goffee/core" -) - -// Example middleware -var ExampleMiddleware core.Middleware = func(c *core.Context) { - fmt.Println("example middleware!") - c.Next() -} diff --git a/models/todo.go b/models/todo.go deleted file mode 100644 index f4abff3..0000000 --- a/models/todo.go +++ /dev/null @@ -1,16 +0,0 @@ -package models - -import "gorm.io/gorm" - -type Todo struct { - gorm.Model - Title string - Body string - IsDone bool - // add your field here... -} - -// Override the table name -func (Todo) TableName() string { - return "todos" -} diff --git a/models/user.go b/models/user.go deleted file mode 100644 index 9aba329..0000000 --- a/models/user.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2023 Harran Ali . All rights reserved. -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package models - -import "gorm.io/gorm" - -type User struct { - gorm.Model - Name string - Email string - Password string -} - -// Override the table name -func (User) TableName() string { - return "users" -} diff --git a/register-events.go b/register-events.go deleted file mode 100644 index edb4bc7..0000000 --- a/register-events.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2023 Harran Ali . All rights reserved. -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package main - -import ( - "git.smarteching.com/goffee/core" - "git.smarteching.com/goffee/todoapp/events" - "git.smarteching.com/goffee/todoapp/events/eventjobs" -) - -// Register events -func registerEvents() { - eventsManager := core.ResolveEventsManager() - //######################################## - //# events registration ##### - //######################################## - - // register your event here ... - eventsManager.Register(events.USER_REGISTERED, eventjobs.SendWelcomeEmail) - eventsManager.Register(events.USER_REGISTERED, eventjobs.TestEvent) - eventsManager.Register(events.USER_PASSWORD_RESET_REQUESTED, eventjobs.SendResetPasswordEmail) - eventsManager.Register(events.PASSWORD_CHANGED, eventjobs.SendPasswordChangedEmail) -} diff --git a/register-global-middlewares.go b/register-global-middlewares.go deleted file mode 100644 index f70aa11..0000000 --- a/register-global-middlewares.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2023 Harran Ali . All rights reserved. -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package main - -// Register middlewares globally -func registerGlobalMiddlewares() { - //######################################## - //# Global middlewares registration ##### - //######################################## - - // Register global middlewares here ... - // core.UseMiddleware(middlewares.AnotherExampleMiddleware) -} diff --git a/routes.go b/routes.go deleted file mode 100644 index 79619f5..0000000 --- a/routes.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2023 Harran Ali . All rights reserved. -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package main - -import ( - "git.smarteching.com/goffee/core" - "git.smarteching.com/goffee/todoapp/handlers" -) - -// Register the app routes -func registerRoutes() { - router := core.ResolveRouter() - //############################# - //# App Routes ##### - //############################# - - // Define your routes here... - router.Get("/", handlers.WelcomeHome) - router.Get("/todos", handlers.ListTodos) - router.Post("/todos", handlers.CreateTodos) - router.Get("/todos/:id", handlers.ShowTodo) - router.Delete("/todos/:id", handlers.DeleteTodo) - router.Put("/todos/:id", handlers.UpdateTodo) - // Uncomment the lines below to enable authentication - // router.Post("/signup", handlers.Signup) - // router.Post("/signin", handlers.Signin) - // router.Post("/signout", handlers.Signout) - // router.Post("/reset-password", handlers.ResetPasswordRequest) - // router.Post("/reset-password/code/:code", handlers.SetNewPassword) - // router.Get("/dashboard", handlers.WelcomeToDashboard, middlewares.AuthCheck) -} diff --git a/run-auto-migrations.go b/run-auto-migrations.go deleted file mode 100644 index cf301ec..0000000 --- a/run-auto-migrations.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2023 Harran Ali . All rights reserved. -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package main - -import ( - "git.smarteching.com/goffee/core" - "git.smarteching.com/goffee/todoapp/models" -) - -func RunAutoMigrations() { - db := core.ResolveGorm() - //############################## - //# Models auto migration ##### - //############################## - - // Add auto migrations for your models here... - db.AutoMigrate(&models.User{}) - db.AutoMigrate(&models.Todo{}) -} diff --git a/storage/.gitignore b/storage/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/storage/sqlite.db b/storage/sqlite.db deleted file mode 100644 index b10cc17..0000000 Binary files a/storage/sqlite.db and /dev/null differ diff --git a/utils/helpers.go b/utils/helpers.go deleted file mode 100644 index 7508e64..0000000 --- a/utils/helpers.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2023 Harran Ali . All rights reserved. -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package utils - -import ( - "crypto/md5" - "fmt" -) - -// generate a hashed string to be used as key for caching auth jwt token -func CreateAuthTokenHashedCacheKey(userID uint, userAgent string) string { - cacheKey := fmt.Sprintf("userid:_%v_useragent:_%v_jwt_token", userID, userAgent) - hashedCacheKey := fmt.Sprintf("%v", fmt.Sprintf("%x", md5.Sum([]byte(cacheKey)))) - - return hashedCacheKey -}