CRUD operations for Posts
- added all CRUD operations for Post model - add() also creates POST_BY_MEMBER and POST_FROM_NETWORK edges - delete() also deletes associated edges - delete() currently does not reallocate node/edge indices after deleting - will write the data to the db.json file and global.db.nodes
This commit is contained in:
@@ -63,6 +63,39 @@ export default class Database {
|
||||
}
|
||||
}
|
||||
|
||||
deleteNode(prefix, id) {
|
||||
try {
|
||||
let model = nodeModels[prefix]
|
||||
if(model) {
|
||||
this.nodes[model.indices[0] + (id - 1)] = 0
|
||||
} else {
|
||||
throw new Error("Type does not exist for node: " + id)
|
||||
}
|
||||
} catch(e) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
editNode(prefix, id, toEdit) {
|
||||
try {
|
||||
let model = nodeModels[prefix]
|
||||
if(model) {
|
||||
let schema = model.schema
|
||||
let result = schema.safeParse(toEdit)
|
||||
if(result.success) {
|
||||
this.nodes[model.indices[0] + (id - 1)] = toEdit
|
||||
} else {
|
||||
console.error(result.error)
|
||||
throw new global.ServerError(400, "Invalid Data!");
|
||||
}
|
||||
} else {
|
||||
throw new Error("Type does not exist for node: " + prefix)
|
||||
}
|
||||
} catch(e) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
addEdge(prefix, edge) {
|
||||
try {
|
||||
let type = prefix
|
||||
@@ -83,7 +116,22 @@ export default class Database {
|
||||
throw new global.ServerError(400, "Invalid Data!");
|
||||
}
|
||||
} else {
|
||||
throw new Error("Type does not exist for edge: " + id)
|
||||
throw new Error("Type does not exist for edge: " + prefix)
|
||||
}
|
||||
} catch(e) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
deleteEdge(prefix, id) {
|
||||
try {
|
||||
let model = edgeModels[prefix]
|
||||
if(model) {
|
||||
console.log(model.indices[0] + (id - 1))
|
||||
this.edges[model.indices[0] + (id - 1)] = 0
|
||||
console.log(this.edges[model.indices[0] + (id - 1)])
|
||||
} else {
|
||||
throw new Error("Type does not exist for edge: " + prefix)
|
||||
}
|
||||
} catch(e) {
|
||||
throw e
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
export default class Edge {
|
||||
add(n) {
|
||||
splitEdge(n) {
|
||||
let toPrefix = n.to.split("-")[0]
|
||||
let fromPrefix = n.from.split("-")[0]
|
||||
let type = n.type
|
||||
let prefix = `${fromPrefix}_${type}_${toPrefix}`
|
||||
return `${fromPrefix}_${type}_${toPrefix}`
|
||||
}
|
||||
|
||||
add(n) {
|
||||
let prefix = this.splitEdge(n)
|
||||
global.db.addEdge(prefix, n)
|
||||
}
|
||||
|
||||
delete(n) {
|
||||
let prefix = this.splitEdge(n)
|
||||
global.db.deleteEdge(prefix, n.from.split("-")[1])
|
||||
}
|
||||
|
||||
getByFrom(fromID) {
|
||||
let result = []
|
||||
for(let i = 0; i < this.entries.length; i++) {
|
||||
|
||||
37
server/db/model/edges/POST_BY_MEMBER.js
Normal file
37
server/db/model/edges/POST_BY_MEMBER.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import { z } from 'zod'
|
||||
|
||||
export default class POST_BY_MEMBER {
|
||||
prefix = "POST_BY_MEMBER"
|
||||
indices = null
|
||||
|
||||
constructor(indices) {
|
||||
this.indices = indices
|
||||
}
|
||||
|
||||
schema = z.object({
|
||||
id: z.number(),
|
||||
type: z.string(),
|
||||
from: z.string(),
|
||||
to: z.string(),
|
||||
created: z.string()
|
||||
})
|
||||
.strict()
|
||||
|
||||
getAuthorId(postId) {
|
||||
for (let i = this.indices[0]; i < this.indices[1]; i++) {
|
||||
if (global.db.edges[i].from === postId) {
|
||||
return Number(global.db.edges[i].to.split("-")[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getByMember(stringID) {
|
||||
let result = []
|
||||
for(let i = this.indices[0]; i < this.indices[1]; i++) {
|
||||
if(global.db.edges[i].from === stringID) {
|
||||
result.push(global.db.edges[i])
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
29
server/db/model/edges/POST_FROM_NETWORK.js
Normal file
29
server/db/model/edges/POST_FROM_NETWORK.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import { z } from 'zod'
|
||||
|
||||
export default class POST_FROM_NETWORK {
|
||||
prefix = "POST_FROM_NETWORK"
|
||||
indices = null
|
||||
|
||||
constructor(indices) {
|
||||
this.indices = indices
|
||||
}
|
||||
|
||||
schema = z.object({
|
||||
id: z.number(),
|
||||
type: z.string(),
|
||||
from: z.string(),
|
||||
to: z.string(),
|
||||
created: z.string()
|
||||
})
|
||||
.strict()
|
||||
|
||||
getByNetwork(id) {
|
||||
let result = []
|
||||
for(let i = this.indices[0]; i < this.indices[1]; i++) {
|
||||
if(global.db.edges[i].to === `${global.db.networks.prefix}-${id}`) {
|
||||
result.push(global.db.edges[i])
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export default class Post {
|
||||
prefix = "POST"
|
||||
indices = null
|
||||
|
||||
constructor(indices) {
|
||||
@@ -8,13 +9,16 @@ export default class Post {
|
||||
}
|
||||
|
||||
schema = z.object({
|
||||
id: z.number(),
|
||||
text: z.string(),
|
||||
time: z.string(),
|
||||
sentBy: z.string()
|
||||
sentBy: z.string(),
|
||||
edited: z.boolean()
|
||||
})
|
||||
|
||||
makeID(forum, number) {
|
||||
return `POST-${forum}-${number}`
|
||||
// return `POST-${forum}-${number}`
|
||||
return `POST-${number}`
|
||||
}
|
||||
|
||||
save(post, id) {
|
||||
@@ -32,30 +36,130 @@ export default class Post {
|
||||
}
|
||||
}
|
||||
|
||||
get(forum, number) {
|
||||
get(forum, by, authorId = null) {
|
||||
let result = []
|
||||
let limit = Math.min(number, this.entries.length)
|
||||
for(let i=1; i<=limit; i++) {
|
||||
let id = this.makeID(forum, i)
|
||||
let post = this.entries[this.ids[id]]
|
||||
let {firstName, lastName} = global.db.members.get(post.sentBy)
|
||||
let seededObj = {
|
||||
...post
|
||||
}
|
||||
seededObj.sentByID = post.sentBy
|
||||
seededObj.sentBy = firstName + " " + lastName
|
||||
result.push(seededObj)
|
||||
if (by === "member" && authorId) {
|
||||
result = this.getByMember(authorId)
|
||||
} else { // network
|
||||
let { id: networkId } = global.db.networks.getByAbbreviation(forum)
|
||||
result = this.getByNetwork(networkId)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
getByID(id) {
|
||||
if(typeof id === 'string') {
|
||||
id = id.split("-")[1]
|
||||
}
|
||||
return {
|
||||
id,
|
||||
authorId: this.getAuthor(id),
|
||||
...global.db.nodes[this.indices[0] + (id - 1)]
|
||||
}
|
||||
}
|
||||
|
||||
getAuthor(postId) {
|
||||
return db.POST_BY_MEMBER.getAuthorId(`${this.prefix}-${postId}`);
|
||||
}
|
||||
|
||||
getByNetwork(id) {
|
||||
let connections = db.POST_FROM_NETWORK.getByNetwork(id)
|
||||
let posts = []
|
||||
connections.forEach((conn) => {
|
||||
posts.push(this.getByID(conn.from))
|
||||
})
|
||||
return posts
|
||||
}
|
||||
|
||||
getByMember(stringID) {
|
||||
let connections = db.POST_BY_MEMBER.getByMember(stringID)
|
||||
let posts = []
|
||||
connections.forEach((conn) => {
|
||||
posts.push(this.getByID(conn.from))
|
||||
})
|
||||
return posts
|
||||
}
|
||||
|
||||
async edit(id, text, userEmail) {
|
||||
try {
|
||||
let userId = global.db.members.getByEmail(userEmail).id
|
||||
let postToEdit = this.getByID(id)
|
||||
|
||||
if (postToEdit.authorId !== userId) {
|
||||
throw new global.ServerError(401, "Not authorized to delete post!")
|
||||
}
|
||||
|
||||
postToEdit.text = text
|
||||
postToEdit.time = global.currentTime()
|
||||
postToEdit.edited = true;
|
||||
|
||||
let { authorId, ...rest } = postToEdit
|
||||
global.db.editNode(this.prefix, id, rest)
|
||||
|
||||
return postToEdit
|
||||
} catch(e) {
|
||||
console.error(e)
|
||||
throw new global.ServerError(400, "Failed to delete post!")
|
||||
}
|
||||
}
|
||||
|
||||
async delete(id, forum, userEmail) {
|
||||
try {
|
||||
let userId = global.db.members.getByEmail(userEmail).id
|
||||
let network = global.db.networks.getByAbbreviation(forum)
|
||||
|
||||
if (this.getAuthor(id) !== userId) {
|
||||
throw new global.ServerError(401, "Not authorized to delete post!")
|
||||
}
|
||||
|
||||
global.db.deleteNode(this.prefix, id)
|
||||
|
||||
if(network) {
|
||||
global.db.edge.delete({
|
||||
type: "FROM",
|
||||
from: `${this.prefix}-${id}`,
|
||||
to: `NETWORK-${network.id}`
|
||||
})
|
||||
}
|
||||
global.db.edge.delete({
|
||||
type: "BY",
|
||||
from: `${this.prefix}-${id}`,
|
||||
to: `MEMBER-${userId}`
|
||||
})
|
||||
} catch(e) {
|
||||
console.error(e)
|
||||
throw new global.ServerError(400, "Failed to delete post!")
|
||||
}
|
||||
}
|
||||
|
||||
async add(text, forum, userEmail) {
|
||||
let newPost = {}
|
||||
newPost.text = text
|
||||
newPost.sentBy = db.members.getIDFromEmail(userEmail)
|
||||
newPost.time = global.currentTime()
|
||||
let sender = global.db.members.getByEmail(userEmail)
|
||||
let network = global.db.networks.getByAbbreviation(forum)
|
||||
|
||||
let idNumber = this.entries.length+1
|
||||
super.add(this.makeID(forum, idNumber), newPost)
|
||||
newPost.text = text
|
||||
newPost.time = global.currentTime()
|
||||
|
||||
try {
|
||||
newPost.sentBy = `${sender.firstName} ${sender.lastName}`
|
||||
|
||||
global.db.addNode(this.prefix, newPost)
|
||||
if(network) {
|
||||
global.db.edge.add({
|
||||
type: "FROM",
|
||||
from: `${this.prefix}-${global.db.getCurrentIndex(this)}`,
|
||||
to: `NETWORK-${network.id}`
|
||||
})
|
||||
}
|
||||
global.db.edge.add({
|
||||
type: "BY",
|
||||
from: `${this.prefix}-${global.db.getCurrentIndex(this)}`,
|
||||
to: `MEMBER-${sender.id}`
|
||||
})
|
||||
return `${this.prefix}-${global.db.getCurrentIndex(this)}`
|
||||
} catch(e) {
|
||||
console.error(e)
|
||||
throw new global.ServerError(400, "Failed to add member!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ import Post from "./forum/post.js"
|
||||
import Conversation from "./dms/conversation.js"
|
||||
import DM from "./dms/dm.js"
|
||||
import MEMBER_IN_NETWORK from "./edges/MEMBER_IN_NETWORK.js"
|
||||
import POST_FROM_NETWORK from "./edges/POST_FROM_NETWORK.js"
|
||||
import POST_BY_MEMBER from "./edges/POST_BY_MEMBER.js"
|
||||
|
||||
let nIndices = {
|
||||
"MEMBER" : [0, 0], // [id, startIndex, nextEmptyIndex
|
||||
@@ -18,7 +20,9 @@ let nIndices = {
|
||||
}
|
||||
|
||||
let eIndices = {
|
||||
"MEMBER_IN_NETWORK": [0, 0]
|
||||
"MEMBER_IN_NETWORK": [0, 0],
|
||||
"POST_FROM_NETWORK": [4000, 4000],
|
||||
"POST_BY_MEMBER": [7000, 7000]
|
||||
}
|
||||
|
||||
export let nodeModels = {
|
||||
@@ -32,5 +36,7 @@ export let nodeModels = {
|
||||
}
|
||||
|
||||
export let edgeModels = {
|
||||
MEMBER_IN_NETWORK: new MEMBER_IN_NETWORK(eIndices.MEMBER_IN_NETWORK)
|
||||
MEMBER_IN_NETWORK: new MEMBER_IN_NETWORK(eIndices.MEMBER_IN_NETWORK),
|
||||
POST_FROM_NETWORK: new POST_FROM_NETWORK(eIndices.POST_FROM_NETWORK),
|
||||
POST_BY_MEMBER: new POST_BY_MEMBER(eIndices.POST_BY_MEMBER)
|
||||
}
|
||||
@@ -24,6 +24,15 @@ export default class Network {
|
||||
return global.db.nodes[index]
|
||||
}
|
||||
|
||||
getByAbbreviation(abbreviation) {
|
||||
for(let i=this.indices[0]; i<this.indices[1]; i++) {
|
||||
if(global.db.nodes[i].abbreviation === abbreviation) {
|
||||
return global.db.nodes[i]
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
save(n) {
|
||||
let id = `${this.prefix}-${n.id}`
|
||||
let result = this.schema.safeParse(n)
|
||||
|
||||
@@ -47,9 +47,11 @@ export let PAYMENT = z.object({
|
||||
})
|
||||
|
||||
export let POST = z.object({
|
||||
id: z.number(),
|
||||
text: z.string(),
|
||||
time: z.string(),
|
||||
sentBy: z.string()
|
||||
sentBy: z.string(),
|
||||
edited: z.boolean()
|
||||
})
|
||||
|
||||
export let CONVSRSATION = z.object({
|
||||
|
||||
@@ -8,35 +8,99 @@ const sendSchema = z.object({
|
||||
|
||||
const getSchema = z.object({
|
||||
forum: z.string(),
|
||||
number: z.number()
|
||||
by: z.string(),
|
||||
authorId: z.number()
|
||||
})
|
||||
.strict()
|
||||
|
||||
const deleteSchema = z.object({
|
||||
forum: z.string(),
|
||||
id: z.number()
|
||||
})
|
||||
.strict()
|
||||
|
||||
const putSchema = z.object({
|
||||
forum: z.string(),
|
||||
id: z.number(),
|
||||
text: z.string()
|
||||
})
|
||||
.strict()
|
||||
|
||||
export default class ForumHandler {
|
||||
static handleSend(msg, ws) {
|
||||
static async handleSend(msg, ws) {
|
||||
try {
|
||||
global.db.posts.add(msg.text, msg.forum, ws.userEmail)
|
||||
global.Socket.broadcast({event: "new-post", app: "FORUM", forum: msg.forum, msg: this.handleGet({forum: msg.forum, number: 100})})
|
||||
return {success: true}
|
||||
let postId = await global.db.posts.add(msg.text, msg.forum, ws.userEmail)
|
||||
let newPost = global.db.posts.getByID(postId)
|
||||
if (newPost) {
|
||||
global.Socket.broadcast({
|
||||
event: "new-post",
|
||||
app: "FORUM",
|
||||
forum: msg.forum,
|
||||
msg: newPost
|
||||
})
|
||||
return {success: true}
|
||||
} else {
|
||||
return {success: false}
|
||||
}
|
||||
} catch(e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
static handleGet(msg) {
|
||||
let data = global.db.posts.get(msg.forum, msg.number)
|
||||
let data = global.db.posts.get(msg.forum, msg.by, msg.authorId)
|
||||
return data
|
||||
}
|
||||
|
||||
static handle(operation, msg, ws) {
|
||||
static async handleDelete(msg, ws) {
|
||||
try {
|
||||
await global.db.posts.delete(msg.id, msg.forum, ws.userEmail)
|
||||
global.Socket.broadcast({
|
||||
event: "deleted-post",
|
||||
app: "FORUM",
|
||||
forum: msg.forum,
|
||||
msg: msg.id
|
||||
})
|
||||
return {success: true}
|
||||
} catch(e) {
|
||||
console.error(e)
|
||||
return {success: false}
|
||||
}
|
||||
}
|
||||
|
||||
static async handlePut(msg, ws) {
|
||||
try {
|
||||
let editedPost = await global.db.posts.edit(msg.id, msg.text, ws.userEmail)
|
||||
console.log(editedPost)
|
||||
if (editedPost) {
|
||||
global.Socket.broadcast({
|
||||
event: "edited-post",
|
||||
app: "FORUM",
|
||||
forum: msg.forum,
|
||||
msg: editedPost
|
||||
})
|
||||
}
|
||||
return {success: true}
|
||||
} catch(e) {
|
||||
console.error(e)
|
||||
return {success: false}
|
||||
}
|
||||
}
|
||||
|
||||
static async handle(operation, msg, ws) {
|
||||
switch(operation) {
|
||||
case "SEND":
|
||||
if(!sendSchema.safeParse(msg).success) throw new Error("Incorrectly formatted Forum ws message!")
|
||||
return this.handleSend(msg, ws)
|
||||
return await this.handleSend(msg, ws)
|
||||
case "GET":
|
||||
if(!getSchema.safeParse(msg).success) throw new Error("Incorrectly formatted Forum ws message!")
|
||||
return this.handleGet(msg)
|
||||
case "DELETE":
|
||||
if(!deleteSchema.safeParse(msg).success) throw new Error("Incorrectly formatted Forum ws message!")
|
||||
return this.handleDelete(msg, ws)
|
||||
case "PUT":
|
||||
if (!putSchema.safeParse(msg).success) throw new Error("Incorrectly formatted ws message!")
|
||||
return this.handlePut(msg, ws)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ export default class Socket {
|
||||
|
||||
// Build a system where the ws obj is updated every time on navigate, so it already has context
|
||||
// this way, we can only send broadcast messages to clients that actually have that app / subapp open
|
||||
handleMessage = (msg, ws) => {
|
||||
handleMessage = async (msg, ws) => {
|
||||
try {
|
||||
const text = msg.toString();
|
||||
const req = JSON.parse(text);
|
||||
@@ -72,7 +72,7 @@ export default class Socket {
|
||||
let responseData;
|
||||
switch (req.app) {
|
||||
case "FORUM":
|
||||
responseData = ForumHandler.handle(req.operation, req.msg, ws)
|
||||
responseData = await ForumHandler.handle(req.operation, req.msg, ws)
|
||||
break;
|
||||
|
||||
case "MESSAGES":
|
||||
|
||||
Reference in New Issue
Block a user