231 lines
4.7 KiB
Go
231 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)
|
|
usr.Activated = true
|
|
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 = ?
|
|
`, ADMIN, uid, true).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
|
|
}
|