- Notifications
You must be signed in to change notification settings - Fork167
Web admin for go framework [gin/iris]
License
NotificationsYou must be signed in to change notification settings
snowlyg/iris-admin
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
简体中文 |English
简单项目仅供学习,欢迎指点!
- 获取依赖包,注意必须带上
master
版本
go get github.com/snowlyg/iris-admin@master
- [viper_server]
- 插件配置初始化,并生成本地配置文件
- 使用github.com/spf13/viper 第三方包实现
- 需要实现
func getViperConfig() viper_server.ViperConfig
方法
package cacheimport ("fmt""github.com/fsnotify/fsnotify""github.com/snowlyg/iris-admin/g""github.com/snowlyg/iris-admin/server/viper_server""github.com/spf13/viper")varCONFIGRedistypeRedisstruct {DBint`mapstructure:"db" json:"db" yaml:"db"`Addrstring`mapstructure:"addr" json:"addr" yaml:"addr"`Passwordstring`mapstructure:"password" json:"password" yaml:"password"`PoolSizeint`mapstructure:"pool-size" json:"poolSize" yaml:"pool-size"`}// getViperConfig get viper configfuncgetViperConfig() viper_server.ViperConfig {configName:="redis"db:=fmt.Sprintf("%d",CONFIG.DB)poolSize:=fmt.Sprintf("%d",CONFIG.PoolSize)return viper_server.ViperConfig{Directory:g.ConfigDir,Name:configName,Type:g.ConfigType,Watch:func(vi*viper.Viper)error {iferr:=vi.Unmarshal(&CONFIG);err!=nil {returnfmt.Errorf("get Unarshal error: %v",err) }// watch config file changevi.SetConfigName(configName)returnnil },//Default: []byte(`db: `+db+`addr: "`+CONFIG.Addr+`"password: "`+CONFIG.Password+`"pool-size: `+poolSize), }}
- [zap_server]
- 插件日志记录
- 使用go.uber.org/zap 第三方包实现
- 通过全局变量
zap_server.ZAPLOG
记录对应级别的日志
zap_server.ZAPLOG.Info("注册数据表错误",zap.Any("err",err))zap_server.ZAPLOG.Debug("注册数据表错误",zap.Any("err",err))zap_server.ZAPLOG.Error("注册数据表错误",zap.Any("err",err))...
- [database]
- 数据插件 [目前仅支持 mysql]
- 使用gorm.io/gorm 第三方包实现
- 通过单列
database.Instance()
操作数据
database.Instance().Model(&User{}).Where("name = ?","name").Find(&user)...
- [casbin]
- 权限控制管理插件
- 使用casbin 第三方包实现
- 并通过
casbin.Instance()
使用中间件,实现接口权限认证
_,err:=casbin.Instance().AddRoleForUser("1","999")uids,err:=casbin.Instance().GetRolesForUser("1")_,err:=casbin.Instance().RemoveFilteredPolicy(v,p...)...
- [cache]
- 缓存驱动插件
- 使用github.com/go-redis/redis 第三方包实现
- 通过单列
cache.Instance()
操作数据
err:=cache.Instance().Set(context.Background(),"key","value",expiration).Err()cache.Instance().Del(context.Background(),"key").Result()cache.Instance().Get(context.Background(),"key")...
[operation]
- 系统操作日志插件
- 并通过
index.Use(operation.OperationRecord())
使用中间件,实现接口自动生成操作日志
[cron_server]
- 任务插件
- 使用robfig/cron 第三方包实现
- 通过单列
cron_server.CronInstance()
操作数据
cron_server.CronInstance().AddJob("@every 1m",YourJob)// 或者cron_server.CronInstance().AddFunc("@every 1m",YourFunc)...
- [web]
- web_irisGo-Iris web 框架插件
- web_ginGo-gin web web 框架插件
- web 框架插件需要实现
type WebFunc interface {}
接口
typeWebBaseFuncinterface {AddWebStatic(staticAbsPath,webPrefixstring,paths...string)AddUploadStatic(staticAbsPath,webPrefixstring)InitRouter()errorRun()}// WebFunc 框架插件接口// - GetTestClient 测试客户端// - GetTestLogin 测试登录// - AddWebStatic 添加静态页面// - AddUploadStatic 上传文件路径// - Run 启动typeWebFuncinterface {WebBaseFunc}
- [mongodb]
- mongodb
- 使用mongodb 第三方包实现.
- 使用原生方法
AutoMigrate()
自动迁移初始化数据表
package mainimport ("github.com/snowlyg/iris-admin/server/web""github.com/snowlyg/iris-admin/server/web/web_iris""github.com/snowlyg/iris-admin-rbac/iris/perm""github.com/snowlyg/iris-admin-rbac/iris/role""github.com/snowlyg/iris-admin/server/database""github.com/snowlyg/iris-admin/server/operation")funcmain() {database.Instance().AutoMigrate(&perm.Permission{},&role.Role{},&user.User{},&operation.Oplog{})}
- 使用
gormigrate
第三方依赖包实现数据的迁移控制,方便后续的升级和开发 - 使用方法详情见iris-admin-cmd
- 添加 main.go 文件
package mainimport ("github.com/snowlyg/iris-admin/server/web""github.com/snowlyg/iris-admin/server/web/web_iris")funcmain() {wi:=web_iris.Init()web.Start(wi)}
- 第一次启动项目后,配置文件会自动生成到
config
目录下. - 同时会生成一个
rbac_model.conf
文件到项目根目录,该文件用于 casbin 权鉴的规则.
go run main.go
- 如果需要权鉴管理,可以使用iris-admin-rbac 项目快速集成权鉴功能
- 可以使用 AddModule() 增加其他 admin 模块
package mainimport ( rbac"github.com/snowlyg/iris-admin-rbac/iris""github.com/snowlyg/iris-admin/server/web""github.com/snowlyg/iris-admin/server/web/web_iris")funcmain() {wi:=web_iris.Init()rbacParty:= web_iris.Party{Perfix:"/api/v1",PartyFunc:rbac.Party(), }wi.AddModule(rbacParty)web.Start(web_iris.Init())}
已经默认内置了一个静态文件访问路径
静态文件将会上传到
/static/upload
目录可以修改配置项
static-path
修改默认目录
system:addr:"127.0.0.1:8085"db-type:""level:debugstatic-prefix:/uploadtime-format:"2006-01-02 15:04:05"web-prefix:/adminweb-path:./dist
编译前端页面默认
dist
目录可以修改配置项
web-path
修改默认目录
package mainimport ("github.com/kataras/iris/v12""github.com/snowlyg/iris-admin/server/web")funcmain() {webServer:=web_iris.Init()wi.AddUploadStatic("/upload","/var/static")wi.AddWebStatic("/","/var/static")webServer.Run()}
- 前端页面参考/借用:【前端只简单实现预览效果】
- gin-vue-admin
- vue-element-admin
- 测试前,需要设置
mysqlPwd
,mysqlAddr
系统环境变量,运行测试实例的时候将会使用到它们。 - 测试使用依赖库helper/tests 是基于httpexpect/v2 的简单封装
- 接口单元测试例子
- 接口单元测试例子
接口单元测试需要新建main_test.go
文件,该文件定义了单元测试的一些通用基础步骤:建议采用 docker 部署 mysql,否则测试错误失败后会有大量测试数据遗留
- 1.测试数据库的数据库的创建和摧毁
- 2.数据表的新建和表数据的填充
PartyFunc
,SeedFunc
方法需要根据对应的测试模块自定义内容如下所示:
main_test.go
package testimport ("os""testing""github.com/snowlyg/httptest" rbac"github.com/snowlyg/iris-admin-rbac/gin""github.com/snowlyg/iris-admin/server/web/common""github.com/snowlyg/iris-admin/server/web/web_gin")varTestServer*web_gin.WebServervarTestClient*httptest.ClientfuncTestMain(m*testing.M) {varuuidstringuuid,TestServer=common.BeforeTestMainGin(rbac.PartyFunc,rbac.SeedFunc)code:=m.Run()common.AfterTestMain(uuid,true)os.Exit(code)}
index_test.go
package testimport ("fmt""net/http""path/filepath""testing""github.com/snowlyg/helper/str""github.com/snowlyg/httptest" rbac"github.com/snowlyg/iris-admin-rbac/gin""github.com/snowlyg/iris-admin/g""github.com/snowlyg/iris-admin/server/web""github.com/snowlyg/iris-admin/server/web/web_gin/response")var (url="/api/v1/admin")funcTestList(t*testing.T) {TestClient=httptest.Instance(t,str.Join("http://",web.CONFIG.System.Addr),TestServer.GetEngine())TestClient.Login(rbac.LoginUrl,nil)ifTestClient==nil {return }pageKeys:= httptest.Responses{ {Key:"status",Value:http.StatusOK}, {Key:"message",Value:response.ResponseOkMessage}, {Key:"data",Value: httptest.Responses{ {Key:"pageSize",Value:10}, {Key:"page",Value:1}, {Key:"list",Value: []httptest.Responses{ { {Key:"id",Value:1,Type:"ge"}, {Key:"nickName",Value:"超级管理员"}, {Key:"username",Value:"admin"}, {Key:"headerImg",Value:"http://xxxx/head.png"}, {Key:"status",Value:g.StatusTrue}, {Key:"isShow",Value:g.StatusFalse}, {Key:"phone",Value:"13800138000"}, {Key:"email",Value:"admin@admin.com"}, {Key:"authorities",Value: []string{"超级管理员"}}, {Key:"updatedAt",Value:"",Type:"notempty"}, {Key:"createdAt",Value:"",Type:"notempty"}, }, }}, {Key:"total",Value:0,Type:"ge"}, }}, }TestClient.GET(fmt.Sprintf("%s/getAll",url),pageKeys,httptest.RequestParams)}funcTestCreate(t*testing.T) {TestClient=httptest.Instance(t,str.Join("http://",web.CONFIG.System.Addr),TestServer.GetEngine())TestClient.Login(rbac.LoginUrl,nil)ifTestClient==nil {return }data:=map[string]interface{}{"nickName":"测试名称","username":"create_test_username","authorityIds": []uint{web.AdminAuthorityId},"email":"get@admin.com","phone":"13800138001","password":"123456", }id:=Create(TestClient,data)ifid==0 {t.Fatalf("测试添加用户失败 id=%d",id) }deferDelete(TestClient,id)}funcTestUpdate(t*testing.T) {TestClient=httptest.Instance(t,str.Join("http://",web.CONFIG.System.Addr),TestServer.GetEngine())TestClient.Login(rbac.LoginUrl,nil)ifTestClient==nil {return }data:=map[string]interface{}{"nickName":"测试名称","username":"create_test_username_for_update","authorityIds": []uint{web.AdminAuthorityId},"email":"get@admin.com","phone":"13800138001","password":"123456", }id:=Create(TestClient,data)ifid==0 {t.Fatalf("测试添加用户失败 id=%d",id) }deferDelete(TestClient,id)update:=map[string]interface{}{"nickName":"测试名称","email":"get@admin.com","phone":"13800138003","password":"123456", }pageKeys:= httptest.Responses{ {Key:"status",Value:http.StatusOK}, {Key:"message",Value:response.ResponseOkMessage}, }TestClient.PUT(fmt.Sprintf("%s/updateAdmin/%d",url,id),pageKeys,update)}funcTestGetById(t*testing.T) {TestClient=httptest.Instance(t,str.Join("http://",web.CONFIG.System.Addr),TestServer.GetEngine())TestClient.Login(rbac.LoginUrl,nil)ifTestClient==nil {return }data:=map[string]interface{}{"nickName":"测试名称","username":"create_test_username_for_get","email":"get@admin.com","phone":"13800138001","authorityIds": []uint{web.AdminAuthorityId},"password":"123456", }id:=Create(TestClient,data)ifid==0 {t.Fatalf("测试添加用户失败 id=%d",id) }deferDelete(TestClient,id)pageKeys:= httptest.Responses{ {Key:"status",Value:http.StatusOK}, {Key:"message",Value:response.ResponseOkMessage}, {Key:"data",Value: httptest.Responses{ {Key:"id",Value:1,Type:"ge"}, {Key:"nickName",Value:data["nickName"].(string)}, {Key:"username",Value:data["username"].(string)}, {Key:"status",Value:g.StatusTrue}, {Key:"email",Value:data["email"].(string)}, {Key:"phone",Value:data["phone"].(string)}, {Key:"isShow",Value:g.StatusTrue}, {Key:"headerImg",Value:"http://xxxx/head.png"}, {Key:"updatedAt",Value:"",Type:"notempty"}, {Key:"createdAt",Value:"",Type:"notempty"}, {Key:"createdAt",Value:"",Type:"notempty"}, {Key:"authorities",Value: []string{"超级管理员"}}, }, }, }TestClient.GET(fmt.Sprintf("%s/getAdmin/%d",url,id),pageKeys)}funcTestChangeAvatar(t*testing.T) {TestClient=httptest.Instance(t,str.Join("http://",web.CONFIG.System.Addr),TestServer.GetEngine())TestClient.Login(rbac.LoginUrl,nil)ifTestClient==nil {return }data:=map[string]interface{}{"headerImg":"/avatar.png", }pageKeys:= httptest.Responses{ {Key:"status",Value:http.StatusOK}, {Key:"message",Value:response.ResponseOkMessage}, }TestClient.POST(fmt.Sprintf("%s/changeAvatar",url),pageKeys,data)profile:= httptest.Responses{ {Key:"status",Value:http.StatusOK}, {Key:"message",Value:response.ResponseOkMessage}, {Key:"data",Value: httptest.Responses{ {Key:"id",Value:1,Type:"ge"}, {Key:"nickName",Value:"超级管理员"}, {Key:"username",Value:"admin"}, {Key:"headerImg",Value:filepath.ToSlash(web.ToStaticUrl("/avatar.png"))}, {Key:"status",Value:g.StatusTrue}, {Key:"isShow",Value:g.StatusFalse}, {Key:"phone",Value:"13800138000"}, {Key:"email",Value:"admin@admin.com"}, {Key:"authorities",Value: []string{"超级管理员"}}, {Key:"updatedAt",Value:"",Type:"notempty"}, {Key:"createdAt",Value:"",Type:"notempty"}, }, }, }TestClient.GET(fmt.Sprintf("%s/profile",url),profile)}funcCreate(TestClient*httptest.Client,datamap[string]interface{})uint {pageKeys:= httptest.Responses{ {Key:"status",Value:http.StatusOK}, {Key:"message",Value:response.ResponseOkMessage}, {Key:"data",Value: httptest.Responses{ {Key:"id",Value:1,Type:"ge"}, }, }, }returnTestClient.POST(fmt.Sprintf("%s/createAdmin",url),pageKeys,data).GetId()}funcDelete(TestClient*httptest.Client,iduint) {pageKeys:= httptest.Responses{ {Key:"status",Value:http.StatusOK}, {Key:"message",Value:response.ResponseOkMessage}, }TestClient.DELETE(fmt.Sprintf("%s/deleteAdmin/%d",url,id),pageKeys)}
JetBrains 对本项目的支持。
您的打赏将用于支付网站运行,会在项目介绍中特别鸣谢您
About
Web admin for go framework [gin/iris]
Topics
Resources
License
Stars
Watchers
Forks
Packages0
No packages published