diff --git a/package-lock.json b/package-lock.json index 166767f..df4b145 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "auth-header": "^1.0.0", "commander": "^10.0.0", "cors": "^2.8.5", - "dblang": "https://jusax.de/git/attachments/18f6a160-3695-4182-97a4-c2d9af97e60a", + "dblang": "https://jusax.de/git/attachments/1317588b-b3f3-4b95-bdcc-34292a023298", "express": "^4.18.2", "juml": "https://jusax.de/git/attachments/208913c5-2851-4b86-a53d-ca99fed168cc", "nman": "https://jusax.de/git/attachments/5333948b-fe6b-45d2-9230-ca388f6a89bc", @@ -1107,9 +1107,9 @@ } }, "node_modules/dblang": { - "version": "0.9.0", - "resolved": "https://jusax.de/git/attachments/18f6a160-3695-4182-97a4-c2d9af97e60a", - "integrity": "sha512-qDgygqUM1ykyKsy1IVdybzbBoBvQW1I9Qq6Sh8TS5rAcJnCHI7gyp2PxvqpK82bJsGL2NLBNBwKqhfetLdrJNw==", + "version": "0.9.3", + "resolved": "https://jusax.de/git/attachments/1317588b-b3f3-4b95-bdcc-34292a023298", + "integrity": "sha512-l2LKpxM79S2UjVWS1W9flLt6uZcVsG2qrc6JwqoFv0rgxMOBzoJnnWaHSD5UJKydgXjMycZIvXpGzkuX6vNfwA==", "license": "UNLICENSED", "dependencies": { "gitea-release": "git+https://jusax.de/git/jusax23/gitea-release.git", diff --git a/package.json b/package.json index ac567c5..16ce74c 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "auth-header": "^1.0.0", "commander": "^10.0.0", "cors": "^2.8.5", - "dblang": "https://jusax.de/git/attachments/18f6a160-3695-4182-97a4-c2d9af97e60a", + "dblang": "https://jusax.de/git/attachments/1317588b-b3f3-4b95-bdcc-34292a023298", "express": "^4.18.2", "juml": "https://jusax.de/git/attachments/208913c5-2851-4b86-a53d-ca99fed168cc", "nman": "https://jusax.de/git/attachments/5333948b-fe6b-45d2-9230-ca388f6a89bc", diff --git a/src/api/acts/roomContent.ts b/src/api/acts/roomContent.ts index b28b04f..35ec544 100644 --- a/src/api/acts/roomContent.ts +++ b/src/api/acts/roomContent.ts @@ -1,3 +1,191 @@ +import { and, eq, remove, select, update } from "dblang"; +import { checkSelfTag } from "../../server/outbagURL.js"; +import { Act, Client, STATE } from "../user.js"; +import { db, listCategories, listProducts } from "../../sys/db.js"; +export const getCategories: Act = { + state: STATE.client | STATE.remote, + right: 0, + data: { + room: "string", + server: "string", + }, + func: async (client: Client, data: any, aws: (code: string, data: any) => void) => { + if (!checkSelfTag(data.server)) { + if (client.state != STATE.client) return void aws("error", "right"); + let resp = await client.pass(data.server, "listCategories", data); + aws(resp.state, resp.data); + return; + } + let roomID = await client.isInRoom(data.room); + if (roomID == -1) { + aws("error", "existence"); + return; + } + let req = await select([ + listCategories.listCatID, + listCategories.title, + listCategories.weight, + listCategories.color + ], listCategories) + .where(eq(listCategories.roomID, roomID)) + .query(db); + let out = req.map(d => { + let id = d[listCategories.listCatID]; + let title = d[listCategories.title]; + let weight = d[listCategories.weight]; + let color = d[listCategories.color]; + return { id, title, weight, color }; + }); + aws("ok", out.filter(d => d != null)); + } +}; +export const changeCategories: Act = { + state: STATE.client | STATE.remote, + right: 0, + data: { + room: "string", + server: "string", + catID: "number", + title: "string-256", + color: "string-32" + }, + func: async (client: Client, data: any, aws: (code: string, data: any) => void) => { + if (!checkSelfTag(data.server)) { + if (client.state != STATE.client) return void aws("error", "right"); + let resp = await client.pass(data.server, "changeCategories", data); + aws(resp.state, resp.data); + return; + } + let roomID = await client.isInRoom(data.room); + if (roomID == -1) { + aws("error", "existence"); + return; + } + let req = await update(listCategories) + .set(listCategories.title, data.title) + .set(listCategories.color, data.color) + .where(and( + eq(listCategories.roomID, roomID), + eq(listCategories.listCatID, data.catID) + )) + .query(db); + if (req.affectedRows > 0) aws("ok", ""); + else aws("error", "existence"); + } +}; +export const changeCategoryWeights: Act = { + state: STATE.client | STATE.remote, + right: 0, + data: { + room: "string", + server: "string", + catIDs: "array-number", + weights: "array-number", + }, + func: async (client: Client, data: any, aws: (code: string, data: any) => void) => { + if (!checkSelfTag(data.server)) { + if (client.state != STATE.client) return void aws("error", "right"); + let resp = await client.pass(data.server, "changeCategoryWeights", data); + aws(resp.state, resp.data); + return; + } + let roomID = await client.isInRoom(data.room); + if (roomID == -1) { + aws("error", "existence"); + return; + } + if (data.weights.length != data.catIDs.length) return void aws("error", "data"); + let affacted = 0; + for (let i = 0; i < data.catIDs.length; i++) { + const catID = data.catIDs[i]; + let req = await update(listCategories) + .set(listCategories.weight, data.title) + .where(and( + eq(listCategories.roomID, roomID), + eq(listCategories.listCatID, catID) + )) + .query(db); + affacted += req.affectedRows; + } + if (affacted > 0) aws("ok", ""); + else aws("error", "existence"); + } +}; + +export const deleteCategory: Act = { + state: STATE.client | STATE.remote, + right: 0, + data: { + room: "string", + server: "string", + catID: "number", + }, + func: async (client: Client, data: any, aws: (code: string, data: any) => void) => { + if (!checkSelfTag(data.server)) { + if (client.state != STATE.client) return void aws("error", "right"); + let resp = await client.pass(data.server, "deleteCategory", data); + aws(resp.state, resp.data); + return; + } + let roomID = await client.isInRoom(data.room); + if (roomID == -1) { + aws("error", "existence"); + return; + } + let req = await remove(listCategories) + .where(and( + eq(listCategories.roomID, roomID), + eq(listCategories.listCatID, data.catID) + )) + .query(db); + if (req.affectedRows > 0) aws("ok", ""); + else aws("error", "existence"); + } +}; + +export const getProducts: Act = { + state: STATE.client | STATE.remote, + right: 0, + data: { + room: "string", + server: "string", + }, + func: async (client: Client, data: any, aws: (code: string, data: any) => void) => { + if (!checkSelfTag(data.server)) { + if (client.state != STATE.client) return void aws("error", "right"); + let resp = await client.pass(data.server, "getProducts", data); + aws(resp.state, resp.data); + return; + } + let roomID = await client.isInRoom(data.room); + if (roomID == -1) { + aws("error", "existence"); + return; + } + let req = await select([ + listProducts.listProdID, + listProducts.title, + listProducts.description, + listProducts.category, + listProducts.defUnit, + listProducts.defValue, + listProducts.ean, + ], listProducts) + .where(eq(listProducts.roomID, roomID)) + .query(db); + let out = req.map(d => { + let listProdID = d[listProducts.listProdID]; + let title = d[listProducts.title]; + let description = d[listProducts.description]; + let category = d[listProducts.category]; + let defUnit = d[listProducts.defUnit]; + let defValue = d[listProducts.defValue]; + let ean = d[listProducts.ean]; + return { listProdID, title, description, category, defUnit, defValue, ean }; + }); + aws("ok", out.filter(d => d != null)); + } +}; diff --git a/src/api/acts/rooms.ts b/src/api/acts/rooms.ts index 1c21e79..bdadd57 100644 --- a/src/api/acts/rooms.ts +++ b/src/api/acts/rooms.ts @@ -477,7 +477,7 @@ export const setAdminStatus: Act = { admin: "boolean", }, func: async (client: Client, data: any, aws: (code: string, data: any) => void) => { - if (!checkSelfTag(data.server)) { + if (!checkSelfTag(data.roomServer)) { if (client.state != STATE.client) return void aws("error", "right"); let resp = await client.pass(data.roomServer, "setAdminStatus", data); aws(resp.state, resp.data); @@ -490,7 +490,7 @@ export const setAdminStatus: Act = { .where(and( eq(roomMembers.roomID, roomID), eq(roomMembers.name, data.name), - eq(roomMembers.server, data.server) + eq(roomMembers.server, checkSelfTag(data.server) ? "local" : data.server) )).query(db); if (req.affectedRows > 0) { aws("ok", ""); diff --git a/src/api/post.ts b/src/api/post.ts index 61ad730..0fdef8d 100644 --- a/src/api/post.ts +++ b/src/api/post.ts @@ -44,6 +44,7 @@ export const addPostMethods = (server: express.Express) => { typeof auth.token == "string" && tempTokens[auth.token] != null && typeof auth?.params?.as == "string" + && tempTokens[auth.token].client.state == STATE.server ) { let serverClient = tempTokens[auth.token]; client = new postClient(req.socket.remoteAddress ?? ""); diff --git a/src/api/user.ts b/src/api/user.ts index 5c1a81a..44b3fdc 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -129,6 +129,12 @@ export function checktype(data: any, type: string) { return parseInt(type.split("-")[1]) >= data.length; } else if (typeof data == "string" && type.startsWith("string-")) { return parseInt(type.split("-")[1]) >= data.length; + } else if (type.startsWith("array-") && Array.isArray(data)) { + let ttype = type.substring(6); + for (let i = 0; i < data.length; i++) { + if(!checktype(data[i], ttype)) return false; + } + return true; } else if (type == "any") { return true; } else { diff --git a/src/server/errors.ts b/src/server/errors.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/sys/db.ts b/src/sys/db.ts index c39484d..22e25d2 100644 --- a/src/sys/db.ts +++ b/src/sys/db.ts @@ -179,34 +179,30 @@ listCategories.addAttributes({ listCatID: { type: INT, primaryKey: true, autoIncrement: true }, roomID: { type: INT, - primaryKey: true, foreignKey: { link: rooms.roomID, onDelete: onAction.cascade, onUpdate: onAction.cascade } }, - title: { type: TEXT }, + title: { type: VARCHAR(256) }, weight: { type: INT }, - color: { type: TEXT } + color: { type: VARCHAR(32) } }); -export const articles = db.newTable("articles"); -articles.addAttributes({ - articleID: { type: INT, primaryKey: true, autoIncrement: true }, +export const listProducts = db.newTable("listProducts"); +listProducts.addAttributes({ + listProdID: { type: INT, primaryKey: true, autoIncrement: true }, roomID: { type: INT, - primaryKey: true, foreignKey: { link: rooms.roomID, onDelete: onAction.cascade, onUpdate: onAction.cascade } }, - state: { type: TINYINT, default: 0 }, title: { type: TEXT }, description: { type: TEXT }, - category: { type: INT, foreignKey: { @@ -215,10 +211,48 @@ articles.addAttributes({ onUpdate: onAction.cascade } }, + defUnit: { type: SMALLINT }, + defValue: { type: TEXT }, + ean: { type: INT, notNull: false } +}); +listProducts.addAttribute("parent", INT, { + foreignKey: { + link: listProducts.listProdID, + onDelete: onAction.setNull, + onUpdate: onAction.cascade + } +}); +export const listItems = db.newTable("listItems"); +listItems.addAttributes({ + listItemID: { type: BIGINT, primaryKey: true, autoIncrement: true }, + roomID: { + type: INT, + foreignKey: { + link: rooms.roomID, + onDelete: onAction.cascade, + onUpdate: onAction.cascade + } + }, + state: { type: SMALLINT, default: 0 }, + title: { type: TEXT }, + description: { type: TEXT }, + category: { + type: INT, + foreignKey: { + link: listCategories.listCatID, + onDelete: onAction.setNull, + onUpdate: onAction.cascade + } + }, unit: { type: SMALLINT }, - amount: { type: TEXT }, - - //link: {type:INT} TODO: foreign key - -}); \ No newline at end of file + value: { type: TEXT }, + link: { + type:INT, + foreignKey: { + link: listProducts.listProdID, + onDelete: onAction.setNull, + onUpdate: onAction.cascade + } + } +});