114 Commits
Author SHA1 Message Date
Ardeman 211f0154be fix: update default environment mode to local and adjust database configurations 2025-04-24 11:25:36 +08:00
Ardeman 136c4634c8 fix: enable SSL for Redis configuration in debug environment 2025-04-23 19:10:31 +08:00
Ardeman 987ac2fe4a fix: update Redis configuration to use SSL and adjust related settings 2025-04-23 19:09:24 +08:00
Ardeman 02d8a509ff fix: update Redis credentials in staging configuration 2025-04-23 18:45:49 +08:00
Ardeman e29bd7986f fix: update default environment mode to staging and add local configuration file 2025-04-23 18:18:44 +08:00
Ardeman 4bf318a9c2 fix: update PostgreSQL configuration for staging environment 2025-04-23 18:01:55 +08:00
Ardeman 52085a5be0 feat: add staging configuration file with server, database, and OSS settings 2025-04-23 17:52:58 +08:00
Ardeman 21c4c1efba fix: update MinIO endpoint and URLs to use news-cdn.legalgo.id in debug.yaml and production.yaml 2025-04-23 14:50:59 +08:00
Ardeman c17540cc20 fix: update MinIO endpoint and URLs to use crm-cdn.legalgo.id in production.yaml 2025-04-23 14:27:26 +08:00
Ardeman 714b1ff4eb fix: correct public URL formatting in GetPublicURL function 2025-04-23 13:50:41 +08:00
Ardeman abc3ce8d2b fix: update bucket name to 'uploads' in debug.yaml and production.yaml 2025-04-23 13:48:28 +08:00
Ardeman cd1097d3d0 fix: update MinIO endpoint to include the full domain in debug.yaml and production.yaml 2025-04-23 13:39:43 +08:00
Ardeman 52991059c6 fix: update bucket name to legalgonews-production in debug.yaml and production.yaml 2025-04-23 13:17:32 +08:00
Ardeman a7ef3f8ca2 fix: update SSL mode configuration in debug.yaml and NewDB function 2025-04-23 13:11:57 +08:00
Ardeman 6f1ac37915 fix: update redis host configuration in production.yaml 2025-04-23 12:57:06 +08:00
Ardeman e20c63e694 feat: add debug configuration file for server, jwt, postgresql, oss, and redis 2025-04-23 12:50:28 +08:00
Ardeman abcbc014a2 feat: add production configuration files for server, jwt, postgresql, oss, and redis 2025-04-23 12:39:50 +08:00
ericprd 98b871a5ed feat: get all staff 2025-03-25 18:01:14 +08:00
ericprd 3311b80943 Merge branch 'main' of github.com:ardeman/project-legalgo-go 2025-03-24 22:16:17 +08:00
ericprd 16fef8706a fix: register staff return message only 2025-03-24 22:15:41 +08:00
Ardeman 4fbfa9c2c9 Merge branch 'main' of https://github.com/ardeman/project-legalgo-go
* 'main' of https://github.com/ardeman/project-legalgo-go:
  fix: search news title by query
2025-03-24 18:18:53 +08:00
ericprd a68780f09e fix: search news title by query 2025-03-24 18:11:08 +08:00
Ardeman 49dc0e4a7b refactor: update GetAll method to return NewsResponse and rename clicked to views 2025-03-24 15:24:52 +08:00
ericprd 09d9c4efb8 fix: error clicked when create new news 2025-03-24 14:02:20 +08:00
ericprd 990026cece fix: error clicked when create new news 2025-03-24 13:35:46 +08:00
ericprd 11051ae89c feat: staff get news by id 2025-03-24 13:32:05 +08:00
ericprd 24f0fe6efa fix: filter active in news 2025-03-20 13:13:28 +08:00
ericprd 8d7500610e fix: get userAgent and IP from custom header 2025-03-20 11:52:12 +08:00
ericprd 0c8133c802 fix: don't record log if staff 2025-03-20 11:19:41 +08:00
ericprd d8f6968f64 fix: improvement logs and record news access 2025-03-20 11:11:08 +08:00
ericprd 290d7f6701 fix: improvement log record ads tih ip, useragent, and uer_id 2025-03-19 22:43:31 +08:00
ericprd b0099dac1e fix: remove auth in ads log 2025-03-19 12:47:41 +08:00
ericprd d7fa8496b0 fix: add created_at field on user profile 2025-03-17 22:50:37 +08:00
ericprd efab193793 fix: add seeding spotlight category 2025-03-17 22:42:25 +08:00
ericprd 7b529ba46e fix: add clicked count on ads 2025-03-17 22:35:22 +08:00
ericprd c0dcdb77fa feat: ads log 2025-03-17 22:19:17 +08:00
ericprd ee8e8e140d fix: improvement access data 2025-03-14 13:00:12 +08:00
ericprd 11bc19360c feat: update staff data 2025-03-14 12:41:11 +08:00
ericprd 1297c71200 feat: update route ads 2025-03-13 12:00:26 +08:00
ericprd 47085ca0ae fix: add start date and end date of ads 2025-03-13 11:45:39 +08:00
ericprd ce17e9dc73 fix: update seeder 2025-03-10 12:28:56 +08:00
ericprd ce341dbc13 fix: add new fields on subscribe plan, and change status type to number in subscribe 2025-03-10 11:48:20 +08:00
ericprd 52dfb7e0f2 feat: delete ads 2025-03-10 10:50:27 +08:00
ericprd ef6b17a363 fix: image must be url in create ads 2025-03-10 10:28:23 +08:00
ericprd 1ae192ccef feat: get all ads 2025-03-09 00:55:40 +08:00
ericprd 213d370332 feat: create ads 2025-03-09 00:47:24 +08:00
ericprd 13c976dcbf fix: update user plan and rearrange structur project 2025-03-08 22:46:05 +08:00
Ardeman a47b7b7d3d feat: update Category model and request struct to use pointers for description and sequence fields 2025-03-08 00:05:04 +08:00
Ardeman c5eb6302ab feat: add description and sequence fields to Create and Update category functions 2025-03-07 23:58:53 +08:00
Ardeman 68f33d101b feat: add description and sequence fields to Category model and update request struct 2025-03-07 23:41:54 +08:00
Ardeman 479703dfd0 feat: add description field to Category model and clean up migration code 2025-03-07 23:26:54 +08:00
ericprd dc1a4dafbc fix: failed to migrate 2025-03-07 19:29:34 +08:00
ericprd fdf572cd3d feat: refactor auth package and add get users for staff 2025-03-07 17:39:26 +08:00
ericprd c48a4b944b fix: update tags and categories not updated 2025-03-07 15:16:05 +08:00
ericprd c410e651ce fix: categories filter is multiple now 2025-03-07 14:30:31 +08:00
ericprd 51b50a3132 fix: get news by query category and tags filters 2025-03-07 00:55:50 +08:00
ericprd e3a9b67e28 feat: update news 2025-03-06 23:55:46 +08:00
ericprd 2046021e01 Merge branch 'main' of github.com:ardeman/project-legalgo-go 2025-03-06 13:30:39 +08:00
ericprd a2a6fe6374 fix: use redis config 2025-03-06 13:30:24 +08:00
Ardeman d6a680634c chore: remove deprecated jwt dependency and update to v5 2025-03-06 12:58:28 +08:00
ericprd cf410bdf05 feat: add redis config env 2025-03-06 12:56:35 +08:00
ericprd efc87ee63e Merge branch 'main' of github.com:ardeman/project-legalgo-go 2025-03-06 11:59:17 +08:00
ericprd c037da4879 feat: add vendor 2025-03-06 11:59:05 +08:00
0xCA7andGitHub 53fda59e3c Delete .DS_Store 2025-03-06 11:17:10 +08:00
ericprd 2525eed2ea Merge branch 'main' of github.com:ardeman/project-legalgo-go 2025-03-06 11:07:04 +08:00
ericprd 85247643e6 feat: get news by slug and and author detail 2025-03-06 11:06:06 +08:00
ericprd d217ec8a62 feat: delete news, tag, and category 2025-03-05 23:55:41 +08:00
ericprd 299fcf949b feat: update and delete tags and categories 2025-03-05 23:13:24 +08:00
ericprd 5c699dfa53 fix: create and get news 2025-03-05 22:15:39 +08:00
ericprd dd109c8aa0 chores: remove unused code 2025-03-05 21:27:37 +08:00
ericprd 567e0e32ca chores: refactor struct and structure project 2025-03-05 21:21:44 +08:00
altru 2b54a9343b Merge pull request 'Update Env' (#4) from feature-test into main
Reviewed-on: #4
2025-03-03 12:56:18 +00:00
aditya.siregar 30091f3362 Update Env 2025-03-03 19:55:44 +07:00
altru 43d5608a51 Merge pull request 'update docker' (#3) from feature-test into main
Reviewed-on: #3
2025-03-03 12:39:25 +00:00
aditya.siregar ed8c523b26 update docker 2025-03-03 19:39:11 +07:00
altru 883ff8b7d1 Merge pull request 'add docker file' (#2) from feature-test into main
Reviewed-on: #2
2025-03-03 12:30:23 +00:00
aditya.siregar e9b9a367a9 add docker file 2025-03-03 19:29:59 +07:00
altru 750a4dc3db Merge pull request 'Add Infra' (#1) from feature-test into main
Reviewed-on: #1
2025-03-03 12:03:19 +00:00
aditya.siregar c9f1e33c24 Add Infra 2025-03-03 18:59:25 +07:00
ericprd 13a8481f22 fix: payload update staff 2025-03-03 13:23:04 +08:00
ericprd 642566c8b2 Merge branch 'main' of github.com:ardeman/project-legalgo-go 2025-03-03 10:39:38 +08:00
ericprd afe6f4e9a6 fix: change username to name and add profile pic to staff 2025-03-03 10:39:01 +08:00
Ardeman 20c9660c3a docs: add instruction to execute binary directly 2025-03-02 22:43:39 +08: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
1994 changed files with 699056 additions and 1010 deletions
+5
View File
@@ -4,9 +4,14 @@ DB_PASSWORD=
DB_NAME=
DB_PORT=
APP_PORT=
GRACEFULL_TIMEOUT=
SALT_SECURITY=
REDIS_HOST=
REDIS_USERNAME=
REDIS_PORT=
REDIS_PASSWORD=
REDIS_TTL=
REDIS_DB=
REDIS_TIMEOUT=
+4
View File
@@ -1,2 +1,6 @@
bin
.env
.DS_Store
/cmd/legalgo/env
__debug*
+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"]
+45 -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,6 +87,7 @@ 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
```
@@ -79,6 +95,7 @@ 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.
@@ -97,12 +114,26 @@ 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
```
@@ -110,16 +141,24 @@ make build
## Run the Program Using `make run`
Finally, you can run your program using:
```bash
make run
```
This command will compile and execute your Go application.
Or you can execute the compiled binary at `bin/legalgo` by:
```bash
./bin/legalgo
```
---
**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
+63 -1
View File
@@ -1,5 +1,67 @@
package main
func main() {
import (
"log"
"os"
"legalgo-BE-go/config"
"legalgo-BE-go/database"
categorydomain "legalgo-BE-go/internal/domain/category"
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 tempSP subscribeplandomain.SubscribePlan
var tempCtg categorydomain.Category
if err := db.Where("code = ?", "basic").First(&tempSP).Error; err != nil {
log.Print("seeding basic subscribe plan")
db.Create(&subscribeplandomain.SubscribePlan{
ID: uuid.NewString(),
Code: "basic",
Name: "Basic",
Length: 0,
Price: 0,
Status: 1,
})
}
if err := db.Where("code = ?", "spotlight").First(&tempCtg).Error; err != nil {
log.Print("seeding basic subscribe plan")
seq := 0
db.Create(&categorydomain.Category{
ID: uuid.NewString(),
Code: "spotlight",
Name: "Spotlight",
Sequence: &seq,
})
}
log.Print("migrate success")
}
+31 -13
View File
@@ -4,38 +4,55 @@ 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"
"github.com/redis/go-redis/v9"
"go.uber.org/fx"
)
func init() {
if err := godotenv.Load(); err != nil {
log.Fatal("cannot load environment file")
// 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()
}
func run(lc fx.Lifecycle, db *database.DB, apiRouter chi.Router) {
func run(
lc fx.Lifecycle,
db *database.DB,
apiRouter chi.Router,
rdb *redis.Client,
) {
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)
_, err := rdb.Ping(ctx).Result()
if err != nil {
log.Fatalf("Could not connect to Redis: %v", err)
}
pkgconfig.Router(apiRouter)
return nil
},
OnStop: func(ctx context.Context) error {
fmt.Println("Shutting down...")
rdb.Close()
return nil
},
})
@@ -43,10 +60,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)
}
+40
View File
@@ -0,0 +1,40 @@
package config
import "fmt"
var (
APP_PORT,
REDIS_DB,
REDIS_TIMEOUT,
GRACEFULL_TIMEOUT int
// DB
DB_HOST,
DB_USER,
DB_PASSWORD,
DB_NAME,
DB_PORT,
REDIS_PASSWORD,
REDIS_ADDR,
REDIS_USERNAME,
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)
REDIS_DB = GetOrDefault("REDIS_DB", 0)
REDIS_PASSWORD = GetOrDefault("REDIS_PASSWORD", "")
REDIS_ADDR = fmt.Sprintf("%s:%s", GetOrDefault("REDIS_HOST", "localhost"), GetOrDefault("REDIS_PORT", "6379"))
REDIS_USERNAME = GetOrDefault("REDIS_USERNAME", "")
REDIS_TIMEOUT = GetOrDefault("REDIS_TIMEOUT", 60)
}
+70
View File
@@ -0,0 +1,70 @@
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 = "local"
)
var (
validEnvMode = map[string]struct{}{
"local": {},
"staging": {},
"production": {},
"debug": {},
}
)
type Config struct {
Server Server `mapstructure:"server"`
Database Database `mapstructure:"postgresql"`
Jwt Jwt `mapstructure:"jwt"`
OSSConfig OSSConfig `mapstructure:"oss"`
Redis Redis `mapstructure:"redis"`
}
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
}
+14
View File
@@ -0,0 +1,14 @@
package config
type Redis struct {
Host string `mapstructure:"host"`
Port string `mapstructure:"port"`
DB int `mapstructure:"db"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
SSL bool `mapstructure:"ssl"`
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"`
}
+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"`
}
+13
View File
@@ -0,0 +1,13 @@
package database
import "time"
type Ads struct {
ID string `gorm:"primaryKey;not null" json:"id"`
ImageUrl string `gorm:"not null" json:"image_url"`
Url string `gorm:"not null" json:"url"`
StartDate *time.Time `gorm:"default:null" json:"start_date"`
EndDate *time.Time `gorm:"default:null" json:"end_date"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}
+18
View File
@@ -0,0 +1,18 @@
package database
import (
"time"
)
type Category struct {
ID string `gorm:"primaryKey" json:"id"`
Name string `gorm:"not null" json:"name"`
Code string `gorm:"not null;unique" json:"code"`
Description string `gorm:"default:null" json:"description"`
Sequence int `gorm:"default:null" json:"sequence"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
DeletedAt time.Time `gorm:"default:null" json:"deleted_at"`
News []News `gorm:"many2many:news_categories" json:"news"`
}
+14
View File
@@ -0,0 +1,14 @@
package database
import "time"
type ContentLog struct {
ID string `gorm:"primaryKey;not null" json:"id"`
ContentID string `gorm:"not null" json:"content_id"`
UserID string `gorm:"default:null" json:"user_id"`
IP string `gorm:"default:null" json:"ip"`
UserAgent string `gorm:"default:null" json:"user_agent"`
Category string `gorm:"not null" json:"category"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}
+28 -17
View File
@@ -2,11 +2,9 @@ package database
import (
"fmt"
"os"
staffmodel "github.com/ardeman/project-legalgo-go/database/staff"
subsmodel "github.com/ardeman/project-legalgo-go/database/subscribe"
usermodel "github.com/ardeman/project-legalgo-go/database/user"
"legalgo-BE-go/config"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
@@ -15,17 +13,17 @@ 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=%s",
cfg.Database.Host,
cfg.Database.Username,
cfg.Database.Password,
cfg.Database.DB,
cfg.Database.Port,
cfg.Database.SslMode,
)
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")
}
@@ -39,12 +37,25 @@ func NewDB() (*DB, error) {
return &DB{db}, nil
}
func (db *DB) DropTables() error {
// Auto Migrate the User model
return db.Migrator().DropTable(
&Tag{},
&Category{},
&News{},
)
}
func (db *DB) Migrate() error {
// Auto Migrate the User model
return db.AutoMigrate(
&staffmodel.Staff{},
&subsmodel.SubscribePlan{},
&subsmodel.Subscribe{},
&usermodel.User{},
&Staff{},
&SubscribePlan{},
&Subscribe{},
&User{},
&News{},
&Tag{},
&Category{},
&Ads{},
&ContentLog{},
)
}
+23
View File
@@ -0,0 +1,23 @@
package database
import (
"time"
)
type News struct {
ID string `gorm:"primaryKey" json:"id"`
Title string `json:"title"`
Content string `json:"content"`
Categories []Category `gorm:"many2many:news_categories" json:"categories"`
Tags []Tag `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"`
DeletedAt time.Time `gorm:"default:null" json:"deleted_at"`
Author Staff `gorm:"foreignKey:AuthorID" json:"author"`
}
-15
View File
@@ -1,15 +0,0 @@
package staffmodel
import (
"time"
"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"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}
+16
View File
@@ -0,0 +1,16 @@
package database
import (
"time"
)
type Staff struct {
ID string `gorm:"primaryKey" json:"id"`
Name string `gorm:"default:null" json:"name"`
ProfilePicture string `gorm:"default:null" json:"profile_picture"`
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"`
DeletedAt time.Time `gorm:"default:null" json:"deleted_at"`
}
@@ -1,28 +1,30 @@
package subsmodel
package database
import (
"time"
"github.com/google/uuid"
)
type Subscribe struct {
ID uuid.UUID `gorm:"type:uuid;primaryKey" json:"id"`
SubscribePlanID uuid.UUID `gorm:"type:uuid;not null" json:"subscribe_plan_id"`
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'"`
Status int8 `gorm:"default:0"`
AutoRenew bool `gorm:"default:true"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP"`
DeletedAt time.Time `gorm:"default:null" json:"deleted_at"`
SubscribePlan SubscribePlan `gorm:"foreignKey:SubscribePlanID;constraint:OnDelete:CASCADE"`
SubscribePlan SubscribePlan `gorm:"foreignKey:SubscribePlanID;constraint:OnDelete:CASCADE" json:"subscribe_plan"`
}
type SubscribePlan struct {
ID uuid.UUID `gorm:"type:uuid;primaryKey" json:"id"`
Code string `gorm:"not null" json:"code"`
ID string `gorm:"primaryKey" json:"id"`
Code string `gorm:"not null;unique" json:"code"`
Name string `gorm:"not null" json:"name"`
Length int `gorm:"default:0" json:"length"`
Price float32 `gorm:"default:0" json:"price"`
Status int8 `gorm:"default:1" json:"status"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP"`
}
+16
View File
@@ -0,0 +1,16 @@
package database
import (
"time"
)
type Tag struct {
ID string `gorm:"primaryKey" json:"id"`
Name string `gorm:"not null" json:"name"`
Code string `gorm:"not null;unique" json:"code"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
DeletedAt time.Time `gorm:"default:null" json:"deleted_at"`
News []News `gorm:"many2many:news_tags" json:"news"`
}
-19
View File
@@ -1,19 +0,0 @@
package usermodel
import (
"time"
subsmodel "github.com/ardeman/project-legalgo-go/database/subscribe"
"github.com/google/uuid"
)
type User struct {
ID uuid.UUID `gorm:"type:uuid;primaryKey" 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:null" json:"phone"`
Subscribe subsmodel.Subscribe `gorm:"foreignKey:SubscribeID;constraint:OnDelete:CASCADE"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}
+18
View File
@@ -0,0 +1,18 @@
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"`
DeletedAt time.Time `gorm:"default:null" json:"deleted_at"`
Subscribe Subscribe `gorm:"foreignKey:SubscribeID;constraint:OnDelete:CASCADE" json:"subscribe"`
}
+43
View File
@@ -0,0 +1,43 @@
server:
base-url: https://api.legalgo.id/core
local-url: http://localhost:3300
port: 3300
jwt:
token:
expires-ttl: 1440
secret: "5Lm25V3Qd7aut8dr4QUxm5PZUrSFs"
postgresql:
host: dpg-d046h549c44c739arfv0-a.singapore-postgres.render.com
port: 5432
driver: postgres
db: legalgonews_prod
username: legalgo_admin
password: "656ogwc0JlLEVQyHnT5RrrYa7762iBQQ"
ssl-mode: require
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: GTK7i3SVy9llQeGH0Htv
access_key_secret: 2psmKXZFpevA9n5ntSDRMqFBpZuSz32dvtXjYclf
endpoint: news-cdn.legalgo.id
bucket_name: uploads
log_level: Error
host_url: https://news-cdn.legalgo.id
public_url: https://news-cdn.legalgo.id
redis:
host: singapore-keyvalue.render.com
port: 6379
username: red-d046l42dbo4c73ea9iag
password: 7cZvu08JKuO9MPNxBb97tZCVNj0ZGNp2
db: 5
ssl: true
max-idle-connections-in-second: 600
max-open-connections-in-second: 600
connection-max-life-time-in-second: 600
debug: false
+43
View File
@@ -0,0 +1,43 @@
server:
base-url: https://api.legalgo.id/core
local-url: http://localhost:3300
port: 3300
jwt:
token:
expires-ttl: 1440
secret: "5Lm25V3Qd7aut8dr4QUxm5PZUrSFs"
postgresql:
host: dpg-d04bi9juibrs73augcc0-a.singapore-postgres.render.com
port: 5432
driver: postgres
db: legalgonews_dev
username: legalgo_admin
password: "5h7DCBR1T8pug6AlbrHXqIDAr9o2vnky"
ssl-mode: require
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: GTK7i3SVy9llQeGH0Htv
access_key_secret: 2psmKXZFpevA9n5ntSDRMqFBpZuSz32dvtXjYclf
endpoint: news-cdn.legalgo.id
bucket_name: uploads-staging
log_level: Error
host_url: https://news-cdn.legalgo.id
public_url: https://news-cdn.legalgo.id
redis:
host: singapore-keyvalue.render.com
port: 6379
username: red-d04c8k49c44c739ga8dg
password: ItPzniHv94yr8vY4HTrhCfKoibqBh61T
db: 5
ssl: true
max-idle-connections-in-second: 600
max-open-connections-in-second: 600
connection-max-life-time-in-second: 600
debug: false
+42
View File
@@ -0,0 +1,42 @@
server:
base-url: https://api.legalgo.id/core
local-url: http://localhost:3300
port: 3300
jwt:
token:
expires-ttl: 1440
secret: "5Lm25V3Qd7aut8dr4QUxm5PZUrSFs"
postgresql:
host: dpg-d046h549c44c739arfv0-a
port: 5432
driver: postgres
db: legalgonews_prod
username: legalgo_admin
password: "656ogwc0JlLEVQyHnT5RrrYa7762iBQQ"
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: GTK7i3SVy9llQeGH0Htv
access_key_secret: 2psmKXZFpevA9n5ntSDRMqFBpZuSz32dvtXjYclf
endpoint: news-cdn.legalgo.id
bucket_name: uploads
log_level: Error
host_url: https://news-cdn.legalgo.id
public_url: https://news-cdn.legalgo.id
redis:
host: red-d046l42dbo4c73ea9iag
port: 6379
password: 7cZvu08JKuO9MPNxBb97tZCVNj0ZGNp2
db: 5
ssl: false
max-idle-connections-in-second: 600
max-open-connections-in-second: 600
connection-max-life-time-in-second: 600
debug: false
+42
View File
@@ -0,0 +1,42 @@
server:
base-url: https://api.legalgo.id/core
local-url: http://localhost:3300
port: 3300
jwt:
token:
expires-ttl: 1440
secret: "5Lm25V3Qd7aut8dr4QUxm5PZUrSFs"
postgresql:
host: dpg-d04bi9juibrs73augcc0-a
port: 5432
driver: postgres
db: legalgonews_dev
username: legalgo_admin
password: "5h7DCBR1T8pug6AlbrHXqIDAr9o2vnky"
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: GTK7i3SVy9llQeGH0Htv
access_key_secret: 2psmKXZFpevA9n5ntSDRMqFBpZuSz32dvtXjYclf
endpoint: news-cdn.legalgo.id
bucket_name: uploads-staging
log_level: Error
host_url: https://news-cdn.legalgo.id
public_url: https://news-cdn.legalgo.id
redis:
host: red-d04c8k49c44c739ga8dg
port: 6379
password: ItPzniHv94yr8vY4HTrhCfKoibqBh61T
db: 5
ssl: false
max-idle-connections-in-second: 600
max-open-connections-in-second: 600
connection-max-life-time-in-second: 600
debug: false
+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.5.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.4.3 // 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
+72 -16
View File
@@ -1,18 +1,29 @@
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/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 +32,76 @@ 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-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.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/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.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
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.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.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=
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,10 +112,10 @@ 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.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/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
@@ -71,15 +123,19 @@ golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/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/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/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.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.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM=
gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA=
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
+14
View File
@@ -0,0 +1,14 @@
package adsrepository
import (
"fmt"
adsdomain "legalgo-BE-go/internal/domain/ads"
)
func (a *accessor) Create(spec adsdomain.Ads) error {
if err := a.db.Create(&spec).Error; err != nil {
return fmt.Errorf("failed to create ads: %v", err)
}
return nil
}
+26
View File
@@ -0,0 +1,26 @@
package adsrepository
import (
"errors"
"fmt"
adsdomain "legalgo-BE-go/internal/domain/ads"
"gorm.io/gorm"
)
func (a *accessor) Delete(id string) error {
var ads adsdomain.Ads
if err := a.db.First(&ads, "id = ?", id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return fmt.Errorf("ads with id %s is not found", id)
}
return fmt.Errorf("failed to g ads %s : %v", id, err)
}
if err := a.db.Delete(&ads).Error; err != nil {
return fmt.Errorf("failed to delete ads %s : %v", id, err)
}
return nil
}
+20
View File
@@ -0,0 +1,20 @@
package adsrepository
import (
"fmt"
adsdomain "legalgo-BE-go/internal/domain/ads"
)
func (a *accessor) GetAll() ([]adsdomain.AdsResponse, error) {
var ads []adsdomain.AdsResponse
if err := a.db.Table("ads").
Select("ads.*, COUNT(content_logs.content_id) as clicked").
Joins("LEFT JOIN content_logs ON content_logs.content_id = ads.id").
Group("ads.id").
Scan(&ads).Error; err != nil {
return ads, fmt.Errorf("failed to get all ads: %v", err)
}
return ads, nil
}
+23
View File
@@ -0,0 +1,23 @@
package adsrepository
import (
"legalgo-BE-go/database"
adsdomain "legalgo-BE-go/internal/domain/ads"
)
type accessor struct {
db *database.DB
}
type Ads interface {
Create(adsdomain.Ads) error
GetAll() ([]adsdomain.AdsResponse, error)
Update(adsdomain.Ads) error
Delete(string) error
}
func New(
db *database.DB,
) Ads {
return &accessor{db}
}
+31
View File
@@ -0,0 +1,31 @@
package adsrepository
import (
"fmt"
adsdomain "legalgo-BE-go/internal/domain/ads"
"gorm.io/gorm/clause"
)
func (a *accessor) Update(spec adsdomain.Ads) error {
if err := a.db.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "id"}},
DoUpdates: clause.AssignmentColumns([]string{
"image_url",
"url",
"updated_at",
"start_date",
"end_date",
}),
}).Select(
"image_url",
"url",
"updated_at",
"start_date",
"end_date",
).Save(&spec).Error; err != nil {
return fmt.Errorf("failed to update tag: %v", err)
}
return nil
}
+24
View File
@@ -0,0 +1,24 @@
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.Category{
ID: uuid.NewString(),
Name: spec.Name,
Code: spec.Code,
Description: *spec.Description,
Sequence: *spec.Sequence,
}
if err := a.db.Create(&data).Error; err != nil {
return err
}
return nil
}
+24
View File
@@ -0,0 +1,24 @@
package categoryrepository
import (
"fmt"
"legalgo-BE-go/database"
)
func (a *accessor) Delete(id string) error {
var category database.Category
if err := a.db.First(&category, "id = ?", id).Error; err != nil {
return fmt.Errorf("failed to find category: %v", err)
}
if err := a.db.Model(&category).Association("News").Clear(); err != nil {
return fmt.Errorf("failed to remove categories association: %v", err)
}
if err := a.db.Delete(&category).Error; err != nil {
return fmt.Errorf("failed to delete category %s : %v", id, err)
}
return nil
}
+15
View File
@@ -0,0 +1,15 @@
package categoryrepository
import (
categorydomain "legalgo-BE-go/internal/domain/category"
)
func (a *accessor) GetAllModel() ([]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,19 @@
package categoryrepository
import (
categorydomain "legalgo-BE-go/internal/domain/category"
)
func (a *accessor) GetIDByCode(codes []string) ([]string, error) {
var categories []string
if err := a.db.
Model(&categorydomain.Category{}).
Select("id").Where("code IN ?", codes).
Pluck("id", &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
}
+25
View File
@@ -0,0 +1,25 @@
package categoryrepository
import (
"legalgo-BE-go/database"
categorydomain "legalgo-BE-go/internal/domain/category"
)
type accessor struct {
db *database.DB
}
type Category interface {
GetAllModel() ([]categorydomain.Category, error)
GetByIDs([]string) ([]categorydomain.Category, error)
GetIDByCode([]string) ([]string, error)
CreateModel(categorydomain.CategoryReq) error
Update(categorydomain.Category) error
Delete(string) error
}
func New(
db *database.DB,
) Category {
return &accessor{db}
}
+19
View File
@@ -0,0 +1,19 @@
package categoryrepository
import (
"fmt"
categorydomain "legalgo-BE-go/internal/domain/category"
"gorm.io/gorm/clause"
)
func (a *accessor) Update(spec categorydomain.Category) error {
if err := a.db.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "id"}},
DoUpdates: clause.AssignmentColumns([]string{"name", "code", "sequence", "description", "updated_at"}),
}).Select("name", "code", "sequence", "description", "updated_at").Save(&spec).Error; err != nil {
return fmt.Errorf("failed to update category: %v", err)
}
return nil
}
+33
View File
@@ -0,0 +1,33 @@
package logrepository
import (
"legalgo-BE-go/database"
logsdomain "legalgo-BE-go/internal/domain/logs"
"github.com/google/uuid"
)
func (a *accessor) CreateLog(spec logsdomain.LogsSpec) error {
newSpec := database.ContentLog{
ID: uuid.NewString(),
ContentID: spec.ContentID,
Category: spec.Category,
}
if spec.UserID != nil {
newSpec.UserID = *spec.UserID
}
if spec.IP != nil {
newSpec.IP = *spec.IP
}
if spec.UserAgent != nil {
newSpec.UserAgent = *spec.UserAgent
}
if err := a.db.Create(&newSpec).Error; err != nil {
return err
}
return nil
}
+21
View File
@@ -0,0 +1,21 @@
package logrepository
import (
adsdomain "legalgo-BE-go/internal/domain/ads"
)
func (a *accessor) GetAllLogAds(userID string) ([]adsdomain.Ads, error) {
var ads []adsdomain.Ads
// if err := a.db.Find(&ads, "user_id = ?", userID).Error; err != nil {
// return ads, err
// }
if err := a.db.
Joins("JOIN log_ads ON ads.id = log_ads.ads_id").
Find(&ads, "log_ads.user_id = ?", userID).Error; err != nil {
return ads, err
}
return ads, nil
}
+20
View File
@@ -0,0 +1,20 @@
package logrepository
import (
"legalgo-BE-go/database"
adsdomain "legalgo-BE-go/internal/domain/ads"
logsdomain "legalgo-BE-go/internal/domain/logs"
)
type accessor struct {
db *database.DB
}
type Log interface {
CreateLog(logsdomain.LogsSpec) error
GetAllLogAds(string) ([]adsdomain.Ads, error)
}
func New(db *database.DB) Log {
return &accessor{db}
}
+18 -5
View File
@@ -1,11 +1,18 @@
package repository
import (
redisaccessor "github.com/ardeman/project-legalgo-go/internal/accessor/redis"
staffrepository "github.com/ardeman/project-legalgo-go/internal/accessor/staff"
subscriberepository "github.com/ardeman/project-legalgo-go/internal/accessor/subscribe"
subscribeplanrepository "github.com/ardeman/project-legalgo-go/internal/accessor/subscribeplan"
userrepository "github.com/ardeman/project-legalgo-go/internal/accessor/user_repository"
adsrepository "legalgo-BE-go/internal/accessor/ads"
categoryrepository "legalgo-BE-go/internal/accessor/category"
logrepository "legalgo-BE-go/internal/accessor/log"
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/subscribe_plan"
tagrepository "legalgo-BE-go/internal/accessor/tag"
userrepository "legalgo-BE-go/internal/accessor/user"
"go.uber.org/fx"
)
@@ -15,4 +22,10 @@ var Module = fx.Module("repository", fx.Provide(
redisaccessor.New,
subscribeplanrepository.New,
subscriberepository.New,
tagrepository.New,
categoryrepository.New,
newsrepository.New,
oss.New,
adsrepository.New,
logrepository.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
}
+28
View File
@@ -0,0 +1,28 @@
package newsrepository
import (
"fmt"
newsdomain "legalgo-BE-go/internal/domain/news"
)
func (a *accessor) Delete(id string) error {
var news newsdomain.News
if err := a.db.Preload("Categories").Preload("Tags").First(&news, "id = ?", id).Error; err != nil {
return fmt.Errorf("failed to find news: %v", err)
}
if err := a.db.Model(&news).Association("Categories").Clear(); err != nil {
return fmt.Errorf("failed to remove categories association: %v", err)
}
if err := a.db.Model(&news).Association("Tags").Clear(); err != nil {
return fmt.Errorf("failed to remove tags association: %v", err)
}
if err := a.db.Delete(&news, "id = ?", id).Error; err != nil {
return fmt.Errorf("failed to delete news %s : %v", id, err)
}
return nil
}
+52
View File
@@ -0,0 +1,52 @@
package newsrepository
import (
newsdomain "legalgo-BE-go/internal/domain/news"
timeutils "legalgo-BE-go/internal/utilities/time_utils"
)
type is_active string
const (
active is_active = "true"
notActive is_active = "false"
)
func (a *accessor) GetAll(filter newsdomain.NewsFilter) ([]newsdomain.NewsResponse, error) {
var news []newsdomain.NewsResponse
query := a.db.Table("news").
Preload("Tags").
Preload("Categories").
Preload("Author").
Joins("LEFT JOIN content_logs ON content_logs.content_id = news.id")
if len(filter.Category) > 0 {
query = query.Joins("JOIN news_categories nc ON nc.news_id = news.id").
Where("nc.category_id IN (?)", filter.Category)
}
if len(filter.Tags) > 0 {
query = query.Joins("JOIN news_tags nt ON nt.news_id = news.id").
Where("nt.tag_id IN (?)", filter.Tags)
}
if filter.Active == string(active) {
query = query.Where("news.live_at <= ?", timeutils.Now())
}
if filter.Search != "" {
query = query.Where("news.title ILIKE ?", "%"+filter.Search+"%")
}
query.
Select("news.*, COUNT(content_logs.content_id) as views").
Group("news.id").
Order("news.created_at DESC")
if err := query.
Find(&news).Error; err != nil {
return nil, err
}
return news, nil
}
+17
View File
@@ -0,0 +1,17 @@
package newsrepository
import newsdomain "legalgo-BE-go/internal/domain/news"
func (a *accessor) GetByID(id string) (*newsdomain.News, error) {
var news newsdomain.News
if err := a.db.
Preload("Tags").
Preload("Categories").
Preload("Author").
First(&news, "id = ?", id).Error; err != nil {
return nil, err
}
return &news, nil
}
+17
View File
@@ -0,0 +1,17 @@
package newsrepository
import newsdomain "legalgo-BE-go/internal/domain/news"
func (a *accessor) GetBySlug(slug string) (*newsdomain.News, error) {
var news newsdomain.News
if err := a.db.
Preload("Tags").
Preload("Categories").
Preload("Author").
First(&news, "slug = ?", slug).Error; err != nil {
return nil, err
}
return &news, nil
}
+23
View File
@@ -0,0 +1,23 @@
package newsrepository
import (
"legalgo-BE-go/database"
newsdomain "legalgo-BE-go/internal/domain/news"
)
type accessor struct {
db *database.DB
}
type News interface {
GetAll(filter newsdomain.NewsFilter) ([]newsdomain.NewsResponse, error)
GetBySlug(string) (*newsdomain.News, error)
GetByID(string) (*newsdomain.News, error)
Create(newsdomain.News) error
Update(newsdomain.News) error
Delete(string) error
}
func New(db *database.DB) News {
return &accessor{db}
}
+69
View File
@@ -0,0 +1,69 @@
package newsrepository
import (
"fmt"
categorydomain "legalgo-BE-go/internal/domain/category"
newsdomain "legalgo-BE-go/internal/domain/news"
tagdomain "legalgo-BE-go/internal/domain/tag"
"gorm.io/gorm/clause"
)
func (a *accessor) Update(spec newsdomain.News) error {
tx := a.db.Begin()
if err := tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "id"}},
DoUpdates: clause.AssignmentColumns([]string{
"title",
"content",
"featured_image",
"is_premium",
"slug",
"author_id",
"live_at",
"updated_at",
}),
}).Select(
"title",
"content",
"featured_image",
"is_premium",
"slug",
"author_id",
"live_at",
"updated_at",
).Save(&spec).Error; err != nil {
tx.Rollback()
return fmt.Errorf("failed to update news: %v", err)
}
tagsDeleted := make([]tagdomain.Tag, len(spec.Tags))
copy(tagsDeleted, spec.Tags)
if err := tx.Model(&spec).Association("Tags").Clear(); err != nil {
tx.Rollback()
return fmt.Errorf("failed to remove previous tags: %v", err)
}
if err := tx.Model(&spec).Association("Tags").Append(tagsDeleted); err != nil {
tx.Rollback()
return fmt.Errorf("failed to add tags: %v", err)
}
categoriesDeleted := make([]categorydomain.Category, len(spec.Categories))
copy(categoriesDeleted, spec.Categories)
if err := tx.Model(&spec).Association("Categories").Clear(); err != nil {
tx.Rollback()
return fmt.Errorf("failed to remove previous categories: %v", err)
}
if err := tx.Model(&spec).Association("Categories").Append(categoriesDeleted); err != nil {
tx.Rollback()
return fmt.Errorf("failed to add categories: %v", err)
}
if err := tx.Commit().Error; err != nil {
return fmt.Errorf("failed to commit transaction: %v", err)
}
return nil
}
+86
View File
@@ -0,0 +1,86 @@
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)
}
func (r *OssRepositoryImpl) DeleteObject(ctx context.Context, fileName string) error {
if fileName == "" {
return fmt.Errorf("file name is not provided")
}
_, err := r.s3.DeleteObject(&s3.DeleteObjectInput{
Key: aws.String(fileName),
})
if err != nil {
return fmt.Errorf("failed to delete object %s from bucket: %v", fileName, err)
}
return nil
}
+11
View File
@@ -0,0 +1,11 @@
package oss
import (
"context"
)
type OSSRepository interface {
UploadFile(ctx context.Context, fileName string, fileContent []byte) (fileUrl string, err error)
GetPublicURL(fileName string) string
DeleteObject(ctx context.Context, fileName string) error
}
+16 -13
View File
@@ -1,8 +1,9 @@
package redisaccessor
import (
"crypto/tls"
"fmt"
"os"
"legalgo-BE-go/config"
"github.com/redis/go-redis/v9"
)
@@ -13,20 +14,22 @@ 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
)
func New(cfg *config.Config) *redis.Client {
addr := fmt.Sprintf("%s:%s", cfg.Redis.Host, cfg.Redis.Port)
redisClient = redis.NewClient(&redis.Options{
Username: username,
options := &redis.Options{
Addr: addr,
Password: password,
DB: db,
})
Password: cfg.Redis.Password,
DB: cfg.Redis.DB,
}
if cfg.Redis.Username != "" {
options.Username = cfg.Redis.Username
}
if cfg.Redis.SSL {
options.TLSConfig = &tls.Config{}
}
redisClient = redis.NewClient(options)
return redisClient
}
+13
View File
@@ -0,0 +1,13 @@
package staffrepository
import (
staffdomain "legalgo-BE-go/internal/domain/staff"
)
func (ur *accessor) Create(spec staffdomain.Staff) error {
if err := ur.db.Create(&spec).Error; err != nil {
return err
}
return nil
}
-11
View File
@@ -1,11 +0,0 @@
package staffrepository
import authdomain "github.com/ardeman/project-legalgo-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
}
+27
View File
@@ -0,0 +1,27 @@
package staffrepository
import (
"errors"
"fmt"
staffdomain "legalgo-BE-go/internal/domain/staff"
"gorm.io/gorm"
)
func (sr *accessor) GetStaffByEmail(email string) (*staffdomain.Staff, error) {
var staff staffdomain.Staff
if email == "" {
return nil, fmt.Errorf("email is required")
}
if err := sr.db.First(&staff, "email = ?", email).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("staff not found")
}
return nil, err
}
return &staff, nil
}
+26
View File
@@ -0,0 +1,26 @@
package staffrepository
import (
"errors"
"fmt"
staffdomain "legalgo-BE-go/internal/domain/staff"
"gorm.io/gorm"
)
func (sr *accessor) GetStaffByID(ID string) (*staffdomain.Staff, error) {
var staff staffdomain.Staff
if ID == "" {
return nil, fmt.Errorf("id is required")
}
if err := sr.db.First(&staff, "id = ? ", ID).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("staff not found")
}
return nil, err
}
return &staff, nil
}
+6 -18
View File
@@ -1,25 +1,13 @@
package staffrepository
import (
"errors"
import staffdomain "legalgo-BE-go/internal/domain/staff"
authdomain "github.com/ardeman/project-legalgo-go/internal/domain/auth"
"gorm.io/gorm"
)
func (a *accessor) GetStaffs() ([]staffdomain.StaffProfile, error) {
var staffs []staffdomain.StaffProfile
func (sr *StaffRepository) GetStaffByEmail(email string) (*authdomain.Staff, error) {
var staff authdomain.Staff
if email == "" {
return nil, errors.New("email is empty")
if err := a.db.Table("staffs").Find(&staffs).Error; err != nil {
return staffs, err
}
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
return staffs, nil
}
+28
View File
@@ -0,0 +1,28 @@
package staffrepository
import userdomain "legalgo-BE-go/internal/domain/user"
func (a *accessor) GetUsers() ([]userdomain.UserProfile, error) {
var usersRaw []userdomain.User
if err := a.db.
Preload("Subscribe").
Preload("Subscribe.SubscribePlan").
Find(&usersRaw).
Error; err != nil {
return nil, err
}
users := []userdomain.UserProfile{}
for _, user := range usersRaw {
users = append(users, userdomain.UserProfile{
ID: user.ID,
Email: user.Email,
Phone: user.Phone,
Subscribe: user.Subscribe,
CreatedAt: user.CreatedAt,
})
}
return users, nil
}
+14 -9
View File
@@ -1,19 +1,24 @@
package staffrepository
import (
"github.com/ardeman/project-legalgo-go/database"
authdomain "github.com/ardeman/project-legalgo-go/internal/domain/auth"
"legalgo-BE-go/database"
staffdomain "legalgo-BE-go/internal/domain/staff"
userdomain "legalgo-BE-go/internal/domain/user"
)
type StaffRepository struct {
DB *database.DB
type accessor struct {
db *database.DB
}
type StaffIntf interface {
GetStaffByEmail(string) (*authdomain.Staff, error)
Create(*authdomain.Staff) (*authdomain.Staff, error)
type Staff interface {
GetStaffByEmail(string) (*staffdomain.Staff, error)
GetStaffByID(string) (*staffdomain.Staff, error)
GetUsers() ([]userdomain.UserProfile, error)
GetStaffs() ([]staffdomain.StaffProfile, error)
Create(staffdomain.Staff) error
Update(staffdomain.Staff) error
}
func New(db *database.DB) StaffIntf {
return &StaffRepository{db}
func New(db *database.DB) Staff {
return &accessor{db}
}
+18
View File
@@ -0,0 +1,18 @@
package staffrepository
import (
staffdomain "legalgo-BE-go/internal/domain/staff"
)
func (ur *accessor) Update(spec staffdomain.Staff) error {
// val, err := utils.StructToMap(spec)
// if err != nil {
// return err
// }
if err := ur.db.Model(&staffdomain.Staff{}).Where("id = ?", spec.ID).Updates(spec).Error; err != nil {
return err
}
return nil
}
+6 -5
View File
@@ -1,19 +1,20 @@
package subscriberepository
import (
subscribedomain "github.com/ardeman/project-legalgo-go/internal/domain/subscribe"
subscribedomain "legalgo-BE-go/internal/domain/subscribe"
"github.com/google/uuid"
)
func (s *SubsAccs) Create(subsPlanId string) (string, error) {
func (s *accessor) Create(subsPlanId string) (string, error) {
spec := &subscribedomain.Subscribe{
ID: uuid.New(),
ID: uuid.NewString(),
SubscribePlanID: subsPlanId,
}
if err := s.DB.Create(&spec).Error; err != nil {
if err := s.db.Create(&spec).Error; err != nil {
return "", err
}
return spec.ID.String(), nil
return spec.ID, nil
}
+23
View File
@@ -0,0 +1,23 @@
package subscriberepository
import (
"errors"
"fmt"
subscribedomain "legalgo-BE-go/internal/domain/subscribe"
"gorm.io/gorm"
)
func (s *accessor) GetByID(id string) (subscribedomain.Subscribe, error) {
var subscribe subscribedomain.Subscribe
if err := s.db.First(&subscribe, "id = ?", id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return subscribe, fmt.Errorf("subscribe data not found: %v", err)
}
return subscribe, err
}
return subscribe, nil
}
+11 -6
View File
@@ -1,15 +1,20 @@
package subscriberepository
import "github.com/ardeman/project-legalgo-go/database"
import (
"legalgo-BE-go/database"
subscribedomain "legalgo-BE-go/internal/domain/subscribe"
)
type SubsAccs struct {
DB *database.DB
type accessor struct {
db *database.DB
}
type SubsIntf interface {
type Subscribe interface {
Create(string) (string, error)
GetByID(string) (subscribedomain.Subscribe, error)
Update(subscribedomain.Subscribe) error
}
func New(db *database.DB) SubsIntf {
return &SubsAccs{db}
func New(db *database.DB) Subscribe {
return &accessor{db}
}
+19
View File
@@ -0,0 +1,19 @@
package subscriberepository
import (
"fmt"
subscribedomain "legalgo-BE-go/internal/domain/subscribe"
"gorm.io/gorm/clause"
)
func (a *accessor) Update(spec subscribedomain.Subscribe) error {
if err := a.db.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "id"}},
DoUpdates: clause.AssignmentColumns([]string{"status", "subscribe_plan_id", "start_date"}),
}).Create(&spec).Error; err != nil {
return fmt.Errorf("failed to update status: %v", err)
}
return nil
}
@@ -0,0 +1,13 @@
package subscribeplanrepository
import (
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
)
func (s *accessor) Create(spec subscribeplandomain.SubscribePlan) error {
if err := s.db.Create(&spec).Error; err != nil {
return err
}
return nil
}
@@ -0,0 +1,30 @@
package subscribeplanrepository
import (
"fmt"
"legalgo-BE-go/database"
subscribedomain "legalgo-BE-go/internal/domain/subscribe"
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
)
func (a *accessor) Delete(id string) error {
var subsPlan database.SubscribePlan
var basicPlan subscribeplandomain.SubscribePlan
if err := a.db.First(&basicPlan, "code = ?", "basic").Error; err != nil {
return fmt.Errorf("failed to find basic plan: %v", err)
}
if err := a.db.
Model(&subscribedomain.Subscribe{}).
Where("subscribe_plan_id = ?", id).
Update("subscribe_plan_id", basicPlan.ID).Error; err != nil {
return fmt.Errorf("failed to change subscribe plan: %v", err)
}
if err := a.db.Delete(&subsPlan, "id = ?", id).Error; err != nil {
return fmt.Errorf("failed to delete subscribe plan %s : %v", id, err)
}
return nil
}
@@ -0,0 +1,15 @@
package subscribeplanrepository
import (
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
)
func (s *accessor) 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,22 @@
package subscribeplanrepository
import (
"errors"
"fmt"
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
"gorm.io/gorm"
)
func (s *accessor) 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, fmt.Errorf("subscribe plan not found")
}
return subscribePlan, err
}
return subscribePlan, nil
}
@@ -0,0 +1,22 @@
package subscribeplanrepository
import (
"legalgo-BE-go/database"
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
"github.com/google/uuid"
)
func (s *accessor) GetDefault() (*subscribeplandomain.SubscribePlan, error) {
var subscribePlan *subscribeplandomain.SubscribePlan
if err := s.db.First(&subscribePlan, "code = ?", "basic").Error; err != nil {
s.db.Create(&database.SubscribePlan{
ID: uuid.NewString(),
Code: "basic",
Name: "Basic",
})
}
return subscribePlan, nil
}
+25
View File
@@ -0,0 +1,25 @@
package subscribeplanrepository
import (
"legalgo-BE-go/database"
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
)
type accessor struct {
db *database.DB
}
type SubscribePlan interface {
Create(subscribeplandomain.SubscribePlan) error
GetAll() ([]subscribeplandomain.SubscribePlan, error)
GetByID(string) (*subscribeplandomain.SubscribePlan, error)
GetDefault() (*subscribeplandomain.SubscribePlan, error)
Update(subscribeplandomain.SubscribePlan) error
Delete(string) error
}
func New(
db *database.DB,
) SubscribePlan {
return &accessor{db}
}
@@ -0,0 +1,33 @@
package subscribeplanrepository
import (
"fmt"
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
"gorm.io/gorm/clause"
)
func (a *accessor) Update(spec subscribeplandomain.SubscribePlan) error {
if err := a.db.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "id"}},
DoUpdates: clause.AssignmentColumns([]string{
"name",
"code",
"length",
"price",
"status",
"updated_at",
}),
}).Select(
"name",
"code",
"length",
"price",
"status",
"updated_at",
).Save(&spec).Error; err != nil {
return fmt.Errorf("failed to update tag: %v", err)
}
return nil
}
-20
View File
@@ -1,20 +0,0 @@
package subscribeplanrepository
import (
subscribeplandomain "github.com/ardeman/project-legalgo-go/internal/domain/subscribe_plan"
"github.com/google/uuid"
)
func (s *SubsPlan) Create(spec subscribeplandomain.SubscribePlanReq) error {
data := &subscribeplandomain.SubscribePlan{
ID: uuid.New(),
Code: spec.Code,
Name: spec.Name,
}
if err := s.DB.Create(&data).Error; err != nil {
return err
}
return nil
}
@@ -1,15 +0,0 @@
package subscribeplanrepository
import (
subscribeplandomain "github.com/ardeman/project-legalgo-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
}
-21
View File
@@ -1,21 +0,0 @@
package subscribeplanrepository
import (
"github.com/ardeman/project-legalgo-go/database"
subscribeplandomain "github.com/ardeman/project-legalgo-go/internal/domain/subscribe_plan"
)
type SubsPlan struct {
DB *database.DB
}
type SubsPlanIntf interface {
Create(subscribeplandomain.SubscribePlanReq) error
GetAll() ([]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
}
+24
View File
@@ -0,0 +1,24 @@
package tagrepository
import (
"fmt"
"legalgo-BE-go/database"
)
func (a *accessor) Delete(id string) error {
var tag database.Tag
if err := a.db.First(&tag, "id = ?", id).Error; err != nil {
return fmt.Errorf("failed to find tag: %v", err)
}
if err := a.db.Model(&tag).Association("News").Clear(); err != nil {
return fmt.Errorf("failed to remove tag association: %v", err)
}
if err := a.db.Delete(&tag).Error; err != nil {
return fmt.Errorf("failed to delete tag %s : %v", id, 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
}
+17
View File
@@ -0,0 +1,17 @@
package tagrepository
import tagdomain "legalgo-BE-go/internal/domain/tag"
func (a *accessor) GetIDsByCodes(codes []string) ([]string, error) {
var tags []string
if err := a.db.
Model(&tagdomain.Tag{}).
Select("id").Where("code IN ?", codes).
Pluck("id", &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
}
+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
GetAll() ([]tagdomain.Tag, error)
GetByIDs([]string) ([]tagdomain.Tag, error)
GetIDsByCodes([]string) ([]string, error)
Update(tagdomain.Tag) error
Delete(string) error
}
func New(
db *database.DB,
) TagAccessor {
return &accessor{db}
}
+23
View File
@@ -0,0 +1,23 @@
package tagrepository
import (
"fmt"
tagdomain "legalgo-BE-go/internal/domain/tag"
"gorm.io/gorm/clause"
)
func (a *accessor) Update(spec tagdomain.Tag) error {
if err := a.db.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "id"}},
DoUpdates: clause.AssignmentColumns([]string{
"name",
"code",
"updated_at",
}),
}).Select("name", "code", "updated_at").Save(&spec).Error; err != nil {
return fmt.Errorf("failed to update tag: %v", err)
}
return nil
}
+13
View File
@@ -0,0 +1,13 @@
package userrepository
import (
userdomain "legalgo-BE-go/internal/domain/user"
)
func (ur *accessor) CreateUser(spec userdomain.User) error {
if err := ur.db.Create(&spec).Error; err != nil {
return err
}
return nil
}
@@ -0,0 +1,26 @@
package userrepository
import (
"errors"
"fmt"
userdomain "legalgo-BE-go/internal/domain/user"
"gorm.io/gorm"
)
func (ur *accessor) GetUserByEmail(email string) (*userdomain.User, error) {
var user *userdomain.User
if email == "" {
return nil, fmt.Errorf("email is empty")
}
if err := ur.db.First(&user, "email = ?", email).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("user not found")
}
return nil, err
}
return user, nil
}
+23
View File
@@ -0,0 +1,23 @@
package userrepository
import (
"fmt"
userdomain "legalgo-BE-go/internal/domain/user"
)
func (ur *accessor) GetUserByID(id string) (*userdomain.User, error) {
var user userdomain.User
if id == "" {
return nil, fmt.Errorf("id is empty")
}
if err := ur.db.
Preload("Subscribe").
Preload("Subscribe.SubscribePlan").
First(&user, "id = ?", id).Error; err != nil {
return nil, err
}
return &user, nil
}
@@ -0,0 +1,32 @@
package userrepository
import (
"fmt"
userdomain "legalgo-BE-go/internal/domain/user"
)
func (ur *accessor) GetUserProfile(id string) (*userdomain.UserProfile, error) {
var user *userdomain.User
if id == "" {
return nil, fmt.Errorf("email is empty")
}
if err := ur.db.
Preload("Subscribe").
Preload("Subscribe.SubscribePlan").
First(&user, "id = ?", id).
Error; err != nil {
return nil, err
}
userProfile := &userdomain.UserProfile{
ID: user.ID,
Email: user.Email,
Phone: user.Phone,
Subscribe: user.Subscribe,
CreatedAt: user.CreatedAt,
}
return userProfile, nil
}
+23
View File
@@ -0,0 +1,23 @@
package userrepository
import (
"legalgo-BE-go/database"
userdomain "legalgo-BE-go/internal/domain/user"
)
type accessor struct {
db *database.DB
}
type User interface {
GetUserByEmail(string) (*userdomain.User, error)
GetUserByID(string) (*userdomain.User, error)
GetUserProfile(string) (*userdomain.UserProfile, error)
CreateUser(userdomain.User) error
}
func New(
db *database.DB,
) User {
return &accessor{db}
}
@@ -1,13 +0,0 @@
package userrepository
import (
authdomain "github.com/ardeman/project-legalgo-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
}

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