Saving token used and time joined
This commit is contained in:
@@ -7,20 +7,22 @@
|
|||||||
"email": "samrussell99@pm.me",
|
"email": "samrussell99@pm.me",
|
||||||
"firstName": "Sam",
|
"firstName": "Sam",
|
||||||
"lastName": "Russell",
|
"lastName": "Russell",
|
||||||
"password": "$argon2id$v=19$m=65536,t=3,p=4$LEd8Zx9YXccDMQyyBYp1oA$+zNo5x6BRRhCcsKvX2zcEAvdth/+tqwN1uqZ8Di/71w",
|
"password": "$argon2id$v=19$m=65536,t=3,p=4$PDu5qx47zzY0dX0/4iQuqw$JxePLouwOEi2Q0wA4JHQQ4GwvqAvxqWhj7n9aC8HZIk",
|
||||||
"address": {
|
"address": {
|
||||||
"address1": "2014 E 9th St",
|
"address1": "2014 E 9th St",
|
||||||
"address2": "Unit A",
|
"address2": "Unit A",
|
||||||
"zip": "78702",
|
"zip": "78702",
|
||||||
"state": "Texas",
|
"state": "Texas",
|
||||||
"city": "Austin"
|
"city": "Austin"
|
||||||
}
|
},
|
||||||
|
"tokenUsed": "810387b6-851e-4883-b9a3-c59703dc0fc9",
|
||||||
|
"joined": "11.24.2025-12:54:360784am"
|
||||||
},
|
},
|
||||||
"TOKEN-810387b6-851e-4883-b9a3-c59703dc0fc9": {
|
"TOKEN-810387b6-851e-4883-b9a3-c59703dc0fc9": {
|
||||||
"index": 1,
|
"index": 1,
|
||||||
"url": "https://hyperia.so/signup?token=",
|
"url": "https://hyperia.so/signup?token=",
|
||||||
"uuid": "810387b6-851e-4883-b9a3-c59703dc0fc9",
|
"uuid": "810387b6-851e-4883-b9a3-c59703dc0fc9",
|
||||||
"used": false
|
"used": true
|
||||||
},
|
},
|
||||||
"TOKEN-d0b417c4-d69a-4958-9e1d-0658176d2710": {
|
"TOKEN-d0b417c4-d69a-4958-9e1d-0658176d2710": {
|
||||||
"index": 2,
|
"index": 2,
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export default class Database {
|
|||||||
try {
|
try {
|
||||||
let collection = this.fromID[type]
|
let collection = this.fromID[type]
|
||||||
if(collection) {
|
if(collection) {
|
||||||
collection.add(node)
|
collection.save(node)
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Type does not exist for node: ", id)
|
throw new Error("Type does not exist for node: ", id)
|
||||||
}
|
}
|
||||||
@@ -77,6 +77,7 @@ export default class Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await fs.writeFile(path.join(process.cwd(), 'db/db.json'), JSON.stringify(data, null, 4), "utf8");
|
let string = JSON.stringify(data, null, 4)
|
||||||
|
await fs.writeFile(path.join(process.cwd(), 'db/db.json'), string, "utf8");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,34 +13,61 @@ export default class Members extends OrderedObject {
|
|||||||
schema = z.object({
|
schema = z.object({
|
||||||
email: z.string().email(),
|
email: z.string().email(),
|
||||||
firstName: z.string(),
|
firstName: z.string(),
|
||||||
lastName: z.number().int().min(0),
|
lastName: z.string(),
|
||||||
password: z.string(),
|
password: z.string(),
|
||||||
address: this.addressSchema
|
tokenUsed: z.string().regex(
|
||||||
|
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
|
||||||
|
"Invalid UUID"
|
||||||
|
),
|
||||||
|
joined: z.string(),
|
||||||
|
address: this.addressSchema,
|
||||||
})
|
})
|
||||||
|
|
||||||
isHashed = (s) => {return s.startsWith("$argon2")}
|
isHashed = (s) => {return s.startsWith("$argon2")}
|
||||||
|
|
||||||
async add(newMember) {
|
save(member) {
|
||||||
console.log("adding ", newMember)
|
let id = `MEMBER-${member.email}`
|
||||||
let id = `MEMBER-${newMember.email}`
|
let result = this.schema.safeParse(member)
|
||||||
if(this.schema.safeParse(newMember)) {
|
if(result.success) {
|
||||||
if(!this.isHashed(newMember.password)) {
|
|
||||||
const hash = await argon2.hash(newMember.password);
|
|
||||||
newMember.password = hash
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
super.add(id, newMember)
|
super.add(id, member)
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new global.ServerError(400, "Invalid Member Data!");
|
console.error("Failed parsing member: ", result.error)
|
||||||
|
throw new global.ServerError(400, "Invalid Member Data!: ");
|
||||||
}
|
}
|
||||||
global.db.saveData()
|
}
|
||||||
|
|
||||||
|
async add(newMember, tokenID) {
|
||||||
|
newMember.tokenUsed = tokenID
|
||||||
|
const hash = await argon2.hash(newMember.password);
|
||||||
|
newMember.password = hash
|
||||||
|
newMember.joined = this.currentTime()
|
||||||
|
this.save(newMember)
|
||||||
}
|
}
|
||||||
|
|
||||||
getByEmail(email) {
|
getByEmail(email) {
|
||||||
return super.get(`MEMBER-${email}`)
|
return super.get(`MEMBER-${email}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentTime() {
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
const month = String(now.getMonth() + 1).padStart(2, "0");
|
||||||
|
const day = String(now.getDate()).padStart(2, "0");
|
||||||
|
const year = now.getFullYear();
|
||||||
|
|
||||||
|
let hours = now.getHours();
|
||||||
|
const ampm = hours >= 12 ? "pm" : "am";
|
||||||
|
hours = hours % 12 || 12; // convert to 12-hour format
|
||||||
|
|
||||||
|
const minutes = String(now.getMinutes()).padStart(2, "0");
|
||||||
|
const seconds = String(now.getSeconds()).padStart(2, "0");
|
||||||
|
const ms = String(now.getMilliseconds()).padStart(4, "0"); // 4-digit like "5838"
|
||||||
|
|
||||||
|
return `${month}.${day}.${year}-${hours}:${minutes}:${seconds}${ms}${ampm}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,11 @@ export default class OrderedObject {
|
|||||||
this.ids[id] = this.entries.length - 1
|
this.ids[id] = this.entries.length - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update(id, data) {
|
||||||
|
let index = this.ids[id]
|
||||||
|
this.entries[index] = data
|
||||||
|
}
|
||||||
|
|
||||||
delete(key) {
|
delete(key) {
|
||||||
if (typeof key === "number") {
|
if (typeof key === "number") {
|
||||||
return this.entries[key]
|
return this.entries[key]
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import OrderedObject from "./OrderedObject.js"
|
|||||||
|
|
||||||
export default class Titles extends OrderedObject {
|
export default class Titles extends OrderedObject {
|
||||||
|
|
||||||
add(newTitle) {
|
save(newTitle) {
|
||||||
let id = `HY-${this.entries.length+1}`
|
let id = `HY-${this.entries.length+1}`
|
||||||
console.log(id)
|
console.log(id)
|
||||||
if(this.validate(id, newTitle)) {
|
if(this.validate(id, newTitle)) {
|
||||||
|
|||||||
@@ -1,10 +1,28 @@
|
|||||||
import OrderedObject from "./OrderedObject.js"
|
import OrderedObject from "./OrderedObject.js"
|
||||||
|
const { z } = require("zod")
|
||||||
|
|
||||||
export default class Tokens extends OrderedObject {
|
export default class Tokens extends OrderedObject {
|
||||||
|
|
||||||
add(token) {
|
schema = z.object({
|
||||||
|
index: z.number(),
|
||||||
|
url: z.string(),
|
||||||
|
uuid: z.string().regex(
|
||||||
|
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
|
||||||
|
"Invalid UUID"
|
||||||
|
),
|
||||||
|
used: z.boolean(),
|
||||||
|
})
|
||||||
|
|
||||||
|
markUsed(uuid) {
|
||||||
|
let token = this.get(uuid)
|
||||||
|
token.used = true
|
||||||
|
super.update(`TOKEN-${uuid}`, token)
|
||||||
|
}
|
||||||
|
|
||||||
|
save(token) {
|
||||||
let id = `TOKEN-${token.uuid}`
|
let id = `TOKEN-${token.uuid}`
|
||||||
if(this.validate(id, token)) {
|
let result = this.schema.safeParse(token)
|
||||||
|
if(result.success) {
|
||||||
try {
|
try {
|
||||||
super.add(id, token)
|
super.add(id, token)
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
@@ -12,6 +30,7 @@ export default class Tokens extends OrderedObject {
|
|||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
console.error(result.error)
|
||||||
throw new global.ServerError(400, "Invalid Member Data!");
|
throw new global.ServerError(400, "Invalid Member Data!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,44 +38,4 @@ export default class Tokens extends OrderedObject {
|
|||||||
get(uuid) {
|
get(uuid) {
|
||||||
return super.get(`TOKEN-${uuid}`)
|
return super.get(`TOKEN-${uuid}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
validate(id, node) {
|
|
||||||
let idTraits = {
|
|
||||||
firstWord: "TOKEN"
|
|
||||||
}
|
|
||||||
|
|
||||||
let fields = [
|
|
||||||
"index",
|
|
||||||
"url",
|
|
||||||
"used"
|
|
||||||
]
|
|
||||||
|
|
||||||
let checkID = () => {
|
|
||||||
let split = id.split("-")
|
|
||||||
return (
|
|
||||||
split[0] === idTraits.firstWord
|
|
||||||
)
|
|
||||||
}
|
|
||||||
let idres = checkID()
|
|
||||||
if(!idres) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
let checkFields = () => {
|
|
||||||
for(let i = 0; i < fields.length; i++) {
|
|
||||||
if(!node[fields[i]]) {
|
|
||||||
throw new Error(`Token ${node.email} is missing trait ${fields[i]}`)
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let fieldres = checkFields()
|
|
||||||
if(!fieldres) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -46,9 +46,14 @@ class Server {
|
|||||||
newUserSubmission = async (req, res) => {
|
newUserSubmission = async (req, res) => {
|
||||||
const { token } = req.query;
|
const { token } = req.query;
|
||||||
try {
|
try {
|
||||||
await db.members.add(req.body)
|
let tokenData = db.tokens.get(token)
|
||||||
|
if(tokenData.used) throw new global.ServerError(400, "Token alredy used!")
|
||||||
|
await db.members.add(req.body, tokenData.uuid)
|
||||||
|
db.tokens.markUsed(token)
|
||||||
|
global.db.saveData()
|
||||||
return res.status(200).json({});
|
return res.status(200).json({});
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
console.log(e)
|
||||||
return res.status(e.status).json({ error: 'Error adding new member' });
|
return res.status(e.status).json({ error: 'Error adding new member' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user