Именно для скорости я взял «скоростную» связку webix+databoom.
С помощью webix мы будем разрабатывать наш фронт-энд, а databoom послужит бэк-эндом.
Что в итоге должно получиться? Приложеньице, с помощью которого два (или более?) пользователя смогут обмениваться информацией не подкармливая свою паранойю.
Набор элементов следующий:
- Текстовое поле для сообщения
- Поле для псевдонима
- Кнопка отправки сообщения
- Сам список сообщений
- Дополнительные опции
Начнем с фронт-энда
Подключим webix и накидаем разметку будущего приложения
webix.ui(
{rows:[
{view:'toolbar', cols:[
// Тулбар
]},
// Сообщения,
{view: 'resizer'},
{view:'form', elements:[
{cols:[
// Текстовое поле
{rows:[
// Псевдоним (никнейм),
// Кнопка отправки
]}
]}
]}
]}
)
Пока все просто. С помощью вышеприведенного кода мы создаем разметку нашего приложения.
После подключения библиотеки webix инициализация происходит в методе ui() объекта webix.
В качестве параметра он принимает объект с описанием структуры приложения.
Все названия говорящие: rows — массив строк, cols — массив колонок, view — компонент webix.
Теперь вместо комментариев надо вставить нужные нам компоненты вебикса, пойдем сверху вниз.
Тулбар представляет собой набор элементов панели инструментов. Нам понадобятся только кнопки:
{view:'toolbar', cols:[
{view:'button', value:'Удалить', align:'right', width:100, click:function(){}},
{view:'button', value:'Расшифровать выделенные', width:200, click:function(){}}
]}
Позже мы опишем их функции, а пока выведем на экран все необходимые элементы.
Самым подходящим для вывода сообщений (учитывая связку с databoom) я посчитал компонент datatable
{view:"datatable", id:'datatableCblp', url: data, select:'row', multiselect:true, columns:[
{id:'from', header:['От кого']},
{id:'msg', header:['Сообщение']}
]}
В параметре select указываем тип выделения (строка/ячейка/столбец, в нашем случае строка), это нам понадобится для реализации возможности удалять сообщения и дешифровывать выборочно.
Параметр multiselect отвечает за возможность выделять несколько строк (с шифтом).
Массив columns описывает то, какие колонки будут в нашей таблице. Для нашего простейшего варианта остановимся на имени отправителя и тексте сообщения.
Элементы формы (поля и кнопки) расписывать не буду, ту все предельно просто
{view:'form', elements:[
{cols:[
{ view:"textarea", label:"Сообщение", id:'Message'},
{rows:[
{ view:"text", label:"Псевдоним", id:'NickName'},
{ view:"text", label:"Ключ", id:'CryptoKey'},
{ view:"button", value:"Отправить", click:function(){}}
]}
]}
]}
На этом размечать визуальную часть закончим, перейдем к реализации технической стороны вопроса.
DataBoom
Чтобы начать пользоваться базой данных, вам необходимо зарегистрироваться на сайте, после чего вам придет письмо со ссылкой в административную панель вашей базы.
Здесь нам нужно сделать несколько манипуляций:
- Разрешить всем пользователям читать данные из базы
- Все
Для осуществления первого пункта ставим условия для группы пользователей anonymus
{"GET":{"*":true},"PUT":{"*":true},"DELETE":{"*":true}}
Все можно, все true.
Для управления базой данных из нашего приложения необходимо подключить скрипт
https://databoom.space/databoom.js
После его подключения создадим объект базы
db = databoom(config.baseHost, config.baseName);
Параметры, которые на этом этапе от вас требуются — это «хост» и «имя базы».
В письме databoom прислал вам ссылку на вашу базу данных, моя выглядит так:
Database URL: https://t014.databoom.space/api1/b014
Хостом является домен, включая «http(s)». А имя базы написано в конце, у нас это «b014».
После того, как объект базы данных инициализирован, мы можем описать функцию отправки сообщения на сервер:
{ view:"button", value:"Отправить", click:function(){
var newData = {};
newData.from = $$('NickName').getValue()
newData.msg = $$('Message').getValue()
db.save(config.collection, newData);
}}
Обращаться к объектам вебикса можно с помощью $$, осуществляя селектор по id, который мы указываем описании компонента (этот id не имеет ничего общего с id DOM элемента).
db.save() сохраняет данные в базу. Первым параметром мы указываем «коллекцию». Считайте это названием таблицы в базе данных, если угодно. Восхищение вызывает тот факт, что ее не надо создавать ни в админке databoom, ни из скрипта, она просто есть. Любая. В качестве коллекции можно указать произвольную (почти) строку, главное ее запомнить, мы еще будем к ней обращаться.
Хорошо, сообщение на сервер отправили, пришло время его считать. Для этого у нас служит параметр url компонента datatable
data = webix.proxy("databoomtree", config.basePath);
{view:"datatable", id:'datatableCblp', url: data, select:'row', multiselect:true, columns:[
{id:'from', header:['От кого']},
{id:'msg', header:['Сообщение']}
]}
В параметре url мы указываем вебикс-прокси объект, аргументом которому будет путь до нужной коллекции (я назвал ее crypto)
https://t014.databoom.space/api1/b014/collections/crypto
И вот мы уже получаем хранящиеся на сервере сообщения. Давайте немного запутаем врагов, внеся капельку криптографии. Можно использовать любой алгоритм шифрования по ключу, я использовал один из простых.
define([''], function(){
var сaesar = function (text, key, decode) {
var textLetter, keyLetter, result = "", conv = decode ? -1 : 1;
key = key ? key : " ";
for (textLetter = keyLetter = 0; textLetter < text.length; textLetter++, keyLetter++) {
if (keyLetter >= key.length) keyLetter = 0;
result += String.fromCharCode( text.charCodeAt(textLetter) + conv * key.charCodeAt(keyLetter) );
}
return result
}
var crypt = {
on: function(text, key){
return сaesar(text, key);
},
off: function(text, key){
return сaesar(text, key, true);
}
}
return crypt;
});
Шифровать, разумеется, будем до отправки на сервер (сохранения в базу). Внесем некоторые изменения, добавив поле ввода ключа:
{ view:"button", value:"Отправить", click:function(){
var newData = {};
newData.from = crypt.on($$('NickName').getValue(), $$('CryptoKey').getValue()); // crypt
newData.msg = crypt.on($$('Message').getValue(), $$('CryptoKey').getValue()); // crypt
db.save(config.collection, newData);
}}
Обратите внимание, что ключи, которые мы записываем в базу (from/msg) совпадают с id'ами, столбцов нашей datatable.
Понять и прочесть
Так как мы знаем, каким ключем шифрования пользуется наш собеседник (в этом и задумка), мы можем прочитать получаемые с сервера зашифрованные сообщения. Опишем функцию кнопки «расшифровать выделенные»:
{view:'button', value:'Расшифровать выделенные',width:200, click:function(){
var sel = $$("datatableCblp").getSelectedId(); // Выделенная ячейка
if(!Array.isArray(sel)){
var row = $$("datatableCblp").getItem(sel.row); // Вычисляем выделенную строку
row['msg'] = crypt.off(row.msg); // Раскриптовываем
row['from'] = crypt.off(row.from); // Раскриптовываем
$$("datatableCblp").updateItem(sel.row, row); // Заменяем данные в наших строках на расшифрованные
}else{
// Аналогично для каждой выделенной строки
}
}}
Заключение
Надеюсь, вы убедились, что создавать нечто не самое грандиозное весьма просто.
В числе прочего мы только что дали возможность разным людям общаться через один месенджер и не мешать друг другу. За исключением случая, если все решат, что их ключ «1234» самый классный.
Практики вам много и разной (новичкам).
Материалы
Благодарности
- @databoom за удобнейшую реализацию связки с webix (у меня пришлось усложнить в виду промежуточной обработки информации перед сохранением)
- @Skaner за обучалку касаемо публикации такого рода приложений через гугл диск
Комментарии (31)
inkvizitor68sl
27.08.2015 13:12+1Мессенджер для параноиков — это ssh-chat, поднимаемый каждый день на новом сервере. Ну и с авторизацией по ключам, конечно же.
klirichek
27.08.2015 19:18+1Ну это для «мягких» параноиков. А то вдруг там руткит в ring0, прошитый прямо в BIOS?
Лучше на микроконтроллере (без возможности виртуализации), в bare-metal, чтоб выдавал во внешний интерфейс уже зашифрованные пакеты. Типа клавиатуры для ввода пин-кода в банкомате.inkvizitor68sl
27.08.2015 19:19+1Для таких параноиков лучше вообще без мессенджера общаться)
seokirill
28.08.2015 01:50Да, оставлять телефоны дома и общаться в парке лично, учитывая последние статьи о прослушке. Но мало кто настолько интересует ФСБ. А если уж на карандаше, то не стоит совершать столь опасных дел. Головой-то тоже думать надо.
Glebcha
27.08.2015 23:08Для облегчения жизни форкающему и ближнему рекомендую добавить в package.json скрипты для установки глобально плагинов галпа если таковые отстуствуют и создания символических ссылок, чтобы не тянуть все модули каждый раз в каждый новый проект.
Пример можно у меня подсмотреть.
Также советую добавить обработку ошибок при сборке с уведомлениями (gulp-notify). Тоже в гисте наличиствует.
И вопрос — зачем овер 1к строк стилей в одной мешанине? Может лучше препроцессор какой-нибудь и фрагментировать?seokirill
28.08.2015 01:48Вопрос не понял. Стили склеиваются и минифицируются галпом. При разработке все обычно. Препроцессор попозже изучу, в очереди стоит на изучение.
Glebcha
28.08.2015 05:58У вас там один файл стилей объемом более 1400 строк. Такое сложно читать уже, а еще боли добавляет приведение каждого выражения к однострочному варианту.
Разбейте на несколько файлов (по блочному контексту или еще как-то), сделайте ваши труды читаемыми.
В публичном репозитории обычно самый полный вариант для разработки (без минификаторов и прочей байды), чтобы все могли ознакомиться с кодом, настроить сборку так как им нужно.beaverBox
28.08.2015 07:58Там стили — от webix, своих стилей нет.
рекомендую добавить в package.json скрипты для установки глобально плагинов галпа
Зачем глобально-то? Gulp — сборщик одного проекта, зачем тащить всё в систему?
чтобы не тянуть все модули каждый раз в каждый новый проект
С нормальным .gitignore ничто никуда не тянется, проект в репах остается чистым.Glebcha
28.08.2015 20:52Причем тут .gitignore? Понятно, что node_modules там будет, я писал про «один раз поставил пакеты глобально и в каждый последующий проект ни один из них не тянешь (кажется с 10-й ноды такое), лишь создаешь символическией ссылки». Gulp используется не только на одном проекте, это весьма популярный инструмент.
Так-то вообще можно минифицированные конкатенированные выложить, тоже ничего ведь, да? Только кто форкнет и вообще посмотрит, его же не перепилишь как нужно тебе, а не автору.seokirill
29.08.2015 01:12Не вполне понял, то есть все установить глобально заранее? Типа все предусмотреть? Есть ли от этого профит?
Glebcha
29.08.2015 10:06Конечно есть — следующие проекты можно собирать без установки локально пакетов в директорию проекта, лишь создать символические ссылки. Место на жестком диске не уходит и пакеты всегда можно использовать где угодно. Я специально заметил, что это я использую только для плагинов галпа (еще и основных модулей, общих для всех моих проектов), так как сборщик используется везде.
seokirill
28.08.2015 10:28А, понял, о чем вы. Так это файл стилей webix'а. В этот раз я ни строчки стилей не писал, забыл совсем.
Mithgol
28.08.2015 11:26+2Я чего-то не понимаю, кажется. Как должен рассуждать параноик, чтобы начать хранить свои данные
в облаке databoom.space вместо собственного компьютера?seokirill
28.08.2015 11:55+1Они ж там шифрованные, да и есть кнопка «удалить»
zharikovpro
28.08.2015 18:26+1Параноик должен понимать, что кнопка может быть бутафорской, а шифрование лишь на словах.
seokirill
29.08.2015 01:10+1Так если ввести другой ключ шифрования, то прочитать нельзя. Это можно протестировать имея 2 вкладки браузера.
И если нельзя прочитать, не имея ключа нужного, это должно обнадеживать.zharikovpro
29.08.2015 01:23> И если нельзя прочитать, не имея ключа нужного, это должно обнадеживать.
Но данные-то отдаются «на сторону»! Ни тебе бэкапов нормальных, ни полного контроля. Так что речь шла исключительно об ассоциациях, которые вызывает слово «паранойя»)seokirill
29.08.2015 02:56Если паранойя тотальная (ничему не верю), то тут уж не спасет ничто: каждый встречный агент, все телефоны — жучки, комп прошит врагами — то, скорее всего, человек вообще с компами дело не имеет, если рассуждать логически. А раз пользуется, значит степень паранойи пока не критическая. Для таких подойдут всяческие анонимайзеры, торы и пр.
isden
29.08.2015 10:48> И если нельзя прочитать, не имея ключа нужного, это должно обнадеживать.
Вы реализацию их алгоритмов шифрования видели? Вполне может быть, например, вот так:
— Есть некий мастер-ключ.
— На самом деле все лежит в открытом виде, а конечному пользователю лишь эмулируется описанное поведение.
— Шифрование честное, но производится каким-нибудь XOR на основе первых 2 символов хэша пользовательского ключа.
b1rdex
01.09.2015 14:54А как вы себе представляете средство общения через интернет, без использования сети для хранения/передачи данных?
beaverBox
Смотрю в сторону webix уже недели две, попробую-ка его на ощупь.
Мизерные придирки к коду:
gulp-livereload
если не используете его?.gitignore
для исключения из репы папкиnode_modules/
webix
хорошо тянется сbower
seokirill
Конструктивнейший комментарий!
Как не использую livereload?
node_modules зачем исключать?
На основе package.json их можно подтянуть?
NeXTs_od
Да как-то не принято на гитхаб заливать содержимое node_modules. Там же полно зависимостей, да и какой смысл так делать?
npm install вписали — все зависимости из package.json подтянулись
seokirill
Учел. Больше так не буду.
beaverBox
В данном случае
livereload: true
является частью APIgulp-connect
.beaverBox
И
Самым штатным образом:
seokirill
Уже записал себе, благодарю
Mithgol
Рекомендую всё же употреблять для этой цели команду«npm install --production» вместо более простого варианта «npm install», потому что этот последний занимается и установкою devDependencies, а не одних только обыкновенных зависимостей.