├── .deepsource.toml ├── .drone.yml ├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── bug_report_zh.md │ ├── proposal.md │ ├── proposal_zh.md │ ├── questions.md │ └── questions_zh.md ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── CONTRIBUTING_CN.md ├── DONATION.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── README_CN.md ├── SECURITY.md ├── adapter ├── adapter.go ├── beego │ └── beego.go ├── beego2 │ └── beego2.go ├── buffalo │ └── buffalo.go ├── chi │ └── chi.go ├── echo │ └── echo.go ├── fasthttp │ └── fasthttp.go ├── gear │ └── gear.go ├── gf │ └── gf.go ├── gf2 │ └── gf2.go ├── gin │ └── gin.go ├── gofiber │ └── gofiber.go ├── gorilla │ └── gorilla.go ├── iris │ └── iris.go └── nethttp │ └── nethttp.go ├── context ├── context.go ├── context_test.go └── trie.go ├── data ├── admin.db ├── admin.mssql ├── admin.pgsql ├── admin.sql └── migrations │ ├── admin_2020_04_14_100427_ms.sql │ ├── admin_2020_04_14_100427_mysql.sql │ ├── admin_2020_04_14_100427_postgres.sql │ ├── admin_2020_04_14_100427_sqlite.sql │ ├── admin_2020_08_04_092427_ms.sql │ ├── admin_2020_08_04_092427_mysql.sql │ ├── admin_2020_08_04_092427_postgres.sql │ └── admin_2020_08_04_092427_sqlite.sql ├── docker-compose.yml ├── engine └── engine.go ├── examples ├── beego │ └── main.go ├── beego2 │ └── main.go ├── buffalo │ └── main.go ├── chi │ └── main.go ├── datamodel │ ├── authors.go │ ├── bootstrap.go │ ├── config.json │ ├── content.go │ ├── goadmin_super_users.go │ ├── mysql_types.go │ ├── posts.go │ ├── tables.go │ └── user.go ├── echo │ └── main.go ├── fasthttp │ └── main.go ├── gear │ └── main.go ├── gf │ └── main.go ├── gf2 │ └── main.go ├── gin │ └── main.go ├── gofiber │ └── main.go ├── gorilla │ └── main.go ├── iris │ └── main.go └── nethttp │ └── main.go ├── go.mod ├── go.sum ├── modules ├── auth │ ├── auth.go │ ├── auth_test.go │ ├── middleware.go │ ├── middleware_test.go │ └── session.go ├── collection │ ├── collection.go │ └── collection_test.go ├── config │ ├── config.go │ ├── config.ini │ ├── config.yaml │ └── config_test.go ├── constant │ └── constant.go ├── db │ ├── base.go │ ├── connection.go │ ├── converter.go │ ├── dialect │ │ ├── common.go │ │ ├── dialect.go │ │ ├── mssql.go │ │ ├── mysql.go │ │ ├── oceanbase.go │ │ ├── postgresql.go │ │ └── sqlite.go │ ├── drivers │ │ ├── mssql │ │ │ └── mssql.go │ │ ├── mysql │ │ │ └── mysql.go │ │ ├── oceanbase │ │ │ └── oceanbase.go │ │ ├── postgres │ │ │ └── postgres.go │ │ └── sqlite │ │ │ └── sqlite.go │ ├── mssql.go │ ├── mysql.go │ ├── oceanbase.go │ ├── performer.go │ ├── postgresql.go │ ├── sqlite.go │ ├── statement.go │ ├── statement_mssql_test.go │ ├── statement_mysql_test.go │ ├── statement_postgresql_test.go │ ├── statement_sqlite_test.go │ ├── statement_test.go │ ├── types.go │ └── types_test.go ├── errors │ └── error.go ├── file │ ├── file.go │ └── local.go ├── language │ ├── cn.go │ ├── en.go │ ├── jp.go │ ├── language.go │ ├── language_test.go │ ├── pt-BR.go │ ├── ru.go │ └── tc.go ├── logger │ ├── logger.go │ └── logger_test.go ├── menu │ ├── menu.go │ └── menu_test.go ├── page │ └── page.go ├── remote_server │ └── remote_server.go ├── service │ └── service.go ├── system │ ├── application.go │ └── version.go ├── trace │ └── trace.go ├── ui │ └── ui.go └── utils │ ├── utils.go │ └── utils_test.go ├── plugins ├── admin │ ├── admin.go │ ├── controller │ │ ├── Update.go │ │ ├── api_create.go │ │ ├── api_detail.go │ │ ├── api_list.go │ │ ├── api_update.go │ │ ├── auth.go │ │ ├── common.go │ │ ├── common_test.go │ │ ├── delete.go │ │ ├── detail.go │ │ ├── edit.go │ │ ├── handler.go │ │ ├── install.go │ │ ├── menu.go │ │ ├── new.go │ │ ├── operation.go │ │ ├── plugins.go │ │ ├── plugins_tmpl.go │ │ ├── show.go │ │ └── system.go │ ├── data │ │ ├── mysql │ │ │ └── admin.sql │ │ └── sqlite │ │ │ └── admin.db │ ├── models │ │ ├── base.go │ │ ├── menu.go │ │ ├── operation_log.go │ │ ├── permission.go │ │ ├── role.go │ │ ├── site.go │ │ └── user.go │ ├── modules │ │ ├── captcha │ │ │ └── captcha.go │ │ ├── constant │ │ │ └── constant.go │ │ ├── form │ │ │ └── form.go │ │ ├── guard │ │ │ ├── delete.go │ │ │ ├── edit.go │ │ │ ├── export.go │ │ │ ├── guard.go │ │ │ ├── menu_delete.go │ │ │ ├── menu_edit.go │ │ │ ├── menu_new.go │ │ │ ├── new.go │ │ │ ├── server_login.go │ │ │ └── update.go │ │ ├── helper.go │ │ ├── helper_test.go │ │ ├── paginator │ │ │ ├── paginator.go │ │ │ └── paginator_test.go │ │ ├── parameter │ │ │ ├── parameter.go │ │ │ └── parameter_test.go │ │ ├── response │ │ │ └── response.go │ │ ├── table │ │ │ ├── config.go │ │ │ ├── default.go │ │ │ ├── default_test.go │ │ │ ├── generators.go │ │ │ ├── table.go │ │ │ ├── tmpl.go │ │ │ └── tmpl │ │ │ │ ├── choose_table_ajax.tmpl │ │ │ │ └── generator.tmpl │ │ └── tools │ │ │ ├── generator.go │ │ │ └── template.go │ └── router.go ├── example │ ├── controller.go │ ├── example.go │ ├── go_plugin │ │ ├── Makefile │ │ └── main.go │ └── router.go ├── plugins.go └── plugins_test.go ├── template ├── chartjs │ ├── assets.go │ ├── assets │ │ └── chart.min.js │ ├── assets_list.go │ ├── bar.go │ ├── chart.go │ ├── chartjs.tmpl │ ├── line.go │ ├── pie.go │ ├── radar.go │ └── template.go ├── color │ └── color.go ├── components │ ├── alert.go │ ├── base.go │ ├── box.go │ ├── button.go │ ├── col.go │ ├── composer.go │ ├── form.go │ ├── image.go │ ├── label.go │ ├── link.go │ ├── paninator.go │ ├── popup.go │ ├── product.go │ ├── row.go │ ├── table.go │ ├── tabs.go │ ├── tree.go │ └── treeview.go ├── icon │ └── icon.go ├── installation │ ├── Makefile │ ├── assets.go │ ├── assets │ │ ├── installation │ │ │ └── dist │ │ │ │ ├── all.min.css │ │ │ │ ├── all.min.js │ │ │ │ └── respond.min.js │ │ └── src │ │ │ ├── css │ │ │ ├── font-awesome.min.css │ │ │ ├── main.css │ │ │ └── noscript.css │ │ │ ├── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ │ │ └── js │ │ │ ├── jquery.min.js │ │ │ ├── main.js │ │ │ └── skel.min.js │ ├── assets_list.go │ ├── installation.go │ ├── installation.tmpl │ └── template.go ├── login │ ├── Makefile │ ├── assets.go │ ├── assets │ │ └── src │ │ │ ├── css │ │ │ ├── 0_font.css │ │ │ ├── 1_bootstrap.min.css │ │ │ ├── 2_animate.css │ │ │ └── 3_style.css │ │ │ └── js │ │ │ ├── combine │ │ │ ├── 1_jquery.min.js │ │ │ ├── 2_bootstrap.min.js │ │ │ ├── 3_particles.js │ │ │ └── 4_main.js │ │ │ └── respond.min.js │ ├── assets_list.go │ ├── login.go │ ├── login.tmpl │ └── template.go ├── template.go ├── template_test.go └── types │ ├── action │ ├── ajax.go │ ├── base.go │ ├── event.go │ ├── fieldfilter.go │ ├── file_upload.go │ ├── jump.go │ ├── jump_selectbox.go │ └── popup.go │ ├── button.go │ ├── components.go │ ├── display.go │ ├── display │ ├── base.go │ ├── bool.go │ ├── carousel.go │ ├── copy.go │ ├── date.go │ ├── dot.go │ ├── downloadable.go │ ├── filesize.go │ ├── icon.go │ ├── image.go │ ├── label.go │ ├── link.go │ ├── loading.go │ ├── progressbar.go │ └── qrcode.go │ ├── display_test.go │ ├── form.go │ ├── form │ ├── form.go │ ├── form_test.go │ └── select │ │ └── select.go │ ├── form_test.go │ ├── info.go │ ├── info_test.go │ ├── operators.go │ ├── page.go │ ├── select.go │ ├── size.go │ ├── table │ └── table.go │ ├── tmpl.go │ └── tmpls │ ├── choose.tmpl │ ├── choose_ajax.tmpl │ ├── choose_custom.tmpl │ ├── choose_disable.tmpl │ ├── choose_hide.tmpl │ ├── choose_map.tmpl │ └── choose_show.tmpl └── tests ├── common ├── api.go ├── auth.go ├── checklist.md ├── common.go ├── config.json ├── config_ms.json ├── config_pg.json ├── config_sqlite.json ├── external.go ├── manager.go ├── menu.go ├── normal.go ├── operation_log.go ├── permission.go └── role.go ├── data ├── admin.db ├── admin.sql ├── admin_ms.bak ├── admin_ms.sql └── admin_pg.sql ├── frameworks ├── beego │ ├── beego.go │ └── beego_test.go ├── beego2 │ ├── beego.go │ └── beego_test.go ├── buffalo │ ├── buffalo.go │ └── buffalo_test.go ├── chi │ ├── chi.go │ └── chi_test.go ├── echo │ ├── echo.go │ └── echo_test.go ├── fasthttp │ ├── fasthttp.go │ └── fasthttp_test.go ├── gear │ ├── gear.go │ └── gear_test.go ├── gf │ ├── gf.go │ └── gf_test.go ├── gf2 │ ├── gf.go │ └── gf_test.go ├── gin │ ├── gin.go │ └── gin_test.go ├── gofiber │ ├── gofiber.go │ └── gofiber_test.go ├── gorilla │ ├── gorilla.go │ └── gorilla_test.go ├── iris │ ├── iris.go │ └── iris_test.go └── nethttp │ ├── nethttp.go │ └── nethttp_test.go ├── tables ├── authors.go ├── content.go ├── external.go ├── posts.go ├── tables.go └── user.go ├── test.go ├── test_test.go └── web ├── README_CN.md ├── config.json ├── page.go ├── test.go └── web_test.go /.deepsource.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[analyzers]] 4 | name = "go" 5 | enabled = true 6 | 7 | [analyzers.meta] 8 | import_paths = ["github.com/GoAdminGroup/go-admin"] 9 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: 4 | patreon: 5 | open_collective: go-admin 6 | ko_fi: 7 | tidelift: 8 | community_bridge: 9 | liberapay: 10 | issuehunt: 11 | otechie: 12 | custom: ['https://www.paypal.me/cg80333'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: "\U0001F41Bbug" 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Bug Description [describe the bug in detail] 11 | 12 | ### How to reproduce [describe the steps how to reproduce the bug] 13 | 14 | ### Expect [describe your expect result] 15 | 16 | ### Reproduction code [here to show your codes or examples] 17 | 18 | ### Versions 19 | 20 | - GoAdmin version: [e.g. 1.0.0] 21 | - golang version 22 | - Browser 23 | - OS [e.g. mac OS] 24 | 25 | ### Others [screenshots or others info here] 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report_zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug 报告 3 | about: 提交bug帮助我们修复 4 | title: "[BUG]" 5 | labels: "\U0001F41Bbug" 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### bug 描述 [详细地描述 bug,让大家都能理解] 11 | 12 | ### 复现步骤 [清晰描述复现步骤,让别人也能看到问题] 13 | 14 | ### 期望结果 [描述你原本期望看到的结果] 15 | 16 | ### 复现代码 [提供可复现的代码,仓库,或线上示例] 17 | 18 | ### 版本信息: 19 | 20 | - GoAdmin 版本: 21 | - golang 版本: 22 | - 浏览器环境: 23 | - 开发环境: 24 | 25 | ### 其他信息 [如截图等其他信息可以贴在这里] 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/proposal.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Proposal 3 | about: Any advice for GoAdmin 4 | title: "[Proposal]" 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Description [describe your advice] 11 | 12 | ### Solution [if any solutions, describe here] 13 | 14 | ### Others [screenshots and other info] 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/proposal_zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 功能需求 3 | about: 对 GoAdmin 的需求或建议 4 | title: "[Proposal]" 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### 需求描述 [详细地描述需求,让大家都能理解] 11 | 12 | ### 解决方案 [如果你有解决方案,在这里清晰地阐述] 13 | 14 | ### 其他信息 [如截图等其他信息可以贴在这里] 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/questions.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Questions 3 | about: Any questions when using GoAdmin 4 | title: "[Question]" 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Description [describe your questions] 11 | 12 | ### Example code [If you have any code info] 13 | 14 | ### Others [screenshots or other info] 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/questions_zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 疑问或需要帮助 ❓ 3 | about: 关于 GoAdmin 的问题 4 | title: "[Question]" 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### 问题描述 [详细地描述问题,让大家都能理解] 11 | 12 | ### 示例代码 [如果有必要,展示代码,线上示例,或仓库] 13 | 14 | ### 其他信息 [如截图等其他信息可以贴在这里] 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .vscode 3 | .DS_Store 4 | demo/config.json 5 | demo/config 6 | demo/deploy.yml 7 | demo/hosts 8 | demo/go-admin 9 | demo/Makefile 10 | demo/deploy.retry 11 | vendor/** 12 | !vendor/vendor.json 13 | logs 14 | adm/build 15 | template/login/assets/login 16 | uploads -------------------------------------------------------------------------------- /CONTRIBUTING_CN.md: -------------------------------------------------------------------------------- 1 | # 贡献 2 | 3 | 如果你想要对项目作出贡献,却不知道怎么做,下面有一些帮助: 4 | 5 | * 翻译 6 | * README.md 7 | * [docs](https://github.com/GoAdminGroup/docs/issues/1) 8 | * 寻找BUG 9 | * 寻找安全问题 10 | * 主题和插件 11 | 12 | 在这里:[功能规划](https://github.com/GoAdminGroup/go-admin/projects/3) 可以获得更多信息。 13 | 14 | 你也可以看一下所有开放的issues,从这里去入手: 15 | 16 | https://github.com/search?q=org%3AGoAdminGroup+is%3Aopen+is%3Aissue+archived%3Afalse&type=Issues 17 | 18 | ## 如何做贡献 19 | 20 | GoAdmin 使用 GitHub 来管理项目代码: 21 | 22 | - 如果你发现一些微不足道的fix或者功能增加,直接提pr即可; 23 | - 如果你有一些提议,那么你可以先开一个issue进行讨论; 24 | 25 | 然后,你需要fork远程的master分支到你本地 **\$GOPATH**/src/github.com/GoAdminGroup/go-admin : 26 | 27 | ```bash 28 | 29 | $ go get github.com/GoAdminGroup/go-admin 30 | $ cd $GOPATH/src/github.com/GoAdminGroup/go-admin # GOPATH is $HOME/go by default. 31 | 32 | $ git remote add 33 | ``` 34 | 35 | 在你提交代码之前,记得执行下面这个命令: 36 | 37 | ``` 38 | make test 39 | ``` 40 | 41 | 看根目录下的```Makefile```获得更多信息。 42 | 43 | 注意了: `go get` 返回 `package github.com/GoAdminGroup/go-admin: no Go files in /go/src/github.com/GoAdminGroup/go-admin` 是正常的。 44 | 45 | ### 依赖管理 46 | 47 | 我们使用 [Go modules](https://golang.org/cmd/go/#hdr-Modules__module_versions__and_more) 来管理依赖。 48 | 这需要 golang 版本大于1.11,以及安装了 git 49 | 50 | 要增加或更新依赖,就使用 `go get` 命令: 51 | 52 | ```bash 53 | # Pick the latest tagged release. 54 | go get example.com/some/module/pkg 55 | 56 | # Pick a specific version. 57 | go get example.com/some/module/pkg@vX.Y.Z 58 | ``` 59 | 60 | 整理好 `go.mod` 和 `go.sum`: 61 | 62 | ```bash 63 | go mod tidy 64 | go mod vendor 65 | git add go.mod go.sum vendor 66 | git commit 67 | ``` 68 | 69 | 直接提交 `go.mod` and `go.sum` 的修改。 70 | 71 | # 赞助 72 | 73 | 你可以捐助或参与众筹来帮助我们维护服务器费用,以及提供一些奖金资助项目发展。 74 | 75 | * **Support on [Open Collective](https://opencollective.com/go-admin)** 76 | * Donate via [PayPal](https://paypal.me/cg80333) 77 | 78 | # 成员 79 | 80 | 如果你已经是GoAdmin的官方开发组成员: 81 | 82 | * [Discussions](http://forum.go-admin.cn) 83 | * [Tasks](https://github.com/GoAdminGroup/go-admin/projects) 84 | * [Chat](https://t.me/joinchat/NlyH6Bch2QARZkArithKvg) -------------------------------------------------------------------------------- /DONATION.md: -------------------------------------------------------------------------------- 1 | # Donation List 捐赠名单(排名不分先后) -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # This file describes the standard way to build GoAdmin develop env image, and using container 2 | # 3 | # Usage: 4 | # 5 | # # Assemble the code dev environment, get related database tools in docker-compose.yml, It is slow the first time. 6 | # docker build -t goadmin:1.0 . 7 | # 8 | # # Mount your source code to container for quick developing: 9 | # docker run -v `pwd`:/home/goadmin --name -d goadmin:1.0 10 | # docker exec -it goadmin /bin/bash 11 | # # if your local code has been changed ,you can restart the container to take effect 12 | # docker restart goadmin 13 | # 14 | 15 | FROM golang:latest 16 | MAINTAINER josingcjx 17 | COPY . /home/goadmin 18 | ENV GOPATH=$GOPATH:/home/goadmin/ GOPROXY=https://mirrors.aliyun.com/goproxy,https://goproxy.cn,direct 19 | RUN apt-get update --fix-missing && \ 20 | apt-get install -y zip vim postgresql mysql-common default-mysql-server && \ 21 | tar -C / -xvf /home/goadmin/tools/godependacy.tgz 22 | #if install dependacy tools failed, you can copy local's to remote 23 | #mkdir -p /go/bin && \ 24 | #mv /home/goadmin/tools/{gotest,goimports,golint,golangci-lint,adm} /go/bin 25 | #go get golang.org/x/tools/cmd/goimports && \ 26 | #go get github.com/rakyll/gotest && \ 27 | #go get -u golang.org/x/lint/golint && \ 28 | #go install github.com/GoAdminGroup/adm@latest && \ 29 | #go get -u github.com/golangci/golangci-lint/cmd/golangci-lint 30 | WORKDIR /home/goadmin -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | Please report security issues to `chg80333@gmail.com` -------------------------------------------------------------------------------- /data/admin.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/go-admin/cd8748f96e19ce3c4bf437520542b097899fc16e/data/admin.db -------------------------------------------------------------------------------- /data/migrations/admin_2020_04_14_100427_ms.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE[goadmin_site] ( 2 | [id] int identity(1,1) , 3 | [key] varchar(100) NOT NULL, 4 | [value] text NOT NULL, 5 | [state] tinyint NOT NULL DEFAULT 0, 6 | [description] varchar(3000) NOT NULL, 7 | [created_at] datetime NULL DEFAULT GETDATE(), 8 | [updated_at] datetime NULL DEFAULT GETDATE(), 9 | PRIMARY KEY ([id]), 10 | ) 11 | -------------------------------------------------------------------------------- /data/migrations/admin_2020_04_14_100427_mysql.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `goadmin_site` ( 2 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 3 | `key` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL, 4 | `value` longtext COLLATE utf8mb4_unicode_ci, 5 | `description` varchar(3000) COLLATE utf8mb4_unicode_ci DEFAULT NULL, 6 | `state` tinyint(3) unsigned NOT NULL DEFAULT '0', 7 | `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, 8 | `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, 9 | PRIMARY KEY (`id`) 10 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -------------------------------------------------------------------------------- /data/migrations/admin_2020_04_14_100427_postgres.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PostgreSQL database dump 3 | -- 4 | 5 | -- Dumped from database version 9.5.14 6 | -- Dumped by pg_dump version 10.5 7 | 8 | SET statement_timeout = 0; 9 | SET lock_timeout = 0; 10 | SET idle_in_transaction_session_timeout = 0; 11 | SET client_encoding = 'EUC_CN'; 12 | SET standard_conforming_strings = on; 13 | SELECT pg_catalog.set_config('search_path', '', false); 14 | SET check_function_bodies = false; 15 | SET client_min_messages = warning; 16 | SET row_security = off; 17 | 18 | SET default_tablespace = ''; 19 | 20 | SET default_with_oids = false; 21 | 22 | -- 23 | -- Name: goadmin_site_myid_seq; Type: SEQUENCE; Schema: public; Owner: postgres 24 | -- 25 | 26 | CREATE SEQUENCE public.goadmin_site_myid_seq 27 | START WITH 1 28 | INCREMENT BY 1 29 | NO MINVALUE 30 | MAXVALUE 99999999 31 | CACHE 1; 32 | 33 | ALTER TABLE public.goadmin_site_myid_seq OWNER TO postgres; 34 | 35 | -- 36 | -- Name: goadmin_site; Type: TABLE; Schema: public; Owner: postgres 37 | -- 38 | 39 | CREATE TABLE public.goadmin_site ( 40 | id integer DEFAULT nextval('public.goadmin_site_myid_seq'::regclass) NOT NULL, 41 | key character varying(100) NOT NULL, 42 | value text NOT NULL, 43 | type integer DEFAULT 0, 44 | description character varying(3000), 45 | state integer DEFAULT 0, 46 | created_at timestamp without time zone DEFAULT now(), 47 | updated_at timestamp without time zone DEFAULT now() 48 | ); 49 | 50 | 51 | ALTER TABLE public.goadmin_site OWNER TO postgres; 52 | 53 | -- 54 | -- Data for Name: goadmin_site; Type: TABLE DATA; Schema: public; Owner: postgres 55 | -- 56 | 57 | COPY public.goadmin_site (id, key, value, type, description, state, created_at, updated_at) FROM stdin; 58 | \. 59 | 60 | 61 | -- 62 | -- Name: goadmin_site goadmin_site_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres 63 | -- 64 | 65 | ALTER TABLE ONLY public.goadmin_site 66 | ADD CONSTRAINT goadmin_site_pkey PRIMARY KEY (id); 67 | 68 | 69 | -- 70 | -- PostgreSQL database dump complete 71 | -- 72 | 73 | -------------------------------------------------------------------------------- /data/migrations/admin_2020_04_14_100427_sqlite.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS "goadmin_site" ( 2 | `id` integer PRIMARY KEY autoincrement, 3 | `key` CHAR(100) COLLATE NOCASE NOT NULL, 4 | `value` text COLLATE NOCASE NOT NULL, 5 | `state` INT NOT NULL DEFAULT '0', 6 | `description` CHAR(3000) COLLATE NOCASE, 7 | `created_at` TIMESTAMP default CURRENT_TIMESTAMP, 8 | `updated_at` TIMESTAMP default CURRENT_TIMESTAMP 9 | ); -------------------------------------------------------------------------------- /data/migrations/admin_2020_08_04_092427_ms.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE goadmin_menu 2 | ADD plugin_name varchar(150) NOT NULL DEFAULT '', 3 | ADD uuid varchar(150) NOT NULL DEFAULT ''; -------------------------------------------------------------------------------- /data/migrations/admin_2020_08_04_092427_mysql.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE goadmin_menu 2 | ADD COLUMN `uuid` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', 3 | ADD COLUMN `plugin_name` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ''; -------------------------------------------------------------------------------- /data/migrations/admin_2020_08_04_092427_postgres.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE goadmin_menu 2 | ADD COLUMN plugin_name character varying(150) NOT NULL DEFAULT '', 3 | ADD COLUMN uuid character varying(150) NOT NULL DEFAULT ''; -------------------------------------------------------------------------------- /data/migrations/admin_2020_08_04_092427_sqlite.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE goadmin_menu 2 | ADD COLUMN `uuid` varchar(150) NOT NULL DEFAULT '', 3 | ADD COLUMN `plugin_name` varchar(150) NOT NULL DEFAULT ''; -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.3" 2 | services: 3 | mysql: 4 | image: mysql:5.6 5 | container_name: mysql 6 | ports: 7 | - "3306:3306" 8 | volumes: 9 | - mysql:/data 10 | networks: 11 | - goadmin 12 | environment: 13 | - MYSQL_ROOT_PASSWORD=goadmin 14 | postgres: 15 | image: postgres:latest 16 | container_name: postgres 17 | ports: 18 | - "5432:5432" 19 | volumes: 20 | - postgres:/data 21 | networks: 22 | - goadmin 23 | environment: 24 | - POSTGRES_PASSWORD=goadmin 25 | goadmin: 26 | image: josingcjx/goadmin:1.1 27 | tty: true 28 | container_name: goadmin 29 | volumes: 30 | - .:/home/goadmin 31 | networks: 32 | - goadmin 33 | command: 34 | - /bin/bash 35 | portainer: 36 | image: portainer/portainer:latest 37 | container_name: portainer 38 | restart: always 39 | ports: 40 | - "9000:9000" 41 | networks: 42 | - goadmin 43 | volumes: 44 | - /var/run/docker.sock:/var/run/docker.sock 45 | - portainer:/data 46 | networks: 47 | goadmin: {} 48 | volumes: 49 | portainer: {} 50 | postgres: {} 51 | mysql: {} 52 | -------------------------------------------------------------------------------- /examples/beego2/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "os" 6 | "os/signal" 7 | "time" 8 | 9 | _ "github.com/GoAdminGroup/go-admin/adapter/beego2" 10 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" 11 | 12 | "github.com/GoAdminGroup/go-admin/engine" 13 | "github.com/GoAdminGroup/go-admin/examples/datamodel" 14 | "github.com/GoAdminGroup/go-admin/modules/config" 15 | "github.com/GoAdminGroup/go-admin/modules/language" 16 | "github.com/GoAdminGroup/go-admin/plugins/example" 17 | "github.com/GoAdminGroup/go-admin/template" 18 | "github.com/GoAdminGroup/go-admin/template/chartjs" 19 | "github.com/GoAdminGroup/themes/adminlte" 20 | "github.com/beego/beego/v2/server/web" 21 | ) 22 | 23 | func main() { 24 | app := web.NewHttpSever() 25 | 26 | eng := engine.Default() 27 | 28 | cfg := config.Config{ 29 | Env: config.EnvLocal, 30 | Databases: config.DatabaseList{ 31 | "default": { 32 | Host: "127.0.0.1", 33 | Port: "3306", 34 | User: "root", 35 | Pwd: "123456", 36 | Name: "godmin", 37 | MaxIdleConns: 50, 38 | MaxOpenConns: 150, 39 | ConnMaxLifetime: time.Hour, 40 | Driver: config.DriverMysql, 41 | }, 42 | }, 43 | Store: config.Store{ 44 | Path: "./uploads", 45 | Prefix: "uploads", 46 | }, 47 | UrlPrefix: "admin", 48 | IndexUrl: "/", 49 | Debug: true, 50 | Language: language.CN, 51 | ColorScheme: adminlte.ColorschemeSkinBlack, 52 | } 53 | 54 | template.AddComp(chartjs.NewChart()) 55 | 56 | examplePlugin := example.NewExample() 57 | 58 | web.SetStaticPath("/uploads", "uploads") 59 | 60 | if err := eng.AddConfig(&cfg). 61 | AddGenerators(datamodel.Generators). 62 | AddDisplayFilterXssJsFilter(). 63 | AddGenerator("user", datamodel.GetUserTable). 64 | AddPlugins(examplePlugin). 65 | Use(app); err != nil { 66 | panic(err) 67 | } 68 | 69 | eng.HTML("GET", "/admin", datamodel.GetContent) 70 | 71 | app.Cfg.Listen.HTTPSAddr = "127.0.0.1" 72 | app.Cfg.Listen.HTTPPort = 9087 73 | go app.Run("") 74 | 75 | quit := make(chan os.Signal, 1) 76 | signal.Notify(quit, os.Interrupt) 77 | <-quit 78 | log.Print("closing database connection") 79 | eng.MysqlConnection().Close() 80 | } 81 | -------------------------------------------------------------------------------- /examples/datamodel/authors.go: -------------------------------------------------------------------------------- 1 | package datamodel 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/modules/db" 6 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 7 | "github.com/GoAdminGroup/go-admin/template/types/form" 8 | ) 9 | 10 | // GetAuthorsTable return the model of table author. 11 | func GetAuthorsTable(ctx *context.Context) (authorsTable table.Table) { 12 | 13 | authorsTable = table.NewDefaultTable(ctx, table.DefaultConfig()) 14 | 15 | // connect your custom connection 16 | // authorsTable = table.NewDefaultTable(ctx, table.DefaultConfigWithDriverAndConnection("mysql", "admin")) 17 | 18 | info := authorsTable.GetInfo() 19 | info.AddField("ID", "id", db.Int).FieldSortable() 20 | info.AddField("First Name", "first_name", db.Varchar) 21 | info.AddField("Last Name", "last_name", db.Varchar) 22 | info.AddField("Email", "email", db.Varchar) 23 | info.AddField("Birthdate", "birthdate", db.Date) 24 | info.AddField("Added", "added", db.Timestamp) 25 | 26 | info.SetTable("authors").SetTitle("Authors").SetDescription("Authors") 27 | 28 | formList := authorsTable.GetForm() 29 | formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate() 30 | formList.AddField("First Name", "first_name", db.Varchar, form.Text) 31 | formList.AddField("Last Name", "last_name", db.Varchar, form.Text) 32 | formList.AddField("Email", "email", db.Varchar, form.Text) 33 | formList.AddField("Birthdate", "birthdate", db.Date, form.Text) 34 | formList.AddField("Added", "added", db.Timestamp, form.Text) 35 | 36 | formList.SetTable("authors").SetTitle("Authors").SetDescription("Authors") 37 | 38 | return 39 | } 40 | -------------------------------------------------------------------------------- /examples/datamodel/bootstrap.go: -------------------------------------------------------------------------------- 1 | package datamodel 2 | -------------------------------------------------------------------------------- /examples/datamodel/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "database": { 3 | "default": { 4 | "host": "127.0.0.1", 5 | "port": "3306", 6 | "user": "root", 7 | "pwd": "root", 8 | "name": "godmin", 9 | "max_idle_con": 50, 10 | "max_open_con": 150, 11 | "driver": "mysql" 12 | } 13 | }, 14 | "domain": "localhost", 15 | "prefix": "admin", 16 | "store": { 17 | "path": "./uploads", 18 | "prefix": "uploads" 19 | }, 20 | "language": "cn", 21 | "index": "/", 22 | "debug": true, 23 | "color_scheme": "skin-black" 24 | } -------------------------------------------------------------------------------- /examples/datamodel/goadmin_super_users.go: -------------------------------------------------------------------------------- 1 | package datamodel 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/modules/db" 6 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 7 | "github.com/GoAdminGroup/go-admin/template/types/form" 8 | ) 9 | 10 | func GetGoadminSuperUsersTable(ctx *context.Context) table.Table { 11 | 12 | goadminSuperUsers := table.NewDefaultTable(ctx, table.DefaultConfigWithDriver("mysql")) 13 | 14 | info := goadminSuperUsers.GetInfo().HideFilterArea() 15 | 16 | info.AddField("Id", "id", db.Int).FieldFilterable() 17 | info.AddField("Username", "username", db.Varchar) 18 | info.AddField("Password", "password", db.Varchar) 19 | info.AddField("Name", "name", db.Varchar) 20 | info.AddField("Avatar", "avatar", db.Varchar) 21 | info.AddField("Remember_token", "remember_token", db.Varchar) 22 | info.AddField("Created_at", "created_at", db.Timestamp) 23 | info.AddField("Updated_at", "updated_at", db.Timestamp) 24 | 25 | info.SetTable("goadmin_super_users").SetTitle("GoadminSuperUsers").SetDescription("GoadminSuperUsers") 26 | 27 | formList := goadminSuperUsers.GetForm() 28 | formList.AddField("Id", "id", db.Int, form.Default) 29 | formList.AddField("Username", "username", db.Varchar, form.Text) 30 | formList.AddField("Password", "password", db.Varchar, form.Password) 31 | formList.AddField("Name", "name", db.Varchar, form.Text) 32 | formList.AddField("Avatar", "avatar", db.Varchar, form.Text) 33 | formList.AddField("Remember_token", "remember_token", db.Varchar, form.Text) 34 | formList.AddField("Created_at", "created_at", db.Timestamp, form.Datetime) 35 | formList.AddField("Updated_at", "updated_at", db.Timestamp, form.Datetime) 36 | 37 | formList.SetTable("goadmin_super_users").SetTitle("GoadminSuperUsers").SetDescription("GoadminSuperUsers") 38 | 39 | return goadminSuperUsers 40 | } 41 | -------------------------------------------------------------------------------- /examples/datamodel/tables.go: -------------------------------------------------------------------------------- 1 | package datamodel 2 | 3 | import "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 4 | 5 | // Generators is a map of table models. 6 | // 7 | // The key of generators is the prefix of table info url. 8 | // The corresponding value is the Form and TableName data. 9 | // 10 | // http://{{config.Domain}}:{{Port}}/{{config.Prefix}}/info/{{key}} 11 | // 12 | // example: 13 | // 14 | // "posts" => http://localhost:9033/admin/info/posts 15 | // "authors" => http://localhost:9033/admin/info/authors 16 | // 17 | var Generators = map[string]table.Generator{ 18 | "posts": GetPostsTable, 19 | "authors": GetAuthorsTable, 20 | } 21 | -------------------------------------------------------------------------------- /examples/gf2/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "os" 6 | "os/signal" 7 | "time" 8 | 9 | _ "github.com/GoAdminGroup/go-admin/adapter/gf2" 10 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" 11 | 12 | "github.com/GoAdminGroup/go-admin/engine" 13 | "github.com/GoAdminGroup/go-admin/examples/datamodel" 14 | "github.com/GoAdminGroup/go-admin/modules/config" 15 | 16 | "github.com/GoAdminGroup/go-admin/modules/language" 17 | "github.com/GoAdminGroup/go-admin/plugins/example" 18 | "github.com/GoAdminGroup/go-admin/template" 19 | "github.com/GoAdminGroup/go-admin/template/chartjs" 20 | "github.com/GoAdminGroup/themes/adminlte" 21 | "github.com/gogf/gf/v2/frame/g" 22 | ) 23 | 24 | func main() { 25 | s := g.Server() 26 | 27 | eng := engine.Default() 28 | 29 | cfg := config.Config{ 30 | Env: config.EnvLocal, 31 | Databases: config.DatabaseList{ 32 | "default": { 33 | Host: "127.0.0.1", 34 | Port: "3306", 35 | User: "root", 36 | Pwd: "123456", 37 | Name: "godmin", 38 | MaxIdleConns: 50, 39 | MaxOpenConns: 150, 40 | ConnMaxLifetime: time.Hour, 41 | Driver: config.DriverMysql, 42 | 43 | //Driver: config.DriverSqlite, 44 | //File: "../datamodel/admin.db", 45 | }, 46 | }, 47 | UrlPrefix: "admin", 48 | Store: config.Store{ 49 | Path: "./uploads", 50 | Prefix: "uploads", 51 | }, 52 | Language: language.CN, 53 | IndexUrl: "/", 54 | Debug: true, 55 | ColorScheme: adminlte.ColorschemeSkinBlack, 56 | } 57 | 58 | template.AddComp(chartjs.NewChart()) 59 | 60 | examplePlugin := example.NewExample() 61 | 62 | if err := eng.AddConfig(&cfg). 63 | AddGenerators(datamodel.Generators). 64 | AddDisplayFilterXssFilter(). 65 | AddGenerator("user", datamodel.GetUserTable). 66 | AddPlugins(examplePlugin). 67 | Use(s); err != nil { 68 | panic(err) 69 | } 70 | 71 | s.AddStaticPath("/uploads", "./uploads") 72 | 73 | eng.HTML("GET", "/admin", datamodel.GetContent) 74 | 75 | s.SetPort(9033) 76 | go s.Run() 77 | 78 | quit := make(chan os.Signal, 1) 79 | signal.Notify(quit, os.Interrupt) 80 | <-quit 81 | log.Print("closing database connection") 82 | eng.MysqlConnection().Close() 83 | 84 | } 85 | -------------------------------------------------------------------------------- /modules/auth/auth_test.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestEncodePassword(t *testing.T) { 10 | pwd := EncodePassword([]byte("123456")) 11 | assert.Equal(t, comparePassword("123456", pwd), true) 12 | } 13 | -------------------------------------------------------------------------------- /modules/collection/collection.go: -------------------------------------------------------------------------------- 1 | package collection 2 | 3 | type Collection []map[string]interface{} 4 | 5 | // Where filters the collection by a given key / value pair. 6 | func (c Collection) Where(key string, values ...interface{}) Collection { 7 | var d = make([]map[string]interface{}, 0) 8 | if len(values) < 1 { 9 | for _, value := range c { 10 | if isTrue(value[key]) { 11 | d = append(d, value) 12 | } 13 | } 14 | } else if len(values) < 2 { 15 | for _, value := range c { 16 | if value[key] == values[0] { 17 | d = append(d, value) 18 | } 19 | } 20 | } else if values[0].(string) == "=" { 21 | for _, value := range c { 22 | if value[key] == values[1] { 23 | d = append(d, value) 24 | } 25 | } 26 | } 27 | return d 28 | } 29 | 30 | func (c Collection) Length() int { 31 | return len(c) 32 | } 33 | 34 | func (c Collection) FirstGet(key string) interface{} { 35 | return c[0][key] 36 | } 37 | 38 | func isTrue(a interface{}) bool { 39 | switch a := a.(type) { 40 | case uint: 41 | return a != uint(0) 42 | case uint8: 43 | return a != uint8(0) 44 | case uint16: 45 | return a != uint16(0) 46 | case uint32: 47 | return a != uint32(0) 48 | case uint64: 49 | return a != uint64(0) 50 | case int: 51 | return a != int(0) 52 | case int8: 53 | return a != int8(0) 54 | case int16: 55 | return a != int16(0) 56 | case int32: 57 | return a != int32(0) 58 | case int64: 59 | return a != int64(0) 60 | case float32: 61 | return a != float32(0) 62 | case float64: 63 | return a != float64(0) 64 | case string: 65 | return a != "" 66 | case bool: 67 | return a 68 | default: 69 | return false 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /modules/collection/collection_test.go: -------------------------------------------------------------------------------- 1 | package collection 2 | -------------------------------------------------------------------------------- /modules/config/config.ini: -------------------------------------------------------------------------------- 1 | domain = localhost 2 | prefix = admin 3 | language = en 4 | index = / 5 | debug = true 6 | open_admin_api = true 7 | color_scheme = skin-black 8 | 9 | [database.default] 10 | 11 | host = 127.0.0.1 12 | port = 5432 13 | user = postgres 14 | pwd = root 15 | name = go-admin-test 16 | max_idle_con = 50 17 | max_open_con = 150 18 | driver = postgresql 19 | 20 | [store] 21 | 22 | path = ./uploads 23 | prefix = uploads 24 | -------------------------------------------------------------------------------- /modules/config/config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | database: 3 | default: 4 | host: 127.0.0.1 5 | port: '1433' 6 | user: sa 7 | pwd: Aa123456 8 | name: goadmin 9 | max_idle_con: 50 10 | max_open_con: 150 11 | driver: mssql 12 | domain: localhost 13 | prefix: admin 14 | store: 15 | path: "./uploads" 16 | prefix: uploads 17 | language: en 18 | index: "/" 19 | debug: true 20 | open_admin_api: true 21 | color_scheme: skin-black -------------------------------------------------------------------------------- /modules/constant/constant.go: -------------------------------------------------------------------------------- 1 | package constant 2 | 3 | const ( 4 | // PjaxHeader is default pjax http header key. 5 | PjaxHeader = "X-PJAX" 6 | 7 | // PjaxUrlHeader is default pjax url http header key. 8 | PjaxUrlHeader = "X-PJAX-Url" 9 | 10 | // Title is default title of the project. 11 | Title = "GoAdmin" 12 | 13 | ContextNodeNeedAuth = "need_auth" 14 | 15 | IframeKey = "__goadmin_iframe" 16 | IframeIDKey = "__goadmin_iframe_id" 17 | ) 18 | -------------------------------------------------------------------------------- /modules/db/base.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "database/sql" 5 | "errors" 6 | "sync" 7 | 8 | "github.com/GoAdminGroup/go-admin/modules/config" 9 | "xorm.io/xorm" 10 | ) 11 | 12 | // Base is a common Connection. 13 | type Base struct { 14 | DbList map[string]*sql.DB 15 | Once sync.Once 16 | Configs config.DatabaseList 17 | } 18 | 19 | // Close implements the method Connection.Close. 20 | func (db *Base) Close() []error { 21 | errs := make([]error, 0) 22 | for _, d := range db.DbList { 23 | errs = append(errs, d.Close()) 24 | } 25 | return errs 26 | } 27 | 28 | // GetDB implements the method Connection.GetDB. 29 | func (db *Base) GetDB(key string) *sql.DB { 30 | return db.DbList[key] 31 | } 32 | 33 | func (db *Base) CreateDB(name string, beans ...interface{}) error { 34 | cfg := db.GetConfig(name) 35 | if cfg.Driver == "" { 36 | return errors.New("wrong connection name") 37 | } 38 | engine, err := xorm.NewEngine(cfg.Driver, cfg.GetDSN()) 39 | if err != nil { 40 | return err 41 | } 42 | defer func() { 43 | _ = engine.Close() 44 | }() 45 | err = engine.Sync(beans...) 46 | if err != nil { 47 | return err 48 | } 49 | return nil 50 | } 51 | 52 | func (db *Base) GetConfig(name string) config.Database { 53 | return db.Configs[name] 54 | } 55 | -------------------------------------------------------------------------------- /modules/db/converter.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 GoAdmin Core Team. All rights reserved. 2 | // Use of this source code is governed by a Apache-2.0 style 3 | // license that can be found in the LICENSE file. 4 | 5 | package db 6 | 7 | import ( 8 | "database/sql" 9 | ) 10 | 11 | // SetColVarType set the column type. 12 | func SetColVarType(colVar *[]interface{}, i int, typeName string) { 13 | dt := DT(typeName) 14 | switch { 15 | case Contains(dt, BoolTypeList): 16 | var s sql.NullBool 17 | (*colVar)[i] = &s 18 | case Contains(dt, IntTypeList): 19 | var s sql.NullInt64 20 | (*colVar)[i] = &s 21 | case Contains(dt, FloatTypeList): 22 | var s sql.NullFloat64 23 | (*colVar)[i] = &s 24 | case Contains(dt, UintTypeList): 25 | var s []uint8 26 | (*colVar)[i] = &s 27 | case Contains(dt, StringTypeList): 28 | var s sql.NullString 29 | (*colVar)[i] = &s 30 | default: 31 | var s interface{} 32 | (*colVar)[i] = &s 33 | } 34 | } 35 | 36 | // SetResultValue set the result value. 37 | func SetResultValue(result *map[string]interface{}, index string, colVar interface{}, typeName string) { 38 | dt := DT(typeName) 39 | switch { 40 | case Contains(dt, BoolTypeList): 41 | temp := *(colVar.(*sql.NullBool)) 42 | if temp.Valid { 43 | (*result)[index] = temp.Bool 44 | } else { 45 | (*result)[index] = nil 46 | } 47 | case Contains(dt, IntTypeList): 48 | temp := *(colVar.(*sql.NullInt64)) 49 | if temp.Valid { 50 | (*result)[index] = temp.Int64 51 | } else { 52 | (*result)[index] = nil 53 | } 54 | case Contains(dt, FloatTypeList): 55 | temp := *(colVar.(*sql.NullFloat64)) 56 | if temp.Valid { 57 | (*result)[index] = temp.Float64 58 | } else { 59 | (*result)[index] = nil 60 | } 61 | case Contains(dt, UintTypeList): 62 | (*result)[index] = *(colVar.(*[]uint8)) 63 | case Contains(dt, StringTypeList): 64 | temp := *(colVar.(*sql.NullString)) 65 | if temp.Valid { 66 | (*result)[index] = temp.String 67 | } else { 68 | (*result)[index] = nil 69 | } 70 | default: 71 | if colVar2, ok := colVar.(*interface{}); ok { 72 | if colVar, ok = (*colVar2).(int64); ok { 73 | (*result)[index] = colVar 74 | } else if colVar, ok = (*colVar2).(string); ok { 75 | (*result)[index] = colVar 76 | } else if colVar, ok = (*colVar2).(float64); ok { 77 | (*result)[index] = colVar 78 | } else if colVar, ok = (*colVar2).([]uint8); ok { 79 | (*result)[index] = colVar 80 | } else { 81 | (*result)[index] = colVar 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /modules/db/dialect/common.go: -------------------------------------------------------------------------------- 1 | package dialect 2 | 3 | import "fmt" 4 | 5 | type commonDialect struct { 6 | delimiter string 7 | delimiter2 string 8 | } 9 | 10 | func (c commonDialect) Insert(comp *SQLComponent) string { 11 | comp.prepareInsert(c.delimiter, c.delimiter2) 12 | return comp.Statement 13 | } 14 | 15 | func (c commonDialect) Delete(comp *SQLComponent) string { 16 | comp.Statement = "delete from " + c.WrapTableName(comp) + comp.getWheres(c.delimiter, c.delimiter2) 17 | return comp.Statement 18 | } 19 | 20 | func (c commonDialect) Update(comp *SQLComponent) string { 21 | comp.prepareUpdate(c.delimiter, c.delimiter2) 22 | return comp.Statement 23 | } 24 | 25 | func (c commonDialect) Count(comp *SQLComponent) string { 26 | comp.prepareUpdate(c.delimiter, c.delimiter2) 27 | return comp.Statement 28 | } 29 | 30 | func (c commonDialect) Select(comp *SQLComponent) string { 31 | comp.Statement = "select " + comp.getFields(c.delimiter, c.delimiter2) + " from " + c.WrapTableName(comp) + comp.getJoins(c.delimiter, c.delimiter2) + 32 | comp.getWheres(c.delimiter, c.delimiter2) + comp.getGroupBy() + comp.getOrderBy() + comp.getLimit() + comp.getOffset() 33 | return comp.Statement 34 | } 35 | 36 | func (c commonDialect) ShowColumns(table string) string { 37 | return fmt.Sprintf("select * from information_schema.columns where table_name = '%s'", table) 38 | } 39 | 40 | func (c commonDialect) GetName() string { 41 | return "common" 42 | } 43 | 44 | func (c commonDialect) WrapTableName(comp *SQLComponent) string { 45 | return c.delimiter + comp.TableName + c.delimiter2 46 | } 47 | 48 | func (c commonDialect) ShowTables() string { 49 | return "show tables" 50 | } 51 | 52 | func (c commonDialect) ShowColumnsWithComment(schema, table string) string { 53 | return "" 54 | } 55 | 56 | func (c commonDialect) GetDelimiter() string { 57 | return c.delimiter 58 | } 59 | 60 | func (c commonDialect) GetDelimiter2() string { 61 | return c.delimiter2 62 | } 63 | 64 | func (c commonDialect) GetDelimiters() []string { 65 | return []string{c.delimiter, c.delimiter2} 66 | } 67 | -------------------------------------------------------------------------------- /modules/db/dialect/mssql.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 GoAdmin Core Team. All rights reserved. 2 | // Use of this source code is governed by a Apache-2.0 style 3 | // license that can be found in the LICENSE file. 4 | 5 | package dialect 6 | 7 | import "fmt" 8 | 9 | type mssql struct { 10 | commonDialect 11 | } 12 | 13 | func (mssql) GetName() string { 14 | return "mssql" 15 | } 16 | 17 | func (mssql) ShowColumnsWithComment(schema, table string) string { 18 | return fmt.Sprintf("select column_name, data_type from information_schema.columns where table_name = '%s'", table) 19 | } 20 | 21 | func (mssql) ShowColumns(table string) string { 22 | return fmt.Sprintf("select column_name, data_type from information_schema.columns where table_name = '%s'", table) 23 | } 24 | 25 | func (mssql) ShowTables() string { 26 | return "select * from information_schema.TABLES" 27 | } 28 | -------------------------------------------------------------------------------- /modules/db/dialect/mysql.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 GoAdmin Core Team. All rights reserved. 2 | // Use of this source code is governed by a Apache-2.0 style 3 | // license that can be found in the LICENSE file. 4 | 5 | package dialect 6 | 7 | type mysql struct { 8 | commonDialect 9 | } 10 | 11 | func (mysql) GetName() string { 12 | return "mysql" 13 | } 14 | 15 | func (mysql) ShowColumnsWithComment(schema, table string) string { 16 | return `SELECT 17 | COLUMN_NAME Field, DATA_TYPE Type, IS_NULLABLE 'Null', COLUMN_KEY 'Key', COLUMN_DEFAULT 'Default', EXTRA Extra, COLUMN_COMMENT Comment 18 | FROM information_schema.COLUMNS 19 | WHERE 20 | table_name = '` + table + `' 21 | AND 22 | table_schema = '` + schema + `'` 23 | } 24 | 25 | func (mysql) ShowColumns(table string) string { 26 | return "show columns in " + table 27 | } 28 | 29 | func (mysql) ShowTables() string { 30 | return "show tables" 31 | } 32 | -------------------------------------------------------------------------------- /modules/db/dialect/oceanbase.go: -------------------------------------------------------------------------------- 1 | package dialect 2 | 3 | type oceanbase struct { 4 | commonDialect 5 | } 6 | 7 | func (oceanbase) GetName() string { 8 | return "oceanbase" 9 | } 10 | 11 | func (oceanbase) ShowColumnsWithComment(schema, table string) string { 12 | return "show columns in " + table 13 | } 14 | 15 | func (oceanbase) ShowColumns(table string) string { 16 | return "show columns in " + table 17 | } 18 | 19 | func (oceanbase) ShowTables() string { 20 | return "show tables" 21 | } 22 | -------------------------------------------------------------------------------- /modules/db/dialect/postgresql.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 GoAdmin Core Team. All rights reserved. 2 | // Use of this source code is governed by a Apache-2.0 style 3 | // license that can be found in the LICENSE file. 4 | 5 | package dialect 6 | 7 | import ( 8 | "fmt" 9 | "strings" 10 | ) 11 | 12 | type postgresql struct { 13 | commonDialect 14 | } 15 | 16 | func (postgresql) GetName() string { 17 | return "postgresql" 18 | } 19 | 20 | func (postgresql) ShowColumnsWithComment(schema, table string) string { 21 | tableArr := strings.Split(table, "\".\"") 22 | if len(tableArr) > 1 { 23 | return fmt.Sprintf("select * from information_schema.columns where table_name = '%s' and table_schema = '%s'", tableArr[1], tableArr[0]) 24 | } else { 25 | return fmt.Sprintf("select * from information_schema.columns where table_name = '%s'", table) 26 | } 27 | } 28 | 29 | func (postgresql) ShowTables() string { 30 | return "SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname != 'pg_catalog' AND schemaname != 'information_schema';" 31 | } 32 | 33 | func (postgresql) ShowColumns(table string) string { 34 | tableArr := strings.Split(table, "\".\"") 35 | if len(tableArr) > 1 { 36 | return fmt.Sprintf("select * from information_schema.columns where table_name = '%s' and table_schema = '%s'", tableArr[1], tableArr[0]) 37 | } else { 38 | return fmt.Sprintf("select * from information_schema.columns where table_name = '%s'", table) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /modules/db/dialect/sqlite.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 GoAdmin Core Team. All rights reserved. 2 | // Use of this source code is governed by a Apache-2.0 style 3 | // license that can be found in the LICENSE file. 4 | 5 | package dialect 6 | 7 | type sqlite struct { 8 | commonDialect 9 | } 10 | 11 | func (sqlite) GetName() string { 12 | return "sqlite" 13 | } 14 | 15 | func (sqlite) ShowColumnsWithComment(schema, table string) string { 16 | return "PRAGMA table_info(" + table + ");" 17 | } 18 | 19 | func (sqlite) ShowColumns(table string) string { 20 | return "PRAGMA table_info(" + table + ");" 21 | } 22 | 23 | func (sqlite) ShowTables() string { 24 | return "SELECT name as tablename FROM sqlite_master WHERE type ='table'" 25 | } 26 | -------------------------------------------------------------------------------- /modules/db/drivers/mssql/mssql.go: -------------------------------------------------------------------------------- 1 | package mssql 2 | 3 | import _ "github.com/denisenkom/go-mssqldb" // Import the mssql driver. 4 | -------------------------------------------------------------------------------- /modules/db/drivers/mysql/mysql.go: -------------------------------------------------------------------------------- 1 | package mysql 2 | 3 | import _ "github.com/go-sql-driver/mysql" // Import the mysql driver. 4 | -------------------------------------------------------------------------------- /modules/db/drivers/oceanbase/oceanbase.go: -------------------------------------------------------------------------------- 1 | package oceanbase 2 | 3 | //oceanbase-ce can use mysql driver 4 | import _ "github.com/go-sql-driver/mysql" // Import the mysql driver. 5 | -------------------------------------------------------------------------------- /modules/db/drivers/postgres/postgres.go: -------------------------------------------------------------------------------- 1 | package postgres 2 | 3 | import _ "github.com/lib/pq" // Import the postgresql driver. 4 | -------------------------------------------------------------------------------- /modules/db/drivers/sqlite/sqlite.go: -------------------------------------------------------------------------------- 1 | package sqlite 2 | 3 | import _ "github.com/mattn/go-sqlite3" // Import the sqlite driver. 4 | -------------------------------------------------------------------------------- /modules/errors/error.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "errors" 5 | "html/template" 6 | 7 | "github.com/GoAdminGroup/go-admin/modules/language" 8 | "github.com/GoAdminGroup/go-admin/template/icon" 9 | ) 10 | 11 | var ( 12 | Msg string 13 | MsgHTML template.HTML 14 | MsgWithIcon template.HTML 15 | ) 16 | 17 | const ( 18 | PermissionDenied = "permission denied" 19 | WrongID = "wrong id" 20 | OperationNotAllow = "operation not allow" 21 | EditFailWrongToken = "edit fail, wrong token" 22 | CreateFailWrongToken = "create fail, wrong token" 23 | NoPermission = "no permission" 24 | SiteOff = "site is off" 25 | ) 26 | 27 | func WrongPK(pk string) string { 28 | return "wrong " + pk 29 | } 30 | 31 | func Init() { 32 | Msg = language.Get("error") 33 | MsgHTML = language.GetFromHtml("error") 34 | MsgWithIcon = icon.Icon(icon.Warning, 2) + MsgHTML + `!` 35 | 36 | PageError404 = errors.New(language.Get("not found")) 37 | PageError500 = errors.New(language.Get("internal error")) 38 | PageError403 = errors.New(language.Get("permission denied")) 39 | PageError401 = errors.New(language.Get("unauthorized")) 40 | } 41 | 42 | type PageError error 43 | 44 | var ( 45 | PageError404 PageError 46 | PageError500 PageError 47 | PageError403 PageError 48 | PageError401 PageError 49 | ) 50 | -------------------------------------------------------------------------------- /modules/file/local.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 GoAdmin Core Team. All rights reserved. 2 | // Use of this source code is governed by a Apache-2.0 style 3 | // license that can be found in the LICENSE file. 4 | 5 | package file 6 | 7 | import ( 8 | "mime/multipart" 9 | 10 | "github.com/GoAdminGroup/go-admin/modules/config" 11 | ) 12 | 13 | // LocalFileUploader is an Uploader of local file engine. 14 | type LocalFileUploader struct { 15 | BasePath string 16 | } 17 | 18 | // GetLocalFileUploader return the default Uploader. 19 | func GetLocalFileUploader() Uploader { 20 | return &LocalFileUploader{ 21 | config.GetStore().Path, 22 | } 23 | } 24 | 25 | // Upload implements the Uploader.Upload. 26 | func (local *LocalFileUploader) Upload(form *multipart.Form) error { 27 | return Upload(func(fileObj *multipart.FileHeader, filename string) (string, error) { 28 | if err := SaveMultipartFile(fileObj, (*local).BasePath+"/"+filename); err != nil { 29 | return "", err 30 | } 31 | return filename, nil 32 | }, form) 33 | } 34 | -------------------------------------------------------------------------------- /modules/language/language_test.go: -------------------------------------------------------------------------------- 1 | package language 2 | 3 | import ( 4 | "fmt" 5 | "html/template" 6 | "testing" 7 | 8 | "github.com/GoAdminGroup/go-admin/modules/config" 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func TestKK(t *testing.T) { 13 | for key := range cn { 14 | if _, ok := ptbr[key]; !ok { 15 | fmt.Println(key, "===", cn[key]) 16 | } 17 | } 18 | } 19 | 20 | func TestAdd(t *testing.T) { 21 | Add("cn", map[string]string{}) 22 | } 23 | 24 | func TestGetWithScope(t *testing.T) { 25 | config.Initialize(&config.Config{ 26 | Language: CN, 27 | }) 28 | cn["foo"] = "bar" 29 | assert.Equal(t, GetWithScope("foo"), "bar") 30 | cn["user.table.foo2"] = "bar" 31 | assert.Equal(t, GetWithScope("foo2"), "foo2") 32 | assert.Equal(t, GetWithScope("foo2", "user"), "foo2") 33 | assert.Equal(t, GetWithScope("foo2", "user", "table"), "bar") 34 | } 35 | 36 | func TestGet(t *testing.T) { 37 | config.Initialize(&config.Config{ 38 | Language: CN, 39 | }) 40 | cn["foo"] = "bar" 41 | assert.Equal(t, Get("foo"), "bar") 42 | } 43 | 44 | func TestWithScopes(t *testing.T) { 45 | assert.Equal(t, WithScopes("foo", "user", "table"), "user.table.foo") 46 | } 47 | 48 | func TestGetFromHtml(t *testing.T) { 49 | config.Initialize(&config.Config{ 50 | Language: CN, 51 | }) 52 | cn["user.table.foo"] = "bar" 53 | assert.Equal(t, GetFromHtml("foo", "user", "table"), template.HTML("bar")) 54 | } 55 | -------------------------------------------------------------------------------- /modules/logger/logger_test.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import "testing" 4 | 5 | func TestInfo(t *testing.T) { 6 | Info("test") 7 | } 8 | -------------------------------------------------------------------------------- /modules/menu/menu_test.go: -------------------------------------------------------------------------------- 1 | package menu 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/magiconair/properties/assert" 7 | ) 8 | 9 | func TestMenu_AddMaxOrder(t *testing.T) { 10 | menus := Menu{ 11 | MaxOrder: 0, 12 | } 13 | menus.AddMaxOrder() 14 | assert.Equal(t, menus.MaxOrder, int64(1)) 15 | } 16 | 17 | func TestMenu_SetMaxOrder(t *testing.T) { 18 | menus := Menu{ 19 | MaxOrder: 0, 20 | } 21 | menus.SetMaxOrder(2) 22 | assert.Equal(t, menus.MaxOrder, int64(2)) 23 | } 24 | 25 | func TestMenu_SetActiveClass(t *testing.T) { 26 | menus := Menu{ 27 | List: []Item{ 28 | { 29 | Name: "item1", 30 | ID: "1", 31 | Url: "/item1", 32 | Icon: "icon", 33 | }, { 34 | Name: "item2", 35 | ID: "2", 36 | Url: "/item2", 37 | Icon: "icon", 38 | }, { 39 | Name: "item3", 40 | ID: "3", 41 | Url: "/item3", 42 | Icon: "icon", 43 | }, { 44 | Name: "item4", 45 | ID: "4", 46 | Url: "/item4", 47 | Icon: "icon", 48 | ChildrenList: []Item{ 49 | { 50 | Name: "item5", 51 | ID: "5", 52 | Url: "/item5", 53 | Icon: "icon", 54 | }, { 55 | Name: "item6", 56 | ID: "6", 57 | Url: "/item6", 58 | Icon: "icon", 59 | }, 60 | }, 61 | }, 62 | }, 63 | Options: []map[string]string{}, 64 | MaxOrder: 0, 65 | } 66 | 67 | menus.SetActiveClass("/item3") 68 | 69 | assert.Equal(t, menus.List[0].Active, "") 70 | assert.Equal(t, menus.List[1].Active, "") 71 | assert.Equal(t, menus.List[2].Active, "active") 72 | assert.Equal(t, menus.List[3].Active, "") 73 | 74 | menus.SetActiveClass("/item5") 75 | 76 | assert.Equal(t, menus.List[0].Active, "") 77 | assert.Equal(t, menus.List[1].Active, "") 78 | assert.Equal(t, menus.List[2].Active, "") 79 | assert.Equal(t, menus.List[3].Active, "active") 80 | assert.Equal(t, menus.List[3].ChildrenList[0].Active, "active") 81 | assert.Equal(t, menus.List[3].ChildrenList[1].Active, "") 82 | } 83 | -------------------------------------------------------------------------------- /modules/page/page.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 GoAdmin Core Team. All rights reserved. 2 | // Use of this source code is governed by a Apache-2.0 style 3 | // license that can be found in the LICENSE file. 4 | 5 | package page 6 | 7 | import ( 8 | "bytes" 9 | 10 | "github.com/GoAdminGroup/go-admin/context" 11 | "github.com/GoAdminGroup/go-admin/modules/config" 12 | "github.com/GoAdminGroup/go-admin/modules/db" 13 | "github.com/GoAdminGroup/go-admin/modules/logger" 14 | "github.com/GoAdminGroup/go-admin/modules/menu" 15 | "github.com/GoAdminGroup/go-admin/plugins/admin/models" 16 | "github.com/GoAdminGroup/go-admin/template" 17 | "github.com/GoAdminGroup/go-admin/template/types" 18 | ) 19 | 20 | // SetPageContent set and return the panel of page content. 21 | func SetPageContent(ctx *context.Context, user models.UserModel, c func(ctx interface{}) (types.Panel, error), conn db.Connection) { 22 | 23 | panel, err := c(ctx) 24 | 25 | if err != nil { 26 | logger.ErrorCtx(ctx, "SetPageContent %+v", err) 27 | panel = template.WarningPanel(ctx, err.Error()) 28 | } 29 | 30 | tmpl, tmplName := template.Get(ctx, config.GetTheme()).GetTemplate(ctx.IsPjax()) 31 | 32 | ctx.AddHeader("Content-Type", "text/html; charset=utf-8") 33 | 34 | buf := new(bytes.Buffer) 35 | 36 | err = tmpl.ExecuteTemplate(buf, tmplName, types.NewPage(ctx, &types.NewPageParam{ 37 | User: user, 38 | Menu: menu.GetGlobalMenu(user, conn, ctx.Lang()).SetActiveClass(config.URLRemovePrefix(ctx.Path())), 39 | Panel: panel.GetContent(config.IsProductionEnvironment()), 40 | Assets: template.GetComponentAssetImportHTML(ctx), 41 | TmplHeadHTML: template.Default(ctx).GetHeadHTML(), 42 | TmplFootJS: template.Default(ctx).GetFootJS(), 43 | Iframe: ctx.IsIframe(), 44 | })) 45 | if err != nil { 46 | logger.ErrorCtx(ctx, "SetPageContent %+v", err) 47 | } 48 | ctx.WriteString(buf.String()) 49 | } 50 | -------------------------------------------------------------------------------- /modules/service/service.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 GoAdmin Core Team. All rights reserved. 2 | // Use of this source code is governed by a Apache-2.0 style 3 | // license that can be found in the LICENSE file. 4 | 5 | package service 6 | 7 | import ( 8 | "log" 9 | ) 10 | 11 | type Service interface { 12 | Name() string 13 | } 14 | 15 | type Generator func() (Service, error) 16 | 17 | func Register(k string, gen Generator) { 18 | if _, ok := services[k]; ok { 19 | log.Panicf("service %s has been registered", k) 20 | } 21 | services[k] = gen 22 | } 23 | 24 | func GetServices() List { 25 | var ( 26 | l = make(List) 27 | err error 28 | ) 29 | for k, gen := range services { 30 | if l[k], err = gen(); err != nil { 31 | log.Panicf("service %s initialize fail, error: %v", k, err) 32 | } 33 | } 34 | return l 35 | } 36 | 37 | var services = make(Generators) 38 | 39 | type Generators map[string]Generator 40 | 41 | type List map[string]Service 42 | 43 | func (g List) Get(k string) Service { 44 | if v, ok := g[k]; ok { 45 | return v 46 | } 47 | log.Panicf("service %s not found", k) 48 | return nil 49 | } 50 | 51 | func (g List) GetOrNot(k string) (Service, bool) { 52 | v, ok := g[k] 53 | return v, ok 54 | } 55 | 56 | func (g List) Add(k string, service Service) { 57 | if _, ok := g[k]; ok { 58 | log.Panicf("service %s exist", k) 59 | } 60 | g[k] = service 61 | } 62 | -------------------------------------------------------------------------------- /modules/system/version.go: -------------------------------------------------------------------------------- 1 | package system 2 | 3 | const version = "v1.2.27" 4 | 5 | var requireThemeVersion = map[string][]string{ 6 | "adminlte": {">=v0.0.41"}, 7 | "sword": {">=v0.0.41"}, 8 | } 9 | 10 | // Version return the version of framework. 11 | func Version() string { 12 | return version 13 | } 14 | 15 | // RequireThemeVersion return the require official version 16 | func RequireThemeVersion() map[string][]string { 17 | return requireThemeVersion 18 | } 19 | -------------------------------------------------------------------------------- /modules/trace/trace.go: -------------------------------------------------------------------------------- 1 | package trace 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "os" 7 | "sync" 8 | "sync/atomic" 9 | "time" 10 | 11 | "github.com/GoAdminGroup/go-admin/context" 12 | ) 13 | 14 | var ( 15 | machineIDOnce sync.Once 16 | machineID string 17 | counter uint32 18 | ) 19 | 20 | func getMachineID() string { 21 | machineIDOnce.Do(func() { 22 | addrs, err := net.InterfaceAddrs() 23 | if err == nil { 24 | for _, addr := range addrs { 25 | if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() { 26 | if ipNet.IP.To4() != nil { 27 | machineID = ipNet.IP.String() 28 | break 29 | } 30 | } 31 | } 32 | } 33 | 34 | if machineID == "" { 35 | machineID = "127.0.0.1" 36 | } 37 | }) 38 | 39 | return machineID 40 | } 41 | 42 | func GenerateTraceID() string { 43 | machineID := getMachineID() 44 | timestamp := time.Now().UnixNano() / int64(time.Millisecond) 45 | processID := os.Getpid() 46 | id := atomic.AddUint32(&counter, 1) 47 | id = id % 1000 48 | traceID := fmt.Sprintf("%08x%05d%013d%04d", machineIDToHex(machineID), processID, timestamp, id) 49 | 50 | return traceID 51 | } 52 | 53 | func machineIDToHex(machineID string) uint32 { 54 | ip := net.ParseIP(machineID) 55 | ipUint32 := uint32(ip[12])<<24 | uint32(ip[13])<<16 | uint32(ip[14])<<8 | uint32(ip[15]) 56 | return ipUint32 57 | } 58 | 59 | func GetTraceID(ctx *context.Context) string { 60 | traceID, ok := ctx.GetUserValue(TraceIDKey).(string) 61 | if !ok { 62 | return "" 63 | } 64 | return traceID 65 | } 66 | 67 | const ( 68 | TraceIDKey = "traceID" 69 | ) 70 | -------------------------------------------------------------------------------- /modules/ui/ui.go: -------------------------------------------------------------------------------- 1 | package ui 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/modules/config" 5 | "github.com/GoAdminGroup/go-admin/modules/language" 6 | "github.com/GoAdminGroup/go-admin/modules/service" 7 | "github.com/GoAdminGroup/go-admin/template/icon" 8 | "github.com/GoAdminGroup/go-admin/template/types" 9 | "github.com/GoAdminGroup/go-admin/template/types/action" 10 | ) 11 | 12 | type Service struct { 13 | NavButtons *types.Buttons 14 | } 15 | 16 | const ServiceKey = "ui" 17 | 18 | func (s *Service) Name() string { 19 | return "ui" 20 | } 21 | 22 | func GetService(srv service.List) *Service { 23 | if v, ok := srv.Get("ui").(*Service); ok { 24 | return v 25 | } 26 | panic("wrong service") 27 | } 28 | 29 | func NewService(btns *types.Buttons) *Service { 30 | return &Service{ 31 | NavButtons: btns, 32 | } 33 | } 34 | 35 | func (s *Service) UpdateButtons() { 36 | 37 | } 38 | 39 | func (s *Service) RemoveOrShowSiteNavButton(remove bool) { 40 | if remove { 41 | *s.NavButtons = (*s.NavButtons).RemoveSiteNavButton() 42 | } else { 43 | *s.NavButtons = (*s.NavButtons).AddNavButton(icon.Gear, types.NavBtnSiteName, 44 | action.JumpInNewTab(config.Url("/info/site/edit"), 45 | language.GetWithScope("site setting", "config"))) 46 | } 47 | } 48 | 49 | func (s *Service) RemoveOrShowInfoNavButton(remove bool) { 50 | if remove { 51 | *s.NavButtons = (*s.NavButtons).RemoveInfoNavButton() 52 | } else { 53 | *s.NavButtons = (*s.NavButtons).AddNavButton(icon.Info, types.NavBtnInfoName, 54 | action.JumpInNewTab(config.Url("/application/info"), 55 | language.GetWithScope("system info", "system"))) 56 | } 57 | 58 | } 59 | 60 | func (s *Service) RemoveOrShowToolNavButton(remove bool) { 61 | if remove { 62 | *s.NavButtons = (*s.NavButtons).RemoveToolNavButton() 63 | } else { 64 | *s.NavButtons = (*s.NavButtons).AddNavButton(icon.Wrench, types.NavBtnToolName, 65 | action.JumpInNewTab(config.Url("/info/generate/new"), 66 | language.GetWithScope("tool", "tool"))) 67 | } 68 | 69 | } 70 | 71 | func (s *Service) RemoveOrShowPlugNavButton(remove bool) { 72 | if remove { 73 | *s.NavButtons = (*s.NavButtons).RemovePlugNavButton() 74 | } else { 75 | *s.NavButtons = (*s.NavButtons).AddNavButton(icon.Plug, types.NavBtnToolName, 76 | action.JumpInNewTab(config.Url("/plugin"), 77 | language.GetWithScope("plugin", "plugin"))) 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /modules/utils/utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "html/template" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestCompressedContent(t *testing.T) { 11 | htmlContent1 := template.HTML(` 12 | 13 | 14 | 15 |

Test

16 | 17 | 18 | 19 |

CompressedContent

20 | 21 | 22 | 23 | 24 | `) 25 | htmlContent2 := htmlContent1 26 | CompressedContent(&htmlContent2) 27 | t.Log(len(htmlContent1) > len(htmlContent2)) 28 | } 29 | 30 | func TestCompareVersion(t *testing.T) { 31 | assert.Equal(t, true, CompareVersion("v1.2.4", "v1.2.5")) 32 | assert.Equal(t, false, CompareVersion("v1.2.4", "v1.2.4")) 33 | assert.Equal(t, false, CompareVersion("v1.2.4", "v1.2.3")) 34 | assert.Equal(t, false, CompareVersion("v1.2.4", "v1.1.3")) 35 | assert.Equal(t, true, CompareVersion("v1.2.4", "v1.3.3")) 36 | assert.Equal(t, false, CompareVersion("v1.2.4", "v0.3.3")) 37 | 38 | assert.Equal(t, true, CompareVersion("v1.2.4", "v1.2.5")) 44 | assert.Equal(t, false, CompareVersion(">v1.2.4", "v1.2.4")) 45 | assert.Equal(t, true, CompareVersion(">=v1.2.4", "v1.2.4")) 46 | assert.Equal(t, true, CompareVersion(">=v1.2.4", "v1.2.5")) 47 | assert.Equal(t, false, CompareVersion(">=v1.2.4", "v1.2.3")) 48 | assert.Equal(t, false, CompareVersion("=v1.2.4", "v1.2.3")) 49 | assert.Equal(t, true, CompareVersion("=v1.2.4", "v1.2.4")) 50 | assert.Equal(t, true, CompareVersion("= v1.2.4", "v1.2.4")) 51 | } 52 | -------------------------------------------------------------------------------- /plugins/admin/controller/Update.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/guard" 6 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" 7 | ) 8 | 9 | // Update update the table row of given id. 10 | func (h *Handler) Update(ctx *context.Context) { 11 | 12 | param := guard.GetUpdateParam(ctx) 13 | 14 | err := param.Panel.UpdateData(ctx, param.Value) 15 | 16 | if err != nil { 17 | response.Error(ctx, err.Error()) 18 | return 19 | } 20 | 21 | response.Ok(ctx) 22 | } 23 | -------------------------------------------------------------------------------- /plugins/admin/controller/api_create.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/modules/file" 6 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" 7 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/guard" 8 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" 9 | ) 10 | 11 | func (h *Handler) ApiCreate(ctx *context.Context) { 12 | param := guard.GetNewFormParam(ctx) 13 | 14 | if len(param.MultiForm.File) > 0 { 15 | err := file.GetFileEngine(h.config.FileUploadEngine.Name).Upload(param.MultiForm) 16 | if err != nil { 17 | response.Error(ctx, err.Error()) 18 | return 19 | } 20 | } 21 | 22 | err := param.Panel.InsertData(ctx, param.Value()) 23 | if err != nil { 24 | response.Error(ctx, err.Error()) 25 | return 26 | } 27 | 28 | response.Ok(ctx) 29 | } 30 | 31 | func (h *Handler) ApiCreateForm(ctx *context.Context) { 32 | 33 | var ( 34 | params = guard.GetShowNewFormParam(ctx) 35 | prefix, paramStr = params.Prefix, params.Param.GetRouteParamStr() 36 | panel = h.table(prefix, ctx) 37 | formInfo = panel.GetNewFormInfo() 38 | infoUrl = h.routePathWithPrefix("api_info", prefix) + paramStr 39 | newUrl = h.routePathWithPrefix("api_new", prefix) 40 | referer = ctx.Referer() 41 | f = panel.GetActualNewForm() 42 | ) 43 | 44 | if referer != "" && !isInfoUrl(referer) && !isNewUrl(referer, ctx.Query(constant.PrefixKey)) { 45 | infoUrl = referer 46 | } 47 | 48 | response.OkWithData(ctx, map[string]interface{}{ 49 | "panel": formInfo, 50 | "urls": map[string]string{ 51 | "info": infoUrl, 52 | "new": newUrl, 53 | }, 54 | "pk": panel.GetPrimaryKey().Name, 55 | "header": f.HeaderHtml, 56 | "footer": f.FooterHtml, 57 | "prefix": h.config.PrefixFixSlash(), 58 | "token": h.authSrv().AddToken(), 59 | "operation_footer": formFooter(ctx, "new", f.IsHideContinueEditCheckBox, f.IsHideContinueNewCheckBox, 60 | f.IsHideResetButton, f.FormNewBtnWord), 61 | }) 62 | } 63 | -------------------------------------------------------------------------------- /plugins/admin/controller/api_list.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" 6 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" 7 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" 8 | ) 9 | 10 | func (h *Handler) ApiList(ctx *context.Context) { 11 | prefix := ctx.Query(constant.PrefixKey) 12 | 13 | panel := h.table(prefix, ctx) 14 | 15 | params := parameter.GetParam(ctx.Request.URL, panel.GetInfo().DefaultPageSize, panel.GetInfo().SortField, 16 | panel.GetInfo().GetSort()) 17 | 18 | panel, panelInfo, urls, err := h.showTableData(ctx, prefix, params, panel, "api_") 19 | if err != nil { 20 | response.Error(ctx, err.Error()) 21 | return 22 | } 23 | 24 | response.OkWithData(ctx, map[string]interface{}{ 25 | "panel": panelInfo, 26 | "footer": panelInfo.Paginator.GetContent() + panel.GetInfo().FooterHtml, 27 | "header": aDataTable(ctx).GetDataTableHeader() + panel.GetInfo().HeaderHtml, 28 | "prefix": h.config.PrefixFixSlash(), 29 | "urls": map[string]string{ 30 | "edit": urls[0], 31 | "new": urls[1], 32 | "delete": urls[2], 33 | "export": urls[3], 34 | "detail": urls[4], 35 | "info": urls[5], 36 | "update": urls[6], 37 | }, 38 | }) 39 | } 40 | -------------------------------------------------------------------------------- /plugins/admin/controller/common_test.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/magiconair/properties/assert" 7 | ) 8 | 9 | func TestIsInfoUrl(t *testing.T) { 10 | u := "https://localhost:8098/admin/info/user?id=sdfs" 11 | assert.Equal(t, true, isInfoUrl(u)) 12 | } 13 | 14 | func TestIsNewUrl(t *testing.T) { 15 | u := "https://localhost:8098/admin/info/user/new?id=sdfs" 16 | assert.Equal(t, true, isNewUrl(u, "user")) 17 | } 18 | -------------------------------------------------------------------------------- /plugins/admin/controller/delete.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/modules/logger" 6 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/guard" 7 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" 8 | ) 9 | 10 | // Delete delete the row from database. 11 | func (h *Handler) Delete(ctx *context.Context) { 12 | 13 | param := guard.GetDeleteParam(ctx) 14 | 15 | //token := ctx.FormValue("_t") 16 | // 17 | //if !auth.TokenHelper.CheckToken(token) { 18 | // ctx.SetStatusCode(http.StatusBadRequest) 19 | // ctx.WriteString(`{"code":400, "msg":"delete fail"}`) 20 | // return 21 | //} 22 | 23 | if err := h.table(param.Prefix, ctx).DeleteData(param.Id); err != nil { 24 | logger.ErrorCtx(ctx, "Delete error %+v", err) 25 | response.Error(ctx, "delete fail") 26 | return 27 | } 28 | 29 | response.OkWithData(ctx, map[string]interface{}{ 30 | "token": h.authSrv().AddToken(), 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /plugins/admin/controller/install.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "bytes" 5 | "database/sql" 6 | "net/http" 7 | 8 | "github.com/GoAdminGroup/go-admin/context" 9 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" 10 | ) 11 | 12 | // ShowInstall show install page. 13 | func (h *Handler) ShowInstall(ctx *context.Context) { 14 | 15 | buffer := new(bytes.Buffer) 16 | //template.GetInstallPage(buffer) 17 | 18 | //rs, _ := mysql.Query("show tables;") 19 | //fmt.Println(rs[0]["Tables_in_godmin"]) 20 | 21 | //rs2, _ := mysql.Query("show columns from users") 22 | //fmt.Println(rs2[0]["Field"]) 23 | 24 | ctx.HTML(http.StatusOK, buffer.String()) 25 | } 26 | 27 | // CheckDatabase check the database connection. 28 | func (h *Handler) CheckDatabase(ctx *context.Context) { 29 | 30 | ip := ctx.FormValue("h") 31 | port := ctx.FormValue("po") 32 | username := ctx.FormValue("u") 33 | password := ctx.FormValue("pa") 34 | databaseName := ctx.FormValue("db") 35 | 36 | SqlDB, err := sql.Open("mysql", username+":"+password+"@tcp("+ip+":"+port+")/"+databaseName+"?charset=utf8mb4") 37 | if SqlDB != nil { 38 | if SqlDB.Ping() != nil { 39 | response.Error(ctx, "请检查参数是否设置正确") 40 | return 41 | } 42 | } 43 | 44 | defer func() { 45 | _ = SqlDB.Close() 46 | }() 47 | 48 | if err != nil { 49 | response.Error(ctx, "请检查参数是否设置正确") 50 | return 51 | 52 | } 53 | 54 | //db.InitDB(username, password, port, ip, databaseName, 100, 100) 55 | 56 | tables := make([]map[string]interface{}, 0) 57 | 58 | list := "[" 59 | 60 | for i := 0; i < len(tables); i++ { 61 | if i != len(tables)-1 { 62 | list += `"` + tables[i]["Tables_in_godmin"].(string) + `",` 63 | } else { 64 | list += `"` + tables[i]["Tables_in_godmin"].(string) + `"` 65 | } 66 | } 67 | list += "]" 68 | 69 | response.OkWithData(ctx, map[string]interface{}{ 70 | "list": list, 71 | }) 72 | } 73 | -------------------------------------------------------------------------------- /plugins/admin/controller/operation.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/GoAdminGroup/go-admin/context" 7 | "github.com/GoAdminGroup/go-admin/modules/config" 8 | "github.com/GoAdminGroup/go-admin/plugins/admin/models" 9 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" 10 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" 11 | ) 12 | 13 | func (h *Handler) Operation(ctx *context.Context) { 14 | id := ctx.Query("__goadmin_op_id") 15 | if !h.OperationHandler(config.Url("/operation/"+id), ctx) { 16 | errMsg := "not found" 17 | if ctx.Headers(constant.PjaxHeader) == "" && ctx.Method() != "GET" { 18 | response.BadRequest(ctx, errMsg) 19 | } else { 20 | response.Alert(ctx, errMsg, errMsg, errMsg, h.conn, h.navButtons) 21 | } 22 | return 23 | } 24 | } 25 | 26 | // RecordOperationLog record all operation logs, store into database. 27 | func (h *Handler) RecordOperationLog(ctx *context.Context) { 28 | if user, ok := ctx.UserValue["user"].(models.UserModel); ok { 29 | var input []byte 30 | form := ctx.Request.MultipartForm 31 | if form != nil { 32 | input, _ = json.Marshal((*form).Value) 33 | } 34 | 35 | models.OperationLog().SetConn(h.conn).New(user.Id, ctx.Path(), ctx.Method(), ctx.LocalIP(), string(input)) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /plugins/admin/data/sqlite/admin.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/go-admin/cd8748f96e19ce3c4bf437520542b097899fc16e/plugins/admin/data/sqlite/admin.db -------------------------------------------------------------------------------- /plugins/admin/models/base.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "database/sql" 5 | 6 | "github.com/GoAdminGroup/go-admin/modules/db" 7 | ) 8 | 9 | // Base is base model structure. 10 | type Base struct { 11 | TableName string 12 | 13 | Conn db.Connection 14 | Tx *sql.Tx 15 | } 16 | 17 | func (b Base) SetConn(con db.Connection) Base { 18 | b.Conn = con 19 | return b 20 | } 21 | 22 | func (b Base) Table(table string) *db.SQL { 23 | return db.Table(table).WithDriver(b.Conn) 24 | } 25 | -------------------------------------------------------------------------------- /plugins/admin/models/operation_log.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/modules/db" 5 | "github.com/GoAdminGroup/go-admin/modules/db/dialect" 6 | ) 7 | 8 | // OperationLogModel is operation log model structure. 9 | type OperationLogModel struct { 10 | Base 11 | 12 | Id int64 13 | UserId int64 14 | Path string 15 | Method string 16 | Ip string 17 | Input string 18 | CreatedAt string 19 | UpdatedAt string 20 | } 21 | 22 | // OperationLog return a default operation log model. 23 | func OperationLog() OperationLogModel { 24 | return OperationLogModel{Base: Base{TableName: "goadmin_operation_log"}} 25 | } 26 | 27 | // Find return a default operation log model of given id. 28 | func (t OperationLogModel) Find(id interface{}) OperationLogModel { 29 | item, _ := t.Table(t.TableName).Find(id) 30 | return t.MapToModel(item) 31 | } 32 | 33 | func (t OperationLogModel) SetConn(con db.Connection) OperationLogModel { 34 | t.Conn = con 35 | return t 36 | } 37 | 38 | // New create a new operation log model. 39 | func (t OperationLogModel) New(userId int64, path, method, ip, input string) OperationLogModel { 40 | 41 | id, _ := t.Table(t.TableName).Insert(dialect.H{ 42 | "user_id": userId, 43 | "path": path, 44 | "method": method, 45 | "ip": ip, 46 | "input": input, 47 | }) 48 | 49 | t.Id = id 50 | t.UserId = userId 51 | t.Path = path 52 | t.Method = method 53 | t.Ip = ip 54 | t.Input = input 55 | 56 | return t 57 | } 58 | 59 | // MapToModel get the operation log model from given map. 60 | func (t OperationLogModel) MapToModel(m map[string]interface{}) OperationLogModel { 61 | t.Id = m["id"].(int64) 62 | t.UserId = m["user_id"].(int64) 63 | t.Path, _ = m["path"].(string) 64 | t.Method, _ = m["method"].(string) 65 | t.Ip, _ = m["ip"].(string) 66 | t.Input, _ = m["input"].(string) 67 | t.CreatedAt, _ = m["created_at"].(string) 68 | t.UpdatedAt, _ = m["updated_at"].(string) 69 | return t 70 | } 71 | -------------------------------------------------------------------------------- /plugins/admin/modules/captcha/captcha.go: -------------------------------------------------------------------------------- 1 | package captcha 2 | 3 | type Captcha interface { 4 | Validate(token string) bool 5 | } 6 | 7 | var List = make(map[string]Captcha) 8 | 9 | func Add(key string, captcha Captcha) { 10 | if _, exist := List[key]; exist { 11 | panic("captcha exist") 12 | } 13 | List[key] = captcha 14 | } 15 | 16 | func Get(key string) (Captcha, bool) { 17 | captcha, ok := List[key] 18 | return captcha, ok 19 | } 20 | -------------------------------------------------------------------------------- /plugins/admin/modules/constant/constant.go: -------------------------------------------------------------------------------- 1 | package constant 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/modules/constant" 5 | ) 6 | 7 | const ( 8 | // PjaxHeader is default pjax http header key. 9 | PjaxHeader = constant.PjaxHeader 10 | 11 | // PjaxUrlHeader is default pjax url http header key. 12 | PjaxUrlHeader = constant.PjaxUrlHeader 13 | 14 | EditPKKey = "__goadmin_edit_pk" 15 | DetailPKKey = "__goadmin_detail_pk" 16 | PrefixKey = "__prefix" 17 | 18 | IframeKey = "__goadmin_iframe" 19 | IframeIDKey = "__goadmin_iframe_id" 20 | 21 | ContextNodeNeedAuth = constant.ContextNodeNeedAuth 22 | ) 23 | -------------------------------------------------------------------------------- /plugins/admin/modules/guard/delete.go: -------------------------------------------------------------------------------- 1 | package guard 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/modules/errors" 6 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 7 | ) 8 | 9 | type DeleteParam struct { 10 | Panel table.Table 11 | Id string 12 | Prefix string 13 | } 14 | 15 | func (g *Guard) Delete(ctx *context.Context) { 16 | panel, prefix := g.table(ctx) 17 | if !panel.GetDeletable() { 18 | alert(ctx, panel, errors.OperationNotAllow, g.conn, g.navBtns) 19 | ctx.Abort() 20 | return 21 | } 22 | 23 | id := ctx.FormValue("id") 24 | if id == "" { 25 | alert(ctx, panel, errors.WrongID, g.conn, g.navBtns) 26 | ctx.Abort() 27 | return 28 | } 29 | 30 | ctx.SetUserValue(deleteParamKey, &DeleteParam{ 31 | Panel: panel, 32 | Id: id, 33 | Prefix: prefix, 34 | }) 35 | ctx.Next() 36 | } 37 | 38 | func GetDeleteParam(ctx *context.Context) *DeleteParam { 39 | return ctx.UserValue[deleteParamKey].(*DeleteParam) 40 | } 41 | -------------------------------------------------------------------------------- /plugins/admin/modules/guard/export.go: -------------------------------------------------------------------------------- 1 | package guard 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/GoAdminGroup/go-admin/context" 7 | "github.com/GoAdminGroup/go-admin/modules/errors" 8 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 9 | ) 10 | 11 | type ExportParam struct { 12 | Panel table.Table 13 | Id []string 14 | Prefix string 15 | IsAll bool 16 | } 17 | 18 | func (g *Guard) Export(ctx *context.Context) { 19 | panel, prefix := g.table(ctx) 20 | if !panel.GetExportable() { 21 | alert(ctx, panel, errors.OperationNotAllow, g.conn, g.navBtns) 22 | ctx.Abort() 23 | return 24 | } 25 | 26 | idStr := make([]string, 0) 27 | ids := ctx.FormValue("id") 28 | if ids != "" { 29 | idStr = strings.Split(ctx.FormValue("id"), ",") 30 | } 31 | 32 | ctx.SetUserValue(exportParamKey, &ExportParam{ 33 | Panel: panel, 34 | Id: idStr, 35 | Prefix: prefix, 36 | IsAll: ctx.FormValue("is_all") == "true", 37 | }) 38 | ctx.Next() 39 | } 40 | 41 | func GetExportParam(ctx *context.Context) *ExportParam { 42 | return ctx.UserValue[exportParamKey].(*ExportParam) 43 | } 44 | -------------------------------------------------------------------------------- /plugins/admin/modules/guard/guard.go: -------------------------------------------------------------------------------- 1 | package guard 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/modules/db" 6 | "github.com/GoAdminGroup/go-admin/modules/errors" 7 | "github.com/GoAdminGroup/go-admin/modules/service" 8 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" 9 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/response" 10 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 11 | "github.com/GoAdminGroup/go-admin/template" 12 | "github.com/GoAdminGroup/go-admin/template/types" 13 | ) 14 | 15 | type Guard struct { 16 | services service.List 17 | conn db.Connection 18 | tableList table.GeneratorList 19 | navBtns *types.Buttons 20 | } 21 | 22 | func New(s service.List, c db.Connection, t table.GeneratorList, b *types.Buttons) *Guard { 23 | return &Guard{ 24 | services: s, 25 | conn: c, 26 | tableList: t, 27 | navBtns: b, 28 | } 29 | } 30 | 31 | func (g *Guard) table(ctx *context.Context) (table.Table, string) { 32 | prefix := ctx.Query(constant.PrefixKey) 33 | return g.tableList[prefix](ctx), prefix 34 | } 35 | 36 | func (g *Guard) CheckPrefix(ctx *context.Context) { 37 | 38 | prefix := ctx.Query(constant.PrefixKey) 39 | 40 | if _, ok := g.tableList[prefix]; !ok { 41 | if ctx.Headers(constant.PjaxHeader) == "" && ctx.Method() != "GET" { 42 | response.BadRequest(ctx, errors.Msg) 43 | } else { 44 | response.Alert(ctx, errors.Msg, errors.Msg, "table model not found", g.conn, g.navBtns, 45 | template.Missing404Page) 46 | } 47 | ctx.Abort() 48 | return 49 | } 50 | 51 | ctx.Next() 52 | } 53 | 54 | const ( 55 | editFormParamKey = "edit_form_param" 56 | deleteParamKey = "delete_param" 57 | exportParamKey = "export_param" 58 | serverLoginParamKey = "server_login_param" 59 | deleteMenuParamKey = "delete_menu_param" 60 | editMenuParamKey = "edit_menu_param" 61 | newMenuParamKey = "new_menu_param" 62 | newFormParamKey = "new_form_param" 63 | updateParamKey = "update_param" 64 | showFormParamKey = "show_form_param" 65 | showNewFormParam = "show_new_form_param" 66 | ) 67 | -------------------------------------------------------------------------------- /plugins/admin/modules/guard/menu_delete.go: -------------------------------------------------------------------------------- 1 | package guard 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/modules/errors" 6 | ) 7 | 8 | type MenuDeleteParam struct { 9 | Id string 10 | } 11 | 12 | func (g *Guard) MenuDelete(ctx *context.Context) { 13 | 14 | id := ctx.Query("id") 15 | 16 | if id == "" { 17 | alertWithTitleAndDesc(ctx, "Menu", "menu", errors.WrongID, g.conn, g.navBtns) 18 | ctx.Abort() 19 | return 20 | } 21 | 22 | // TODO: check the user permission 23 | 24 | ctx.SetUserValue(deleteMenuParamKey, &MenuDeleteParam{ 25 | Id: id, 26 | }) 27 | ctx.Next() 28 | } 29 | 30 | func GetMenuDeleteParam(ctx *context.Context) *MenuDeleteParam { 31 | return ctx.UserValue[deleteMenuParamKey].(*MenuDeleteParam) 32 | } 33 | -------------------------------------------------------------------------------- /plugins/admin/modules/guard/menu_edit.go: -------------------------------------------------------------------------------- 1 | package guard 2 | 3 | import ( 4 | "html/template" 5 | "strconv" 6 | 7 | "github.com/GoAdminGroup/go-admin/context" 8 | "github.com/GoAdminGroup/go-admin/modules/auth" 9 | "github.com/GoAdminGroup/go-admin/modules/errors" 10 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" 11 | ) 12 | 13 | type MenuEditParam struct { 14 | Id string 15 | Title string 16 | Header string 17 | PluginName string 18 | ParentId int64 19 | Icon string 20 | Uri string 21 | Roles []string 22 | Alert template.HTML 23 | } 24 | 25 | func (e MenuEditParam) HasAlert() bool { 26 | return e.Alert != template.HTML("") 27 | } 28 | 29 | func (g *Guard) MenuEdit(ctx *context.Context) { 30 | 31 | parentId := ctx.FormValue("parent_id") 32 | if parentId == "" { 33 | parentId = "0" 34 | } 35 | 36 | var ( 37 | parentIdInt, _ = strconv.Atoi(parentId) 38 | token = ctx.FormValue(form.TokenKey) 39 | alert template.HTML 40 | ) 41 | 42 | if !auth.GetTokenService(g.services.Get(auth.TokenServiceKey)).CheckToken(token) { 43 | alert = getAlert(ctx, errors.EditFailWrongToken) 44 | } 45 | 46 | if alert == "" { 47 | alert = checkEmpty(ctx, "id", "title", "icon") 48 | } 49 | 50 | ctx.SetUserValue(editMenuParamKey, &MenuEditParam{ 51 | Id: ctx.FormValue("id"), 52 | Title: ctx.FormValue("title"), 53 | Header: ctx.FormValue("header"), 54 | PluginName: ctx.FormValue("plugin_name"), 55 | ParentId: int64(parentIdInt), 56 | Icon: ctx.FormValue("icon"), 57 | Uri: ctx.FormValue("uri"), 58 | Roles: ctx.Request.Form["roles[]"], 59 | Alert: alert, 60 | }) 61 | ctx.Next() 62 | } 63 | 64 | func GetMenuEditParam(ctx *context.Context) *MenuEditParam { 65 | return ctx.UserValue[editMenuParamKey].(*MenuEditParam) 66 | } 67 | 68 | func checkEmpty(ctx *context.Context, key ...string) template.HTML { 69 | for _, k := range key { 70 | if ctx.FormValue(k) == "" { 71 | return getAlert(ctx, "wrong "+k) 72 | } 73 | } 74 | return template.HTML("") 75 | } 76 | -------------------------------------------------------------------------------- /plugins/admin/modules/guard/menu_new.go: -------------------------------------------------------------------------------- 1 | package guard 2 | 3 | import ( 4 | "html/template" 5 | "strconv" 6 | 7 | "github.com/GoAdminGroup/go-admin/context" 8 | "github.com/GoAdminGroup/go-admin/modules/auth" 9 | "github.com/GoAdminGroup/go-admin/modules/errors" 10 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" 11 | ) 12 | 13 | type MenuNewParam struct { 14 | Title string 15 | Header string 16 | ParentId int64 17 | Icon string 18 | PluginName string 19 | Uri string 20 | Roles []string 21 | Alert template.HTML 22 | } 23 | 24 | func (e MenuNewParam) HasAlert() bool { 25 | return e.Alert != template.HTML("") 26 | } 27 | 28 | func (g *Guard) MenuNew(ctx *context.Context) { 29 | 30 | parentId := ctx.FormValue("parent_id") 31 | if parentId == "" { 32 | parentId = "0" 33 | } 34 | 35 | var ( 36 | alert template.HTML 37 | token = ctx.FormValue(form.TokenKey) 38 | ) 39 | 40 | if !auth.GetTokenService(g.services.Get(auth.TokenServiceKey)).CheckToken(token) { 41 | alert = getAlert(ctx, errors.EditFailWrongToken) 42 | } 43 | 44 | if alert == "" { 45 | alert = checkEmpty(ctx, "title", "icon") 46 | } 47 | 48 | parentIdInt, _ := strconv.Atoi(parentId) 49 | 50 | ctx.SetUserValue(newMenuParamKey, &MenuNewParam{ 51 | Title: ctx.FormValue("title"), 52 | Header: ctx.FormValue("header"), 53 | PluginName: ctx.FormValue("plugin_name"), 54 | ParentId: int64(parentIdInt), 55 | Icon: ctx.FormValue("icon"), 56 | Uri: ctx.FormValue("uri"), 57 | Roles: ctx.Request.Form["roles[]"], 58 | Alert: alert, 59 | }) 60 | ctx.Next() 61 | } 62 | 63 | func GetMenuNewParam(ctx *context.Context) *MenuNewParam { 64 | return ctx.UserValue[newMenuParamKey].(*MenuNewParam) 65 | } 66 | -------------------------------------------------------------------------------- /plugins/admin/modules/guard/server_login.go: -------------------------------------------------------------------------------- 1 | package guard 2 | 3 | import ( 4 | "encoding/json" 5 | "io/ioutil" 6 | 7 | "github.com/GoAdminGroup/go-admin/context" 8 | "github.com/GoAdminGroup/go-admin/modules/logger" 9 | ) 10 | 11 | type ServerLoginParam struct { 12 | Account string 13 | Password string 14 | } 15 | 16 | func (g *Guard) ServerLogin(ctx *context.Context) { 17 | 18 | var p ServerLoginParam 19 | 20 | body, err := ioutil.ReadAll(ctx.Request.Body) 21 | 22 | if err != nil { 23 | logger.Error("get server login parameter error: ", err) 24 | } 25 | 26 | err = json.Unmarshal(body, &p) 27 | 28 | if err != nil { 29 | logger.Error("unmarshal server login parameter error: ", err) 30 | } 31 | 32 | ctx.SetUserValue(serverLoginParamKey, &p) 33 | ctx.Next() 34 | } 35 | 36 | func GetServerLoginParam(ctx *context.Context) *ServerLoginParam { 37 | return ctx.UserValue[serverLoginParamKey].(*ServerLoginParam) 38 | } 39 | -------------------------------------------------------------------------------- /plugins/admin/modules/guard/update.go: -------------------------------------------------------------------------------- 1 | package guard 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/GoAdminGroup/go-admin/context" 7 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" 8 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 9 | ) 10 | 11 | type UpdateParam struct { 12 | Panel table.Table 13 | Prefix string 14 | Value form.Values 15 | } 16 | 17 | func (g *Guard) Update(ctx *context.Context) { 18 | panel, prefix := g.table(ctx) 19 | 20 | pname := panel.GetPrimaryKey().Name 21 | 22 | id := ctx.FormValue("pk") 23 | 24 | if id == "" { 25 | ctx.JSON(http.StatusBadRequest, map[string]interface{}{ 26 | "msg": "wrong " + pname, 27 | }) 28 | ctx.Abort() 29 | return 30 | } 31 | 32 | var f = make(form.Values) 33 | f.Add(form.PostIsSingleUpdateKey, "1") 34 | f.Add(pname, id) 35 | f.Add(ctx.FormValue("name"), ctx.FormValue("value")) 36 | 37 | ctx.SetUserValue(updateParamKey, &UpdateParam{ 38 | Panel: panel, 39 | Prefix: prefix, 40 | Value: f, 41 | }) 42 | ctx.Next() 43 | } 44 | 45 | func GetUpdateParam(ctx *context.Context) *UpdateParam { 46 | return ctx.UserValue[updateParamKey].(*UpdateParam) 47 | } 48 | -------------------------------------------------------------------------------- /plugins/admin/modules/helper.go: -------------------------------------------------------------------------------- 1 | package modules 2 | 3 | import ( 4 | "html/template" 5 | "strconv" 6 | 7 | "github.com/google/uuid" 8 | ) 9 | 10 | func InArray(arr []string, str string) bool { 11 | for _, v := range arr { 12 | if v == str { 13 | return true 14 | } 15 | } 16 | return false 17 | } 18 | 19 | func Delimiter(del, del2, s string) string { 20 | return del + s + del2 21 | } 22 | 23 | func FilterField(filed, delimiter, delimiter2 string) string { 24 | return delimiter + filed + delimiter2 25 | } 26 | 27 | func InArrayWithoutEmpty(arr []string, str string) bool { 28 | if len(arr) == 0 { 29 | return true 30 | } 31 | for _, v := range arr { 32 | if v == str { 33 | return true 34 | } 35 | } 36 | return false 37 | } 38 | 39 | func RemoveBlankFromArray(s []string) []string { 40 | var r []string 41 | for _, str := range s { 42 | if str != "" { 43 | r = append(r, str) 44 | } 45 | } 46 | return r 47 | } 48 | 49 | func Uuid() string { 50 | return uuid.New().String() 51 | } 52 | 53 | func SetDefault(source, def string) string { 54 | if source == "" { 55 | return def 56 | } 57 | return source 58 | } 59 | 60 | func GetPage(page string) (pageInt int) { 61 | if page == "" { 62 | pageInt = 1 63 | } else { 64 | pageInt, _ = strconv.Atoi(page) 65 | } 66 | return 67 | } 68 | 69 | func AorB(condition bool, a, b string) string { 70 | if condition { 71 | return a 72 | } 73 | return b 74 | } 75 | 76 | func AorEmpty(condition bool, a string) string { 77 | if condition { 78 | return a 79 | } 80 | return "" 81 | } 82 | 83 | func AorBHTML(condition bool, a, b template.HTML) template.HTML { 84 | if condition { 85 | return a 86 | } 87 | return b 88 | } 89 | -------------------------------------------------------------------------------- /plugins/admin/modules/helper_test.go: -------------------------------------------------------------------------------- 1 | package modules 2 | 3 | import ( 4 | "regexp" 5 | "testing" 6 | 7 | "github.com/magiconair/properties/assert" 8 | ) 9 | 10 | func TestInArray(t *testing.T) { 11 | assert.Equal(t, isFormURL("/admin/info/profile/new"), true) 12 | } 13 | 14 | func isFormURL(s string) bool { 15 | reg, _ := regexp.Compile("(.*?)info/(.*)/(new|edit)(.*?)") 16 | return reg.MatchString(s) 17 | } 18 | -------------------------------------------------------------------------------- /plugins/admin/modules/paginator/paginator_test.go: -------------------------------------------------------------------------------- 1 | package paginator 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/GoAdminGroup/go-admin/modules/config" 7 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" 8 | _ "github.com/GoAdminGroup/themes/sword" 9 | ) 10 | 11 | func TestGet(t *testing.T) { 12 | config.Initialize(&config.Config{Theme: "sword"}) 13 | param := parameter.BaseParam() 14 | param.Page = "7" 15 | Get(nil, Config{ 16 | Size: 105, 17 | Param: param, 18 | PageSizeList: []string{"10", "20", "50", "100"}, 19 | }) 20 | } 21 | -------------------------------------------------------------------------------- /plugins/admin/modules/parameter/parameter_test.go: -------------------------------------------------------------------------------- 1 | package parameter 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestGetParamFromUrl(t *testing.T) { 9 | fmt.Println(GetParamFromURL("/admin/info/user?__page=1&__pageSize=10&__sort=id&__sort_type=desc", 10 | 1, "asc", "id")) 11 | } 12 | 13 | func TestParameters_PKs(t *testing.T) { 14 | pks := BaseParam().PKs() 15 | fmt.Println("pks", pks, "len", len(pks)) 16 | } 17 | -------------------------------------------------------------------------------- /plugins/admin/modules/table/default_test.go: -------------------------------------------------------------------------------- 1 | package table 2 | -------------------------------------------------------------------------------- /plugins/example/example.go: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | import ( 4 | c "github.com/GoAdminGroup/go-admin/modules/config" 5 | "github.com/GoAdminGroup/go-admin/modules/service" 6 | "github.com/GoAdminGroup/go-admin/plugins" 7 | ) 8 | 9 | type Example struct { 10 | *plugins.Base 11 | } 12 | 13 | func NewExample() *Example { 14 | return &Example{ 15 | Base: &plugins.Base{PlugName: "example"}, 16 | } 17 | } 18 | 19 | func (e *Example) InitPlugin(srv service.List) { 20 | e.InitBase(srv, "example") 21 | e.App = e.initRouter(c.Prefix(), srv) 22 | } 23 | -------------------------------------------------------------------------------- /plugins/example/go_plugin/Makefile: -------------------------------------------------------------------------------- 1 | all: build 2 | 3 | build: 4 | go build -buildmode=plugin -o plugin.so main.go -------------------------------------------------------------------------------- /plugins/example/go_plugin/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/modules/auth" 6 | c "github.com/GoAdminGroup/go-admin/modules/config" 7 | "github.com/GoAdminGroup/go-admin/modules/db" 8 | "github.com/GoAdminGroup/go-admin/modules/service" 9 | "github.com/GoAdminGroup/go-admin/plugins" 10 | ) 11 | 12 | type Example struct { 13 | *plugins.Base 14 | } 15 | 16 | var Plugin = &Example{ 17 | Base: &plugins.Base{PlugName: "example"}, 18 | } 19 | 20 | func (example *Example) InitPlugin(srv service.List) { 21 | example.InitBase(srv, "example") 22 | Plugin.App = example.initRouter(c.Prefix(), srv) 23 | } 24 | 25 | func (example *Example) initRouter(prefix string, srv service.List) *context.App { 26 | 27 | app := context.NewApp() 28 | route := app.Group(prefix) 29 | route.GET("/example", auth.Middleware(db.GetConnection(srv)), example.TestHandler) 30 | 31 | return app 32 | } 33 | 34 | func (example *Example) TestHandler(ctx *context.Context) { 35 | 36 | } 37 | -------------------------------------------------------------------------------- /plugins/example/router.go: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/modules/auth" 6 | "github.com/GoAdminGroup/go-admin/modules/db" 7 | "github.com/GoAdminGroup/go-admin/modules/service" 8 | ) 9 | 10 | func (e *Example) initRouter(prefix string, srv service.List) *context.App { 11 | 12 | app := context.NewApp() 13 | route := app.Group(prefix) 14 | route.GET("/example", auth.Middleware(db.GetConnection(srv)), e.TestHandler) 15 | 16 | return app 17 | } 18 | -------------------------------------------------------------------------------- /plugins/plugins_test.go: -------------------------------------------------------------------------------- 1 | package plugins 2 | 3 | import "testing" 4 | 5 | func TestLoadFromPlugin(t *testing.T) { 6 | LoadFromPlugin("./example/go_plugin/plugin.so") 7 | } 8 | -------------------------------------------------------------------------------- /template/chartjs/assets_list.go: -------------------------------------------------------------------------------- 1 | package chartjs 2 | 3 | var AssetsList = []string{ 4 | "/chart.min.js", 5 | } 6 | -------------------------------------------------------------------------------- /template/chartjs/chartjs.tmpl: -------------------------------------------------------------------------------- 1 | {{define "chartjs"}} 2 | {{if ne .Title ""}} 3 |

4 | {{langHtml .Title}} 5 |

6 | {{end}} 7 |
8 | 9 |
10 | 13 | {{end}} -------------------------------------------------------------------------------- /template/chartjs/radar.go: -------------------------------------------------------------------------------- 1 | package chartjs 2 | -------------------------------------------------------------------------------- /template/chartjs/template.go: -------------------------------------------------------------------------------- 1 | package chartjs 2 | 3 | var List = map[string]string{ 4 | "chartjs": `{{define "chartjs"}} 5 | {{if ne .Title ""}} 6 |

7 | {{langHtml .Title}} 8 |

9 | {{end}} 10 |
11 | 12 |
13 | 16 | {{end}}`, 17 | } 18 | -------------------------------------------------------------------------------- /template/components/alert.go: -------------------------------------------------------------------------------- 1 | package components 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/modules/errors" 7 | "github.com/GoAdminGroup/go-admin/modules/language" 8 | "github.com/GoAdminGroup/go-admin/template/types" 9 | ) 10 | 11 | type AlertAttribute struct { 12 | Name string 13 | Theme string 14 | Title template.HTML 15 | Content template.HTML 16 | types.Attribute 17 | } 18 | 19 | func (compo *AlertAttribute) SetTheme(value string) types.AlertAttribute { 20 | compo.Theme = value 21 | return compo 22 | } 23 | 24 | func (compo *AlertAttribute) SetTitle(value template.HTML) types.AlertAttribute { 25 | compo.Title = value 26 | return compo 27 | } 28 | 29 | func (compo *AlertAttribute) SetContent(value template.HTML) types.AlertAttribute { 30 | compo.Content = value 31 | return compo 32 | } 33 | 34 | func (compo *AlertAttribute) Warning(msg string) template.HTML { 35 | return compo.SetTitle(errors.MsgWithIcon). 36 | SetTheme("warning"). 37 | SetContent(language.GetFromHtml(template.HTML(msg))). 38 | GetContent() 39 | } 40 | 41 | func (compo *AlertAttribute) GetContent() template.HTML { 42 | return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "alert") 43 | } 44 | -------------------------------------------------------------------------------- /template/components/col.go: -------------------------------------------------------------------------------- 1 | package components 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/template/types" 7 | ) 8 | 9 | type ColAttribute struct { 10 | Name string 11 | Content template.HTML 12 | Size string 13 | types.Attribute 14 | } 15 | 16 | func (compo *ColAttribute) SetContent(value template.HTML) types.ColAttribute { 17 | compo.Content = value 18 | return compo 19 | } 20 | 21 | func (compo *ColAttribute) AddContent(value template.HTML) types.ColAttribute { 22 | compo.Content += value 23 | return compo 24 | } 25 | 26 | func (compo *ColAttribute) SetSize(value types.S) types.ColAttribute { 27 | compo.Size = "" 28 | for key, size := range value { 29 | compo.Size += "col-" + key + "-" + size + " " 30 | } 31 | return compo 32 | } 33 | 34 | func (compo *ColAttribute) GetContent() template.HTML { 35 | return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "col") 36 | } 37 | -------------------------------------------------------------------------------- /template/components/composer.go: -------------------------------------------------------------------------------- 1 | package components 2 | 3 | import ( 4 | "bytes" 5 | "html/template" 6 | 7 | "github.com/GoAdminGroup/go-admin/modules/config" 8 | "github.com/GoAdminGroup/go-admin/modules/logger" 9 | "github.com/GoAdminGroup/go-admin/modules/utils" 10 | template2 "github.com/GoAdminGroup/go-admin/template" 11 | ) 12 | 13 | func ComposeHtml(temList map[string]string, separation bool, compo interface{}, templateName ...string) template.HTML { 14 | 15 | tmplName := "" 16 | if len(templateName) > 0 { 17 | tmplName = templateName[0] + " " 18 | } 19 | 20 | var ( 21 | tmpl *template.Template 22 | err error 23 | ) 24 | 25 | if separation { 26 | files := make([]string, 0) 27 | root := config.GetAssetRootPath() + "pages/" 28 | for _, v := range templateName { 29 | files = append(files, root+temList["components/"+v]+".tmpl") 30 | } 31 | tmpl, err = template.New("comp").Funcs(template2.DefaultFuncMap).ParseFiles(files...) 32 | } else { 33 | var text = "" 34 | for _, v := range templateName { 35 | text += temList["components/"+v] 36 | } 37 | tmpl, err = template.New("comp").Funcs(template2.DefaultFuncMap).Parse(text) 38 | } 39 | 40 | if err != nil { 41 | logger.Panic(tmplName + "ComposeHtml Error:" + err.Error()) 42 | return "" 43 | } 44 | buf := new(bytes.Buffer) 45 | 46 | defineName := utils.ReplaceAll(templateName[0], "table/", "", "form/", "") 47 | 48 | err = tmpl.ExecuteTemplate(buf, defineName, compo) 49 | if err != nil { 50 | logger.Error(tmplName+" ComposeHtml Error:", err) 51 | } 52 | return template.HTML(buf.String()) 53 | } 54 | -------------------------------------------------------------------------------- /template/components/image.go: -------------------------------------------------------------------------------- 1 | package components 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules" 7 | "github.com/GoAdminGroup/go-admin/template/types" 8 | ) 9 | 10 | type ImgAttribute struct { 11 | Name string 12 | Width string 13 | Height string 14 | Uuid string 15 | HasModal bool 16 | Src template.URL 17 | types.Attribute 18 | } 19 | 20 | func (compo *ImgAttribute) SetWidth(value string) types.ImgAttribute { 21 | compo.Width = value 22 | return compo 23 | } 24 | 25 | func (compo *ImgAttribute) SetHeight(value string) types.ImgAttribute { 26 | compo.Height = value 27 | return compo 28 | } 29 | 30 | func (compo *ImgAttribute) WithModal() types.ImgAttribute { 31 | compo.HasModal = true 32 | compo.Uuid = modules.Uuid() 33 | return compo 34 | } 35 | 36 | func (compo *ImgAttribute) SetSrc(value template.HTML) types.ImgAttribute { 37 | compo.Src = template.URL(value) 38 | return compo 39 | } 40 | 41 | func (compo *ImgAttribute) GetContent() template.HTML { 42 | return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "image") 43 | } 44 | -------------------------------------------------------------------------------- /template/components/label.go: -------------------------------------------------------------------------------- 1 | package components 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/template/types" 7 | ) 8 | 9 | type LabelAttribute struct { 10 | Name string 11 | Color template.HTML 12 | Type string 13 | Content template.HTML 14 | types.Attribute 15 | } 16 | 17 | func (compo *LabelAttribute) SetType(value string) types.LabelAttribute { 18 | compo.Type = value 19 | return compo 20 | } 21 | 22 | func (compo *LabelAttribute) SetColor(value template.HTML) types.LabelAttribute { 23 | compo.Color = value 24 | return compo 25 | } 26 | 27 | func (compo *LabelAttribute) SetContent(value template.HTML) types.LabelAttribute { 28 | compo.Content = value 29 | return compo 30 | } 31 | 32 | func (compo *LabelAttribute) GetContent() template.HTML { 33 | return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "label") 34 | } 35 | -------------------------------------------------------------------------------- /template/components/link.go: -------------------------------------------------------------------------------- 1 | package components 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/template/types" 7 | ) 8 | 9 | type LinkAttribute struct { 10 | Name string 11 | URL string 12 | Class template.HTML 13 | Title template.HTML 14 | Attributes template.HTMLAttr 15 | Content template.HTML 16 | types.Attribute 17 | } 18 | 19 | func (compo *LinkAttribute) OpenInNewTab() types.LinkAttribute { 20 | compo.Class += " new-tab-link" 21 | return compo 22 | } 23 | 24 | func (compo *LinkAttribute) SetURL(value string) types.LinkAttribute { 25 | compo.URL = value 26 | return compo 27 | } 28 | 29 | func (compo *LinkAttribute) SetClass(class template.HTML) types.LinkAttribute { 30 | compo.Class = class 31 | return compo 32 | } 33 | 34 | func (compo *LinkAttribute) SetAttributes(attr template.HTMLAttr) types.LinkAttribute { 35 | compo.Attributes = attr 36 | return compo 37 | } 38 | 39 | func (compo *LinkAttribute) NoPjax() types.LinkAttribute { 40 | compo.Class += " no-pjax" 41 | return compo 42 | } 43 | 44 | func (compo *LinkAttribute) SetTabTitle(value template.HTML) types.LinkAttribute { 45 | compo.Title = value 46 | return compo 47 | } 48 | 49 | func (compo *LinkAttribute) SetContent(value template.HTML) types.LinkAttribute { 50 | compo.Content = value 51 | return compo 52 | } 53 | 54 | func (compo *LinkAttribute) GetContent() template.HTML { 55 | return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "link") 56 | } 57 | -------------------------------------------------------------------------------- /template/components/popup.go: -------------------------------------------------------------------------------- 1 | package components 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/template/types" 7 | ) 8 | 9 | type PopupAttribute struct { 10 | Name string 11 | ID string 12 | Body template.HTML 13 | Footer template.HTML 14 | FooterHTML template.HTML 15 | Title template.HTML 16 | Size string 17 | HideFooter bool 18 | Height string 19 | Width string 20 | Draggable bool 21 | types.Attribute 22 | } 23 | 24 | func (compo *PopupAttribute) SetID(value string) types.PopupAttribute { 25 | compo.ID = value 26 | return compo 27 | } 28 | 29 | func (compo *PopupAttribute) SetTitle(value template.HTML) types.PopupAttribute { 30 | compo.Title = value 31 | return compo 32 | } 33 | 34 | func (compo *PopupAttribute) SetFooter(value template.HTML) types.PopupAttribute { 35 | compo.Footer = value 36 | return compo 37 | } 38 | 39 | func (compo *PopupAttribute) SetFooterHTML(value template.HTML) types.PopupAttribute { 40 | compo.FooterHTML = value 41 | return compo 42 | } 43 | 44 | func (compo *PopupAttribute) SetWidth(width string) types.PopupAttribute { 45 | compo.Width = width 46 | return compo 47 | } 48 | 49 | func (compo *PopupAttribute) SetHeight(height string) types.PopupAttribute { 50 | compo.Height = height 51 | return compo 52 | } 53 | 54 | func (compo *PopupAttribute) SetDraggable() types.PopupAttribute { 55 | compo.Draggable = true 56 | return compo 57 | } 58 | 59 | func (compo *PopupAttribute) SetHideFooter() types.PopupAttribute { 60 | compo.HideFooter = true 61 | return compo 62 | } 63 | 64 | func (compo *PopupAttribute) SetBody(value template.HTML) types.PopupAttribute { 65 | compo.Body = value 66 | return compo 67 | } 68 | 69 | func (compo *PopupAttribute) SetSize(value string) types.PopupAttribute { 70 | compo.Size = value 71 | return compo 72 | } 73 | 74 | func (compo *PopupAttribute) GetContent() template.HTML { 75 | return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "popup") 76 | } 77 | -------------------------------------------------------------------------------- /template/components/product.go: -------------------------------------------------------------------------------- 1 | package components 2 | -------------------------------------------------------------------------------- /template/components/row.go: -------------------------------------------------------------------------------- 1 | package components 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/template/types" 7 | ) 8 | 9 | type RowAttribute struct { 10 | Name string 11 | Content template.HTML 12 | types.Attribute 13 | } 14 | 15 | func (compo *RowAttribute) SetContent(value template.HTML) types.RowAttribute { 16 | compo.Content = value 17 | return compo 18 | } 19 | 20 | func (compo *RowAttribute) AddContent(value template.HTML) types.RowAttribute { 21 | compo.Content += value 22 | return compo 23 | } 24 | 25 | func (compo *RowAttribute) GetContent() template.HTML { 26 | return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "row") 27 | } 28 | -------------------------------------------------------------------------------- /template/components/tabs.go: -------------------------------------------------------------------------------- 1 | package components 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/template/types" 7 | ) 8 | 9 | type TabsAttribute struct { 10 | Name string 11 | Data []map[string]template.HTML 12 | types.Attribute 13 | } 14 | 15 | func (compo *TabsAttribute) SetData(value []map[string]template.HTML) types.TabsAttribute { 16 | compo.Data = value 17 | return compo 18 | } 19 | 20 | func (compo *TabsAttribute) GetContent() template.HTML { 21 | return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "tabs") 22 | } 23 | -------------------------------------------------------------------------------- /template/components/tree.go: -------------------------------------------------------------------------------- 1 | package components 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/modules/menu" 7 | "github.com/GoAdminGroup/go-admin/template/types" 8 | ) 9 | 10 | type TreeAttribute struct { 11 | Name string 12 | Tree []menu.Item 13 | EditUrl string 14 | DeleteUrl string 15 | UrlPrefix string 16 | OrderUrl string 17 | types.Attribute 18 | } 19 | 20 | func (compo *TreeAttribute) SetTree(value []menu.Item) types.TreeAttribute { 21 | compo.Tree = value 22 | return compo 23 | } 24 | 25 | func (compo *TreeAttribute) SetEditUrl(value string) types.TreeAttribute { 26 | compo.EditUrl = value 27 | return compo 28 | } 29 | 30 | func (compo *TreeAttribute) SetUrlPrefix(value string) types.TreeAttribute { 31 | compo.UrlPrefix = value 32 | return compo 33 | } 34 | 35 | func (compo *TreeAttribute) SetDeleteUrl(value string) types.TreeAttribute { 36 | compo.DeleteUrl = value 37 | return compo 38 | } 39 | 40 | func (compo *TreeAttribute) SetOrderUrl(value string) types.TreeAttribute { 41 | compo.OrderUrl = value 42 | return compo 43 | } 44 | 45 | func (compo *TreeAttribute) GetContent() template.HTML { 46 | return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "tree") 47 | } 48 | 49 | func (compo *TreeAttribute) GetTreeHeader() template.HTML { 50 | return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "tree-header") 51 | } 52 | -------------------------------------------------------------------------------- /template/components/treeview.go: -------------------------------------------------------------------------------- 1 | package components 2 | 3 | import ( 4 | "encoding/json" 5 | "html/template" 6 | 7 | "github.com/GoAdminGroup/go-admin/modules/utils" 8 | "github.com/GoAdminGroup/go-admin/template/types" 9 | ) 10 | 11 | type TreeViewAttribute struct { 12 | Name string 13 | ID string 14 | Tree types.TreeViewData 15 | TreeJSON template.JS 16 | UrlPrefix string 17 | types.Attribute 18 | } 19 | 20 | func (compo *TreeViewAttribute) SetID(id string) types.TreeViewAttribute { 21 | compo.ID = id 22 | return compo 23 | } 24 | 25 | func (compo *TreeViewAttribute) SetTree(value types.TreeViewData) types.TreeViewAttribute { 26 | compo.Tree = value 27 | return compo 28 | } 29 | 30 | func (compo *TreeViewAttribute) SetUrlPrefix(value string) types.TreeViewAttribute { 31 | compo.UrlPrefix = value 32 | return compo 33 | } 34 | 35 | func (compo *TreeViewAttribute) GetContent() template.HTML { 36 | if compo.ID == "" { 37 | compo.ID = utils.Uuid(10) 38 | } 39 | b, _ := json.Marshal(compo.Tree) 40 | compo.TreeJSON = template.JS(b) 41 | return ComposeHtml(compo.TemplateList, compo.Separation, *compo, "treeview") 42 | } 43 | -------------------------------------------------------------------------------- /template/installation/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | find ./ -name ".DS_Store" -depth -exec rm {} \; 3 | adm combine js --path=./assets/src/js/combine/ --out=./assets/login/dist/all.min.js 4 | adm combine css --path=./assets/src/css/ --out=./assets/login/dist/all.min.css 5 | adm compile asset --path=./assets/login/dist/ --out=./ --pa=login -------------------------------------------------------------------------------- /template/installation/assets/src/css/noscript.css: -------------------------------------------------------------------------------- 1 | /* 2 | Ethereal by HTML5 UP 3 | html5up.net | @ajlkn 4 | Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | */ 6 | 7 | /* Page */ 8 | 9 | body { 10 | overflow-x: scroll; 11 | } -------------------------------------------------------------------------------- /template/installation/assets/src/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/go-admin/cd8748f96e19ce3c4bf437520542b097899fc16e/template/installation/assets/src/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /template/installation/assets/src/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/go-admin/cd8748f96e19ce3c4bf437520542b097899fc16e/template/installation/assets/src/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /template/installation/assets/src/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/go-admin/cd8748f96e19ce3c4bf437520542b097899fc16e/template/installation/assets/src/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /template/installation/assets/src/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/go-admin/cd8748f96e19ce3c4bf437520542b097899fc16e/template/installation/assets/src/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /template/installation/assets/src/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/go-admin/cd8748f96e19ce3c4bf437520542b097899fc16e/template/installation/assets/src/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /template/installation/assets_list.go: -------------------------------------------------------------------------------- 1 | package login 2 | 3 | var AssetsList = []string{ 4 | "/login/dist/all.min.css", 5 | "/login/dist/all.min.js", 6 | "/login/dist/respond.min.js", 7 | } 8 | -------------------------------------------------------------------------------- /template/installation/installation.go: -------------------------------------------------------------------------------- 1 | package login 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "html/template" 7 | "strings" 8 | 9 | "github.com/GoAdminGroup/go-admin/modules/language" 10 | "github.com/GoAdminGroup/go-admin/modules/logger" 11 | ) 12 | 13 | type Installation struct { 14 | Name string 15 | } 16 | 17 | func Get() *Installation { 18 | return &Installation{ 19 | Name: "installation", 20 | } 21 | } 22 | 23 | var DefaultFuncMap = template.FuncMap{ 24 | "lang": language.Get, 25 | "langHtml": language.GetFromHtml, 26 | "link": func(cdnUrl, prefixUrl, assetsUrl string) string { 27 | if cdnUrl == "" { 28 | return prefixUrl + assetsUrl 29 | } 30 | return cdnUrl + assetsUrl 31 | }, 32 | "isLinkUrl": func(s string) bool { 33 | return (len(s) > 7 && s[:7] == "http://") || (len(s) > 8 && s[:8] == "https://") 34 | }, 35 | "render": func(s, old, repl template.HTML) template.HTML { 36 | return template.HTML(strings.ReplaceAll(string(s), string(old), string(repl))) 37 | }, 38 | "renderJS": func(s template.JS, old, repl template.HTML) template.JS { 39 | return template.JS(strings.ReplaceAll(string(s), string(old), string(repl))) 40 | }, 41 | "divide": func(a, b int) int { 42 | return a / b 43 | }, 44 | } 45 | 46 | func (i *Installation) GetTemplate() (*template.Template, string) { 47 | tmpl, err := template.New("installation"). 48 | Funcs(DefaultFuncMap). 49 | Parse(List["installation"]) 50 | 51 | if err != nil { 52 | logger.Error("Installation GetTemplate Error: ", err) 53 | } 54 | 55 | return tmpl, "installation" 56 | } 57 | 58 | func (i *Installation) GetAssetList() []string { return AssetsList } 59 | func (i *Installation) GetAsset(name string) ([]byte, error) { return Asset(name[1:]) } 60 | func (i *Installation) IsAPage() bool { return true } 61 | func (i *Installation) GetName() string { return "login" } 62 | 63 | func (i *Installation) GetContent() template.HTML { 64 | buffer := new(bytes.Buffer) 65 | tmpl, defineName := i.GetTemplate() 66 | err := tmpl.ExecuteTemplate(buffer, defineName, i) 67 | if err != nil { 68 | fmt.Println("ComposeHtml Error:", err) 69 | } 70 | return template.HTML(buffer.String()) 71 | } 72 | -------------------------------------------------------------------------------- /template/login/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | find ./ -name ".DS_Store" -depth -exec rm {} \; 3 | adm combine js --path=./assets/src/js/combine/ --out=./assets/login/dist/all.min.js 4 | adm combine css --path=./assets/src/css/ --out=./assets/login/dist/all.min.css 5 | adm compile asset --path=./assets/login/dist/ --out=./ --pa=login -------------------------------------------------------------------------------- /template/login/assets/src/js/combine/4_main.js: -------------------------------------------------------------------------------- 1 | particlesJS('particles-js', 2 | { 3 | "particles": { 4 | "number": { 5 | "value": 80, 6 | "density": { 7 | "enable": true, 8 | "value_area": 800 9 | } 10 | }, 11 | "color": { 12 | "value": "#ffffff" 13 | }, 14 | "shape": { 15 | "type": "circle", 16 | "stroke": { 17 | "width": 0, 18 | "color": "#000000" 19 | }, 20 | "polygon": { 21 | "nb_sides": 5 22 | }, 23 | "image": { 24 | "src": "img/github.svg", 25 | "width": 100, 26 | "height": 100 27 | } 28 | }, 29 | "opacity": { 30 | "value": 0.5, 31 | "random": false, 32 | "anim": { 33 | "enable": false, 34 | "speed": 1, 35 | "opacity_min": 0.1, 36 | "sync": false 37 | } 38 | }, 39 | "size": { 40 | "value": 5, 41 | "random": true, 42 | "anim": { 43 | "enable": false, 44 | "speed": 40, 45 | "size_min": 0.1, 46 | "sync": false 47 | } 48 | }, 49 | "line_linked": { 50 | "enable": true, 51 | "distance": 150, 52 | "color": "#ffffff", 53 | "opacity": 0.4, 54 | "width": 1 55 | }, 56 | "move": { 57 | "enable": true, 58 | "speed": 6, 59 | "direction": "none", 60 | "random": false, 61 | "straight": false, 62 | "out_mode": "out", 63 | "attract": { 64 | "enable": false, 65 | "rotateX": 600, 66 | "rotateY": 1200 67 | } 68 | } 69 | }, 70 | "interactivity": { 71 | "detect_on": "canvas", 72 | "events": { 73 | "onhover": { 74 | "enable": true, 75 | "mode": "repulse" 76 | }, 77 | "onclick": { 78 | "enable": true, 79 | "mode": "push" 80 | }, 81 | "resize": true 82 | }, 83 | "modes": { 84 | "grab": { 85 | "distance": 400, 86 | "line_linked": { 87 | "opacity": 1 88 | } 89 | }, 90 | "bubble": { 91 | "distance": 400, 92 | "size": 40, 93 | "duration": 2, 94 | "opacity": 8, 95 | "speed": 3 96 | }, 97 | "repulse": { 98 | "distance": 200 99 | }, 100 | "push": { 101 | "particles_nb": 4 102 | }, 103 | "remove": { 104 | "particles_nb": 2 105 | } 106 | } 107 | }, 108 | "retina_detect": true, 109 | "config_demo": { 110 | "hide_card": false, 111 | "background_color": "#b61924", 112 | "background_image": "", 113 | "background_position": "50% 50%", 114 | "background_repeat": "no-repeat", 115 | "background_size": "cover" 116 | } 117 | } 118 | ); -------------------------------------------------------------------------------- /template/login/assets_list.go: -------------------------------------------------------------------------------- 1 | package login 2 | 3 | var AssetsList = []string{ 4 | "/login/dist/all.min.css", 5 | "/login/dist/all.min.js", 6 | "/login/dist/respond.min.js", 7 | } 8 | -------------------------------------------------------------------------------- /template/login/login.go: -------------------------------------------------------------------------------- 1 | package login 2 | 3 | import ( 4 | "bytes" 5 | "html/template" 6 | "strings" 7 | 8 | "github.com/GoAdminGroup/go-admin/template/types" 9 | 10 | "github.com/GoAdminGroup/go-admin/modules/language" 11 | "github.com/GoAdminGroup/go-admin/modules/logger" 12 | ) 13 | 14 | type Login struct { 15 | Name string 16 | } 17 | 18 | func GetLoginComponent() *Login { 19 | return &Login{ 20 | Name: "login", 21 | } 22 | } 23 | 24 | var DefaultFuncMap = template.FuncMap{ 25 | "lang": language.Get, 26 | "langHtml": language.GetFromHtml, 27 | "link": func(cdnUrl, prefixUrl, assetsUrl string) string { 28 | if cdnUrl == "" { 29 | return prefixUrl + assetsUrl 30 | } 31 | return cdnUrl + assetsUrl 32 | }, 33 | "isLinkUrl": func(s string) bool { 34 | return (len(s) > 7 && s[:7] == "http://") || (len(s) > 8 && s[:8] == "https://") 35 | }, 36 | "render": func(s, old, repl template.HTML) template.HTML { 37 | return template.HTML(strings.ReplaceAll(string(s), string(old), string(repl))) 38 | }, 39 | "renderJS": func(s template.JS, old, repl template.HTML) template.JS { 40 | return template.JS(strings.ReplaceAll(string(s), string(old), string(repl))) 41 | }, 42 | "divide": func(a, b int) int { 43 | return a / b 44 | }, 45 | } 46 | 47 | func (l *Login) GetTemplate() (*template.Template, string) { 48 | tmpl, err := template.New("login_theme1"). 49 | Funcs(DefaultFuncMap). 50 | Parse(loginTmpl) 51 | 52 | if err != nil { 53 | logger.Error("Login GetTemplate Error: ", err) 54 | } 55 | 56 | return tmpl, "login_theme1" 57 | } 58 | 59 | func (l *Login) GetAssetList() []string { return AssetsList } 60 | func (l *Login) GetAsset(name string) ([]byte, error) { return Asset(name[1:]) } 61 | func (l *Login) IsAPage() bool { return true } 62 | func (l *Login) GetName() string { return "login" } 63 | 64 | func (l *Login) GetContent() template.HTML { 65 | buffer := new(bytes.Buffer) 66 | tmpl, defineName := l.GetTemplate() 67 | err := tmpl.ExecuteTemplate(buffer, defineName, l) 68 | if err != nil { 69 | logger.Error("login ComposeHtml Error:", err) 70 | } 71 | return template.HTML(buffer.String()) 72 | } 73 | 74 | func (l *Login) GetJS() template.JS { return "" } 75 | func (l *Login) GetCSS() template.CSS { return "" } 76 | func (l *Login) GetCallbacks() types.Callbacks { return make(types.Callbacks, 0) } 77 | -------------------------------------------------------------------------------- /template/template_test.go: -------------------------------------------------------------------------------- 1 | package template 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestVersionCompare(t *testing.T) { 10 | assert.Equal(t, true, VersionCompare("v1.2.8", []string{"v1.2.7"})) 11 | assert.Equal(t, true, VersionCompare("v1.2.8", []string{"v1.2.8"})) 12 | assert.Equal(t, true, VersionCompare("v1.2.8", []string{"v1.2.5", "v1.2.8"})) 13 | assert.Equal(t, false, VersionCompare("v1.2.7", []string{"v1.2.8"})) 14 | assert.Equal(t, true, VersionCompare("v0.0.30", []string{"v0.0.30"})) 15 | assert.Equal(t, true, VersionCompare("v0.0.30", []string{">=v0.0.30"})) 16 | assert.Equal(t, true, VersionCompare("v0.0.30", []string{">=v0.0.29"})) 17 | assert.Equal(t, false, VersionCompare("v0.0.30", []string{">=v0.1.1"})) 18 | assert.Equal(t, true, VersionCompare("v0.0.30", []string{"<=v0.1.1"})) 19 | } 20 | -------------------------------------------------------------------------------- /template/types/action/base.go: -------------------------------------------------------------------------------- 1 | package action 2 | 3 | import ( 4 | "encoding/json" 5 | "html/template" 6 | 7 | "github.com/GoAdminGroup/go-admin/context" 8 | "github.com/GoAdminGroup/go-admin/modules/config" 9 | "github.com/GoAdminGroup/go-admin/modules/utils" 10 | "github.com/GoAdminGroup/go-admin/template/types" 11 | ) 12 | 13 | type AjaxData map[string]interface{} 14 | 15 | func NewAjaxData() AjaxData { 16 | return AjaxData{"ids": "{{.Ids}}"} 17 | } 18 | 19 | func (a AjaxData) Add(m map[string]interface{}) AjaxData { 20 | for k, v := range m { 21 | a[k] = v 22 | } 23 | return a 24 | } 25 | 26 | func (a AjaxData) JSON() string { 27 | b, _ := json.Marshal(a) 28 | return utils.ReplaceAll(string(b), `"{%id}"`, "{{.Id}}", 29 | `"{%ids}"`, "{{.Ids}}", 30 | `"{{.Ids}}"`, "{{.Ids}}", 31 | `"{{.Id}}"`, "{{.Id}}") 32 | } 33 | 34 | type BaseAction struct { 35 | BtnId string 36 | BtnData interface{} 37 | JS template.JS 38 | } 39 | 40 | func (base *BaseAction) SetBtnId(btnId string) { 41 | if btnId[0] != '.' && btnId[0] != '#' { 42 | base.BtnId = "." + btnId 43 | } else { 44 | base.BtnId = btnId 45 | } 46 | } 47 | func (base *BaseAction) Js() template.JS { return base.JS } 48 | func (base *BaseAction) BtnClass() template.HTML { return "" } 49 | func (base *BaseAction) BtnAttribute() template.HTML { return "" } 50 | func (base *BaseAction) GetCallbacks() context.Node { return context.Node{} } 51 | func (base *BaseAction) ExtContent(ctx *context.Context) template.HTML { return template.HTML(``) } 52 | func (base *BaseAction) FooterContent(ctx *context.Context) template.HTML { return template.HTML(``) } 53 | func (base *BaseAction) SetBtnData(data interface{}) { base.BtnData = data } 54 | 55 | var _ types.Action = (*AjaxAction)(nil) 56 | var _ types.Action = (*PopUpAction)(nil) 57 | var _ types.Action = (*JumpAction)(nil) 58 | var _ types.Action = (*JumpSelectBoxAction)(nil) 59 | 60 | func URL(id string) string { 61 | return config.Url("/operation/" + utils.WrapURL(id)) 62 | } 63 | -------------------------------------------------------------------------------- /template/types/action/event.go: -------------------------------------------------------------------------------- 1 | package action 2 | 3 | type Event string 4 | 5 | const ( 6 | EventBlur Event = "blur" 7 | EventFocus Event = "focus" 8 | EventFocusin Event = "focusin" 9 | EventFocusout Event = "focusout" 10 | EventLoad Event = "load" 11 | EventResize Event = "resize" 12 | EventScroll Event = "scroll" 13 | EventUnload Event = "unload" 14 | EventClick Event = "click" 15 | EventDblclick Event = "dblclick" 16 | EventMousedown Event = "mousedown" 17 | EventMouseup Event = "mouseup" 18 | EventMousemove Event = "mousemove" 19 | EventMouseover Event = "mouseover" 20 | EventMouseout Event = "mouseout" 21 | EventMouseenter Event = "mouseenter" 22 | EventMouseleave Event = "mouseleave" 23 | EventChange Event = "change" 24 | EventSelect Event = "select" 25 | EventSubmit Event = "submit" 26 | EventKeydown Event = "keydown" 27 | EventKeypress Event = "keypress" 28 | EventKeyup Event = "keyup" 29 | EventError Event = "error" 30 | EventContextmenu Event = "contextmenu" 31 | ) 32 | -------------------------------------------------------------------------------- /template/types/action/fieldfilter.go: -------------------------------------------------------------------------------- 1 | package action 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/context" 7 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" 8 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" 9 | "github.com/GoAdminGroup/go-admin/template/types" 10 | ) 11 | 12 | type FieldFilterAction struct { 13 | BaseAction 14 | Field string 15 | } 16 | 17 | func FieldFilter(field string) *FieldFilterAction { 18 | return &FieldFilterAction{Field: field} 19 | } 20 | 21 | func (jump *FieldFilterAction) ExtContent(ctx *context.Context) template.HTML { 22 | 23 | options := jump.BtnData.(types.FieldOptions) 24 | 25 | cm := `` 26 | for _, obejct := range options { 27 | cm += `if (e.params.data.text === "` + obejct.Text + `") { 28 | $.pjax({url: setURL("` + jump.Field + `", "` + obejct.Value + `"), container: '#pjax-container'}); 29 | }` 30 | } 31 | 32 | return template.HTML(``) 75 | } 76 | -------------------------------------------------------------------------------- /template/types/action/file_upload.go: -------------------------------------------------------------------------------- 1 | package action 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/context" 7 | "github.com/GoAdminGroup/go-admin/modules/constant" 8 | "github.com/GoAdminGroup/go-admin/template/types" 9 | ) 10 | 11 | type FileUploadAction struct { 12 | BaseAction 13 | Url string 14 | Method string 15 | FileName string 16 | Handlers []context.Handler 17 | } 18 | 19 | func FileUpload(id string, handler types.Handler) *FileUploadAction { 20 | if id == "" { 21 | panic("wrong file upload action parameter, empty id") 22 | } 23 | return &FileUploadAction{ 24 | Url: URL(id), 25 | Method: "post", 26 | FileName: "file", 27 | Handlers: context.Handlers{handler.Wrap()}, 28 | } 29 | } 30 | 31 | func (file *FileUploadAction) SetUrl(url string) *FileUploadAction { 32 | file.Url = url 33 | return file 34 | } 35 | 36 | func (file *FileUploadAction) SetMethod(method string) *FileUploadAction { 37 | file.Method = method 38 | return file 39 | } 40 | 41 | func (file *FileUploadAction) GetCallbacks() context.Node { 42 | return context.Node{ 43 | Path: file.Url, 44 | Method: file.Method, 45 | Handlers: file.Handlers, 46 | Value: map[string]interface{}{constant.ContextNodeNeedAuth: 1}, 47 | } 48 | } 49 | 50 | func (file *FileUploadAction) Js() template.JS { 51 | 52 | return template.JS(`$('` + file.BtnId + `').on('click', function(){ 53 | $('` + file.BtnId + `_input').click(); 54 | }); 55 | 56 | $("` + file.BtnId + `_input").on("change", function () { 57 | var files = $('` + file.BtnId + `_input').prop('files'); 58 | 59 | var data = new FormData(); 60 | data.append('` + file.FileName + `', files[0]); 61 | NProgress.start(); 62 | 63 | $.ajax({ 64 | url: '` + file.Url + `', 65 | type: '` + file.Method + `', 66 | data: data, 67 | cache: false, 68 | processData: false, 69 | contentType: false, 70 | success: function (data) { 71 | NProgress.done(); 72 | if (data.code === 0) { 73 | swal(data.msg, '', 'success'); 74 | $.pjax.reload('#pjax-container'); 75 | } else { 76 | swal(data.msg, '', 'error'); 77 | } 78 | }, 79 | error: function (data) { 80 | NProgress.done(); 81 | if (data.responseText !== "") { 82 | swal(data.responseJSON.msg, '', 'error'); 83 | } else { 84 | swal('error', '', 'error'); 85 | } 86 | }, 87 | }); 88 | });`) 89 | } 90 | 91 | func (file *FileUploadAction) BtnAttribute() template.HTML { 92 | return template.HTML(`href="javascript:;"`) 93 | } 94 | 95 | func (file *FileUploadAction) FooterContent(ctx *context.Context) template.HTML { 96 | return template.HTML(``) 97 | 98 | } 99 | -------------------------------------------------------------------------------- /template/types/action/jump.go: -------------------------------------------------------------------------------- 1 | package action 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/context" 7 | "github.com/GoAdminGroup/go-admin/modules/utils" 8 | ) 9 | 10 | type JumpAction struct { 11 | BaseAction 12 | Url string 13 | Target string 14 | Ext template.HTML 15 | NewTabTitle string 16 | } 17 | 18 | func Jump(url string, ext ...template.HTML) *JumpAction { 19 | url = utils.ReplaceAll(url, "{%id}", "{{.Id}}", "{%ids}", "{{.Ids}}") 20 | if len(ext) > 0 { 21 | return &JumpAction{Url: url, Ext: ext[0]} 22 | } 23 | return &JumpAction{Url: url, NewTabTitle: ""} 24 | } 25 | 26 | func JumpInNewTab(url, title string, ext ...template.HTML) *JumpAction { 27 | url = utils.ReplaceAll(url, "{%id}", "{{.Id}}", "{%ids}", "{{.Ids}}") 28 | if len(ext) > 0 { 29 | return &JumpAction{Url: url, NewTabTitle: title, Ext: ext[0]} 30 | } 31 | return &JumpAction{Url: url, NewTabTitle: title} 32 | } 33 | 34 | func JumpWithTarget(url, target string, ext ...template.HTML) *JumpAction { 35 | url = utils.ReplaceAll(url, "{%id}", "{{.Id}}", "{%ids}", "{{.Ids}}") 36 | if len(ext) > 0 { 37 | return &JumpAction{Url: url, Target: target, Ext: ext[0]} 38 | } 39 | return &JumpAction{Url: url, Target: target} 40 | } 41 | 42 | func (jump *JumpAction) GetCallbacks() context.Node { 43 | return context.Node{Path: jump.Url, Method: "GET"} 44 | } 45 | 46 | func (jump *JumpAction) BtnAttribute() template.HTML { 47 | html := template.HTML(`href="` + jump.Url + `"`) 48 | if jump.NewTabTitle != "" { 49 | html += template.HTML(` data-title="` + jump.NewTabTitle + `"`) 50 | } 51 | if jump.Target != "" { 52 | html += template.HTML(` target="` + jump.Target + `"`) 53 | } 54 | return html 55 | } 56 | 57 | func (jump *JumpAction) BtnClass() template.HTML { 58 | if jump.NewTabTitle != "" { 59 | return "new-tab-link" 60 | } 61 | return "" 62 | } 63 | 64 | func (jump *JumpAction) ExtContent(ctx *context.Context) template.HTML { 65 | return jump.Ext 66 | } 67 | -------------------------------------------------------------------------------- /template/types/action/jump_selectbox.go: -------------------------------------------------------------------------------- 1 | package action 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/context" 7 | ) 8 | 9 | type JumpSelectBoxAction struct { 10 | BaseAction 11 | Options JumpOptions 12 | NewTabTitle string 13 | } 14 | 15 | type JumpOptions []JumpOption 16 | 17 | type JumpOption struct { 18 | Value string 19 | Url string 20 | } 21 | 22 | func SelectBoxJump(options JumpOptions) *JumpSelectBoxAction { 23 | return &JumpSelectBoxAction{Options: options} 24 | } 25 | 26 | func (jump *JumpSelectBoxAction) ExtContent(ctx *context.Context) template.HTML { 27 | 28 | cm := `` 29 | for _, obejct := range jump.Options { 30 | cm += `if (e.params.data.text === "` + obejct.Value + `") { 31 | $.pjax({url: "` + obejct.Url + `", container: '#pjax-container'}); 32 | }` 33 | } 34 | 35 | return template.HTML(``) 40 | } 41 | -------------------------------------------------------------------------------- /template/types/display/base.go: -------------------------------------------------------------------------------- 1 | package display 2 | -------------------------------------------------------------------------------- /template/types/display/bool.go: -------------------------------------------------------------------------------- 1 | package display 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/GoAdminGroup/go-admin/context" 7 | "github.com/GoAdminGroup/go-admin/template/icon" 8 | "github.com/GoAdminGroup/go-admin/template/types" 9 | "github.com/GoAdminGroup/html" 10 | ) 11 | 12 | type Bool struct { 13 | types.BaseDisplayFnGenerator 14 | } 15 | 16 | func init() { 17 | types.RegisterDisplayFnGenerator("bool", new(Bool)) 18 | } 19 | 20 | func (b *Bool) Get(ctx *context.Context, args ...interface{}) types.FieldFilterFn { 21 | return func(value types.FieldModel) interface{} { 22 | params := args[0].([]string) 23 | pass := icon.IconWithStyle(icon.Check, html.Style{ 24 | "color": "green", 25 | }) 26 | fail := icon.IconWithStyle(icon.Remove, html.Style{ 27 | "color": "red", 28 | }) 29 | if len(params) == 0 { 30 | if value.Value == "0" || strings.ToLower(value.Value) == "false" { 31 | return fail 32 | } 33 | return pass 34 | } else if len(params) == 1 { 35 | if value.Value == params[0] { 36 | return pass 37 | } 38 | return fail 39 | } else { 40 | if value.Value == params[0] { 41 | return pass 42 | } 43 | if value.Value == params[1] { 44 | return fail 45 | } 46 | } 47 | return "" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /template/types/display/carousel.go: -------------------------------------------------------------------------------- 1 | package display 2 | 3 | import ( 4 | "html/template" 5 | "strconv" 6 | 7 | "github.com/GoAdminGroup/go-admin/context" 8 | "github.com/GoAdminGroup/go-admin/template/types" 9 | ) 10 | 11 | type Carousel struct { 12 | types.BaseDisplayFnGenerator 13 | } 14 | 15 | func init() { 16 | types.RegisterDisplayFnGenerator("carousel", new(Carousel)) 17 | } 18 | 19 | func (c *Carousel) Get(ctx *context.Context, args ...interface{}) types.FieldFilterFn { 20 | return func(value types.FieldModel) interface{} { 21 | fn := args[0].(types.FieldGetImgArrFn) 22 | size := args[1].([]int) 23 | 24 | width := "300" 25 | height := "200" 26 | 27 | if len(size) > 0 { 28 | width = strconv.Itoa(size[0]) 29 | } 30 | 31 | if len(size) > 1 { 32 | height = strconv.Itoa(size[1]) 33 | } 34 | 35 | images := fn(value.Value) 36 | 37 | indicators := "" 38 | items := "" 39 | active := "" 40 | 41 | for i, img := range images { 42 | indicators += `
  • ` 44 | if i == 0 { 45 | active = " active" 46 | } else { 47 | active = "" 48 | } 49 | items += `
    50 | 52 | 53 |
    ` 54 | } 55 | 56 | return template.HTML(` 57 | 72 | `) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /template/types/display/copy.go: -------------------------------------------------------------------------------- 1 | package display 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/context" 7 | "github.com/GoAdminGroup/go-admin/template/types" 8 | ) 9 | 10 | type Copyable struct { 11 | types.BaseDisplayFnGenerator 12 | } 13 | 14 | func init() { 15 | types.RegisterDisplayFnGenerator("copyable", new(Copyable)) 16 | } 17 | 18 | func (c *Copyable) Get(ctx *context.Context, args ...interface{}) types.FieldFilterFn { 19 | return func(value types.FieldModel) interface{} { 20 | return template.HTML(` 21 | 23 | 24 |  ` + value.Value + ` 25 | `) 26 | } 27 | } 28 | 29 | func (c *Copyable) JS() template.HTML { 30 | return template.HTML(` 31 | $('body').on('click','.grid-column-copyable',(function (e) { 32 | var content = $(this).data('content'); 33 | 34 | var temp = $(''); 35 | 36 | $("body").append(temp); 37 | temp.val(content).select(); 38 | document.execCommand("copy"); 39 | temp.remove(); 40 | 41 | $(this).tooltip('show'); 42 | })); 43 | `) 44 | } 45 | -------------------------------------------------------------------------------- /template/types/display/date.go: -------------------------------------------------------------------------------- 1 | package display 2 | 3 | import ( 4 | "strconv" 5 | "time" 6 | 7 | "github.com/GoAdminGroup/go-admin/context" 8 | "github.com/GoAdminGroup/go-admin/template/types" 9 | ) 10 | 11 | type Date struct { 12 | types.BaseDisplayFnGenerator 13 | } 14 | 15 | func init() { 16 | types.RegisterDisplayFnGenerator("date", new(Date)) 17 | } 18 | 19 | func (d *Date) Get(ctx *context.Context, args ...interface{}) types.FieldFilterFn { 20 | return func(value types.FieldModel) interface{} { 21 | format := args[0].(string) 22 | ts, _ := strconv.ParseInt(value.Value, 10, 64) 23 | tm := time.Unix(ts, 0) 24 | return tm.Format(format) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /template/types/display/dot.go: -------------------------------------------------------------------------------- 1 | package display 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/context" 7 | "github.com/GoAdminGroup/go-admin/template/types" 8 | ) 9 | 10 | type Dot struct { 11 | types.BaseDisplayFnGenerator 12 | } 13 | 14 | func init() { 15 | types.RegisterDisplayFnGenerator("dot", new(Dot)) 16 | } 17 | 18 | func (d *Dot) Get(ctx *context.Context, args ...interface{}) types.FieldFilterFn { 19 | return func(value types.FieldModel) interface{} { 20 | icons := args[0].(map[string]types.FieldDotColor) 21 | defaultDot := types.FieldDotColor("") 22 | if len(args) > 1 { 23 | defaultDot = args[1].(types.FieldDotColor) 24 | } 25 | for k, style := range icons { 26 | if k == value.Value { 27 | return template.HTML(` 29 |   `) + 30 | template.HTML(value.Value) 31 | } 32 | } 33 | if defaultDot != "" { 34 | return template.HTML(` 36 |   `) + 37 | template.HTML(value.Value) 38 | } 39 | return value.Value 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /template/types/display/downloadable.go: -------------------------------------------------------------------------------- 1 | package display 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/context" 7 | "github.com/GoAdminGroup/go-admin/template/types" 8 | ) 9 | 10 | type Downloadable struct { 11 | types.BaseDisplayFnGenerator 12 | } 13 | 14 | func init() { 15 | types.RegisterDisplayFnGenerator("downloadable", new(Downloadable)) 16 | } 17 | 18 | func (d *Downloadable) Get(ctx *context.Context, args ...interface{}) types.FieldFilterFn { 19 | return func(value types.FieldModel) interface{} { 20 | param := args[0].([]string) 21 | 22 | u := value.Value 23 | 24 | if len(param) > 0 { 25 | u = param[0] + u 26 | } 27 | 28 | return template.HTML(` 29 | 30 | ` + value.Value + ` 31 | 32 | `) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /template/types/display/filesize.go: -------------------------------------------------------------------------------- 1 | package display 2 | 3 | import ( 4 | "strconv" 5 | 6 | "github.com/GoAdminGroup/go-admin/context" 7 | "github.com/GoAdminGroup/go-admin/modules/utils" 8 | "github.com/GoAdminGroup/go-admin/template/types" 9 | ) 10 | 11 | type FileSize struct { 12 | types.BaseDisplayFnGenerator 13 | } 14 | 15 | func init() { 16 | types.RegisterDisplayFnGenerator("filesize", new(FileSize)) 17 | } 18 | 19 | func (f *FileSize) Get(ctx *context.Context, args ...interface{}) types.FieldFilterFn { 20 | return func(value types.FieldModel) interface{} { 21 | size, _ := strconv.ParseUint(value.Value, 10, 64) 22 | return utils.FileSize(size) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /template/types/display/icon.go: -------------------------------------------------------------------------------- 1 | package display 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/template/icon" 6 | "github.com/GoAdminGroup/go-admin/template/types" 7 | ) 8 | 9 | type Icon struct { 10 | types.BaseDisplayFnGenerator 11 | } 12 | 13 | func init() { 14 | types.RegisterDisplayFnGenerator("icon", new(Icon)) 15 | } 16 | 17 | func (i *Icon) Get(ctx *context.Context, args ...interface{}) types.FieldFilterFn { 18 | return func(value types.FieldModel) interface{} { 19 | icons := args[0].(map[string]string) 20 | defaultIcon := "" 21 | if len(args) > 1 { 22 | defaultIcon = args[1].(string) 23 | } 24 | for k, iconClass := range icons { 25 | if k == value.Value { 26 | return icon.Icon(iconClass) 27 | } 28 | } 29 | if defaultIcon != "" { 30 | return icon.Icon(defaultIcon) 31 | } 32 | return value.Value 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /template/types/display/image.go: -------------------------------------------------------------------------------- 1 | package display 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/template" 6 | "github.com/GoAdminGroup/go-admin/template/types" 7 | ) 8 | 9 | type Image struct { 10 | types.BaseDisplayFnGenerator 11 | } 12 | 13 | func init() { 14 | types.RegisterDisplayFnGenerator("image", new(Image)) 15 | } 16 | 17 | func (image *Image) Get(ctx *context.Context, args ...interface{}) types.FieldFilterFn { 18 | param := args[2].([]string) 19 | return func(value types.FieldModel) interface{} { 20 | if value.Value == "" { 21 | return "" 22 | } 23 | if len(param) > 0 { 24 | return template.Default(ctx).Image().SetWidth(args[0].(string)).SetHeight(args[1].(string)). 25 | SetSrc(template.HTML(param[0] + value.Value)).GetContent() 26 | 27 | } else { 28 | return template.Default(ctx).Image().SetWidth(args[0].(string)).SetHeight(args[1].(string)). 29 | SetSrc(template.HTML(value.Value)).GetContent() 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /template/types/display/label.go: -------------------------------------------------------------------------------- 1 | package display 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/template" 6 | "github.com/GoAdminGroup/go-admin/template/types" 7 | ) 8 | 9 | type Label struct { 10 | types.BaseDisplayFnGenerator 11 | } 12 | 13 | func init() { 14 | types.RegisterDisplayFnGenerator("label", new(Label)) 15 | } 16 | 17 | func (label *Label) Get(ctx *context.Context, args ...interface{}) types.FieldFilterFn { 18 | return func(value types.FieldModel) interface{} { 19 | params := args[0].([]types.FieldLabelParam) 20 | if len(params) == 0 { 21 | return template.Default(ctx).Label(). 22 | SetContent(template.HTML(value.Value)). 23 | SetType("success"). 24 | GetContent() 25 | } else if len(params) == 1 { 26 | return template.Default(ctx).Label(). 27 | SetContent(template.HTML(value.Value)). 28 | SetColor(params[0].Color). 29 | SetType(params[0].Type). 30 | GetContent() 31 | } 32 | return "" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /template/types/display/link.go: -------------------------------------------------------------------------------- 1 | package display 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/template" 6 | "github.com/GoAdminGroup/go-admin/template/types" 7 | ) 8 | 9 | type Link struct { 10 | types.BaseDisplayFnGenerator 11 | } 12 | 13 | func init() { 14 | types.RegisterDisplayFnGenerator("link", new(Link)) 15 | } 16 | 17 | func (l *Link) Get(ctx *context.Context, args ...interface{}) types.FieldFilterFn { 18 | prefix := "" 19 | openInNewTabs := false 20 | if len(args) > 0 { 21 | prefix = args[0].(string) 22 | } 23 | if len(args) > 1 { 24 | if openInNewTabsArr, ok := args[1].([]bool); ok { 25 | openInNewTabs = openInNewTabsArr[0] 26 | } 27 | } 28 | return func(value types.FieldModel) interface{} { 29 | if openInNewTabs { 30 | return template.Default(ctx).Link().SetURL(prefix + value.Value).OpenInNewTab().GetContent() 31 | } else { 32 | return template.Default(ctx).Link().SetURL(prefix + value.Value).GetContent() 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /template/types/display/loading.go: -------------------------------------------------------------------------------- 1 | package display 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/context" 7 | "github.com/GoAdminGroup/go-admin/template/types" 8 | ) 9 | 10 | type Loading struct { 11 | types.BaseDisplayFnGenerator 12 | } 13 | 14 | func init() { 15 | types.RegisterDisplayFnGenerator("loading", new(Loading)) 16 | } 17 | 18 | func (l *Loading) Get(ctx *context.Context, args ...interface{}) types.FieldFilterFn { 19 | return func(value types.FieldModel) interface{} { 20 | param := args[0].([]string) 21 | 22 | for i := 0; i < len(param); i++ { 23 | if value.Value == param[i] { 24 | return template.HTML(``) 25 | } 26 | } 27 | 28 | return value.Value 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /template/types/display/progressbar.go: -------------------------------------------------------------------------------- 1 | package display 2 | 3 | import ( 4 | "fmt" 5 | "html/template" 6 | "strconv" 7 | 8 | "github.com/GoAdminGroup/go-admin/context" 9 | "github.com/GoAdminGroup/go-admin/template/types" 10 | ) 11 | 12 | type ProgressBar struct { 13 | types.BaseDisplayFnGenerator 14 | } 15 | 16 | func init() { 17 | types.RegisterDisplayFnGenerator("progressbar", new(ProgressBar)) 18 | } 19 | 20 | func (p *ProgressBar) Get(ctx *context.Context, args ...interface{}) types.FieldFilterFn { 21 | return func(value types.FieldModel) interface{} { 22 | param := args[0].([]types.FieldProgressBarData) 23 | style := "primary" 24 | size := "sm" 25 | max := 100 26 | if len(param) > 0 { 27 | if param[0].Style != "" { 28 | style = param[0].Style 29 | } 30 | if param[0].Size != "" { 31 | size = param[0].Size 32 | } 33 | if param[0].Max != 0 { 34 | max = param[0].Max 35 | } 36 | } 37 | base, _ := strconv.Atoi(value.Value) 38 | per := fmt.Sprintf("%.0f", float32(base)/float32(max)*100) 39 | return template.HTML(` 40 |
    41 | ` + per + `% 42 |
    43 |
    45 |
    46 |
    47 |
    `) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /template/types/display/qrcode.go: -------------------------------------------------------------------------------- 1 | package display 2 | 3 | import ( 4 | "html/template" 5 | 6 | "github.com/GoAdminGroup/go-admin/context" 7 | "github.com/GoAdminGroup/go-admin/template/types" 8 | ) 9 | 10 | type Qrcode struct { 11 | types.BaseDisplayFnGenerator 12 | } 13 | 14 | func init() { 15 | types.RegisterDisplayFnGenerator("qrcode", new(Qrcode)) 16 | } 17 | 18 | func (q *Qrcode) Get(ctx *context.Context, args ...interface{}) types.FieldFilterFn { 19 | return func(value types.FieldModel) interface{} { 20 | 21 | src := `https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=` + value.Value 22 | 23 | return template.HTML(` 24 | 27 | 28 |  ` + value.Value + ` 29 | `) 30 | } 31 | } 32 | 33 | func (q *Qrcode) JS() template.HTML { 34 | return template.HTML(` 35 | $('.grid-column-qrcode').popover({ 36 | html: true, 37 | container: 'body', 38 | trigger: 'focus' 39 | }); 40 | `) 41 | } 42 | -------------------------------------------------------------------------------- /template/types/display_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | -------------------------------------------------------------------------------- /template/types/form/form_test.go: -------------------------------------------------------------------------------- 1 | package form 2 | -------------------------------------------------------------------------------- /template/types/form_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | -------------------------------------------------------------------------------- /template/types/info_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | -------------------------------------------------------------------------------- /template/types/operators.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "html/template" 4 | 5 | type FilterOperator string 6 | 7 | const ( 8 | FilterOperatorLike FilterOperator = "like" 9 | FilterOperatorGreater FilterOperator = ">" 10 | FilterOperatorGreaterOrEqual FilterOperator = ">=" 11 | FilterOperatorEqual FilterOperator = "=" 12 | FilterOperatorNotEqual FilterOperator = "!=" 13 | FilterOperatorLess FilterOperator = "<" 14 | FilterOperatorLessOrEqual FilterOperator = "<=" 15 | FilterOperatorFree FilterOperator = "free" 16 | ) 17 | 18 | func GetOperatorFromValue(value string) FilterOperator { 19 | switch value { 20 | case "like": 21 | return FilterOperatorLike 22 | case "gr": 23 | return FilterOperatorGreater 24 | case "gq": 25 | return FilterOperatorGreaterOrEqual 26 | case "eq": 27 | return FilterOperatorEqual 28 | case "ne": 29 | return FilterOperatorNotEqual 30 | case "le": 31 | return FilterOperatorLess 32 | case "lq": 33 | return FilterOperatorLessOrEqual 34 | case "free": 35 | return FilterOperatorFree 36 | default: 37 | return FilterOperatorEqual 38 | } 39 | } 40 | 41 | func (o FilterOperator) Value() string { 42 | switch o { 43 | case FilterOperatorLike: 44 | return "like" 45 | case FilterOperatorGreater: 46 | return "gr" 47 | case FilterOperatorGreaterOrEqual: 48 | return "gq" 49 | case FilterOperatorEqual: 50 | return "eq" 51 | case FilterOperatorNotEqual: 52 | return "ne" 53 | case FilterOperatorLess: 54 | return "le" 55 | case FilterOperatorLessOrEqual: 56 | return "lq" 57 | case FilterOperatorFree: 58 | return "free" 59 | default: 60 | return "eq" 61 | } 62 | } 63 | 64 | func (o FilterOperator) String() string { 65 | return string(o) 66 | } 67 | 68 | func (o FilterOperator) Label() template.HTML { 69 | if o == FilterOperatorLike { 70 | return "" 71 | } 72 | return template.HTML(o) 73 | } 74 | 75 | func (o FilterOperator) AddOrNot() bool { 76 | return string(o) != "" && o != FilterOperatorFree 77 | } 78 | 79 | func (o FilterOperator) Valid() bool { 80 | switch o { 81 | case FilterOperatorLike, FilterOperatorGreater, FilterOperatorGreaterOrEqual, 82 | FilterOperatorLess, FilterOperatorLessOrEqual, FilterOperatorFree: 83 | return true 84 | default: 85 | return false 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /template/types/select.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "html/template" 5 | "strconv" 6 | 7 | "github.com/GoAdminGroup/go-admin/context" 8 | "github.com/GoAdminGroup/go-admin/modules/language" 9 | "github.com/GoAdminGroup/go-admin/modules/utils" 10 | ) 11 | 12 | type DefaultSelection struct { 13 | *BaseButton 14 | Options FieldOptions 15 | Placeholder string 16 | Width int 17 | } 18 | 19 | func btnUUID() string { 20 | return "info-btn-" + utils.Uuid(10) 21 | } 22 | 23 | func GetDefaultSelection(placeholder string, options FieldOptions, action Action, widths ...int) *DefaultSelection { 24 | 25 | id := btnUUID() 26 | action.SetBtnId("." + id) 27 | 28 | var width = 100 29 | if len(widths) > 0 { 30 | width = widths[0] 31 | } 32 | node := action.GetCallbacks() 33 | return &DefaultSelection{ 34 | BaseButton: &BaseButton{ 35 | Id: id, 36 | Action: action, 37 | Url: node.Path, 38 | Method: node.Method, 39 | }, 40 | Placeholder: placeholder, 41 | Width: width, 42 | Options: options, 43 | } 44 | 45 | } 46 | 47 | func (b *DefaultSelection) Content(ctx *context.Context) (template.HTML, template.JS) { 48 | 49 | optionsHtml := `` 50 | 51 | for _, op := range b.Options { 52 | optionsHtml += `` 53 | } 54 | 55 | h := template.HTML(`
    56 |
    57 | 62 |
    63 |
    64 | `) + b.Action.ExtContent(ctx) 74 | 75 | return h, b.Action.Js() + template.JS(` 76 | $(".`+b.Id+`").select2(); 77 | `) 78 | } 79 | -------------------------------------------------------------------------------- /template/types/size.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "strconv" 4 | 5 | // Extra small screen / phone 6 | // xs: 0 7 | 8 | // Small screen / phone 9 | // sm: 576px 10 | 11 | // Medium screen / tablet 12 | // md: 768px 13 | 14 | // Large screen / desktop 15 | // lg: 992px 16 | 17 | // Extra large screen / wide desktop 18 | // xl: 1200px 19 | 20 | type S map[string]string 21 | 22 | func Size(sm, md, lg int) S { 23 | var s = make(S) 24 | if sm > 0 && sm < 13 { 25 | s["sm"] = strconv.Itoa(sm) 26 | } 27 | if md > 0 && md < 13 { 28 | s["md"] = strconv.Itoa(md) 29 | } 30 | if lg > 0 && lg < 13 { 31 | s["lg"] = strconv.Itoa(lg) 32 | } 33 | return s 34 | } 35 | 36 | func (s S) LG(lg int) S { 37 | if lg > 0 && lg < 13 { 38 | s["lg"] = strconv.Itoa(lg) 39 | } 40 | return s 41 | } 42 | 43 | func (s S) XS(xs int) S { 44 | if xs > 0 && xs < 13 { 45 | s["xs"] = strconv.Itoa(xs) 46 | } 47 | return s 48 | } 49 | 50 | func (s S) XL(xl int) S { 51 | if xl > 0 && xl < 13 { 52 | s["xl"] = strconv.Itoa(xl) 53 | } 54 | return s 55 | } 56 | 57 | func (s S) SM(sm int) S { 58 | if sm > 0 && sm < 13 { 59 | s["sm"] = strconv.Itoa(sm) 60 | } 61 | return s 62 | } 63 | 64 | func (s S) MD(md int) S { 65 | if md > 0 && md < 13 { 66 | s["md"] = strconv.Itoa(md) 67 | } 68 | return s 69 | } 70 | 71 | func SizeXS(xs int) S { 72 | var s = make(S) 73 | if xs > 0 && xs < 13 { 74 | s["xs"] = strconv.Itoa(xs) 75 | } 76 | return s 77 | } 78 | 79 | func SizeXL(xl int) S { 80 | var s = make(S) 81 | if xl > 0 && xl < 13 { 82 | s["xl"] = strconv.Itoa(xl) 83 | } 84 | return s 85 | } 86 | 87 | func SizeSM(sm int) S { 88 | var s = make(S) 89 | if sm > 0 && sm < 13 { 90 | s["sm"] = strconv.Itoa(sm) 91 | } 92 | return s 93 | } 94 | 95 | func SizeMD(md int) S { 96 | var s = make(S) 97 | if md > 0 && md < 13 { 98 | s["md"] = strconv.Itoa(md) 99 | } 100 | return s 101 | } 102 | 103 | func SizeLG(lg int) S { 104 | var s = make(S) 105 | if lg > 0 && lg < 13 { 106 | s["lg"] = strconv.Itoa(lg) 107 | } 108 | return s 109 | } 110 | -------------------------------------------------------------------------------- /template/types/table/table.go: -------------------------------------------------------------------------------- 1 | package table 2 | 3 | type Type uint8 4 | 5 | const ( 6 | Text Type = iota 7 | Textarea 8 | Select 9 | Date 10 | Datetime 11 | Year 12 | Month 13 | Day 14 | Switch 15 | ) 16 | 17 | func (t Type) String() string { 18 | switch t { 19 | case Text: 20 | return "text" 21 | case Select: 22 | return "select" 23 | case Textarea: 24 | return "textarea" 25 | case Date: 26 | return "date" 27 | case Switch: 28 | return "switch" 29 | case Year: 30 | return "year" 31 | case Month: 32 | return "month" 33 | case Day: 34 | return "day" 35 | case Datetime: 36 | return "datetime" 37 | default: 38 | panic("wrong form type") 39 | } 40 | } 41 | 42 | func (t Type) IsSwitch() bool { 43 | return t == Switch 44 | } 45 | -------------------------------------------------------------------------------- /template/types/tmpls/choose.tmpl: -------------------------------------------------------------------------------- 1 | {{define "choose"}} 2 | 13 | {{end}} -------------------------------------------------------------------------------- /template/types/tmpls/choose_custom.tmpl: -------------------------------------------------------------------------------- 1 | {{define "choose_custom"}} 2 | 7 | {{end}} -------------------------------------------------------------------------------- /template/types/tmpls/choose_disable.tmpl: -------------------------------------------------------------------------------- 1 | {{define "choose_disable"}} 2 | 19 | {{end}} -------------------------------------------------------------------------------- /template/types/tmpls/choose_hide.tmpl: -------------------------------------------------------------------------------- 1 | {{define "choose_hide"}} 2 | 35 | {{end}} -------------------------------------------------------------------------------- /template/types/tmpls/choose_map.tmpl: -------------------------------------------------------------------------------- 1 | {{define "choose_map"}} 2 | 37 | {{end}} -------------------------------------------------------------------------------- /template/types/tmpls/choose_show.tmpl: -------------------------------------------------------------------------------- 1 | {{define "choose_show"}} 2 | 35 | {{end}} -------------------------------------------------------------------------------- /tests/common/api.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/GoAdminGroup/go-admin/modules/config" 8 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" 9 | "github.com/gavv/httpexpect" 10 | ) 11 | 12 | func apiTest(e *httpexpect.Expect, sesID *http.Cookie) { 13 | 14 | fmt.Println() 15 | printlnWithColor("Api", "blue") 16 | fmt.Println("============================") 17 | 18 | printlnWithColor("show", "green") 19 | e.GET(config.Url("/api/list/manager")). 20 | WithHeader("Accept", "application/json, text/plain, */*"). 21 | WithCookie(sesID.Name, sesID.Value). 22 | Expect(). 23 | Status(200).JSON().Object().ValueEqual("code", 200) 24 | 25 | //printlnWithColor("update form without id", "green") 26 | //e.GET(config.Url("/api/edit/form/manager")). 27 | // WithHeader("Accept", "application/json, text/plain, */*"). 28 | // WithCookie(sesID.Name, sesID.Value). 29 | // Expect(). 30 | // Status(400).JSON().Object().ValueEqual("code", 400) 31 | 32 | printlnWithColor("update form", "green") 33 | e.GET(config.Url("/api/edit/form/manager")). 34 | WithHeader("Accept", "application/json, text/plain, */*"). 35 | WithQuery(constant.EditPKKey, "1"). 36 | WithCookie(sesID.Name, sesID.Value). 37 | Expect(). 38 | Status(200).JSON().Object().ValueEqual("code", 200) 39 | 40 | printlnWithColor("create form", "green") 41 | e.GET(config.Url("/api/create/form/manager")). 42 | WithHeader("Accept", "application/json, text/plain, */*"). 43 | WithCookie(sesID.Name, sesID.Value). 44 | Expect(). 45 | Status(200).JSON().Object().ValueEqual("code", 200) 46 | } 47 | -------------------------------------------------------------------------------- /tests/common/auth.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/GoAdminGroup/go-admin/modules/auth" 8 | "github.com/GoAdminGroup/go-admin/modules/config" 9 | "github.com/gavv/httpexpect" 10 | ) 11 | 12 | func authTest(e *httpexpect.Expect) *http.Cookie { 13 | 14 | printlnWithColor("Auth", "blue") 15 | fmt.Println("============================") 16 | 17 | // login: show 18 | 19 | printlnWithColor("login: show", "green") 20 | e.GET(config.Url(config.GetLoginUrl())).Expect().Status(200) 21 | printlnWithColor("login: empty password", "green") 22 | e.POST(config.Url("/signin")).WithJSON(map[string]string{ 23 | "username": "admin", 24 | "password": "", 25 | }).Expect().Status(400) 26 | 27 | // login 28 | 29 | printlnWithColor("login", "green") 30 | sesID := e.POST(config.Url("/signin")).WithForm(map[string]string{ 31 | "username": "admin", 32 | "password": "admin", 33 | }).Expect().Status(200).Cookie(auth.DefaultCookieKey).Raw() 34 | 35 | // logout: without login 36 | 37 | printlnWithColor("logout: without login", "green") 38 | e.GET(config.Url("/logout")).Expect(). 39 | Status(200) 40 | 41 | // logout 42 | 43 | printlnWithColor("logout", "green") 44 | e.GET(config.Url("/logout")).WithCookie(auth.DefaultCookieKey, sesID.Value).Expect(). 45 | Status(200) 46 | 47 | // login again 48 | 49 | printlnWithColor("login again", "green") 50 | cookie1 := e.POST(config.Url("/signin")).WithForm(map[string]string{ 51 | "username": "admin", 52 | "password": "admin", 53 | }).Expect().Status(200).Cookie(auth.DefaultCookieKey).Raw() 54 | 55 | printlnWithColor("login again:restrict users from logging in at the same time", "green") 56 | cookie2 := e.POST(config.Url("/signin")).WithForm(map[string]string{ 57 | "username": "admin", 58 | "password": "admin", 59 | }).Expect().Status(200).Cookie(auth.DefaultCookieKey).Raw() 60 | 61 | // login success 62 | 63 | printlnWithColor("cookie failure", "green") 64 | e.GET(config.Url("/")). 65 | WithCookie(auth.DefaultCookieKey, cookie1.Value).Expect(). 66 | Status(200). 67 | Body().Contains("login") 68 | 69 | printlnWithColor("login success", "green") 70 | e.GET(config.Url("/")). 71 | WithCookie(auth.DefaultCookieKey, cookie2.Value).Expect(). 72 | Status(200). 73 | Body().Contains("Dashboard") 74 | 75 | return cookie2 76 | 77 | } 78 | -------------------------------------------------------------------------------- /tests/common/checklist.md: -------------------------------------------------------------------------------- 1 | # Test Case Checklist 2 | 3 | ## Authentication 4 | 5 | - [ ] Show login page 6 | - [ ] Login 7 | - [ ] Logout without login 8 | - [ ] Logout 9 | 10 | ## Admin Management 11 | 12 | - [ ] Show list page 13 | - [ ] Edit 14 | - [ ] Show form page without ID 15 | - [ ] Show form 16 | - [ ] Edit form 17 | - [ ] Show new form 18 | - [ ] New manager tester 19 | - [ ] Tester login with wrong password 20 | - [ ] Tester login with right password -------------------------------------------------------------------------------- /tests/common/common.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "fmt" 5 | "regexp" 6 | 7 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" 8 | "github.com/gavv/httpexpect" 9 | "github.com/mgutz/ansi" 10 | ) 11 | 12 | var reg, _ = regexp.Compile("") 13 | 14 | // ExtraTest contains unit test sections of the GoAdmin admin plugin. 15 | func ExtraTest(e *httpexpect.Expect) { 16 | 17 | fmt.Println() 18 | fmt.Println("============================================") 19 | printlnWithColor("Basic Function Black-Box Testing", "blue") 20 | fmt.Println("============================================") 21 | fmt.Println() 22 | 23 | cookie := authTest(e) 24 | 25 | // permission check 26 | permissionTest(e, cookie) 27 | // role check 28 | roleTest(e, cookie) 29 | // manager check 30 | managerTest(e, cookie) 31 | // api check 32 | apiTest(e, cookie) 33 | // menu check 34 | menuTest(e, cookie) 35 | // operation log check 36 | operationLogTest(e, cookie) 37 | 38 | // get data from outside source check 39 | externalTest(e, cookie) 40 | // normal table tests 41 | normalTest(e, cookie) 42 | } 43 | 44 | // ExtraTest contains unit test sections of the GoAdmin admin plugin. 45 | func Test(e *httpexpect.Expect) { 46 | 47 | fmt.Println() 48 | fmt.Println("============================================") 49 | printlnWithColor("Basic Function Black-Box Testing", "blue") 50 | fmt.Println("============================================") 51 | fmt.Println() 52 | 53 | cookie := authTest(e) 54 | 55 | // permission check 56 | permissionTest(e, cookie) 57 | // role check 58 | roleTest(e, cookie) 59 | // manager check 60 | managerTest(e, cookie) 61 | // menu check 62 | menuTest(e, cookie) 63 | // operation log check 64 | operationLogTest(e, cookie) 65 | } 66 | 67 | func printlnWithColor(msg string, color string) { 68 | fmt.Println(ansi.Color(msg, color)) 69 | } 70 | -------------------------------------------------------------------------------- /tests/common/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "database": { 3 | "default": { 4 | "host": "db_mysql", 5 | "port": "3306", 6 | "user": "root", 7 | "pwd": "root", 8 | "name": "go-admin-test", 9 | "max_idle_con": 50, 10 | "max_open_con": 150, 11 | "driver": "mysql" 12 | } 13 | }, 14 | "domain": "localhost", 15 | "prefix": "admin", 16 | "store": { 17 | "path": "./uploads", 18 | "prefix": "uploads" 19 | }, 20 | "env": "local", 21 | "language": "en", 22 | "index": "/", 23 | "debug": true, 24 | "open_admin_api": true, 25 | "color_scheme": "skin-black" 26 | } -------------------------------------------------------------------------------- /tests/common/config_ms.json: -------------------------------------------------------------------------------- 1 | { 2 | "database": { 3 | "default": { 4 | "host": "db_mssql", 5 | "port": "1433", 6 | "user": "sa", 7 | "pwd": "Aa123456", 8 | "name": "goadmin", 9 | "max_idle_con": 50, 10 | "max_open_con": 150, 11 | "driver": "mssql" 12 | } 13 | }, 14 | "domain": "localhost", 15 | "prefix": "admin", 16 | "store": { 17 | "path": "./uploads", 18 | "prefix": "uploads" 19 | }, 20 | "env": "local", 21 | "language": "en", 22 | "index": "/", 23 | "debug": true, 24 | "open_admin_api": true, 25 | "color_scheme": "skin-black" 26 | } 27 | -------------------------------------------------------------------------------- /tests/common/config_pg.json: -------------------------------------------------------------------------------- 1 | { 2 | "database": { 3 | "default": { 4 | "host": "db_pgsql", 5 | "port": "5432", 6 | "user": "postgres", 7 | "pwd": "root", 8 | "name": "go-admin-test", 9 | "max_idle_con": 50, 10 | "max_open_con": 150, 11 | "driver": "postgresql" 12 | } 13 | }, 14 | "domain": "localhost", 15 | "prefix": "admin", 16 | "store": { 17 | "path": "./uploads", 18 | "prefix": "uploads" 19 | }, 20 | "env": "local", 21 | "language": "en", 22 | "index": "/", 23 | "debug": true, 24 | "open_admin_api": true, 25 | "color_scheme": "skin-black" 26 | } -------------------------------------------------------------------------------- /tests/common/config_sqlite.json: -------------------------------------------------------------------------------- 1 | { 2 | "database": { 3 | "default": { 4 | "driver": "sqlite", 5 | "file": "./../../common/admin.db" 6 | } 7 | }, 8 | "domain": "localhost", 9 | "prefix": "admin", 10 | "store": { 11 | "path": "./uploads", 12 | "prefix": "uploads" 13 | }, 14 | "env": "local", 15 | "language": "en", 16 | "index": "/", 17 | "debug": true, 18 | "open_admin_api": true, 19 | "color_scheme": "skin-black" 20 | } -------------------------------------------------------------------------------- /tests/common/external.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/GoAdminGroup/go-admin/modules/config" 8 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/constant" 9 | "github.com/gavv/httpexpect" 10 | ) 11 | 12 | func externalTest(e *httpexpect.Expect, sesID *http.Cookie) { 13 | fmt.Println() 14 | printlnWithColor("External", "blue") 15 | fmt.Println("============================") 16 | 17 | // show 18 | 19 | printlnWithColor("show", "green") 20 | e.GET(config.Url("/info/external")). 21 | WithCookie(sesID.Name, sesID.Value). 22 | Expect(). 23 | Status(200). 24 | Body().Contains("External").Contains("this is a title").Contains("10") 25 | 26 | // show form: without id 27 | 28 | //printlnWithColor("show form: without id", "green") 29 | //e.GET(config.Url("/info/external/edit")). 30 | // WithCookie(sesID.Name, sesID.Value). 31 | // Expect().Status(200).Body().Contains(errors.WrongID) 32 | 33 | // show form 34 | 35 | printlnWithColor("show form", "green") 36 | e.GET(config.Url("/info/external/edit")). 37 | WithQuery(constant.EditPKKey, "10"). 38 | WithCookie(sesID.Name, sesID.Value). 39 | Expect().Status(200).Body() 40 | 41 | // show new form 42 | 43 | printlnWithColor("show new form", "green") 44 | e.GET(config.Url("/info/external/new")). 45 | WithCookie(sesID.Name, sesID.Value). 46 | Expect().Status(200).Body() 47 | } 48 | -------------------------------------------------------------------------------- /tests/common/normal.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/GoAdminGroup/go-admin/modules/config" 8 | "github.com/gavv/httpexpect" 9 | ) 10 | 11 | func normalTest(e *httpexpect.Expect, sesID *http.Cookie) { 12 | 13 | fmt.Println() 14 | printlnWithColor("Normal Table", "blue") 15 | fmt.Println("============================") 16 | 17 | // show 18 | 19 | printlnWithColor("show", "green") 20 | e.GET(config.Url("/info/user")). 21 | WithCookie(sesID.Name, sesID.Value). 22 | Expect(). 23 | Status(200). 24 | Body().Contains("Users") 25 | 26 | // export 27 | 28 | printlnWithColor("export test", "green") 29 | e.POST(config.Url("/export/user")). 30 | WithCookie(sesID.Name, sesID.Value). 31 | WithMultipart(). 32 | WithFormField("id", "1"). 33 | Expect().Status(200) 34 | 35 | // show form: without id 36 | 37 | //printlnWithColor("show form: without id", "green") 38 | //e.GET(config.Url("/info/user/edit")). 39 | // WithCookie(sesID.Name, sesID.Value). 40 | // Expect().Status(200).Body().Contains(errors.WrongID) 41 | 42 | // show form 43 | 44 | //printlnWithColor("show form", "green") 45 | //e.GET(config.Url("/info/user/edit")). 46 | // WithQuery(constant.EditPKKey, "362"). 47 | // WithCookie(sesID.Name, sesID.Value). 48 | // Expect().Status(200).Body() 49 | 50 | // show new form 51 | 52 | printlnWithColor("show new form", "green") 53 | e.GET(config.Url("/info/user/new")). 54 | WithCookie(sesID.Name, sesID.Value). 55 | Expect().Status(200).Body() 56 | 57 | } 58 | -------------------------------------------------------------------------------- /tests/common/operation_log.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/GoAdminGroup/go-admin/modules/config" 8 | "github.com/GoAdminGroup/go-admin/modules/language" 9 | "github.com/gavv/httpexpect" 10 | ) 11 | 12 | func operationLogTest(e *httpexpect.Expect, sesID *http.Cookie) { 13 | 14 | fmt.Println() 15 | printlnWithColor("Operation Log", "blue") 16 | fmt.Println("============================") 17 | 18 | // show 19 | 20 | printlnWithColor("show", "green") 21 | e.GET(config.Url("/info/op")). 22 | WithCookie(sesID.Name, sesID.Value). 23 | Expect(). 24 | Status(200). 25 | Body().Contains(language.Get("operation log")) 26 | } 27 | -------------------------------------------------------------------------------- /tests/data/admin.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/go-admin/cd8748f96e19ce3c4bf437520542b097899fc16e/tests/data/admin.db -------------------------------------------------------------------------------- /tests/data/admin_ms.bak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/go-admin/cd8748f96e19ce3c4bf437520542b097899fc16e/tests/data/admin_ms.bak -------------------------------------------------------------------------------- /tests/frameworks/beego/beego.go: -------------------------------------------------------------------------------- 1 | package beego 2 | 3 | import ( 4 | // add beego adapter 5 | _ "github.com/GoAdminGroup/go-admin/adapter/beego" 6 | "github.com/GoAdminGroup/go-admin/modules/config" 7 | "github.com/GoAdminGroup/go-admin/modules/language" 8 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 9 | 10 | // add mysql driver 11 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" 12 | // add postgresql driver 13 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/postgres" 14 | // add sqlite driver 15 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/sqlite" 16 | // add mssql driver 17 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mssql" 18 | // add adminlte ui theme 19 | "github.com/GoAdminGroup/themes/adminlte" 20 | 21 | "net/http" 22 | "os" 23 | 24 | "github.com/GoAdminGroup/go-admin/engine" 25 | "github.com/GoAdminGroup/go-admin/plugins/admin" 26 | "github.com/GoAdminGroup/go-admin/plugins/example" 27 | "github.com/GoAdminGroup/go-admin/template" 28 | "github.com/GoAdminGroup/go-admin/template/chartjs" 29 | "github.com/GoAdminGroup/go-admin/tests/tables" 30 | "github.com/astaxie/beego" 31 | ) 32 | 33 | func internalHandler() http.Handler { 34 | 35 | app := beego.NewApp() 36 | 37 | eng := engine.Default() 38 | adminPlugin := admin.NewAdmin(tables.Generators) 39 | adminPlugin.AddGenerator("user", tables.GetUserTable) 40 | 41 | examplePlugin := example.NewExample() 42 | 43 | if err := eng.AddConfigFromJSON(os.Args[len(os.Args)-1]). 44 | AddPlugins(adminPlugin, examplePlugin).Use(app); err != nil { 45 | panic(err) 46 | } 47 | 48 | template.AddComp(chartjs.NewChart()) 49 | 50 | eng.HTML("GET", "/admin", tables.GetContent) 51 | 52 | beego.BConfig.Listen.HTTPAddr = "127.0.0.1" 53 | beego.BConfig.Listen.HTTPPort = 9087 54 | 55 | return app.Handlers 56 | } 57 | 58 | func NewHandler(dbs config.DatabaseList, gens table.GeneratorList) http.Handler { 59 | 60 | app := beego.NewApp() 61 | 62 | eng := engine.Default() 63 | adminPlugin := admin.NewAdmin(gens) 64 | 65 | if err := eng.AddConfig(&config.Config{ 66 | Databases: dbs, 67 | UrlPrefix: "admin", 68 | Store: config.Store{ 69 | Path: "./uploads", 70 | Prefix: "uploads", 71 | }, 72 | Language: language.EN, 73 | IndexUrl: "/", 74 | Debug: true, 75 | ColorScheme: adminlte.ColorschemeSkinBlack, 76 | }). 77 | AddPlugins(adminPlugin).Use(app); err != nil { 78 | panic(err) 79 | } 80 | 81 | template.AddComp(chartjs.NewChart()) 82 | 83 | eng.HTML("GET", "/admin", tables.GetContent) 84 | 85 | beego.BConfig.Listen.HTTPAddr = "127.0.0.1" 86 | beego.BConfig.Listen.HTTPPort = 9087 87 | 88 | return app.Handlers 89 | } 90 | -------------------------------------------------------------------------------- /tests/frameworks/beego/beego_test.go: -------------------------------------------------------------------------------- 1 | package beego 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | 7 | "github.com/GoAdminGroup/go-admin/tests/common" 8 | "github.com/gavv/httpexpect" 9 | ) 10 | 11 | func TestBeego(t *testing.T) { 12 | common.ExtraTest(httpexpect.WithConfig(httpexpect.Config{ 13 | Client: &http.Client{ 14 | Transport: httpexpect.NewBinder(internalHandler()), 15 | Jar: httpexpect.NewJar(), 16 | }, 17 | Reporter: httpexpect.NewAssertReporter(t), 18 | })) 19 | } 20 | -------------------------------------------------------------------------------- /tests/frameworks/beego2/beego.go: -------------------------------------------------------------------------------- 1 | package beego 2 | 3 | import ( 4 | "net/http" 5 | "os" 6 | 7 | // add beego adapter 8 | _ "github.com/GoAdminGroup/go-admin/adapter/beego2" 9 | // add mysql driver 10 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" 11 | // add postgresql driver 12 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/postgres" 13 | // add sqlite driver 14 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/sqlite" 15 | // add mssql driver 16 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mssql" 17 | 18 | "github.com/GoAdminGroup/go-admin/engine" 19 | "github.com/GoAdminGroup/go-admin/modules/config" 20 | "github.com/GoAdminGroup/go-admin/modules/language" 21 | "github.com/GoAdminGroup/go-admin/plugins/admin" 22 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 23 | "github.com/GoAdminGroup/go-admin/plugins/example" 24 | "github.com/GoAdminGroup/go-admin/template" 25 | "github.com/GoAdminGroup/go-admin/template/chartjs" 26 | "github.com/GoAdminGroup/go-admin/tests/tables" 27 | "github.com/GoAdminGroup/themes/adminlte" 28 | "github.com/beego/beego/v2/server/web" 29 | ) 30 | 31 | func internalHandler() http.Handler { 32 | 33 | app := web.NewHttpSever() 34 | 35 | eng := engine.Default() 36 | adminPlugin := admin.NewAdmin(tables.Generators) 37 | adminPlugin.AddGenerator("user", tables.GetUserTable) 38 | 39 | examplePlugin := example.NewExample() 40 | 41 | if err := eng.AddConfigFromJSON(os.Args[len(os.Args)-1]). 42 | AddPlugins(adminPlugin, examplePlugin).Use(app); err != nil { 43 | panic(err) 44 | } 45 | 46 | template.AddComp(chartjs.NewChart()) 47 | 48 | eng.HTML("GET", "/admin", tables.GetContent) 49 | 50 | app.Cfg.Listen.HTTPAddr = "127.0.0.1" 51 | app.Cfg.Listen.HTTPPort = 9087 52 | 53 | return app.Handlers 54 | } 55 | 56 | func NewHandler(dbs config.DatabaseList, gens table.GeneratorList) http.Handler { 57 | 58 | app := web.NewHttpSever() 59 | 60 | eng := engine.Default() 61 | adminPlugin := admin.NewAdmin(gens) 62 | 63 | if err := eng.AddConfig(&config.Config{ 64 | Databases: dbs, 65 | UrlPrefix: "admin", 66 | Store: config.Store{ 67 | Path: "./uploads", 68 | Prefix: "uploads", 69 | }, 70 | Language: language.EN, 71 | IndexUrl: "/", 72 | Debug: true, 73 | ColorScheme: adminlte.ColorschemeSkinBlack, 74 | }). 75 | AddPlugins(adminPlugin).Use(app); err != nil { 76 | panic(err) 77 | } 78 | 79 | template.AddComp(chartjs.NewChart()) 80 | 81 | eng.HTML("GET", "/admin", tables.GetContent) 82 | 83 | app.Cfg.Listen.HTTPAddr = "127.0.0.1" 84 | app.Cfg.Listen.HTTPPort = 9087 85 | 86 | return app.Handlers 87 | } 88 | -------------------------------------------------------------------------------- /tests/frameworks/beego2/beego_test.go: -------------------------------------------------------------------------------- 1 | package beego 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | 7 | "github.com/GoAdminGroup/go-admin/tests/common" 8 | "github.com/gavv/httpexpect" 9 | ) 10 | 11 | func TestBeego2(t *testing.T) { 12 | common.ExtraTest(httpexpect.WithConfig(httpexpect.Config{ 13 | Client: &http.Client{ 14 | Transport: httpexpect.NewBinder(internalHandler()), 15 | Jar: httpexpect.NewJar(), 16 | }, 17 | Reporter: httpexpect.NewAssertReporter(t), 18 | })) 19 | } 20 | -------------------------------------------------------------------------------- /tests/frameworks/buffalo/buffalo_test.go: -------------------------------------------------------------------------------- 1 | package buffalo 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | 7 | "github.com/GoAdminGroup/go-admin/tests/common" 8 | "github.com/gavv/httpexpect" 9 | ) 10 | 11 | func TestBuffalo(t *testing.T) { 12 | common.ExtraTest(httpexpect.WithConfig(httpexpect.Config{ 13 | Client: &http.Client{ 14 | Transport: httpexpect.NewBinder(internalHandler()), 15 | Jar: httpexpect.NewJar(), 16 | }, 17 | Reporter: httpexpect.NewAssertReporter(t), 18 | })) 19 | } 20 | -------------------------------------------------------------------------------- /tests/frameworks/chi/chi.go: -------------------------------------------------------------------------------- 1 | package chi 2 | 3 | import ( 4 | // add chi adapter 5 | _ "github.com/GoAdminGroup/go-admin/adapter/chi" 6 | "github.com/GoAdminGroup/go-admin/modules/config" 7 | "github.com/GoAdminGroup/go-admin/modules/language" 8 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 9 | 10 | // add mysql driver 11 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" 12 | // add postgresql driver 13 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/postgres" 14 | // add sqlite driver 15 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/sqlite" 16 | // add mssql driver 17 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mssql" 18 | // add adminlte ui theme 19 | "github.com/GoAdminGroup/themes/adminlte" 20 | 21 | "net/http" 22 | "os" 23 | 24 | "github.com/GoAdminGroup/go-admin/engine" 25 | "github.com/GoAdminGroup/go-admin/plugins/admin" 26 | "github.com/GoAdminGroup/go-admin/plugins/example" 27 | "github.com/GoAdminGroup/go-admin/template" 28 | "github.com/GoAdminGroup/go-admin/template/chartjs" 29 | "github.com/GoAdminGroup/go-admin/tests/tables" 30 | "github.com/go-chi/chi" 31 | ) 32 | 33 | func internalHandler() http.Handler { 34 | r := chi.NewRouter() 35 | 36 | eng := engine.Default() 37 | 38 | adminPlugin := admin.NewAdmin(tables.Generators) 39 | adminPlugin.AddGenerator("user", tables.GetUserTable) 40 | examplePlugin := example.NewExample() 41 | template.AddComp(chartjs.NewChart()) 42 | 43 | if err := eng.AddConfigFromJSON(os.Args[len(os.Args)-1]). 44 | AddPlugins(adminPlugin, examplePlugin).Use(r); err != nil { 45 | panic(err) 46 | } 47 | 48 | eng.HTML("GET", "/admin", tables.GetContent) 49 | 50 | return r 51 | } 52 | 53 | func NewHandler(dbs config.DatabaseList, gens table.GeneratorList) http.Handler { 54 | r := chi.NewRouter() 55 | 56 | eng := engine.Default() 57 | 58 | adminPlugin := admin.NewAdmin(gens) 59 | template.AddComp(chartjs.NewChart()) 60 | 61 | if err := eng.AddConfig(&config.Config{ 62 | Databases: dbs, 63 | UrlPrefix: "admin", 64 | Store: config.Store{ 65 | Path: "./uploads", 66 | Prefix: "uploads", 67 | }, 68 | Language: language.EN, 69 | IndexUrl: "/", 70 | Debug: true, 71 | ColorScheme: adminlte.ColorschemeSkinBlack, 72 | }). 73 | AddPlugins(adminPlugin).Use(r); err != nil { 74 | panic(err) 75 | } 76 | 77 | eng.HTML("GET", "/admin", tables.GetContent) 78 | 79 | return r 80 | } 81 | -------------------------------------------------------------------------------- /tests/frameworks/chi/chi_test.go: -------------------------------------------------------------------------------- 1 | package chi 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | 7 | "github.com/GoAdminGroup/go-admin/tests/common" 8 | "github.com/gavv/httpexpect" 9 | ) 10 | 11 | func TestChi(t *testing.T) { 12 | common.ExtraTest(httpexpect.WithConfig(httpexpect.Config{ 13 | Client: &http.Client{ 14 | Transport: httpexpect.NewBinder(internalHandler()), 15 | Jar: httpexpect.NewJar(), 16 | }, 17 | Reporter: httpexpect.NewAssertReporter(t), 18 | })) 19 | } 20 | -------------------------------------------------------------------------------- /tests/frameworks/echo/echo.go: -------------------------------------------------------------------------------- 1 | package echo 2 | 3 | import ( 4 | // add echo adapter 5 | _ "github.com/GoAdminGroup/go-admin/adapter/echo" 6 | "github.com/GoAdminGroup/go-admin/modules/config" 7 | "github.com/GoAdminGroup/go-admin/modules/language" 8 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 9 | 10 | // add mysql driver 11 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" 12 | // add postgresql driver 13 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/postgres" 14 | // add sqlite driver 15 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/sqlite" 16 | // add mssql driver 17 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mssql" 18 | // add adminlte ui theme 19 | "github.com/GoAdminGroup/themes/adminlte" 20 | 21 | "net/http" 22 | "os" 23 | 24 | "github.com/GoAdminGroup/go-admin/engine" 25 | "github.com/GoAdminGroup/go-admin/plugins/admin" 26 | "github.com/GoAdminGroup/go-admin/plugins/example" 27 | "github.com/GoAdminGroup/go-admin/template" 28 | "github.com/GoAdminGroup/go-admin/template/chartjs" 29 | "github.com/GoAdminGroup/go-admin/tests/tables" 30 | "github.com/labstack/echo/v4" 31 | ) 32 | 33 | func internalHandler() http.Handler { 34 | e := echo.New() 35 | 36 | eng := engine.Default() 37 | 38 | adminPlugin := admin.NewAdmin(tables.Generators) 39 | adminPlugin.AddGenerator("user", tables.GetUserTable) 40 | template.AddComp(chartjs.NewChart()) 41 | 42 | examplePlugin := example.NewExample() 43 | 44 | if err := eng.AddConfigFromJSON(os.Args[len(os.Args)-1]). 45 | AddPlugins(adminPlugin, examplePlugin).Use(e); err != nil { 46 | panic(err) 47 | } 48 | 49 | eng.HTML("GET", "/admin", tables.GetContent) 50 | 51 | return e 52 | } 53 | 54 | func NewHandler(dbs config.DatabaseList, gens table.GeneratorList) http.Handler { 55 | e := echo.New() 56 | 57 | eng := engine.Default() 58 | 59 | adminPlugin := admin.NewAdmin(gens) 60 | 61 | template.AddComp(chartjs.NewChart()) 62 | 63 | if err := eng.AddConfig(&config.Config{ 64 | Databases: dbs, 65 | UrlPrefix: "admin", 66 | Store: config.Store{ 67 | Path: "./uploads", 68 | Prefix: "uploads", 69 | }, 70 | Language: language.EN, 71 | IndexUrl: "/", 72 | Debug: true, 73 | ColorScheme: adminlte.ColorschemeSkinBlack, 74 | }). 75 | AddPlugins(adminPlugin).Use(e); err != nil { 76 | panic(err) 77 | } 78 | 79 | eng.HTML("GET", "/admin", tables.GetContent) 80 | 81 | return e 82 | } 83 | -------------------------------------------------------------------------------- /tests/frameworks/echo/echo_test.go: -------------------------------------------------------------------------------- 1 | package echo 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | 7 | "github.com/GoAdminGroup/go-admin/tests/common" 8 | "github.com/gavv/httpexpect" 9 | ) 10 | 11 | func TestEcho(t *testing.T) { 12 | common.ExtraTest(httpexpect.WithConfig(httpexpect.Config{ 13 | Client: &http.Client{ 14 | Transport: httpexpect.NewBinder(internalHandler()), 15 | Jar: httpexpect.NewJar(), 16 | }, 17 | Reporter: httpexpect.NewAssertReporter(t), 18 | })) 19 | } 20 | -------------------------------------------------------------------------------- /tests/frameworks/fasthttp/fasthttp.go: -------------------------------------------------------------------------------- 1 | package fasthttp 2 | 3 | import ( 4 | // add fasthttp adapter 5 | ada "github.com/GoAdminGroup/go-admin/adapter/fasthttp" 6 | // add mysql driver 7 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" 8 | // add postgresql driver 9 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/postgres" 10 | // add sqlite driver 11 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/sqlite" 12 | // add mssql driver 13 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mssql" 14 | // add adminlte ui theme 15 | "github.com/GoAdminGroup/themes/adminlte" 16 | 17 | "os" 18 | 19 | "github.com/GoAdminGroup/go-admin/engine" 20 | "github.com/GoAdminGroup/go-admin/modules/config" 21 | "github.com/GoAdminGroup/go-admin/modules/language" 22 | "github.com/GoAdminGroup/go-admin/plugins/admin" 23 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 24 | "github.com/GoAdminGroup/go-admin/template" 25 | "github.com/GoAdminGroup/go-admin/template/chartjs" 26 | "github.com/GoAdminGroup/go-admin/tests/tables" 27 | "github.com/buaazp/fasthttprouter" 28 | "github.com/valyala/fasthttp" 29 | ) 30 | 31 | func internalHandler() fasthttp.RequestHandler { 32 | router := fasthttprouter.New() 33 | 34 | eng := engine.Default() 35 | 36 | adminPlugin := admin.NewAdmin(tables.Generators).AddDisplayFilterXssJsFilter() 37 | adminPlugin.AddGenerator("user", tables.GetUserTable) 38 | 39 | template.AddComp(chartjs.NewChart()) 40 | 41 | if err := eng.AddConfigFromJSON(os.Args[len(os.Args)-1]). 42 | AddPlugins(adminPlugin). 43 | Use(router); err != nil { 44 | panic(err) 45 | } 46 | 47 | eng.HTML("GET", "/admin", tables.GetContent) 48 | 49 | return func(ctx *fasthttp.RequestCtx) { 50 | router.Handler(ctx) 51 | } 52 | } 53 | 54 | func NewHandler(dbs config.DatabaseList, gens table.GeneratorList) fasthttp.RequestHandler { 55 | router := fasthttprouter.New() 56 | 57 | eng := engine.Default() 58 | 59 | template.AddComp(chartjs.NewChart()) 60 | 61 | if err := eng.AddConfig(&config.Config{ 62 | Databases: dbs, 63 | UrlPrefix: "admin", 64 | Store: config.Store{ 65 | Path: "./uploads", 66 | Prefix: "uploads", 67 | }, 68 | Language: language.EN, 69 | IndexUrl: "/", 70 | Debug: true, 71 | ColorScheme: adminlte.ColorschemeSkinBlack, 72 | }). 73 | AddAdapter(new(ada.Fasthttp)). 74 | AddGenerators(gens). 75 | Use(router); err != nil { 76 | panic(err) 77 | } 78 | 79 | eng.HTML("GET", "/admin", tables.GetContent) 80 | 81 | return func(ctx *fasthttp.RequestCtx) { 82 | router.Handler(ctx) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /tests/frameworks/fasthttp/fasthttp_test.go: -------------------------------------------------------------------------------- 1 | package fasthttp 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | 7 | "github.com/GoAdminGroup/go-admin/tests/common" 8 | "github.com/gavv/httpexpect" 9 | ) 10 | 11 | func TestFasthttp(t *testing.T) { 12 | common.ExtraTest(httpexpect.WithConfig(httpexpect.Config{ 13 | Client: &http.Client{ 14 | Transport: httpexpect.NewFastBinder(internalHandler()), 15 | Jar: httpexpect.NewJar(), 16 | }, 17 | Reporter: httpexpect.NewAssertReporter(t), 18 | })) 19 | } 20 | -------------------------------------------------------------------------------- /tests/frameworks/gear/gear.go: -------------------------------------------------------------------------------- 1 | package gear 2 | 3 | import ( 4 | // add gin adapter 5 | ada "github.com/GoAdminGroup/go-admin/adapter/gear" 6 | "github.com/teambition/gear" 7 | 8 | // add mysql driver 9 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" 10 | // add postgresql driver 11 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/postgres" 12 | // add sqlite driver 13 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/sqlite" 14 | // add mssql driver 15 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mssql" 16 | // add adminlte ui theme 17 | "github.com/GoAdminGroup/themes/adminlte" 18 | 19 | "net/http" 20 | "os" 21 | 22 | "github.com/GoAdminGroup/go-admin/engine" 23 | "github.com/GoAdminGroup/go-admin/modules/config" 24 | "github.com/GoAdminGroup/go-admin/modules/language" 25 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 26 | "github.com/GoAdminGroup/go-admin/template" 27 | "github.com/GoAdminGroup/go-admin/template/chartjs" 28 | "github.com/GoAdminGroup/go-admin/tests/tables" 29 | ) 30 | 31 | func internalHandler() http.Handler { 32 | app := gear.New() 33 | 34 | eng := engine.Default() 35 | 36 | template.AddComp(chartjs.NewChart()) 37 | 38 | if err := eng.AddConfigFromJSON(os.Args[len(os.Args)-1]). 39 | AddGenerators(tables.Generators). 40 | AddGenerator("user", tables.GetUserTable). 41 | Use(app); err != nil { 42 | panic(err) 43 | } 44 | 45 | eng.HTML("GET", "/admin", tables.GetContent) 46 | 47 | return app 48 | } 49 | 50 | func NewHandler(dbs config.DatabaseList, gens table.GeneratorList) http.Handler { 51 | app := gear.New() 52 | 53 | eng := engine.Default() 54 | 55 | template.AddComp(chartjs.NewChart()) 56 | 57 | if err := eng.AddConfig(&config.Config{ 58 | Databases: dbs, 59 | UrlPrefix: "admin", 60 | Store: config.Store{ 61 | Path: "./uploads", 62 | Prefix: "uploads", 63 | }, 64 | Language: language.EN, 65 | IndexUrl: "/", 66 | Debug: true, 67 | ColorScheme: adminlte.ColorschemeSkinBlack, 68 | }). 69 | AddAdapter(new(ada.Gear)). 70 | AddGenerators(gens). 71 | Use(app); err != nil { 72 | panic(err) 73 | } 74 | 75 | eng.HTML("GET", "/admin", tables.GetContent) 76 | 77 | return app 78 | } 79 | -------------------------------------------------------------------------------- /tests/frameworks/gear/gear_test.go: -------------------------------------------------------------------------------- 1 | package gear 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | 7 | "github.com/GoAdminGroup/go-admin/tests/common" 8 | "github.com/gavv/httpexpect" 9 | ) 10 | 11 | func TestGear(t *testing.T) { 12 | common.ExtraTest(httpexpect.WithConfig(httpexpect.Config{ 13 | Client: &http.Client{ 14 | Transport: httpexpect.NewBinder(internalHandler()), 15 | Jar: httpexpect.NewJar(), 16 | }, 17 | Reporter: httpexpect.NewAssertReporter(t), 18 | })) 19 | } 20 | -------------------------------------------------------------------------------- /tests/frameworks/gf/gf.go: -------------------------------------------------------------------------------- 1 | package gf 2 | 3 | import ( 4 | "net/http" 5 | "os" 6 | 7 | // add gf adapter 8 | _ "github.com/GoAdminGroup/go-admin/adapter/gf" 9 | // add mysql driver 10 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" 11 | // add postgresql driver 12 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/postgres" 13 | // add sqlite driver 14 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/sqlite" 15 | // add mssql driver 16 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mssql" 17 | // add adminlte ui theme 18 | "github.com/GoAdminGroup/themes/adminlte" 19 | 20 | "github.com/GoAdminGroup/go-admin/engine" 21 | "github.com/GoAdminGroup/go-admin/modules/config" 22 | "github.com/GoAdminGroup/go-admin/modules/language" 23 | "github.com/GoAdminGroup/go-admin/plugins/admin" 24 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 25 | "github.com/GoAdminGroup/go-admin/template" 26 | "github.com/GoAdminGroup/go-admin/template/chartjs" 27 | "github.com/GoAdminGroup/go-admin/tests/tables" 28 | "github.com/gogf/gf/frame/g" 29 | ) 30 | 31 | func internalHandler() http.Handler { 32 | s := g.Server(8103) 33 | 34 | eng := engine.Default() 35 | 36 | adminPlugin := admin.NewAdmin(tables.Generators).AddDisplayFilterXssJsFilter() 37 | 38 | template.AddComp(chartjs.NewChart()) 39 | 40 | adminPlugin.AddGenerator("user", tables.GetUserTable) 41 | 42 | if err := eng.AddConfigFromJSON(os.Args[len(os.Args)-1]). 43 | AddPlugins(adminPlugin). 44 | Use(s); err != nil { 45 | panic(err) 46 | } 47 | 48 | eng.HTML("GET", "/admin", tables.GetContent) 49 | 50 | return s 51 | } 52 | 53 | func NewHandler(dbs config.DatabaseList, gens table.GeneratorList) http.Handler { 54 | 55 | s := g.Server(8103) 56 | 57 | eng := engine.Default() 58 | adminPlugin := admin.NewAdmin(gens) 59 | 60 | if err := eng.AddConfig(&config.Config{ 61 | Databases: dbs, 62 | UrlPrefix: "admin", 63 | Store: config.Store{ 64 | Path: "./uploads", 65 | Prefix: "uploads", 66 | }, 67 | Language: language.EN, 68 | IndexUrl: "/", 69 | Debug: true, 70 | ColorScheme: adminlte.ColorschemeSkinBlack, 71 | }). 72 | AddPlugins(adminPlugin).Use(s); err != nil { 73 | panic(err) 74 | } 75 | 76 | template.AddComp(chartjs.NewChart()) 77 | 78 | eng.HTML("GET", "/admin", tables.GetContent) 79 | 80 | return s 81 | } 82 | -------------------------------------------------------------------------------- /tests/frameworks/gf/gf_test.go: -------------------------------------------------------------------------------- 1 | package gf 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | 7 | "github.com/GoAdminGroup/go-admin/tests/common" 8 | "github.com/gavv/httpexpect" 9 | ) 10 | 11 | func TestGf(t *testing.T) { 12 | common.ExtraTest(httpexpect.WithConfig(httpexpect.Config{ 13 | Client: &http.Client{ 14 | Transport: httpexpect.NewBinder(internalHandler()), 15 | Jar: httpexpect.NewJar(), 16 | }, 17 | Reporter: httpexpect.NewAssertReporter(t), 18 | })) 19 | } 20 | -------------------------------------------------------------------------------- /tests/frameworks/gf2/gf.go: -------------------------------------------------------------------------------- 1 | package gf 2 | 3 | import ( 4 | // add gf adapter 5 | "reflect" 6 | 7 | _ "github.com/GoAdminGroup/go-admin/adapter/gf2" 8 | "github.com/agiledragon/gomonkey" 9 | 10 | // add mysql driver 11 | "github.com/GoAdminGroup/go-admin/modules/config" 12 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" 13 | "github.com/GoAdminGroup/go-admin/modules/language" 14 | 15 | // add postgresql driver 16 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/postgres" 17 | // add sqlite driver 18 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/sqlite" 19 | // add mssql driver 20 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mssql" 21 | // add adminlte ui theme 22 | "github.com/GoAdminGroup/themes/adminlte" 23 | 24 | "net/http" 25 | "os" 26 | 27 | "github.com/GoAdminGroup/go-admin/engine" 28 | "github.com/GoAdminGroup/go-admin/plugins/admin" 29 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 30 | "github.com/GoAdminGroup/go-admin/template" 31 | "github.com/GoAdminGroup/go-admin/template/chartjs" 32 | "github.com/GoAdminGroup/go-admin/tests/tables" 33 | "github.com/gogf/gf/v2/frame/g" 34 | "github.com/gogf/gf/v2/net/ghttp" 35 | ) 36 | 37 | func internalHandler() http.Handler { 38 | s := g.Server() 39 | 40 | eng := engine.Default() 41 | 42 | adminPlugin := admin.NewAdmin(tables.Generators).AddDisplayFilterXssJsFilter() 43 | 44 | template.AddComp(chartjs.NewChart()) 45 | 46 | adminPlugin.AddGenerator("user", tables.GetUserTable) 47 | 48 | if err := eng.AddConfigFromJSON(os.Args[len(os.Args)-1]). 49 | AddPlugins(adminPlugin). 50 | Use(s); err != nil { 51 | panic(err) 52 | } 53 | 54 | eng.HTML("GET", "/admin", tables.GetContent) 55 | 56 | s.SetPort(8103) 57 | 58 | gomonkey.ApplyMethod(reflect.TypeOf(new(ghttp.Request).Session), "Close", 59 | func(*ghttp.Session) error { 60 | return nil 61 | }) 62 | 63 | return s 64 | } 65 | 66 | func NewHandler(dbs config.DatabaseList, gens table.GeneratorList) http.Handler { 67 | 68 | s := g.Server(8103) 69 | 70 | eng := engine.Default() 71 | adminPlugin := admin.NewAdmin(gens) 72 | 73 | if err := eng.AddConfig(&config.Config{ 74 | Databases: dbs, 75 | UrlPrefix: "admin", 76 | Store: config.Store{ 77 | Path: "./uploads", 78 | Prefix: "uploads", 79 | }, 80 | Language: language.EN, 81 | IndexUrl: "/", 82 | Debug: true, 83 | ColorScheme: adminlte.ColorschemeSkinBlack, 84 | }). 85 | AddPlugins(adminPlugin).Use(s); err != nil { 86 | panic(err) 87 | } 88 | 89 | template.AddComp(chartjs.NewChart()) 90 | 91 | eng.HTML("GET", "/admin", tables.GetContent) 92 | 93 | return s 94 | } 95 | -------------------------------------------------------------------------------- /tests/frameworks/gf2/gf_test.go: -------------------------------------------------------------------------------- 1 | package gf 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | 7 | "github.com/GoAdminGroup/go-admin/tests/common" 8 | "github.com/gavv/httpexpect" 9 | ) 10 | 11 | func TestGf2(t *testing.T) { 12 | common.ExtraTest(httpexpect.WithConfig(httpexpect.Config{ 13 | Client: &http.Client{ 14 | Transport: httpexpect.NewBinder(internalHandler()), 15 | Jar: httpexpect.NewJar(), 16 | }, 17 | Reporter: httpexpect.NewAssertReporter(t), 18 | })) 19 | } 20 | -------------------------------------------------------------------------------- /tests/frameworks/gin/gin.go: -------------------------------------------------------------------------------- 1 | package gin 2 | 3 | import ( 4 | // add gin adapter 5 | 6 | ada "github.com/GoAdminGroup/go-admin/adapter/gin" 7 | // add mysql driver 8 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" 9 | // add postgresql driver 10 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/postgres" 11 | // add sqlite driver 12 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/sqlite" 13 | // add mssql driver 14 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mssql" 15 | // add adminlte ui theme 16 | "github.com/GoAdminGroup/themes/adminlte" 17 | 18 | "net/http" 19 | "os" 20 | 21 | "github.com/GoAdminGroup/go-admin/engine" 22 | "github.com/GoAdminGroup/go-admin/modules/config" 23 | "github.com/GoAdminGroup/go-admin/modules/language" 24 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 25 | "github.com/GoAdminGroup/go-admin/template" 26 | "github.com/GoAdminGroup/go-admin/template/chartjs" 27 | "github.com/GoAdminGroup/go-admin/tests/tables" 28 | "github.com/gin-gonic/gin" 29 | ) 30 | 31 | func internalHandler() http.Handler { 32 | r := gin.Default() 33 | 34 | gin.SetMode(gin.ReleaseMode) 35 | 36 | eng := engine.Default() 37 | 38 | template.AddComp(chartjs.NewChart()) 39 | 40 | if err := eng.AddConfigFromJSON(os.Args[len(os.Args)-1]). 41 | AddGenerators(tables.Generators). 42 | AddGenerator("user", tables.GetUserTable). 43 | Use(r); err != nil { 44 | panic(err) 45 | } 46 | 47 | eng.HTML("GET", "/admin", tables.GetContent) 48 | 49 | r.Static("/uploads", "./uploads") 50 | 51 | return r 52 | } 53 | 54 | func NewHandler(dbs config.DatabaseList, gens table.GeneratorList) http.Handler { 55 | r := gin.Default() 56 | 57 | gin.SetMode(gin.ReleaseMode) 58 | 59 | eng := engine.Default() 60 | 61 | template.AddComp(chartjs.NewChart()) 62 | 63 | if err := eng.AddConfig(&config.Config{ 64 | Databases: dbs, 65 | UrlPrefix: "admin", 66 | Store: config.Store{ 67 | Path: "./uploads", 68 | Prefix: "uploads", 69 | }, 70 | Language: language.EN, 71 | IndexUrl: "/", 72 | Debug: true, 73 | ColorScheme: adminlte.ColorschemeSkinBlack, 74 | }). 75 | AddAdapter(new(ada.Gin)). 76 | AddGenerators(gens). 77 | Use(r); err != nil { 78 | panic(err) 79 | } 80 | 81 | eng.HTML("GET", "/admin", tables.GetContent) 82 | 83 | r.Static("/uploads", "./uploads") 84 | 85 | return r 86 | } 87 | -------------------------------------------------------------------------------- /tests/frameworks/gin/gin_test.go: -------------------------------------------------------------------------------- 1 | package gin 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | 7 | "github.com/GoAdminGroup/go-admin/tests/common" 8 | "github.com/gavv/httpexpect" 9 | ) 10 | 11 | func TestGin(t *testing.T) { 12 | common.ExtraTest(httpexpect.WithConfig(httpexpect.Config{ 13 | Client: &http.Client{ 14 | Transport: httpexpect.NewBinder(internalHandler()), 15 | Jar: httpexpect.NewJar(), 16 | }, 17 | Reporter: httpexpect.NewAssertReporter(t), 18 | })) 19 | } 20 | -------------------------------------------------------------------------------- /tests/frameworks/gofiber/gofiber.go: -------------------------------------------------------------------------------- 1 | package gofiber 2 | 3 | import ( 4 | // add fasthttp adapter 5 | ada "github.com/GoAdminGroup/go-admin/adapter/gofiber" 6 | // add mysql driver 7 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" 8 | // add postgresql driver 9 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/postgres" 10 | // add sqlite driver 11 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/sqlite" 12 | // add mssql driver 13 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mssql" 14 | // add adminlte ui theme 15 | "github.com/GoAdminGroup/themes/adminlte" 16 | 17 | "os" 18 | 19 | "github.com/GoAdminGroup/go-admin/engine" 20 | "github.com/GoAdminGroup/go-admin/modules/config" 21 | "github.com/GoAdminGroup/go-admin/modules/language" 22 | "github.com/GoAdminGroup/go-admin/plugins/admin" 23 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 24 | "github.com/GoAdminGroup/go-admin/template" 25 | "github.com/GoAdminGroup/go-admin/template/chartjs" 26 | "github.com/GoAdminGroup/go-admin/tests/tables" 27 | "github.com/gofiber/fiber/v2" 28 | "github.com/valyala/fasthttp" 29 | ) 30 | 31 | func internalHandler() fasthttp.RequestHandler { 32 | app := fiber.New(fiber.Config{ 33 | ServerHeader: "Fiber", 34 | }) 35 | 36 | eng := engine.Default() 37 | 38 | adminPlugin := admin.NewAdmin(tables.Generators).AddDisplayFilterXssJsFilter() 39 | adminPlugin.AddGenerator("user", tables.GetUserTable) 40 | 41 | template.AddComp(chartjs.NewChart()) 42 | 43 | if err := eng.AddConfigFromJSON(os.Args[len(os.Args)-1]). 44 | AddPlugins(adminPlugin). 45 | Use(app); err != nil { 46 | panic(err) 47 | } 48 | 49 | eng.HTML("GET", "/admin", tables.GetContent) 50 | 51 | return app.Handler() 52 | } 53 | 54 | func NewHandler(dbs config.DatabaseList, gens table.GeneratorList) fasthttp.RequestHandler { 55 | app := fiber.New(fiber.Config{ 56 | ServerHeader: "Fiber", 57 | }) 58 | 59 | eng := engine.Default() 60 | 61 | template.AddComp(chartjs.NewChart()) 62 | 63 | if err := eng.AddConfig(&config.Config{ 64 | Databases: dbs, 65 | UrlPrefix: "admin", 66 | Store: config.Store{ 67 | Path: "./uploads", 68 | Prefix: "uploads", 69 | }, 70 | Language: language.EN, 71 | IndexUrl: "/", 72 | Debug: true, 73 | ColorScheme: adminlte.ColorschemeSkinBlack, 74 | }). 75 | AddAdapter(new(ada.Gofiber)). 76 | AddGenerators(gens). 77 | Use(app); err != nil { 78 | panic(err) 79 | } 80 | 81 | eng.HTML("GET", "/admin", tables.GetContent) 82 | 83 | return app.Handler() 84 | } 85 | -------------------------------------------------------------------------------- /tests/frameworks/gofiber/gofiber_test.go: -------------------------------------------------------------------------------- 1 | package gofiber 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | 7 | "github.com/GoAdminGroup/go-admin/tests/common" 8 | "github.com/gavv/httpexpect" 9 | ) 10 | 11 | func TestGofiber(t *testing.T) { 12 | common.ExtraTest(httpexpect.WithConfig(httpexpect.Config{ 13 | Client: &http.Client{ 14 | Transport: httpexpect.NewFastBinder(internalHandler()), 15 | Jar: httpexpect.NewJar(), 16 | }, 17 | Reporter: httpexpect.NewAssertReporter(t), 18 | })) 19 | } 20 | -------------------------------------------------------------------------------- /tests/frameworks/gorilla/gorilla.go: -------------------------------------------------------------------------------- 1 | package gorilla 2 | 3 | import ( 4 | // add gorilla adapter 5 | _ "github.com/GoAdminGroup/go-admin/adapter/gorilla" 6 | "github.com/GoAdminGroup/go-admin/modules/config" 7 | "github.com/GoAdminGroup/go-admin/modules/language" 8 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 9 | 10 | // add mysql driver 11 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" 12 | // add postgresql driver 13 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/postgres" 14 | // add sqlite driver 15 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/sqlite" 16 | // add mssql driver 17 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mssql" 18 | // add adminlte ui theme 19 | "github.com/GoAdminGroup/themes/adminlte" 20 | 21 | "net/http" 22 | "os" 23 | 24 | "github.com/GoAdminGroup/go-admin/engine" 25 | "github.com/GoAdminGroup/go-admin/plugins/admin" 26 | "github.com/GoAdminGroup/go-admin/plugins/example" 27 | "github.com/GoAdminGroup/go-admin/template" 28 | "github.com/GoAdminGroup/go-admin/template/chartjs" 29 | "github.com/GoAdminGroup/go-admin/tests/tables" 30 | "github.com/gorilla/mux" 31 | ) 32 | 33 | func internalHandler() http.Handler { 34 | app := mux.NewRouter() 35 | eng := engine.Default() 36 | 37 | examplePlugin := example.NewExample() 38 | template.AddComp(chartjs.NewChart()) 39 | 40 | if err := eng.AddConfigFromJSON(os.Args[len(os.Args)-1]). 41 | AddPlugins(admin.NewAdmin(tables.Generators). 42 | AddGenerator("user", tables.GetUserTable), examplePlugin). 43 | Use(app); err != nil { 44 | panic(err) 45 | } 46 | 47 | eng.HTML("GET", "/admin", tables.GetContent) 48 | 49 | return app 50 | } 51 | 52 | func NewHandler(dbs config.DatabaseList, gens table.GeneratorList) http.Handler { 53 | app := mux.NewRouter() 54 | eng := engine.Default() 55 | 56 | template.AddComp(chartjs.NewChart()) 57 | 58 | if err := eng.AddConfig(&config.Config{ 59 | Databases: dbs, 60 | UrlPrefix: "admin", 61 | Store: config.Store{ 62 | Path: "./uploads", 63 | Prefix: "uploads", 64 | }, 65 | Language: language.EN, 66 | IndexUrl: "/", 67 | Debug: true, 68 | ColorScheme: adminlte.ColorschemeSkinBlack, 69 | }). 70 | AddPlugins(admin.NewAdmin(gens)). 71 | Use(app); err != nil { 72 | panic(err) 73 | } 74 | 75 | eng.HTML("GET", "/admin", tables.GetContent) 76 | 77 | return app 78 | } 79 | -------------------------------------------------------------------------------- /tests/frameworks/gorilla/gorilla_test.go: -------------------------------------------------------------------------------- 1 | package gorilla 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | 7 | "github.com/GoAdminGroup/go-admin/tests/common" 8 | "github.com/gavv/httpexpect" 9 | ) 10 | 11 | func TestGorilla(t *testing.T) { 12 | common.ExtraTest(httpexpect.WithConfig(httpexpect.Config{ 13 | Client: &http.Client{ 14 | Transport: httpexpect.NewBinder(internalHandler()), 15 | Jar: httpexpect.NewJar(), 16 | }, 17 | Reporter: httpexpect.NewAssertReporter(t), 18 | })) 19 | } 20 | -------------------------------------------------------------------------------- /tests/frameworks/iris/iris.go: -------------------------------------------------------------------------------- 1 | package iris 2 | 3 | import ( 4 | // add iris adapter 5 | _ "github.com/GoAdminGroup/go-admin/adapter/iris" 6 | "github.com/GoAdminGroup/go-admin/modules/config" 7 | "github.com/GoAdminGroup/go-admin/modules/language" 8 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 9 | 10 | // add mysql driver 11 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" 12 | // add postgresql driver 13 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/postgres" 14 | // add sqlite driver 15 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/sqlite" 16 | // add mssql driver 17 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mssql" 18 | // add adminlte ui theme 19 | "github.com/GoAdminGroup/themes/adminlte" 20 | 21 | "github.com/GoAdminGroup/go-admin/template" 22 | "github.com/GoAdminGroup/go-admin/template/chartjs" 23 | 24 | "net/http" 25 | "os" 26 | 27 | "github.com/GoAdminGroup/go-admin/engine" 28 | "github.com/GoAdminGroup/go-admin/plugins/admin" 29 | "github.com/GoAdminGroup/go-admin/plugins/example" 30 | "github.com/GoAdminGroup/go-admin/tests/tables" 31 | "github.com/kataras/iris/v12" 32 | ) 33 | 34 | func internalHandler() http.Handler { 35 | app := iris.New() 36 | 37 | eng := engine.Default() 38 | 39 | adminPlugin := admin.NewAdmin(tables.Generators) 40 | adminPlugin.AddGenerator("user", tables.GetUserTable) 41 | examplePlugin := example.NewExample() 42 | template.AddComp(chartjs.NewChart()) 43 | 44 | if err := eng.AddConfigFromJSON(os.Args[len(os.Args)-1]). 45 | AddPlugins(adminPlugin, examplePlugin).Use(app); err != nil { 46 | panic(err) 47 | } 48 | 49 | eng.HTML("GET", "/admin", tables.GetContent) 50 | 51 | if err := app.Build(); err != nil { 52 | panic(err) 53 | } 54 | 55 | return app.Router 56 | } 57 | 58 | func NewHandler(dbs config.DatabaseList, gens table.GeneratorList) http.Handler { 59 | app := iris.New() 60 | 61 | eng := engine.Default() 62 | 63 | adminPlugin := admin.NewAdmin(gens) 64 | 65 | examplePlugin := example.NewExample() 66 | template.AddComp(chartjs.NewChart()) 67 | 68 | if err := eng.AddConfig(&config.Config{ 69 | Databases: dbs, 70 | UrlPrefix: "admin", 71 | Store: config.Store{ 72 | Path: "./uploads", 73 | Prefix: "uploads", 74 | }, 75 | Language: language.EN, 76 | IndexUrl: "/", 77 | Debug: true, 78 | ColorScheme: adminlte.ColorschemeSkinBlack, 79 | }). 80 | AddPlugins(adminPlugin, examplePlugin).Use(app); err != nil { 81 | panic(err) 82 | } 83 | 84 | eng.HTML("GET", "/admin", tables.GetContent) 85 | 86 | if err := app.Build(); err != nil { 87 | panic(err) 88 | } 89 | 90 | return app.Router 91 | } 92 | -------------------------------------------------------------------------------- /tests/frameworks/iris/iris_test.go: -------------------------------------------------------------------------------- 1 | package iris 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | 7 | "github.com/GoAdminGroup/go-admin/tests/common" 8 | "github.com/gavv/httpexpect" 9 | ) 10 | 11 | func TestIris(t *testing.T) { 12 | common.ExtraTest(httpexpect.WithConfig(httpexpect.Config{ 13 | Client: &http.Client{ 14 | Transport: httpexpect.NewBinder(internalHandler()), 15 | Jar: httpexpect.NewJar(), 16 | }, 17 | Reporter: httpexpect.NewAssertReporter(t), 18 | })) 19 | } 20 | -------------------------------------------------------------------------------- /tests/frameworks/nethttp/nethttp.go: -------------------------------------------------------------------------------- 1 | package nethttp 2 | 3 | import ( 4 | // add net/http adapter 5 | _ "github.com/GoAdminGroup/go-admin/adapter/nethttp" 6 | "github.com/GoAdminGroup/go-admin/modules/config" 7 | "github.com/GoAdminGroup/go-admin/modules/language" 8 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 9 | 10 | // add mysql driver 11 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mysql" 12 | // add postgresql driver 13 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/postgres" 14 | // add sqlite driver 15 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/sqlite" 16 | // add mssql driver 17 | _ "github.com/GoAdminGroup/go-admin/modules/db/drivers/mssql" 18 | // add adminlte ui theme 19 | "github.com/GoAdminGroup/themes/adminlte" 20 | 21 | "net/http" 22 | "os" 23 | 24 | "github.com/GoAdminGroup/go-admin/engine" 25 | "github.com/GoAdminGroup/go-admin/plugins/admin" 26 | "github.com/GoAdminGroup/go-admin/plugins/example" 27 | "github.com/GoAdminGroup/go-admin/template" 28 | "github.com/GoAdminGroup/go-admin/template/chartjs" 29 | "github.com/GoAdminGroup/go-admin/tests/tables" 30 | ) 31 | 32 | func internalHandler() http.Handler { 33 | r := http.NewServeMux() 34 | 35 | eng := engine.Default() 36 | 37 | adminPlugin := admin.NewAdmin(tables.Generators) 38 | adminPlugin.AddGenerator("user", tables.GetUserTable) 39 | examplePlugin := example.NewExample() 40 | template.AddComp(chartjs.NewChart()) 41 | 42 | if err := eng.AddConfigFromJSON(os.Args[len(os.Args)-1]). 43 | AddPlugins(adminPlugin, examplePlugin).Use(r); err != nil { 44 | panic(err) 45 | } 46 | 47 | eng.HTML("GET", "/admin", tables.GetContent) 48 | 49 | return r 50 | } 51 | 52 | func NewHandler(dbs config.DatabaseList, gens table.GeneratorList) http.Handler { 53 | r := http.NewServeMux() 54 | 55 | eng := engine.Default() 56 | 57 | adminPlugin := admin.NewAdmin(gens) 58 | template.AddComp(chartjs.NewChart()) 59 | 60 | if err := eng.AddConfig(&config.Config{ 61 | Databases: dbs, 62 | UrlPrefix: "admin", 63 | Store: config.Store{ 64 | Path: "./uploads", 65 | Prefix: "uploads", 66 | }, 67 | Language: language.EN, 68 | IndexUrl: "/", 69 | Debug: true, 70 | ColorScheme: adminlte.ColorschemeSkinBlack, 71 | }). 72 | AddPlugins(adminPlugin).Use(r); err != nil { 73 | panic(err) 74 | } 75 | 76 | eng.HTML("GET", "/admin", tables.GetContent) 77 | 78 | return r 79 | } 80 | -------------------------------------------------------------------------------- /tests/frameworks/nethttp/nethttp_test.go: -------------------------------------------------------------------------------- 1 | package nethttp 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | 7 | "github.com/GoAdminGroup/go-admin/tests/common" 8 | "github.com/gavv/httpexpect" 9 | ) 10 | 11 | func TestNetHTTP(t *testing.T) { 12 | common.ExtraTest(httpexpect.WithConfig(httpexpect.Config{ 13 | Client: &http.Client{ 14 | Transport: httpexpect.NewBinder(internalHandler()), 15 | Jar: httpexpect.NewJar(), 16 | }, 17 | Reporter: httpexpect.NewAssertReporter(t), 18 | })) 19 | } 20 | -------------------------------------------------------------------------------- /tests/tables/authors.go: -------------------------------------------------------------------------------- 1 | package tables 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/modules/db" 6 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 7 | "github.com/GoAdminGroup/go-admin/template/types/form" 8 | ) 9 | 10 | // GetAuthorsTable return the model of table author. 11 | func GetAuthorsTable(ctx *context.Context) (authorsTable table.Table) { 12 | 13 | authorsTable = table.NewDefaultTable(ctx, table.DefaultConfig()) 14 | 15 | // connect your custom connection 16 | // authorsTable = table.NewDefaultTable(ctx, table.DefaultConfigWithDriverAndConnection("mysql", "admin")) 17 | 18 | info := authorsTable.GetInfo() 19 | info.AddField("ID", "id", db.Int).FieldSortable() 20 | info.AddField("First Name", "first_name", db.Varchar) 21 | info.AddField("Last Name", "last_name", db.Varchar) 22 | info.AddField("Email", "email", db.Varchar) 23 | info.AddField("Birthdate", "birthdate", db.Date) 24 | info.AddField("Added", "added", db.Timestamp) 25 | 26 | info.SetTable("authors").SetTitle("Authors").SetDescription("Authors") 27 | 28 | formList := authorsTable.GetForm() 29 | formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate() 30 | formList.AddField("First Name", "first_name", db.Varchar, form.Text) 31 | formList.AddField("Last Name", "last_name", db.Varchar, form.Text) 32 | formList.AddField("Email", "email", db.Varchar, form.Text) 33 | formList.AddField("Birthdate", "birthdate", db.Date, form.Text) 34 | formList.AddField("Added", "added", db.Timestamp, form.Text) 35 | 36 | formList.SetTable("authors").SetTitle("Authors").SetDescription("Authors") 37 | 38 | return 39 | } 40 | -------------------------------------------------------------------------------- /tests/tables/external.go: -------------------------------------------------------------------------------- 1 | package tables 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/modules/db" 6 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/parameter" 7 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 8 | "github.com/GoAdminGroup/go-admin/template/types/form" 9 | ) 10 | 11 | // GetExternalTable return the model from external data source. 12 | func GetExternalTable(ctx *context.Context) (externalTable table.Table) { 13 | 14 | externalTable = table.NewDefaultTable(ctx, ) 15 | 16 | info := externalTable.GetInfo() 17 | info.AddField("ID", "id", db.Int).FieldSortable() 18 | info.AddField("Title", "title", db.Varchar) 19 | 20 | info.SetTable("external"). 21 | SetTitle("Externals"). 22 | SetDescription("Externals"). 23 | SetGetDataFn(func(param parameter.Parameters) ([]map[string]interface{}, int) { 24 | return []map[string]interface{}{ 25 | { 26 | "id": 10, 27 | "title": "this is a title", 28 | }, { 29 | "id": 11, 30 | "title": "this is a title2", 31 | }, { 32 | "id": 12, 33 | "title": "this is a title3", 34 | }, { 35 | "id": 13, 36 | "title": "this is a title4", 37 | }, 38 | }, 10 39 | }) 40 | 41 | formList := externalTable.GetForm() 42 | formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate() 43 | formList.AddField("Title", "title", db.Varchar, form.Text) 44 | 45 | formList.SetTable("external").SetTitle("Externals").SetDescription("Externals") 46 | 47 | detail := externalTable.GetDetail() 48 | 49 | detail.SetTable("external"). 50 | SetTitle("Externals"). 51 | SetDescription("Externals"). 52 | SetGetDataFn(func(param parameter.Parameters) ([]map[string]interface{}, int) { 53 | return []map[string]interface{}{ 54 | { 55 | "id": 10, 56 | "title": "this is a title", 57 | }, 58 | }, 1 59 | }) 60 | 61 | return 62 | } 63 | -------------------------------------------------------------------------------- /tests/tables/posts.go: -------------------------------------------------------------------------------- 1 | package tables 2 | 3 | import ( 4 | "github.com/GoAdminGroup/go-admin/context" 5 | "github.com/GoAdminGroup/go-admin/modules/db" 6 | "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 7 | "github.com/GoAdminGroup/go-admin/template" 8 | "github.com/GoAdminGroup/go-admin/template/types" 9 | "github.com/GoAdminGroup/go-admin/template/types/form" 10 | editType "github.com/GoAdminGroup/go-admin/template/types/table" 11 | ) 12 | 13 | // GetPostsTable return the model of table posts. 14 | func GetPostsTable(ctx *context.Context) (postsTable table.Table) { 15 | 16 | postsTable = table.NewDefaultTable(ctx, table.DefaultConfig()) 17 | 18 | info := postsTable.GetInfo() 19 | info.AddField("ID", "id", db.Int).FieldSortable() 20 | info.AddField("Title", "title", db.Varchar) 21 | info.AddField("AuthorID", "author_id", db.Varchar).FieldDisplay(func(value types.FieldModel) interface{} { 22 | return template.Default(ctx). 23 | Link(). 24 | SetURL("/admin/info/authors/detail?__goadmin_detail_pk=100"). 25 | SetContent("100"). 26 | OpenInNewTab(). 27 | SetTabTitle("Author Detail"). 28 | GetContent() 29 | }) 30 | info.AddField("Description", "description", db.Varchar) 31 | info.AddField("Content", "content", db.Varchar).FieldEditAble(editType.Textarea) 32 | info.AddField("Date", "date", db.Varchar) 33 | 34 | info.SetTable("posts").SetTitle("Posts").SetDescription("Posts") 35 | 36 | formList := postsTable.GetForm() 37 | formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate() 38 | formList.AddField("Title", "title", db.Varchar, form.Text) 39 | formList.AddField("Description", "description", db.Varchar, form.Text) 40 | formList.AddField("Content", "content", db.Varchar, form.RichText).FieldEnableFileUpload() 41 | formList.AddField("Date", "date", db.Varchar, form.Datetime) 42 | 43 | formList.SetTable("posts").SetTitle("Posts").SetDescription("Posts") 44 | 45 | return 46 | } 47 | -------------------------------------------------------------------------------- /tests/tables/tables.go: -------------------------------------------------------------------------------- 1 | package tables 2 | 3 | import "github.com/GoAdminGroup/go-admin/plugins/admin/modules/table" 4 | 5 | var Generators = map[string]table.Generator{ 6 | "posts": GetPostsTable, 7 | "authors": GetAuthorsTable, 8 | "external": GetExternalTable, 9 | } 10 | -------------------------------------------------------------------------------- /tests/test_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/GoAdminGroup/go-admin/modules/config" 8 | "github.com/GoAdminGroup/go-admin/tests/frameworks/gin" 9 | ) 10 | 11 | func TestBlackBoxTestSuitOfBuiltInTables(t *testing.T) { 12 | BlackBoxTestSuitOfBuiltInTables(t, gin.NewHandler, config.DatabaseList{ 13 | "default": { 14 | Host: "127.0.0.1", 15 | Port: "3306", 16 | User: "root", 17 | Pwd: "root", 18 | Name: "go-admin-test", 19 | MaxIdleConns: 50, 20 | MaxOpenConns: 150, 21 | ConnMaxLifetime: time.Hour, 22 | ConnMaxIdleTime: 0, 23 | Driver: config.DriverMysql, 24 | }, 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /tests/web/README_CN.md: -------------------------------------------------------------------------------- 1 | # 测试功能清单 2 | 3 | 列举详尽的功能测试清单。 4 | 5 | ## 登录 6 | 7 | - [x] 输入正确的账号密码 8 | - [ ] 输入错误的账号密码 9 | - [ ] 带验证码的登录页面正常登录 10 | 11 | ## 导航栏与侧边栏 12 | 13 | - [x] 导航栏菜单的显示点击与关闭 14 | - [ ] 导航栏菜单过长情况的判断 15 | - [ ] 导航栏功能按钮的点击 16 | 17 | ## 表格页面 18 | 19 | ### 功能按钮 20 | 21 | - [x] 表格功能按钮,弹出按钮的点击显示关闭 22 | - [x] 表格功能按钮,Ajax按钮的点击显示关闭 23 | - [x] 表格功能按钮,下拉选择按钮的点击 24 | 25 | ### 行更新 26 | 27 | - [x] 表格项文本更新功能 28 | - [ ] 表格项选择更新功能 29 | 30 | ### 筛选框 31 | 32 | - [x] 筛选框显示 33 | - [x] 筛选框文本筛选功能 34 | - [ ] 筛选框选择筛选功能 35 | 36 | ### 导出功能 37 | 38 | - [x] 导出按钮,导出当前页 39 | - [ ] 导出按钮,导出全部 40 | - [ ] 导出按钮,导出选择的 41 | 42 | ### 列选择 43 | 44 | - [x] 列选择按钮显示选择点击 45 | 46 | ### 列排序 47 | 48 | - [x] 列排序按钮,正序 49 | - [x] 列排序按钮,倒序 50 | 51 | ### 列功能按钮 52 | 53 | - [x] 列功能按钮,弹出操作点击显示关闭 54 | - [x] 列功能按钮,Ajax操作点击显示关闭 55 | 56 | ### 按钮的隐藏 57 | 58 | - [ ] 筛选框的隐藏 59 | - [ ] 新建按钮的隐藏 60 | - [ ] 导出按钮的隐藏 61 | - [ ] 编辑按钮的隐藏 62 | - [ ] 删除按钮的隐藏 63 | - [ ] 详情按钮的隐藏 64 | - [ ] 筛选按钮的隐藏 65 | - [ ] 列选择按钮的隐藏 66 | - [ ] 分页条的隐藏 67 | - [ ] 查询信息的隐藏 68 | 69 | ### 列的显示 70 | 71 | - [ ] 标签的显示 FieldLabel 72 | - [ ] 图片的显示 FieldImage 73 | - [ ] bool值的显示 FieldBool 74 | - [ ] 链接的显示 FieldLink 75 | - [ ] 文件大小的显示 FieldFileSize 76 | - [ ] 日期的显示 FieldDate 77 | - [ ] icon的显示 FieldIcon 78 | - [ ] 点的显示 FieldDot 79 | - [ ] 进度条的显示 FieldProgressBar 80 | - [ ] loading的显示 FieldLoading 81 | - [ ] 下载链接的显示 FieldDownLoadable 82 | - [ ] 可复制文本的显示 FieldCopyable 83 | - [ ] 图片轮播的显示 FieldCarousel 84 | - [ ] 二维码的显示 FieldQrcode 85 | 86 | ## 表单页面 87 | 88 | ### 组件显示 89 | 90 | - [x] 单选的点击显示选择 91 | - [x] 多选的点击显示选择 92 | - [x] selectbox的点击显示选择 93 | - [x] 文本框的输入 94 | - [ ] 富文本的输入编辑保存 95 | - [ ] 单/多文件选择 96 | - [ ] 时间选择组件的选择 97 | - [ ] 时间选择范围组件的选择 98 | - [ ] Array组件的点击显示编辑 99 | - [ ] Table组件的点击显示编辑 100 | - [ ] IconPicker组件的选择 101 | - [ ] 滑动组件的点击 102 | - [ ] 代码组件的编辑 103 | - [ ] 数字组件的点击 104 | - [ ] 数字范围组件的点击 105 | - [ ] 自定义字段的编辑 106 | 107 | ### 按钮显示 108 | 109 | - [x] 保存错误框显示 110 | - [x] 重设按钮的点击 111 | - [x] 继续编辑的选择 112 | 113 | ### 联动 114 | 115 | - [ ] chooseMapJS 116 | - [ ] chooseJS 117 | - [ ] chooseAjax 118 | - [ ] chooseHideJS 119 | - [ ] chooseShowJS 120 | - [ ] chooseDisableJS 121 | 122 | ## 详情页 123 | 124 | ## 权限的增删改查 125 | 126 | ## 角色的增删改查 127 | 128 | ## 管理员的增删改查 129 | 130 | - [x] 新建管理员 131 | - [x] 新建管理员正常登录 132 | 133 | ## 菜单的增删改查 134 | 135 | - [x] 新建菜单 136 | - [x] 删除菜单 137 | - [ ] 改变菜单顺序 138 | - [ ] 三级菜单的新建与显示 -------------------------------------------------------------------------------- /tests/web/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "database": { 3 | "default": { 4 | "host": "db_mysql", 5 | "port": "3306", 6 | "user": "root", 7 | "pwd": "root", 8 | "name": "go-admin-test", 9 | "max_idle_con": 50, 10 | "max_open_con": 150, 11 | "driver": "mysql" 12 | } 13 | }, 14 | "domain": "localhost", 15 | "prefix": "admin", 16 | "store": { 17 | "path": "./uploads", 18 | "prefix": "uploads" 19 | }, 20 | "env": "local", 21 | "language": "en", 22 | "index": "/", 23 | "access_log_off": true, 24 | "debug": false, 25 | "color_scheme": "skin-black" 26 | } --------------------------------------------------------------------------------