diff --git a/flake.lock b/flake.lock
index f12b903..887a767 100644
--- a/flake.lock
+++ b/flake.lock
@@ -20,11 +20,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1748460289,
- "narHash": "sha256-7doLyJBzCllvqX4gszYtmZUToxKvMUrg45EUWaUYmBg=",
+ "lastModified": 1748693115,
+ "narHash": "sha256-StSrWhklmDuXT93yc3GrTlb0cKSS0agTAxMGjLKAsY8=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102",
+ "rev": "910796cabe436259a29a72e8d3f5e180fc6dfacc",
"type": "github"
},
"original": {
diff --git a/plan.md b/plan.md
index 7e54a64..cbedbd5 100644
--- a/plan.md
+++ b/plan.md
@@ -26,15 +26,17 @@
- [ ] Get current budget
- [ ] Review spending history
- [ ] Request additional budget in case of emergency
-- [-] Emergency alarm
- - [ ] Get alarm list (monitor)
- - [ ] Silencing/clearing
+- [x] Emergency alarm
+ - [x] Get alarm list (monitor)
+ - [x] Silencing/clearing
- [ ] Optional: integration with park's emergency services
-- [ ] Emergency contact & info card
+- [x] Emergency contact & info card
+ - [ ] Endpoints
- [ ] Limitations on consumptions
- [ ] Allergies
- [ ] Sugar intake limitations
-- [ ] Location tracking
+- [x] Location tracking
+ - [ ] Endpoints
- [ ] Sensor tracking (sugar level, heart rate, temperature, ...)
- [ ] Day planning (meetups, departure, ...)
- [ ] Location of activities
diff --git a/src/api/middlewares/authMiddleware.js b/src/api/middlewares/authMiddleware.js
index 19de4d8..3a71e45 100644
--- a/src/api/middlewares/authMiddleware.js
+++ b/src/api/middlewares/authMiddleware.js
@@ -30,9 +30,13 @@ export function validateAuth(options) {
};
}
-export const requireUser = validateAuth({ roles: [UserType.USER] });
-export const requireMonitor = validateAuth({ roles: [UserType.MONITOR] });
+export const requireAuth = validateAuth({});
export const requireAdmin = validateAuth({ roles: [UserType.ADMIN] });
+export const requireMonitor = validateAuth({ roles: [UserType.MONITOR] });
+export const requireUser = validateAuth({ roles: [UserType.USER] });
+export const requireUserOrMonitor = validateAuth({
+ roles: [UserType.USER, UserType.MONITOR]
+});
class AuthValidationOptions {
roles;
diff --git a/src/api/routes.js b/src/api/routes.js
index ade440e..e808d50 100644
--- a/src/api/routes.js
+++ b/src/api/routes.js
@@ -1,11 +1,13 @@
import * as routes from './routes/index.js';
-function logHttpEntry(method, route, exampleBody) {
+function logHttpEntry(method, route, exampleBody, description) {
+ if (description) console.log('%', '#', description);
+
console.log('%', method, '{{baseUrl}}' + route, 'HTTP/1.1');
if (exampleBody) {
console.log('%', 'Content-Type: application/json');
console.log('% ');
- console.log('%', exampleBody);
+ console.log('%', JSON.stringify(exampleBody, null, 4));
console.log('% ');
}
console.log('% ');
@@ -22,17 +24,22 @@ export function registerRoutes(app) {
* @type {RouteDescription}
*/
const route = routes[routeName];
- console.log(
- `Registering ${routeName} (${route.path})`,
- routes[routeName]
- );
Object.keys(route.methods).forEach(routeMethodName => {
/**
* @type {RouteMethod}
*/
const routeMethod = route.methods[routeMethodName];
- console.log(routeMethodName, routeMethod);
+ console.log(
+ 'Registering',
+ routeMethodName.toUpperCase(),
+ route.path
+ );
+ logHttpEntry(
+ routeMethodName.toUpperCase(),
+ route.path,
+ routeMethod.exampleBody
+ );
app[routeMethodName](route.path, [
...routeMethod.middlewares,
routeMethod.method
diff --git a/src/api/routes/auth/deviceRoutes.js b/src/api/routes/auth/deviceRoutes.js
index ac4514f..849a48c 100644
--- a/src/api/routes/auth/deviceRoutes.js
+++ b/src/api/routes/auth/deviceRoutes.js
@@ -1,5 +1,5 @@
-import { deleteUser, loginUser, registerUser } from '#db/index.js';
-import { AuthDto, RegisterDto } from '#dto/index.js';
+import { registerUser } from '#db/index.js';
+import { RegisterDto } from '#dto/index.js';
import { validateAuth } from '#api/middlewares/index.js';
import { RouteDescription, RouteMethod } from '#api/RouteDescription.js';
diff --git a/src/api/routes/budgetRoutes.js b/src/api/routes/budgetRoutes.js
index 1cebffe..a808f58 100644
--- a/src/api/routes/budgetRoutes.js
+++ b/src/api/routes/budgetRoutes.js
@@ -5,6 +5,7 @@ import {
} from '#api/middlewares/index.js';
import { UserType } from '#db/schemas/index.js';
import { RouteDescription, RouteMethod } from '#api/RouteDescription.js';
+import {getUserById} from "#db/dbAccess/index.js";
/**
* @type {RouteDescription}
@@ -14,7 +15,10 @@ export const getBudgetByUserRoute = {
methods: {
get: new RouteMethod({
middlewares: [requireMonitor],
- async method(req, res) {}
+ async method(req, res) {
+ if (!req.)
+ const user = await getUserById(req.);
+ }
})
}
};
diff --git a/src/db/dbAccess/user.js b/src/db/dbAccess/user.js
index 4ab70fd..3900c16 100644
--- a/src/db/dbAccess/user.js
+++ b/src/db/dbAccess/user.js
@@ -7,7 +7,7 @@ import { generateJwtToken } from '#util/jwtUtils.js';
async function whoAmI(token) {}
-async function getUserById(id) {
+export async function getUserById(id) {
const user = await DbUser.findById(id);
if (!user) {
throw new SafeNSoundError({
diff --git a/src/db/schemas/index.js b/src/db/schemas/index.js
index ee1c337..ef18499 100644
--- a/src/db/schemas/index.js
+++ b/src/db/schemas/index.js
@@ -1 +1,3 @@
export * from './user.js';
+export * from './spendHistory.js';
+export * from './sensorHistory.js';
diff --git a/src/db/schemas/sensorHistory.js b/src/db/schemas/sensorHistory.js
new file mode 100644
index 0000000..0cf1187
--- /dev/null
+++ b/src/db/schemas/sensorHistory.js
@@ -0,0 +1,34 @@
+import { model, Schema, ObjectId } from 'mongoose';
+
+/**
+ * User schema for MongoDB.
+ * @type {module:mongoose.Schema}
+ */
+export const sensorHistorySchema = new Schema(
+ {
+ createdAt: {
+ type: Date,
+ default: Date.now,
+ immutable: true
+ },
+ sensor: {
+ type: String,
+ required: true,
+ immutable: true
+ },
+ value: {
+ type: Number,
+ required: true,
+ immutable: true
+ }
+ },
+ {
+ timeseries: {
+ timeField: 'createdAt'
+ }
+ }
+);
+
+export const DbSpendHistory = model('sensorHistory', sensorHistorySchema);
+
+console.log('[MONGODB] sensorHistory schema initialized successfully!');
diff --git a/src/db/schemas/spendHistory.js b/src/db/schemas/spendHistory.js
index b12bcc3..b4c3f20 100644
--- a/src/db/schemas/spendHistory.js
+++ b/src/db/schemas/spendHistory.js
@@ -1,29 +1,39 @@
-import { model, Schema } from 'mongoose';
-import { hash, compare } from 'bcrypt';
-import {ref} from "joi";
+import { model, Schema, ObjectId } from 'mongoose';
/**
* User schema for MongoDB.
* @type {module:mongoose.Schema}
*/
-export const spendHistorySchema = new Schema({
- spentBy: {
- type: ObjectId,
- ref: "users"
+export const spendHistorySchema = new Schema(
+ {
+ venue: {
+ type: String,
+ required: true,
+ immutable: true
+ },
+ items: {
+ type: [String],
+ required: true,
+ immutable: true
+ },
+ cost: {
+ type: Number,
+ required: true,
+ immutable: true
+ },
+ createdAt: {
+ type: Date,
+ default: Date.now,
+ immutable: true
+ }
+ },
+ {
+ timeseries: {
+ timeField: 'createdAt'
+ }
}
- createdAt: {
- type: Date,
- default: Date.now,
- immutable: true
- }
-});
-
-export const UserType = Object.freeze({
- USER: 'user',
- MONITOR: 'monitor',
- ADMIN: 'admin'
-});
+);
-export const DbUser = model('user', userSchema);
+export const DbSpendHistory = model('spendHistory', spendHistorySchema);
-console.log('[MONGODB] User schema initialized successfully!');
+console.log('[MONGODB] spendHistory schema initialized successfully!');
diff --git a/src/db/schemas/user.js b/src/db/schemas/user.js
index f8802d7..7680319 100644
--- a/src/db/schemas/user.js
+++ b/src/db/schemas/user.js
@@ -84,6 +84,27 @@ export const userSchema = new Schema({
monitoredUsers: {
type: [ObjectId],
ref: 'users'
+ },
+ balance: {
+ type: Number,
+ default: 0
+ },
+ spendHistory: {
+ type: [ObjectId],
+ ref: 'spendHistory'
+ },
+ emergencyContacts: {
+ type: String
+ },
+ medicalInfo: {
+ type: String
+ },
+ location: {
+ // https://stackoverflow.com/a/27218808
+ // Longtitute, Latitude info
+ type: [Number],
+ index: { type: '2dsphere', sparse: true },
+ count: 2
}
});
diff --git a/src/dto/auth/DeviceDto.js b/src/dto/auth/DeviceDto.js
deleted file mode 100644
index 40f1959..0000000
--- a/src/dto/auth/DeviceDto.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import { SafeNSoundError } from '#util/error.js';
-import Joi from 'joi';
-
-export class RegisterDto {
- static schema = new Joi.object({
- username: Joi.string().required(),
- email: Joi.string().email().required(),
- password: Joi.string().required(),
- type: Joi.string().valid('user', 'monitor', 'admin').required()
- });
-
- username;
- email;
- password;
- type = 'user';
-
- static async create(data) {
- const obj = new RegisterDto();
- for (const key of Object.keys(data)) {
- if (key in obj) {
- obj[key] = data[key];
- }
- }
-
- try {
- return await RegisterDto.schema.validateAsync(obj);
- } catch (e) {
- console.log(e);
- throw new SafeNSoundError({
- errCode: 'JOI_VALIDATION_ERROR',
- message: e.message,
- validation_details: e.details
- });
- }
- }
-}
diff --git a/test.http b/test.http
index 66dfa1e..98b1ebd 100644
--- a/test.http
+++ b/test.http
@@ -1,59 +1,58 @@
-@base
-GET /budget/:id/add HTTP/1.1
+GET {{baseUrl}}/budget/:id/add HTTP/1.1
###
-GET /admin/users HTTP/1.1
+GET {{baseUrl}}/admin/users HTTP/1.1
###
-GET /admin/user/:id HTTP/1.1
+GET {{baseUrl}}/admin/user/:id HTTP/1.1
###
-DELETE /admin/user/:id HTTP/1.1
+DELETE {{baseUrl}}/admin/user/:id HTTP/1.1
###
-GET /alarm/:id HTTP/1.1
+GET {{baseUrl}}/alarm/:id HTTP/1.1
###
-DELETE /alarm/:id HTTP/1.1
+PUT {{baseUrl}}/alarm/:id HTTP/1.1
###
-GET /alarms HTTP/1.1
+GET {{baseUrl}}/alarms HTTP/1.1
###
-GET /alarm/@me HTTP/1.1
+GET {{baseUrl}}/alarm/@me HTTP/1.1
###
-PUT /alarm/@me HTTP/1.1
+PUT {{baseUrl}}/alarm/@me HTTP/1.1
###
-DELETE /alarm/@me HTTP/1.1
+DELETE {{baseUrl}}/alarm/@me HTTP/1.1
###
-DELETE /auth/delete HTTP/1.1
+DELETE {{baseUrl}}/auth/delete HTTP/1.1
###
-GET /budget/:id HTTP/1.1
+GET {{baseUrl}}/budget/:id HTTP/1.1
###
-GET /budget/@me HTTP/1.1
+GET {{baseUrl}}/budget/@me HTTP/1.1
###
-GET /auth/devices HTTP/1.1
+GET {{baseUrl}}/auth/devices HTTP/1.1
###
-GET / HTTP/1.1
+GET {{baseUrl}}/ HTTP/1.1
###
-POST /auth/login HTTP/1.1
+POST {{baseUrl}}/auth/login HTTP/1.1
###
-POST /auth/logout HTTP/1.1
+POST {{baseUrl}}/auth/logout HTTP/1.1
###
-POST /auth/register HTTP/1.1
+POST {{baseUrl}}/auth/register HTTP/1.1
###
-GET /status HTTP/1.1
+GET {{baseUrl}}/status HTTP/1.1
###
diff --git a/testFrontend/SafeNSound.Frontend/Pages/Alarm.razor b/testFrontend/SafeNSound.Frontend/Pages/Alarm.razor
index 9b90ef4..9b2ee9d 100644
--- a/testFrontend/SafeNSound.Frontend/Pages/Alarm.razor
+++ b/testFrontend/SafeNSound.Frontend/Pages/Alarm.razor
@@ -1,7 +1,7 @@
@page "/Alarm"
<h1>Alarm</h1>
-
+<LinkButton OnClick="@RaiseAlarm">Raise alarm</LinkButton>
<br/><br/>
@if (Exception != null) {
@@ -33,4 +33,8 @@
}
}
+ private async Task RaiseAlarm() {
+ await App.Client!.SetAlarm(new() { });
+ }
+
}
\ No newline at end of file
|