- Add --setup flag to create admin user - Add --admin-user and --admin-password for setup - Generate cryptographically random passwords for --setup - Add --bind and --port flags for server binding - Add BIND env var support - Add SMTP email service for password reset - Add password reset token storage - Add auth header to queue/logs frontend pages - Fix journalctl timestamp format - Fix logs to return empty array instead of error when no entries - Fix queue handler to return proper error message - Hide Users/Aliases nav links when no domain selected
146 lines
3.9 KiB
Go
146 lines
3.9 KiB
Go
package db
|
|
|
|
import "time"
|
|
|
|
func (d *DB) GetImcUserByUsername(username string) (*ImcUser, error) {
|
|
var user ImcUser
|
|
if err := d.Preload("Domains.Domain").Where("username = ?", username).First(&user).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &user, nil
|
|
}
|
|
|
|
func (d *DB) GetImcUserByID(id uint) (*ImcUser, error) {
|
|
var user ImcUser
|
|
if err := d.Preload("Domains.Domain").First(&user, id).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &user, nil
|
|
}
|
|
|
|
func (d *DB) CreateImcUser(username, passwordHash, role string) (*ImcUser, error) {
|
|
user := ImcUser{
|
|
Username: username,
|
|
PasswordHash: passwordHash,
|
|
Role: role,
|
|
}
|
|
if err := d.Create(&user).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &user, nil
|
|
}
|
|
|
|
func (d *DB) UpdateImcUserPassword(id uint, passwordHash string) error {
|
|
return d.Model(&ImcUser{}).Where("id = ?", id).Update("password_hash", passwordHash).Error
|
|
}
|
|
|
|
func (d *DB) DeleteImcUser(id uint) error {
|
|
return d.Delete(&ImcUser{}, id).Error
|
|
}
|
|
|
|
func (d *DB) EnsureAdminUser(username, passwordHash string) error {
|
|
var user ImcUser
|
|
err := d.Where("username = ? AND role = ?", username, "admin").First(&user).Error
|
|
if err == nil {
|
|
return d.Model(&ImcUser{}).Where("id = ?", user.ID).Update("password_hash", passwordHash).Error
|
|
}
|
|
_, err = d.CreateImcUser(username, passwordHash, "admin")
|
|
return err
|
|
}
|
|
|
|
func (d *DB) GetUserAccessibleDomains(userID uint, isAdmin bool) ([]Domain, error) {
|
|
if isAdmin {
|
|
var domains []Domain
|
|
if err := d.Find(&domains).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return domains, nil
|
|
}
|
|
|
|
var domains []Domain
|
|
err := d.Table("imc_users2domains").
|
|
Select("virtual_domains.*").
|
|
Joins("JOIN virtual_domains ON virtual_domains.id = imc_users2domains.domain_id").
|
|
Where("imc_users2domains.user_id = ?", userID).
|
|
Find(&domains).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if domains == nil {
|
|
domains = []Domain{}
|
|
}
|
|
return domains, nil
|
|
}
|
|
|
|
func (d *DB) CanAccessDomain(userID uint, domainName string, isAdmin bool) (bool, error) {
|
|
if isAdmin {
|
|
return true, nil
|
|
}
|
|
|
|
var count int64
|
|
err := d.Table("imc_users2domains").
|
|
Select("COUNT(*)").
|
|
Joins("JOIN virtual_domains ON virtual_domains.id = imc_users2domains.domain_id").
|
|
Where("imc_users2domains.user_id = ? AND virtual_domains.name = ?", userID, domainName).
|
|
Count(&count).Error
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return count > 0, nil
|
|
}
|
|
|
|
func (d *DB) AddUserToDomain(userID, domainID uint) error {
|
|
ud := ImcUserDomain{
|
|
UserID: userID,
|
|
DomainID: domainID,
|
|
}
|
|
return d.Create(&ud).Error
|
|
}
|
|
|
|
func (d *DB) RemoveUserFromDomain(userID, domainID uint) error {
|
|
return d.Where("user_id = ? AND domain_id = ?", userID, domainID).Delete(&ImcUserDomain{}).Error
|
|
}
|
|
|
|
func (d *DB) GetUsersForDomain(domainID uint) ([]ImcUser, error) {
|
|
var users []ImcUser
|
|
err := d.Table("imc_users2domains").
|
|
Select("imc_users.*").
|
|
Joins("JOIN imc_users ON imc_users.id = imc_users2domains.user_id").
|
|
Where("imc_users2domains.domain_id = ?", domainID).
|
|
Find(&users).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if users == nil {
|
|
users = []ImcUser{}
|
|
}
|
|
return users, nil
|
|
}
|
|
|
|
func (d *DB) IsUserInDomain(userID, domainID uint) (bool, error) {
|
|
var count int64
|
|
err := d.Model(&ImcUserDomain{}).Where("user_id = ? AND domain_id = ?", userID, domainID).Count(&count).Error
|
|
return count > 0, err
|
|
}
|
|
|
|
func (d *DB) CreatePasswordResetToken(userID uint, token string, expiresAt time.Time) error {
|
|
resetToken := PasswordResetToken{
|
|
UserID: userID,
|
|
Token: token,
|
|
ExpiresAt: expiresAt,
|
|
}
|
|
return d.Create(&resetToken).Error
|
|
}
|
|
|
|
func (d *DB) GetValidPasswordResetToken(token string) (*PasswordResetToken, error) {
|
|
var resetToken PasswordResetToken
|
|
err := d.Where("token = ? AND used = false AND expires_at > ?", token, time.Now()).First(&resetToken).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &resetToken, nil
|
|
}
|
|
|
|
func (d *DB) MarkResetTokenUsed(token string) error {
|
|
return d.Model(&PasswordResetToken{}).Where("token = ?", token).Update("used", true).Error
|
|
}
|