Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
github.com/snowlyg/iris-admin
简体中文 | English
简单项目仅供学习,欢迎指点!
master
版本 go get github.com/snowlyg/iris-admin@master
func getViperConfig() viper_server.ViperConfig
方法package cache
import (
"fmt"
"github.com/fsnotify/fsnotify"
"github.com/snowlyg/iris-admin/g"
"github.com/snowlyg/iris-admin/server/viper_server"
"github.com/spf13/viper"
)
var CONFIG Redis
type Redis struct {
DB int `mapstructure:"db" json:"db" yaml:"db"`
Addr string `mapstructure:"addr" json:"addr" yaml:"addr"`
Password string `mapstructure:"password" json:"password" yaml:"password"`
PoolSize int `mapstructure:"pool-size" json:"poolSize" yaml:"pool-size"`
}
// getViperConfig get viper config
func getViperConfig() 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 {
if err := vi.Unmarshal(&CONFIG); err != nil {
return fmt.Errorf("get Unarshal error: %v", err)
}
// watch config file change
vi.SetConfigName(configName)
return nil
},
//
Default: []byte(`
db: ` + db + `
addr: "` + CONFIG.Addr + `"
password: "` + CONFIG.Password + `"
pool-size: ` + poolSize),
}
}
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.Instance()
操作数据 database.Instance().Model(&User{}).Where("name = ?","name").Find(&user)
...
casbin.Instance()
使用中间件,实现接口权限认证 _, err := casbin.Instance().AddRoleForUser("1", "999")
uids, err := casbin.Instance().GetRolesForUser("1")
_, err := casbin.Instance().RemoveFilteredPolicy(v, p...)
...
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]
cron_server.CronInstance()
操作数据 cron_server.CronInstance().AddJob("@every 1m",YourJob)
// 或者
cron_server.CronInstance().AddFunc("@every 1m",YourFunc)
...
type WebFunc interface {}
接口type WebBaseFunc interface {
AddWebStatic(staticAbsPath, webPrefix string, paths ...string)
AddUploadStatic(staticAbsPath, webPrefix string)
InitRouter() error
Run()
}
// WebFunc 框架插件接口
// - GetTestClient 测试客户端
// - GetTestLogin 测试登录
// - AddWebStatic 添加静态页面
// - AddUploadStatic 上传文件路径
// - Run 启动
type WebFunc interface {
WebBaseFunc
}
AutoMigrate()
自动迁移初始化数据表package main
import (
"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"
)
func main() {
database.Instance().AutoMigrate(&perm.Permission{},&role.Role{},&user.User{},&operation.Oplog{})
}
gormigrate
第三方依赖包实现数据的迁移控制,方便后续的升级和开发package main
import (
"github.com/snowlyg/iris-admin/server/web"
"github.com/snowlyg/iris-admin/server/web/web_iris"
)
func main() {
wi := web_iris.Init()
web.Start(wi)
}
config
目录下.rbac_model.conf
文件到项目根目录,该文件用于 casbin 权鉴的规则.go run main.go
package main
import (
rbac "github.com/snowlyg/iris-admin-rbac/iris"
"github.com/snowlyg/iris-admin/server/web"
"github.com/snowlyg/iris-admin/server/web/web_iris"
)
func main() {
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: debug
static-prefix: /upload
time-format: "2006-01-02 15:04:05"
web-prefix: /admin
web-path: ./dist
编译前端页面默认 dist
目录
可以修改配置项 web-path
修改默认目录
package main
import (
"github.com/kataras/iris/v12"
"github.com/snowlyg/iris-admin/server/web"
)
func main() {
webServer := web_iris.Init()
wi.AddUploadStatic("/upload", "/var/static")
wi.AddWebStatic("/", "/var/static")
webServer.Run()
}
mysqlPwd
, mysqlAddr
系统环境变量,运行测试实例的时候将会使用到它们。接口单元测试需要新建 main_test.go
文件,该文件定义了单元测试的一些通用基础步骤:
建议采用docker部署mysql,否则测试错误失败后会有大量测试数据遗留
PartyFunc
, SeedFunc
方法需要根据对应的测试模块自定义
内容如下所示:main_test.go
package test
import (
"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"
)
var TestServer *web_gin.WebServer
var TestClient *httptest.Client
func TestMain(m *testing.M) {
var uuid string
uuid, TestServer = common.BeforeTestMainGin(rbac.PartyFunc, rbac.SeedFunc)
code := m.Run()
common.AfterTestMain(uuid, true)
os.Exit(code)
}
index_test.go
package test
import (
"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"
)
func TestList(t *testing.T) {
TestClient = httptest.Instance(t, str.Join("http://", web.CONFIG.System.Addr), TestServer.GetEngine())
TestClient.Login(rbac.LoginUrl, nil)
if TestClient == 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)
}
func TestCreate(t *testing.T) {
TestClient = httptest.Instance(t, str.Join("http://", web.CONFIG.System.Addr), TestServer.GetEngine())
TestClient.Login(rbac.LoginUrl, nil)
if TestClient == 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)
if id == 0 {
t.Fatalf("测试添加用户失败 id=%d", id)
}
defer Delete(TestClient, id)
}
func TestUpdate(t *testing.T) {
TestClient = httptest.Instance(t, str.Join("http://", web.CONFIG.System.Addr), TestServer.GetEngine())
TestClient.Login(rbac.LoginUrl, nil)
if TestClient == 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)
if id == 0 {
t.Fatalf("测试添加用户失败 id=%d", id)
}
defer Delete(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)
}
func TestGetById(t *testing.T) {
TestClient = httptest.Instance(t, str.Join("http://", web.CONFIG.System.Addr), TestServer.GetEngine())
TestClient.Login(rbac.LoginUrl, nil)
if TestClient == 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)
if id == 0 {
t.Fatalf("测试添加用户失败 id=%d", id)
}
defer Delete(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)
}
func TestChangeAvatar(t *testing.T) {
TestClient = httptest.Instance(t, str.Join("http://", web.CONFIG.System.Addr), TestServer.GetEngine())
TestClient.Login(rbac.LoginUrl, nil)
if TestClient == 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)
}
func Create(TestClient *httptest.Client, data map[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"},
},
},
}
return TestClient.POST(fmt.Sprintf("%s/createAdmin", url), pageKeys, data).GetId()
}
func Delete(TestClient *httptest.Client, id uint) {
pageKeys := httptest.Responses{
{Key: "status", Value: http.StatusOK},
{Key: "message", Value: response.ResponseOkMessage},
}
TestClient.DELETE(fmt.Sprintf("%s/deleteAdmin/%d", url, id), pageKeys)
}
JetBrains 对本项目的支持。
您的打赏将用于支付网站运行,会在项目介绍中特别鸣谢您
FAQs
Unknown package
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.