refactored

This commit is contained in:
2025-03-18 23:27:27 +02:00
parent 64f59ea232
commit 6c1f34c682
45 changed files with 398 additions and 413 deletions

19
dbhandler/mongo/go.mod Normal file
View File

@@ -0,0 +1,19 @@
module git.acooldomain.co/server-manager/backend/dbhandler/mongo
go 1.24.1
require go.mongodb.org/mongo-driver v1.14.0
require (
github.com/golang/snappy v0.0.1 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/klauspost/compress v1.13.6 // indirect
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/text v0.15.0 // indirect
)

13
dbhandler/mongo/go.sum Normal file
View File

@@ -0,0 +1,13 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=

192
dbhandler/mongo/servers.go Normal file
View File

@@ -0,0 +1,192 @@
package mongo
import (
"context"
"fmt"
"time"
"git.acooldomain.co/server-manager/backend/dbhandler"
"git.acooldomain.co/server-manager/backend/models"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type Image struct {
Registry string `bson:"registry"`
Tag string `bson:"tag"`
}
type Port struct {
PublicPort uint16 `bson:"public_port"`
ContainerPort uint16 `bson:"container_port"`
Protocol models.PortProtocol `bson:"protocol"`
}
type Server struct {
Id string `bson:"id"`
Owner string `bson:"owner"`
Image Image `bson:"image"`
Nickname string `bson:"nickname"`
Command string `bson:"command"`
Ports []Port `bson:"ports"`
}
func convertToDbServer(server dbhandler.Server) Server {
ports := make([]Port, len(server.Ports))
for i, port := range server.Ports {
ports[i] = Port{
PublicPort: port.PublicPort,
ContainerPort: port.ContainerPort,
Protocol: port.Protocol,
}
}
return Server{
Id: server.Id,
Owner: server.Owner,
Image: Image{
Registry: server.Image.Registry,
Tag: server.Image.Tag,
},
Nickname: server.Nickname,
Command: server.Command,
Ports: ports,
}
}
func convertToResponseServer(server Server) dbhandler.Server {
ports := make([]models.Port, len(server.Ports))
for i, port := range server.Ports {
ports[i] = models.Port{
PublicPort: port.PublicPort,
ContainerPort: port.ContainerPort,
Protocol: port.Protocol,
}
}
return dbhandler.Server{
Id: server.Id,
Owner: server.Owner,
Image: &models.Image{
Registry: server.Image.Registry,
Tag: server.Image.Tag,
},
Nickname: server.Nickname,
Command: server.Command,
Ports: ports,
}
}
type ServersDbHandler struct {
dbhandler.ServersDbHandler
collection *mongo.Collection
}
func (self *ServersDbHandler) ListServers(ctx context.Context) ([]dbhandler.Server, error) {
var servers []Server
cursor, err := self.collection.Find(ctx, bson.M{})
if err != nil {
return nil, err
}
defer cursor.Close(ctx)
err = cursor.All(ctx, &servers)
if err != nil {
return nil, err
}
dbServers := make([]dbhandler.Server, len(servers))
for i, server := range servers {
dbServers[i] = convertToResponseServer(server)
}
return dbServers, nil
}
func (self *ServersDbHandler) GetServer(ctx context.Context, serverId string) (*dbhandler.Server, error) {
var server Server
err := self.collection.FindOne(ctx, bson.M{"server_id": serverId}).Decode(&server)
if err != nil {
return nil, err
}
responseServer := convertToResponseServer(server)
return &responseServer, nil
}
func (self *ServersDbHandler) CreateServer(ctx context.Context, server dbhandler.Server) error {
dbServer := convertToDbServer(server)
_, err := self.collection.InsertOne(ctx, &dbServer)
return err
}
func (self *ServersDbHandler) DeleteServer(ctx context.Context, serverId string) error {
_, err := self.collection.DeleteOne(ctx, bson.M{
"server_id": serverId,
})
return err
}
func (self *ServersDbHandler) UpdateServer(ctx context.Context, serverId string, updateParams dbhandler.ServerUpdateRequest) error {
updateServerRequest := bson.M{}
if updateParams.Owner != "" {
updateServerRequest["owner"] = updateParams.Owner
}
if updateParams.Image != nil {
updateServerRequest["image"] = bson.M{
"registry": updateParams.Image.Registry,
"tag": updateParams.Image.Tag,
}
}
if updateParams.Ports != nil {
ports := make([]bson.M, len(updateParams.Ports))
for i, port := range updateParams.Ports {
ports[i] = bson.M{
"number": port.PublicPort,
"protocol": port.Protocol,
}
}
}
if updateParams.Nickname != "" {
updateServerRequest["nickname"] = updateParams.Nickname
}
if updateParams.Command != "" {
updateServerRequest["command"] = updateParams.Command
}
_, err := self.collection.UpdateOne(ctx, bson.M{"server_id": serverId}, bson.M{"$set": updateServerRequest})
return err
}
func NewServersDbHandler(config models.MongoDBConfig) (*ServersDbHandler, error) {
clientOptions := options.Client().ApplyURI(config.Url).SetAuth(options.Credential{
Username: config.Username,
Password: config.Password,
})
ctx, cancel := context.WithTimeoutCause(context.Background(), 30*time.Second, fmt.Errorf("Timeout"))
defer cancel()
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
return nil, err
}
return &ServersDbHandler{
collection: client.Database(config.Database).Collection(config.Collection),
}, nil
}

View File

@@ -0,0 +1,161 @@
package mongo
import (
"context"
"fmt"
"time"
"git.acooldomain.co/server-manager/backend/dbhandler"
"git.acooldomain.co/server-manager/backend/models"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type ServerPermissions struct {
Username string `bson:"username"`
ServerId string `bson:"server_id"`
Permissions models.Permission `bson:"permissions"`
}
type ServersAuthorizationDbHandler struct {
dbhandler.ServersAuthorizationDbHandler
collection *mongo.Collection
}
func (self *ServersAuthorizationDbHandler) RemoveUser(ctx context.Context, username string) error {
_, err := self.collection.DeleteMany(
ctx,
bson.M{
"username": username,
},
)
return err
}
func (self *ServersAuthorizationDbHandler) RemoveServer(ctx context.Context, serverId string) error {
_, err := self.collection.DeleteMany(
ctx,
bson.M{
"server_id": serverId,
},
)
return err
}
func (self *ServersAuthorizationDbHandler) AddPermissions(ctx context.Context, username string, serverId string, permissions models.Permission) error {
var serverPermissions ServerPermissions
err := self.collection.FindOne(
ctx,
bson.M{
"username": username,
"server_id": serverId,
},
).Decode(&serverPermissions)
if err != nil {
return err
}
newPermissions := serverPermissions.Permissions | permissions
_, err = self.collection.UpdateOne(
ctx,
bson.M{
"username": username,
"server_id": serverId,
},
bson.M{"$set": bson.M{
"permissions": newPermissions,
},
},
)
return err
}
func (self *ServersAuthorizationDbHandler) RemovePermissions(ctx context.Context, username string, serverId string, permissions models.Permission) error {
var serverPermissions ServerPermissions
err := self.collection.FindOne(
ctx,
bson.M{
"username": username,
"server_id": serverId,
},
).Decode(&serverPermissions)
if err != nil {
return err
}
newPermissions := serverPermissions.Permissions | permissions ^ permissions
_, err = self.collection.UpdateOne(
ctx,
bson.M{
"username": username,
"server_id": serverId,
},
bson.M{"$set": bson.M{
"permissions": newPermissions,
},
},
)
return err
}
func (self *ServersAuthorizationDbHandler) SetPermissions(ctx context.Context, username string, serverId string, permissions models.Permission) error {
_, err := self.collection.UpdateOne(
ctx,
bson.M{
"username": username,
"server_id": serverId,
},
bson.M{"$set": bson.M{
"permissions": permissions,
},
},
)
return err
}
func (self *ServersAuthorizationDbHandler) GetPermissions(ctx context.Context, username string, serverId string) (models.Permission, error) {
var serverPermissions ServerPermissions
err := self.collection.FindOne(
ctx,
bson.M{
"username": username,
"server_id": serverId,
},
).Decode(&serverPermissions)
if err != nil {
return 0, err
}
return serverPermissions.Permissions, nil
}
func NewServersAuthorizationHandler(config models.MongoDBConfig) (*ServersAuthorizationDbHandler, error) {
clientOptions := options.Client().ApplyURI(config.Url).SetAuth(options.Credential{
Username: config.Username,
Password: config.Password,
})
ctx, cancel := context.WithTimeoutCause(context.Background(), 30*time.Second, fmt.Errorf("Timeout"))
defer cancel()
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
return nil, err
}
return &ServersAuthorizationDbHandler{
collection: client.Database(config.Database).Collection(config.Collection),
}, nil
}

View File

@@ -0,0 +1,216 @@
package mongo
import (
"context"
"fmt"
"time"
"git.acooldomain.co/server-manager/backend/dbhandler"
"git.acooldomain.co/server-manager/backend/models"
"github.com/google/uuid"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type AuthUser struct {
Username string `json:"username"`
Nickname string `json:"nickname"`
HashedPassword string `json:"hashed_password"`
Permissions models.Permission `json:"permissions"`
MaxOwnedSevers uint `json:"max_owned_severs"`
Email string `json:"email"`
}
type UserPassAuthenticationDbHandler struct {
dbhandler.UserPassAuthanticationDbHandler
collection *mongo.Collection
}
func (self *UserPassAuthenticationDbHandler) ListUsers(ctx context.Context) ([]models.User, error) {
cursor, err := self.collection.Find(ctx, nil)
if err != nil {
return nil, err
}
var authUsers []AuthUser
cursor.All(ctx, &authUsers)
modelUsers := make([]models.User, len(authUsers))
for i, authUser := range authUsers {
modelUsers[i] = models.User{
Username: authUser.Username,
Nickname: authUser.Nickname,
Email: authUser.Email,
MaxOwnedServers: authUser.MaxOwnedSevers,
Permissions: authUser.Permissions,
}
}
return modelUsers, nil
}
func (self *UserPassAuthenticationDbHandler) AuthenticateUser(ctx context.Context, username string, password string) (*models.User, error) {
var user AuthUser
err := self.collection.FindOne(ctx, bson.M{"username": username}).Decode(&user)
if err != nil {
return nil, err
}
hashedPassword, err := dbhandler.HashPassword(password)
if err != nil {
return nil, err
}
if user.HashedPassword != hashedPassword {
return nil, fmt.Errorf("Incorrect Password")
}
return &models.User{
Username: user.Username,
Nickname: user.Nickname,
Email: user.Email,
MaxOwnedServers: user.MaxOwnedSevers,
Permissions: user.Permissions,
}, nil
}
func (self *UserPassAuthenticationDbHandler) CreateUser(
ctx context.Context,
username string,
password string,
permissions models.Permission,
email string,
maxOwnedServers uint,
) error {
hashedPassword, err := dbhandler.HashPassword(password)
if err != nil {
return err
}
_, err = self.collection.InsertOne(ctx, &AuthUser{
Username: username,
HashedPassword: hashedPassword,
Permissions: permissions,
Email: email,
MaxOwnedSevers: maxOwnedServers,
})
return err
}
func (self *UserPassAuthenticationDbHandler) RemoveUser(ctx context.Context, username string) error {
_, err := self.collection.DeleteOne(
ctx,
bson.M{
"username": username,
},
)
return err
}
func (self *UserPassAuthenticationDbHandler) SetPermissions(
ctx context.Context,
username string,
permissions models.Permission,
) error {
_, err := self.collection.UpdateOne(
ctx,
bson.M{
"username": username,
},
bson.M{
"$set": bson.M{
"permissions": permissions,
},
},
)
return err
}
func NewUserPassAuthHandler(config models.MongoDBConfig) (*UserPassAuthenticationDbHandler, error) {
clientOptions := options.Client().ApplyURI(config.Url).SetAuth(options.Credential{
Username: config.Username,
Password: config.Password,
})
ctx, cancel := context.WithTimeoutCause(context.Background(), 30*time.Second, fmt.Errorf("Timeout"))
defer cancel()
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
return nil, err
}
return &UserPassAuthenticationDbHandler{
collection: client.Database(config.Database).Collection(config.Collection),
}, nil
}
type InviteToken struct {
Email string `json:"email"`
Token string `json:"token"`
Permissions models.Permission `json:"permissions"`
}
type InviteTokenDbHandler struct {
dbhandler.InviteTokenDbHandler
collection *mongo.Collection
}
func (self *ServersDbHandler) SaveInviteToken(ctx context.Context, email string, permissions models.Permission) (string, error) {
token := uuid.NewString()
_, err := self.collection.InsertOne(ctx, &InviteToken{
Permissions: permissions,
Email: email,
Token: token,
})
if err != nil {
return "", err
}
return token, nil
}
func (self *ServersDbHandler) GetInviteToken(ctx context.Context, token string) (*dbhandler.InviteToken, error) {
var inviteToken InviteToken
err := self.collection.FindOne(ctx, bson.M{"token": token}).Decode(&inviteToken)
if err != nil {
return nil, err
}
return &dbhandler.InviteToken{
Email: inviteToken.Email,
Permissions: inviteToken.Permissions,
Token: inviteToken.Token,
}, nil
}
func NewInviteTokenDbHandler(config models.MongoDBConfig) (*InviteTokenDbHandler, error) {
clientOptions := options.Client().ApplyURI(config.Url).SetAuth(options.Credential{
Username: config.Username,
Password: config.Password,
})
ctx, cancel := context.WithTimeoutCause(context.Background(), 30*time.Second, fmt.Errorf("Timeout"))
defer cancel()
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
return nil, err
}
return &InviteTokenDbHandler{
collection: client.Database(config.Database).Collection(config.Collection),
}, nil
}