github.com/kotovmak/go-admin@v1.1.1/plugins/admin/models/user.go (about)

     1  package models
     2  
     3  import (
     4  	"database/sql"
     5  	"net/url"
     6  	"reflect"
     7  	"regexp"
     8  	"strconv"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/kotovmak/go-admin/modules/config"
    13  	"github.com/kotovmak/go-admin/modules/db"
    14  	"github.com/kotovmak/go-admin/modules/db/dialect"
    15  	"github.com/kotovmak/go-admin/modules/logger"
    16  	"github.com/kotovmak/go-admin/modules/utils"
    17  	"github.com/kotovmak/go-admin/plugins/admin/modules/constant"
    18  )
    19  
    20  // UserModel is user model structure.
    21  type UserModel struct {
    22  	Base `json:"-"`
    23  
    24  	Id            int64             `json:"id"`
    25  	Name          string            `json:"name"`
    26  	UserName      string            `json:"user_name"`
    27  	Password      string            `json:"password"`
    28  	Avatar        string            `json:"avatar"`
    29  	RememberToken string            `json:"remember_token"`
    30  	Permissions   []PermissionModel `json:"permissions"`
    31  	MenuIds       []int64           `json:"menu_ids"`
    32  	Roles         []RoleModel       `json:"role"`
    33  	Level         string            `json:"level"`
    34  	LevelName     string            `json:"level_name"`
    35  
    36  	CreatedAt string `json:"created_at"`
    37  	UpdatedAt string `json:"updated_at"`
    38  
    39  	cacheReplacer *strings.Replacer
    40  }
    41  
    42  // User return a default user model.
    43  func User() UserModel {
    44  	return UserModel{Base: Base{TableName: config.GetAuthUserTable()}}
    45  }
    46  
    47  // UserWithId return a default user model of given id.
    48  func UserWithId(id string) UserModel {
    49  	idInt, _ := strconv.Atoi(id)
    50  	return UserModel{Base: Base{TableName: config.GetAuthUserTable()}, Id: int64(idInt)}
    51  }
    52  
    53  func (t UserModel) SetConn(con db.Connection) UserModel {
    54  	t.Conn = con
    55  	return t
    56  }
    57  
    58  func (t UserModel) WithTx(tx *sql.Tx) UserModel {
    59  	t.Tx = tx
    60  	return t
    61  }
    62  
    63  // Find return a default user model of given id.
    64  func (t UserModel) Find(id interface{}) UserModel {
    65  	item, _ := t.Table(t.TableName).Find(id)
    66  	return t.MapToModel(item)
    67  }
    68  
    69  // FindByUserName return a default user model of given name.
    70  func (t UserModel) FindByUserName(username interface{}) UserModel {
    71  	item, _ := t.Table(t.TableName).Where("username", "=", username).First()
    72  	return t.MapToModel(item)
    73  }
    74  
    75  // IsEmpty check the user model is empty or not.
    76  func (t UserModel) IsEmpty() bool {
    77  	return t.Id == int64(0)
    78  }
    79  
    80  // HasMenu check the user has visitable menu or not.
    81  func (t UserModel) HasMenu() bool {
    82  	return len(t.MenuIds) != 0 || t.IsSuperAdmin()
    83  }
    84  
    85  // IsSuperAdmin check the user model is super admin or not.
    86  func (t UserModel) IsSuperAdmin() bool {
    87  	for _, per := range t.Permissions {
    88  		if len(per.HttpPath) > 0 && per.HttpPath[0] == "*" && per.HttpMethod[0] == "" {
    89  			return true
    90  		}
    91  	}
    92  	return false
    93  }
    94  
    95  func (t UserModel) GetCheckPermissionByUrlMethod(path, method string) string {
    96  	if !t.CheckPermissionByUrlMethod(path, method, url.Values{}) {
    97  		return ""
    98  	}
    99  	return path
   100  }
   101  
   102  func (t UserModel) IsVisitor() bool {
   103  	return !t.CheckPermissionByUrlMethod(config.Url("/info/normal_manager"), "GET", url.Values{})
   104  }
   105  
   106  func (t UserModel) HideUserCenterEntrance() bool {
   107  	return t.IsVisitor() && config.GetHideVisitorUserCenterEntrance()
   108  }
   109  
   110  func (t UserModel) Template(str string) string {
   111  	if t.cacheReplacer == nil {
   112  		t.cacheReplacer = strings.NewReplacer("{{.AuthId}}", strconv.Itoa(int(t.Id)),
   113  			"{{.AuthName}}", t.Name, "{{.AuthUserName}}", t.UserName)
   114  	}
   115  	return t.cacheReplacer.Replace(str)
   116  }
   117  
   118  func (t UserModel) CheckPermissionByUrlMethod(path, method string, formParams url.Values) bool {
   119  
   120  	// path, _ = url.PathUnescape(path)
   121  	if !strings.Contains(path, config.Url("")) {
   122  		path = config.Url(path)
   123  	}
   124  
   125  	if t.IsSuperAdmin() {
   126  		return true
   127  	}
   128  
   129  	if path == "" {
   130  		path = "/"
   131  	}
   132  
   133  	logoutCheck, _ := regexp.Compile(config.Url("/logout") + "(.*?)")
   134  
   135  	if logoutCheck.MatchString(path) {
   136  		return true
   137  	}
   138  
   139  	if path != "/" && path[len(path)-1] == '/' {
   140  		path = path[:len(path)-1]
   141  	}
   142  
   143  	path = utils.ReplaceAll(path, constant.EditPKKey, "id", constant.DetailPKKey, "id")
   144  
   145  	path, params := getParam(path)
   146  	for key, value := range formParams {
   147  		if len(value) > 0 {
   148  			params.Add(key, value[0])
   149  		}
   150  	}
   151  
   152  	for _, v := range t.Permissions {
   153  
   154  		if v.HttpMethod[0] == "" || inMethodArr(v.HttpMethod, method) {
   155  
   156  			if v.HttpPath[0] == "*" {
   157  				return true
   158  			}
   159  
   160  			for i := 0; i < len(v.HttpPath); i++ {
   161  
   162  				matchPath := config.Url(t.Template(strings.TrimSpace(v.HttpPath[i])))
   163  				matchPath, matchParam := getParam(matchPath)
   164  
   165  				if matchPath == path {
   166  					if t.checkParam(params, matchParam) {
   167  						return true
   168  					}
   169  				}
   170  
   171  				reg, err := regexp.Compile(matchPath)
   172  
   173  				if err != nil {
   174  					logger.Error("CheckPermissions error: ", err)
   175  					continue
   176  				}
   177  
   178  				if reg.FindString(path) == path {
   179  					if t.checkParam(params, matchParam) {
   180  						return true
   181  					}
   182  				}
   183  			}
   184  		}
   185  	}
   186  
   187  	return false
   188  }
   189  
   190  func getParam(u string) (string, url.Values) {
   191  	m := make(url.Values)
   192  	urr := strings.Split(u, "?")
   193  	if len(urr) > 1 {
   194  		m, _ = url.ParseQuery(urr[1])
   195  	}
   196  	return urr[0], m
   197  }
   198  
   199  func (t UserModel) checkParam(src, comp url.Values) bool {
   200  	if len(comp) == 0 {
   201  		return true
   202  	}
   203  	if len(src) == 0 {
   204  		return false
   205  	}
   206  	for key, value := range comp {
   207  		v, find := src[key]
   208  		if !find {
   209  			return false
   210  		}
   211  		if len(value) == 0 {
   212  			continue
   213  		}
   214  		if len(v) == 0 {
   215  			return false
   216  		}
   217  		for i := 0; i < len(v); i++ {
   218  			if v[i] == t.Template(value[i]) {
   219  				continue
   220  			} else {
   221  				return false
   222  			}
   223  		}
   224  	}
   225  	return true
   226  }
   227  
   228  func inMethodArr(arr []string, str string) bool {
   229  	for i := 0; i < len(arr); i++ {
   230  		if strings.EqualFold(arr[i], str) {
   231  			return true
   232  		}
   233  	}
   234  	return false
   235  }
   236  
   237  // UpdateAvatar update the avatar of user.
   238  func (t UserModel) ReleaseConn() UserModel {
   239  	t.Conn = nil
   240  	return t
   241  }
   242  
   243  // UpdateAvatar update the avatar of user.
   244  func (t UserModel) UpdateAvatar(avatar string) {
   245  	t.Avatar = avatar
   246  }
   247  
   248  // WithRoles query the role info of the user.
   249  func (t UserModel) WithRoles() UserModel {
   250  	roleModel, _ := t.Table("goadmin_role_users").
   251  		LeftJoin("goadmin_roles", "goadmin_roles.id", "=", "goadmin_role_users.role_id").
   252  		Where("user_id", "=", t.Id).
   253  		Select("goadmin_roles.id", "goadmin_roles.name", "goadmin_roles.slug",
   254  			"goadmin_roles.created_at", "goadmin_roles.updated_at").
   255  		All()
   256  
   257  	for _, role := range roleModel {
   258  		t.Roles = append(t.Roles, Role().MapToModel(role))
   259  	}
   260  
   261  	if len(t.Roles) > 0 {
   262  		t.Level = t.Roles[0].Slug
   263  		t.LevelName = t.Roles[0].Name
   264  	}
   265  
   266  	return t
   267  }
   268  
   269  func (t UserModel) GetAllRoleId() []interface{} {
   270  
   271  	var ids = make([]interface{}, len(t.Roles))
   272  
   273  	for key, role := range t.Roles {
   274  		ids[key] = role.Id
   275  	}
   276  
   277  	return ids
   278  }
   279  
   280  // WithPermissions query the permission info of the user.
   281  func (t UserModel) WithPermissions() UserModel {
   282  
   283  	var permissions = make([]map[string]interface{}, 0)
   284  
   285  	roleIds := t.GetAllRoleId()
   286  
   287  	if len(roleIds) > 0 {
   288  		permissions, _ = t.Table("goadmin_role_permissions").
   289  			LeftJoin("goadmin_permissions", "goadmin_permissions.id", "=", "goadmin_role_permissions.permission_id").
   290  			WhereIn("role_id", roleIds).
   291  			Select("goadmin_permissions.http_method", "goadmin_permissions.http_path",
   292  				"goadmin_permissions.id", "goadmin_permissions.name", "goadmin_permissions.slug",
   293  				"goadmin_permissions.created_at", "goadmin_permissions.updated_at").
   294  			All()
   295  	}
   296  
   297  	userPermissions, _ := t.Table("goadmin_user_permissions").
   298  		LeftJoin("goadmin_permissions", "goadmin_permissions.id", "=", "goadmin_user_permissions.permission_id").
   299  		Where("user_id", "=", t.Id).
   300  		Select("goadmin_permissions.http_method", "goadmin_permissions.http_path",
   301  			"goadmin_permissions.id", "goadmin_permissions.name", "goadmin_permissions.slug",
   302  			"goadmin_permissions.created_at", "goadmin_permissions.updated_at").
   303  		All()
   304  
   305  	permissions = append(permissions, userPermissions...)
   306  
   307  	for i := 0; i < len(permissions); i++ {
   308  		exist := false
   309  		for j := 0; j < len(t.Permissions); j++ {
   310  			if t.Permissions[j].Id == permissions[i]["id"] {
   311  				exist = true
   312  				break
   313  			}
   314  		}
   315  		if exist {
   316  			continue
   317  		}
   318  		t.Permissions = append(t.Permissions, Permission().MapToModel(permissions[i]))
   319  	}
   320  
   321  	return t
   322  }
   323  
   324  // WithMenus query the menu info of the user.
   325  func (t UserModel) WithMenus() UserModel {
   326  
   327  	var menuIdsModel []map[string]interface{}
   328  
   329  	if t.IsSuperAdmin() {
   330  		menuIdsModel, _ = t.Table("goadmin_role_menu").
   331  			LeftJoin("goadmin_menu", "goadmin_menu.id", "=", "goadmin_role_menu.menu_id").
   332  			Select("menu_id", "parent_id").
   333  			All()
   334  	} else {
   335  		rolesId := t.GetAllRoleId()
   336  		if len(rolesId) > 0 {
   337  			menuIdsModel, _ = t.Table("goadmin_role_menu").
   338  				LeftJoin("goadmin_menu", "goadmin_menu.id", "=", "goadmin_role_menu.menu_id").
   339  				WhereIn("goadmin_role_menu.role_id", rolesId).
   340  				Select("menu_id", "parent_id").
   341  				All()
   342  		}
   343  	}
   344  
   345  	var menuIds []int64
   346  	var midInt int
   347  	var mid2Int int
   348  	var mInt int
   349  
   350  	for _, mid := range menuIdsModel {
   351  		if reflect.TypeOf(mid["parent_id"]).String() == "[]uint8" {
   352  			midInt, _ = strconv.Atoi(string(mid["parent_id"].([]uint8)))
   353  			mInt, _ = strconv.Atoi(string(mid["menu_id"].([]uint8)))
   354  		} else {
   355  			midInt = int(mid["parent_id"].(int64))
   356  			mInt = int(mid["menu_id"].(int64))
   357  		}
   358  		if midInt != 0 {
   359  			for _, mid2 := range menuIdsModel {
   360  				if reflect.TypeOf(mid2["menu_id"]).String() == "[]uint8" {
   361  					mid2Int, _ = strconv.Atoi(string(mid2["menu_id"].([]uint8)))
   362  				} else {
   363  					mid2Int = int(mid2["menu_id"].(int64))
   364  				}
   365  				if mid2Int == midInt {
   366  					menuIds = append(menuIds, int64(mInt))
   367  					break
   368  				}
   369  			}
   370  		} else {
   371  			menuIds = append(menuIds, int64(mInt))
   372  		}
   373  	}
   374  
   375  	t.MenuIds = menuIds
   376  	return t
   377  }
   378  
   379  // New create a user model.
   380  func (t UserModel) New(username, password, name, avatar string) (UserModel, error) {
   381  
   382  	id, err := t.WithTx(t.Tx).Table(t.TableName).Insert(dialect.H{
   383  		"username": username,
   384  		"password": password,
   385  		"name":     name,
   386  		"avatar":   avatar,
   387  	})
   388  
   389  	t.Id = id
   390  	t.UserName = username
   391  	t.Password = password
   392  	t.Avatar = avatar
   393  	t.Name = name
   394  
   395  	return t, err
   396  }
   397  
   398  // Update update the user model.
   399  func (t UserModel) Update(username, password, name, avatar string, isUpdateAvatar bool) (int64, error) {
   400  
   401  	fieldValues := dialect.H{
   402  		"username":   username,
   403  		"name":       name,
   404  		"updated_at": time.Now().Format("2006-01-02 15:04:05"),
   405  	}
   406  
   407  	if avatar == "" || isUpdateAvatar {
   408  		fieldValues["avatar"] = avatar
   409  	}
   410  
   411  	if password != "" {
   412  		fieldValues["password"] = password
   413  	}
   414  
   415  	return t.WithTx(t.Tx).Table(t.TableName).
   416  		Where("id", "=", t.Id).
   417  		Update(fieldValues)
   418  }
   419  
   420  // UpdatePwd update the password of the user model.
   421  func (t UserModel) UpdatePwd(password string) UserModel {
   422  
   423  	_, _ = t.Table(t.TableName).
   424  		Where("id", "=", t.Id).
   425  		Update(dialect.H{
   426  			"password": password,
   427  		})
   428  
   429  	t.Password = password
   430  	return t
   431  }
   432  
   433  // CheckRole check the role of the user model.
   434  func (t UserModel) CheckRoleId(roleId string) bool {
   435  	checkRole, _ := t.Table("goadmin_role_users").
   436  		Where("role_id", "=", roleId).
   437  		Where("user_id", "=", t.Id).
   438  		First()
   439  	return checkRole != nil
   440  }
   441  
   442  // DeleteRoles delete all the roles of the user model.
   443  func (t UserModel) DeleteRoles() error {
   444  	return t.Table("goadmin_role_users").
   445  		Where("user_id", "=", t.Id).
   446  		Delete()
   447  }
   448  
   449  // AddRole add a role of the user model.
   450  func (t UserModel) AddRole(roleId string) (int64, error) {
   451  	if roleId != "" {
   452  		if !t.CheckRoleId(roleId) {
   453  			return t.WithTx(t.Tx).Table("goadmin_role_users").
   454  				Insert(dialect.H{
   455  					"role_id": roleId,
   456  					"user_id": t.Id,
   457  				})
   458  		}
   459  	}
   460  	return 0, nil
   461  }
   462  
   463  // CheckRole check the role of the user.
   464  func (t UserModel) CheckRole(slug string) bool {
   465  	for _, role := range t.Roles {
   466  		if role.Slug == slug {
   467  			return true
   468  		}
   469  	}
   470  
   471  	return false
   472  }
   473  
   474  // CheckPermission check the permission of the user.
   475  func (t UserModel) CheckPermissionById(permissionId string) bool {
   476  	checkPermission, _ := t.Table("goadmin_user_permissions").
   477  		Where("permission_id", "=", permissionId).
   478  		Where("user_id", "=", t.Id).
   479  		First()
   480  	return checkPermission != nil
   481  }
   482  
   483  // CheckPermission check the permission of the user.
   484  func (t UserModel) CheckPermission(permission string) bool {
   485  	for _, per := range t.Permissions {
   486  		if per.Slug == permission {
   487  			return true
   488  		}
   489  	}
   490  
   491  	return false
   492  }
   493  
   494  // DeletePermissions delete all the permissions of the user model.
   495  func (t UserModel) DeletePermissions() error {
   496  	return t.WithTx(t.Tx).Table("goadmin_user_permissions").
   497  		Where("user_id", "=", t.Id).
   498  		Delete()
   499  }
   500  
   501  // AddPermission add a permission of the user model.
   502  func (t UserModel) AddPermission(permissionId string) (int64, error) {
   503  	if permissionId != "" {
   504  		if !t.CheckPermissionById(permissionId) {
   505  			return t.WithTx(t.Tx).Table("goadmin_user_permissions").
   506  				Insert(dialect.H{
   507  					"permission_id": permissionId,
   508  					"user_id":       t.Id,
   509  				})
   510  		}
   511  	}
   512  	return 0, nil
   513  }
   514  
   515  // MapToModel get the user model from given map.
   516  func (t UserModel) MapToModel(m map[string]interface{}) UserModel {
   517  	t.Id, _ = m["id"].(int64)
   518  	t.Name, _ = m["name"].(string)
   519  	t.UserName, _ = m["username"].(string)
   520  	t.Password, _ = m["password"].(string)
   521  	t.Avatar, _ = m["avatar"].(string)
   522  	t.RememberToken, _ = m["remember_token"].(string)
   523  	t.CreatedAt, _ = m["created_at"].(string)
   524  	t.UpdatedAt, _ = m["updated_at"].(string)
   525  	return t
   526  }