app/auth/helper.go

230 lines
4.7 KiB
Go

package auth
import (
"strings"
"github.com/gin-gonic/gin"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
// HasGroup checks if a group is in the claim groups
func (c *Claims) HasGroup(grps ...string) bool {
m := make(map[string]bool)
for _, grp := range grps {
m[grp] = true
}
for _, trg := range c.Groups {
if m[trg] {
return true
}
}
return false
}
func (srv Service) SetDefaultGroups() error {
l.Debug().Msg("Setup default groups")
for _, g := range []string{SYSTEM, ADMIN, USER} {
grp := &Group{}
if err := DB.Where("name = ?", g).First(grp).Error; err != nil {
err := DB.Create(&Group{
Name: g,
}).Error
if err != nil {
l.Error().Err(err).Msg("create group error")
return err
}
}
}
return nil
}
func (srv Service) SetDefaultAdmin(username, password string) error {
admin := &Group{}
err := DB.Where("name = ?", ADMIN).First(admin).Error
if err != nil {
l.Error().Err(err).Msg("SetDefaultAdmin")
return err
}
usrgrp := struct {
GroupID uint
UserID string
}{}
result := DB.
Raw("select * from user_groups where group_id = ?", admin.ID).
Scan(&usrgrp)
if result.Error != nil {
l.Error().Err(result.Error).Msg("SetDefaultAdmin")
return result.Error
}
usr := &User{}
if result.RowsAffected == 0 {
l.Debug().Msg("Setting up admin account")
pwd, _ := bcrypt.GenerateFromPassword([]byte(password), 14)
usr.Username = username
usr.Password = string(pwd)
err = DB.Transaction(func(tx *gorm.DB) error {
err := tx.Create(usr).Error
if err != nil {
return err
}
grp := &Group{
Name: username,
}
err = tx.Create(grp).Error
if err != nil {
return err
}
err = tx.Model(usr).Association("Groups").Append(admin, grp)
if err != nil {
return err
}
profile := &Profile{
DisplayName: username,
}
err = tx.Model(usr).Association("Profile").Append(profile)
if err != nil {
return err
}
return nil
})
if err != nil {
return err
}
SetGroup(usr.ID, USER, true)
}
return nil
}
func IsLastAdmin() bool {
var count int
DB.Raw(`
select count(*) from user_groups where group_id = (
select id from groups where name = ?
)
`, ADMIN).Scan(&count)
return count == 1
}
func IsLastAdminUser(uid string) bool {
var count int
DB.Raw(`
select count(*) from user_groups ug, users u
where group_id = (select id from groups where name = ?)
and user_id <> ?
and u.id = user_id
and u.activated = 1
`, ADMIN, uid).Scan(&count)
return count == 0
}
func SetAdmin(uid string, set bool) {
SetGroup(uid, ADMIN, set)
}
func SetGroup(uid string, group_name string, set bool) {
var grp_id uint
DB.Raw(
`select id from groups where name = ?`,
group_name,
).Scan(&grp_id)
var count int
DB.Raw(`
select count(*) from user_groups where group_id = ?
and user_id = ?`,
grp_id, uid).Scan(&count)
// remove
if count == 1 && !set {
DB.Exec(`delete from user_groups where group_id = ?
and user_id = ?`, grp_id, uid)
}
// add
if count == 0 && set {
DB.Exec(`insert into user_groups (group_id, user_id)
values (?, ?)`, grp_id, uid)
}
}
func GetUser(c *gin.Context) (*User, error) {
claim, err := GetContextClaims(c)
if err != nil {
return nil, err
}
usr := &User{}
if claim.Uid == sys_user {
usr = GetSysUser()
return usr, nil
}
err = DB.Preload("Groups").Preload("Profile").Where("id = ?", claim.Uid).First(usr).Error
if err != nil {
return nil, err
}
return usr, nil
}
// NewUser the password is still not hashed
func NewUser(usr *User) error {
if usr.Username == "" || usr.Password == "" {
return ErrorBadRequestTmpl.New("auth.User")
}
if usr.Username == sys_user {
return ErrorUserExist
}
bytes, err := bcrypt.GenerateFromPassword([]byte(usr.Password), 14)
if err != nil {
return err
}
usr.Password = string(bytes)
err = DB.Transaction(func(tx *gorm.DB) error {
err := tx.Create(usr).Error
if err != nil {
return err
}
grp := &Group{
Name: usr.Username,
}
err = tx.Create(grp).Error
if err != nil {
return err
}
grp_user := &Group{}
err = DB.Where("name = ?", USER).First(grp_user).Error
if err != nil {
return err
}
err = tx.Model(usr).Association("Groups").Append(grp, grp_user)
if err != nil {
return err
}
profile := &Profile{
DisplayName: usr.Username,
}
err = tx.Model(usr).Association("Profile").Append(profile)
if err != nil {
return err
}
return nil
})
return err
}
func GetSysUser() *User {
grps := []*Group{}
if err := DB.Where("name = ?", SYSTEM).Find(&grps).Error; err != nil {
grps = []*Group{{
Name: SYSTEM,
DisplayName: strings.TrimPrefix(SYSTEM, SYS_AUTH_PREFIX),
}}
}
usr := &User{
ID: sys_user,
Username: sys_user,
Profile: Profile{
DisplayName: "System Developer",
},
Groups: grps,
}
return usr
}