|
|
@@ -13,22 +13,17 @@ import (
|
|
|
"github.com/jinzhu/gorm"
|
|
|
)
|
|
|
|
|
|
-// User represents the interface that is being used within the public api.
|
|
|
-type User interface {
|
|
|
- GetUsername() string
|
|
|
- GetServerSerialNumber() string
|
|
|
- GetCert() string
|
|
|
- GetIPNet() string
|
|
|
- IsNoGW() bool
|
|
|
- GetHostID() uint32
|
|
|
- IsAdmin() bool
|
|
|
+// dbRevokedModel is a database model for revoked VPN users.
|
|
|
+type dbRevokedModel struct {
|
|
|
+ gorm.Model
|
|
|
+ SerialNumber string
|
|
|
}
|
|
|
|
|
|
-// DBUser is database model for VPN users.
|
|
|
-type DBUser struct {
|
|
|
+// dbUserModel is database model for VPN users.
|
|
|
+type dbUserModel struct {
|
|
|
gorm.Model
|
|
|
ServerID uint
|
|
|
- Server DBServer
|
|
|
+ Server dbServerModel
|
|
|
|
|
|
Username string `gorm:"unique_index"`
|
|
|
Cert string // not user writable
|
|
|
@@ -40,13 +35,12 @@ type DBUser struct {
|
|
|
Admin bool
|
|
|
}
|
|
|
|
|
|
-// DBRevoked is a database model for revoked VPN users.
|
|
|
-type DBRevoked struct {
|
|
|
- gorm.Model
|
|
|
- SerialNumber string
|
|
|
+// User represents a vpn user.
|
|
|
+type User struct {
|
|
|
+ dbUserModel
|
|
|
}
|
|
|
|
|
|
-func (u *DBUser) setPassword(password string) error {
|
|
|
+func (u *dbUserModel) setPassword(password string) error {
|
|
|
hashedPassword, err := passlib.Hash(password)
|
|
|
if err != nil {
|
|
|
return fmt.Errorf("can not set password: %v", err)
|
|
|
@@ -57,7 +51,7 @@ func (u *DBUser) setPassword(password string) error {
|
|
|
}
|
|
|
|
|
|
// CheckPassword returns whether the given password is correct for the user.
|
|
|
-func (u *DBUser) CheckPassword(password string) bool {
|
|
|
+func (u *User) CheckPassword(password string) bool {
|
|
|
_, err := passlib.Verify(password, u.Hash)
|
|
|
if err != nil {
|
|
|
logrus.Error(err)
|
|
|
@@ -67,21 +61,24 @@ func (u *DBUser) CheckPassword(password string) bool {
|
|
|
}
|
|
|
|
|
|
// GetUser finds and returns the user with the given username from database.
|
|
|
-func GetUser(username string) (*DBUser, error) {
|
|
|
- user := DBUser{}
|
|
|
- db.Where(&DBUser{Username: username}).First(&user)
|
|
|
+func GetUser(username string) (*User, error) {
|
|
|
+ user := dbUserModel{}
|
|
|
+ db.Where(&dbUserModel{Username: username}).First(&user)
|
|
|
if db.NewRecord(&user) {
|
|
|
// user is not found
|
|
|
return nil, fmt.Errorf("user not found: %s", username)
|
|
|
}
|
|
|
- return &user, nil
|
|
|
+ return &User{dbUserModel: user}, nil
|
|
|
}
|
|
|
|
|
|
// GetAllUsers returns all recorded users in the database.
|
|
|
-func GetAllUsers() ([]*DBUser, error) {
|
|
|
- var users []*DBUser
|
|
|
- db.Find(&users)
|
|
|
-
|
|
|
+func GetAllUsers() ([]*User, error) {
|
|
|
+ var users []*User
|
|
|
+ var dbUsers []*dbUserModel
|
|
|
+ db.Find(&dbUsers)
|
|
|
+ for _, u := range dbUsers {
|
|
|
+ users = append(users, &User{dbUserModel: *u})
|
|
|
+ }
|
|
|
return users, nil
|
|
|
|
|
|
}
|
|
|
@@ -91,7 +88,7 @@ func GetAllUsers() ([]*DBUser, error) {
|
|
|
//
|
|
|
// It also generates the necessary client keys and signs certificates with the current
|
|
|
// server's CA.
|
|
|
-func CreateNewUser(username, password string, nogw bool, hostid uint32, admin bool) (*DBUser, error) {
|
|
|
+func CreateNewUser(username, password string, nogw bool, hostid uint32, admin bool) (*User, error) {
|
|
|
if !IsInitialized() {
|
|
|
return nil, fmt.Errorf("you first need to create server")
|
|
|
}
|
|
|
@@ -132,7 +129,7 @@ func CreateNewUser(username, password string, nogw bool, hostid uint32, admin bo
|
|
|
return nil, fmt.Errorf("ip %s is already allocated", ip)
|
|
|
}
|
|
|
}
|
|
|
- user := DBUser{
|
|
|
+ user := dbUserModel{
|
|
|
Username: username,
|
|
|
Cert: clientCert.Cert,
|
|
|
Key: clientCert.Key,
|
|
|
@@ -155,13 +152,13 @@ func CreateNewUser(username, password string, nogw bool, hostid uint32, admin bo
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
- return &user, nil
|
|
|
+ return &User{dbUserModel: user}, nil
|
|
|
}
|
|
|
|
|
|
// Update updates the user's attributes and writes them to the database.
|
|
|
//
|
|
|
// How this method works is similiar to PUT semantics of REST. It sets the user record fields to the provided function arguments.
|
|
|
-func (u *DBUser) Update(password string, nogw bool, hostid uint32, admin bool) error {
|
|
|
+func (u *User) Update(password string, nogw bool, hostid uint32, admin bool) error {
|
|
|
if !IsInitialized() {
|
|
|
return fmt.Errorf("you first need to create server")
|
|
|
}
|
|
|
@@ -195,7 +192,7 @@ func (u *DBUser) Update(password string, nogw bool, hostid uint32, admin bool) e
|
|
|
return fmt.Errorf("ip %s is already allocated", ip)
|
|
|
}
|
|
|
}
|
|
|
- db.Save(u)
|
|
|
+ db.Save(u.dbUserModel)
|
|
|
|
|
|
err := Emit()
|
|
|
if err != nil {
|
|
|
@@ -205,8 +202,8 @@ func (u *DBUser) Update(password string, nogw bool, hostid uint32, admin bool) e
|
|
|
}
|
|
|
|
|
|
// Delete deletes a user by the given username from the database.
|
|
|
-func (u *DBUser) Delete() error {
|
|
|
- if db.NewRecord(u) {
|
|
|
+func (u *User) Delete() error {
|
|
|
+ if db.NewRecord(u.dbUserModel) {
|
|
|
// user is not found
|
|
|
return fmt.Errorf("user is not initialized: %s", u.Username)
|
|
|
}
|
|
|
@@ -214,10 +211,10 @@ func (u *DBUser) Delete() error {
|
|
|
if err != nil {
|
|
|
return fmt.Errorf("can not get user's certificate: %v", err)
|
|
|
}
|
|
|
- db.Create(&DBRevoked{
|
|
|
+ db.Create(&dbRevokedModel{
|
|
|
SerialNumber: crt.SerialNumber.Text(16),
|
|
|
})
|
|
|
- db.Unscoped().Delete(u)
|
|
|
+ db.Unscoped().Delete(u.dbUserModel)
|
|
|
logrus.Infof("user deleted: %s", u.GetUsername())
|
|
|
err = Emit()
|
|
|
if err != nil {
|
|
|
@@ -228,13 +225,13 @@ func (u *DBUser) Delete() error {
|
|
|
}
|
|
|
|
|
|
// ResetPassword resets the users password into the provided password.
|
|
|
-func (u *DBUser) ResetPassword(password string) error {
|
|
|
- err := u.setPassword(password)
|
|
|
+func (u *User) ResetPassword(password string) error {
|
|
|
+ err := u.dbUserModel.setPassword(password)
|
|
|
if err != nil {
|
|
|
// user password can not be updated
|
|
|
return fmt.Errorf("user password can not be updated %s: %v", u.Username, err)
|
|
|
}
|
|
|
- db.Save(u)
|
|
|
+ db.Save(u.dbUserModel)
|
|
|
err = Emit()
|
|
|
if err != nil {
|
|
|
return err
|
|
|
@@ -250,7 +247,7 @@ func (u *DBUser) ResetPassword(password string) error {
|
|
|
// still existing users in the database.
|
|
|
//
|
|
|
// Also it can be used when a user cert is expired or user's private key stolen, missing etc.
|
|
|
-func (u *DBUser) Renew() error {
|
|
|
+func (u *User) Renew() error {
|
|
|
if !IsInitialized() {
|
|
|
return fmt.Errorf("you first need to create server")
|
|
|
}
|
|
|
@@ -273,7 +270,7 @@ func (u *DBUser) Renew() error {
|
|
|
u.Key = clientCert.Key
|
|
|
u.ServerSerialNumber = server.SerialNumber
|
|
|
|
|
|
- db.Save(u)
|
|
|
+ db.Save(u.dbUserModel)
|
|
|
err = Emit()
|
|
|
if err != nil {
|
|
|
return err
|
|
|
@@ -284,27 +281,27 @@ func (u *DBUser) Renew() error {
|
|
|
}
|
|
|
|
|
|
// GetUsername returns user's username.
|
|
|
-func (u *DBUser) GetUsername() string {
|
|
|
+func (u *User) GetUsername() string {
|
|
|
return u.Username
|
|
|
}
|
|
|
|
|
|
// GetCert returns user's public certificate.
|
|
|
-func (u *DBUser) GetCert() string {
|
|
|
+func (u *User) GetCert() string {
|
|
|
return u.Cert
|
|
|
}
|
|
|
|
|
|
// GetServerSerialNumber returns user's server serial number.
|
|
|
-func (u *DBUser) GetServerSerialNumber() string {
|
|
|
+func (u *User) GetServerSerialNumber() string {
|
|
|
return u.ServerSerialNumber
|
|
|
}
|
|
|
|
|
|
// GetCreatedAt returns user's creation time.
|
|
|
-func (u *DBUser) GetCreatedAt() string {
|
|
|
+func (u *User) GetCreatedAt() string {
|
|
|
return u.CreatedAt.Format(time.UnixDate)
|
|
|
}
|
|
|
|
|
|
// getIP returns user's vpn ip addr.
|
|
|
-func (u *DBUser) getIP() net.IP {
|
|
|
+func (u *User) getIP() net.IP {
|
|
|
users := getNonStaticHostUsers()
|
|
|
staticHostIDs := getStaticHostIDs()
|
|
|
server, err := GetServerInstance()
|
|
|
@@ -342,7 +339,7 @@ func (u *DBUser) getIP() net.IP {
|
|
|
}
|
|
|
|
|
|
// GetIPNet returns user's vpn ip network. (e.g. 192.168.0.1/24)
|
|
|
-func (u *DBUser) GetIPNet() string {
|
|
|
+func (u *User) GetIPNet() string {
|
|
|
server, err := GetServerInstance()
|
|
|
if err != nil {
|
|
|
logrus.Panicf("can not get user ipnet: %v", err)
|
|
|
@@ -357,29 +354,42 @@ func (u *DBUser) GetIPNet() string {
|
|
|
}
|
|
|
|
|
|
// IsNoGW returns whether user is set to get the vpn server as their default gateway.
|
|
|
-func (u *DBUser) IsNoGW() bool {
|
|
|
+func (u *User) IsNoGW() bool {
|
|
|
return u.NoGW
|
|
|
}
|
|
|
|
|
|
// GetHostID returns user's Host ID.
|
|
|
-func (u *DBUser) GetHostID() uint32 {
|
|
|
+func (u *User) GetHostID() uint32 {
|
|
|
return u.HostID
|
|
|
}
|
|
|
|
|
|
// IsAdmin returns whether user is admin or not.
|
|
|
-func (u *DBUser) IsAdmin() bool {
|
|
|
+func (u *User) IsAdmin() bool {
|
|
|
return u.Admin
|
|
|
}
|
|
|
|
|
|
-func getStaticHostUsers() []*DBUser {
|
|
|
- var users []*DBUser
|
|
|
- db.Unscoped().Not(DBUser{HostID: 0}).Find(&users)
|
|
|
+func (u *User) getKey() string {
|
|
|
+ return u.Key
|
|
|
+}
|
|
|
+
|
|
|
+func getStaticHostUsers() []*User {
|
|
|
+ var users []*User
|
|
|
+ var dbUsers []*dbUserModel
|
|
|
+ db.Unscoped().Not(dbUserModel{HostID: 0}).Find(&dbUsers)
|
|
|
+ for _, u := range dbUsers {
|
|
|
+ users = append(users, &User{dbUserModel: *u})
|
|
|
+ }
|
|
|
return users
|
|
|
}
|
|
|
|
|
|
-func getNonStaticHostUsers() []*DBUser {
|
|
|
- var users []*DBUser
|
|
|
- db.Unscoped().Where(DBUser{HostID: 0}).Find(&users)
|
|
|
+func getNonStaticHostUsers() []*User {
|
|
|
+ var users []*User
|
|
|
+ var dbUsers []*dbUserModel
|
|
|
+ db.Unscoped().Where(dbUserModel{HostID: 0}).Find(&dbUsers)
|
|
|
+ for _, u := range dbUsers {
|
|
|
+ users = append(users, &User{dbUserModel: *u})
|
|
|
+ }
|
|
|
+
|
|
|
return users
|
|
|
}
|
|
|
|