Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
|
e34a8e7a2b |
|
@ -1,2 +1,2 @@
|
||||||
node_modules
|
node_modules
|
||||||
vybe.db
|
celi.db
|
||||||
|
|
4
DOCS.md
4
DOCS.md
|
@ -1,7 +1,7 @@
|
||||||
# NOTICE: this document is outdated
|
# NOTICE: this document is outdated
|
||||||
# todo: update this document
|
# todo: update this document
|
||||||
|
|
||||||
# vybe websocket protocol - sent by client
|
# celi websocket protocol - sent by client
|
||||||
|
|
||||||
socket.io actions + expected msg format and other info
|
socket.io actions + expected msg format and other info
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ if a message fails, you get a response with the following format:
|
||||||
|
|
||||||
## authenticate
|
## authenticate
|
||||||
|
|
||||||
you must generate a random salt, sign a message `vybe_auth [salt]`, and then send
|
you must generate a random salt, sign a message `celi_auth [salt]`, and then send
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
11
README.md
11
README.md
|
@ -1,9 +1,9 @@
|
||||||
|
|
||||||
## vybe
|
## celi
|
||||||
|
|
||||||
vybe is a work-in-progress decentralized **communication network**.
|
celi is a work-in-progress decentralized **communication network**.
|
||||||
|
|
||||||
a vybe instance (server) features user accounts and **threads**.
|
a celi instance (server) features user accounts and **threads**.
|
||||||
|
|
||||||
user accounts are owned by PGP keys stored in users' clients.
|
user accounts are owned by PGP keys stored in users' clients.
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ after first run, the port is configured in instance.json.
|
||||||
**currently, you'll need to proxy it through a webserver like nginx or Caddy, which needs to have https enabled** for things to work correctly. if you want the easy option, i recommend Caddy. example Caddy config:
|
**currently, you'll need to proxy it through a webserver like nginx or Caddy, which needs to have https enabled** for things to work correctly. if you want the easy option, i recommend Caddy. example Caddy config:
|
||||||
|
|
||||||
> ```
|
> ```
|
||||||
> vybe.example.domain {
|
> celi.example.domain {
|
||||||
> reverse_proxy localhost:1312
|
> reverse_proxy localhost:1312
|
||||||
> header Access-Control-Allow-Origin "*"
|
> header Access-Control-Allow-Origin "*"
|
||||||
> }
|
> }
|
||||||
|
@ -38,13 +38,14 @@ after first run, the port is configured in instance.json.
|
||||||
|
|
||||||
(the allow-origin header isn't necessarily required but works as a fallback in case websockets don't work for whatever reason)
|
(the allow-origin header isn't necessarily required but works as a fallback in case websockets don't work for whatever reason)
|
||||||
|
|
||||||
then go to `https://vybe.example.domain` to start using vybe!
|
then go to `https://celi.example.domain` to start using celi!
|
||||||
|
|
||||||
## todo
|
## todo
|
||||||
|
|
||||||
- encrypt private threads (users already use pgp)
|
- encrypt private threads (users already use pgp)
|
||||||
- video in calls
|
- video in calls
|
||||||
- instance administration and moderation
|
- instance administration and moderation
|
||||||
|
- notifications
|
||||||
|
|
||||||
let me know if you have any questions or issues. i can be reached via my website [jerl.zone](https://jerl.zone).
|
let me know if you have any questions or issues. i can be reached via my website [jerl.zone](https://jerl.zone).
|
||||||
if you want to contribute, contact me :)
|
if you want to contribute, contact me :)
|
||||||
|
|
|
@ -219,7 +219,7 @@ document.body.append(html.node`
|
||||||
</div>
|
</div>
|
||||||
<hr class='separator' color='#505050'>
|
<hr class='separator' color='#505050'>
|
||||||
<div id='home' class='column'>
|
<div id='home' class='column'>
|
||||||
<h3>vybe</h3>
|
<h3>celi</h3>
|
||||||
<p id='instances' class='header'>instances:<button onclick=${e => {
|
<p id='instances' class='header'>instances:<button onclick=${e => {
|
||||||
let div = html.node`
|
let div = html.node`
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -21,7 +21,7 @@ async function auth() {
|
||||||
}, callback);
|
}, callback);
|
||||||
|
|
||||||
window.signedMessage = await openpgp.sign({
|
window.signedMessage = await openpgp.sign({
|
||||||
message: new openpgp.CleartextMessage('vybe_auth ' + window.session, ''),
|
message: new openpgp.CleartextMessage(window.session, ''),
|
||||||
signingKeys: window.keys.priv
|
signingKeys: window.keys.priv
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -103,11 +103,11 @@ async function submit(event) {
|
||||||
|
|
||||||
render(document.body, html`
|
render(document.body, html`
|
||||||
<div id='register' class='hidden'>
|
<div id='register' class='hidden'>
|
||||||
<h1>welcome to vybe</h1>
|
<h1>welcome to celi</h1>
|
||||||
<h3>a communication network (beta)</h3>
|
<h3>a communication network (beta)</h3>
|
||||||
<p>
|
<p>
|
||||||
to get started, you'll need an account. we use public key cryptography
|
to get started, you'll need an account. we use public key cryptography
|
||||||
for security, rather than passwords. your keys are stored in your
|
for security, rather than passwords, your keys are stored in your
|
||||||
browser storage only, so do this on a browser you can access again.
|
browser storage only, so do this on a browser you can access again.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>vybe</title>
|
<title>celi</title>
|
||||||
<style>
|
<style>
|
||||||
* {
|
* {
|
||||||
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
|
||||||
|
@ -127,16 +127,14 @@
|
||||||
margin-block: 5px;
|
margin-block: 5px;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
.thread:hover,
|
|
||||||
.tab:hover,
|
.tab:hover,
|
||||||
.instancetitle > span:hover,
|
.instancetitle > span:hover,
|
||||||
#user:hover {
|
#user:hover {
|
||||||
background-color: #333;
|
background-color: #333;
|
||||||
}
|
}
|
||||||
.thread.active,
|
|
||||||
.tab.active,
|
.tab.active,
|
||||||
button:hover {
|
button:hover {
|
||||||
background-color: #4f4f4f;
|
background-color: #484848;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
label.heading {
|
label.heading {
|
||||||
|
@ -253,6 +251,13 @@
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
.thread {
|
.thread {
|
||||||
|
&:hover {
|
||||||
|
background-color: #303030;
|
||||||
|
}
|
||||||
|
&.active {
|
||||||
|
background-color: #404040;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
padding: 2px 3px;
|
padding: 2px 3px;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
@ -293,9 +298,9 @@
|
||||||
}
|
}
|
||||||
.tab {
|
.tab {
|
||||||
padding: 5px 7px;
|
padding: 5px 7px;
|
||||||
background-color: #1f1f1f;
|
background-color: #222;
|
||||||
border: 0;
|
border: 0;
|
||||||
color: #ddd;
|
color: #e0e0e0;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
.tabcontent {
|
.tabcontent {
|
||||||
|
|
|
@ -22,7 +22,7 @@ function loadMessages(callback) {
|
||||||
});
|
});
|
||||||
msg.value = '';
|
msg.value = '';
|
||||||
}}>
|
}}>
|
||||||
<input id='msg' placeholder='write a message...' />
|
<input id='msg' placeholder='write a message...' autocomplete='off' />
|
||||||
<button type='submit' id='sendmsg'>send</button>
|
<button type='submit' id='sendmsg'>send</button>
|
||||||
</form>
|
</form>
|
||||||
`);
|
`);
|
||||||
|
|
|
@ -17,11 +17,14 @@ function setVisibility() {
|
||||||
function openThread(div, pushState) {
|
function openThread(div, pushState) {
|
||||||
if (!document.getElementById('removemember').classList.contains('hidden'))
|
if (!document.getElementById('removemember').classList.contains('hidden'))
|
||||||
document.getElementById('member').classList.add('hidden');
|
document.getElementById('member').classList.add('hidden');
|
||||||
|
if (window.currentThread)
|
||||||
|
window.currentThread.div.classList.remove('active');
|
||||||
if (!div) {
|
if (!div) {
|
||||||
document.getElementById('thread').classList.add('hidden');
|
document.getElementById('thread').classList.add('hidden');
|
||||||
window.currentThread = null;
|
window.currentThread = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
div.classList.add('active');
|
||||||
document.getElementById('thread').classList.remove('hidden');
|
document.getElementById('thread').classList.remove('hidden');
|
||||||
const edit = document.getElementById('edit');
|
const edit = document.getElementById('edit');
|
||||||
if (div.thread.permissions.admin) {
|
if (div.thread.permissions.admin) {
|
||||||
|
@ -32,9 +35,6 @@ function openThread(div, pushState) {
|
||||||
document.getElementById('membersadd').classList.add('hidden');
|
document.getElementById('membersadd').classList.add('hidden');
|
||||||
}
|
}
|
||||||
document.getElementById('threadname').textContent = div.thread.name;
|
document.getElementById('threadname').textContent = div.thread.name;
|
||||||
if (window.currentThread)
|
|
||||||
window.currentThread.div.classList.remove('active');
|
|
||||||
div.classList.add('active');
|
|
||||||
window.currentThread = div.thread;
|
window.currentThread = div.thread;
|
||||||
window.currentInstance = div.thread.instance;
|
window.currentInstance = div.thread.instance;
|
||||||
window.currentInstance.emit('get_thread', { thread: div.thread.id }, async msg => {
|
window.currentInstance.emit('get_thread', { thread: div.thread.id }, async msg => {
|
||||||
|
@ -487,9 +487,9 @@ async function loadThreads(instancediv, select) {
|
||||||
if (el) {
|
if (el) {
|
||||||
Object.assign(el.thread, thread);
|
Object.assign(el.thread, thread);
|
||||||
el.children['name'].textContent = thread.name;
|
el.children['name'].textContent = thread.name;
|
||||||
if (!thread.permissions.everyone.view.value && !el.children['membericon'])
|
if (!thread.permissions.public && !el.children['membericon'])
|
||||||
el.insertAdjacentHTML('beforeend', `<img id='membericon' src='/members.png'>`);
|
el.insertAdjacentHTML('beforeend', `<img id='membericon' src='/members.png'>`);
|
||||||
else if (el.children['membericon'] && thread.permissions.everyone.value)
|
else if (el.children['membericon'] && thread.permissions.public)
|
||||||
el.children['membericon'].remove();
|
el.children['membericon'].remove();
|
||||||
if (window.currentThread?.id === thread.id) {
|
if (window.currentThread?.id === thread.id) {
|
||||||
Object.assign(window.currentThread, thread);
|
Object.assign(window.currentThread, thread);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "vybe",
|
"name": "celi",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "server.js",
|
"main": "server.js",
|
||||||
|
|
22
server.js
22
server.js
|
@ -46,7 +46,7 @@ if (!instance.url)
|
||||||
it will be auto-set by the first user authentication !
|
it will be auto-set by the first user authentication !
|
||||||
it can be manually set in instance.json .`);
|
it can be manually set in instance.json .`);
|
||||||
|
|
||||||
global.vybe = {
|
global.celi = {
|
||||||
instance,
|
instance,
|
||||||
saveSettings,
|
saveSettings,
|
||||||
instances: {},
|
instances: {},
|
||||||
|
@ -55,7 +55,7 @@ global.vybe = {
|
||||||
calls: {}, // rtc peer connections go in here
|
calls: {}, // rtc peer connections go in here
|
||||||
streams: {},
|
streams: {},
|
||||||
connectInstance: async url => {
|
connectInstance: async url => {
|
||||||
let instance = vybe.instances[url];
|
let instance = celi.instances[url];
|
||||||
function connecting(resolve, reject) {
|
function connecting(resolve, reject) {
|
||||||
instance.socket.on('connect', resolve);
|
instance.socket.on('connect', resolve);
|
||||||
instance.socket.on('connect_error', error => {
|
instance.socket.on('connect_error', error => {
|
||||||
|
@ -70,7 +70,7 @@ global.vybe = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
instance = vybe.instances[url] = {
|
instance = celi.instances[url] = {
|
||||||
socket: ioclient('https://' + url)
|
socket: ioclient('https://' + url)
|
||||||
};
|
};
|
||||||
await new Promise(connecting);
|
await new Promise(connecting);
|
||||||
|
@ -92,7 +92,7 @@ app.use(express.static('client'));
|
||||||
|
|
||||||
// todo: secure this
|
// todo: secure this
|
||||||
app.get('/stream/:id', (req, res) => {
|
app.get('/stream/:id', (req, res) => {
|
||||||
let stream = vybe.streams[req.params.id];
|
let stream = celi.streams[req.params.id];
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
res.sendStatus(404);
|
res.sendStatus(404);
|
||||||
return;
|
return;
|
||||||
|
@ -121,17 +121,17 @@ io.on('connection', (socket) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
socket.on('disconnect', async reason => {
|
socket.on('disconnect', async reason => {
|
||||||
let user = vybe.users[socket.__userid];
|
let user = celi.users[socket.__userid];
|
||||||
if (user)
|
if (user)
|
||||||
user.sockets.splice(user.sockets.indexOf(socket), 1);
|
user.sockets.splice(user.sockets.indexOf(socket), 1);
|
||||||
for (let id in vybe.streams) {
|
for (let id in celi.streams) {
|
||||||
const stream = vybe.streams[id];
|
const stream = celi.streams[id];
|
||||||
delete stream.listeners[socket.id];
|
delete stream.listeners[socket.id];
|
||||||
if (stream.socket === socket)
|
if (stream.socket === socket)
|
||||||
stream.stop();
|
stream.stop();
|
||||||
}
|
}
|
||||||
for (let id in vybe.calls) {
|
for (let id in celi.calls) {
|
||||||
let call = vybe.calls[id];
|
let call = celi.calls[id];
|
||||||
let connection = call[socket.__userid];
|
let connection = call[socket.__userid];
|
||||||
if (!connection)
|
if (!connection)
|
||||||
continue;
|
continue;
|
||||||
|
@ -141,8 +141,8 @@ io.on('connection', (socket) => {
|
||||||
}
|
}
|
||||||
connection.close();
|
connection.close();
|
||||||
delete call[id];
|
delete call[id];
|
||||||
delete vybe.threads[id].call[socket.__userid];
|
delete celi.threads[id].call[socket.__userid];
|
||||||
await vybe.threads[id].emitcall();
|
await celi.threads[id].emitcall();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,7 +11,7 @@ const authwrap = (fn) => async (msg, respond, socket) => {
|
||||||
}
|
}
|
||||||
return await fn({
|
return await fn({
|
||||||
...msg,
|
...msg,
|
||||||
auth_user: vybe.users[socket.__userid]
|
auth_user: celi.users[socket.__userid]
|
||||||
}, respond, socket);
|
}, respond, socket);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
const sqlite3 = require('sqlite3');
|
const sqlite3 = require('sqlite3');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
const path = 'vybe.db';
|
const path = 'celi.db';
|
||||||
|
|
||||||
const existed = fs.existsSync(path);
|
const existed = fs.existsSync(path);
|
||||||
const db = new sqlite3.Database(path);
|
const db = new sqlite3.Database(path);
|
||||||
|
|
||||||
db.query = function (sql, params) {
|
db.query = function(sql, params) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
db.all(sql, params, (error, rows) => {
|
db.all(sql, params, (error, rows) => {
|
||||||
if (error)
|
if (error)
|
||||||
|
@ -17,11 +17,12 @@ db.query = function (sql, params) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
(async () => {
|
db.ready = new Promise(async resolve => {
|
||||||
if (!existed)
|
if (!existed)
|
||||||
for (let sql of fs.readFileSync('./db/1-init.sql').toString().split(';'))
|
for (let sql of fs.readFileSync('./db/1-init.sql').toString().split(';'))
|
||||||
if (sql.trim())
|
if (sql.trim())
|
||||||
await db.query(sql);
|
await db.query(sql);
|
||||||
})();
|
resolve();
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = db;
|
module.exports = db;
|
||||||
|
|
|
@ -15,8 +15,8 @@ async function join(msg, respond, socket) {
|
||||||
success: false,
|
success: false,
|
||||||
message: "user doesn't have permission"
|
message: "user doesn't have permission"
|
||||||
});
|
});
|
||||||
const thread = vybe.threads[msg.thread];
|
const thread = celi.threads[msg.thread];
|
||||||
const call = vybe.calls[msg.thread];
|
const call = celi.calls[msg.thread];
|
||||||
let connection = call[msg.auth_user.id];
|
let connection = call[msg.auth_user.id];
|
||||||
if (connection) {
|
if (connection) {
|
||||||
if (connection.track) {
|
if (connection.track) {
|
||||||
|
@ -66,8 +66,8 @@ async function join(msg, respond, socket) {
|
||||||
connection.connected = true;
|
connection.connected = true;
|
||||||
thread.call[msg.auth_user.id] = {
|
thread.call[msg.auth_user.id] = {
|
||||||
id: msg.auth_user.id,
|
id: msg.auth_user.id,
|
||||||
name: vybe.users[msg.auth_user.id].name,
|
name: celi.users[msg.auth_user.id].name,
|
||||||
displayname: vybe.users[msg.auth_user.id].displayname,
|
displayname: celi.users[msg.auth_user.id].displayname,
|
||||||
permissions: Object.fromEntries((await db.query(
|
permissions: Object.fromEntries((await db.query(
|
||||||
`select permission, value from permission
|
`select permission, value from permission
|
||||||
where type = 'user' and thread = ? and user = ?`,
|
where type = 'user' and thread = ? and user = ?`,
|
||||||
|
@ -104,7 +104,7 @@ async function offer(msg, respond) {
|
||||||
success: false,
|
success: false,
|
||||||
message: 'missing argument'
|
message: 'missing argument'
|
||||||
});
|
});
|
||||||
let connection = vybe.calls[msg.thread]?.[msg.auth_user.id];
|
let connection = celi.calls[msg.thread]?.[msg.auth_user.id];
|
||||||
if (!connection)
|
if (!connection)
|
||||||
return respond({
|
return respond({
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -124,7 +124,7 @@ async function ice(msg, respond) {
|
||||||
success: false,
|
success: false,
|
||||||
message: 'missing argument'
|
message: 'missing argument'
|
||||||
});
|
});
|
||||||
let connection = vybe.calls[msg.thread]?.[msg.auth_user.id];
|
let connection = celi.calls[msg.thread]?.[msg.auth_user.id];
|
||||||
if (!connection)
|
if (!connection)
|
||||||
return respond({
|
return respond({
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -144,8 +144,8 @@ async function ice(msg, respond) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function leave(msg, respond) {
|
async function leave(msg, respond) {
|
||||||
let thread = vybe.threads[msg.thread];
|
let thread = celi.threads[msg.thread];
|
||||||
let call = vybe.calls[msg.thread];
|
let call = celi.calls[msg.thread];
|
||||||
let connection = call?.[msg.auth_user.id];
|
let connection = call?.[msg.auth_user.id];
|
||||||
if (!connection)
|
if (!connection)
|
||||||
return respond({
|
return respond({
|
||||||
|
|
|
@ -33,10 +33,10 @@ async function send_message(msg, respond) {
|
||||||
if (p.type === 'user' && p.user == msg.auth_user.id)
|
if (p.type === 'user' && p.user == msg.auth_user.id)
|
||||||
userperms[p.permission] = ['admin', 'post', 'view'].includes(p.permission)
|
userperms[p.permission] = ['admin', 'post', 'view'].includes(p.permission)
|
||||||
? p.value === 'true' : p.value;
|
? p.value === 'true' : p.value;
|
||||||
for (let id in vybe.users) {
|
for (let id in celi.users) {
|
||||||
if (perms.find(p => p.type === 'everyone' && p.permission === 'view' && p.value === 'true')
|
if (perms.find(p => p.type === 'everyone' && p.permission === 'view' && p.value === 'true')
|
||||||
|| members.includes(id)) {
|
|| members.includes(id)) {
|
||||||
for (let s of vybe.users[id].sockets) {
|
for (let s of celi.users[id].sockets) {
|
||||||
s.emit('new_message', {
|
s.emit('new_message', {
|
||||||
id,
|
id,
|
||||||
user: {
|
user: {
|
||||||
|
|
|
@ -65,9 +65,9 @@ async function save_span(msg, respond, socket) {
|
||||||
and type = 'everyone' and value = 'true' and permission = 'view'`,
|
and type = 'everyone' and value = 'true' and permission = 'view'`,
|
||||||
msg.thread
|
msg.thread
|
||||||
);
|
);
|
||||||
for (let userid in vybe.users) {
|
for (let userid in celi.users) {
|
||||||
if (permissions.rows.length > 0 || members.includes(userid)) {
|
if (permissions.rows.length > 0 || members.includes(userid)) {
|
||||||
for (let s of vybe.users[userid].sockets) {
|
for (let s of celi.users[userid].sockets) {
|
||||||
if (s !== socket)
|
if (s !== socket)
|
||||||
s.emit('span', {
|
s.emit('span', {
|
||||||
id,
|
id,
|
||||||
|
|
|
@ -17,14 +17,14 @@ async function stream(msg, respond, socket) {
|
||||||
`select * from permission
|
`select * from permission
|
||||||
where thread = ? and type = 'everyone' and value = 'true' and permission = 'view'`,
|
where thread = ? and type = 'everyone' and value = 'true' and permission = 'view'`,
|
||||||
msg.thread)).rows.length) {
|
msg.thread)).rows.length) {
|
||||||
for (let id in vybe.users)
|
for (let id in celi.users)
|
||||||
for (let socket of vybe.users[id].sockets)
|
for (let socket of celi.users[id].sockets)
|
||||||
socket.emit('stream', stream);
|
socket.emit('stream', stream);
|
||||||
} else {
|
} else {
|
||||||
for (let member of (
|
for (let member of (
|
||||||
await db.query('select user from member where member.thread = ?', msg.thread)
|
await db.query('select user from member where member.thread = ?', msg.thread)
|
||||||
).rows) {
|
).rows) {
|
||||||
member = vybe.users[member.user];
|
member = celi.users[member.user];
|
||||||
if (member)
|
if (member)
|
||||||
for (let socket of member.sockets)
|
for (let socket of member.sockets)
|
||||||
socket.emit('stream', stream);
|
socket.emit('stream', stream);
|
||||||
|
@ -32,7 +32,7 @@ async function stream(msg, respond, socket) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typeof msg.id === 'number') {
|
if (typeof msg.id === 'number') {
|
||||||
let vstream = vybe.streams[msg.id];
|
let vstream = celi.streams[msg.id];
|
||||||
if (!vstream)
|
if (!vstream)
|
||||||
return respond({
|
return respond({
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -68,9 +68,9 @@ async function stream(msg, respond, socket) {
|
||||||
},
|
},
|
||||||
name: msg.name
|
name: msg.name
|
||||||
};
|
};
|
||||||
let thread = vybe.threads[msg.thread];
|
let thread = celi.threads[msg.thread];
|
||||||
thread.streams.push(stream);
|
thread.streams.push(stream);
|
||||||
vybe.streams[stream.id] = {
|
celi.streams[stream.id] = {
|
||||||
stream,
|
stream,
|
||||||
userid: msg.auth_user.id,
|
userid: msg.auth_user.id,
|
||||||
listeners: {},
|
listeners: {},
|
||||||
|
@ -78,7 +78,7 @@ async function stream(msg, respond, socket) {
|
||||||
stop: async () => {
|
stop: async () => {
|
||||||
stream.stopped = true;
|
stream.stopped = true;
|
||||||
thread.streams.splice(thread.streams.findIndex(s => s.id === stream.id), 1);
|
thread.streams.splice(thread.streams.findIndex(s => s.id === stream.id), 1);
|
||||||
delete vybe.streams[stream.id];
|
delete celi.streams[stream.id];
|
||||||
await send();
|
await send();
|
||||||
},
|
},
|
||||||
streams: new Set()
|
streams: new Set()
|
||||||
|
@ -92,7 +92,7 @@ async function stream(msg, respond, socket) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function streamdata(msg, respond) {
|
async function streamdata(msg, respond) {
|
||||||
let stream = vybe.streams[msg.id];
|
let stream = celi.streams[msg.id];
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
return respond({
|
return respond({
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -119,7 +119,7 @@ async function play_stream(msg, respond, socket) {
|
||||||
message: "user doesn't have permission"
|
message: "user doesn't have permission"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let stream = vybe.streams[msg.id];
|
let stream = celi.streams[msg.id];
|
||||||
if (!stream)
|
if (!stream)
|
||||||
return respond({
|
return respond({
|
||||||
success: false,
|
success: false,
|
||||||
|
|
|
@ -2,11 +2,11 @@ const db = require('../db');
|
||||||
const authwrap = require('../authwrap');
|
const authwrap = require('../authwrap');
|
||||||
const check_permission = require('../check_permission');
|
const check_permission = require('../check_permission');
|
||||||
|
|
||||||
(async () => {
|
db.ready.then(async () => {
|
||||||
for (let thread of (await db.query(
|
for (let thread of (await db.query(
|
||||||
`select name, id from thread`
|
`select name, id from thread`
|
||||||
)).rows) {
|
)).rows) {
|
||||||
vybe.threads[thread.id] = {
|
celi.threads[thread.id] = {
|
||||||
...thread,
|
...thread,
|
||||||
streams: [],
|
streams: [],
|
||||||
call: {}, // list of members in call
|
call: {}, // list of members in call
|
||||||
|
@ -19,14 +19,14 @@ const check_permission = require('../check_permission');
|
||||||
`select * from permission
|
`select * from permission
|
||||||
where thread = ? and type = 'everyone' and value = 'true' and permission = 'view'`,
|
where thread = ? and type = 'everyone' and value = 'true' and permission = 'view'`,
|
||||||
this.id)).rows.length) {
|
this.id)).rows.length) {
|
||||||
for (let id in vybe.users)
|
for (let id in celi.users)
|
||||||
for (let socket of vybe.users[id].sockets)
|
for (let socket of celi.users[id].sockets)
|
||||||
socket.emit('call', msg);
|
socket.emit('call', msg);
|
||||||
} else {
|
} else {
|
||||||
for (let member of (
|
for (let member of (
|
||||||
await db.query('select user from member where member.thread = ?', this.id)
|
await db.query('select user from member where member.thread = ?', this.id)
|
||||||
).rows) {
|
).rows) {
|
||||||
member = vybe.users[member.user];
|
member = celi.users[member.user];
|
||||||
if (member)
|
if (member)
|
||||||
for (let socket of member.sockets)
|
for (let socket of member.sockets)
|
||||||
socket.emit('call', msg);
|
socket.emit('call', msg);
|
||||||
|
@ -34,9 +34,9 @@ const check_permission = require('../check_permission');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
vybe.calls[thread.id] = {};
|
celi.calls[thread.id] = {};
|
||||||
}
|
}
|
||||||
})();
|
});
|
||||||
|
|
||||||
async function create_thread(msg, respond) {
|
async function create_thread(msg, respond) {
|
||||||
// validate inputs
|
// validate inputs
|
||||||
|
@ -101,7 +101,7 @@ async function create_thread(msg, respond) {
|
||||||
let members = {};
|
let members = {};
|
||||||
for (let member of msg.members) {
|
for (let member of msg.members) {
|
||||||
let id = member.id.split('@');
|
let id = member.id.split('@');
|
||||||
id = id[1] === vybe.instance.url ? id[0] : member.id;
|
id = id[1] === celi.instance.url ? id[0] : member.id;
|
||||||
if (members[id])
|
if (members[id])
|
||||||
continue;
|
continue;
|
||||||
await db.query(
|
await db.query(
|
||||||
|
@ -116,19 +116,20 @@ async function create_thread(msg, respond) {
|
||||||
values (?, ?, ?, ?, ?, ?)`,
|
values (?, ?, ?, ?, ?, ?)`,
|
||||||
[thread_id, 'user', id, true, permission, String(member.permissions[permission])]);
|
[thread_id, 'user', id, true, permission, String(member.permissions[permission])]);
|
||||||
}
|
}
|
||||||
let thread = vybe.threads[thread_id] = {
|
let thread = celi.threads[thread_id] = {
|
||||||
id: thread_id,
|
id: thread_id,
|
||||||
name: msg.name,
|
name: msg.name,
|
||||||
streams: [],
|
streams: [],
|
||||||
call: {}
|
call: {}
|
||||||
};
|
};
|
||||||
vybe.calls[thread_id] = {};
|
celi.calls[thread_id] = {};
|
||||||
if (!msg.permissions?.view_limited) {
|
if (!msg.permissions?.view_limited) {
|
||||||
for (let id in vybe.users) {
|
for (let id in celi.users) {
|
||||||
for (let socket of vybe.users[id].sockets) {
|
for (let socket of celi.users[id].sockets) {
|
||||||
socket.emit('thread', {
|
socket.emit('thread', {
|
||||||
...thread,
|
...thread,
|
||||||
permissions: {
|
permissions: {
|
||||||
|
public: true,
|
||||||
view: true,
|
view: true,
|
||||||
post: !msg.permissions?.post_limited || members[id],
|
post: !msg.permissions?.post_limited || members[id],
|
||||||
admin: id === msg.auth_user.id
|
admin: id === msg.auth_user.id
|
||||||
|
@ -139,7 +140,7 @@ async function create_thread(msg, respond) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (let member in members) {
|
for (let member in members) {
|
||||||
member = vybe.users[member];
|
member = celi.users[member];
|
||||||
if (!member)
|
if (!member)
|
||||||
continue;
|
continue;
|
||||||
for (let socket of member.sockets) {
|
for (let socket of member.sockets) {
|
||||||
|
@ -180,7 +181,7 @@ async function list_threads(msg, respond) {
|
||||||
success: true,
|
success: true,
|
||||||
threads: await Promise.all(threads.rows.map(async row => {
|
threads: await Promise.all(threads.rows.map(async row => {
|
||||||
let thread = {};
|
let thread = {};
|
||||||
Object.assign(thread, vybe.threads[row.id]);
|
Object.assign(thread, celi.threads[row.id]);
|
||||||
thread.permissions = await check_permission(msg.auth_user.id, row.id);
|
thread.permissions = await check_permission(msg.auth_user.id, row.id);
|
||||||
thread.permissions.public = row.value === 'true';
|
thread.permissions.public = row.value === 'true';
|
||||||
return thread;
|
return thread;
|
||||||
|
@ -248,7 +249,7 @@ async function get_thread(msg, respond) {
|
||||||
return respond({
|
return respond({
|
||||||
success: true,
|
success: true,
|
||||||
thread: {
|
thread: {
|
||||||
...vybe.threads[msg.thread],
|
...celi.threads[msg.thread],
|
||||||
permissions: perms,
|
permissions: perms,
|
||||||
members: Object.values(members)
|
members: Object.values(members)
|
||||||
}
|
}
|
||||||
|
@ -276,7 +277,7 @@ async function edit_thread(msg, respond) {
|
||||||
message: "user doesn't have permission"
|
message: "user doesn't have permission"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let thread = vybe.threads[msg.id];
|
let thread = celi.threads[msg.id];
|
||||||
// update name
|
// update name
|
||||||
await db.query(
|
await db.query(
|
||||||
'update thread set name = ? where id = ?',
|
'update thread set name = ? where id = ?',
|
||||||
|
@ -368,11 +369,12 @@ async function edit_thread(msg, respond) {
|
||||||
msg.id
|
msg.id
|
||||||
)).rows.map(row => [row.user, true]));
|
)).rows.map(row => [row.user, true]));
|
||||||
if (!msg.permissions?.view_limited) {
|
if (!msg.permissions?.view_limited) {
|
||||||
for (let id in vybe.users)
|
for (let id in celi.users)
|
||||||
for (let socket of vybe.users[id].sockets)
|
for (let socket of celi.users[id].sockets)
|
||||||
socket.emit('thread', {
|
socket.emit('thread', {
|
||||||
...thread,
|
...thread,
|
||||||
permissions: {
|
permissions: {
|
||||||
|
public: true,
|
||||||
view: true,
|
view: true,
|
||||||
post: !msg.permissions?.post_limited || id in members,
|
post: !msg.permissions?.post_limited || id in members,
|
||||||
admin: id === msg.auth_user.id && perms.admin,
|
admin: id === msg.auth_user.id && perms.admin,
|
||||||
|
@ -382,7 +384,7 @@ async function edit_thread(msg, respond) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (let member in members) {
|
for (let member in members) {
|
||||||
member = vybe.users[member];
|
member = celi.users[member];
|
||||||
if (!member)
|
if (!member)
|
||||||
continue;
|
continue;
|
||||||
for (let socket of member.sockets)
|
for (let socket of member.sockets)
|
||||||
|
|
|
@ -85,14 +85,7 @@ async function authenticate(msg, respond, socket) {
|
||||||
expectSigned: true,
|
expectSigned: true,
|
||||||
date: new Date(Date.now() + 60000 * 4) // slightly in the future to compensate for some system clocks
|
date: new Date(Date.now() + 60000 * 4) // slightly in the future to compensate for some system clocks
|
||||||
});
|
});
|
||||||
const data = verification.data.split(' ');
|
if (celi.instance.url === id[1] || (!celi.instance.url && !id[0])) {
|
||||||
if (data[0] !== 'vybe_auth') {
|
|
||||||
return respond({
|
|
||||||
success: false,
|
|
||||||
message: 'bad auth message'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (vybe.instance.url === id[1] || (!vybe.instance.url && !id[0])) {
|
|
||||||
// this should be user's home instance
|
// this should be user's home instance
|
||||||
user = await getUser(id[0], msg.name);
|
user = await getUser(id[0], msg.name);
|
||||||
if (!user) {
|
if (!user) {
|
||||||
|
@ -109,13 +102,13 @@ async function authenticate(msg, respond, socket) {
|
||||||
);
|
);
|
||||||
if (result.rows.length === 0) {
|
if (result.rows.length === 0) {
|
||||||
// request auth from logged in sessions
|
// request auth from logged in sessions
|
||||||
if (!vybe.users[user.id])
|
if (!celi.users[user.id])
|
||||||
vybe.users[user.id] = {
|
celi.users[user.id] = {
|
||||||
...user,
|
...user,
|
||||||
sockets: [],
|
sockets: [],
|
||||||
authrequests: {}
|
authrequests: {}
|
||||||
};
|
};
|
||||||
user = vybe.users[user.id];
|
user = celi.users[user.id];
|
||||||
let id = key.getFingerprint().slice(0, 8);
|
let id = key.getFingerprint().slice(0, 8);
|
||||||
let time = Date.now();
|
let time = Date.now();
|
||||||
if (!await new Promise(resolve => {
|
if (!await new Promise(resolve => {
|
||||||
|
@ -136,15 +129,15 @@ async function authenticate(msg, respond, socket) {
|
||||||
[user.id, pubkey]);
|
[user.id, pubkey]);
|
||||||
}
|
}
|
||||||
// default instance url to first authenticated user's location.host
|
// default instance url to first authenticated user's location.host
|
||||||
if (!vybe.instance.url) {
|
if (!celi.instance.url) {
|
||||||
vybe.instance.url = id[1];
|
celi.instance.url = id[1];
|
||||||
vybe.saveSettings();
|
celi.saveSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// connect to user's home instance and ask for their key
|
// connect to user's home instance and ask for their key
|
||||||
try {
|
try {
|
||||||
let instance = await vybe.connectInstance(id[1]);
|
let instance = await celi.connectInstance(id[1]);
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
instance.socket.emit('get_keys', { ids: [id[0]] }, msg => {
|
instance.socket.emit('get_keys', { ids: [id[0]] }, msg => {
|
||||||
if (!msg.success) {
|
if (!msg.success) {
|
||||||
|
@ -171,18 +164,18 @@ async function authenticate(msg, respond, socket) {
|
||||||
// this socket is now authenticated
|
// this socket is now authenticated
|
||||||
if (!user.displayname)
|
if (!user.displayname)
|
||||||
user.displayname = user.name;
|
user.displayname = user.name;
|
||||||
user = vybe.users[user.id] || (vybe.users[user.id] = {
|
user = celi.users[user.id] || (celi.users[user.id] = {
|
||||||
...user,
|
...user,
|
||||||
sockets: [],
|
sockets: [],
|
||||||
authrequests: {}
|
authrequests: {}
|
||||||
});
|
});
|
||||||
socket.__auth = data[1];
|
socket.__auth = verification.data;
|
||||||
socket.__userid = user.id;
|
socket.__userid = user.id;
|
||||||
user.sockets.push(socket);
|
user.sockets.push(socket);
|
||||||
respond({
|
respond({
|
||||||
success: true,
|
success: true,
|
||||||
instance: {
|
instance: {
|
||||||
id: vybe.instance.id
|
id: celi.instance.id
|
||||||
},
|
},
|
||||||
id: user.id,
|
id: user.id,
|
||||||
name: user.name,
|
name: user.name,
|
||||||
|
@ -205,7 +198,7 @@ async function authenticate(msg, respond, socket) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function authorize_key(msg, respond) {
|
async function authorize_key(msg, respond) {
|
||||||
let authrequest = vybe.users[msg.auth_user.id].authrequests[msg.id];
|
let authrequest = celi.users[msg.auth_user.id].authrequests[msg.id];
|
||||||
if (!authrequest) {
|
if (!authrequest) {
|
||||||
return respond({
|
return respond({
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -226,8 +219,8 @@ async function update_user(msg, respond) {
|
||||||
await db.query(
|
await db.query(
|
||||||
`update user set displayname = ?, bio = ?, public = ? where id = ?`,
|
`update user set displayname = ?, bio = ?, public = ? where id = ?`,
|
||||||
[msg.displayname, msg.bio, !!msg.public, msg.auth_user.id]);
|
[msg.displayname, msg.bio, !!msg.public, msg.auth_user.id]);
|
||||||
vybe.users[msg.auth_user.id].displayname = msg.displayname;
|
celi.users[msg.auth_user.id].displayname = msg.displayname;
|
||||||
vybe.users[msg.auth_user.id].bio = msg.bio;
|
celi.users[msg.auth_user.id].bio = msg.bio;
|
||||||
respond({ success: true });
|
respond({ success: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue