Skip to content

Commit

Permalink
Add passphrases to user settings page as additional tab, save passphr…
Browse files Browse the repository at this point in the history
…ases and use them to new encoded objects
  • Loading branch information
On1x committed Jul 10, 2023
1 parent ec4a68e commit aff6e99
Show file tree
Hide file tree
Showing 4 changed files with 246 additions and 16 deletions.
46 changes: 46 additions & 0 deletions app.css
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,53 @@ body.dark .hashtag-item:hover{
body.dark .hashtag-item-caption a{
color:#3daff5;
}
.passphrase-item{
font-size:20px;
margin-top:0;
padding:10px 15px;
text-align:left;
outline:0;

position:relative;
display:flex;
flex-direction:row;

border-bottom:1px solid rgba(204, 204, 221, 0.5);

-webkit-transition:all 0.3s ease-out; /* Saf3.2+, Chrome */
-moz-transition:all 0.3s ease-out; /* FF4+ */
-ms-transition:all 0.3s ease-out; /* IE10 */
-o-transition:all 0.3s ease-out; /* Opera 10.5+ */
transition:all 0.3s ease-out;
}
.passphrase-item:hover{
background-color:rgba(28, 152, 229, 0.05);
}
body.dark .passphrase-item:hover{
background-color:rgba(179, 180, 184, 0.05);
}
.passphrase-item.nohover:hover{
background-color:transparent !important;
}
.passphrase-item-caption{
word-break:break-word;
flex-grow:1;
font-size:15px;
line-height:35px;
}
.passphrase-item-manage a{
color:#1c98e5;
}
body.dark .passphrase-item-manage a{
color:#3daff5;
}
a.passphrase-remove-action{
display:inline-block;
color:red;
}
a.passphrase-remove-action i{
pointer-events:none;
}
.user-item-box{
line-height:20px;
font-size:14px;
Expand Down
194 changes: 180 additions & 14 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -1316,7 +1316,7 @@ var idb_init=false;
var db;
var db_req;
var db_version=1;
var global_db_version=9;
var global_db_version=10;
var need_update_db_version=false;
var local_global_db_version=parseInt(localStorage.getItem(storage_prefix+'global_db_version'));
if(isNaN(local_global_db_version)){
Expand Down Expand Up @@ -1546,6 +1546,16 @@ function load_db(callback){
}
console.log('Events storage upgraded!');

if(!db.objectStoreNames.contains('passphrases')){//store passphrases data
items_table=db.createObjectStore('passphrases',{keyPath:'id',autoIncrement:true});
items_table.createIndex('account','account',{unique:false});//one account can handle multiple passphrases
items_table.createIndex('time','time',{unique:false});//first usage time
}
else{
//new index for passphrases
}
console.log('Passphrases storage upgraded');

if(trx_need_commit){
update_trx.commit();
}
Expand Down Expand Up @@ -5087,6 +5097,17 @@ function app_mouse(e){
}
else{//not editor buttons
if(!ignore){
if($(target).hasClass('passphrase-remove-action')){
e.preventDefault();
let passphrase_id=$(target).closest('.passphrase-item').data('passphrase-id');
let t=db.transaction(['passphrases'],'readwrite');
let q=t.objectStore('passphrases');
let req=q.delete(passphrase_id);
req.onsuccess=function(event){
$(target).closest('.passphrase-item').remove();
};
return;
}
if($(target).hasClass('decode-form')){
e.preventDefault();
if(!$(target).hasClass('activated')){
Expand All @@ -5096,7 +5117,7 @@ function app_mouse(e){
}
return;
}
if($(target).hasClass('encode-object-action')){
if($(target).hasClass('decode-object-action')){
e.preventDefault();
let input_el=$(target).closest('.decode-form').find('.decode-passphrase input');
let passphrase=input_el.val();
Expand Down Expand Up @@ -8370,6 +8391,58 @@ function parse_object(account,block,feed_load_flag,callback){
add_t.commit();
}
add_t.oncomplete=function(e){
//try load all known passphrases for account if type is encoded
if('encoded'==type){
get_passphrases(account,function(err,result){
if(!err){
for(let i in result){
let passphrase=result[i];
decode_object(account,block,passphrase,function(result){
if(result){
get_user(account,false,function(err,object_user){
if(!err){
get_object(account,block,false,function(err,object_result){
if(!err){
let link='viz://@'+account+'/'+block+'/';
let view=$('.view[data-level="'+level+'"]');
if(-1==path.indexOf('viz://')){//look in services views
let path_parts=path.split('/');
view=$('.view[data-path="'+path_parts[0]+'"]');
}
let find_object=view.find('.objects>.object[data-account="'+account+'"][data-block="'+block+'"]');
if(find_object.length>0){
find_object=view.find('.object[data-link="'+link+'"]');
}
if(find_object.length>0){
let object_preview=false;
if(find_object.hasClass('type-text-preview')){
object_preview=true;
}
let object_type='default';
if(object_preview){
object_type='preview';
}
new_render=render_object(object_user,object_result,object_type);
find_object.before(new_render);
find_object.remove();//remove old view
if(object_preview){
update_short_date();
}
else{
let link='viz://@'+account+'/'+block+'/';
set_date_view($('.object[data-link="'+link+'"] .date-view'),true);
}
}
}
});
}
});
}
});
}
}
});
}
if(!feed_load_flag){
//solved by feed_load_flag (true when come from feed_load)
//problem code, it's trigger automatically for user, if you open object by link in new page, feed not loaded for him, but it's limited now with current object height
Expand Down Expand Up @@ -8493,7 +8566,68 @@ function get_replies(object_account,object_block,callback){
};
}

function add_passphrase(account,passphrase){
console.log('!!! add_passphrase',account,passphrase);
let t=db.transaction(['passphrases'],'readwrite');
let q=t.objectStore('passphrases');
req=q.index('account').openCursor(IDBKeyRange.only(account),'next');

let find=false;
req.onsuccess=function(event){
let cur=event.target.result;
if(cur){
console.log('!!! add_passphrase check',cur.value);
if(cur.value.passphrase==passphrase){
find=true;
}
cur.continue();
}
else{
console.log('!!! add_passphrase find',find);
if(!find){
/*
passphrases struct:
account - string
passphrase - string
time - unixtime
*/
q.add({account:account,passphrase:passphrase,time:(new Date().getTime() / 1000 | 0)});
if(trx_need_commit){
t.commit();
}
}
}
};
}

function get_passphrases(account,callback){
let passphrases=[];
let t=db.transaction(['passphrases'],'readonly');
let q=t.objectStore('passphrases');
let req=q.index('account').openCursor(IDBKeyRange.only(account),'next');
let find=0;
req.onsuccess=function(event){
let cur=event.target.result;
if(cur){
passphrases.push(cur.value.passphrase);
find++;
cur.continue();
}
else{
if(find){
callback(false,passphrases);
}
else{
callback(true,[]);
}
}
};
}

function decode_object(account,block,passphrase,callback){
if(typeof callback==='undefined'){
callback=function(){};
}
block=parseInt(block);
let t,q,req;
t=db.transaction(['objects'],'readwrite');
Expand All @@ -8506,8 +8640,9 @@ function decode_object(account,block,passphrase,callback){
let cur=event.target.result;
if(cur){
let result=cur.value;
if('e'==result.data.t){//encoded

if('e'!=result.data.t){//encoded
console.log('object already decoded',account,block);
callback(true);//as decoded already
}
let new_object_data=false;
try{
Expand All @@ -8524,6 +8659,7 @@ function decode_object(account,block,passphrase,callback){
}
}
}
add_passphrase(account,passphrase);
update_context=true;
}
catch(e){
Expand Down Expand Up @@ -10121,14 +10257,22 @@ function view_users(view,path_parts,query,title,back_to){
header+=ltmp(ltmp_arr.header_back_action,{icon:ltmp_global.icon_back,force:back_to});

view.data('user-account','');
if((typeof path_parts[1] != 'undefined')&&(''!=path_parts[1])){
if((typeof path_parts[1] != 'undefined')&&(''!=path_parts[1])){//view user page
let user_account=decodeURIComponent(path_parts[1]);
idb_get_by_id('users','account',user_account,function(user_data){
view.data('user-account',user_account);
if(false===user_data){
view.find('.objects').html(ltmp(ltmp_arr.error_notice,{error:ltmp_arr.account_not_found}));
}
else{
let tabs='';
let current_tab='settings';
if(''!=path_parts[2]){
current_tab=path_parts[2];
}
tabs+=ltmp(ltmp_arr.tab,{link:'dapp:users/'+user_account+'/settings/',class:('settings'==current_tab?'current':''),caption:ltmp_arr.users_user_settings_tab});
tabs+=ltmp(ltmp_arr.tab,{link:'dapp:users/'+user_account+'/passphrases/',class:('passphrases'==current_tab?'current':''),caption:ltmp_arr.users_user_passphrases_tab});
view.find('.tabs').html(tabs);
document.title='@'+user_data.account+' - '+document.title;
let user_data_profile=JSON.parse(user_data.profile);
header+=ltmp(ltmp_arr.header_caption_link,{caption:user_data_profile.nickname,link:'viz://@'+user_data.account});
Expand Down Expand Up @@ -10158,17 +10302,40 @@ function view_users(view,path_parts,query,title,back_to){
header+=ltmp_arr.user_actions_close;
}
}
view.find('.header').html(header);
let objects='';
if(typeof user_data.settings === 'undefined'){
user_data.settings={};
view.find('.objects').html(objects);
if('settings'==current_tab){
if(typeof user_data.settings === 'undefined'){
user_data.settings={};
}
let prop_value='';
if(typeof user_data.settings.activity_period !== 'undefined'){
prop_value=user_data.settings.activity_period;
}

objects+=ltmp(ltmp_arr.settings_item,{caption:ltmp_arr.settings_activity_period,prop:'activity_period',placeholder:settings.activity_period,value:prop_value,addon:ltmp_arr.settings_addon_activity_period});
view.find('.objects').html(ltmp(ltmp_arr.content_view,{content:objects+ltmp_arr.users_settings_buttons}));
}
let prop_value='';
if(typeof user_data.settings.activity_period !== 'undefined'){
prop_value=user_data.settings.activity_period;
if('passphrases'==current_tab){
let t=db.transaction(['passphrases'],'readonly');
let q=t.objectStore('passphrases');
let req=q.index('account').openCursor(IDBKeyRange.only(user_account),'next');
let find=0;
req.onsuccess=function(event){
let cur=event.target.result;
if(cur){
objects+=ltmp(ltmp_arr.passphrases_objects_item,{id:cur.value.id,passphrase:cur.value.passphrase});
find++;
cur.continue();
}
else{
if(!find){
objects+=ltmp(ltmp_arr.error_notice,{error:ltmp_arr.passphrases_not_found});
}
view.find('.objects').html(ltmp(ltmp_arr.content_view,{content:ltmp_arr.users_user_passphrases_description})+objects);
}
};
}
objects+=ltmp(ltmp_arr.settings_item,{caption:ltmp_arr.settings_activity_period,prop:'activity_period',placeholder:settings.activity_period,value:prop_value,addon:ltmp_arr.settings_addon_activity_period});
view.find('.objects').html(ltmp(ltmp_arr.content_view,{content:objects+ltmp_arr.users_settings_buttons}));
}
view.find('.header').html(header);
$('.loader').css('display','none');
Expand Down Expand Up @@ -13118,7 +13285,6 @@ function render_object(user,object,type,preset_level){
decoded_view=ltmp(ltmp_arr.decoded_object);
}
}
console.log(decoded_view);

render=ltmp(ltmp_arr.object_type_text,{
reply:reply,
Expand Down
11 changes: 10 additions & 1 deletion ltmp_en.js
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,11 @@ var ltmp_en_arr = {
hashtags_ignored_tab: 'Ignored',
hashtags_objects_header: `<div class="hashtag-item nohover"><div class="hashtag-item-num">№</div><div class="hashtag-item-caption">Tag</div><div class="hashtag-item-count">Count</div></div>`,
hashtags_objects_item: `<div class="hashtag-item" data-hashtag-id="{id}"><div class="hashtag-item-num">{num}</div><div class="hashtag-item-caption"><a data-href="dapp:hashtags/{tag}">#{tag}{addon}</a></div><div class="hashtag-item-count">{count}</div></div>`,
passphrases_objects_item: `
<div class="passphrase-item" data-passphrase-id="{id}">
<div class="passphrase-item-caption">{passphrase}</div>
<div class="passphrase-item-manage"><a class="passphrase-remove-action" tabindex="0" title="Remove">%%icon_close%%</div>
</div>`,

found_results: 'Found: {count}',

Expand All @@ -543,6 +548,10 @@ var ltmp_en_arr = {
users_qr_code_tab: 'Provide',
users_scan_qr_code_tab: 'Scan',
users_scan_retrieving: 'Retrieving video...',
users_user_settings_tab: 'Settings',
users_user_passphrases_tab: 'Passphrases',
users_user_passphrases_description: '<p>There are all the passphrases with which you successfully decrypted the objects of the selected user.</p>',
passphrases_not_found: 'No passphrases found',
scan_qr_unable: 'Unable to access video stream (please make sure you have a webcam enabled)',
scan_qr_error: '<div class="scan-qr-error-icon">{icon}</div><div class="scan-qr-error-text">{text}</div>',
scan_qr_error_browser: 'Browser not support video capture',
Expand Down Expand Up @@ -825,7 +834,7 @@ var ltmp_en_arr = {
<div class="notice-description">If you know the passphrase you can decode it.<br>All keys will be stored to specific account.<br>Press on me.</div>
<div class="decode-passphrase">
<input type="password" name="passphrase" placeholder="Key passphrase is..."><br>
<a class="button small encode-object-action">Decode</a>
<a class="button small decode-object-action">Decode</a>
</div>
`,
more_column: `<div class="more-column"><a tabindex="0" class="more-action" title="Available actions" data-account="{account}" data-block="{block}">%%icon_more%%</a></div>`,
Expand Down
11 changes: 10 additions & 1 deletion ltmp_ru.js
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,11 @@ var ltmp_ru_arr = {
hashtags_ignored_tab: 'Игнорируемые',
hashtags_objects_header: `<div class="hashtag-item nohover"><div class="hashtag-item-num">№</div><div class="hashtag-item-caption">Тэг</div><div class="hashtag-item-count">Количество</div></div>`,
hashtags_objects_item: `<div class="hashtag-item" data-hashtag-id="{id}"><div class="hashtag-item-num">{num}</div><div class="hashtag-item-caption"><a data-href="dapp:hashtags/{tag}">#{tag}{addon}</a></div><div class="hashtag-item-count">{count}</div></div>`,
passphrases_objects_item: `
<div class="passphrase-item" data-passphrase-id="{id}">
<div class="passphrase-item-caption">{passphrase}</div>
<div class="passphrase-item-manage"><a class="passphrase-remove-action" tabindex="0" title="Удалить">%%icon_close%%</div>
</div>`,

found_results: 'Найдено: {count}',

Expand All @@ -543,6 +548,10 @@ var ltmp_ru_arr = {
users_qr_code_tab: 'Предоставить',
users_scan_qr_code_tab: 'Сканировать',
users_scan_retrieving: 'Получаем видео...',
users_user_settings_tab: 'Настройки',
users_user_passphrases_tab: 'Пароли для расшифровки',
users_user_passphrases_description: '<p>Здесь вы найдете все пароли, которыми вы успешно расшифровывали объекты выбранного пользователя.</p>',
passphrases_not_found: 'Паролей не найдено',
scan_qr_unable: 'Не получается получить доступ к видео потоку (убедитесь, что у вас включена камера)',
scan_qr_error: '<div class="scan-qr-error-icon">{icon}</div><div class="scan-qr-error-text">{text}</div>',
scan_qr_error_browser: 'Браузер не поддерживает захват видео',
Expand Down Expand Up @@ -825,7 +834,7 @@ var ltmp_ru_arr = {
<div class="notice-description">Если вы знаете кодовую фразу вы можете расшифровать его.<br>Все ключи будут храниться к конкретному аккаунту.<br>Нажми на мне.</div>
<div class="decode-passphrase">
<input type="password" name="passphrase" placeholder="Кодовая фраза..."><br>
<a class="button small encode-object-action">Декодировать</a>
<a class="button small decode-object-action">Декодировать</a>
</div>
`,
more_column: `<div class="more-column"><a tabindex="0" class="more-action" title="Доступные действия" data-account="{account}" data-block="{block}">%%icon_more%%</a></div>`,
Expand Down

0 comments on commit aff6e99

Please sign in to comment.