ubuntu resolute

This commit is contained in:
Maxime KINTS
2026-05-16 23:42:06 +02:00
commit c0f607fa0b
944 changed files with 112243 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
const fs = require('fs');
module.exports = function(app, checkApiKey) {
app.post('/action/addingroup', checkApiKey, (req, res) => {
const { groupName, username } = req.body;
if (!groupName || !username) {
return res.status(400).send('Group name and username are required');
}
const authzFilePath = '/etc/apache2/dav_svn.authz';
fs.readFile(authzFilePath, 'utf8', (err, data) => {
if (err) {
return res.status(500).send(`Error reading authz file: ${err}`);
}
const lines = data.split('\n');
let groupLineIndex = -1;
let groupLine = '';
// Find the group line
for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith(groupName + ' =')) {
groupLineIndex = i;
groupLine = lines[i];
break;
}
}
if (groupLineIndex === -1) {
return res.status(404).send(`Group ${groupName} not found`);
}
// Parse existing users and add new user
const users = groupLine.split('=')[1].trim().split(',').map(u => u.trim());
if (!users.includes(username)) {
users.push(username);
lines[groupLineIndex] = `${groupName} = ${users.join(', ')}`;
fs.writeFile(authzFilePath, lines.join('\n'), 'utf8', (err) => {
if (err) {
return res.status(500).send(`Error updating authz file: ${err}`);
}
res.send(`User ${username} added to group ${groupName} successfully`);
});
} else {
res.send(`User ${username} is already in group ${groupName}`);
}
});
});
};

View File

@@ -0,0 +1,45 @@
const fs = require('fs');
const apacheMd5 = require('apache-md5');
module.exports = function(app, checkApiKey) {
app.post('/action/changepassword', checkApiKey, (req, res) => {
const { username, newPassword } = req.body;
// Vérification des paramètres
if (!username || !newPassword) {
return res.status(400).send('Username and new password are required');
}
const passwdFilePath = '/etc/apache2/dav_svn.passwd';
// Lire le fichier passwd
fs.readFile(passwdFilePath, 'utf8', (err, data) => {
if (err) {
return res.status(500).send(`Error reading passwd file: ${err}`);
}
const lines = data.split('\n');
let userFound = false;
const newLines = lines.map(line => {
if (line.startsWith(`${username}:`)) {
userFound = true;
const hashedPassword = apacheMd5(newPassword);
return `${username}:${hashedPassword}`;
}
return line;
});
if (!userFound) {
return res.status(404).send(`User ${username} not found`);
}
// Écrire les modifications dans le fichier passwd
fs.writeFile(passwdFilePath, newLines.join('\n'), 'utf8', (err) => {
if (err) {
return res.status(500).send(`Error updating passwd file: ${err}`);
}
res.send(`Password for user ${username} changed successfully`);
});
});
});
};

View File

@@ -0,0 +1,55 @@
const fs = require('fs');
module.exports = function (app, checkApiKey) {
app.post('/action/delperm', checkApiKey, (req, res) => {
const authzFilePath = '/etc/apache2/dav_svn.authz';
const { repoName, user } = req.body;
console.log("Nom du repo reçu :", repoName); // DEBUG
console.log("Utilisateur reçu :", user); // DEBUG
if (!repoName || !user) {
return res.status(400).json({ error: "Missing repoName or user parameter" });
}
try {
const fileContent = fs.readFileSync(authzFilePath, 'utf8');
console.log("Contenu du fichier avant modification :");
console.log(fileContent); // DEBUG
const repoRegex = new RegExp(`(\\[/${repoName}\\][^\\[]*)(?=\\[|$)`, 'gs');
const match = repoRegex.exec(fileContent);
if (!match) {
return res.status(400).json({ error: "Repository section not found" });
}
const fullRepoSection = match[0];
const lines = fullRepoSection.split('\n');
const newLines = lines.filter(line => {
const trimmed = line.trim();
return !trimmed.startsWith(user + ' =');
});
const updatedRepoSection = newLines.join('\n');
const newFileContent = fileContent.replace(fullRepoSection, updatedRepoSection);
console.log("Contenu du fichier après modification :");
console.log(newFileContent); // DEBUG
fs.writeFileSync(authzFilePath, newFileContent, 'utf8');
res.json({ message: 'Permission removed successfully' });
} catch (error) {
res.status(500).json({
error: "Error processing repository permissions",
details: error.message
});
}
});
};

View File

@@ -0,0 +1,30 @@
const fs = require('fs');
module.exports = function(app, checkApiKey) {
app.post('/action/deletegroup', checkApiKey, (req, res) => {
const { groupName } = req.body;
if (!groupName) {
return res.status(400).send('Group name is required');
}
const authzFilePath = '/etc/apache2/dav_svn.authz'; // Updated correct path
fs.readFile(authzFilePath, 'utf8', (err, data) => {
if (err) {
return res.status(500).send(`Error reading authz file: ${err}`);
}
const groupRegex = new RegExp(`^${groupName}\\s*=.*$`, 'm');
let updatedData = data;
if (groupRegex.test(data)) {
updatedData = updatedData.replace(groupRegex, '');
updatedData = updatedData.replace(/^\s*[\r\n]/gm, '');
} else {
return res.status(404).send(`Group ${groupName} does not exist`);
}
fs.writeFile(authzFilePath, updatedData, 'utf8', (err) => {
if (err) {
return res.status(500).send(`Error writing authz file: ${err}`);
}
res.send(`Group ${groupName} deleted successfully`);
});
});
});
};

View File

@@ -0,0 +1,40 @@
const fs = require('fs');
const { execSync } = require('child_process');
module.exports = function(app, checkApiKey) {
app.post('/action/deleterepo', checkApiKey, (req, res) => {
const { repoName } = req.body;
if (!repoName) {
return res.status(400).send('Repository name is required');
}
const repoPath = `/var/svn/${repoName}`;
const authzFilePath = '/etc/apache2/dav_svn.authz';
try {
// Check if repo exists
if (!fs.existsSync(repoPath)) {
return res.status(404).send(`Repository ${repoName} not found`);
}
// Delete repository directory
execSync(`rm -rf ${repoPath}`);
// Update authz file
let authzContent = fs.readFileSync(authzFilePath, 'utf8');
const repoSection = new RegExp(`\\[/${repoName}\\][^\\[]*`, 'g');
authzContent = authzContent.replace(repoSection, '');
// Clean up empty lines
authzContent = authzContent.replace(/\n\s*\n/g, '\n');
fs.writeFileSync(authzFilePath, authzContent);
res.send(`Repository ${repoName} and its permissions deleted successfully`);
} catch (error) {
res.status(500).send(`Error deleting repository: ${error.message}`);
}
});
};

View File

@@ -0,0 +1,37 @@
const fs = require('fs');
module.exports = function(app, checkApiKey) {
app.post('/action/deleteuser', checkApiKey, (req, res) => {
const { username } = req.body;
// Vérification des paramètres
if (!username) {
return res.status(400).send('Username is required');
}
const passwdFilePath = '/etc/apache2/dav_svn.passwd';
// Lire le fichier passwd
fs.readFile(passwdFilePath, 'utf8', (err, data) => {
if (err) {
return res.status(500).send(`Error reading passwd file: ${err}`);
}
const lines = data.split('\n');
const newLines = lines.filter(line => !line.startsWith(`${username}:`));
// Vérifier si l'utilisateur a été trouvé et supprimé
if (lines.length === newLines.length) {
return res.status(404).send(`User ${username} not found`);
}
// Écrire les modifications dans le fichier passwd
fs.writeFile(passwdFilePath, newLines.join('\n'), 'utf8', (err) => {
if (err) {
return res.status(500).send(`Error updating passwd file: ${err}`);
}
res.send(`User ${username} deleted successfully`);
});
});
});
};

View File

@@ -0,0 +1,54 @@
const fs = require('fs');
module.exports = function(app, checkApiKey) {
app.post('/action/deleteuseringroup', checkApiKey, (req, res) => {
const { groupName, username } = req.body;
if (!groupName || !username) {
return res.status(400).send('Group name and username are required');
}
const authzFilePath = '/etc/apache2/dav_svn.authz';
fs.readFile(authzFilePath, 'utf8', (err, data) => {
if (err) {
return res.status(500).send(`Error reading authz file: ${err}`);
}
const lines = data.split('\n');
let groupLineIndex = -1;
let groupLine = '';
// Find the group line
for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith(groupName + ' =')) {
groupLineIndex = i;
groupLine = lines[i];
break;
}
}
if (groupLineIndex === -1) {
return res.status(404).send(`Group ${groupName} not found`);
}
// Parse existing users and remove the specified user
const users = groupLine.split('=')[1].trim().split(',').map(u => u.trim());
const userIndex = users.indexOf(username);
if (userIndex === -1) {
return res.status(404).send(`User ${username} not found in group ${groupName}`);
}
users.splice(userIndex, 1);
lines[groupLineIndex] = `${groupName} = ${users.join(', ')}`;
fs.writeFile(authzFilePath, lines.join('\n'), 'utf8', (err) => {
if (err) {
return res.status(500).send(`Error updating authz file: ${err}`);
}
res.send(`User ${username} removed from group ${groupName} successfully`);
});
});
});
};

View File

@@ -0,0 +1,47 @@
const fs = require('fs');
module.exports = function (app, checkApiKey) {
app.get('/action/getgroups', checkApiKey, (req, res) => {
const authzFilePath = '/etc/apache2/dav_svn.authz';
try {
const fileContent = fs.readFileSync(authzFilePath, 'utf8');
const lines = fileContent.split('\n');
let groups = [];
let inGroupsSection = false;
for (const line of lines) {
const trimmed = line.trim();
// Début de la section [groups]
if (trimmed === '[groups]') {
inGroupsSection = true;
continue;
}
// Fin de la section [groups]
if (inGroupsSection && trimmed.startsWith('[')) {
break;
}
// Lire les groupes
if (inGroupsSection && trimmed.includes('=')) {
const groupName = trimmed.split('=')[0].trim();
groups.push(groupName);
}
}
res.json({
groups: groups,
count: groups.length
});
} catch (error) {
res.status(500).json({
error: "Error reading groups file",
details: error.message
});
}
});
};

View File

@@ -0,0 +1,47 @@
const fs = require('fs');
module.exports = function (app, checkApiKey) {
app.get('/action/getperm', checkApiKey, (req, res) => {
const authzFilePath = '/etc/apache2/dav_svn.authz';
// Récupérer le nom du repo depuis la query string ou le body
const repoName = req.query.repo || req.body.repo;
console.log("Nom du repo reçu :", repoName); // DEBUG
if (!repoName) {
return res.status(400).json({ error: "Missing repo parameter" });
}
try {
const fileContent = fs.readFileSync(authzFilePath, 'utf8');
const repoSection = fileContent.split(`[/${repoName}]`)[1];
if (!repoSection) {
return res.json({
users: [],
permissions: [],
count: 0
});
}
const lines = repoSection.split('\n')
.filter(line => line.includes('=') && !line.includes('['));
const users = lines.map(line => line.split('=')[0].trim());
const permissions = lines.map(line => line.split('=')[1].trim());
res.json({
users: users,
permissions: permissions,
count: users.length
});
} catch (error) {
res.status(500).json({
error: "Error reading repository permissions",
details: error.message
});
}
});
};

View File

@@ -0,0 +1,26 @@
const fs = require('fs');
const { execSync } = require('child_process');
module.exports = function(app, checkApiKey) {
app.get('/action/getrepos', checkApiKey, (req, res) => {
const repoPath = '/var/svn'; // Updated correct path
try {
// Read the repositories directory
const repos = fs.readdirSync(repoPath)
.filter(item => fs.statSync(`${repoPath}/${item}`).isDirectory())
.filter(item => fs.existsSync(`${repoPath}/${item}/format`)); // Verify it's a SVN repo
res.json({
repositories: repos,
count: repos.length
});
} catch (error) {
res.status(500).json({
error: "Error reading repositories",
details: error.message
});
}
});
};

View File

@@ -0,0 +1,49 @@
const fs = require('fs');
module.exports = function (app, checkApiKey) {
// Récupération des groupes SVN
app.get('/action/getuseringroup', checkApiKey, (req, res) => {
const authzFilePath = '/etc/apache2/dav_svn.authz';
const groupName = req.query.group;
if (!groupName) {
return res.status(400).json({ error: "Missing group parameter" });
}
try {
const fileContent = fs.readFileSync(authzFilePath, 'utf8');
const groupsSection = fileContent.split('[groups]')[1];
if (!groupsSection) {
return res.json({
users: [],
count: 0
});
}
const groupLine = groupsSection
.split('\n')
.find(line => line.startsWith(groupName + ' ='));
if (!groupLine) {
return res.json({
users: [],
count: 0
});
}
const users = groupLine.split('=')[1].split(',').map(user => user.trim());
res.json({
users: users,
count: users.length
});
} catch (error) {
res.status(500).json({
error: "Error reading groups file",
details: error.message
});
}
});
};

View File

@@ -0,0 +1,29 @@
const fs = require('fs');
module.exports = function(app, checkApiKey) {
app.get('/action/getusers', checkApiKey, (req, res) => {
const passwdFilePath = '/etc/apache2/dav_svn.passwd';
try {
const fileContent = fs.readFileSync(passwdFilePath, 'utf8');
const users = fileContent
.split('\n')
.filter(line => line.trim() !== '')
.map(line => {
const username = line.split(':')[0];
return username;
});
res.json({
users: users,
count: users.length
});
} catch (error) {
res.status(500).json({
error: "Error reading users file",
details: error.message
});
}
});
};

View File

@@ -0,0 +1,64 @@
const fs = require('fs');
const apacheMd5 = require('apache-md5');
module.exports = function(app, getToken) {
app.post('/action/login', (req, res) => {
const { username, password } = req.body;
if (!username || !password) {
return res.status(400).send('Username and password are required');
}
const passwdFilePath = '/etc/apache2/dav_svn.passwd';
const authzFilePath = '/etc/apache2/dav_svn.authz';
try {
const passwdContent = fs.readFileSync(passwdFilePath, 'utf8');
const userLine = passwdContent.split('\n').find(line => line.startsWith(`${username}:`));
if (!userLine) {
return res.status(401).send('Invalid credentials');
}
const storedHash = userLine.split(':')[1];
const calculatedHash = apacheMd5(password, storedHash);
if (storedHash !== calculatedHash) {
return res.status(401).send('Invalid credentials');
}
const authzContent = fs.readFileSync(authzFilePath, 'utf8');
const lines = authzContent.split('\n');
let isInAdminGroup = false;
let inGroupSection = false;
for (const line of lines) {
if (line.trim() === '[groups]') {
inGroupSection = true;
continue;
}
if (inGroupSection && line.startsWith('admin =')) {
const groupMembers = line.split('=')[1].trim().split(',').map(m => m.trim());
isInAdminGroup = groupMembers.includes(username);
break;
}
}
if (isInAdminGroup) {
res.json({
authenticated: true,
isAdmin: true,
token: getToken()
});
} else {
res.json({
authenticated: true,
isAdmin: false
});
}
} catch (error) {
res.status(500).send('Authentication failed');
}
});
};

View File

@@ -0,0 +1,35 @@
const fs = require('fs');
module.exports = function(app, checkApiKey) {
app.post('/action/newgroup', checkApiKey, (req, res) => {
const { groupName, users } = req.body;
if (!groupName || !users || !Array.isArray(users)) {
return res.status(400).send('Group name and list of users are required');
}
const authzFilePath = '/etc/apache2/dav_svn.authz'; // Updated path
fs.readFile(authzFilePath, 'utf8', (err, data) => {
if (err) {
return res.status(500).send(`Error reading authz file: ${err}`);
}
const groupSection = `${groupName} = ${users.join(', ')}`;
let updatedData = data;
const groupRegex = new RegExp(`^${groupName}\\s*=.*$`, 'm');
if (groupRegex.test(data)) {
updatedData = updatedData.replace(groupRegex, groupSection);
} else {
const groupsSectionRegex = /^\[groups\][\s\S]*?(?=\[|$)/m;
if (groupsSectionRegex.test(data)) {
updatedData = updatedData.replace(groupsSectionRegex, `$&\n${groupSection}`);
} else {
updatedData += `\n[groups]\n${groupSection}`;
}
}
fs.writeFile(authzFilePath, updatedData, 'utf8', (err) => {
if (err) {
return res.status(500).send(`Error writing authz file: ${err}`);
}
res.send(`Group ${groupName} created/updated successfully with users: ${users.join(', ')}`);
});
});
});
};

View File

@@ -0,0 +1,57 @@
const { exec } = require('child_process');
const fs = require('fs');
const path = require('path');
module.exports = function(app, checkApiKey) {
app.post('/action/newrepo', checkApiKey, (req, res) => {
const repoName = req.body.repoName;
if (!repoName) {
return res.status(400).send('Repo name is required');
}
const repoPath = `/var/svn/${repoName}`;
const cmd = `svnadmin create ${repoPath}`;
exec(cmd, async (err, stdout, stderr) => {
if (err) {
return res.status(500).send(`Error creating repo: ${stderr}`);
}
try {
await setPermissions(repoName);
await updateAuthzFile(repoName);
res.send({
message: `Repository ${repoName} created successfully`,
apiKey: process.env.API_KEY
});
} catch (error) {
res.status(500).send(`Error setting permissions: ${error}`);
}
});
});
async function setPermissions(repo) {
try {
const svnReposPath = `/var/svn/${repo}`;
const chmodCmd = `chmod -R 775 ${svnReposPath}`;
const chownCmd = `chown -R www-data:www-data ${svnReposPath}`;
await executeCommand(chmodCmd);
await executeCommand(chownCmd);
console.log('Permissions updated successfully.');
} catch (error) {
console.error('Error setting permissions:', error);
throw error;
}
}
function executeCommand(cmd) {
return new Promise((resolve, reject) => {
exec(cmd, (error, stdout, stderr) => {
if (error) {
reject(`Error executing command: ${cmd}\n${stderr}`);
} else {
resolve(stdout);
}
});
});
}
};

View File

@@ -0,0 +1,20 @@
const fs = require('fs');
const apacheMd5 = require('apache-md5');
module.exports = function(app, checkApiKey) {
app.post('/action/newuser', checkApiKey, (req, res) => {
const { username, password } = req.body;
if (!username || !password) {
return res.status(400).send('Username and password are required');
}
const passwdFilePath = '/etc/apache2/dav_svn.passwd';
const hashedPassword = apacheMd5(password); // Hacher le mot de passe au format APR1-MD5
const userLine = `${username}:${hashedPassword}`;
fs.appendFile(passwdFilePath, `${userLine}\n`, (err) => {
if (err) {
return res.status(500).send(`Error updating passwd file: ${err}`);
}
res.send(`User ${username} created successfully`);
});
});
};

View File

@@ -0,0 +1,69 @@
const fs = require('fs');
module.exports = function(app, checkApiKey) {
// Route pour supprimer un utilisateur ou un groupe d'un dépôt
app.post('/action/removepermrepo', checkApiKey, async (req, res) => {
try {
const { repoName, userOrGroup } = req.body;
if (!repoName || !userOrGroup) {
return res.status(400).json({ error: "Missing required parameters" });
}
await removeAuthzEntry(repoName, userOrGroup);
res.json({ message: `Permissions removed successfully for ${userOrGroup} on ${repoName}` });
} catch (error) {
console.error('Error in removepermrepo:', error);
res.status(500).json({ error: error.message });
}
});
};
// Fonction pour supprimer une entrée dans le fichier authz
async function removeAuthzEntry(repoName, userOrGroup) {
const authzFilePath = '/etc/apache2/dav_svn.authz';
try {
if (!fs.existsSync(authzFilePath) || !fs.lstatSync(authzFilePath).isFile()) {
throw new Error(`${authzFilePath} is not a valid file.`);
}
let data = fs.readFileSync(authzFilePath, 'utf8');
const repoSection = `[/${repoName}]`;
if (!data.includes(repoSection)) {
throw new Error(`Repository ${repoName} not found in authz file.`);
}
// Split le contenu du fichier en lignes
const lines = data.split('\n');
let repoSectionIndex = lines.findIndex(line => line.trim() === repoSection);
let sectionEnd = lines.slice(repoSectionIndex + 1).findIndex(line => line.startsWith('[')) + repoSectionIndex + 1;
if (sectionEnd <= repoSectionIndex) sectionEnd = lines.length;
// Format de l'entrée utilisateur/groupe
const entryPrefix = userOrGroup.startsWith('@') ? '' : '';
const entryToRemove = `${entryPrefix}${userOrGroup} =`;
// Trouve et supprime l'entrée utilisateur/groupe
const entryIndex = lines.findIndex((line, index) => {
return index > repoSectionIndex &&
index < sectionEnd &&
line.trim().startsWith(entryToRemove);
});
if (entryIndex !== -1) {
lines.splice(entryIndex, 1);
// Écrit les modifications dans le fichier
fs.writeFileSync(authzFilePath, lines.join('\n'));
console.log(`Permissions removed for ${userOrGroup} on repository ${repoName}`);
} else {
throw new Error(`User or group ${userOrGroup} not found in repository ${repoName}.`);
}
} catch (error) {
console.error('Error removing authz entry:', error);
throw error;
}
}

View File

@@ -0,0 +1,74 @@
const fs = require('fs');
module.exports = function(app, checkApiKey) {
app.post('/action/setpermrepo', checkApiKey, async (req, res) => {
try {
const { repoName, userOrGroup, permission } = req.body;
if (!repoName || !userOrGroup || !permission) {
return res.status(400).json({ error: "Missing required parameters" });
}
// Validate permission value
if (!['r', 'rw'].includes(permission)) {
return res.status(400).json({ error: "Permission must be 'r' or 'rw'" });
}
await updateAuthzFile(repoName, userOrGroup, permission);
res.json({ message: `Permissions updated successfully for ${userOrGroup} on ${repoName}` });
} catch (error) {
console.error('Error in setpermrepo:', error);
res.status(500).json({ error: error.message });
}
});
};
async function updateAuthzFile(repoName, userOrGroup, permission) {
const authzFilePath = '/etc/apache2/dav_svn.authz';
try {
if (!fs.existsSync(authzFilePath) || !fs.lstatSync(authzFilePath).isFile()) {
throw new Error(`${authzFilePath} is not a valid file.`);
}
let data = fs.readFileSync(authzFilePath, 'utf8');
const repoSection = `[/${repoName}]`;
if (!data.includes(repoSection)) {
// If repo section doesn't exist, create it
data += `\n${repoSection}\n`;
}
// Split the file content into lines
const lines = data.split('\n');
let repoSectionIndex = lines.findIndex(line => line.trim() === repoSection);
let sectionEnd = lines.slice(repoSectionIndex + 1).findIndex(line => line.startsWith('[')) + repoSectionIndex + 1;
if (sectionEnd <= repoSectionIndex) sectionEnd = lines.length;
// Format the user/group entry
const entryPrefix = userOrGroup.startsWith('@') ? '' : '';
const newEntry = `${entryPrefix}${userOrGroup} = ${permission}`;
// Remove existing entry if it exists
const existingEntryIndex = lines.findIndex((line, index) => {
return index > repoSectionIndex &&
index < sectionEnd &&
line.trim().startsWith(`${entryPrefix}${userOrGroup} =`);
});
if (existingEntryIndex !== -1) {
lines[existingEntryIndex] = newEntry;
} else {
lines.splice(repoSectionIndex + 1, 0, newEntry);
}
// Write back to file
fs.writeFileSync(authzFilePath, lines.join('\n'));
console.log(`Permissions updated for ${userOrGroup} on repository ${repoName}`);
} catch (error) {
console.error('Error updating authz file:', error);
throw error;
}
}

32
nodejs/commande/utils.js Normal file
View File

@@ -0,0 +1,32 @@
const { exec } = require('child_process');
function executeCommand(cmd) {
return new Promise((resolve, reject) => {
exec(cmd, (error, stdout, stderr) => {
if (error) {
reject(`Error executing command: ${cmd}\n${stderr}`);
} else {
resolve(stdout);
}
});
});
}
async function setPermissions(repo) {
try {
const svnReposPath = `/var/svn/${repo}`;
const chmodCmd = `chmod -R 775 ${svnReposPath}`;
const chownCmd = `chown -R www-data:www-data ${svnReposPath}`;
await executeCommand(chmodCmd);
await executeCommand(chownCmd);
console.log('Permissions updated successfully.');
} catch (error) {
console.error('Error setting permissions:', error);
}
}
module.exports = {
setPermissions,
};