42 Commits
Author SHA1 Message Date
aditya.siregar 30091f3362 Update Env 2025-03-03 19:55:44 +07:00
aditya.siregar ed8c523b26 update docker 2025-03-03 19:39:11 +07:00
aditya.siregar e9b9a367a9 add docker file 2025-03-03 19:29:59 +07:00
aditya.siregar c9f1e33c24 Add Infra 2025-03-03 18:59:25 +07:00
ericprd c02d8cda69 fix: return error when there is no subscribe plan found 2025-03-02 10:07:42 +08:00
ericprd 55460653e3 fix: should be find one instead of find all 2025-03-02 09:48:40 +08:00
ericprd 915f12eaf7 feat: news router 2025-03-02 04:36:17 +08:00
ericprd f4ae93bc48 fix: condition query 2025-03-02 02:33:03 +08:00
ericprd eb1584f8c4 fix: unique entity 2025-03-01 21:27:28 +08:00
ericprd bdf6dd131e feat: category routes 2025-03-01 21:20:51 +08:00
ericprd acd80480dd feat: tag routes 2025-03-01 20:00:54 +08:00
ericprd 613379c8a5 fix: simplified gorm query 2025-03-01 19:00:12 +08:00
Ardeman c29df8a3d6 feat: add VSCode extensions recommendations 2025-02-28 22:12:35 +08:00
ericprd 2bef24fbb6 docs: fix tags 2025-02-28 22:03:47 +08:00
ericprd c23ee933c1 Merge branch 'main' of github.com:ardeman/project-legalgo-go 2025-02-28 12:19:18 +08:00
ericprd 6b858b99fb fix: get profile user/staff using token rather than id 2025-02-28 12:18:47 +08:00
Ardeman 4ec50cee8a feat: add check for .env file existence before loading environment variables 2025-02-27 22:32:38 +08:00
Ardeman 84239864c1 feat: add .env file existence check before loading environment variables 2025-02-27 22:30:00 +08:00
ericprd 5fb0764630 feat: get user/staff profile 2025-02-27 18:59:58 +08:00
Ardeman 290c0edff7 docs: clean up database migration instructions in README 2025-02-27 10:48:04 +08:00
ericprd ccd92c270a Merge branch 'main' of github.com:ardeman/project-legalgo-go 2025-02-27 10:33:09 +08:00
Ardeman d2a43a88c4 docs: add migration instructions to README for database updates 2025-02-27 10:28:26 +08:00
ericprd 33ba5fbbdc Merge branch 'main' of github.com:ardeman/project-legalgo-go 2025-02-27 10:28:15 +08:00
ericprd 7b367f655e fix: docs and required field 2025-02-27 10:27:57 +08:00
Ardeman 802692f6c1 docs: update installation instructions for Go and Make across platforms 2025-02-27 10:23:24 +08:00
Ardeman 14f38b792d chore: add markdownlint configuration and update README for installation instructions 2025-02-27 10:20:55 +08:00
Ardeman da5b65b582 refactor: update module name and adjust import paths to legalgo-BE-go 2025-02-27 07:25:25 +08:00
Ardeman 0a87f85358 chore: update dependencies and bump OpenAPI version to 3.1.0 2025-02-27 06:58:12 +08:00
ericprd 0317ba04d9 Merge branch 'main' of github.com:ardeman/project-legalgo-go 2025-02-27 01:16:48 +08:00
ericprd 775a9def75 refactor: project name and set default plan for new user 2025-02-27 01:15:47 +08:00
Ardeman 27ff3996ed fix: add APP_PORT and GRACEFULL_TIMEOUT to .env.example 2025-02-26 22:54:31 +08:00
ericprd 46472d01fe fix: app port and check subscribe_plan_id 2025-02-26 22:50:13 +08:00
ericprd 0100134527 fix: refactor layout init 2025-02-26 22:28:19 +08:00
ericprd ba075b67fd fix: change path get all subscribe plan 2025-02-25 14:23:59 +08:00
ericprd aee94a5c9c fix: improvement response api and docs 2025-02-25 11:25:36 +08:00
ericprd 81c7a51256 docs: fix path 2025-02-24 20:32:08 +08:00
ericprd 3466a4b4c5 docs: fix path 2025-02-24 20:30:10 +08:00
ericprd 037acbe128 fix: path url and add docs 2025-02-24 20:27:07 +08:00
ericprd d492f3ce44 feat: get all plans and improvement 2025-02-24 20:18:09 +08:00
ericprd 3b2321d5db fix: handle duplicate input 2025-02-24 19:47:40 +08:00
ericprd bd305f0edf docs: update setup database 2025-02-24 16:53:18 +08:00
ericprd cb3d06fa02 feat: CR login, register, subscribe 2025-02-24 16:48:20 +08:00
1904 changed files with 696768 additions and 167 deletions
+11
View File
@@ -3,3 +3,14 @@ DB_USER=
DB_PASSWORD=
DB_NAME=
DB_PORT=
APP_PORT=
GRACEFULL_TIMEOUT=
SALT_SECURITY=
REDIS_HOST=
REDIS_USERNAME=
REDIS_PORT=
REDIS_PASSWORD=
REDIS_TTL=
REDIS_DB=
+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
+119
View File
@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="ALL" />
</component>
<component name="ChangeListManager">
<list default="true" id="e5a7c631-b0eb-4bcf-9341-cd30afbc8d51" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/.idea/legalgo-BE-go.iml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/config/auth.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/config/configs.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/config/db.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/config/http.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/config/jwt.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/config/module.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/config/oss.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/config/server.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/development.yaml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/internal/accessor/oss/oss.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/internal/accessor/oss/upload.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/internal/api/http/oss/module.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/internal/api/http/oss/upload.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/internal/domain/oss/oss.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/internal/services/oss/impl.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/internal/services/oss/init.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/k8s/staging/deployment.yaml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/k8s/staging/ingress.yaml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/k8s/staging/namespace.yaml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/k8s/staging/service.yaml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/cmd/gorm/main.go" beforeDir="false" afterPath="$PROJECT_DIR$/cmd/gorm/main.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/cmd/legalgo/main.go" beforeDir="false" afterPath="$PROJECT_DIR$/cmd/legalgo/main.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/database/new_db.go" beforeDir="false" afterPath="$PROJECT_DIR$/database/new_db.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/go.mod" beforeDir="false" afterPath="$PROJECT_DIR$/go.mod" afterDir="false" />
<change beforePath="$PROJECT_DIR$/go.sum" beforeDir="false" afterPath="$PROJECT_DIR$/go.sum" afterDir="false" />
<change beforePath="$PROJECT_DIR$/internal/accessor/module.go" beforeDir="false" afterPath="$PROJECT_DIR$/internal/accessor/module.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/internal/api/http/router.go" beforeDir="false" afterPath="$PROJECT_DIR$/internal/api/http/router.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/internal/services/module.go" beforeDir="false" afterPath="$PROJECT_DIR$/internal/services/module.go" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Go File" />
</list>
</option>
</component>
<component name="GOROOT" url="file:///opt/homebrew/Cellar/go/1.24.0/libexec" />
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProjectId" id="2tlQuDgnVjD2XCHsYVtzhu4hYTb" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
"DefaultGoTemplateProperty": "Go File",
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.go.formatter.settings.were.checked": "true",
"RunOnceActivity.go.migrated.go.modules.settings": "true",
"RunOnceActivity.go.modules.go.list.on.any.changes.was.set": "true",
"RunOnceActivity.go.vendoring.notification.had.been.shown": "true",
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
"WebServerToolWindowFactoryState": "false",
"configurable..is.expanded": "false",
"configurable.GoLibrariesConfigurable.is.expanded": "true",
"go.import.settings.migrated": "true",
"go.sdk.automatically.set": "true",
"last_opened_file_path": "/Users/aditya.siregar/Personal/Altru/legalgo-news/legalgo-BE-go",
"node.js.detected.package.eslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"settings.editor.selected.configurable": "go.sdk"
}
}]]></component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$" />
<recent name="$PROJECT_DIR$/internal/api/http/oss" />
<recent name="$PROJECT_DIR$/internal/services" />
<recent name="$PROJECT_DIR$/internal/accessor" />
<recent name="$PROJECT_DIR$/config" />
</key>
<key name="MoveFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/internal/api/http/oss" />
</key>
</component>
<component name="RunManager">
<configuration name="go build legalgo-BE-go/cmd/legalgo" type="GoApplicationRunConfiguration" factoryName="Go Application" temporary="true" nameIsGenerated="true">
<module name="legalgo-BE-go" />
<working_directory value="$PROJECT_DIR$" />
<kind value="PACKAGE" />
<package value="legalgo-BE-go/cmd/legalgo" />
<directory value="$PROJECT_DIR$" />
<filePath value="$PROJECT_DIR$/cmd/legalgo/main.go" />
<method v="2" />
</configuration>
<recent_temporary>
<list>
<item itemvalue="Go Build.go build legalgo-BE-go/cmd/legalgo" />
</list>
</recent_temporary>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="VgoProject">
<settings-migrated>true</settings-migrated>
</component>
</project>
+8
View File
@@ -0,0 +1,8 @@
{
"default": true,
"MD013": false,
"MD026": false,
"MD033": false,
"MD040": false,
"MD041": false
}
+5
View File
@@ -0,0 +1,5 @@
{
"recommendations": [
"arjun.swagger-viewer"
]
}
+22
View File
@@ -0,0 +1,22 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceFolder}/cmd/legalgo/",
"dlvLoadConfig":{
"followPointers": true,
"maxVariableRecurse": 1,
"maxStringLen": 512, // 字符串最大长度
"maxArrayValues": 64,
"maxStructFields": -1
},
"dlvFlags": ["--check-go-version=false"],
"env": {
"TZ": ""
}
}]
}
+22
View File
@@ -0,0 +1,22 @@
FROM golang:1.24 AS build
WORKDIR /src
COPY . .
# RUN CGO_ENABLED=0 GOOS=linux go build -o /app cmd/klinik-core-service
RUN CGO_ENABLED=0 GOOS=linux go build -o /app cmd/legalgo/main.go
RUN ls -la /
FROM gcr.io/distroless/static
WORKDIR /
COPY --from=build /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=build /app /app
# RUN ls -la /
ENV TZ=Asia/Jakarta
ENTRYPOINT ["/app"]
+63 -6
View File
@@ -9,32 +9,41 @@ Before proceeding, make sure you have the following installed on your computer:
## Steps to Install Go 1.24.0
### For Windows:
### `go` For Windows:
1. Download the installer from [official Go website](https://golang.org/dl/).
2. Run the downloaded `.msi` file and follow the installation wizard.
3. During installation, you may be prompted to set the `GOPATH` and `GOROOT`. Choose the appropriate settings
based on your preference or keep the default values.
### For macOS:
### `go` For macOS:
1. Open Terminal.
2. Download the package using Homebrew (if not installed, visit [Homebrew website](https://brew.sh/) for
installation instructions):
```bash
brew install go@1.24
```
3. Link the installed version to your PATH:
```bash
brew link --overwrite --force go@1.24
```
### For Linux:
### `go` For Linux:
1. Open Terminal.
2. Download the appropriate tarball from [official Go website](https://golang.org/dl/).
3. Extract the downloaded archive:
```bash
tar -C /usr/local -xzf go1.24.linux-amd64.tar.gz
```
4. Add Go to your PATH by editing your shell configuration file (e.g., `.bashrc`, `.zshrc`):
```bash
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
source ~/.bashrc
@@ -43,25 +52,31 @@ installation instructions):
## Verify Installation
After installation, verify that Go 1.24.0 is installed correctly by running:
```bash
go version
```
You should see an output like `go version go1.24 darwin/amd64` (or similar, depending on your OS).
## Install Make (if not already installed)
### For Windows:
### `make` For Windows:
- Download and install [Make for Windows](http://gnuwin32.sourceforge.net/packages/make.htm).
- Add the installation directory to your PATH.
### For macOS:
### `make` For macOS:
1. Open Terminal.
2. Install Make using Homebrew:
```bash
brew install make
```
### For Linux:
### `make` For Linux:
Make is usually pre-installed on most Linux distributions. If it's not installed, you can install it using your
package manager (e.g., `sudo apt-get install make` for Ubuntu).
@@ -72,13 +87,53 @@ Open Terminal and navigate to the root directory of your Go project.
## Resolve Dependencies with `go mod tidy`
Run the following command to download and resolve all dependencies specified in your `go.mod` file:
```bash
go mod tidy
```
## Setup Database
In your Go application, you'll need to set the following environment variables to connect to your database:
```bash
DB_HOST: The hostname or IP address of your database server (e.g., localhost, 127.0.0.1, or the actual DB server URL).
DB_USER: The username for your database connection.
DB_PASSWORD: The password associated with the DB_USER.
DB_NAME: The name of the database you want to connect to.
DB_PORT: The port number your database server is running on (default MySQL port is 3306, default PostgreSQL port is 5432).
```
## Create `.env` File
It's best practice to keep sensitive information like database credentials in an environment file. Create or edit the .env file in the root directory of your project and add the following lines:
```bash
DB_HOST=localhost
DB_USER=your_db_user
DB_PASSWORD=your_db_password
DB_NAME=your_db_name
DB_PORT=3306 # or 5432, depending on your DB type
APP_PORT=3000 # example
GRACEFULL_TIMEOUT=10 #example
SALT_SECURITY=your_secret_security
Make sure to replace the values with your actual database details.
```
## Migrate the Database Using `make migrate`
Before running your application, let's setup your database first.
```bash
make migrate
```
## Build the Binary Using `make build`
Run the following command to build your project. The binary will be placed in the `bin` folder.
```bash
make build
```
@@ -86,6 +141,7 @@ make build
## Run the Program Using `make run`
Finally, you can run your program using:
```bash
make run
```
@@ -96,6 +152,7 @@ This command will compile and execute your Go application.
**Note:** Ensure that your `Makefile` is correctly set up to handle these commands. If not, you may need to create
or adjust it accordingly.
```
Please follow the above instructions to set up Go version 1.24.0, manage dependencies using `go mod tidy`, build a
+47 -1
View File
@@ -1,5 +1,51 @@
package main
func main() {
import (
"log"
"os"
"legalgo-BE-go/config"
"legalgo-BE-go/database"
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
"github.com/google/uuid"
"github.com/joho/godotenv"
)
func main() {
// Check if the .env file exists
if _, err := os.Stat(".env"); err == nil {
// Load environment variables from .env file if it exists
if err := godotenv.Load(); err != nil {
log.Println("Error loading .env file, continuing without it")
}
} else {
log.Println(".env file not found, skipping load")
}
config.InitEnv()
cfg := config.LoadConfig()
db, err := database.NewDB(cfg)
if err != nil {
log.Fatalf("failed to connect to database: %v", err)
}
// db.DropTables()
if err := db.Migrate(); err != nil {
log.Fatal("Migration failed: ", err)
}
var temp subscribeplandomain.SubscribePlan
if err := db.Where("code = ?", "basic").First(&temp).Error; err != nil {
log.Print("seeding basic subscribe plan")
db.Create(&subscribeplandomain.SubscribePlan{
ID: uuid.NewString(),
Code: "basic",
Name: "Basic",
})
}
log.Print("migrate success")
}
+19 -12
View File
@@ -4,32 +4,38 @@ import (
"context"
"fmt"
"log"
"os"
"legalgo-BE-go/config"
"legalgo-BE-go/database"
repository "legalgo-BE-go/internal/accessor"
internalhttp "legalgo-BE-go/internal/api/http"
pkgconfig "legalgo-BE-go/internal/config"
"legalgo-BE-go/internal/services"
"github.com/ardeman/project-legalgo-go/database"
repository "github.com/ardeman/project-legalgo-go/internal/accessor"
internalhttp "github.com/ardeman/project-legalgo-go/internal/api/http"
pkgconfig "github.com/ardeman/project-legalgo-go/internal/config"
"github.com/ardeman/project-legalgo-go/internal/services"
"github.com/go-chi/chi/v5"
"github.com/joho/godotenv"
"go.uber.org/fx"
)
func init() {
// Check if the .env file exists
if _, err := os.Stat(".env"); err == nil {
// Load environment variables from .env file if it exists
if err := godotenv.Load(); err != nil {
log.Fatal("cannot load environment file")
log.Println("Error loading .env file, continuing without it")
}
} else {
log.Println(".env file not found, skipping load")
}
config.InitEnv()
}
func run(lc fx.Lifecycle, db *database.DB, apiRouter chi.Router) {
lc.Append(fx.Hook{
OnStart: func(ctx context.Context) error {
fmt.Println("Application has started...")
// Run migration
if err := db.Migrate(); err != nil {
log.Fatal("Migration failed: ", err)
}
pkgconfig.Router(apiRouter)
return nil
@@ -43,10 +49,11 @@ func run(lc fx.Lifecycle, db *database.DB, apiRouter chi.Router) {
func main() {
app := fx.New(
config.Module,
database.Module,
repository.Module,
internalhttp.Module,
services.Module,
internalhttp.Module,
fx.Invoke(run),
)
+17
View File
@@ -0,0 +1,17 @@
package config
import "time"
type AuthConfig struct {
jwtTokenExpiresTTL int
jwtTokenSecret string
}
func (c *AuthConfig) AccessTokenSecret() string {
return c.jwtTokenSecret
}
func (c *AuthConfig) AccessTokenExpiresDate() time.Time {
duration := time.Duration(c.jwtTokenExpiresTTL)
return time.Now().UTC().Add(time.Minute * duration)
}
+27
View File
@@ -0,0 +1,27 @@
package config
var (
APP_PORT int
GRACEFULL_TIMEOUT int
// DB
DB_HOST,
DB_USER,
DB_PASSWORD,
DB_NAME,
DB_PORT,
SALT_SECURITY string
)
func InitEnv() {
DB_HOST = GetOrDefault("DB_HOST", "localhost")
DB_USER = GetOrDefault("DB_USER", "")
DB_PASSWORD = GetOrDefault("DB_PASSWORD", "")
DB_NAME = GetOrDefault("DB_NAME", "")
DB_PORT = GetOrDefault("DB_PORT", "")
SALT_SECURITY = GetOrDefault("SALT_SECURITY", "legalgo")
APP_PORT = GetOrDefault("APP_PORT", 3000)
GRACEFULL_TIMEOUT = GetOrDefault("GRACEFULL_TIMEOUT", 10)
}
+68
View File
@@ -0,0 +1,68 @@
package config
import (
"fmt"
"os"
"sync"
"github.com/spf13/viper"
_ "gopkg.in/yaml.v3"
)
const (
YAML_PATH = "env/%s"
ENV_MODE = "ENV_MODE"
DEFAULT_ENV_MODE = "development"
)
var (
validEnvMode = map[string]struct{}{
"local": {},
"development": {},
"production": {},
}
)
type Config struct {
Server Server `mapstructure:"server"`
Database Database `mapstructure:"postgresql"`
Jwt Jwt `mapstructure:"jwt"`
OSSConfig OSSConfig `mapstructure:"oss"`
}
var (
config *Config
configOnce sync.Once
)
func LoadConfig() *Config {
envMode := os.Getenv(ENV_MODE)
if _, ok := validEnvMode[envMode]; !ok {
envMode = DEFAULT_ENV_MODE // default env mode
}
cfgFilePath := fmt.Sprintf(YAML_PATH, envMode)
configOnce.Do(func() {
v := viper.New()
v.SetConfigType("yaml")
v.AddConfigPath(".")
v.SetConfigName(cfgFilePath)
if err := v.ReadInConfig(); err != nil {
panic(fmt.Errorf("failed to read config file: %s", err))
}
config = &Config{}
if err := v.Unmarshal(config); err != nil {
panic(fmt.Errorf("failed to unmarshal config: %s", err))
}
})
return config
}
func (c *Config) Auth() *AuthConfig {
return &AuthConfig{
jwtTokenSecret: c.Jwt.Token.Secret,
jwtTokenExpiresTTL: c.Jwt.Token.ExpiresTTL,
}
}
+28
View File
@@ -0,0 +1,28 @@
package config
import (
"fmt"
"time"
)
type Database struct {
Host string `mapstructure:"host"`
Port string `mapstructure:"port"`
DB string `mapstructure:"db"`
Driver string `mapstructure:"driver"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
SslMode string `mapstructure:"ssl-mode"`
Debug bool `mapstructure:"debug"`
MaxIdleConnectionsInSecond int `mapstructure:"max-idle-connections-in-second"`
MaxOpenConnectionsInSecond int `mapstructure:"max-open-connections-in-second"`
ConnectionMaxLifetimeInSecond int64 `mapstructure:"connection-max-life-time-in-second"`
}
func (c Database) DSN() string {
return fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s sslmode=%s", c.Host, c.Port, c.DB, c.Username, c.Password, c.SslMode)
}
func (c Database) ConnectionMaxLifetime() time.Duration {
return time.Duration(c.ConnectionMaxLifetimeInSecond) * time.Second
}
+34
View File
@@ -0,0 +1,34 @@
package config
import (
"os"
"reflect"
"strconv"
)
func GetOrDefault[T any](key string, defaultValue T) T {
value, exist := os.LookupEnv(key)
if !exist {
return defaultValue
}
var valueInstance T
kind := reflect.ValueOf(valueInstance).Kind()
switch kind {
case reflect.String:
return any(value).(T)
case reflect.Int:
if val, err := strconv.Atoi(value); err == nil {
return any(val).(T)
}
return any(defaultValue).(T)
case reflect.Bool:
if val, err := strconv.ParseBool(value); err == nil {
return any(val).(T)
}
return any(defaultValue).(T)
default:
return any(defaultValue).(T)
}
}
+17
View File
@@ -0,0 +1,17 @@
package config
import "fmt"
type httpConfig struct {
host string
port int
detailedError bool
}
func (c *httpConfig) Address() string {
return fmt.Sprintf("%s:%d", c.host, c.port)
}
func (c *httpConfig) DetailedError() bool {
return c.detailedError
}
+10
View File
@@ -0,0 +1,10 @@
package config
type Jwt struct {
Token Token `mapstructure:"token"`
}
type Token struct {
ExpiresTTL int `mapstructure:"expires-ttl"`
Secret string `mapstructure:"secret"`
}
+11
View File
@@ -0,0 +1,11 @@
package config
import (
"go.uber.org/fx"
)
var Module = fx.Module("config",
fx.Provide(
LoadConfig,
),
)
+44
View File
@@ -0,0 +1,44 @@
package config
type OSSConfig struct {
AccessKeyID string `mapstructure:"access_key_id"`
AccessKeySecret string `mapstructure:"access_key_secret"`
Endpoint string `mapstructure:"endpoint"`
BucketName string `mapstructure:"bucket_name"`
PhotoFolder string `mapstructure:"photo_folder"`
LogLevel string `mapstructure:"log_level"`
HostURL string `mapstructure:"host_url"`
PublicURL string `mapstructure:"public_url"`
}
func (c OSSConfig) GetAccessKeyID() string {
return c.AccessKeyID
}
func (c OSSConfig) GetAccessKeySecret() string {
return c.AccessKeySecret
}
func (c OSSConfig) GetEndpoint() string {
return c.Endpoint
}
func (c OSSConfig) GetBucketName() string {
return c.BucketName
}
func (c OSSConfig) GetLogLevel() string {
return c.LogLevel
}
func (c OSSConfig) GetHostURL() string {
return c.HostURL
}
func (c OSSConfig) GetPublicURL() string {
return c.PublicURL
}
func (c OSSConfig) GetPhotoFolder() string {
return c.PhotoFolder
}
+7
View File
@@ -0,0 +1,7 @@
package config
type Server struct {
Port string `mapstructure:"port"`
BaseUrl string `mapstructure:"common-url"`
LocalUrl string `mapstructure:"local-url"`
}
+21
View File
@@ -0,0 +1,21 @@
package database
import (
"time"
)
type Category struct {
ID string `gorm:"primaryKey" json:"id"`
Code string `gorm:"not null;unique" json:"code"`
Name string `gorm:"not null" json:"name"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}
type CategoryModel struct {
ID string `gorm:"primaryKey" json:"id"`
Name string `gorm:"not null;unique" json:"name"`
Code string `gorm:"not null" json:"code"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}
+34 -12
View File
@@ -2,9 +2,9 @@ package database
import (
"fmt"
"os"
staffmodel "github.com/ardeman/project-legalgo-go/database/staff"
"legalgo-BE-go/config"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
@@ -13,17 +13,16 @@ type DB struct {
*gorm.DB
}
func NewDB() (*DB, error) {
var (
host = os.Getenv("DB_HOST")
user = os.Getenv("DB_USER")
password = os.Getenv("DB_PASSWORD")
dbName = os.Getenv("DB_NAME")
dbPort = os.Getenv("DB_PORT")
func NewDB(cfg *config.Config) (*DB, error) {
dsn := fmt.Sprintf(
"host=%s user=%s password=%s dbname=%s port=%v sslmode=disable",
cfg.Database.Host,
cfg.Database.Username,
cfg.Database.Password,
cfg.Database.DB,
cfg.Database.Port,
)
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%v sslmode=disable", host, user, password, dbName, dbPort)
if dsn == "" {
return nil, fmt.Errorf("DATABASE_URL environment is not set")
}
@@ -37,7 +36,30 @@ func NewDB() (*DB, error) {
return &DB{db}, nil
}
func (db *DB) DropTables() error {
// Auto Migrate the User model
return db.Migrator().DropTable(
// &Staff{},
// &SubscribePlan{},
// &Subscribe{},
// &User{},
&Tag{},
&Category{},
&News{},
)
}
func (db *DB) Migrate() error {
// Auto Migrate the User model
return db.AutoMigrate(&staffmodel.Staff{})
return db.AutoMigrate(
&Staff{},
&SubscribePlan{},
&Subscribe{},
&User{},
// &Tag{},
// &Category{},
// &News{},
&NewsModel{},
&TagModel{},
&CategoryModel{},
)
}
+35
View File
@@ -0,0 +1,35 @@
package database
import (
"time"
)
type News struct {
ID string `gorm:"primaryKey" json:"id"`
Title string `gorm:"default:null" json:"title"`
Tags []Tag `gorm:"many2many:news_tags" json:"tags"`
Categories []Category `gorm:"many2many:news_categories" json:"categories"`
Content string `gorm:"default:null" json:"content"`
LiveAt time.Time `gorm:"not null" json:"live_at"`
AuthorID string `gorm:"not null" json:"author_id"`
IsPremium bool `gorm:"default:false" json:"is_premium"`
Slug string `gorm:"default:null" json:"slug"`
FeaturedImage string `gorm:"default:null" json:"featured_image"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}
type NewsModel struct {
ID string `gorm:"primaryKey" json:"id"`
Title string `json:"title"`
Content string `json:"content"`
Categories []CategoryModel `gorm:"many2many:news_categories" json:"categories"`
Tags []TagModel `gorm:"many2many:news_tags" json:"tags"`
IsPremium bool `gorm:"default:false" json:"is_premium"`
Slug string `gorm:"default:null" json:"slug"`
FeaturedImage string `gorm:"default:null" json:"featured_image"`
AuthorID string `gorm:"not null" json:"author_id"`
LiveAt time.Time `gorm:"not null" json:"live_at"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}
-11
View File
@@ -1,11 +0,0 @@
package staffmodel
import (
"github.com/google/uuid"
)
type Staff struct {
ID uuid.UUID `gorm:"type:uuid;primaryKey" json:"id"`
Email string `gorm:"unique,not null" json:"email"`
Password string `gorm:"not null" json:"password"`
}
+14
View File
@@ -0,0 +1,14 @@
package database
import (
"time"
)
type Staff struct {
ID string `gorm:"primaryKey" json:"id"`
Username string `gorm:"default:null;unique" json:"username"`
Email string `gorm:"unique;not null" json:"email"`
Password string `gorm:"not null" json:"password"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}
+26
View File
@@ -0,0 +1,26 @@
package database
import (
"time"
)
type Subscribe struct {
ID string `gorm:"primaryKey" json:"id"`
SubscribePlanID string `gorm:"not null" json:"subscribe_plan_id"`
StartDate time.Time `gorm:"default:CURRENT_TIMESTAMP"`
EndDate time.Time `gorm:"default:null"`
Status string `gorm:"default:'inactive'"`
AutoRenew bool `gorm:"default:true"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP"`
SubscribePlan SubscribePlan `gorm:"foreignKey:SubscribePlanID;constraint:OnDelete:CASCADE"`
}
type SubscribePlan struct {
ID string `gorm:"primaryKey" json:"id"`
Code string `gorm:"not null;unique" json:"code"`
Name string `gorm:"not null" json:"name"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP"`
}
+21
View File
@@ -0,0 +1,21 @@
package database
import (
"time"
)
type Tag struct {
ID string `gorm:"primaryKey" json:"id"`
Code string `gorm:"not null;unique" json:"code"`
Name string `gorm:"not null" json:"name"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}
type TagModel struct {
ID string `gorm:"primaryKey" json:"id"`
Name string `gorm:"not null;unique" json:"name"`
Code string `gorm:"not null" json:"code"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}
+17
View File
@@ -0,0 +1,17 @@
package database
import (
"time"
)
type User struct {
ID string `gorm:"primaryKey;not null" json:"id"`
SubscribeID string `gorm:"not null" json:"subscribe_id"`
Email string `gorm:"unique;not null" json:"email"`
Password string `gorm:"not null" json:"password"`
Phone string `gorm:"default:not null;unique" json:"phone"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
Subscribe Subscribe `gorm:"foreignKey:SubscribeID;constraint:OnDelete:CASCADE"`
}
+31
View File
@@ -0,0 +1,31 @@
server:
base-url: https://api.legalgo.id/core
local-url: http://localhost:3300
port: 3300
jwt:
token:
expires-ttl: 1440
secret: "5Lm25V3Qd7aut8dr4QUxm5PZUrSFs"
postgresql:
host: 62.72.45.250
port: 20826
driver: postgres
db: legalgonews-dev
username: legalgo_admin
password: 'K4K!2Kg7c@KW6H&4A2aBy2dFCRY3Sh'
ssl-mode: disable
max-idle-connections-in-second: 600
max-open-connections-in-second: 600
connection-max-life-time-in-second: 600
debug: false
oss:
access_key_id: cf9a475e18bc7626cbdbf09709d82a64
access_key_secret: 91f3321294d3e23035427a0ecb893ada
endpoint: sin1.contabostorage.com
bucket_name: legalgonews-dev
log_level: Error
host_url: https://sin1.contabostorage.com
public_url: https://sin1.contabostorage.com/fda98c2228f246f29a7e466b86b3b9e7
+27 -11
View File
@@ -1,40 +1,56 @@
module github.com/ardeman/project-legalgo-go
module legalgo-BE-go
go 1.24.0
go 1.24
require (
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/joho/godotenv v1.5.1
github.com/spf13/viper v1.19.0
go.uber.org/fx v1.23.0
golang.org/x/crypto v0.34.0
gopkg.in/yaml.v3 v3.0.1
gorm.io/driver/postgres v1.4.7
)
require (
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.7.2 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/jackc/pgx/v5 v5.2.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
golang.org/x/crypto v0.34.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/net v0.34.0 // indirect
golang.org/x/text v0.22.0 // indirect
gorm.io/driver/postgres v1.5.11 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)
require (
github.com/aws/aws-sdk-go v1.50.0
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/go-chi/chi v1.5.5
github.com/go-chi/chi/v5 v5.2.1 // indirect
github.com/go-chi/chi/v5 v5.2.1
github.com/go-chi/cors v1.2.1
github.com/go-playground/validator/v10 v10.25.0
github.com/google/uuid v1.6.0
github.com/redis/go-redis/v9 v9.7.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/redis/go-redis/v9 v9.7.1
github.com/sirupsen/logrus v1.9.3
go.uber.org/dig v1.18.0 // indirect
go.uber.org/multierr v1.10.0 // indirect
go.uber.org/zap v1.26.0 // indirect
+123 -16
View File
@@ -1,18 +1,30 @@
github.com/aws/aws-sdk-go v1.50.0 h1:HBtrLeO+QyDKnc3t1+5DR1RxodOHCGr8ZcrHudpv7jI=
github.com/aws/aws-sdk-go v1.50.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/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/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
github.com/go-chi/chi v1.5.5 h1:vOB/HbEMt9QqBqErz07QehcOKHaWFtuj87tTDVz2qXE=
github.com/go-chi/chi v1.5.5/go.mod h1:C9JqLr3tIYjDOZpzn+BCuxY8z8vmca43EeMgyZt7irw=
github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
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=
@@ -21,35 +33,89 @@ github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0
github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
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/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
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-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.7.2 h1:mLoDLV6sonKlvjIEsV56SkWNCnuNv531l94GaIzO+XI=
github.com/jackc/pgx/v5 v5.7.2/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jackc/pgx/v5 v5.2.0 h1:NdPpngX0Y6z6XDFKqmFQaE+bCtkqzvQIOt1wvBlAqs8=
github.com/jackc/pgx/v5 v5.2.0/go.mod h1:Ptn7zmohNsWEsdxRawMzk3gaKma2obW+NWTnKa0S4nk=
github.com/jackc/puddle/v2 v2.1.2/go.mod h1:2lpufsF5mRHO6SuZkm0fNYxM6SWHfvyFj62KwNzgels=
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.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/redis/go-redis/v9 v9.7.1 h1:4LhKRCIduqXqtvCUlaq9c8bdHOkICjDMrr1+Zb3osAc=
github.com/redis/go-redis/v9 v9.7.1/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
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/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
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.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/dig v1.18.0 h1:imUL1UiY0Mg4bqbFfsRQO5G4CGRBec/ZujWTvSVp3pw=
go.uber.org/dig v1.18.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
go.uber.org/fx v1.23.0 h1:lIr/gYWQGfTwGcSXWXu4vP5Ws6iqnNEIY+F/aFzCKTg=
@@ -60,26 +126,67 @@ go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
golang.org/x/crypto v0.34.0 h1:+/C6tk6rf/+t5DhUketUbD1aNGqiSX3j15Z6xuIDlBA=
golang.org/x/crypto v0.34.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314=
gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
gorm.io/driver/postgres v1.4.7 h1:J06jXZCNq7Pdf7LIPn8tZn9LsWjd81BRSKveKNr0ZfA=
gorm.io/driver/postgres v1.4.7/go.mod h1:UJChCNLFKeBqQRE+HrkFUbKbq9idPXmTOk2u4Wok8S4=
gorm.io/gorm v1.24.2/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
+21
View File
@@ -0,0 +1,21 @@
package categoryrepository
import (
categorydomain "legalgo-BE-go/internal/domain/category"
"github.com/google/uuid"
)
func (a *accessor) Create(spec categorydomain.CategoryReq) error {
data := categorydomain.Category{
ID: uuid.NewString(),
Name: spec.Name,
Code: spec.Code,
}
if err := a.DB.Create(&data).Error; err != nil {
return err
}
return nil
}
@@ -0,0 +1,22 @@
package categoryrepository
import (
"legalgo-BE-go/database"
categorydomain "legalgo-BE-go/internal/domain/category"
"github.com/google/uuid"
)
func (a *accessor) CreateModel(spec categorydomain.CategoryReq) error {
data := database.CategoryModel{
ID: uuid.NewString(),
Name: spec.Name,
Code: spec.Code,
}
if err := a.DB.Create(&data).Error; err != nil {
return err
}
return nil
}
+13
View File
@@ -0,0 +1,13 @@
package categoryrepository
import categorydomain "legalgo-BE-go/internal/domain/category"
func (a *accessor) GetAll() ([]categorydomain.Category, error) {
var categories []categorydomain.Category
if err := a.DB.Find(&categories).Error; err != nil {
return nil, err
}
return categories, nil
}
@@ -0,0 +1,15 @@
package categoryrepository
import (
"legalgo-BE-go/database"
)
func (a *accessor) GetAllModel() ([]database.CategoryModel, error) {
var categories []database.CategoryModel
if err := a.DB.Find(&categories).Error; err != nil {
return nil, err
}
return categories, nil
}
+15
View File
@@ -0,0 +1,15 @@
package categoryrepository
import (
categorydomain "legalgo-BE-go/internal/domain/category"
)
func (a *accessor) GetByIDs(ids []string) ([]categorydomain.Category, error) {
var categories []categorydomain.Category
if err := a.DB.Find(&categories, "id IN ?", ids).Error; err != nil {
return nil, err
}
return categories, nil
}
@@ -0,0 +1,15 @@
package categoryrepository
import (
"legalgo-BE-go/database"
)
func (a *accessor) GetBulks(ids []string) ([]database.CategoryModel, error) {
var categories []database.CategoryModel
if err := a.DB.Find(&categories, "id IN ?", ids).Error; err != nil {
return nil, err
}
return categories, nil
}
+27
View File
@@ -0,0 +1,27 @@
package categoryrepository
import (
"legalgo-BE-go/database"
categorydomain "legalgo-BE-go/internal/domain/category"
)
type accessor struct {
DB *database.DB
}
type Category interface {
Create(categorydomain.CategoryReq) error
CreateModel(categorydomain.CategoryReq) error
GetAll() ([]categorydomain.Category, error)
GetAllModel() ([]database.CategoryModel, error)
GetByIDs([]string) ([]categorydomain.Category, error)
GetBulks([]string) ([]database.CategoryModel, error)
}
func New(
db *database.DB,
) Category {
return &accessor{db}
}
+18 -1
View File
@@ -1,10 +1,27 @@
package repository
import (
staffrepository "github.com/ardeman/project-legalgo-go/internal/accessor/staff"
categoryrepository "legalgo-BE-go/internal/accessor/category"
newsrepository "legalgo-BE-go/internal/accessor/news"
"legalgo-BE-go/internal/accessor/oss"
redisaccessor "legalgo-BE-go/internal/accessor/redis"
staffrepository "legalgo-BE-go/internal/accessor/staff"
subscriberepository "legalgo-BE-go/internal/accessor/subscribe"
subscribeplanrepository "legalgo-BE-go/internal/accessor/subscribeplan"
tagrepository "legalgo-BE-go/internal/accessor/tag"
userrepository "legalgo-BE-go/internal/accessor/user_repository"
"go.uber.org/fx"
)
var Module = fx.Module("repository", fx.Provide(
staffrepository.New,
userrepository.New,
redisaccessor.New,
subscribeplanrepository.New,
subscriberepository.New,
tagrepository.New,
categoryrepository.New,
newsrepository.New,
oss.New,
))
+13
View File
@@ -0,0 +1,13 @@
package newsrepository
import (
"fmt"
newsdomain "legalgo-BE-go/internal/domain/news"
)
func (a *accessor) Create(spec *newsdomain.News) error {
if err := a.db.Create(&spec).Error; err != nil {
return fmt.Errorf("failed to create news: %w", err)
}
return nil
}
+13
View File
@@ -0,0 +1,13 @@
package newsrepository
import (
"fmt"
"legalgo-BE-go/database"
)
func (a *accessor) CreateModel(spec database.NewsModel) error {
if err := a.db.Create(&spec).Error; err != nil {
return fmt.Errorf("failed to create news: %w", err)
}
return nil
}
+13
View File
@@ -0,0 +1,13 @@
package newsrepository
import newsdomain "legalgo-BE-go/internal/domain/news"
func (a *accessor) GetAll() ([]newsdomain.News, error) {
var news []newsdomain.News
if err := a.db.Preload("Tags").Preload("Categories").Find(&news).Error; err != nil {
return nil, err
}
return news, nil
}
+13
View File
@@ -0,0 +1,13 @@
package newsrepository
import "legalgo-BE-go/database"
func (a *accessor) GetAllModel() ([]database.NewsModel, error) {
var news []database.NewsModel
if err := a.db.Preload("Tags").Preload("Categories").Find(&news).Error; err != nil {
return nil, err
}
return news, nil
}
+21
View File
@@ -0,0 +1,21 @@
package newsrepository
import (
"legalgo-BE-go/database"
newsdomain "legalgo-BE-go/internal/domain/news"
)
type accessor struct {
db *database.DB
}
type News interface {
GetAll() ([]newsdomain.News, error)
GetAllModel() ([]database.NewsModel, error)
Create(*newsdomain.News) error
CreateModel(database.NewsModel) error
}
func New(db *database.DB) News {
return &accessor{db}
}
+70
View File
@@ -0,0 +1,70 @@
package oss
import (
"bytes"
"context"
"fmt"
"legalgo-BE-go/config"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
)
type OSSConfig interface {
GetAccessKeyID() string
GetAccessKeySecret() string
GetEndpoint() string
GetBucketName() string
GetHostURL() string
GetPublicURL() string
}
const _awsRegion = "us-east-1"
const _s3ACL = "public-read"
type OssRepositoryImpl struct {
s3 *s3.S3
cfg OSSConfig
}
func New(cfg *config.Config) OSSRepository {
ossCfg := cfg.OSSConfig
sess, err := session.NewSession(&aws.Config{
S3ForcePathStyle: aws.Bool(true),
Endpoint: aws.String(ossCfg.GetEndpoint()),
Region: aws.String(_awsRegion),
Credentials: credentials.NewStaticCredentials(ossCfg.GetAccessKeyID(), ossCfg.GetAccessKeySecret(), ""),
})
if err != nil {
fmt.Println("Failed to create AWS session:", err)
return nil
}
return &OssRepositoryImpl{
s3: s3.New(sess),
cfg: ossCfg,
}
}
func (r *OssRepositoryImpl) UploadFile(ctx context.Context, fileName string, fileContent []byte) (fileUrl string, err error) {
reader := bytes.NewReader(fileContent)
_, err = r.s3.PutObject(&s3.PutObjectInput{
Bucket: aws.String(r.cfg.GetBucketName()),
Key: aws.String(fileName),
Body: reader,
ACL: aws.String(_s3ACL),
})
return r.GetPublicURL(fileName), err
}
func (r *OssRepositoryImpl) GetPublicURL(fileName string) string {
if fileName == "" {
return ""
}
return fmt.Sprintf("%s:%s%s", r.cfg.GetPublicURL(), r.cfg.GetBucketName(), fileName)
}
+10
View File
@@ -0,0 +1,10 @@
package oss
import (
"context"
)
type OSSRepository interface {
UploadFile(ctx context.Context, fileName string, fileContent []byte) (fileUrl string, err error)
GetPublicURL(fileName string) string
}
+32
View File
@@ -0,0 +1,32 @@
package redisaccessor
import (
"fmt"
"os"
"github.com/redis/go-redis/v9"
)
var redisClient *redis.Client
func Get() *redis.Client {
return redisClient
}
func New() *redis.Client {
var (
username = os.Getenv("REDIS_USERNAME")
addr = fmt.Sprintf("%s:%s", os.Getenv("REDIS_HOST"), os.Getenv("REDIS_PORT"))
password = os.Getenv("REDIS_PASSWORD")
db = 2 // TODO: change later
)
redisClient = redis.NewClient(&redis.Options{
Username: username,
Addr: addr,
Password: password,
DB: db,
})
return redisClient
}
+11
View File
@@ -0,0 +1,11 @@
package staffrepository
import authdomain "legalgo-BE-go/internal/domain/auth"
func (ur *StaffRepository) Create(spec *authdomain.Staff) (*authdomain.Staff, error) {
if err := ur.DB.Create(&spec).Error; err != nil {
return nil, err
}
return spec, nil
}
+26
View File
@@ -0,0 +1,26 @@
package staffrepository
import (
"errors"
authdomain "legalgo-BE-go/internal/domain/auth"
"gorm.io/gorm"
)
func (sr *StaffRepository) GetStaffByEmail(email string) (*authdomain.Staff, error) {
var staff authdomain.Staff
if email == "" {
return nil, errors.New("email is required")
}
if err := sr.DB.First(&staff, "email = ?", email).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("staff not found")
}
return nil, err
}
return &staff, nil
}
+25
View File
@@ -0,0 +1,25 @@
package staffrepository
import (
"errors"
authdomain "legalgo-BE-go/internal/domain/auth"
"gorm.io/gorm"
)
func (sr *StaffRepository) GetStaffByID(ID string) (*authdomain.Staff, error) {
var staff authdomain.Staff
if ID == "" {
return nil, errors.New("id is required")
}
if err := sr.DB.First(&staff, "id = ? ", ID).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("staff not found")
}
return nil, err
}
return &staff, nil
}
-25
View File
@@ -1,25 +0,0 @@
package staffrepository
import (
"errors"
staffmodel "github.com/ardeman/project-legalgo-go/database/staff"
"gorm.io/gorm"
)
func (sr *StaffRepository) GetStaff(email string) (*staffmodel.Staff, error) {
var staff staffmodel.Staff
if email == "" {
return nil, errors.New("email is empty")
}
if err := sr.DB.Where("email = ?", email).First(&staff).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("staff not found")
}
return nil, err
}
return &staff, nil
}
+8 -5
View File
@@ -1,18 +1,21 @@
package staffrepository
import (
"github.com/ardeman/project-legalgo-go/database"
staffmodel "github.com/ardeman/project-legalgo-go/database/staff"
"legalgo-BE-go/database"
authdomain "legalgo-BE-go/internal/domain/auth"
)
type StaffRepository struct {
DB *database.DB
}
type StaffInterface interface {
GetStaff(string) (*staffmodel.Staff, error)
type StaffIntf interface {
GetStaffByEmail(string) (*authdomain.Staff, error)
GetStaffByID(string) (*authdomain.Staff, error)
Create(*authdomain.Staff) (*authdomain.Staff, error)
Update(authdomain.Staff) error
}
func New(db *database.DB) StaffInterface {
func New(db *database.DB) StaffIntf {
return &StaffRepository{db}
}
+19
View File
@@ -0,0 +1,19 @@
package staffrepository
import (
authdomain "legalgo-BE-go/internal/domain/auth"
"legalgo-BE-go/internal/utilities/utils"
)
func (ur *StaffRepository) Update(spec authdomain.Staff) error {
val, err := utils.StructToMap(spec)
if err != nil {
return err
}
if err := ur.DB.Model(&authdomain.Staff{}).Where("id = ?", spec.ID).Updates(val).Error; err != nil {
return err
}
return nil
}
+20
View File
@@ -0,0 +1,20 @@
package subscriberepository
import (
subscribedomain "legalgo-BE-go/internal/domain/subscribe"
"github.com/google/uuid"
)
func (s *SubsAccs) Create(subsPlanId string) (string, error) {
spec := &subscribedomain.Subscribe{
ID: uuid.NewString(),
SubscribePlanID: subsPlanId,
}
if err := s.DB.Create(&spec).Error; err != nil {
return "", err
}
return spec.ID, nil
}
+15
View File
@@ -0,0 +1,15 @@
package subscriberepository
import "legalgo-BE-go/database"
type SubsAccs struct {
DB *database.DB
}
type SubsIntf interface {
Create(string) (string, error)
}
func New(db *database.DB) SubsIntf {
return &SubsAccs{db}
}
+21
View File
@@ -0,0 +1,21 @@
package subscribeplanrepository
import (
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
"github.com/google/uuid"
)
func (s *SubsPlan) Create(spec subscribeplandomain.SubscribePlanReq) error {
data := &subscribeplandomain.SubscribePlan{
ID: uuid.NewString(),
Code: spec.Code,
Name: spec.Name,
}
if err := s.DB.Create(&data).Error; err != nil {
return err
}
return nil
}
@@ -0,0 +1,15 @@
package subscribeplanrepository
import (
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
)
func (s *SubsPlan) GetAll() ([]subscribeplandomain.SubscribePlan, error) {
var subscribePlans []subscribeplandomain.SubscribePlan
if err := s.DB.Find(&subscribePlans).Error; err != nil {
return nil, err
}
return subscribePlans, nil
}
@@ -0,0 +1,21 @@
package subscribeplanrepository
import (
"errors"
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
"gorm.io/gorm"
)
func (s *SubsPlan) GetByID(id string) (subscribeplandomain.SubscribePlan, error) {
var subscribePlan subscribeplandomain.SubscribePlan
if err := s.DB.First(&subscribePlan, "id = ? ", id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return subscribePlan, errors.New("subscribe plan not found")
}
return subscribePlan, err
}
return subscribePlan, nil
}
@@ -0,0 +1,21 @@
package subscribeplanrepository
import (
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
"github.com/google/uuid"
)
func (s *SubsPlan) GetDefault() (subscribeplandomain.SubscribePlan, error) {
var subscribePlan subscribeplandomain.SubscribePlan
if err := s.DB.First(&subscribePlan, "code = ?", "basic").Error; err != nil {
s.DB.Create(&subscribeplandomain.SubscribePlan{
ID: uuid.NewString(),
Code: "basic",
Name: "Basic",
})
}
return subscribePlan, nil
}
+23
View File
@@ -0,0 +1,23 @@
package subscribeplanrepository
import (
"legalgo-BE-go/database"
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
)
type SubsPlan struct {
DB *database.DB
}
type SubsPlanIntf interface {
Create(subscribeplandomain.SubscribePlanReq) error
GetAll() ([]subscribeplandomain.SubscribePlan, error)
GetByID(string) (subscribeplandomain.SubscribePlan, error)
GetDefault() (subscribeplandomain.SubscribePlan, error)
}
func New(
db *database.DB,
) SubsPlanIntf {
return &SubsPlan{db}
}
+21
View File
@@ -0,0 +1,21 @@
package tagrepository
import (
tagdomain "legalgo-BE-go/internal/domain/tag"
"github.com/google/uuid"
)
func (acc *accessor) Create(spec tagdomain.TagReq) error {
data := &tagdomain.Tag{
ID: uuid.NewString(),
Code: spec.Code,
Name: spec.Name,
}
if err := acc.DB.Create(&data).Error; err != nil {
return err
}
return nil
}
+22
View File
@@ -0,0 +1,22 @@
package tagrepository
import (
"legalgo-BE-go/database"
tagdomain "legalgo-BE-go/internal/domain/tag"
"github.com/google/uuid"
)
func (acc *accessor) CreateModel(spec tagdomain.TagReq) error {
data := &database.TagModel{
ID: uuid.NewString(),
Code: spec.Code,
Name: spec.Name,
}
if err := acc.DB.Create(&data).Error; err != nil {
return err
}
return nil
}
+15
View File
@@ -0,0 +1,15 @@
package tagrepository
import (
tagdomain "legalgo-BE-go/internal/domain/tag"
)
func (acc *accessor) GetAll() ([]tagdomain.Tag, error) {
var tags []tagdomain.Tag
if err := acc.DB.Find(&tags).Error; err != nil {
return nil, err
}
return tags, nil
}
+13
View File
@@ -0,0 +1,13 @@
package tagrepository
import "legalgo-BE-go/database"
func (acc *accessor) GetAllModel() ([]database.TagModel, error) {
var tags []database.TagModel
if err := acc.DB.Find(&tags).Error; err != nil {
return nil, err
}
return tags, nil
}
+13
View File
@@ -0,0 +1,13 @@
package tagrepository
import tagdomain "legalgo-BE-go/internal/domain/tag"
func (a *accessor) GetByIDs(ids []string) ([]tagdomain.Tag, error) {
var tags []tagdomain.Tag
if err := a.DB.Find(&tags, "id IN ?", ids).Error; err != nil {
return nil, err
}
return tags, nil
}
+13
View File
@@ -0,0 +1,13 @@
package tagrepository
import "legalgo-BE-go/database"
func (a *accessor) GetBulks(ids []string) ([]database.TagModel, error) {
var tags []database.TagModel
if err := a.DB.Find(&tags, "id IN ?", ids).Error; err != nil {
return nil, err
}
return tags, nil
}
+25
View File
@@ -0,0 +1,25 @@
package tagrepository
import (
"legalgo-BE-go/database"
tagdomain "legalgo-BE-go/internal/domain/tag"
)
type accessor struct {
DB *database.DB
}
type TagAccessor interface {
Create(tagdomain.TagReq) error
CreateModel(tagdomain.TagReq) error
GetAll() ([]tagdomain.Tag, error)
GetAllModel() ([]database.TagModel, error)
GetByIDs([]string) ([]tagdomain.Tag, error)
GetBulks(ids []string) ([]database.TagModel, error)
}
func New(
db *database.DB,
) TagAccessor {
return &accessor{db}
}
@@ -0,0 +1,13 @@
package userrepository
import (
authdomain "legalgo-BE-go/internal/domain/auth"
)
func (ur *UserRepository) CreateUser(spec *authdomain.User) (*authdomain.User, error) {
if err := ur.DB.Create(&spec).Error; err != nil {
return nil, err
}
return spec, nil
}
@@ -0,0 +1,26 @@
package userrepository
import (
"errors"
authdomain "legalgo-BE-go/internal/domain/auth"
"gorm.io/gorm"
)
func (ur *UserRepository) GetUserByEmail(email string) (*authdomain.User, error) {
var user authdomain.User
if email == "" {
return nil, errors.New("email is empty")
}
if err := ur.DB.First(&user, "email = ?", email).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("user not found")
}
return nil, err
}
return &user, nil
}
@@ -0,0 +1,30 @@
package userrepository
import (
"errors"
authdomain "legalgo-BE-go/internal/domain/auth"
"gorm.io/gorm"
)
func (ur *UserRepository) GetUserByID(email string) (*authdomain.UserProfile, error) {
var users []authdomain.UserProfile
if email == "" {
return nil, errors.New("email is empty")
}
if err := ur.DB.Table("users u").
Select("u.email, u.id, s.status as subscribe_status, sp.code as subscribe_plan_code, sp.name as subscribe_plan_name").
Joins("join subscribes s on s.id = u.subscribe_id").
Joins("join subscribe_plans sp on s.subscribe_plan_id = sp.id").
Scan(&users).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("user not found")
}
return nil, err
}
return &users[0], nil
}
@@ -0,0 +1,30 @@
package userrepository
import (
"errors"
authdomain "legalgo-BE-go/internal/domain/auth"
"gorm.io/gorm"
)
func (ur *UserRepository) GetUserProfile(email string) (*authdomain.UserProfile, error) {
var users []authdomain.UserProfile
if email == "" {
return nil, errors.New("email is empty")
}
if err := ur.DB.Table("users u").
Where("email = ?", email).
Select("u.email, u.id, s.status as subscribe_status, sp.code as subscribe_plan_code, sp.name as subscribe_plan_name").
Joins("join subscribes s on s.id = u.subscribe_id").
Joins("join subscribe_plans sp on s.subscribe_plan_id = sp.id").
Scan(&users).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("user not found")
}
return nil, err
}
return &users[0], nil
}
+23
View File
@@ -0,0 +1,23 @@
package userrepository
import (
"legalgo-BE-go/database"
authdomain "legalgo-BE-go/internal/domain/auth"
)
type UserRepository struct {
DB *database.DB
}
type UserIntf interface {
GetUserByEmail(string) (*authdomain.User, error)
GetUserByID(string) (*authdomain.UserProfile, error)
GetUserProfile(string) (*authdomain.UserProfile, error)
CreateUser(*authdomain.User) (*authdomain.User, error)
}
func New(
db *database.DB,
) UserIntf {
return &UserRepository{db}
}
+66 -10
View File
@@ -3,25 +3,26 @@ package authhttp
import (
"net/http"
domain "github.com/ardeman/project-legalgo-go/internal/domain/auth"
serviceauth "github.com/ardeman/project-legalgo-go/internal/services/auth"
"github.com/ardeman/project-legalgo-go/internal/utilities/response"
"github.com/ardeman/project-legalgo-go/internal/utilities/utils"
authdomain "legalgo-BE-go/internal/domain/auth"
authsvc "legalgo-BE-go/internal/services/auth"
"legalgo-BE-go/internal/utilities/response"
"legalgo-BE-go/internal/utilities/utils"
"github.com/go-chi/chi/v5"
"github.com/go-playground/validator/v10"
)
func LoginStaff(
router chi.Router,
authSvc serviceauth.LoginStaffIntf,
authSvc authsvc.AuthIntf,
validate *validator.Validate,
) {
router.Post("/staff/login", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var request domain.StaffLoginReq
var spec authdomain.LoginReq
if err := utils.UnmarshalBody(r, &request); err != nil {
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
@@ -33,7 +34,7 @@ func LoginStaff(
return
}
if err := validate.Struct(request); err != nil {
if err := validate.Struct(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
@@ -45,7 +46,7 @@ func LoginStaff(
return
}
token, err := authSvc.LoginAsStaff(request.Email)
token, err := authSvc.LoginAsStaff(spec)
if err != nil {
response.ResponseWithErrorCode(
ctx,
@@ -58,7 +59,62 @@ func LoginStaff(
return
}
responsePayload := &domain.StaffLoginResponse{
responsePayload := &authdomain.AuthResponse{
Token: token,
}
response.RespondJsonSuccess(ctx, w, responsePayload)
})
}
func LoginUser(
router chi.Router,
authSvc authsvc.AuthIntf,
validate *validator.Validate,
) {
router.Post("/user/login", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec authdomain.LoginReq
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
"failed to unmarshal request",
)
return
}
if err := validate.Struct(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.(validator.ValidationErrors).Error(),
)
return
}
token, err := authSvc.LoginAsUser(spec)
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
responsePayload := &authdomain.AuthResponse{
Token: token,
}
+6
View File
@@ -5,5 +5,11 @@ import "go.uber.org/fx"
var Module = fx.Module("auth-api",
fx.Invoke(
LoginStaff,
LoginUser,
RegisterUser,
RegisterStaff,
UpdateStaff,
GetStaffProfile,
GetUserProfile,
),
)
+82
View File
@@ -0,0 +1,82 @@
package authhttp
import (
authsvc "legalgo-BE-go/internal/services/auth"
"legalgo-BE-go/internal/utilities/response"
"legalgo-BE-go/internal/utilities/utils"
"net/http"
"github.com/go-chi/chi/v5"
)
func GetStaffProfile(
router chi.Router,
authSvc authsvc.AuthIntf,
) {
router.Get("/staff/profile", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
destructedToken, err := utils.GetTokenDetail(r)
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
staffProfile, err := authSvc.GetStaffProfile(destructedToken.Email)
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, staffProfile)
})
}
func GetUserProfile(
router chi.Router,
authSvc authsvc.AuthIntf,
) {
router.Get("/user/profile", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
destructedToken, err := utils.GetTokenDetail(r)
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
userProfile, err := authSvc.GetUserProfile(destructedToken.Email)
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, userProfile)
})
}
+121
View File
@@ -0,0 +1,121 @@
package authhttp
import (
"net/http"
authdomain "legalgo-BE-go/internal/domain/auth"
authsvc "legalgo-BE-go/internal/services/auth"
"legalgo-BE-go/internal/utilities/response"
"legalgo-BE-go/internal/utilities/utils"
"github.com/go-chi/chi/v5"
"github.com/go-playground/validator/v10"
)
func RegisterUser(
router chi.Router,
validate *validator.Validate,
authSvc authsvc.AuthIntf,
) {
router.Post("/user/register", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec authdomain.RegisterUserReq
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
"failed to unmarshal request",
)
return
}
if err := validate.Struct(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.(validator.ValidationErrors).Error(),
)
return
}
token, err := authSvc.RegisterUser(spec)
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
responsePayload := &authdomain.AuthResponse{
Token: token,
}
response.RespondJsonSuccess(ctx, w, responsePayload)
})
}
func RegisterStaff(
router chi.Router,
validate *validator.Validate,
authSvc authsvc.AuthIntf,
) {
router.Post("/staff/register", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec authdomain.RegisterStaffReq
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
"failed to unmarshal request",
)
return
}
if err := validate.Struct(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.(validator.ValidationErrors).Error(),
)
return
}
token, err := authSvc.RegisterStaff(spec)
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
responsePayload := &authdomain.AuthResponse{
Token: token,
}
response.RespondJsonSuccess(ctx, w, responsePayload)
})
}
+75
View File
@@ -0,0 +1,75 @@
package authhttp
import (
"errors"
authdomain "legalgo-BE-go/internal/domain/auth"
authsvc "legalgo-BE-go/internal/services/auth"
"legalgo-BE-go/internal/utilities/response"
"legalgo-BE-go/internal/utilities/utils"
"net/http"
"github.com/go-chi/chi/v5"
)
func UpdateStaff(
router chi.Router,
authSvc authsvc.AuthIntf,
) {
router.Patch("/staff/{id}/update", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
id := chi.URLParam(r, "id")
if id == "" {
response.ResponseWithErrorCode(
ctx,
w,
errors.New("provided id is empty"),
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
"required params is not provided",
)
return
}
var spec authdomain.RegisterStaffReq
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
"failed to unmarshal request",
)
return
}
staff := authdomain.Staff{
ID: id,
Email: spec.Email,
Password: spec.Password,
Username: spec.Username,
}
if err := authSvc.UpdateStaff(staff); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
responsePayload := struct{
Message string
} {
Message: "update staff success",
}
response.RespondJsonSuccess(ctx, w, responsePayload)
})
}
+67
View File
@@ -0,0 +1,67 @@
package categoryhttp
import (
categorydomain "legalgo-BE-go/internal/domain/category"
categorysvc "legalgo-BE-go/internal/services/category"
"legalgo-BE-go/internal/utilities/response"
"legalgo-BE-go/internal/utilities/utils"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-playground/validator/v10"
)
func Create(
router chi.Router,
validate *validator.Validate,
categorySvc categorysvc.Category,
) {
router.Post("/category/create", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec categorydomain.CategoryReq
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
if err := validate.Struct(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.(validator.ValidationErrors).Error(),
)
return
}
if err := categorySvc.Create(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrCreateEntity.Code,
response.ErrCreateEntity.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, struct {
Message string
}{
Message: "category created successfully",
})
})
}
+33
View File
@@ -0,0 +1,33 @@
package categoryhttp
import (
categorysvc "legalgo-BE-go/internal/services/category"
"legalgo-BE-go/internal/utilities/response"
"net/http"
"github.com/go-chi/chi/v5"
)
func GetAll(
router chi.Router,
categorySvc categorysvc.Category,
) {
router.Get("/category", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
subsPlan, err := categorySvc.GetAllModel()
// subsPlan, err := categorySvc.GetAll()
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, subsPlan)
})
}
+8
View File
@@ -0,0 +1,8 @@
package categoryhttp
import "go.uber.org/fx"
var Module = fx.Module("categories", fx.Invoke(
Create,
GetAll,
))
+5
View File
@@ -0,0 +1,5 @@
package contenthttp
import "go.uber.org/fx"
var Module = fx.Module("content-api", fx.Invoke())
@@ -0,0 +1,138 @@
package authmiddleware
// import (
// "context"
// "fmt"
// "net/http"
// "strings"
// redisaccessor "legalgo-BE-go/internal/accessor/redis"
// contextkeyenum "legalgo-BE-go/internal/enums/context_key"
// jwtclaimenum "legalgo-BE-go/internal/enums/jwt"
// resourceenum "legalgo-BE-go/internal/enums/resource"
// "legalgo-BE-go/internal/services/auth"
// "github.com/golang-jwt/jwt/v5"
// )
// const SessionHeader = "Authorization"
// func Authorization() func(next http.Handler) http.Handler {
// return func(next http.Handler) http.Handler {
// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// ctx := r.Context()
// tokenString, err := GetToken(r)
// if err != nil {
// RespondWithError(w, r, err, "Invalid auth header")
// return
// }
// token, err := ValidateToken(ctx, tokenString)
// if err != nil {
// RespondWithError(w, r, err, err.Error())
// return
// }
// if isAuthorized, ctx := VerifyClaims(ctx, token, nil); !isAuthorized {
// RespondWithError(w, r, errorcode.ErrCodeUnauthorized, errorcode.ErrCodeUnauthorized.Message)
// return
// } else {
// next.ServeHTTP(w, r.WithContext(ctx))
// return
// }
// })
// }
// }
// func GetToken(r *http.Request) (string, error) {
// tokenString := GetTokenFromHeader(r)
// if tokenString == "" {
// tokenString = getTokenFromQuery(r)
// }
// if tokenString == "" {
// return "", fmt.Errorf("token not found")
// }
// return tokenString, nil
// }
// func GetTokenFromHeader(r *http.Request) string {
// session := r.Header.Get(SessionHeader)
// arr := strings.Split(session, " ")
// if len(arr) != 2 || strings.ToUpper(arr[0]) != "BEARER" {
// return ""
// }
// return arr[1]
// }
// func getTokenFromQuery(r *http.Request) string {
// token := r.URL.Query().Get("token")
// return token
// }
// func VerifyClaims(ctx context.Context, token *jwt.Token,
// requiredResources []resourceenum.Resource) (bool, context.Context) {
// if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
// rawResources := []interface{}{}
// if claimValue, exist := claims[string(jwtclaimenum.RESOURCES)]; exist {
// rawResources = claimValue.([]interface{})
// }
// resources := []resourceenum.Resource{}
// resourceMap := map[string]bool{}
// for _, v := range rawResources {
// value := v.(string)
// resources = append(resources, resourceenum.Resource(value))
// resourceMap[value] = true
// }
// ctx = context.WithValue(ctx, contextkeyenum.Authorization, UserAuthorization{
// Type: claims[string(jwtclaimenum.TYPE)].(string),
// UserId: claims[string(jwtclaimenum.AUDIENCE)].(string),
// Username: claims[string(jwtclaimenum.USERNAME)].(string),
// Resources: resources,
// })
// isResourceFulfilled := false
// for _, v := range requiredResources {
// if _, ok := resourceMap[string(v)]; ok {
// isResourceFulfilled = true
// ctx = context.WithValue(ctx, contextkeyenum.Resource, v)
// break
// }
// }
// if isResourceFulfilled || len(requiredResources) == 0 {
// return true, ctx
// }
// }
// return false, nil
// }
// func ValidateToken(ctx context.Context, tokenString string) (*jwt.Token, error) {
// redisClient := redisaccessor.Get()
// redisToken, err := redisClient.Exists(ctx, fmt.Sprintf("%s:%s", auth.BLACKLISTED_TOKEN_KEY, tokenString)).Result()
// if err != nil || redisToken > 0 {
// return nil, fmt.Errorf("session already expired")
// }
// token, err := jwt.Parse(tokenString, authsvc.VerifyToken(conf.JWTAccessToken))
// if err != nil {
// if ve, ok := err.(*jwt.ValidationError); ok {
// if ve.Errors&jwt.ValidationErrorExpired != 0 {
// err = errorcode.ErrCodeExpiredToken
// }
// }
// return nil, err
// }
// return token, nil
// }
+93
View File
@@ -0,0 +1,93 @@
package newshttp
import (
staffrepository "legalgo-BE-go/internal/accessor/staff"
newsdomain "legalgo-BE-go/internal/domain/news"
newssvc "legalgo-BE-go/internal/services/news"
"legalgo-BE-go/internal/utilities/response"
"legalgo-BE-go/internal/utilities/utils"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-playground/validator/v10"
)
func Create(
validate *validator.Validate,
newsSvc newssvc.News,
staffRepo staffrepository.StaffIntf,
router chi.Router,
) {
router.Post("/news/create", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec newsdomain.NewsReq
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
if err := validate.Struct(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.(validator.ValidationErrors).Error(),
)
return
}
destructedToken, err := utils.GetTokenDetail(r)
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
staffProfile, err := staffRepo.GetStaffByEmail(destructedToken.Email)
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
if err := newsSvc.CreateModel(spec, staffProfile.ID); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, struct {
Message string
}{
Message: "news created successfully.",
})
})
}
+32
View File
@@ -0,0 +1,32 @@
package newshttp
import (
newssvc "legalgo-BE-go/internal/services/news"
"legalgo-BE-go/internal/utilities/response"
"net/http"
"github.com/go-chi/chi/v5"
)
func GetAll(
router chi.Router,
newsSvc newssvc.News,
) {
router.Get("/news", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
news, err := newsSvc.GetAllModel()
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, news)
})
}
+8
View File
@@ -0,0 +1,8 @@
package newshttp
import "go.uber.org/fx"
var Module = fx.Module("news", fx.Invoke(
GetAll,
Create,
))
+11
View File
@@ -0,0 +1,11 @@
package osshttp
import (
"go.uber.org/fx"
)
var Module = fx.Module("upload",
fx.Invoke(
RegisterUploadFile,
),
)
+92
View File
@@ -0,0 +1,92 @@
package osshttp
import (
"fmt"
oss2 "legalgo-BE-go/internal/domain/oss"
"legalgo-BE-go/internal/services/oss"
"legalgo-BE-go/internal/utilities/response"
"net/http"
"github.com/go-chi/chi/v5"
)
const _oneMB = 1 << 20
const _maxUploadSize = 2 * _oneMB
const _folderName = "/file"
func RegisterUploadFile(ossService oss.OSSService, router chi.Router) {
router.Post("/file", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
// Limit the size of the request body to prevent very large uploads.
r.Body = http.MaxBytesReader(w, r.Body, int64(_maxUploadSize))
if err := r.ParseMultipartForm(int64(_maxUploadSize)); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
"Failed to parse multipart form",
)
return
}
// Retrieve the file from the form.
file, header, err := r.FormFile("file")
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
"Failed to retrieve file",
)
return
}
defer file.Close()
// Check if file size exceeds the maximum limit.
if header.Size > int64(_maxUploadSize) {
response.ResponseWithErrorCode(
ctx,
w,
fmt.Errorf("file too big"),
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
fmt.Sprintf("The file is too big. The maximum size is %d MB", _maxUploadSize/_oneMB),
)
return
}
// Prepare the request for the OSS service.
uploadReq := &oss2.UploadFileRequest{
FileHeader: header,
FolderName: _folderName,
}
// Call the OSS service to handle the file upload.
result, err := ossService.UploadFile(ctx, uploadReq)
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
// Return a successful JSON response.
response.RespondJsonSuccess(ctx, w, struct {
Message string `json:"message"`
Data interface{} `json:"data"`
}{
Message: "File uploaded successfully.",
Data: result,
})
})
}
+12 -1
View File
@@ -1,7 +1,13 @@
package internalhttp
import (
authhttp "github.com/ardeman/project-legalgo-go/internal/api/http/auth"
authhttp "legalgo-BE-go/internal/api/http/auth"
categoryhttp "legalgo-BE-go/internal/api/http/category"
newshttp "legalgo-BE-go/internal/api/http/news"
osshttp "legalgo-BE-go/internal/api/http/oss"
subscribeplanhttp "legalgo-BE-go/internal/api/http/subscribe_plan"
taghttp "legalgo-BE-go/internal/api/http/tag"
"github.com/go-chi/chi/v5"
"github.com/go-chi/cors"
"github.com/go-playground/validator/v10"
@@ -16,6 +22,11 @@ var Module = fx.Module("router",
validator.New,
),
authhttp.Module,
subscribeplanhttp.Module,
taghttp.Module,
categoryhttp.Module,
newshttp.Module,
osshttp.Module,
)
func initRouter() chi.Router {
@@ -0,0 +1,67 @@
package subscribeplanhttp
import (
"net/http"
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
subscribeplansvc "legalgo-BE-go/internal/services/subscribe_plan"
"legalgo-BE-go/internal/utilities/response"
"legalgo-BE-go/internal/utilities/utils"
"github.com/go-chi/chi/v5"
"github.com/go-playground/validator/v10"
)
func CreateSubscribePlan(
router chi.Router,
validate *validator.Validate,
subsSvc subscribeplansvc.SubsPlanIntf,
) {
router.Post("/subscribe-plan/create", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec subscribeplandomain.SubscribePlanReq
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
"failed to unmarshal request",
)
return
}
if err := validate.Struct(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.(validator.ValidationErrors).Error(),
)
return
}
if err := subsSvc.CreatePlan(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrCreateEntity.Code,
response.ErrCreateEntity.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, struct {
Message string
}{
Message: "subscription plan created successfully.",
})
})
}
@@ -0,0 +1,33 @@
package subscribeplanhttp
import (
"net/http"
subscribeplansvc "legalgo-BE-go/internal/services/subscribe_plan"
"legalgo-BE-go/internal/utilities/response"
"github.com/go-chi/chi/v5"
)
func GetAllPlan(
router chi.Router,
subsPlanSvc subscribeplansvc.SubsPlanIntf,
) {
router.Get("/subscribe-plan", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
subsPlan, err := subsPlanSvc.GetAllPlan()
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
response.ErrBadRequest.Message,
)
return
}
response.RespondJsonSuccess(ctx, w, subsPlan)
})
}
@@ -0,0 +1,10 @@
package subscribeplanhttp
import "go.uber.org/fx"
var Module = fx.Module("subscribe-plan",
fx.Invoke(
CreateSubscribePlan,
GetAllPlan,
),
)
+67
View File
@@ -0,0 +1,67 @@
package taghttp
import (
"net/http"
tagdomain "legalgo-BE-go/internal/domain/tag"
tagsvc "legalgo-BE-go/internal/services/tag"
"legalgo-BE-go/internal/utilities/response"
"legalgo-BE-go/internal/utilities/utils"
"github.com/go-chi/chi/v5"
"github.com/go-playground/validator/v10"
)
func Create(
router chi.Router,
validate *validator.Validate,
tagSvc tagsvc.TagIntf,
) {
router.Post("/tag/create", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec tagdomain.TagReq
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
"failed to unmarshal request",
)
return
}
if err := validate.Struct(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.(validator.ValidationErrors).Error(),
)
return
}
if err := tagSvc.Create(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrCreateEntity.Code,
response.ErrCreateEntity.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, struct {
Message string
}{
Message: "tag created successfully.",
})
})
}
+33
View File
@@ -0,0 +1,33 @@
package taghttp
import (
tagsvc "legalgo-BE-go/internal/services/tag"
"legalgo-BE-go/internal/utilities/response"
"net/http"
"github.com/go-chi/chi/v5"
)
func GetAll(
router chi.Router,
tagSvc tagsvc.TagIntf,
) {
router.Get("/tag", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
tags, err := tagSvc.GetAllModel()
// tags, err := tagSvc.GetAll()
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, tags)
})
}
+8
View File
@@ -0,0 +1,8 @@
package taghttp
import "go.uber.org/fx"
var Module = fx.Module("tag", fx.Invoke(
Create,
GetAll,
))
+6 -4
View File
@@ -8,6 +8,8 @@ import (
"syscall"
"time"
"legalgo-BE-go/config"
"github.com/go-chi/chi/v5"
"github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
@@ -16,26 +18,26 @@ import (
func Router(apiRouter chi.Router) {
mainRouter := chi.NewRouter()
mainRouter.Mount("/", apiRouter)
mainRouter.Mount("/api", apiRouter)
mainCtx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
svr := &http.Server{
Addr: fmt.Sprintf(":%d", APP_PORT),
Addr: fmt.Sprintf(":%d", config.APP_PORT),
Handler: mainRouter,
}
group, groupCtx := errgroup.WithContext(mainCtx)
group.Go(func() error {
logrus.Infof("Listening to port %d", APP_PORT)
logrus.Infof("Listening to port %d", config.APP_PORT)
return svr.ListenAndServe()
})
group.Go(func() error {
<-groupCtx.Done()
ctxTimeout, cancel := context.WithTimeout(mainCtx, GRACEFULL_TIMEOUT*time.Second)
ctxTimeout, cancel := context.WithTimeout(mainCtx, time.Duration(config.GRACEFULL_TIMEOUT)*time.Second)
defer cancel()
svr.Shutdown(ctxTimeout)
-4
View File
@@ -1,4 +0,0 @@
package pkgconfig
const APP_PORT = 3000
const GRACEFULL_TIMEOUT = 20
+31
View File
@@ -0,0 +1,31 @@
package authdomain
type LoginReq struct {
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
}
type AuthResponse struct {
Token string `json:"token"`
}
type LoginRepoResponse struct {
ID string `json:"id"`
Email string `json:"email"`
Password string `json:"password"`
Username string `json:"username"`
}
type StaffProfile struct {
ID string `json:"id"`
Email string `json:"email"`
Username string `json:"username"`
}
type UserProfile struct {
ID string `json:"id"`
Email string `json:"email"`
SubscribePlanCode string `json:"subscribe_plan_code"`
SubscribePlanName string `json:"subscribe_plan_name"`
SubscribeStatus string `json:"subscribe_status"`
}
+35
View File
@@ -0,0 +1,35 @@
package authdomain
type RegisterUserReq struct {
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
Phone string `json:"phone" validate:"required"`
SubscribePlanID string `json:"subscribe_plan_id"`
}
type User struct {
ID string `json:"id"`
Email string `json:"email"`
Password string `json:"password"`
Phone string `json:"phone"`
SubscribeID string `json:"subscribe_id"`
}
type RegisterStaffReq struct {
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
Username string `json:"username" validate:"required"`
}
type UpdateStaffReq struct {
Email string `json:"email"`
Password string `json:"password"`
Username string `json:"username"`
}
type Staff struct {
ID string `json:"id"`
Email string `json:"email"`
Password string `json:"password"`
Username string `json:"username"`
}
-10
View File
@@ -1,10 +0,0 @@
package domain
type StaffLoginReq struct {
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
}
type StaffLoginResponse struct {
Token string `json:"token"`
}
+6
View File
@@ -0,0 +1,6 @@
package authdomain
type AuthToken struct {
Email string
SessionID string
}

Some files were not shown because too many files have changed in this diff Show More