@@ -112,6 +112,8 @@
return elem.value;
} else if (elem = form_elem.querySelector('textarea[name=' + field_name + ']')) {
return elem.value;
+ } else if (elem = form_elem.querySelector('select[name=' + field_name + ']')) {
+ return elem.value;
}
if (not_found_value !== undefined)
return not_found_value;
@@ -167,8 +169,11 @@
cache_id_to_group_key_i32a : { }, // str to key
msg_sound : null,
user_pid : null,
- cur_chat_other_user_pid : null,
+ cur_chat_other_user_pids : [],
cur_chat_group_pid : null,
+ // Service chat
+ cur_chat_agent_service_pid : null,
+ cur_chat_agent_user_pids : [], // Which users in current chat are service agents
};
const tmp_id = function()
@@ -587,6 +592,7 @@
};
const KV_STORE_KEY_CHAT_STATUS = 0;
+const KV_STORE_KEY_SELF_ATTRIBUTES = 1;
const handle_new_post_response = function(values)
{
@@ -630,7 +636,11 @@
let stored_object = null;
if (kv.key === KV_STORE_KEY_CHAT_STATUS) {
let content = u8a_to_str(i32a_to_u8a(decrypt_content_to_i32a(master_key_i32a(), u8a_to_i32a(b64_to_u8a(kv.value_ec_b64)))));
- //console.log('chat_status', content);
+ stored_object = JSON.parse(content);
+ }
+
+ if (kv.key === KV_STORE_KEY_SELF_ATTRIBUTES) {
+ let content = u8a_to_str(i32a_to_u8a(decrypt_content_to_i32a(master_key_i32a(), u8a_to_i32a(b64_to_u8a(kv.value_ec_b64)))));
stored_object = JSON.parse(content);
}
@@ -752,7 +762,7 @@
t: 'div', classes: 'popup',
});
- // TODO: Wrap elem is useless now (?)
+ // TODO: Wrap elem is useless now
let wrap_elem = create_elem_tree({ t: 'div', classes: 'popup_wrap' });
wrap_elem.appendChild(elem);
g_some.open_popups.push({
@@ -1423,8 +1433,7 @@
return ret;
};
-// For RSA key generation that has crappy api
-// TODO: Make sure that rsa key-pair is generated from random data!
+// For RSA key generation that has weird api
function SecureRandom() {}
SecureRandom.prototype.nextBytes = function(ba)
{
@@ -1590,6 +1599,25 @@
}
};
+const post_login = function(email, pw, callback)
+{
+ let server_pass = pw;
+ let pass_key_i32a = null;
+ {
+ let derived_pair = password_to_key_i32a_and_str(pw);
+ pass_key_i32a = derived_pair[0];
+ server_pass = derived_pair[1];
+ }
+
+ basic_data_post('/login', obj_to_uri({ email: email, password: server_pass }), function(success, info)
+ {
+ if (success && pass_key_i32a)
+ window.localStorage.setItem('pass_key', pass_key_i32a); // For decrypting mkey at next page
+
+ callback(success, info);
+ });
+};
+
const submit_login = function(evt)
{
let form = evt.target;
@@ -1600,15 +1628,7 @@
button.disabled = true;
clear_local_session_data(function() {
- let server_pass = pw;
- let pass_key_i32a = null;
- {
- let derived_pair = password_to_key_i32a_and_str(pw);
- pass_key_i32a = derived_pair[0];
- server_pass = derived_pair[1];
- }
-
- basic_data_post('/login', obj_to_uri({ email: email, password: server_pass }), function(success, info)
+ post_login(email, pw, function(success, info)
{
if (!success) {
show_page_notification(info);
@@ -1616,8 +1636,6 @@
return;
}
- if (pass_key_i32a)
- window.localStorage.setItem('pass_key', pass_key_i32a); // For decrypting mkey at next page
window.location.href = '/welcome';
});
});
@@ -1646,63 +1664,127 @@
window.sessionStorage.setItem('page_notification', msg);
};
-const submit_register_user = function(evt)
+const try_generate_user_registration_info = function(inputs)
{
- let form = evt.target;
- let display_name = form_field_value(form, 'display_name');
- let email = form_field_value(form, 'email');
- let password = form_field_value(form, 'password');
- let password2 = form_field_value(form, 'password2');
- let additional_info = form_field_value(form, 'additional_info');
- let token = form_field_value(form, 'token');
- let lang_id = form_field_value(form, 'lang_id');
- let legal_text_id = form_field_value(form, 'legal_text_id');
- let legal_consent = form_field_value(form, 'legal_consent');
-
- if (password != password2) {
+ if (inputs.password != inputs.password2) {
show_page_notification(translated('Passwords do not match'));
return;
}
- if (password.length <= 10) {
+ if (inputs.password.length <= 10) {
show_page_notification(translated('Password too short'));
return;
}
- if (legal_consent != 'on') {
+ if (inputs.legal_consent != 'on') {
show_page_notification(translated('You have not accepted the terms and conditions'));
return;
}
// Always create also crypto user
- let crypto = generate_crypto_credentials(password);
+ let crypto = generate_crypto_credentials(inputs.password);
assert(crypto.server_pw);
assert(crypto.mkey_ec_b64);
assert(crypto.rsa_modulus_hex);
assert(crypto.rsa_private_ec_b64);
assert(crypto.rating_key_ec_b64);
+ return {
+ create_also_crypto_user: 'on',
+
+ display_name: inputs.display_name,
+ email: inputs.email,
+ additional_info: inputs.additional_info,
+ token: inputs.token,
+ lang_id: inputs.lang_id,
+ legal_text_id: inputs.legal_text_id,
+ legal_consent: inputs.legal_consent,
+
+ preferred_agent: inputs.preferred_agent,
+
+ password: crypto.server_pw,
+ password2: crypto.server_pw,
+ mkey_ec_b64: crypto.mkey_ec_b64,
+ rsa_modulus_hex: crypto.rsa_modulus_hex,
+ rsa_private_ec_b64: crypto.rsa_private_ec_b64,
+ rating_key_ec_b64: crypto.rating_key_ec_b64,
+ };
+};
+
+const submit_register_user = function(evt)
+{
+ let form = evt.target;
+ const form_inputs = {
+ display_name: form_field_value(form, 'display_name'),
+ email: form_field_value(form, 'email'),
+ password: form_field_value(form, 'password'),
+ password2: form_field_value(form, 'password2'),
+ additional_info: form_field_value(form, 'additional_info'),
+ token: form_field_value(form, 'token'),
+ lang_id: form_field_value(form, 'lang_id'),
+ legal_text_id: form_field_value(form, 'legal_text_id'),
+ legal_consent: form_field_value(form, 'legal_consent'),
+ };
+
+ const user_registration_info = try_generate_user_registration_info(form_inputs);
+ if (!user_registration_info)
+ return;
+
basic_data_post('/register_user',
- obj_to_uri({
- create_also_crypto_user: 'on',
+ obj_to_uri(user_registration_info),
+ function(success, info, values)
+ {
+ if (success) {
+ post_login(form_inputs.email, form_inputs.password, function(success, info)
+ {
+ if (success)
+ window.location.href = '/';
+ else
+ show_page_notification(info);
+ });
+ } else {
+ show_page_notification(info);
+ }
+ }
+ );
+};
- display_name: display_name,
- email: email,
- password: crypto.server_pw,
- password2: crypto.server_pw,
- additional_info: additional_info,
- token: token,
- lang_id: lang_id,
- legal_text_id: legal_text_id,
- legal_consent: legal_consent,
-
- mkey_ec_b64: crypto.mkey_ec_b64,
- rsa_modulus_hex: crypto.rsa_modulus_hex,
- rsa_private_ec_b64: crypto.rsa_private_ec_b64,
- rating_key_ec_b64: crypto.rating_key_ec_b64
- }),
+const submit_register_to_agent_service = function(evt)
+{
+ let form = evt.target;
+ const form_inputs = {
+ //gender: form_field_value(form, 'gender'),
+ //birthyear: form_field_value(form, 'birthyear'),
+ display_name: form_field_value(form, 'display_name'),
+ email: form_field_value(form, 'email'),
+ password: form_field_value(form, 'password'),
+ password2: form_field_value(form, 'password2'),
+ lang_id: form_field_value(form, 'lang_id'),
+ legal_text_id: form_field_value(form, 'legal_text_id'),
+ legal_consent: form_field_value(form, 'legal_consent'),
+ additional_info: '',
+ token: '',
+
+ preferred_agent: form_field_value(form, 'preferred_agent')
+ };
+
+ assert(form_inputs.preferred_agent);
+
+ const user_registration_info = try_generate_user_registration_info(form_inputs);
+
+ if (!user_registration_info)
+ return;
+
+ basic_data_post('/register_user',
+ obj_to_uri(user_registration_info),
function(success, info, values)
{
if (success) {
- window.location.href = '/registration_complete';
+ post_login(form_inputs.email, form_inputs.password, function(success, info)
+ {
+ if (success)
+ window.location.href = '/';
+ else
+ show_page_notification(info);
+ });
} else {
show_page_notification(info);
}
@@ -1891,6 +1973,83 @@
});
};
+// Create and open chat between two users
+const submit_open_chat = function(evt)
+{
+ const form = evt.target;
+ const other_user_pid = form_field_value(form, 'other_user_pid');
+ const other_rsa_modulus_hex = form_field_value(form, 'other_rsa_modulus_hex');
+
+ assert(sjcl.random.isReady(ENTROPY_PARANOIA));
+ assert(other_rsa_modulus_hex);
+ const key_i32a = sjcl.random.randomWords(4);
+ const key_ec_hex = rsa_encrypt_i32a_to_hex(rsa_public_key(), key_i32a);
+ const other_key_ec_hex = rsa_encrypt_i32a_to_hex(make_rsa_public_key(other_rsa_modulus_hex), key_i32a);
+
+ basic_data_post('/create_chat',
+ obj_to_uri({
+ key_ec_hex: key_ec_hex,
+ other_user_pid: other_user_pid,
+ other_key_ec_hex: other_key_ec_hex
+ }),
+ function(success, info, values)
+ {
+ if (!success) {
+ show_page_notification(info);
+ return;
+ }
+
+ const group_pid = values[0];
+ assert(group_pid);
+ document.location = '/chats/' + group_pid;
+ }
+ );
+};
+// Create and open chat between specific service agents and a user
+const submit_open_agent_chat = function(evt)
+{
+ const form = evt.target;
+ const agent_service_pid = form_field_value(form, 'agent_service_pid');
+ const other_users_psv = form_field_value(form, 'other_users');
+ const other_users_schema = [
+ { type: 'array', name: 'array', schema: [
+ 'pid', 'rsa_modulus_hex'
+ ]
+ },
+ ];
+ const other_users = array_to_obj(other_users_schema, psv_to_array(other_users_psv)).array;
+
+ assert(sjcl.random.isReady(ENTROPY_PARANOIA));
+ const key_i32a = sjcl.random.randomWords(4);
+ const key_ec_hex = rsa_encrypt_i32a_to_hex(rsa_public_key(), key_i32a);
+
+ // TODO: psv writing utils
+ let return_data = '' + other_users.length;
+ for (let i = 0; i < other_users.length; ++i) {
+ return_data += '|' + other_users[i].pid;
+ return_data += '|' + rsa_encrypt_i32a_to_hex(make_rsa_public_key(other_users[i].rsa_modulus_hex), key_i32a);
+ }
+
+ basic_data_post('/create_agent_chat',
+ obj_to_uri({
+ agent_service_pid: agent_service_pid,
+ key_ec_hex: key_ec_hex,
+ other_users_psv: return_data,
+ }),
+ function(success, info, values)
+ {
+ if (!success) {
+ show_page_notification(info);
+ return;
+ }
+
+ const group_pid = values[0];
+ assert(group_pid);
+ document.location = '/agent_chats/' + group_pid;
+ }
+ );
+};
+
// Preprocess post src
const upload_blobs_from_post = function(str, on_finished)
{
@@ -2866,7 +3025,6 @@
{ type: 'array', name: 'posts', schema: post_schema },
];
const obj = array_to_obj(schema, parts);
-
const group_pid = html_encoded(obj.group_pid);
query_group_key_i32a(group_pid, function(group_key_i32a) // TODO: Store group key to 'decrypted_groups' instead of always requerying
@@ -2927,6 +3085,7 @@
{
let chat_elem = $(this);
let msgs_elem = $('#chat_msgs');
+
if (!msgs_elem.length) {
is_first_time = true;
chat_elem.append(create_elem_tree(
@@ -2935,13 +3094,13 @@
text: translated('Chat, ') + chat_elem.data('other_user_name')
}
));
- msgs_elem = $('<div id="chat_msgs"></div>');
+ msgs_elem = $(create_elem_tree({ t: 'div', id: 'chat_msgs' }));
chat_elem.append(msgs_elem);
}
let got_new_msg_from_other = false;
- let other_user_pid = chat_elem.data('other_user_pid') + '';
+ let elem_group_pid = chat_elem.data('group_pid') + '';
- if (last_msg_author_pid === g_some.user_pid || last_msg_author_pid === other_user_pid) { // TODO: Use group id to filter messages
+ if (elem_group_pid === group_pid) {
for (let i = 0; i < new_elems.length; ++i)
msgs_elem.append(new_elems[i]);
}
@@ -2951,6 +3110,7 @@
if (is_first_time) {
chat_elem.append($(
+ // TODO: Use create_elem_tree
'<form id="chat_msg_form" class="form">'
+'<input type="hidden" name="group_pid" value="' + group_pid + '" />'
+'<input type="hidden" name="visibility" value="' + POST_VISIBILITY_DEFAULT + '" />'
@@ -2980,7 +3140,7 @@
} else {
try_play_sound(g_some.msg_sound, 0.3);
// Using service workers now
- //try_show_desktop_notification(translated('New message: ') + last_other_msg_author_name, '/chats/' + last_other_msg_author_pid);
+ //try_show_desktop_notification(translated('New message: ') + last_other_msg_author_name, '/chats/' + group_pid);
}
update_notifications();
@@ -3491,6 +3651,8 @@
} else if (item.kind === 'string' && item.type === 'text/plain') {
item.getAsString(function(s)
{
+ wysiwyg_add_code(editor_id, s);
+
let found_urls = find_and_classify_urls(s);
for (let i = 0; i < found_urls.length; ++i) {
if (found_urls[i].embed_instruction) { // E.g. video embeds to external sites
@@ -3783,6 +3945,8 @@
submit_login(evt);
} else if (tag === 'register_user') {
submit_register_user(evt);
+ } else if (tag === 'register_to_agent_service') {
+ submit_register_to_agent_service(evt);
} else if (tag === 'change_password') {
submit_change_password(evt);
} else if (tag === 'reset_password_and_crypto') {
@@ -3793,6 +3957,10 @@
submit_destroy_post(evt);
} else if (tag === 'accept_encryted_group_member') {
submit_accept_encryted_group_member(evt);
+ } else if (tag === 'open_chat') {
+ submit_open_chat(evt);
+ } else if (tag === 'open_agent_chat') {
+ submit_open_agent_chat(evt);
} else if (tag === 'emulated') {
// Normal html form converted to js form with minimal effort
let form = evt.target;
@@ -4070,35 +4238,28 @@
{
let chat_elem = $(this);
assert(master_key_i32a());
- g_some.cur_chat_other_user_pid = chat_elem.data('other_user_pid') + '';
+ g_some.cur_chat_other_user_pids = psv_to_array(chat_elem.data('other_user_pids'));
g_some.cur_chat_group_pid = chat_elem.data('group_pid') + '';
+
+ if (chat_elem.data('agent_service_pid')) {
+ g_some.cur_chat_agent_service_pid = chat_elem.data('agent_service_pid');
+ g_some.cur_chat_agent_user_pids = psv_to_array(chat_elem.data('other_agent_user_pids'));
+ }
+
let key_i32a;
let key_ec_hex = chat_elem.data('key_ec_hex');
let other_rsa_modulus_hex = chat_elem.data('other_rsa_modulus_hex');
if (!other_rsa_modulus_hex || other_rsa_modulus_hex.length === 0) {
chat_elem.html('<p>' + translated('Encrypted messaging is not possible because of the other party') + '</p>');
} else {
- if (!g_some.cur_chat_group_pid) { // Create chat group
- assert(sjcl.random.isReady(ENTROPY_PARANOIA));
- assert(other_rsa_modulus_hex);
- key_i32a = sjcl.random.randomWords(4);
- key_ec_hex = rsa_encrypt_i32a_to_hex(rsa_public_key(), key_i32a);
- let other_key_ec_hex = rsa_encrypt_i32a_to_hex(make_rsa_public_key(other_rsa_modulus_hex), key_i32a);
- // TODO: Pipe-separated values as standard
- const send_cmd = 'create_chat\0' + key_ec_hex + '\0' + g_some.cur_chat_other_user_pid + '\0' + other_key_ec_hex;
- send(send_cmd);
- } else {
- assert(key_ec_hex);
- key_i32a = rsa_decrypt_hex_to_i32a(rsa_private_key(), key_ec_hex);
- on_msg_chat_content(psv_to_array(chat_elem.data('chat_content')));
- }
+ assert(key_ec_hex);
+ key_i32a = rsa_decrypt_hex_to_i32a(rsa_private_key(), key_ec_hex);
assert(key_i32a && key_i32a.length == 4);
+ on_msg_chat_content(psv_to_array(chat_elem.data('chat_content')));
}
});
- if (g_some.is_verified)
- init_websocket();
-
+ init_websocket();
let rating_symbol = function(rating)
{
@@ -4317,8 +4478,8 @@
g_some.push_sub_p256dh_b64u = script_init.push_sub_p256dh_b64u || null;
g_some.push_sub_auth_b64u = script_init.push_sub_auth_b64u || null;
g_some.user_pid = script_init.user_pid || null;
- g_some.has_crypto_user = script_init.has_crypto;
- g_some.is_verified = script_init.is_verified;
+ g_some.has_crypto_user = (script_init.has_crypto === '1');
+ g_some.is_verified = (script_init.is_verified === '1');
g_some.bridge_origin = script_init.bridge_origin;
g_some.script_init_data = script_init.data;