edit thread
parent
e9f3b3f15a
commit
6531e692f7
256
client/app.js
256
client/app.js
|
@ -2,13 +2,34 @@ import { render, html } from '/uhtml.js';
|
|||
import loadMessages from '/message.js';
|
||||
import loadSpace from '/space.js';
|
||||
|
||||
function setVisibility() {
|
||||
document.getElementById('visibility').innerText = `${
|
||||
window.currentThread.permissions.everyone.view.value ?
|
||||
'this thread is visible to everyone' :
|
||||
'members can view this thread'}
|
||||
${window.currentThread.permissions.everyone.post.value ?
|
||||
'anyone can post' :
|
||||
window.currentThread.permissions.members.post.value ?
|
||||
'only members can post' : 'some members can post'}`;
|
||||
}
|
||||
|
||||
function chooseThread() {
|
||||
const edit = document.getElementById('edit');
|
||||
if (window.currentThread) {
|
||||
if (window.currentThread.id === this.thread.id)
|
||||
return;
|
||||
document.getElementById(`thread${window.currentThread.id}`)
|
||||
.classList.remove('active');
|
||||
let editform = document.getElementById('editthread');
|
||||
if (editform) {
|
||||
editform.remove();
|
||||
edit.textContent = 'edit';
|
||||
}
|
||||
}
|
||||
if (this.thread.permissions.admin)
|
||||
edit.classList.remove('hidden');
|
||||
else
|
||||
edit.classList.add('hidden');
|
||||
document.getElementById('threadname').textContent = this.thread.name;
|
||||
this.classList.add('active');
|
||||
window.currentThread = this.thread;
|
||||
|
@ -19,15 +40,8 @@ function chooseThread() {
|
|||
document.getElementById('msginput').classList.add('hidden');
|
||||
switchTab(document.getElementById(this.tab));
|
||||
window.emit('get_thread', { thread: this.thread.id }, msg => {
|
||||
window.currentThread.members = msg.thread.members;
|
||||
document.getElementById('visibility').innerText = `${
|
||||
msg.thread.permissions.everyone?.view.value === 'true' ?
|
||||
'this thread is visible to everyone' :
|
||||
'members can view this thread'}
|
||||
${msg.thread.permissions.everyone?.post.value === 'true' ?
|
||||
'anyone can post' :
|
||||
msg.thread.permissions.members?.post.view ?
|
||||
'only members can post' : 'select members can post'}`;
|
||||
window.currentThread = msg.thread;
|
||||
setVisibility();
|
||||
document.getElementById('memberlist').replaceChildren(
|
||||
...msg.thread.members.map(member =>
|
||||
html.node`<p class='member'>${member.name}</p>`)
|
||||
|
@ -48,48 +62,23 @@ function switchTab(tab) {
|
|||
loadSpace();
|
||||
}
|
||||
|
||||
function addMember() {
|
||||
const name = document.getElementById('membername').value;
|
||||
window.threadmembers.push(name);
|
||||
document
|
||||
.getElementById('newmembers')
|
||||
.appendChild(html.node`<p class='member'>${name}</p>`);
|
||||
document.getElementById('membername').value = '';
|
||||
}
|
||||
|
||||
async function createThread(event) {
|
||||
event.preventDefault();
|
||||
let name = document.getElementById('newthreadname').value;
|
||||
if (!name) {
|
||||
document.getElementById('nameempty').classList.remove('hidden');
|
||||
document.getElementById('newnameempty').classList.remove('hidden');
|
||||
return;
|
||||
}
|
||||
let members = window.threadmembers.map(name => ({ name }));
|
||||
const perms = document.querySelector(
|
||||
'input[name="permissions"]:checked'
|
||||
'input[name="newpermissions"]:checked'
|
||||
).value;
|
||||
if (perms === 'private_view')
|
||||
members = (
|
||||
await new Promise(resolve =>
|
||||
window.emit('get_keys', { names: window.threadmembers }, resolve)
|
||||
)
|
||||
).keys;
|
||||
let permissions;
|
||||
if (perms === 'public') {
|
||||
permissions = {
|
||||
view_limited: false,
|
||||
post_limited: false
|
||||
};
|
||||
} else if (perms === 'private_post') {
|
||||
permissions = {
|
||||
view_limited: false,
|
||||
post_limited: true
|
||||
};
|
||||
} else if (perms === 'private_view') {
|
||||
permissions = {
|
||||
view_limited: true,
|
||||
post_limited: true
|
||||
};
|
||||
if (perms === 'public')
|
||||
permissions = { view_limited: false, post_limited: false };
|
||||
else if (perms === 'private_post')
|
||||
permissions = { view_limited: false, post_limited: true };
|
||||
else if (perms === 'private_view') {
|
||||
permissions = { view_limited: true, post_limited: true };
|
||||
// generate key
|
||||
/* wip
|
||||
var buf = new Uint8Array(32);
|
||||
|
@ -100,18 +89,13 @@ async function createThread(event) {
|
|||
const member = newmembers[i];
|
||||
const sig = await openpgp.encrypt({
|
||||
message: await openpgp.createMessage({ text: key }),
|
||||
signingKeys: window.keys.priv,
|
||||
signingKeys: window.keys.priv
|
||||
});
|
||||
}
|
||||
*/
|
||||
}
|
||||
window.emit(
|
||||
'create_thread',
|
||||
{
|
||||
name,
|
||||
permissions,
|
||||
members
|
||||
},
|
||||
window.emit('create_thread',
|
||||
{ name, permissions, members: window.threadmembers },
|
||||
msg => {
|
||||
chooseThread.call(document.getElementById('thread' + msg.id));
|
||||
// since the form exists, this will perform cleanup
|
||||
|
@ -121,52 +105,125 @@ async function createThread(event) {
|
|||
);
|
||||
}
|
||||
|
||||
function addMember() {
|
||||
const name = document.getElementById('membername');
|
||||
if (!name.value)
|
||||
return;
|
||||
window.threadmembers.push({ name: name.value });
|
||||
document.getElementById('newmembers')
|
||||
.appendChild(html.node`<p class='member'>${name.value}</p>`);
|
||||
name.value = '';
|
||||
}
|
||||
|
||||
function newThread() {
|
||||
let form = document.getElementById('createthread');
|
||||
if (form) {
|
||||
form.remove();
|
||||
document.getElementById('createseparator').remove();
|
||||
document.getElementById('newthread').textContent = 'create';
|
||||
} else {
|
||||
window.threadmembers = [window.name];
|
||||
document.getElementById('home')
|
||||
.insertAdjacentElement('afterend', html.node`
|
||||
<hr id='createseparator' class='separator' color='#505050'>`)
|
||||
.insertAdjacentElement('afterend', html.node`
|
||||
<form id='createthread' class='column' onsubmit=${createThread}>
|
||||
<h3>create thread</h3>
|
||||
<label for='newthreadname' class='heading'>thread name</label>
|
||||
<p id='nameempty' class='hidden'>name cannot be empty</p>
|
||||
<input type='text' id='newthreadname' />
|
||||
<p id='permissions'>thread permissions</p>
|
||||
<input type='radio' id='public' name='permissions' value='public' checked />
|
||||
<label for='public'>anyone can view and post</label><br />
|
||||
<input type='radio' id='private_post'
|
||||
name='permissions' value='private_post'
|
||||
/>
|
||||
<label for='private_post'>anyone can view, only members can post</label><br/>
|
||||
<input type='radio' id='private_view'
|
||||
name='permissions' value='private_view'
|
||||
/>
|
||||
<label for='private_view'>only members can view and post</label
|
||||
><br /><br />
|
||||
<label class='heading' for='membername'>members</label>
|
||||
<input type='text' id='membername' placeholder='username' onkeydown=${event => {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
addMember();
|
||||
}
|
||||
}}/>
|
||||
<button id='addmember' onclick=${addMember}>add</button>
|
||||
<div id='newmembers'>
|
||||
<p class='member'>${window.name}</p>
|
||||
</div>
|
||||
<br />
|
||||
<button id='submitthread' type='submit'>create</button>
|
||||
</form>
|
||||
`);
|
||||
document.getElementById('newthread').textContent = 'cancel';
|
||||
return;
|
||||
}
|
||||
window.threadmembers = [{
|
||||
name: window.name,
|
||||
permissions: { admin: 'true' }
|
||||
}];
|
||||
document.querySelector('#home + .separator').insertAdjacentElement('afterend', html.node`
|
||||
<form id='createthread' class='column' onsubmit=${createThread}>
|
||||
<h3>create thread</h3>
|
||||
<label for='newthreadname' class='heading'>thread name</label>
|
||||
<p id='newnameempty' class='hidden'>name cannot be empty</p>
|
||||
<input type='text' id='newthreadname' />
|
||||
<p id='permissions'>thread permissions</p>
|
||||
<input type='radio' name='newpermissions'
|
||||
id='public' value='public' checked />
|
||||
<label for='public'>anyone can view and post</label><br>
|
||||
<input type='radio' name='newpermissions'
|
||||
id='private_post' value='private_post' />
|
||||
<label for='private_post'>anyone can view, only members can post</label><br>
|
||||
<input type='radio' name='newpermissions'
|
||||
id='private_view' value='private_view' />
|
||||
<label for='private_view'>only members can view and post</label><br>
|
||||
<br>
|
||||
<label class='heading' for='membername'>members</label>
|
||||
<input type='text' id='membername' placeholder='username' onkeydown=${event => {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
addMember();
|
||||
}
|
||||
}} />
|
||||
<button id='addmember' type='button' onclick=${addMember}>add</button>
|
||||
<div id='newmembers'>
|
||||
<p class='member'>${window.name}</p>
|
||||
</div>
|
||||
<br>
|
||||
<button id='submitthread' type='submit'>create</button>
|
||||
</form>`);
|
||||
document.getElementById('newthread').textContent = 'cancel';
|
||||
}
|
||||
|
||||
async function saveThread(event) {
|
||||
event.preventDefault();
|
||||
let name = document.getElementById('editthreadname').value;
|
||||
if (!name) {
|
||||
document.getElementById('nameempty').classList.remove('hidden');
|
||||
return;
|
||||
}
|
||||
const perms = document.querySelector(
|
||||
'input[name="permissions"]:checked'
|
||||
).value;
|
||||
let permissions;
|
||||
if (perms === 'public')
|
||||
permissions = { view_limited: false, post_limited: false };
|
||||
else if (perms === 'private_post')
|
||||
permissions = { view_limited: false, post_limited: true };
|
||||
else if (perms === 'private_view') {
|
||||
permissions = { view_limited: true, post_limited: true };
|
||||
// todo: generate key and encrypt
|
||||
}
|
||||
window.emit('edit_thread',
|
||||
{ id: window.currentThread.id, name, permissions },
|
||||
msg => {
|
||||
if (!msg.success) {
|
||||
console.log('edit_thread failed: ', msg.message);
|
||||
return;
|
||||
}
|
||||
editThread();
|
||||
});
|
||||
}
|
||||
|
||||
function editThread() {
|
||||
let form = document.getElementById('editthread');
|
||||
if (form) {
|
||||
form.remove();
|
||||
document.getElementById('edit').textContent = 'edit';
|
||||
return;
|
||||
}
|
||||
form = html.node`
|
||||
<form id='editthread' class='column' onsubmit=${saveThread}>
|
||||
<label for='editthreadname' class='heading'>thread name</label>
|
||||
<input type='text' id='editthreadname' />
|
||||
<p id='nameempty' class='hidden'>name cannot be empty</p>
|
||||
<p id='permissions'>thread permissions</p>
|
||||
<input type='radio' name='permissions'
|
||||
id='public' value='public' />
|
||||
<label for='public'>anyone can view and post</label><br>
|
||||
<input type='radio' name='permissions'
|
||||
id='private_post' value='private_post' />
|
||||
<label for='private_post'>anyone can view, only members can post</label><br>
|
||||
<input type='radio' name='permissions'
|
||||
id='private_view' value='private_view' />
|
||||
<label for='private_view'>only members can view and post</label><br>
|
||||
<br>
|
||||
<button id='savethread'>save</button>
|
||||
</form>`;
|
||||
form['editthreadname'].value = window.currentThread.name;
|
||||
if (window.currentThread.permissions.everyone.post.value)
|
||||
form['public'].checked = true;
|
||||
else if (window.currentThread.permissions.everyone.view.value)
|
||||
form['private_post'].checked = true;
|
||||
else
|
||||
form['private_view'].checked = true;
|
||||
document.querySelector('#thread').append(form);
|
||||
document.getElementById('edit').textContent = 'cancel';
|
||||
}
|
||||
|
||||
function clickedTab(event) {
|
||||
|
@ -188,6 +245,8 @@ document.body.append(html.node`
|
|||
}>${window.name}</div>
|
||||
</div>
|
||||
<hr class='separator' color='#505050'>
|
||||
<!-- create thread column goes here -->
|
||||
<hr class='separator' color='#505050'>
|
||||
<div id='profile' class='column hidden'>
|
||||
<p><strong>authentication requests</strong></p>
|
||||
<div id='authrequests'></div>
|
||||
|
@ -196,7 +255,8 @@ document.body.append(html.node`
|
|||
<div id='thread' class='column'>
|
||||
<div id='content'>
|
||||
<div id='title'>
|
||||
thread: <strong id='threadname'>meow</strong>
|
||||
<span>thread: <strong id='threadname'>meow</strong></span>
|
||||
<button id='edit' class='hidden' onclick=${editThread}>edit</button>
|
||||
</div>
|
||||
<div id='buttons'>
|
||||
<div id='tabs'>
|
||||
|
@ -217,6 +277,7 @@ document.body.append(html.node`
|
|||
<div id='memberlist'>
|
||||
</div>
|
||||
</div>
|
||||
<hr class='separator' color='#505050'>
|
||||
</div>
|
||||
`);
|
||||
|
||||
|
@ -231,7 +292,18 @@ function makeThread(thread) {
|
|||
return node;
|
||||
}
|
||||
|
||||
window.socket.on('new_thread', thread => {
|
||||
window.socket.on('thread', thread => {
|
||||
let el = document.getElementById('thread' + thread.id);
|
||||
if (el) {
|
||||
el.thread = thread;
|
||||
el.textContent = thread.name;
|
||||
if (window.currentThread.id === thread.id) {
|
||||
Object.assign(window.currentThread, thread);
|
||||
document.getElementById('threadname').textContent = thread.name;
|
||||
setVisibility();
|
||||
}
|
||||
return;
|
||||
}
|
||||
document.getElementById('threadlist').prepend(makeThread(thread));
|
||||
});
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
button,
|
||||
input,
|
||||
.tab {
|
||||
padding: 5px 7px;
|
||||
padding: 4px 7px;
|
||||
}
|
||||
input {
|
||||
background: #1b1b1b;
|
||||
|
@ -81,9 +81,11 @@
|
|||
margin-bottom: 5px;
|
||||
display: block;
|
||||
}
|
||||
h3,
|
||||
h3 {
|
||||
margin: 0;
|
||||
}
|
||||
h4 {
|
||||
margin: 10px 0;
|
||||
margin: 6px 0;
|
||||
}
|
||||
.hidden {
|
||||
display: none !important;
|
||||
|
@ -96,7 +98,8 @@
|
|||
margin: 8px 2px;
|
||||
}
|
||||
.separator:has(+ .separator),
|
||||
.separator:has(+ *.hidden) {
|
||||
.separator:has(+ *.hidden),
|
||||
.separator:last-child {
|
||||
display: none;
|
||||
}
|
||||
#home {
|
||||
|
@ -107,6 +110,12 @@
|
|||
}
|
||||
#threads {
|
||||
margin: 3px;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
#threadlist {
|
||||
overflow: auto;
|
||||
}
|
||||
#user {
|
||||
padding: 6px;
|
||||
|
@ -127,25 +136,26 @@
|
|||
}
|
||||
#newthread {
|
||||
margin-top: 5px;
|
||||
width: fit-content;
|
||||
}
|
||||
#createthread {
|
||||
max-width: fit-content;
|
||||
overflow: auto;
|
||||
}
|
||||
#permissions {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
#thread {
|
||||
display: flex;
|
||||
margin: 0;
|
||||
}
|
||||
#content {
|
||||
margin: 2px;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
#title {
|
||||
margin: 4px;
|
||||
}
|
||||
#buttons {
|
||||
#title, #buttons {
|
||||
margin: 4px 2px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
@ -194,8 +204,12 @@
|
|||
margin: 4px;
|
||||
}
|
||||
}
|
||||
#editthread {
|
||||
max-width: fit-content;
|
||||
}
|
||||
#visibility {
|
||||
white-space: pre-line;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.member {
|
||||
margin: 5px 0;
|
||||
|
|
|
@ -7,31 +7,20 @@ const check_permission = async (user_id, thread_id) => {
|
|||
[thread_id]
|
||||
);
|
||||
// check if the user is a member
|
||||
const is_member =
|
||||
(
|
||||
await db.query('select * from member where thread = ? and user = ?', [
|
||||
thread_id,
|
||||
user_id,
|
||||
])
|
||||
const is_member = (
|
||||
await db.query('select * from member where thread = ? and user = ?',
|
||||
[thread_id, user_id])
|
||||
).rows.length > 0;
|
||||
const get_permission = (permission) => {
|
||||
const relevant = permissions.rows.filter(
|
||||
(i) => i.permission === permission
|
||||
);
|
||||
for (let i of relevant) {
|
||||
if (i.type === 'everyone' && i.value === 'true') {
|
||||
return true;
|
||||
}
|
||||
if (i.type === 'members' && i.value === 'true' && is_member) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
return {
|
||||
is_member,
|
||||
view: get_permission('view'),
|
||||
post: get_permission('post')
|
||||
};
|
||||
let perms = { is_member };
|
||||
for (let p of permissions.rows) {
|
||||
if (p.type === 'everyone' && p.value === 'true')
|
||||
perms[p.permission] = true;
|
||||
else if (p.type === 'members' && is_member && p.value === 'true')
|
||||
perms[p.permission] = true;
|
||||
else if (p.type === 'user' && p.user === user_id && p.value === 'true')
|
||||
perms[p.permission] = true;
|
||||
}
|
||||
return perms;
|
||||
};
|
||||
|
||||
module.exports = check_permission;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const db = require('../db');
|
||||
const authwrap = require('../authwrap');
|
||||
|
||||
const create_thread = async (msg, respond, socket) => {
|
||||
const create_thread = async (msg, respond) => {
|
||||
// validate inputs
|
||||
if (typeof msg.name !== 'string') {
|
||||
return respond({
|
||||
|
@ -26,52 +26,61 @@ const create_thread = async (msg, respond, socket) => {
|
|||
await db.query(
|
||||
`insert into permission (thread, type, mutable, permission, value)
|
||||
values (?, ?, ?, ?, ?)`,
|
||||
[thread_id, 'everyone', false, 'view', 'true']
|
||||
[thread_id, 'everyone', true, 'view', 'true']
|
||||
);
|
||||
if (!msg.permissions || !msg.permissions.post_limited) {
|
||||
await db.query(
|
||||
`insert into permission (thread, type, mutable, permission, value)
|
||||
values (?, ?, ?, ?, ?)`,
|
||||
[thread_id, 'everyone', false, 'post', 'true']
|
||||
[thread_id, 'everyone', true, 'post', 'true']
|
||||
);
|
||||
} else {
|
||||
await db.query(
|
||||
`insert into permission (thread, type, mutable, permission, value)
|
||||
values (?, ?, ?, ?, ?)`,
|
||||
[thread_id, 'members', false, 'post', 'true']
|
||||
[thread_id, 'members', true, 'post', 'true']
|
||||
);
|
||||
}
|
||||
} else {
|
||||
await db.query(
|
||||
`insert into permission (thread, type, mutable, permission, value)
|
||||
values (?, ?, ?, ?, ?)`,
|
||||
[thread_id, 'members', false, 'view', 'true']
|
||||
[thread_id, 'members', true, 'view', 'true']
|
||||
);
|
||||
await db.query(
|
||||
`insert into permission (thread, type, mutable, permission, value)
|
||||
values (?, ?, ?, ?, ?)`,
|
||||
[thread_id, 'members', false, 'post', 'true']
|
||||
[thread_id, 'members', true, 'post', 'true']
|
||||
);
|
||||
}
|
||||
// add members
|
||||
for (let user of msg.members) {
|
||||
if (!user) continue;
|
||||
// get user id
|
||||
const id = await db.query('select id from user where name = ?', [
|
||||
user.name,
|
||||
]);
|
||||
if (id.rows.length > 0) {
|
||||
const user_id = id.rows[0].id;
|
||||
if (Array.isArray(msg.members)) {
|
||||
for (let member of msg.members) {
|
||||
if (!member) continue;
|
||||
// get user id
|
||||
const id = await db.query('select id from user where name = ?', [
|
||||
member.name,
|
||||
]);
|
||||
if (id.rows.length === 0) {
|
||||
console.log('user not found: ' + member.name);
|
||||
continue;
|
||||
}
|
||||
await db.query(
|
||||
'insert into member (thread, user) values (?, ?)',
|
||||
[thread_id, user_id]
|
||||
[thread_id, id.rows[0].id]
|
||||
);
|
||||
if (typeof member.permissions === 'object')
|
||||
for (let permission in member.permissions)
|
||||
await db.query(`
|
||||
insert into permission (thread, type, user, mutable, permission, value)
|
||||
values (?, ?, ?, ?, ?, ?)`,
|
||||
[thread_id, 'user', id.rows[0].id, true, permission, member.permissions[permission]]);
|
||||
}
|
||||
}
|
||||
if (!msg.permissions || !msg.permissions.view_limited) {
|
||||
for (let username in vybe.users) {
|
||||
for (let socket of vybe.users[username].sockets) {
|
||||
socket.emit('new_thread', {
|
||||
socket.emit('thread', {
|
||||
name: msg.name,
|
||||
id: insert.rows[0].id,
|
||||
permissions: {
|
||||
|
@ -83,10 +92,12 @@ const create_thread = async (msg, respond, socket) => {
|
|||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (Array.isArray(msg.members)) {
|
||||
for (let member of msg.members) {
|
||||
if (!vybe.users[member.name])
|
||||
continue;
|
||||
for (let socket of vybe.users[member.name].sockets) {
|
||||
socket.emit('new_thread', {
|
||||
socket.emit('thread', {
|
||||
name: msg.name,
|
||||
id: insert.rows[0].id,
|
||||
permissions: {
|
||||
|
@ -101,7 +112,7 @@ const create_thread = async (msg, respond, socket) => {
|
|||
// respond
|
||||
return respond({
|
||||
success: true,
|
||||
id: insert.rows[0].id
|
||||
id: thread_id
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
const db = require('../db');
|
||||
const authwrap = require('../authwrap');
|
||||
const check_permission = require('../check_permission');
|
||||
|
||||
const edit_thread = async (msg, respond) => {
|
||||
// validate inputs
|
||||
if (!msg.id || typeof msg.name !== 'string') {
|
||||
return respond({
|
||||
success: false,
|
||||
message: 'invalid msg'
|
||||
});
|
||||
}
|
||||
if (msg.name.length > 200) {
|
||||
return respond({
|
||||
success: false,
|
||||
message: 'thread name 200 chars max'
|
||||
});
|
||||
}
|
||||
const perms = await check_permission(msg.auth_user.id, msg.id);
|
||||
if (!perms.admin) {
|
||||
return respond({
|
||||
success: false,
|
||||
message: "user doesn't have permission"
|
||||
});
|
||||
}
|
||||
// update name
|
||||
await db.query(
|
||||
'update thread set name = ? where id = ?',
|
||||
[msg.name, msg.id]
|
||||
);
|
||||
// update permissions
|
||||
let permissions = {};
|
||||
for (const p of (await db.query(
|
||||
`select type, permission, value, mutable
|
||||
from permission
|
||||
where type != 'user' and thread = ?`,
|
||||
[msg.id]
|
||||
)).rows) {
|
||||
(permissions[p.type] || (permissions[p.type] = {}))
|
||||
[p.permission] = {
|
||||
value: p.value,
|
||||
mutable: p.mutable
|
||||
};
|
||||
}
|
||||
async function setPermission(type, permission, value) {
|
||||
if (permissions[type] && permissions[type][permission]) {
|
||||
if (!permissions[type][permission].mutable) {
|
||||
respond({
|
||||
success: false,
|
||||
message: 'permission not mutable'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (permissions[type][permission].value !== value) {
|
||||
await db.query(`
|
||||
update permission set value = ?
|
||||
where thread = ? and type = ? and permission = ?`,
|
||||
[value, msg.id, type, permission]
|
||||
);
|
||||
permissions[type][permission].value = value;
|
||||
}
|
||||
}
|
||||
else {
|
||||
await db.query(
|
||||
`insert into permission (thread, type, mutable, permission, value)
|
||||
values (?, ?, ?, ?, ?)`,
|
||||
[msg.id, type, true, permission, value]
|
||||
);
|
||||
(permissions[type] || (permissions[type] = {}))
|
||||
[permission] = {
|
||||
value,
|
||||
mutable: true
|
||||
};
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!msg.permissions || !msg.permissions.view_limited) {
|
||||
if (!await setPermission('everyone', 'view', 'true'))
|
||||
return;
|
||||
if (!msg.permissions || !msg.permissions.post_limited) {
|
||||
if (!await setPermission('everyone', 'post', 'true'))
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (!await setPermission('members', 'post', 'true'))
|
||||
return;
|
||||
if (!await setPermission('everyone', 'post', 'false'))
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!await setPermission('members', 'view', 'true'))
|
||||
return;
|
||||
if (!await setPermission('members', 'post', 'true'))
|
||||
return;
|
||||
if (!await setPermission('everyone', 'view', 'false'))
|
||||
return;
|
||||
if (!await setPermission('everyone', 'post', 'false'))
|
||||
return;
|
||||
}
|
||||
if (!msg.permissions || !msg.permissions.view_limited) {
|
||||
for (let username in vybe.users) {
|
||||
for (let socket of vybe.users[username].sockets) {
|
||||
socket.emit('thread', {
|
||||
name: msg.name,
|
||||
id: msg.id,
|
||||
permissions: {
|
||||
is_member: false,
|
||||
view: true,
|
||||
post: !msg.permissions || !msg.permissions.post_limited,
|
||||
...permissions
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let member of (await db.query(
|
||||
`select user.name from thread
|
||||
join member on thread.id = member.thread
|
||||
join user on user.id = member.user
|
||||
where thread.id = ?`,
|
||||
[msg.id]
|
||||
)).rows) {
|
||||
if (!vybe.users[member.name])
|
||||
continue;
|
||||
for (let socket of vybe.users[member.name].sockets) {
|
||||
socket.emit('thread', {
|
||||
name: msg.name,
|
||||
id: msg.id,
|
||||
permissions: {
|
||||
is_member: true,
|
||||
view: true,
|
||||
post: true,
|
||||
...permissions
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return respond({
|
||||
success: true
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = authwrap(edit_thread);
|
|
@ -9,7 +9,8 @@ const get_thread = async (msg, respond) => {
|
|||
message: 'thread ID required'
|
||||
});
|
||||
}
|
||||
if (!(await check_permission(msg.auth_user.id, msg.thread)).view) {
|
||||
let perms = await check_permission(msg.auth_user.id, msg.thread);
|
||||
if (!perms.view) {
|
||||
return respond({
|
||||
success: false,
|
||||
message: "you can't view this thread"
|
||||
|
@ -23,39 +24,50 @@ const get_thread = async (msg, respond) => {
|
|||
[msg.thread]
|
||||
);
|
||||
const permissions = await db.query(
|
||||
`select permission.type, permission.user, permission.permission, permission.value, permission.mutable
|
||||
from thread
|
||||
join permission on thread.id = permission.thread
|
||||
where thread.id = ?`,
|
||||
`select type, user, permission, value, mutable
|
||||
from permission where thread = ?`,
|
||||
[msg.thread]
|
||||
);
|
||||
let threadperms = {};
|
||||
let members = Object.fromEntries(thread.rows.map(member => [member.id, member.user]));
|
||||
let members = Object.fromEntries(thread.rows.map(member =>
|
||||
[member.id, { name: member.user }]
|
||||
));
|
||||
for (let permission of permissions.rows) {
|
||||
const member = members[permission.user];
|
||||
if (member) {
|
||||
if (!member.permissions)
|
||||
member.permissions = {};
|
||||
member.permissions[permission.permission] = {
|
||||
value: permission.value,
|
||||
mutable: permission.mutable
|
||||
};
|
||||
}
|
||||
if (member)
|
||||
(member.permissions || (member.permissions = {}))
|
||||
[permission.permission] = {
|
||||
value: permission.value,
|
||||
mutable: permission.mutable
|
||||
};
|
||||
else
|
||||
(threadperms[permission.type] || (threadperms[permission.type] = {}))
|
||||
(perms[permission.type] || (perms[permission.type] = {}))
|
||||
[permission.permission] = {
|
||||
value: permission.value,
|
||||
mutable: permission.mutable
|
||||
};
|
||||
}
|
||||
function makeBool(type, permission) {
|
||||
if (perms[type]) {
|
||||
if (perms[type][permission])
|
||||
perms[type][permission].value = perms[type][permission].value === 'true' ? true : false;
|
||||
else
|
||||
perms[type][permission] = { value: false, mutable: true };
|
||||
} else
|
||||
(perms[type] = {})[permission] = { value: false, mutable: true };
|
||||
}
|
||||
makeBool('everyone', 'view');
|
||||
makeBool('everyone', 'post');
|
||||
makeBool('members', 'view');
|
||||
makeBool('members', 'post');
|
||||
return respond({
|
||||
success: true,
|
||||
thread: {
|
||||
id: msg.thread,
|
||||
name: thread.rows[0].name,
|
||||
permissions: threadperms,
|
||||
permissions: perms,
|
||||
members: Object.entries(members).map(member => ({
|
||||
id: member[0],
|
||||
name: member[1]
|
||||
...member[1]
|
||||
}))
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue