stuff n tabs
parent
8cd970e4f8
commit
0b830174d3
|
@ -58,10 +58,14 @@ function addMember() {
|
||||||
|
|
||||||
async function createThread(e) {
|
async function createThread(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
let members = window.threadmembers.map(name => { name });
|
let name = document.getElementById("newthreadname");
|
||||||
|
if (!name.value) {
|
||||||
|
name.insertAdjacentHTML('afterend', `<p>name cannot be empty</p>`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let members = window.threadmembers.map(name => ({ name }));
|
||||||
const perms = document.querySelector(
|
const perms = document.querySelector(
|
||||||
'input[name="permissions"]:checked'
|
'input[name="permissions"]:checked').value;
|
||||||
).value;
|
|
||||||
if (perms === "private_view")
|
if (perms === "private_view")
|
||||||
members = (await new Promise(resolve =>
|
members = (await new Promise(resolve =>
|
||||||
window.emit("get_keys", { names: window.threadmembers }, resolve)
|
window.emit("get_keys", { names: window.threadmembers }, resolve)
|
||||||
|
@ -98,12 +102,12 @@ async function createThread(e) {
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
window.emit("create_thread", {
|
window.emit("create_thread", {
|
||||||
name: document.getElementById("newthreadname").value,
|
name: name.value,
|
||||||
permissions,
|
permissions,
|
||||||
members
|
members
|
||||||
}, msg => {
|
}, msg => {
|
||||||
chooseThread({
|
chooseThread({
|
||||||
name: document.getElementById("newthreadname").value,
|
name: name.value,
|
||||||
id: msg.id
|
id: msg.id
|
||||||
});
|
});
|
||||||
document.getElementById('createthread').remove();
|
document.getElementById('createthread').remove();
|
||||||
|
@ -138,12 +142,12 @@ function newThread(e) {
|
||||||
<label for="newthreadname">thread name</label>
|
<label for="newthreadname">thread name</label>
|
||||||
<input type="text" id="newthreadname" />
|
<input type="text" id="newthreadname" />
|
||||||
<p id='permissions'>thread permissions</p>
|
<p id='permissions'>thread permissions</p>
|
||||||
<input type="radio" id="public" name="permissions" value="public" />
|
<input type="radio" id="public" name="permissions" value="public" checked />
|
||||||
<label for="public">anyone can view and post</label><br />
|
<label for="public">anyone can view and post</label><br />
|
||||||
<input type="radio" id="private_post"
|
<input type="radio" id="private_post"
|
||||||
name="permissions" value="private_post"
|
name="permissions" value="private_post"
|
||||||
/>
|
/>
|
||||||
<label for="private_post">only members can post, anyone can view</label><br/>
|
<label for="private_post">anyone can view, only members can post</label><br/>
|
||||||
<input type="radio" id="private_view"
|
<input type="radio" id="private_view"
|
||||||
name="permissions" value="private_view"
|
name="permissions" value="private_view"
|
||||||
/>
|
/>
|
||||||
|
@ -168,27 +172,41 @@ function newThread(e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function switchTab(event){
|
||||||
|
for (let tab of document.querySelectorAll('.tab'))
|
||||||
|
tab.classList.remove('active');
|
||||||
|
for (let tab of document.querySelectorAll('.tabcontent'))
|
||||||
|
tab.classList.add('hidden');
|
||||||
|
event.target.classList.add('active');
|
||||||
|
document.getElementById(event.target.id.substring(0, event.target.id.length - 3))
|
||||||
|
.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
render(document.body, html`
|
render(document.body, html`
|
||||||
<div id="app">
|
<div id="threads" class="column">
|
||||||
<div id="threads" class="column">
|
<h3>vybe</h3>
|
||||||
<h1>vybe</h1>
|
<h4>threads</h4>
|
||||||
<h3>threads</h3>
|
<div id="threadlist">loading...</div>
|
||||||
<div id="threadlist">loading...</div>
|
<button id='newthread' onclick=${newThread}>create</button>
|
||||||
<button id='newthread' onclick=${newThread}>create</button>
|
</div>
|
||||||
|
<div id="thread" class="column">
|
||||||
|
<div id='title'>
|
||||||
|
thread: <strong id="threadname">meow</strong>
|
||||||
</div>
|
</div>
|
||||||
<div id="thread" class="column">
|
<button id='messagetab' class='tab active' onclick=${switchTab}>messages</button>
|
||||||
<h3>
|
<button id='spacetab' class='tab' onclick=${switchTab}>space</button>
|
||||||
thread: <strong id="threadname">meow</strong>
|
<button id="loadmore" class="hidden" onclick=${loadMessages}>load more messages</button>
|
||||||
</h3>
|
<div id='message' class='tabcontent'>
|
||||||
<h3>messages</h3>
|
<div id='messages'>
|
||||||
<button id="loadmore" class="hidden" onclick=${loadMessages}>load more messages</button>
|
</div>
|
||||||
<div id="messages"></div>
|
|
||||||
<form id="msginput" onsubmit=${sendMessage}>
|
<form id="msginput" onsubmit=${sendMessage}>
|
||||||
<input type="text" placeholder="write a message..." id="msg" />
|
<input type="text" placeholder="write a message..." id="msg" />
|
||||||
<button type="submit" class="hidden" id="sendmsg"></button>
|
<button type="submit" class="hidden" id="sendmsg"></button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>`);
|
<div id='space' class='tabcontent'></div>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
|
||||||
window.socket.on("new_message", (msg) => {
|
window.socket.on("new_message", (msg) => {
|
||||||
if (msg.thread !== window.currentThreadId)
|
if (msg.thread !== window.currentThreadId)
|
||||||
|
|
|
@ -46,15 +46,16 @@ render(document.body, html`
|
||||||
});
|
});
|
||||||
const priv = await openpgp.readKey({ armoredKey: keys.privateKey });
|
const priv = await openpgp.readKey({ armoredKey: keys.privateKey });
|
||||||
const pub = await openpgp.readKey({ armoredKey: keys.publicKey });
|
const pub = await openpgp.readKey({ armoredKey: keys.publicKey });
|
||||||
window.keys = { priv, pub };
|
|
||||||
localStorage.setItem("keys", JSON.stringify(keys));
|
|
||||||
localStorage.setItem("name", name);
|
|
||||||
window.name = name;
|
|
||||||
window.emit("create_user", { name, pubkey: keys.publicKey }, msg => {
|
window.emit("create_user", { name, pubkey: keys.publicKey }, msg => {
|
||||||
if (!msg.success) {
|
if (!msg.success) {
|
||||||
console.log('create user failed');
|
document.querySelector('#registerform').insertAdjacentHTML('afterend', `
|
||||||
|
<p>${msg.message}</p>`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
window.keys = { priv, pub };
|
||||||
|
localStorage.setItem("keys", JSON.stringify(keys));
|
||||||
|
localStorage.setItem("name", name);
|
||||||
|
window.name = name;
|
||||||
auth();
|
auth();
|
||||||
});
|
});
|
||||||
}} id="registerform">
|
}} id="registerform">
|
||||||
|
|
|
@ -27,11 +27,8 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
min-width: min-content;
|
min-width: min-content;
|
||||||
}
|
}
|
||||||
h1 {
|
h3, h4 {
|
||||||
margin: 0;
|
margin: 10px 0;
|
||||||
}
|
|
||||||
h3 {
|
|
||||||
margin: 11px 0;
|
|
||||||
}
|
}
|
||||||
button {
|
button {
|
||||||
border-color: #767676;
|
border-color: #767676;
|
||||||
|
@ -39,12 +36,6 @@
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
#app {
|
|
||||||
display: contents;
|
|
||||||
}
|
|
||||||
#app.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.column {
|
.column {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
|
@ -53,18 +44,41 @@
|
||||||
#threads {
|
#threads {
|
||||||
max-width: 250px;
|
max-width: 250px;
|
||||||
}
|
}
|
||||||
.thread:hover {
|
|
||||||
background-color: #3b3b3b;
|
|
||||||
}
|
|
||||||
.thread.selected {
|
.thread.selected {
|
||||||
background-color: #4f4f4f;
|
background-color: #4f4f4f;
|
||||||
}
|
}
|
||||||
|
.thread:hover {
|
||||||
|
background-color: #3b3b3b;
|
||||||
|
}
|
||||||
#newthread {
|
#newthread {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
#createthread {
|
||||||
|
max-width: 350px;
|
||||||
|
}
|
||||||
#permissions {
|
#permissions {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
#title {
|
||||||
|
margin: 4px 2px;
|
||||||
|
}
|
||||||
|
.tab {
|
||||||
|
border: 0;
|
||||||
|
margin-top: 2px;
|
||||||
|
padding: 5px 7px;
|
||||||
|
color: #ccc;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.tab.active {
|
||||||
|
background-color: #4f4f4f;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.tab:hover {
|
||||||
|
background-color:#3b3b3b;
|
||||||
|
}
|
||||||
|
#messages {
|
||||||
|
margin: 4px 2px;
|
||||||
|
}
|
||||||
#msginput {
|
#msginput {
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
5
index.js
5
index.js
|
@ -32,6 +32,11 @@ io.on("connection", (socket) => {
|
||||||
events[event](msg, callback, socket, io)
|
events[event](msg, callback, socket, io)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
socket.on('disconnect', reason => {
|
||||||
|
let sockets = io.cache[socket.username];
|
||||||
|
if (sockets)
|
||||||
|
sockets.splice(sockets.indexOf(socket.id), 1);
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
server.listen(PORT, () => {
|
server.listen(PORT, () => {
|
||||||
|
|
|
@ -42,7 +42,7 @@ const authenticate = async (msg, respond, socket, io) => {
|
||||||
result.rows[0].id,
|
result.rows[0].id,
|
||||||
data[1],
|
data[1],
|
||||||
]);
|
]);
|
||||||
socket.userid = result.rows[0].id;
|
socket.username = msg.name;
|
||||||
if (io.cache[msg.name]) {
|
if (io.cache[msg.name]) {
|
||||||
io.cache[msg.name].push(socket.id);
|
io.cache[msg.name].push(socket.id);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,109 +2,108 @@ const db = require("../db");
|
||||||
const authwrap = require("./authwrap");
|
const authwrap = require("./authwrap");
|
||||||
|
|
||||||
const create_thread = async (msg, respond, socket, io) => {
|
const create_thread = async (msg, respond, socket, io) => {
|
||||||
// validate inputs
|
// validate inputs
|
||||||
if (!msg.name) {
|
if (typeof msg.name !== 'string') {
|
||||||
return respond({
|
return respond({
|
||||||
success: false,
|
success: false,
|
||||||
message: "thread name required",
|
message: "thread name required",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (msg.name.length > 200) {
|
if (msg.name.length > 200) {
|
||||||
return respond({
|
return respond({
|
||||||
success: false,
|
success: false,
|
||||||
message: "thread name 200 chars max",
|
message: "thread name 200 chars max",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// add to db
|
// add to db
|
||||||
const insert = await db.query(
|
const insert = await db.query(
|
||||||
"insert into threads (name, creator) values (?, ?) returning id",
|
"insert into threads (name, creator) values (?, ?) returning id",
|
||||||
[msg.name, msg.auth_user.id]
|
[msg.name, msg.auth_user.id]
|
||||||
);
|
);
|
||||||
const thread_id = insert.rows[0].id;
|
const thread_id = insert.rows[0].id;
|
||||||
// set up permissions
|
// set up permissions
|
||||||
if (!msg.permissions || !msg.permissions.view_limited) {
|
if (!msg.permissions || !msg.permissions.view_limited) {
|
||||||
await db.query(
|
await db.query(
|
||||||
`insert into permissions (thread, type, mutable, permission, value)
|
`insert into permissions (thread, type, mutable, permission, value)
|
||||||
values (?, ?, ?, ?, ?)`,
|
values (?, ?, ?, ?, ?)`,
|
||||||
[thread_id, "everyone", false, "view", "true"]
|
[thread_id, "everyone", false, "view", "true"]
|
||||||
);
|
);
|
||||||
if (!msg.permissions || !msg.permissions.post_limited) {
|
if (!msg.permissions || !msg.permissions.post_limited) {
|
||||||
await db.query(
|
await db.query(
|
||||||
`insert into permissions (thread, type, mutable, permission, value)
|
`insert into permissions (thread, type, mutable, permission, value)
|
||||||
values (?, ?, ?, ?, ?)`,
|
values (?, ?, ?, ?, ?)`,
|
||||||
[thread_id, "everyone", false, "post", "true"]
|
[thread_id, "everyone", false, "post", "true"]
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
await db.query(
|
await db.query(
|
||||||
`insert into permissions (thread, type, mutable, permission, value)
|
`insert into permissions (thread, type, mutable, permission, value)
|
||||||
values (?, ?, ?, ?, ?)`,
|
values (?, ?, ?, ?, ?)`,
|
||||||
[thread_id, "members", false, "post", "true"]
|
[thread_id, "members", false, "post", "true"]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await db.query(
|
await db.query(
|
||||||
`insert into permissions (thread, type, mutable, permission, value)
|
`insert into permissions (thread, type, mutable, permission, value)
|
||||||
values (?, ?, ?, ?, ?)`,
|
values (?, ?, ?, ?, ?)`,
|
||||||
[thread_id, "members", false, "view", "true"]
|
[thread_id, "members", false, "view", "true"]
|
||||||
);
|
);
|
||||||
await db.query(
|
await db.query(
|
||||||
`insert into permissions (thread, type, mutable, permission, value)
|
`insert into permissions (thread, type, mutable, permission, value)
|
||||||
values (?, ?, ?, ?, ?)`,
|
values (?, ?, ?, ?, ?)`,
|
||||||
[thread_id, "members", false, "post", "true"]
|
[thread_id, "members", false, "post", "true"]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// add members
|
// add members
|
||||||
for (let user of msg.members) {
|
for (let user of msg.members) {
|
||||||
// get user id
|
if (!user) continue;
|
||||||
const id = await db.query("select id from users where name = ?", [
|
// get user id
|
||||||
user.name,
|
const id = await db.query("select id from users where name = ?", [
|
||||||
]);
|
user.name,
|
||||||
if (id.rows.length > 0) {
|
]);
|
||||||
const user_id = id.rows[0].id;
|
if (id.rows.length > 0) {
|
||||||
await db.query(
|
const user_id = id.rows[0].id;
|
||||||
"insert into members (thread, user, key_delivery) values (?, ?, ?)",
|
await db.query(
|
||||||
[thread_id, user_id, user.key]
|
"insert into members (thread, user, key_delivery) values (?, ?, ?)",
|
||||||
);
|
[thread_id, user_id, user.key]
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
const member_perms = {
|
}
|
||||||
is_member: true,
|
if (!msg.permissions || !msg.permissions.view_limited) {
|
||||||
view: true,
|
for (let username in io.cache) {
|
||||||
post: true,
|
for (let socket of io.cache[username]) {
|
||||||
};
|
io.to(socket).emit("new_thread", {
|
||||||
const general_perms = {
|
name: msg.name,
|
||||||
is_member: false,
|
id: insert.rows[0].id,
|
||||||
view: !msg.permissions || !msg.permissions.view_limited,
|
permissions: {
|
||||||
post: !msg.permissions || !msg.permissions.post_limited,
|
is_member: false,
|
||||||
};
|
view: true,
|
||||||
for (let username in io.cache) {
|
post: !msg.permissions || !msg.permissions.post_limited
|
||||||
let member = msg.members.filter((i) => i.user === username)[0];
|
},
|
||||||
if (member) {
|
});
|
||||||
const sockets = io.cache[username];
|
}
|
||||||
for (let s of sockets) {
|
}
|
||||||
io.to(s).emit("new_thread", {
|
}
|
||||||
name: msg.name,
|
else {
|
||||||
id: insert.rows[0].id,
|
for (let member of msg.members) {
|
||||||
permissions: member_perms,
|
for (let socket of io.cache[member.user]) {
|
||||||
key: member.key,
|
io.to(socket).emit("new_thread", {
|
||||||
});
|
name: msg.name,
|
||||||
}
|
id: insert.rows[0].id,
|
||||||
} else if (general_perms.view) {
|
permissions: {
|
||||||
const sockets = io.cache[username];
|
is_member: true,
|
||||||
for (let s of sockets) {
|
view: true,
|
||||||
io.to(s).emit("new_thread", {
|
post: true
|
||||||
name: msg.name,
|
},
|
||||||
id: insert.rows[0].id,
|
key: member.key
|
||||||
permissions: general_perms,
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// respond
|
||||||
// respond
|
return respond({
|
||||||
return respond({
|
success: true,
|
||||||
success: true,
|
id: insert.rows[0].id,
|
||||||
id: insert.rows[0].id,
|
});
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = authwrap(create_thread);
|
module.exports = authwrap(create_thread);
|
||||||
|
|
|
@ -6,7 +6,7 @@ const create_user = async (msg, respond) => {
|
||||||
if (!msg.name) {
|
if (!msg.name) {
|
||||||
return respond({
|
return respond({
|
||||||
success: false,
|
success: false,
|
||||||
message: "Username required",
|
message: "username required",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// ensure username is not taken
|
// ensure username is not taken
|
||||||
|
@ -17,14 +17,14 @@ const create_user = async (msg, respond) => {
|
||||||
console.log(`username already exists: ${result}`);
|
console.log(`username already exists: ${result}`);
|
||||||
return respond({
|
return respond({
|
||||||
success: false,
|
success: false,
|
||||||
message: "A user with this name already exists on this server",
|
message: "a user with this name already exists on this server",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// validate public key
|
// validate public key
|
||||||
if (!msg.pubkey) {
|
if (!msg.pubkey) {
|
||||||
return respond({
|
return respond({
|
||||||
success: false,
|
success: false,
|
||||||
message: "Public key required",
|
message: "public key required",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -33,7 +33,7 @@ const create_user = async (msg, respond) => {
|
||||||
console.err("error in create_user readkey: " + err);
|
console.err("error in create_user readkey: " + err);
|
||||||
return respond({
|
return respond({
|
||||||
success: false,
|
success: false,
|
||||||
message: "Public key invalid",
|
message: "public key invalid",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// add to db
|
// add to db
|
||||||
|
|
Loading…
Reference in New Issue