1 Commits

Author SHA1 Message Date
8f0f1efb88 v1.0.1 (#2)
* fix: Resolves Slasherss1/ipwa#6

* fix: minor issues with keys

* fix: chrome android raises some issues which i couldn't find a fix for on google.

* fix: Added attendence clear button and notes.

* fix: bumped version number
2025-05-13 19:30:18 +02:00
9 changed files with 46 additions and 19 deletions

2
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{ {
"name": "backend2", "name": "backend2",
"version": "1.0.0", "version": "1.0.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "backend2", "name": "backend2",
"version": "1.0.0", "version": "1.0.1",
"description": "", "description": "",
"main": "src/index.js", "main": "src/index.js",
"type": "module", "type": "module",

View File

@@ -1,7 +1,15 @@
import { Job, scheduleJob } from "node-schedule"; import { Job, scheduleJob } from "node-schedule";
interface IAttendence {
auto: {
_id: string;
hour?: string
}[];
notes: string;
}
class Attendence { class Attendence {
private attendence = new Map<string, {_id: string, hour?: string}[]>(); private attendence = new Map<string, IAttendence>();
private job: Job private job: Job
constructor () { constructor () {
this.job = scheduleJob("0 0 * * *", () => { this.job = scheduleJob("0 0 * * *", () => {
@@ -9,18 +17,22 @@ class Attendence {
}) })
} }
setRoom (room: string, att: {_id: string, hour?: string}[]) { setRoom (room: string, att: IAttendence) {
this.attendence.set(room, att) this.attendence.set(room, att)
} }
clearRoom (room: string) {
this.attendence.delete(room)
}
getRoom (room: string) { getRoom (room: string) {
return this.attendence.get(room) return this.attendence.get(room)
} }
summary () { summary () {
var summary: {room: string, hours: string[]}[] = [] var summary: {room: string, hours: string[], notes: string}[] = []
this.attendence.forEach((v, k) => { this.attendence.forEach((v, k) => {
summary.push({room: k, hours: v.map(i => i.hour)}) summary.push({room: k, hours: v.auto.map(i => i.hour), notes: v.notes})
}) })
return summary return summary
} }

View File

@@ -54,8 +54,8 @@ app.use(passport.session())
//#region Passport strategies initialization //#region Passport strategies initialization
passport.use("normal",new LocalStrategy(async function verify(uname,pass,done) { passport.use("normal",new LocalStrategy(async function verify(uname,pass,done) {
let query = await User.findOne({uname: uname.toLowerCase()}) let query = await User.findOne({uname: uname.toLowerCase()})
if (query.locked == true) return done(null, false)
if (query) { if (query) {
if (query.locked == true) return done(null, false)
if (await bcrypt.compare(pass, query.pass)) { if (await bcrypt.compare(pass, query.pass)) {
return done(null, query) return done(null, query)
} else done(null, false) } else done(null, false)

View File

@@ -1,7 +1,6 @@
import { PushSubscription, RequestOptions, VapidKeys, sendNotification } from "web-push"; import { PushSubscription, RequestOptions, VapidKeys, WebPushError, sendNotification } from "web-push";
import Notification from "./schemas/Notification"; import Notification from "./schemas/Notification";
import vapidKeys from "./vapidKeys"; import vapidKeys from "./vapidKeys";
import { Types } from "mongoose";
import { IUser } from "./schemas/User"; import { IUser } from "./schemas/User";
export class NotifcationHelper { export class NotifcationHelper {
@@ -26,12 +25,23 @@ export class NotifcationHelper {
result = await sendNotification(v, message, this.options) result = await sendNotification(v, message, this.options)
count++ count++
} catch (error) { } catch (error) {
if (error.statusCode == 410) { if (error instanceof WebPushError) {
console.log("GONE") switch (error.statusCode) {
await Notification.findOneAndDelete({endpoint: v.endpoint, keys: v.keys}) case 410:
subslen-- console.log("GONE")
await Notification.findOneAndDelete({endpoint: v.endpoint, keys: v.keys})
subslen--
break;
case 404:
console.warn("NOT FOUND", error.message)
await Notification.findOneAndDelete(v)
subslen--
break;
default:
console.log(error)
break;
}
} }
else console.log(error)
} }
} }
return {sent: count, possible: subslen} return {sent: count, possible: subslen}

View File

@@ -82,6 +82,11 @@ cleanRouter.post('/attendence/:room', async (req, res) => {
res.send({status: 200}) res.send({status: 200})
}) })
cleanRouter.delete('/attendence/:room', async (req, res) => {
attendence.clearRoom(req.params.room)
res.send({status: 200})
})
cleanRouter.get('/attendenceSummary', async (req, res) => { cleanRouter.get('/attendenceSummary', async (req, res) => {
res.send(attendence.summary()) res.send(attendence.summary())
}) })

View File

@@ -2,7 +2,7 @@ import { Router } from "express";
import capability, { Features } from "@/capability"; import capability, { Features } from "@/capability";
import Key from "@schemas/Key"; import Key from "@schemas/Key";
import usettings from "@/usettings"; import usettings from "@/usettings";
import User from "@schemas/User"; import User, { IUser } from "@schemas/User";
import { Perms, adminPerm } from "@/utility"; import { Perms, adminPerm } from "@/utility";
const keysRouter = Router() const keysRouter = Router()
@@ -11,7 +11,7 @@ keysRouter.use(capability.mw(Features.Key))
keysRouter.use(adminPerm(Perms.Key)) keysRouter.use(adminPerm(Perms.Key))
keysRouter.get("/", async (req, res) => { keysRouter.get("/", async (req, res) => {
var keys = await Key.find({}, {}, {sort: {borrow: -1}}).populate("whom", {uname: 1, _id: 1, room: 1}) var keys = await Key.find({}, undefined, {sort: {borrow: -1}}).populate<Pick<IUser, "uname" | "room"> & {_id: string}>({path: "whom", select: { _id: 1, uname: 1, room: 1}})
res.send(keys) res.send(keys)
}) })

View File

@@ -5,7 +5,7 @@ import Menu from "@schemas/Menu";
import Vote from "@schemas/Vote"; import Vote from "@schemas/Vote";
import { vote } from "@/pipelines/vote"; import { vote } from "@/pipelines/vote";
import capability, { Features } from "@/capability"; import capability, { Features } from "@/capability";
import Key from "@schemas/Key"; import Key, { IKey } from "@schemas/Key";
import usettings from "@/usettings"; import usettings from "@/usettings";
import Grade from "@schemas/Grade"; import Grade from "@schemas/Grade";
import { createHash } from "node:crypto"; import { createHash } from "node:crypto";
@@ -58,7 +58,7 @@ appRouter.post("/menu/:timestamp", capability.mw(Features.Menu), async (req, res
}) })
appRouter.get("/keys", capability.mw(Features.Key), async (req, res) => { appRouter.get("/keys", capability.mw(Features.Key), async (req, res) => {
var keys = await Key.find({tb: {$exists: false}}, {_id: 0, room: 1, whom: 0}, {sort: {room: 1}}) var keys = await Key.find<Pick<IKey, "room">>({tb: {$exists: false}}, {room: 1}, {sort: {room: 1}})
var occ = keys.map(x=>x.room) var occ = keys.map(x=>x.room)
var all = usettings.settings.keyrooms var all = usettings.settings.keyrooms
var free = all.filter(x=>!occ.includes(x)).sort().map(x => { var free = all.filter(x=>!occ.includes(x)).sort().map(x => {

View File

@@ -1,6 +1,6 @@
import { Schema, Types, model } from "mongoose" import { Schema, Types, model } from "mongoose"
interface IKey { export interface IKey {
room: string; room: string;
whom: Types.ObjectId; whom: Types.ObjectId;
borrow: Date; borrow: Date;