
Линус Торвальдс: "Я создаю Linux не ради денег, а потому что это весело. Это как играть в Lego, только на уровне операционной системы."
Эти слова как нельзя лучше отражают дух сообщества открытого исходного кода, где разработка — это не просто работа, а страсть и возможность сделать мир лучше.
Именно с этой цитаты у меня в голове живет идея создать что-то для мирового свободного сообщества.
Сегодня я хочу рассказать о своем проекте — современном личном кабинете, который интегрируется с модулями ISP system, такими как Billmanager и VMmanager. Этот проект будет распространяться абсолютно бесплатно под лицензией GNU GPL, и я надеюсь, что он станет моим вкладом в сообщество свободного ПО.
Что делает мой dashboard blackmore уникальным?
User-friendly дизайн:
Современный и минималистичный интерфейс, который делает работу с Billmanager и другими модулями простой и приятной. Хочу сделать комплимент организации timeweb за лучший и приятный дизайн управления системой isp.Интеграция с ISP system:
Полная совместимость с популярными модулями, такими как Billmanager, VMmanager и другими, что позволяет управлять всеми процессами из одного места.Открытый исходный код:
Проект будет распространяться под лицензией GNU GPL, что означает свободу использования, модификации и распространения. Репозитойрий и figma макет будут доступны для загрузки.Сообщество и развитие:
Я надеюсь, что мой проект станет отправной точкой для других разработчиков, которые захотят внести свой вклад и сделать его еще лучше.

Глава: Техническая составляющая: почему Node.js?
Простота и доступность кода
Одним из ключевых принципов моего проекта является простота. Я убежден, что если код будет слишком сложным, то сообщество вокруг него не сформируется. Вместо этого, пользователи будут просто использовать "дефолтную" версию, не внося изменений и не создавая интересных форков. Чтобы избежать этого, я уделяю особое внимание следующим аспектам:
Чистый и понятный код:
Я стараюсь писать код, который легко читать и понимать. Это включает в себя использование понятных имен переменных и функций, а также следование принципам DRY (Don't Repeat Yourself) и KISS (Keep It Simple, Stupid).Глубокие комментарии:
Каждая сложная часть кода сопровождается подробными комментариями, которые объясняют, что происходит и почему это сделано именно так. Это помогает другим разработчикам быстрее разобраться в проекте и внести свои улучшения.Модульная структура:
Проект разделен на модули, каждый из которых отвечает за определенную функциональность. Это не только упрощает разработку, но и позволяет другим разработчикам легко добавлять новые функции или изменять существующие.Документация:
Помимо комментариев в коде, я создаю подробную документацию, которая объясняет, как настроить проект, как он работает и как можно его расширить. Это особенно важно для новичков, которые только начинают знакомиться с проектом.Примеры использования:
В проекте будут включены примеры использования API и других ключевых функций. Это поможет разработчикам быстрее понять, как интегрировать dashboard в свои проекты.
Почему это важно?
Как сказал один из разработчиков открытого ПО: "Простота — это не отсутствие сложности, а ясность и понятность." Я верю, что только простой и хорошо документированный проект может привлечь сообщество и вдохновить других на создание форков. Если код будет слишком сложным, то даже самые заинтересованные разработчики могут отказаться от участия в проекте.
// Этот модуль отвечает за интеграцию с Billmanager API
// Используется библиотека Axios для отправки HTTP-запросов
const axios = require('axios');
/**
* Функция для получения информации о счете пользователя
* @param {string} userId - ID пользователя
* @returns {Promise} - Возвращает данные о счете или ошибку
*/
async function getUserBill(userId) {
try {
const response = await axios.get(`https://api.billmanager.com/user/${userId}/bill`);
return response.data;
} catch (error) {
console.error('Ошибка при получении данных:', error);
throw error;
}
}
module.exports = { getUserBill };
Простота и доступность кода — это не просто пожелание, это необходимость для успешного open-source проекта. Я стремлюсь сделать свой dashboard максимально понятным и дружелюбным для других разработчиков, чтобы каждый мог легко внести свой вклад или создать собственный форк. В конце концов, именно сообщество делает open-source проекты по-настоящему живыми и развивающимися.

Глава: Реализация авторизации в dashboard
Авторизация — это ключевой элемент любого приложения, особенно если оно взаимодействует с внешними системами, такими как Billmanager. В этой главе я расскажу, как будет реализована авторизация в моем dashboard, начиная с верстки макета и заканчивая интеграцией с API Billmanager.
1. Верстка макета авторизации
Макет авторизации был создан в Figma и включает следующие элементы:
Поля ввода для email и пароля.
Кнопка "Войти".
Ссылки "Забыли пароль?" и "Регистрация".
Для верстки этого макета я использую React (или Vue.js, если вы предпочитаете этот фреймворк) и библиотеку компонентов, такую как Material-UI или Tailwind CSS, чтобы сделать интерфейс современным и отзывчивым.
Пример верстки на React:
import React, { useState } from 'react';
const LoginForm = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [rememberMe, setRememberMe] = useState(false);
const handleLogin = async () => {
// Логика авторизации через API
console.log('Email:', email, 'Password:', password);
};
return (
<div className="min-h-screen bg-gray-100 flex items-center justify-center">
<div className="bg-white p-8 rounded-lg shadow-md w-80">
{/* Заголовок */}
<div className="text-center mb-8">
<div className="text-2xl font-bold text-gray-800 mb-2">
BLACKMORE
<span className="text-blue-600">CLOUD</span>
</div>
<div className="text-sm text-gray-500">
GNU GPL DASHBOARD
</div>
<div className="mt-2 text-3xl text-gray-400">#BXoA</div>
</div>
{/* Поля ввода */}
<div className="space-y-4">
<input
type="email"
placeholder="Введите Email"
className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-400"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="password"
placeholder="Введите пароль"
className="w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-400"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
{/* Чекбокс и напоминание */}
<div className="flex items-center justify-between mt-4">
<label className="flex items-center space-x-2">
<input
type="checkbox"
checked={rememberMe}
onChange={(e) => setRememberMe(e.target.checked)}
className="form-checkbox h-4 w-4 text-blue-600"
/>
<span className="text-sm text-gray-600">Запомнить?</span>
</label>
<a href="#" className="text-sm text-blue-600 hover:underline">
Напомнить?
</a>
</div>
{/* Кнопка входа */}
<button
onClick={handleLogin}
className="w-full mt-6 bg-blue-600 text-white py-2 rounded-lg hover:bg-blue-700 transition-colors"
>
войти
</button>
{/* Регистрация */}
<div className="mt-4 text-center">
<span className="text-sm text-gray-600">НЕТ АККАУНТА? </span>
<a href="#" className="text-blue-600 hover:underline">РЕГИСТРАЦИЯ</a>
</div>
</div>
</div>
);
};
export default LoginForm;
Интеграция с API Billmanager
Для авторизации в Billmanager используется API, который поддерживает несколько методов. Я выбрал метод авторизации с использованием уникального номера сессии, так как он наиболее подходит для веб-приложений.
Шаги авторизации:
Отправка запроса на авторизацию:
Пользователь вводит email и пароль, которые отправляются на сервер Billmanager для получения номера сессии.Получение номера сессии:
Если авторизация успешна, сервер возвращает XML-документ с номером сессии.Использование номера сессии:
Номер сессии используется для всех последующих запросов к API Billmanager.
const axios = require('axios');
async function login(username, password) {
try {
const response = await axios.get('https://IP-адрес:1500/billmgr', {
params: {
out: 'xml',
func: 'auth',
username: username,
password: password,
},
});
// Парсим XML-ответ
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(response.data, 'text/xml');
const sessionId = xmlDoc.querySelector('auth').textContent;
console.log('Сессия успешно создана. ID сессии:', sessionId);
return sessionId;
} catch (error) {
console.error('Ошибка авторизации:', error);
throw error;
}
}
3. Хранение номера сессии
Номер сессии необходимо хранить на клиенте (например, в localStorage или cookies) и передавать с каждым запросом к API. Это можно сделать следующим образом:
// Сохраняем номер сессии в localStorage
localStorage.setItem('sessionId', sessionId);
// Используем номер сессии для запросов
async function makeRequest(func, params) {
const sessionId = localStorage.getItem('sessionId');
const response = await axios.get('https://IP-адрес:1500/billmgr', {
params: {
auth: sessionId,
out: 'xml',
func: func,
...params,
},
});
return response.data;
}
4. Завершение сессии
Чтобы завершить сессию пользователя, необходимо отправить запрос на удаление сессии:
async function logout(sessionId) {
try {
await axios.get('https://IP-адрес:1500/billmgr', {
params: {
func: 'session.delete',
elid: sessionId,
sok: 'ok',
},
});
console.log('Сессия успешно завершена.');
} catch (error) {
console.error('Ошибка завершения сессии:', error);
}
}
5. Обработка ошибок
Важно предусмотреть обработку ошибок, таких как:
Неверный email или пароль.
Истекший номер сессии.
Ограничения доступа.
Пример обработки ошибок:
try {
const sessionId = await login(email, password);
// Дальнейшие действия
} catch (error) {
if (error.response && error.response.status === 401) {
alert('Неверный email или пароль');
} else {
alert('Произошла ошибка. Попробуйте еще раз.');
}
}
Конечно в нашем дашборде будет мини-админ панель, что бы можно было автоматизировать процесс добавления и даже установки модулей isp.
Все в статье не возможно отобразить, надеюсь к следующей главе я завершу 40% кода и открою репозиторий для всех. Если Вам понравилась такая идея то сделайте подписку в Хабре, я расскажу много интересного. Самое основное на хабре это рейтинг, тут есть старички которые всегда минусуют, если уйду в сильный минус, то будет запрет на написание статей.
Комментарии (6)
zorn-v100500
17.02.2025 14:57// Используется библиотека Axios для отправки HTTP-запросов
const axios = require('axios');А что еще может делать
require('axios')
?/**
* Функция для получения информации о счете пользователя
* @param {string} userId - ID пользователя
* @returns {Promise} - Возвращает данные о счете или ошибку
*/
async function getUserBill(userId)
Да ладно, по названиям не понятно ?
КО рукоплещет (на самом деле возвращает промис, но да ладно).
...
Начал писать коментарий, а потом решил найти ссылку на код и наткнулся на
Для верстки этого макета я использую React (или Vue.js, если вы предпочитаете этот фреймворк)
ГПТ мусор в квадрате.
gavrilovegor519
17.02.2025 14:57Лучше Vaadin'а ничего нету :D
Пишешь фуллстек на Java (которая именно Java, а не JS), вёрстку + бэковую часть делаешь прям в Java-классах (никакой шаблонизации!) - а оно превращается во вполне себе фронт + бэк на Spring и React, который находится внутри JAR-файла с обычным спринговым томкатом. Достаточно просто ввести mvn package :)
gavrilovegor519
17.02.2025 14:57Лучше Vaadin'а ничего нету :D
Если что, я этот комментарий писал с некоторым сарказмом (о чём свидетельствует тот смайлик в конце). Идея писать сайт на "взрослом" ЯП конечно хороша, но у Vaadin есть недостаток - он тормозной, и плохо поддаётся автоматическому тестированию, а также не подходит под микросервисы точно.
semendyaevanton
17.02.2025 14:57сам юзаю продукты от испсистем и ни на что их не променяю, так что будет интересно ознакомиться с дашбордом. ждем-с
Prepodobnyi
Ждем всей семьей! Очень многообещающе.