thread members
							parent
							
								
									af690ebea9
								
							
						
					
					
						commit
						e9f3b3f15a
					
				|  | @ -3,21 +3,36 @@ import loadMessages from '/message.js'; | |||
| import loadSpace from '/space.js'; | ||||
| 
 | ||||
| function chooseThread() { | ||||
| 	if (window.threadId) { | ||||
| 		if (window.threadId === this.thread.id) | ||||
| 	if (window.currentThread) { | ||||
| 		if (window.currentThread.id === this.thread.id) | ||||
| 			return; | ||||
| 		document.getElementById(`thread${window.threadId}`) | ||||
| 		document.getElementById(`thread${window.currentThread.id}`) | ||||
| 			.classList.remove('active'); | ||||
| 	} | ||||
| 	document.getElementById('threadname').textContent = this.thread.name; | ||||
| 	this.classList.add('active'); | ||||
| 	window.threadId = this.thread.id; | ||||
| 	window.currentThread = this.thread; | ||||
| 	loadMessages(); | ||||
| 	if (this.thread.permissions.post) | ||||
| 		document.getElementById('msginput').classList.remove('hidden'); | ||||
| 	else | ||||
| 		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'}`;
 | ||||
| 		document.getElementById('memberlist').replaceChildren( | ||||
| 			...msg.thread.members.map(member => | ||||
| 				html.node`<p class='member'>${member.name}</p>`) | ||||
| 		); | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| function switchTab(tab) { | ||||
|  | @ -116,7 +131,7 @@ function newThread() { | |||
| 		window.threadmembers = [window.name]; | ||||
| 		document.getElementById('home') | ||||
| 			.insertAdjacentElement('afterend', html.node` | ||||
| 				<hr id='createseparator' class='separator' color='#666'>`)
 | ||||
| 				<hr id='createseparator' class='separator' color='#505050'>`)
 | ||||
| 			.insertAdjacentElement('afterend', html.node` | ||||
| 				<form id='createthread' class='column' onsubmit=${createThread}> | ||||
| 					<h3>create thread</h3> | ||||
|  | @ -156,7 +171,7 @@ function newThread() { | |||
| 
 | ||||
| function clickedTab(event) { | ||||
| 	switchTab(event.target); | ||||
| 	document.getElementById(`thread${window.threadId}`).tab = event.target.id; | ||||
| 	document.getElementById(`thread${window.currentThread.id}`).tab = event.target.id; | ||||
| } | ||||
| 
 | ||||
| // main app html
 | ||||
|  | @ -172,12 +187,12 @@ document.body.append(html.node` | |||
| 			document.getElementById('profile').classList.toggle('hidden') | ||||
| 		}>${window.name}</div> | ||||
| 	</div> | ||||
| 	<hr class='separator' color='#666'> | ||||
| 	<hr class='separator' color='#505050'> | ||||
| 	<div id='profile' class='column hidden'> | ||||
| 		<p><strong>authentication requests</strong></p> | ||||
| 		<div id='authrequests'></div> | ||||
| 	</div> | ||||
| 	<hr class='separator' color='#666'> | ||||
| 	<hr class='separator' color='#505050'> | ||||
| 	<div id='thread' class='column'> | ||||
| 		<div id='content'> | ||||
| 			<div id='title'> | ||||
|  | @ -195,9 +210,10 @@ document.body.append(html.node` | |||
| 			<div id='message' class='tabcontent'></div> | ||||
| 			<div id='space' class='tabcontent hidden'></div> | ||||
| 		</div> | ||||
| 		<hr class='separator' color='#666'> | ||||
| 		<hr class='separator' color='#505050'> | ||||
| 		<div id='members' class='hidden'> | ||||
| 			<p id='visibility'></p> | ||||
| 			<p><strong>members</strong></p> | ||||
| 			<div id='memberlist'> | ||||
| 			</div> | ||||
| 		</div> | ||||
|  | @ -220,10 +236,8 @@ window.socket.on('new_thread', thread => { | |||
| }); | ||||
| 
 | ||||
| window.emit('list_threads', {}, msg => { | ||||
| 	const threadlist = document.getElementById('threadlist') | ||||
| 	threadlist.innerHTML = ''; | ||||
| 	for (let thread of msg.threads) | ||||
| 		threadlist.appendChild(makeThread(thread)); | ||||
| 	const threadlist = document.getElementById('threadlist'); | ||||
| 	threadlist.replaceChildren(...msg.threads.map(makeThread)); | ||||
| 	chooseThread.call(threadlist.firstChild); | ||||
| }); | ||||
| 
 | ||||
|  |  | |||
|  | @ -170,15 +170,11 @@ | |||
| 				flex: 1; | ||||
| 				overflow: auto; | ||||
| 			} | ||||
| 			#members { | ||||
| 				flex: 1; | ||||
| 				max-width: 250px; | ||||
| 			} | ||||
| 			#msginput { | ||||
| 				display: flex; | ||||
| 				flex-direction: row; | ||||
| 				> * { | ||||
| 					margin: 3px; | ||||
| 					margin: 2px; | ||||
| 				} | ||||
| 			} | ||||
| 			#msg { | ||||
|  | @ -191,6 +187,16 @@ | |||
| 			#loadmore { | ||||
| 				margin-bottom: 10px; | ||||
| 			} | ||||
| 			#members { | ||||
| 				flex: 1; | ||||
| 				max-width: 250px; | ||||
| 				> * { | ||||
| 					margin: 4px; | ||||
| 				} | ||||
| 			} | ||||
| 			#visibility { | ||||
| 				white-space: pre-line; | ||||
| 			} | ||||
| 			.member { | ||||
| 				margin: 5px 0; | ||||
| 			} | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ function sendMessage(e) { | |||
| 		return; | ||||
| 	window.emit('send_message', { | ||||
| 		message: msg.value, | ||||
| 		thread: window.threadId | ||||
| 		thread: window.currentThread.id | ||||
| 	}); | ||||
| 	msg.value = ''; | ||||
| } | ||||
|  | @ -16,7 +16,7 @@ function sendMessage(e) { | |||
| let earliestMessage; | ||||
| 
 | ||||
| window.socket.on('new_message', message => { | ||||
| 	if (message.thread !== window.threadId) | ||||
| 	if (message.thread !== window.currentThread.id) | ||||
| 		return; | ||||
| 	const messages = document.getElementById('messages'); | ||||
| 	let scroll = messages.scrollHeight - messages.scrollTop <= messages.clientHeight; | ||||
|  | @ -54,7 +54,7 @@ function loadMessages() { | |||
| 		'get_history', | ||||
| 		{ | ||||
| 			before: earliestMessage, | ||||
| 			thread: window.threadId | ||||
| 			thread: window.currentThread.id | ||||
| 		}, | ||||
| 		msg => { | ||||
|          if (!msg.success) | ||||
|  |  | |||
|  | @ -144,11 +144,11 @@ export default function loadSpace() { | |||
| 			editing.focus(); | ||||
| 		}; | ||||
| 	} | ||||
| 	if (spaceId === window.threadId) | ||||
| 	if (spaceId === window.window.currentThread.id) | ||||
| 		return; | ||||
| 	spaceId = window.threadId; | ||||
| 	spaceId = window.window.currentThread.id; | ||||
| 	space.innerHTML = ''; | ||||
| 	window.emit('get_space', { thread: window.threadId }, msg => { | ||||
| 	window.emit('get_space', { thread: window.window.currentThread.id }, msg => { | ||||
| 		if (!msg.success) | ||||
| 			console.log('get space failed: ' + msg.message); | ||||
| 		for (const span of msg.spans) | ||||
|  |  | |||
|  | @ -0,0 +1,64 @@ | |||
| const db = require('../db'); | ||||
| const authwrap = require('../authwrap'); | ||||
| const check_permission = require('../check_permission'); | ||||
| 
 | ||||
| const get_thread = async (msg, respond) => { | ||||
| 	if (!msg.thread) { | ||||
| 		return respond({ | ||||
| 			success: false, | ||||
| 			message: 'thread ID required' | ||||
| 		}); | ||||
| 	} | ||||
| 	if (!(await check_permission(msg.auth_user.id, msg.thread)).view) { | ||||
| 		return respond({ | ||||
| 			success: false, | ||||
| 			message: "you can't view this thread" | ||||
| 		}); | ||||
| 	} | ||||
| 	const thread = await db.query( | ||||
| 		`select thread.name, user.name as user, user.id from thread
 | ||||
| 		left join member on thread.id = member.thread | ||||
| 		left join user on user.id = member.user | ||||
| 		where thread.id = ?`,
 | ||||
| 		[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 = ?`,
 | ||||
| 		[msg.thread] | ||||
| 	); | ||||
| 	let threadperms = {}; | ||||
| 	let members = Object.fromEntries(thread.rows.map(member => [member.id, 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 | ||||
| 			}; | ||||
| 		} | ||||
| 		else | ||||
| 			(threadperms[permission.type] || (threadperms[permission.type] = {})) | ||||
| 				[permission.permission] = { | ||||
| 					value: permission.value, | ||||
| 					mutable: permission.mutable | ||||
| 				}; | ||||
| 	} | ||||
| 	return respond({ | ||||
| 		success: true, | ||||
| 		thread: { | ||||
| 			name: thread.rows[0].name, | ||||
| 			permissions: threadperms, | ||||
| 			members: Object.entries(members).map(member => ({ | ||||
| 				id: member[0], | ||||
| 				name: member[1] | ||||
| 			})) | ||||
| 		} | ||||
| 	}); | ||||
| }; | ||||
| 
 | ||||
| module.exports = authwrap(get_thread); | ||||
		Loading…
	
		Reference in New Issue