github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/db/role.go (about)

     1  // This file is part of the Smart Home
     2  // Program complex distribution https://github.com/e154/smart-home
     3  // Copyright (C) 2016-2023, Filippov Alex
     4  //
     5  // This library is free software: you can redistribute it and/or
     6  // modify it under the terms of the GNU Lesser General Public
     7  // License as published by the Free Software Foundation; either
     8  // version 3 of the License, or (at your option) any later version.
     9  //
    10  // This library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13  // Library General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public
    16  // License along with this library.  If not, see
    17  // <https://www.gnu.org/licenses/>.
    18  
    19  package db
    20  
    21  import (
    22  	"context"
    23  	"database/sql"
    24  	"fmt"
    25  	"time"
    26  
    27  	"github.com/e154/smart-home/common/apperr"
    28  
    29  	"github.com/pkg/errors"
    30  	"gorm.io/gorm"
    31  )
    32  
    33  // Roles ...
    34  type Roles struct {
    35  	Db *gorm.DB
    36  }
    37  
    38  // Role ...
    39  type Role struct {
    40  	Name        string `gorm:"primary_key"`
    41  	Description string
    42  	Role        *Role
    43  	RoleName    sql.NullString `gorm:"column:parent"`
    44  	Children    []*Role
    45  	Permissions []*Permission
    46  	CreatedAt   time.Time `gorm:"<-:create"`
    47  	UpdatedAt   time.Time
    48  }
    49  
    50  // TableName ...
    51  func (m *Role) TableName() string {
    52  	return "roles"
    53  }
    54  
    55  // Add ...
    56  func (n Roles) Add(ctx context.Context, role *Role) (err error) {
    57  	if err = n.Db.WithContext(ctx).Create(&role).Error; err != nil {
    58  		err = errors.Wrap(apperr.ErrRoleAdd, err.Error())
    59  		return
    60  	}
    61  	return
    62  }
    63  
    64  // GetByName ...
    65  func (n Roles) GetByName(ctx context.Context, name string) (role *Role, err error) {
    66  
    67  	role = &Role{Name: name}
    68  	err = n.Db.WithContext(ctx).First(&role).Error
    69  	if err != nil {
    70  		if errors.Is(err, gorm.ErrRecordNotFound) {
    71  			err = errors.Wrap(apperr.ErrRoleNotFound, fmt.Sprintf("name \"%s\"", name))
    72  			return
    73  		}
    74  		err = errors.Wrap(apperr.ErrRoleGet, err.Error())
    75  		return
    76  	}
    77  
    78  	err = n.RelData(ctx, role)
    79  
    80  	return
    81  }
    82  
    83  // Update ...
    84  func (n Roles) Update(ctx context.Context, m *Role) (err error) {
    85  	err = n.Db.WithContext(ctx).Model(&Role{Name: m.Name}).Updates(map[string]interface{}{
    86  		"description": m.Description,
    87  		"parent":      m.RoleName,
    88  	}).Error
    89  	if err != nil {
    90  		err = errors.Wrap(apperr.ErrRoleUpdate, err.Error())
    91  	}
    92  
    93  	return
    94  }
    95  
    96  // Delete ...
    97  func (n Roles) Delete(ctx context.Context, name string) (err error) {
    98  	if err = n.Db.WithContext(ctx).Delete(&Role{Name: name}).Error; err != nil {
    99  		err = errors.Wrap(apperr.ErrRoleDelete, err.Error())
   100  	}
   101  	return
   102  }
   103  
   104  // List ...
   105  func (n *Roles) List(ctx context.Context, limit, offset int, orderBy, sort string) (list []*Role, total int64, err error) {
   106  
   107  	if err = n.Db.WithContext(ctx).Model(Role{}).Count(&total).Error; err != nil {
   108  		err = errors.Wrap(apperr.ErrRoleList, err.Error())
   109  		return
   110  	}
   111  
   112  	list = make([]*Role, 0)
   113  	err = n.Db.WithContext(ctx).
   114  		Limit(limit).
   115  		Offset(offset).
   116  		Order(fmt.Sprintf("%s %s", sort, orderBy)).
   117  		Find(&list).
   118  		Error
   119  
   120  	if err != nil {
   121  		err = errors.Wrap(apperr.ErrRoleList, err.Error())
   122  		return
   123  	}
   124  
   125  	for _, role := range list {
   126  		_ = n.RelData(ctx, role)
   127  	}
   128  
   129  	return
   130  }
   131  
   132  // Search ...
   133  func (n *Roles) Search(ctx context.Context, query string, limit, offset int) (list []*Role, total int64, err error) {
   134  
   135  	q := n.Db.WithContext(ctx).Model(&Role{}).
   136  		Where("name LIKE ?", "%"+query+"%")
   137  
   138  	if err = q.Count(&total).Error; err != nil {
   139  		err = errors.Wrap(apperr.ErrRoleSearch, err.Error())
   140  		return
   141  	}
   142  
   143  	q = q.
   144  		Limit(limit).
   145  		Offset(offset).
   146  		Order("name ASC")
   147  
   148  	list = make([]*Role, 0)
   149  	if err = q.Find(&list).Error; err != nil {
   150  		err = errors.Wrap(apperr.ErrRoleSearch, err.Error())
   151  	}
   152  
   153  	return
   154  }
   155  
   156  // RelData ...
   157  func (n *Roles) RelData(ctx context.Context, role *Role) (err error) {
   158  
   159  	// get parent
   160  	if role.RoleName.Valid {
   161  		role.Role = &Role{}
   162  		err = n.Db.WithContext(ctx).Model(role).
   163  			Where("name = ?", role.RoleName.String).
   164  			Find(&role.Role).
   165  			Error
   166  		if err != nil {
   167  			err = errors.Wrap(apperr.ErrRoleGet, err.Error())
   168  		}
   169  	}
   170  
   171  	// get children
   172  	role.Children = make([]*Role, 0)
   173  	err = n.Db.WithContext(ctx).Model(role).
   174  		Where("parent = ?", role.Name).
   175  		Find(&role.Children).
   176  		Error
   177  	if err != nil {
   178  		err = errors.Wrap(apperr.ErrRoleGet, err.Error())
   179  	}
   180  
   181  	return
   182  }