Giter Club home page Giter Club logo

suyuan32 / simple-admin-core Goto Github PK

View Code? Open in Web Editor NEW
1.5K 17.0 252.0 16.54 MB

Simple Admin是一个基于Go Zero开发面向小型到大型项目的分布式微服务后端管理系统脚手架,提供丰富的后台管理功能,支持k8s快速部署,助力快速开发高并发微服务集群,适合学习和商用。Simple Admin is a powerful microservice framework for large management system. It is based on go-zero and supports several advanced features. It can help you to develop a microservice back-end management system in a short time.

Home Page: http://doc.ryansu.tech/zh

License: MIT License

Go 98.56% Makefile 1.23% Shell 0.21%
go golang backend admin casbin go-zero rbac microservices rocketmq rpc-framework

simple-admin-core's Introduction

simple-admin-core's People

Contributors

aoeiuvbpmfdtnl avatar ch3nnn avatar ctra-wang avatar lordlezehaf avatar shaohongwu avatar suyuan32 avatar zhuangpeng avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

simple-admin-core's Issues

分页返回的Total有歧义

       var roles []*model.Role
	result := l.svcCtx.DB.Limit(int(in.PageSize)).Offset(int((in.Page - 1) * in.PageSize)).Find(&roles)
	if result.Error != nil {
		logx.Errorw(logmessage.DatabaseError, logx.Field("detail", result.Error.Error()))
		return nil, status.Error(codes.Internal, result.Error.Error())
	}
	resp := &core.RoleListResp{}
	resp.Total = uint64(result.RowsAffected)
	for _, v := range roles {
		resp.Data = append(resp.Data, &core.RoleInfo{
			Id:            uint64(v.ID),
			Name:          v.Name,
			Value:         v.Value,
			DefaultRouter: v.DefaultRouter,
			Status:        v.Status,
			Remark:        v.Remark,
			OrderNo:       v.OrderNo,
			CreateAt:      v.CreatedAt.UnixMilli(),
		})
	}
	return resp, nil

一般的total 应该是所有的数据条数,而不是分页的items的条数

关于validator的一些优化

一般的accept-language是这样的

accept-language: zh,en;q=0.9,en-US;q=0.8,zh-CN;q=0.7,zh-TW;q=0.6,la;q=0.5,ja;q=0.4,id;q=0.3,fr;q=0.2

下面的这段 在validate时, translate估计只能fallback到en了

https://github.com/suyuan32/simple-admin-tools/blob/f9473c481b9ae1c3f7e3a428314be3fce4760909/rest/httpx/requests.go#L48-L56

建议parse accept-language header时可以参考这里

https://github.com/nicksnyder/go-i18n/blob/639caa7eb5031c3fc275d5b3bf1f44fe3c3f2623/v2/i18n/localizer.go#L30-L51

还有就是在RegisterDefaultTranslation 失败的error类型不应是类似RegisterDefaultTranslationsError 吗?
为啥要抛出DatabaseError ?
还有作为 gozero 为何要引用回你的core-admin 的error代码?

	err := en_translations.RegisterDefaultTranslations(v.Validator, enTrans)
	if err != nil {
		logx.Errorw(logmessage.DatabaseError, logx.Field("Detail", err.Error()))
		return nil
	}
	err = zh_translations.RegisterDefaultTranslations(v.Validator, zhTrans)
	if err != nil {
		logx.Errorw(logmessage.DatabaseError, logx.Field("Detail", err.Error()))
		return nil
	}

swagger generated fail!

Describe the bug
I try with the latest version.

To Reproduce
Steps to reproduce the behavior:

  1. run "make gen-api"
  2. See error

Screenshots
image
image

pagination的count不支持modifier的情况

在模板中,count的实现方式如下:

count, err := {{ $r }}.Clone().Count(ctx)

一观Clone方法,并未对modifier属性进行复制(ent的问题吧?)

对模板文件进行修改如下即可正常使用

acClone := {{ $r }}.Clone()
acClone.modifiers = {{ $r }}.modifiers
count, err := acClone.Count(ctx)

此方式需要注意modifier的编写,若编写subQuery,必须在最外层套一个 select * from (subquery) AS { $tableName }

这是因为 Count(ctx) 默认的查询语法是

SELECT COUNT(`$tableName`.`id`)

最好是嵌套一层最外层,且将其AStableName

建议贴 | Suggestions

大家可以在该贴提各种建议,点赞高的建议优先处理哦, 注意 simple-admin-core 主要负责所有其他微服务的鉴权、认证等操作,类似于 SSO 单点登录,以及后台的一些基本配置功能,其他拓展功能建议新增 API 服务,类似于 simple-admin-file。

目前规划

怎么运行

能否把源代码运行写的详细一些,谢谢

整理字符串的常量

redis cache key

	var apis []model.Api
	check := l.svcCtx.DB.Find(&apis)
	if check.RowsAffected != 0 {
		err := l.svcCtx.Redis.Set("database_init_state", "1")
		if err != nil {
			logx.Errorw(logmessage.RedisError, logx.Field("detail", err.Error()))
			return nil, status.Error(codes.Internal, errorx.RedisError)
		}
		return &core.BaseResp{Msg: errorx.AlreadyInit}, nil
	}

	// set default state value
	l.svcCtx.Redis.Setex("database_error_msg", "", 300)
	l.svcCtx.Redis.Set("database_init_state", "0")

roleId

func (l *InitDatabaseLogic) insertRoleMenuAuthorityData() error {
	var menus []model.Menu
	result := l.svcCtx.DB.Find(&menus)
	if result.Error != nil {
		logx.Errorw(logmessage.DatabaseError, logx.Field("detail", result.Error.Error()))
		return status.Error(codes.Internal, result.Error.Error())
	}

	var insertString strings.Builder
	insertString.WriteString("insert into role_menus values ")
	for i := 0; i < len(menus); i++ {
		if i != len(menus)-1 {
			insertString.WriteString(fmt.Sprintf("(%d, %d),", menus[i].ID, 1))
		} else {
			insertString.WriteString(fmt.Sprintf("(%d, %d);", menus[i].ID, 1))
		}
	}

mysql初始化问题

您好,ent是自动生成table吗?有sql文件吗?
我启动rpc以后也没有生成新的表格。有具体初始化数据库的文档吗?

更新请求体限制过于严格

    // The profile request data | 个人信息请求参数
    // swagger:model ProfileReq
    ProfileReq {
        // user's nickname | 用户的昵称
        // Required: true
        // Max length: 10
        Nickname string `json:"nickname" validate:"alphanumunicode,max=10"`

        // The user's avatar path | 用户的头像路径
        // Required: true
        // Max length: 30
        Avatar string `json:"avatar"`

        // User's mobile phone number | 用户的手机号码
        // Required: true
        // Max length: 18
        Mobile string `json:"mobile" validate:"numeric,max=18"`

        // The user's email address | 用户的邮箱
        // Required: true
        // Max length: 100
        Email string `json:"email" validate:"email,max=100"`
    }

更新的的字段不是所有的required的,可能是parital 更新

启动找不到配置文件

1、latest版本
2、run err:
2023/02/02 10:28:22 error: config file etc/core.yaml, open etc/core.yaml: no such file or directory
3、源代码:
var configFile = flag.String("f", "etc/core.yaml", "the config file")
4、修改成:
var configFile = flag.String("f", "api/etc/core.yaml", "the config file")
可以成功启动

Split proto file

Describe the bug
Can't split core.proto to small file

To Reproduce
Steps to reproduce the behavior:

  1. Try to split core.proto to core_1.proto and core_2.proto then import core_2 into core_1
  2. run command : "make gen-rpc"
  3. throw error : "line xxx, request type must defined in core_1.proto"

Expected behavior
Split file proto like goctl

ent版本 postgresql 菜单管理报错

ent版本 postgresql 菜单管理报错!
错误大意:[must appear in the GROUP BY clause or be used in an aggregate function]
忘记保存了 ,可以看看!

mac M1 使用make docker构建时,一直提示does not match the specified platform: wanted linux/amd64, actual: linux/arm64/v8

Describe the bug
failed to get destination image "sha256:XXX": image with reference sha256:XXX was found but does not match the specified platform: wanted linux/amd64, actual: linux/arm64/v8

To Reproduce
Steps to reproduce the behavior:

  1. 修改dockerfile中FROM --platform=linux/amd64 XXX
  2. 修改makefile中docker build --no-cache --platform linux/amd64 XXX
  3. 执行make docker
  4. 报错如上

Expected behavior
不修改的话打包的镜像无法在服务器端使用,报错:standard_init_linux.go:228: exec user process caused: exec format error

Screenshots
image

源码中的/rpc/ent/pagination.go不会通过gen-ent生成吗

通过goctls创建的RPC 基本项目
在通过go generate生成了/ent下的的文件后
缺少类似pagination.go的还有not_empty_update.go

导致生成的逻辑代码中l.svcCtx.DB.Student.Query().Where(predicates...).Page(l.ctx, in.Page, in.PageSize)用不了
err := l.svcCtx.DB.Student.UpdateOneID(in.Id). SetNotEmptyName(in.Name). SetNotEmptyAge(int(in.Age)). Exec(l.ctx)
中SetNotEmptyName,SetNotEmptyAge方法也没有

swagger 注解的优化

    // swagger:route DELETE /user user deleteUser
    // Delete user information | 删除用户信息
    // Parameters:
    //  + name: body
    //    require: true
    //    in: body
    //    type: IDReq
    // Responses:
    //   200: SimpleMsg
    //   401: SimpleMsg
    //   500: SimpleMsg
    @handler deleteUser
    delete /user (IDReq) returns (SimpleMsg)

现在感觉api文件过于重复显得臃肿。
如果结合 gozero api 已有语法 @doc
可以删减一些重复的定义, 譬如 // swagger:route DELETE /user user deleteUser
在api文件parse的过程中,应该可以推出类似的swagger 路由信息

登录时候显示用户无权限访问此接口

大佬,最新的代码,点击登录后,弹出用户无权限访问此接口,错误是/sys-api/user/info这个接口返回的。
是不是ent schema哪里没有导入数据了?我看casbin admin有权限访问这个接口啊。我是整个项目重新拉了跑了下,应该没有操作问题

执行goctls rpc new example生成文件依赖爆红

根目录执行goctls rpc new example --ent=true --port=9015 --desc=true
拉的最新的simple-admin-core和simple-admin-tool
1.生成的/example/internal/config/config.go中
`import (
"github.com/suyuan32/simple-admin-core/pkg/config"

"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/zrpc"

)`
github.com/suyuan32/simple-admin-core/pkg/config爆红
rpc下的相同位置引用的是github.com/suyuan32/simple-admin-common/config

3.文档中说goctls指令的go_zero_version和tool_version参数都是必须的,但是不添加也能执行

关于postgresql的一点点建议

我看到您将pgsql的链接方式写法改了一下
` //return fmt.Sprintf("postgresql://%s:%s@%s/%s?sslmode=%s", c.Username, c.Password, c.Host, c.DBName, c.SSLMode)

return fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s", c.Host, c.Username, c.Password,
	c.DBName, c.Port, c.SSLMode)`

按照您更改的这种方式,那么在config文件中定义的port字段(如果端口不是5432的话就需要更改host值)就失去了意义!
建议还是维持更新前的写法!

纯属个人建议!

项目安排 | RoadMap

项目安排

  • 登录注册
  • 菜单管理
  • 角色管理
  • 角色权限
  • 用户管理
  • 操作日志
  • 服务注册发现
  • 字典功能
  • 三方登录管理
  • 全面支持 K8s
  • 服务监控
  • 日志收集
  • JWT黑名单
  • 定时任务
  • 消息队列
  • Ent
  • 后端 CRUD 代码生成
  • 前端 CRUD 代码生成
  • 一键运行 demo 脚本
  • RPC logic 分组
  • Proto 文件拆分
  • 优化第三方登陆
  • 多角色多职位
  • casbin跨api同步
  • 在线定时任务模块 simple admin job
  • API 单体服务代码生成

Road Map

  • Login and Register
  • Menu Management
  • Role Management
  • Role Authority
  • User Management
  • Operation log
  • Service discovery
  • Dictionary management
  • Oauth management
  • Fully support K8s
  • Service Monitor
  • Log collecting
  • JWT blacklist
  • Job Schedule
  • Message queue
  • Ent
  • Backend CRUD generation
  • Frontend CRUD code generation
  • docker-compose script
  • RPC logic group
  • Proto files divide
  • Enhance oauth
  • Multiple roles and positions
  • Casbin policy synchonize by redis
  • Online job schedule - simple admin job
  • API Single Service Code generation

DictionaryDetail 表结构

// DictionaryDetail table struct
// 字典键值表结构
type DictionaryDetail struct {
	gorm.Model
	Title        string `json:"title,omitempty" yaml:"title" gorm:"comment:the title shown in the UI"` // the title shown in the UI | 展示名
	Key          string `json:"key,omitempty" yaml:"key" gorm:"comment:key"`                           // key | 键
	Value        string `json:"value,omitempty" yaml:"value" gorm:"comment:value"`                     // value | 值
	Status       bool   `json:"status,omitempty" yaml:"status" gorm:"comment:status"`                  // status | 状态
	DictionaryID uint
}

DictionaryID 是不是漏了gorm的相关注解

/user/update 修改 status 字段成功 实际数据库未修改

func (l *UpdateUserLogic) UpdateUser(in *core.UserInfo) (*core.BaseResp, error) {
	err := entx.WithTx(l.ctx, l.svcCtx.DB, func(tx *ent.Tx) error {
		updateQuery := tx.User.UpdateOneID(uuidx.ParseUUIDString(in.Id)).
			SetNotEmptyUsername(in.Username).
			SetNotEmptyNickname(in.Nickname).
			SetNotEmptyEmail(in.Email).
			SetNotEmptyMobile(in.Mobile).
			SetNotEmptyAvatar(in.Avatar).
			SetNotEmptyHomePath(in.HomePath).
			SetNotEmptyDescription(in.Description).
			SetNotEmptyDepartmentID(in.DepartmentId)

		if in.Password != "" {
			updateQuery = updateQuery.SetNotEmptyPassword(encrypt.BcryptEncrypt(in.Password))
		}

		if in.RoleIds != nil {
			err := l.svcCtx.DB.User.UpdateOneID(uuidx.ParseUUIDString(in.Id)).ClearRoles().Exec(l.ctx)
			if err != nil {
				return err
			}

			updateQuery = updateQuery.AddRoleIDs(in.RoleIds...)
		}

		if in.PositionIds != nil {
			err := l.svcCtx.DB.User.UpdateOneID(uuidx.ParseUUIDString(in.Id)).ClearPositions().Exec(l.ctx)
			if err != nil {
				return err
			}

			_, err = token.NewBlockUserAllTokenLogic(l.ctx, l.svcCtx).BlockUserAllToken(&core.UUIDReq{Id: in.Id})
			if err != nil {
				return err
			}

			updateQuery = updateQuery.AddPositionIDs(in.PositionIds...)
		}

		return updateQuery.Exec(l.ctx)
	})
	if err != nil {
		return nil, errorhandler.DefaultEntError(l.Logger, err, in)
	}

	return &core.BaseResp{
		Msg: i18n.Success,
	}, nil
}

缺少对status的修改操作

error的国际化问题

package errorx

const (
	// DatabaseError
	// normal database error
	DatabaseError string = "database error occur"

	// RedisError
	// normal redis error
	RedisError string = "redis error occur"

	// request error

	// ApiRequestFailed
	// EN: The interface request failed, please try again later!
	// ZH_CN: 请求出错,请稍候重试
	ApiRequestFailed string = "sys.api.apiRequestFailed"

这部分的message有translate 的支持吗?

desc的merge功能能否添加map支持?

一些接口需使用动态参数,proto可支持map,但使用merge后,map丢失,且生成的文件也有一些问题。

示例:

message SMSCodeReq {
  string phone_number = 1;
  string type = 2;
  string provider_name = 3;
  map<string, string> parameters = 4;
}

看了一下源码,使用了 parser#Parse 方法去逐个parse .proto 文件,然后使用 stringBuilder 构造最终merge后的文件。

在处理 message 时,使用了protox.MessageVisitorprotox.ProtoField.Type 似乎并不能正确取到 map 的类型,这里没有仔细研究应该怎么处理。。。

适合新手的PR | PR for new contributors

下面列出一些还需要完善的简单功能,适合新手参与项目:

  • 优化 logx 日志格式 | Optimize log data
  • 优化项目文档 | Optimize project documents
  • 增加第三方登陆(在初始化代码里提供,token地址等) | Add other 3rd-party providers for loging in
  • 优化翻译 | Optimize i18n translation
  • #75
  • #74
  • #73

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.