Init commit. Practically everything done. Supports apt and pacman.

This commit is contained in:
Lev Zagatov 2024-09-07 12:59:39 +03:00
commit f0a9d8c70f
7 changed files with 508 additions and 0 deletions

49
gencmd.js Normal file
View File

@ -0,0 +1,49 @@
var pacman_f = document.getElementById("pacman");
var username_f = document.getElementById("username");
var password_f = document.getElementById("pass");
var db_password_f = document.getElementById("dbpass");
var output_f = document.getElementById("output");
var cmd_el = document.getElementById("cmd");
var username, password, db_password, pacman, cmd;
function sanitize(s) {
return s
.replaceAll("\\", "\\\\")
.replaceAll('"', '\\"')
.replaceAll("'", "\\'")
.replaceAll("$", "\\$");
}
function generate_cmd(e) {
install_deps = pacman_f.value;
username = sanitize(username_f.value);
password = sanitize(password_f.value);
db_password = sanitize(db_password_f.value);
if (username && password && db_password) {
cmd_el.style.display = "block";
} else {
cmd_el.style.display = "none";
console.log("empty");
return;
}
clone_repo =
"git clone -b prototype https://git.thedroth.rocks/DecUp/platform /opt/decup";
run_ansible =
"ansible-playbook /opt/decup/install.yml --extra-vars 'adminpanel=\\\"" +
username +
'\\" panelpassword=\\"' +
password +
'\\" dbpassword=\\"' +
db_password +
"\\\"'";
cmd = install_deps + " && " + clone_repo + " && " + run_ansible;
output_f.value = 'sudo sh -c "' + cmd + '"';
resize_textarea(output_f);
}
username_f.oninput = generate_cmd;
pacman_f.onchange = generate_cmd;
password_f.oninput = generate_cmd;
db_password_f.oninput = generate_cmd;

96
index.html Normal file
View File

@ -0,0 +1,96 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>DecUp</title>
<link href="style.css" rel="stylesheet" />
</head>
<body>
<div id="header">
<div class="container">
<h1>DecUp</h1>
<a class="primary" href="install.html">Установить</a>
</div>
</div>
<div id="main">
<div class="container">
<h2>Ваши сервисы — наша забота</h2>
<p>
DecUp поможет развернуть <strong>собственную</strong> инфраструктуру
легче, чем когда-либо.
</p>
<div class="block">
<h2>Зачем?</h2>
<p>
Два года назад блокировки Facebook<span class="ref">*</span>,
Instagram<span class="ref">*</span> и Twitter были
<strong>немыслимыми</strong>.
</p>
<p>Также как и вычистка <strong>банков</strong> из Play Store.</p>
<p>Также как и «<strong>замедление</strong>» YouTube.</p>
<p>
Уже понятно, что будущее России
<strong>закрыто чёрной плашкой</strong>.
</p>
<p class="ref">
* — принадлежит корпорации Meta, признанной в РФ экстремистской
</p>
</div>
<div class="block">
<h2>Что делать?</h2>
<p>
Сейчас набирают популярность
<strong>децентрализованные сервисы</strong>.
</p>
<p>
Их крайне сложно заблокировать: всё раздроблено на маленькие
сервера, которые можно создать <strong>за минуты</strong>.
</p>
<p>
Они предлагают <strong>полный контроль</strong> за вашими данными,
будь то секрет компании или план по захвату мира.
<span class="ref">;)</span>
</p>
</div>
<div class="block">
<h2>Почему мы?</h2>
<h3>Легковесность:</h3>
<p class="details">
DecUp оптимизирован, чтобы не мешать вам пользоваться сервисами.
</p>
<address>лучше, чем SelfPrivacy</address>
<h3>Контроль:</h3>
<p class="details">
DecUp не привязан к чужому компьютеру. С нами вы можете выбрать,
где хранятся ваши данные.
</p>
<address>лучше, чем Yunohost</address>
<h3>Отделённость:</h3>
<p class="details">
DecUp — <strong>не ОС</strong>. После установки программы сервером
можно продолжать пользоваться <strong>как угодно</strong>.
</p>
<h3>Простота установки:</h3>
<p class="details">
Единственное, что нужно — Unix-подобная ОС
<strong>с правами root</strong>.
</p>
<h3>Поддержка:</h3>
<p class="details">
Большинство подобных проектов предоставляются «как есть» (as is).
Мы предлагаем <strong>техподдержку</strong> по различным вопросам,
связанным с DecUp.
</p>
</div>
<a class="full primary" href="install.html">Установить</a>
</div>
</div>
</body>
</html>

99
install.html Normal file
View File

@ -0,0 +1,99 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Установка DecUp</title>
<link href="style.css" rel="stylesheet" />
</head>
<body>
<div id="header">
<div class="container">
<h1>DecUp</h1>
</div>
</div>
<div id="main">
<noscript class="container" style="display: block">
<h2>У вас отключён JavaScript</h2>
<p>
В связи с этим автоматическая генерация команды установки
<strong>не работает</strong>.
</p>
<p>
Попробуйте включить JavaScript и перезагрузить страницу или
<a href="docs/install.html">установите DecUp вручную</a>.
</p>
</noscript>
<div id="wizard" class="container" style="display: none">
<script>
document.getElementById("wizard").style.display = "block";
</script>
<h2>Установка</h2>
<p>
После заполнения <strong>всех</strong> полей внизу появится команда,
устанавливающая DecUp. Вставьте её в терминал.
</p>
<p>
Мы <strong>не собираем</strong> никакие данные. Команда генерируется
локально.
</p>
<label for="pacman">Менеджер пакетов</label>
<select id="pacman">
<option value="apt-get update && apt-get install git ansible -y">
apt (Debian, Ubuntu, Mint, ALT, Rosa)
</option>
<option value="pacman -Sy --noconfirm git ansible">
pacman (Arch, Manjaro, Endeavour OS)
</option>
</select>
<label for="username">Логин</label>
<input class="code" id="username" placeholder="Введите логин..." />
<label for="pass">Пароль</label>
<div class="password-wrapper">
<input
class="code password"
name="password"
id="pass"
placeholder="Введите пароль..." />
</div>
<label for="dbpass">Пароль базы данных</label>
<div class="password-wrapper">
<input
class="code password"
name="db_password"
id="dbpass"
placeholder="Введите пароль БД..." />
</div>
<div id="cmd" style="display: none">
<label for="output">Команда</label>
<textarea class="tertiary code" id="output"></textarea>
<button
onclick="copyText = document.getElementById('output'); copyText.select(); copyText.setSelectionRange(0, 99999); navigator.clipboard.writeText(copyText.value);"
class="primary"
style="width: 100%; margin-top: 8px">
Скопировать
</button>
</div>
<script
src="password.js"
data-alt="Показать/скрыть пароль"
data-type="password"
data-icons="."></script>
<script src="textarea.js"></script>
<script src="gencmd.js"></script>
</div>
</div>
</body>
</html>

48
password.js Normal file
View File

@ -0,0 +1,48 @@
var password_fields = document.getElementsByClassName("password");
var password_toggle_buttons = [];
for (let i = 0; i < password_fields.length; i++) {
try {
password_fields.item(i).type = "password"; // ie8 fails here
password_toggle_buttons.push(document.createElement("button"));
password_toggle_buttons[i].setAttribute(
"style",
"position: relative; top: -38px; right: 2px; float: right; padding: 6px 14px; height: 36px; border: 0"
);
password_toggle_buttons[i].setAttribute(
"class",
"tertiary no-text button"
);
password_toggle_buttons[i].onclick = function () {
showPass(password_fields.item(i).id);
};
password_toggle_buttons[i].type = "button";
var me = document.querySelector("script[data-type='password']");
var icons = me.getAttribute("data-icons");
var alt = me.getAttribute("data-alt");
var img = document.createElement("img");
img.setAttribute("src", icons + "/reveal.png");
img.setAttribute("alt", alt);
password_toggle_buttons[i].appendChild(img);
password_fields
.item(i)
.insertAdjacentElement("afterend", password_toggle_buttons[i]);
} catch (e) {
window.console.log(e);
window.console.log("Browser doesn't support modifying the type of input.");
window.console.log("Password field left visible.");
}
}
function showPass(field_id) {
var password_field = document.getElementById(field_id);
if (password_field.type === "password") {
password_field.type = "text";
} else {
password_field.type = "password";
}
}

BIN
reveal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

199
style.css Normal file
View File

@ -0,0 +1,199 @@
@import url("https://fonts.googleapis.com/css2?family=Golos+Text:wght@400..700&family=JetBrains+Mono&display=swap");
html {
background-color: #333;
}
body,
h1,
h2,
h3,
label,
p,
button,
select,
input {
font-family: "Golos Text", Helvetica, Arial, sans-serif;
text-rendering: optimizeLegibility;
font-size: 16px;
color: #fff;
margin: 0;
}
h1,
h2 {
font-size: 24px;
}
label,
strong {
font-weight: 600;
}
#header {
background-color: #505050;
padding: 16px 32px;
}
.container {
max-width: 800px;
margin: 0 auto;
}
#main {
padding: 32px;
padding-top: 0;
}
#main > .container > * {
margin-top: 32px;
}
.block {
margin-left: -16px;
margin-right: -16px;
padding: 16px;
padding-top: 0;
background-color: #505050;
border: 3px #808080 solid;
border-radius: 16px;
}
.block > * {
margin-top: 16px;
}
span.ref {
color: #ccc;
}
p.ref {
color: #ccc;
font-size: 12px;
}
.primary {
background-color: #354fcf;
color: #fff;
text-decoration: none;
font-weight: 700;
border: 0;
border-radius: 16px;
padding: 8px 16px;
line-height: 24px;
}
#header a.primary {
float: right;
}
#header h1 {
display: inline;
line-height: 40px;
}
p.details {
margin-top: 0;
margin-left: 16px;
}
address {
font-style: normal;
color: #ccc;
float: right;
}
.full {
display: block;
text-align: center;
}
a {
color: #00bcff;
}
input,
select,
textarea {
border-radius: 16px;
height: 24px;
font-size: 16px;
line-height: 16px;
padding: 6px 14px;
height: 40px;
box-sizing: border-box;
min-height: 24px;
width: 100%;
display: block;
line-height: 24px;
}
.tertiary,
input,
select,
textarea {
background-color: #505050;
border-color: #808080;
color: #fff;
}
.tertiary:hover,
input:hover,
select:hover,
textarea:hover,
#header .btns img:hover {
background-color: #4c4c4c;
}
.tertiary:focus,
#header .btns img:focus {
background-color: #4c4c4c;
}
:focus {
border-color: #ccc;
outline: none;
}
.tertiary:active,
#header .btns img:active {
background-color: #474747;
}
input,
select,
textarea {
border: 2px solid #808080;
text-decoration: none;
}
input,
select,
textarea,
.password-wrapper {
margin: 0 !important;
}
label {
margin-bottom: 4px;
display: inline-block;
}
.button.no-text > img {
width: 24px;
height: 24px;
margin-left: 0;
}
button {
border-radius: 16px;
}
.code {
font-family:
JetBrains Mono,
Consolas,
"Courier New",
Courier,
monospace;
}

17
textarea.js Normal file
View File

@ -0,0 +1,17 @@
const tx = document.getElementsByTagName("textarea");
for (let i = 0; i < tx.length; i++) {
tx[i].setAttribute(
"style",
tx[i].getAttribute("style") +
";height:" +
(tx[i].scrollHeight + 4) +
"px;overflow-y:hidden;"
);
tx[i].addEventListener("change", resize_textarea, false);
}
function resize_textarea(t) {
t = t instanceof Element ? t : this;
t.style.height = "auto";
t.style.height = t.scrollHeight + 4 + "px";
}