diff --git a/src/extensions/chat/index.ts b/src/extensions/chat/index.ts index daa07a3..97637f3 100644 --- a/src/extensions/chat/index.ts +++ b/src/extensions/chat/index.ts @@ -15,7 +15,7 @@ export default class extends ExtensionBase { const message: message = { name: ctx.context.user?.name, pfp_code: ctx.context.user?.pfp_code, - created_at: (new Date()).toLocaleTimeString('en-US', {hour12: false}), + created_at: (Date.now()), content, } let userID = Number(ctx.context.user?.id) diff --git a/src/extensions/chat/static/chat.js b/src/extensions/chat/static/chat.js index 33ae4b8..c41f3d0 100644 --- a/src/extensions/chat/static/chat.js +++ b/src/extensions/chat/static/chat.js @@ -23,21 +23,39 @@ function sendMessage (e) { e.target.message.value = '' } +let lastMessageDate function addMessage(msg) { function field(c) { let f = document.createElement('span') f.textContent = c return f } + + const messageDate = new Date(msg.created_at); // Convert UNIX timestamp to Date + const messageDay = messageDate.toISOString().split('T', 1).at(0) + + //ADD DAY SEPARATOR + if (messageDay !== lastMessageDate) { + const separator_row = messages.insertRow(-1) + separator_row.insertCell(-1) + const separator_col = separator_row.insertCell(-1) + const date_col = separator_col.appendChild(document.createElement('div')) + date_col.classList.add('separator') + date_col.appendChild(field(messageDay)) + } + + const row = messages.insertRow(-1) const img_col = row.insertCell(-1) img_col.innerHTML = `` const col = row.insertCell(-1) const info_col = col.appendChild(document.createElement('div')) info_col.appendChild(field(msg.name)) - info_col.appendChild(field(msg.created_at)) + info_col.appendChild(field(messageDate.toLocaleTimeString('en-US', {hour12: false}))) const msg_col = col.appendChild(document.createElement('div')) msg_col.appendChild(field(msg.content)) + + lastMessageDate = messageDay } function getHistory() { diff --git a/src/extensions/chat/static/index.css b/src/extensions/chat/static/index.css index f578f6e..657b2c2 100644 --- a/src/extensions/chat/static/index.css +++ b/src/extensions/chat/static/index.css @@ -91,6 +91,10 @@ width: fit-content; } +.separator { + margin: auto; +} + /* Phones */ @media (max-width: 700px) { diff --git a/src/extensions/invite/index.html b/src/extensions/invite/index.html index 5f87456..d360296 100644 --- a/src/extensions/invite/index.html +++ b/src/extensions/invite/index.html @@ -10,9 +10,14 @@ ID - Code + Invite Code Created at - Used + {% if user.is_admin %} + Created by + Used by + {% else %} + Used + {% endif %} @@ -21,7 +26,12 @@ {{link.id}} {{link.code}} {{link.created_at}} - {{"Yes" if link.used else "No"}} + {% if user.is_admin %} + {{link.created_by}} + {{link.used_by if link.used else "Not used"}} + {% else %} + {{"Yes" if link.used else "No"}} + {% endif %} {% endfor %} diff --git a/src/extensions/invite/index.ts b/src/extensions/invite/index.ts index 67d7d33..269b01c 100644 --- a/src/extensions/invite/index.ts +++ b/src/extensions/invite/index.ts @@ -7,7 +7,6 @@ export default class extends ExtensionBase { override name = 'invite' override title = 'Invite' override tables = true - override hidden = true salt: string @@ -16,12 +15,6 @@ export default class extends ExtensionBase { return ExtensionBase.init(this, context) } - override requires_admin: Extension['requires_admin'] = (path) => { - if (['register', 'create_acc', 'register.css'].includes(path.at(0)??'')) { - return false - } - return true - } override requires_login: Extension['requires_login'] = (path) => { if (['register', 'create_acc', 'register.css'].includes(path.at(0)??'')) { return false @@ -35,14 +28,28 @@ export default class extends ExtensionBase { switch (location) { case '': - case undefined:{ - let [invite_links, err] = await knex - .query('_invite') - .select('*') - .then(unpack) - - ctx.context.invite_links = invite_links - return this.return_html(ctx, 'index') + case undefined: { + if (ctx.context.user?.is_admin) { + let [invite_links, err] = await knex + .query('_invite') + .select('_invite.id', '_invite.code', '_invite.created_at', '_invite.used', 'a.name as used_by', 'b.name as created_by') + .leftJoin(knex.raw('user a'), '_invite.user_id', '=', 'a.id') + .leftJoin(knex.raw('user b'), '_invite.created_by', '=', 'b.id') + .then(unpack) + + ctx.context.invite_links = invite_links + return this.return_html(ctx, 'index') + }else + { + let [invite_links, err] = await knex + .query('_invite') + .select('*') + .where('created_by', ctx.context.user?.id) + .then(unpack) + + ctx.context.invite_links = invite_links + return this.return_html(ctx, 'index') + } } case 'create':{ @@ -55,7 +62,7 @@ export default class extends ExtensionBase { let code = random_chars await knex.query('_invite') // @ts-expect-error - .insert({code: code}) + .insert({code: code, created_by: ctx.context.user?.id}) return this.return(ctx, undefined, location='/invite') } @@ -63,15 +70,8 @@ export default class extends ExtensionBase { const invite_code = ctx.args.get('code') if (!invite_code) return - - let [invite, err] = await knex - .query('_invite') - .select('used') - .where('code', invite_code) - .first() - .then(unpack) - - if (!err && !invite?.used){ + + if (await this.inviteCodeValid(invite_code)){ ctx.context.invite_code = invite_code return this.return_html(ctx, 'register', undefined, 500, 200, { "Set-Cookie": this.del_cookie('auth') @@ -83,7 +83,8 @@ export default class extends ExtensionBase { if (ctx.data) { let form: {invite_code?: string, username?: string, password?: string, minecraft_name?: string} = ctx.data.form - if (form.username && form.password && form.invite_code) { + const valid_invite_code = await this.inviteCodeValid(form.invite_code) + if (form.username && form.password && valid_invite_code) { form.username = form.username.substring(0, 32) this.addUser(form.username, form.password, async (id?: number, err?: Error) => { @@ -151,6 +152,24 @@ export default class extends ExtensionBase { }) } + async inviteCodeValid(code?: string): Promise{ + if (code === undefined) + return false + let [knex]: [Knex] = this.get_dependencies('Knex') + + let [invite, err] = await knex + .query('_invite') + .select('used') + .where('code', code) + .first() + .then(unpack) + + if (!err && !invite?.used) + return true + else + return false + } + private exists(name: User['name'], callback: (exists: boolean, err?: Error) => void): void { let [knex]: [Knex] = this.get_dependencies('Knex') // check if name already exists diff --git a/src/extensions/invite/static/index.css b/src/extensions/invite/static/index.css index b892790..ad92414 100644 --- a/src/extensions/invite/static/index.css +++ b/src/extensions/invite/static/index.css @@ -1,7 +1,7 @@ table { - margin: 2%; - padding-bottom: 5%; + margin: var(--margin-normal); + padding-bottom: 10px; text-align: center; font-size: smaller; } @@ -16,3 +16,9 @@ table th, td{ font-style: italic; font-weight: lighter; } + +@media (max-width: 550px) { + table { + margin: var(--margin-normal) auto; + } +} diff --git a/src/extensions/invite/tables.ts b/src/extensions/invite/tables.ts index cefcdee..5c8b1f5 100644 --- a/src/extensions/invite/tables.ts +++ b/src/extensions/invite/tables.ts @@ -3,7 +3,7 @@ import { Knex } from '../../modules.ts' export default class extends Tables { override versions(versions: VersionMap) { - versions.set('invite', 0) + versions.set('invite', 1) return versions } @@ -24,6 +24,17 @@ export default class extends Tables { // @ts-expect-error .insert({code: 'admin'}) }, + 1: async ()=>{ + await knex.schema() + .alterTable('_invite', (table) => { + table.integer('created_by') + table.foreign('created_by', 'fk_user_id').references('_root_user.id') + }) + + await knex.query('_invite') + // @ts-expect-error + .update({created_by: 1}) + }, }) return migrations