mirror of
https://github.com/h44z/wg-portal.git
synced 2025-09-15 07:11:15 +00:00
V2 alpha - initial version (#172)
Initial alpha codebase for version 2 of WireGuard Portal. This version is considered unstable and incomplete (for example, no public REST API)! Use with care! Fixes/Implements the following issues: - OAuth support #154, #1 - New Web UI with internationalisation support #98, #107, #89, #62 - Postgres Support #49 - Improved Email handling #47, #119 - DNS Search Domain support #46 - Bugfixes #94, #48 --------- Co-authored-by: Fabian Wechselberger <wechselbergerf@hotmail.com>
This commit is contained in:
139
internal/domain/user.go
Normal file
139
internal/domain/user.go
Normal file
@@ -0,0 +1,139 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
const (
|
||||
UserSourceLdap UserSource = "ldap" // LDAP / ActiveDirectory
|
||||
UserSourceDatabase UserSource = "db" // sqlite / mysql database
|
||||
UserSourceOauth UserSource = "oauth" // oauth / open id connect
|
||||
)
|
||||
|
||||
type UserIdentifier string
|
||||
|
||||
type UserSource string
|
||||
|
||||
// User is the user model that gets linked to peer entries, by default an empty user model with only the email address is created
|
||||
type User struct {
|
||||
BaseModel
|
||||
|
||||
// required fields
|
||||
Identifier UserIdentifier `gorm:"primaryKey;column:identifier"`
|
||||
Email string `form:"email" binding:"required,email"`
|
||||
Source UserSource
|
||||
ProviderName string
|
||||
IsAdmin bool
|
||||
|
||||
// optional fields
|
||||
Firstname string `form:"firstname" binding:"omitempty"`
|
||||
Lastname string `form:"lastname" binding:"omitempty"`
|
||||
Phone string `form:"phone" binding:"omitempty"`
|
||||
Department string `form:"department" binding:"omitempty"`
|
||||
Notes string `form:"notes" binding:"omitempty"`
|
||||
|
||||
// optional, integrated password authentication
|
||||
Password PrivateString `form:"password" binding:"omitempty"`
|
||||
Disabled *time.Time `gorm:"index;column:disabled"` // if this field is set, the user is disabled (WireGuard peers are disabled as well)
|
||||
DisabledReason string // the reason why the user has been disabled
|
||||
Locked *time.Time `gorm:"index;column:locked"` // if this field is set, the user is locked and can no longer login (WireGuard peers still can connect)
|
||||
LockedReason string // the reason why the user has been locked
|
||||
|
||||
LinkedPeerCount int `gorm:"-"`
|
||||
}
|
||||
|
||||
// IsDisabled returns true if the user is disabled. In such a case,
|
||||
// no login is possible and WireGuard peers associated with the user are disabled.
|
||||
func (u *User) IsDisabled() bool {
|
||||
return u.Disabled != nil
|
||||
}
|
||||
|
||||
// IsLocked returns true if the user is locked. In such a case, no login is possible, WireGuard connections still work.
|
||||
func (u *User) IsLocked() bool {
|
||||
return u.Locked != nil
|
||||
}
|
||||
|
||||
func (u *User) CanChangePassword() error {
|
||||
if u.Source == UserSourceDatabase {
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.New("password change only allowed for database source")
|
||||
}
|
||||
|
||||
func (u *User) EditAllowed(new *User) error {
|
||||
if u.Source == UserSourceDatabase {
|
||||
return nil
|
||||
}
|
||||
|
||||
// for users which are not database users, only the notes field and the disabled flag can be updated
|
||||
updateOk := true
|
||||
updateOk = updateOk && u.Identifier == new.Identifier
|
||||
updateOk = updateOk && u.Source == new.Source
|
||||
updateOk = updateOk && u.IsAdmin == new.IsAdmin
|
||||
updateOk = updateOk && u.Email == new.Email
|
||||
updateOk = updateOk && u.Firstname == new.Firstname
|
||||
updateOk = updateOk && u.Lastname == new.Lastname
|
||||
updateOk = updateOk && u.Phone == new.Phone
|
||||
updateOk = updateOk && u.Department == new.Department
|
||||
|
||||
if !updateOk {
|
||||
return errors.New("edit only allowed for database source")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) DeleteAllowed() error {
|
||||
if u.Source == UserSourceDatabase {
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.New("delete only allowed for database source")
|
||||
}
|
||||
|
||||
func (u *User) CheckPassword(password string) error {
|
||||
if u.Source != UserSourceDatabase {
|
||||
return errors.New("invalid user source")
|
||||
}
|
||||
|
||||
if u.IsDisabled() {
|
||||
return errors.New("user disabled")
|
||||
}
|
||||
|
||||
if u.Password == "" {
|
||||
return errors.New("empty user password")
|
||||
}
|
||||
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password)); err != nil {
|
||||
return errors.New("wrong password")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) HashPassword() error {
|
||||
if u.Password == "" {
|
||||
return nil // nothing to hash
|
||||
}
|
||||
|
||||
if _, err := bcrypt.Cost([]byte(u.Password)); err == nil {
|
||||
return nil // password already hashed
|
||||
}
|
||||
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u.Password = PrivateString(hash)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) CopyCalculatedAttributes(src *User) {
|
||||
u.BaseModel = src.BaseModel
|
||||
u.LinkedPeerCount = src.LinkedPeerCount
|
||||
}
|
Reference in New Issue
Block a user