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) { collection, err := getMongoCollection(config) if err != nil { return nil, err } return &InviteTokenDbHandler{ collection: collection, }, nil }