Пояснительная записка к электронному журналу с использованием технологии Блокчейн, практическая часть: часть 3


Продолжаем.

2.2.3 PHP, часть 1

Эта часть находится в подпапке web директории проекта и имеет структуру:

add (папка с html файлами форм добавления):

1.1. assessment.html – добавление оценки

1.2. disciple.html — ученика

1.3. lactor.html — преподавателя

1.4. lesson.html — предмета

1.5. lesson\_topics.html — тем предмета.

Будет рассматриваться код одного файла, т. к. он везде идентичен
(отличаются только поля).

Js

2.1. helper.js — JS код веб-части;

2.2. jquery.min.js — jQuery (стандартная библиотека — рассматривать не
будем);

2.3. sjcl.min.js — jQuery библиотека шифрования и расшифровки данных.
Также код файла рассматривать не будем (её методы используются в
helper.js).

Add.php – файл добавления данных в блокчейн;

db.php — подключение к базе данных и функции работы с ней;

functions.php — файл функций (функция главной страницы, функция базы
данных и пр.)

index.php — основной файл: вызов функции homePage из functions.php и
вывод данных в html коде, вызов по Ajax op.php с контентом;

op.php — файл, вызываемый по Ajax. Получает данные: пользователя и
значение page, после чего производит проверку на соответствие
авторизовавшегося одному из пользователей и выводит данные в
зависимости от значения page;

style.css — файл стилей;

1\. Папка add

Формы сгенерированы при помощи моего сервиса
https://viz.dpos.space/custom.

Код формы из файла assessment.html

\<form id="istr-i52" class=">

\<p style="display: none>

\<label\>

Таблица\<br\>

\ \<br\>

\</label\>

\</p\>

\<fieldset\>

\<legend\>Данные\</legend\>

\<p\>

\<label\>

Дата (формат: 20191605(\<br\>

\ \<br\>

\</label\>

\</p\>

\<p\>

\<label\>

Предмет\<br\>

\ \<br\>

\</label\>

\</p\>

\<p\>

\<label\>

Ученик\<br\>

\ \<br\>

\</label\>

\</p\>

\<p\>

\<label\>

Оценка\<br\>

\ \<br\>

\</label\>

\</p\>

\</fieldset\>

\<p\>\<button\>Отправить\</button\>\</p\>

\</form\>

\<script\>\!function(){function
e(e){if(localStorage.getItem("login")&\&localStorage.getItem("PostingKey"))viz\_login=localStorage.getItem("login"),posting\_key=sjcl.decrypt(viz\_login+"\_postingKey",localStorage.getItem("PostingKey"));else
if(sessionStorage.getItem("login")&\&sessionStorage.getItem("PostingKey"))viz\_login=sessionStorage.getItem("login"),posting\_key=sjcl.decrypt(viz\_login+"\_postingKey",sessionStorage.getItem("PostingKey"));else{document.getElementById(e)&&(document.getElementById(e).style.display="none");var
t=document.createElement("div");t.innerHTML='\<form id="auth\_form"
action="index.html" >\<>\<strong\>Пожалуйста
авторизируйтесь\</strong\>\</p\>\<p\>\\</p\>\<p\>\\</p\>\<p\>\\</p\>\</form\>',document.getElementById(e).parentNode.insertAdjacentElement("beforeend",t),found"):(t=e\[o\],viz.config.set("websocket",t),viz.api.getDynamicGlobalPropertiesAsync().then(e=\>{console.log("found
working
node",t),localStorage.setItem("node",t)}).catch(e=\>{console.log("connection
error",t,e),n(o+1)}))};n(o)}(),e(t),document.querySelector(".generated-form").querySelector("button").disabled=\!1):(console.log("wait"),setTimeout(o,50))},0);document.querySelector(".generated-form").onsubmit=function(e){e.preventDefault(),this.querySelector("button").disabled=\!0;var
t=new
XMLHttpRequest;t.open("POST","https://viz.dpos.space/custom/json\_encode.php"),t.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),t.onload=function(){200===t.status?(console.log(t.responseText),viz.broadcast.custom(posting\_key,\[\],\[viz\_login\],document.querySelector(".generated-form").id,t.responseText,function(e,t){e?alert("Ошибка:
"+e):(alert("Ок. custom
отправлен"),console.log(t)),docum

ent.querySelector(".generated-form").querySelector("button").disabled=\!1})):alert("Request
failed. Returned status of "+t.status)},t.send(function(e){for(var
t=\[\],o=0;o\<e.elements.length;o++){ return
t.join("&")}(document.querySelector(".generated-form")))}}()\</script\>

Поля добавления оценки: первое в скрытом абзаце — название таблицы,
дата, предмет, ученик, оценка.

Далее идёт js код, который вызывает форму авторизации, если не
авторизован, который обращается к ajax скрипту на
viz.dpos.space/custom, который принимает данные и вызывает скрипт
отправки данных в блокчейн.

Функция checkWorkingNode

Выбирает паблик-Ноду блокчейна, к которой подключиться:

function checkWorkingNode() {

const NODES = \[

"wss://solox.world/ws",

"wss://vizlite.lexai.host/",

\];

let node = localStorage.getItem("node") || NODES\[0\];

const idx = Math.max(NODES.indexOf(node), 0);

let checked = 0;

const find = (idx) 😕> {

if (idx \>= NODES.length) {

idx = 0;

}

if (checked \>= NODES.length) {

alert("no working nodes found");

return;

}

node = NODES\[idx\];

console.log("check", idx, node);

viz.config.set("websocket", node);

try {

viz.api.stop();

} catch(e) {

}

let timeout = false;

let timer = setTimeout(() 😕> {

console.log("timeout", NODES\[idx\])

timeout = true;

find(idx + 1);

}, 3000);

viz.api.getDynamicGlobalPropertiesAsync()

.then(props 😕> {

if(\!timeout) {

check = props.head\_block\_number;

console.log("found working node", node);

localStorage.setItem("node", node);

clearTimeout(timer);

}

})

.catch(e 😕> {

console.log("connection error", node, e);

find(idx + 1);

});

}

find(idx);

}

checkWorkingNode();

Проверяет работоспособность текущей паблик-Ноды, беря её из
localStorage, используя getDynamicGlobalPropertiesAsync (Если возвращает
ошибку или пустое значение, значит не всё ок). Если ошибка, проверяет
паблик-Ноды из списка массива nodes. Когда находится работающая,
выбирается и добавляется в localStorage.

Ниже создаются переменные

var viz\_login = ''; // Логин

var posting\_key = ''; // Регулярный (ранее постинг) ключ

Функция getUrlVars

Берёт из url get запросы, позволяет с ними работать.

function getUrlVars() {

var vars = {};

var parts =
window.location.href.replace(/\[?&\]+(\[^=&\]+)=(\[^&\]\*)/gi,
function(m,key,value) {

vars\[key\] = value;

});

return vars;

}

Async функция ajaxSend

Отправляет ajax запрос:

async function ajaxSend(login) {

if (getUrlVars()) { // Проверка наличия get параметров

var data = getUrlVars(); // Назначение массива параметров переменной
data

page = data\['page'\].toLowerCase(); // Назначение переменной page GET
параметра соответствующего с переводом в нижний регистр

action = (data\['action'\] \!== undefined) ? "\&action=" +
data\["action"\] : ''; // Проверка на наличие GET action и добавление
значения или, если его нет, создание пустой переменной.

lactor = (data\['lactor'\] \!== undefined) ? "\&lactor=" +
data\["lactor"\] : ''; // Проверка наличия значения GET lactor.
Используется при удалении.

disciple = (data\['disciple'\] \!== undefined) ? "\&disciple=" +
data\["disciple"\] : ''; // Проверка disciple с возвратом значения, если
есть.

lesson = (data\['lesson'\] \!== undefined) ? "\&lesson=" +
data\["lesson"\] : '';// Также с lesson .

$(document).ready(function() { // jQuery: Вызывается при готовности
документа.

$(".content").load("op.php", "user=" + login + "\&page=" + page + action

  • lactor + disciple + lesson); // Отправка ajax запроса со всеми
    возможными переменными.

    });

    }

    }

Функция async userAuth

async function userAuth() {

let login = $('\#this\_login').val(); // Получаем логин из поля

let posting = $('\#this\_posting').val(); // Также и ключ

if (localStorage.getItem('PostingKey')) { // Если есть ключ в
localStorage

var isPostingKey = sjcl.decrypt(login + '\_postingKey',
localStorage.getItem('PostingKey')); // Расшифровываем ключ, используя
логин, слово \_postingKey и зашифрованный ключ из localStorage.

} else if (sessionStorage.getItem('PostingKey')) { // Если кл

юч в
sessionStorage

var isPostingKey = sjcl.decrypt(login + '\_postingKey',
sessionStorage.getItem('PostingKey')); // Также расшифровываем, но берём
из сессий.

} else { // Иначе

var isPostingKey = posting; // Берём значение из переменной

}

var resultIsPostingWif = viz.auth.isWif(isPostingKey); // Проверяем, что
ключ валиден.

if (resultIsPostingWif === true) { // Если это так

const account\_approve = await viz.api.getAccountsAsync(\[login\]); //
вызываем информацию о пользователе

const public\_wif = viz.auth.wifToPublic(isPostingKey); // Приобразуем
полученный приватный ключ в публичный

let posting\_public\_keys = \[\]; // Создаём массив публичных ключей

if (account\_approve.length \> 0) { // Если данные аккаунта есть

for (key of account\_approve\[0\].regular\_authority.key\_auths) { //
Проходим по массиву ключей публичных

posting\_public\_keys.push(key\[0\]); // Добавляем их в массив
posting\_public\_keys.

}

} else {

window.alert('Вероятно, аккаунт не существует. Просьба проверить
введённый логин.'); // Иначе, если данных аккаунта нет, вывести
это сообщение.

}

if (posting\_public\_keys.includes(public\_wif)) { // Далее проверяем,
есть ли наш публичный ключ в массиве posting\_public\_keys. Если
находит, делаются дальнейшие действия.

var isSavePosting = document.getElementById('isSavePosting'); // Смотрит
элемент с чекбоксом в форме авторизации

if (isSavePosting.checked) { // Если отмечен

localStorage.setItem('login', login); // Добавляем логин в localStorage

localStorage.setItem('PostingKey', sjcl.encrypt(login + '\_postingKey',
posting)); // и в зашифрованном виде постинг ключ.

} else { // Если не отмечен.

sessionStorage.setItem('login', login); // добавляется логин в Сессии

sessionStorage.setItem('PostingKey', sjcl.encrypt(login +
'\_postingKey', posting)); // ч.

}

viz\_login = login; // Добавляется логин в переменную

posting\_key = isPostingKey; // и ключ.

} else {

window.alert('Постинг ключ не соответствует пренадлежащему аккаунту.');
// Если в массиве ключей нашего public нет, выводится это сообщение.

}

} else {

window.alert('Постинг ключ имеет неверный формат. Пожалуйста, попробуйте
ещё раз.'); // Если формат неверен, выводится такое сообщение (относится
к resultIsPostingWif).

}

if (\!viz\_login && \!posting\_key) { // Если нет значений у переменных
логина и ключа

$('\#delete\_posting\_key').css("display", "none"); // Скрывается блок с
кнопкой выхода.

$('\#unblock\_form').css("display", "block"); // Отображается блок с
формой входа.

} else {

$('\#unblock\_form').css("display", "none"); // иначе скрывается форма
входа

$('\#delete\_posting\_key').css("display", "block"); // а ссылка выхода
отображается.

jQuery("\#delete\_posting\_key").html('\<>Выйти\</a\>\</p\>');// Также выводится в
соответствующем элементе ссылка выхода, удаляющая из localStorage
логин и ключ.

ajaxSend(localStorage.getItem('login')); // и вызывается функция
отправки ajax.

}

} // end userAuth

Всё

Благодарю за внимание. С вами был незрячий автор, программист и делегат @denis-skripnik. До встречи в новых постах.


Comments 3


Фонд БОД сделал репост.
Ваше творчество в ленте.
Наша лента в telegram.
)
Вы являетесь участником проекта БОД, поэтому все ваши посты
размещаются в ленте репостов фонда. Если не желаете получать
апвот фонда и этот комментарий, ставьте тег nobod.
06.08.2019 17:01
0

Здравствуйте, @denis-skripnik. Вы получили 100% апвот от UPRomo за сожженные GBG. Продвигали сей пост в очереди: @denis-skripnik.
Сервис прибавил к вашему посту примерно 124.887 GBG.

Инструкция по сжиганию для продвижения или задвигания постов.

Соглашение об использовании UPRomo.


Делегируйте СГ сервису UPRomo и способствуйте уменьшению количества GBG, что поможет выйти из кризиса, возобновить GBG и восстановить его цену, равную 1 МГ золота.

12.08.2019 18:23
0