# Exemple avec base de données
Cet exemple montre comment utiliser le serveur FTP avec la base de données SQLite intégrée et le hashage de mot de passe Argon2.
Support Base de Données
Version 2.0+ utilise exclusivement SQLite via @db/sqlite pour de meilleures performances et un déploiement simplifié.
# Points clés
- Option
database: Configurez la base de données directement dansFTPServerOptions server.users: Accédez auUserRepositoryvia l'instance serveurUserRepository: Classe instanciable exportée pour une gestion avancée- Multi-tenant : Permet plusieurs serveurs avec différentes bases de données (idéal pour le multi-tenant ou les tests)
# Import
Ajoutez le package à votre projet :
deno add @dftp/server
Importez le serveur, le repository utilisateurs et Argon2 :
import { Server, UserRepository } from "@dftp/server";
import { hash, verify } from "@node-rs/argon2";
# Initialiser le serveur avec base de données
Passez l'option database directement dans les options du serveur :
// Créer le serveur avec sa propre base de données
const server = new Server({
port: 21,
database: { connector: "SQLite", filepath: "./users.db" }
});
// Accéder au UserRepository via server.users
server.users.create({
username: "admin",
password: await hash("secret"),
root: "/srv/ftp",
uid: 1000,
gid: 1000,
});
Multi-tenant et Tests
Chaque instance Server peut avoir sa propre base de données, permettant d'exécuter plusieurs serveurs FTP isolés (multi-tenant) ou de créer des environnements de test indépendants.
# Gérer les connexions
Authentifiez les utilisateurs contre la base de données :
for await (const conn of server) {
conn.on("login", async ({ username, password }, resolve, reject) => {
const user = server.users.findByUsername(username);
if (user && await verify(user.password, password)) {
resolve({ root: user.root, uid: user.uid, gid: user.gid });
} else {
reject();
}
});
}
# Utilisation avancée : UserRepository indépendant
Pour une gestion avancée, vous pouvez instancier UserRepository directement :
import { UserRepository } from "@dftp/server";
// Créer un repository indépendant
const repo = new UserRepository({ connector: "SQLite", filepath: "./custom.db" });
// Gérer les utilisateurs
repo.create({ username: "user1", password: await hash("pass"), root: "/data", uid: 1001, gid: 1001 });
const user = repo.findByUsername("user1");
# Exemple complet
import { Server, UserRepository } from "@dftp/server";
import { hash, verify } from "@node-rs/argon2";
// Créer le serveur avec sa propre base de données
const server = new Server({
port: 21,
database: { connector: "SQLite", filepath: "./users.db" }
});
// Créer un utilisateur (exécuter une fois)
server.users.create({
username: "admin",
password: await hash("secret"),
root: "/srv/ftp",
uid: 1000,
gid: 1000,
});
// Démarrer le serveur
console.log("Serveur FTP en écoute sur le port 21");
for await (const conn of server) {
conn.on("login", async ({ username, password }, resolve, reject) => {
const user = server.users.findByUsername(username);
if (user && await verify(user.password, password)) {
resolve({ root: user.root, uid: user.uid, gid: user.gid });
} else {
reject();
}
});
}
# Exemple multi-tenant
import { Server } from "@dftp/server";
import { hash, verify } from "@node-rs/argon2";
// Serveur tenant A
const serverA = new Server({
port: 2121,
database: { connector: "SQLite", filepath: "./tenant-a.db" }
});
// Serveur tenant B
const serverB = new Server({
port: 2122,
database: { connector: "SQLite", filepath: "./tenant-b.db" }
});
// Chaque serveur a son propre UserRepository isolé
serverA.users.create({ username: "admin", password: await hash("a"), root: "/a", uid: 1000, gid: 1000 });
serverB.users.create({ username: "admin", password: await hash("b"), root: "/b", uid: 1000, gid: 1000 });