wip(backend): Cloning of people
This commit is contained in:
parent
e37548fcf7
commit
d0b8572f46
6 changed files with 127 additions and 30 deletions
|
@ -8,7 +8,7 @@ export function PersonController() {}
|
||||||
*/
|
*/
|
||||||
PersonController.prototype.create = async (req, res, tools) => {
|
PersonController.prototype.create = async (req, res, tools) => {
|
||||||
const Person = new PersonModel(tools)
|
const Person = new PersonModel(tools)
|
||||||
await Person.create(req)
|
await Person.guardedCreate(req)
|
||||||
|
|
||||||
return Person.sendResponse(res)
|
return Person.sendResponse(res)
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ PersonController.prototype.create = async (req, res, tools) => {
|
||||||
*/
|
*/
|
||||||
PersonController.prototype.read = async (req, res, tools) => {
|
PersonController.prototype.read = async (req, res, tools) => {
|
||||||
const Person = new PersonModel(tools)
|
const Person = new PersonModel(tools)
|
||||||
await Person.readForReturn({ id: parseInt(req.params.id) }, req.user)
|
await Person.guardedRead(req)
|
||||||
|
|
||||||
return Person.sendResponse(res)
|
return Person.sendResponse(res)
|
||||||
}
|
}
|
||||||
|
@ -50,9 +50,9 @@ PersonController.prototype.delete = async (req, res, tools) => {
|
||||||
* Clone a person
|
* Clone a person
|
||||||
* See: https://freesewing.dev/reference/backend/api
|
* See: https://freesewing.dev/reference/backend/api
|
||||||
*/
|
*/
|
||||||
//PersonController.prototype.clone = async (req, res, tools) => {
|
PersonController.prototype.clone = async (req, res, tools) => {
|
||||||
// const Person = new PersonModel(tools)
|
const Person = new PersonModel(tools)
|
||||||
// await Person.unsafeUpdate(req)
|
await Person.guardedClone(req)
|
||||||
//
|
|
||||||
// return Person.sendResponse(res)
|
return Person.sendResponse(res)
|
||||||
//}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ export function UserController() {}
|
||||||
*/
|
*/
|
||||||
UserController.prototype.signup = async (req, res, tools) => {
|
UserController.prototype.signup = async (req, res, tools) => {
|
||||||
const User = new UserModel(tools)
|
const User = new UserModel(tools)
|
||||||
await User.create(req)
|
await User.guardedCreate(req)
|
||||||
|
|
||||||
return User.sendResponse(res)
|
return User.sendResponse(res)
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ UserController.prototype.login = async function (req, res, tools) {
|
||||||
*/
|
*/
|
||||||
UserController.prototype.whoami = async (req, res, tools) => {
|
UserController.prototype.whoami = async (req, res, tools) => {
|
||||||
const User = new UserModel(tools)
|
const User = new UserModel(tools)
|
||||||
await User.readForReturn({ id: req.user.uid })
|
await User.guardedRead({ id: req.user.uid })
|
||||||
|
|
||||||
return User.sendResponse(res)
|
return User.sendResponse(res)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ export function PersonModel(tools) {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
PersonModel.prototype.create = async function ({ body, user }) {
|
PersonModel.prototype.guardedCreate = async function ({ body, user }) {
|
||||||
if (user.level < 3) return this.setResponse(403, 'insufficientAccessLevel')
|
if (user.level < 3) return this.setResponse(403, 'insufficientAccessLevel')
|
||||||
if (Object.keys(body) < 1) return this.setResponse(400, 'postBodyMissing')
|
if (Object.keys(body) < 1) return this.setResponse(400, 'postBodyMissing')
|
||||||
if (!body.name || typeof body.name !== 'string') return this.setResponse(400, 'nameMissing')
|
if (!body.name || typeof body.name !== 'string') return this.setResponse(400, 'nameMissing')
|
||||||
|
@ -28,12 +28,7 @@ PersonModel.prototype.create = async function ({ body, user }) {
|
||||||
data.img = this.config.avatars.person
|
data.img = this.config.avatars.person
|
||||||
|
|
||||||
// Create record
|
// Create record
|
||||||
try {
|
await this.unguardedCreate(data)
|
||||||
this.record = await this.prisma.person.create({ data: this.cloak(data) })
|
|
||||||
} catch (err) {
|
|
||||||
log.warn(err, 'Could not create person')
|
|
||||||
return this.setResponse(500, 'createPersonFailed')
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update img? (now that we have the ID)
|
// Update img? (now that we have the ID)
|
||||||
const img =
|
const img =
|
||||||
|
@ -49,6 +44,17 @@ PersonModel.prototype.create = async function ({ body, user }) {
|
||||||
return this.setResponse(201, 'created', { person: this.asPerson() })
|
return this.setResponse(201, 'created', { person: this.asPerson() })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PersonModel.prototype.unguardedCreate = async function (data) {
|
||||||
|
try {
|
||||||
|
this.record = await this.prisma.person.create({ data: this.cloak(data) })
|
||||||
|
} catch (err) {
|
||||||
|
log.warn(err, 'Could not create person')
|
||||||
|
return this.setResponse(500, 'createPersonFailed')
|
||||||
|
}
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Loads a person from the database based on the where clause you pass it
|
* Loads a person from the database based on the where clause you pass it
|
||||||
*
|
*
|
||||||
|
@ -72,11 +78,11 @@ PersonModel.prototype.read = async function (where) {
|
||||||
*
|
*
|
||||||
* Stores result in this.record
|
* Stores result in this.record
|
||||||
*/
|
*/
|
||||||
PersonModel.prototype.readForReturn = async function (where, user) {
|
PersonModel.prototype.guardedRead = async function ({ params, user }) {
|
||||||
if (user.level < 1) return this.setResponse(403, 'insufficientAccessLevel')
|
if (user.level < 1) return this.setResponse(403, 'insufficientAccessLevel')
|
||||||
if (user.iss && user.status < 1) return this.setResponse(403, 'accountStatusLacking')
|
if (user.iss && user.status < 1) return this.setResponse(403, 'accountStatusLacking')
|
||||||
|
|
||||||
await this.read(where)
|
await this.read({ id: parseInt(params.id) })
|
||||||
if (this.record.userId !== user.uid && user.level < 5) {
|
if (this.record.userId !== user.uid && user.level < 5) {
|
||||||
return this.setResponse(403, 'insufficientAccessLevel')
|
return this.setResponse(403, 'insufficientAccessLevel')
|
||||||
}
|
}
|
||||||
|
@ -87,6 +93,37 @@ PersonModel.prototype.readForReturn = async function (where, user) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clones a person
|
||||||
|
* In addition prepares it for returning the person data
|
||||||
|
*
|
||||||
|
* Stores result in this.record
|
||||||
|
*/
|
||||||
|
PersonModel.prototype.guardedClone = async function ({ params, user }) {
|
||||||
|
if (user.level < 3) return this.setResponse(403, 'insufficientAccessLevel')
|
||||||
|
if (user.iss && user.status < 1) return this.setResponse(403, 'accountStatusLacking')
|
||||||
|
|
||||||
|
await this.read({ id: parseInt(params.id) })
|
||||||
|
if (this.record.userId !== user.uid && !this.record.public && user.level < 5) {
|
||||||
|
return this.setResponse(403, 'insufficientAccessLevel')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone person
|
||||||
|
const data = this.asPerson()
|
||||||
|
delete data.id
|
||||||
|
data.name += ` (cloned from #${this.record.id})`
|
||||||
|
data.notes += ` (Note: This person was cloned from person #${this.record.id})`
|
||||||
|
await this.unguardedCreate(data)
|
||||||
|
|
||||||
|
// Update unencrypted data
|
||||||
|
this.reveal()
|
||||||
|
|
||||||
|
return this.setResponse(200, false, {
|
||||||
|
result: 'success',
|
||||||
|
person: this.asPerson(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper method to decrypt at-rest data
|
* Helper method to decrypt at-rest data
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -67,7 +67,7 @@ UserModel.prototype.cloak = function (data) {
|
||||||
*
|
*
|
||||||
* Stores result in this.record
|
* Stores result in this.record
|
||||||
*/
|
*/
|
||||||
UserModel.prototype.readForReturn = async function (where) {
|
UserModel.prototype.guardedRead = async function (where) {
|
||||||
await this.read(where)
|
await this.read(where)
|
||||||
|
|
||||||
return this.setResponse(200, false, {
|
return this.setResponse(200, false, {
|
||||||
|
@ -136,7 +136,7 @@ UserModel.prototype.setExists = function () {
|
||||||
/*
|
/*
|
||||||
* Creates a user+confirmation and sends out signup email
|
* Creates a user+confirmation and sends out signup email
|
||||||
*/
|
*/
|
||||||
UserModel.prototype.create = async function ({ body }) {
|
UserModel.prototype.guardedCreate = async function ({ body }) {
|
||||||
if (Object.keys(body) < 1) return this.setResponse(400, 'postBodyMissing')
|
if (Object.keys(body) < 1) return this.setResponse(400, 'postBodyMissing')
|
||||||
if (!body.email) return this.setResponse(400, 'emailMissing')
|
if (!body.email) return this.setResponse(400, 'emailMissing')
|
||||||
if (!body.language) return this.setResponse(400, 'languageMissing')
|
if (!body.language) return this.setResponse(400, 'languageMissing')
|
||||||
|
|
|
@ -15,6 +15,14 @@ export function personRoutes(tools) {
|
||||||
Person.create(req, res, tools)
|
Person.create(req, res, tools)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Clone person
|
||||||
|
app.post('/people/:id/clone/jwt', passport.authenticate(...jwt), (req, res) =>
|
||||||
|
Person.clone(req, res, tools)
|
||||||
|
)
|
||||||
|
app.post('/people/:id/clone/key', passport.authenticate(...bsc), (req, res) =>
|
||||||
|
Person.clone(req, res, tools)
|
||||||
|
)
|
||||||
|
|
||||||
// Read person
|
// Read person
|
||||||
app.get('/people/:id/jwt', passport.authenticate(...jwt), (req, res) =>
|
app.get('/people/:id/jwt', passport.authenticate(...jwt), (req, res) =>
|
||||||
Person.read(req, res, tools)
|
Person.read(req, res, tools)
|
||||||
|
@ -31,14 +39,6 @@ export function personRoutes(tools) {
|
||||||
Person.update(req, res, tools)
|
Person.update(req, res, tools)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Clone person
|
|
||||||
app.put('/people/:id/clone/jwt', passport.authenticate(...jwt), (req, res) =>
|
|
||||||
Person.clone(req, res, tools)
|
|
||||||
)
|
|
||||||
app.put('/people/:id/clone/key', passport.authenticate(...bsc), (req, res) =>
|
|
||||||
Person.clone(req, res, tools)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Delete person
|
// Delete person
|
||||||
app.delete('/people/:id/jwt', passport.authenticate(...jwt), (req, res) =>
|
app.delete('/people/:id/jwt', passport.authenticate(...jwt), (req, res) =>
|
||||||
Person.delete(req, res, tools)
|
Person.delete(req, res, tools)
|
||||||
|
|
|
@ -95,7 +95,7 @@ export const personTests = async (chai, config, expect, store) => {
|
||||||
for (const field of ['imperial', 'public']) {
|
for (const field of ['imperial', 'public']) {
|
||||||
it(`${store.icon('person', auth)} Should update the ${field} field (${auth})`, (done) => {
|
it(`${store.icon('person', auth)} Should update the ${field} field (${auth})`, (done) => {
|
||||||
const data = {}
|
const data = {}
|
||||||
const val = false
|
const val = !store.person[auth][field]
|
||||||
data[field] = val
|
data[field] = val
|
||||||
chai
|
chai
|
||||||
.request(config.api)
|
.request(config.api)
|
||||||
|
@ -115,6 +115,7 @@ export const personTests = async (chai, config, expect, store) => {
|
||||||
expect(res.status).to.equal(200)
|
expect(res.status).to.equal(200)
|
||||||
expect(res.body.result).to.equal(`success`)
|
expect(res.body.result).to.equal(`success`)
|
||||||
expect(res.body.person[field]).to.equal(val)
|
expect(res.body.person[field]).to.equal(val)
|
||||||
|
store.person[auth][field] = val
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -310,6 +311,65 @@ export const personTests = async (chai, config, expect, store) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
//it(`${store.icon(
|
||||||
|
// 'person',
|
||||||
|
// auth
|
||||||
|
//)} Should clone a person (${auth})`, (done) => {
|
||||||
|
// chai
|
||||||
|
// .request(config.api)
|
||||||
|
// .post(`/people/${store.person[auth].id}/clone/${auth}`)
|
||||||
|
// .set(
|
||||||
|
// 'Authorization',
|
||||||
|
// auth === 'jwt'
|
||||||
|
// ? 'Bearer ' + store.account.token
|
||||||
|
// : 'Basic ' +
|
||||||
|
// new Buffer(
|
||||||
|
// `${store.account.apikey.key}:${store.account.apikey.secret}`
|
||||||
|
// ).toString('base64')
|
||||||
|
// )
|
||||||
|
// .end((err, res) => {
|
||||||
|
// expect(err === null).to.equal(true)
|
||||||
|
// expect(res.status).to.equal(200)
|
||||||
|
// expect(res.body.result).to.equal(`success`)
|
||||||
|
// expect(typeof res.body.error).to.equal(`undefined`)
|
||||||
|
// expect(typeof res.body.person.id).to.equal(`number`)
|
||||||
|
// done()
|
||||||
|
// })
|
||||||
|
//})
|
||||||
|
|
||||||
|
it(`${store.icon(
|
||||||
|
'person',
|
||||||
|
auth
|
||||||
|
)} Should (not) clone a public person across accounts (${auth})`, (done) => {
|
||||||
|
chai
|
||||||
|
.request(config.api)
|
||||||
|
.post(`/people/${store.person[auth].id}/clone/${auth}`)
|
||||||
|
.set(
|
||||||
|
'Authorization',
|
||||||
|
auth === 'jwt'
|
||||||
|
? 'Bearer ' + store.altaccount.token
|
||||||
|
: 'Basic ' +
|
||||||
|
new Buffer(
|
||||||
|
`${store.altaccount.apikey.key}:${store.altaccount.apikey.secret}`
|
||||||
|
).toString('base64')
|
||||||
|
)
|
||||||
|
.end((err, res) => {
|
||||||
|
if (store.person[auth].public) {
|
||||||
|
expect(err === null).to.equal(true)
|
||||||
|
expect(res.status).to.equal(200)
|
||||||
|
expect(res.body.result).to.equal(`success`)
|
||||||
|
expect(typeof res.body.error).to.equal(`undefined`)
|
||||||
|
expect(typeof res.body.person.id).to.equal(`number`)
|
||||||
|
} else {
|
||||||
|
expect(err === null).to.equal(true)
|
||||||
|
expect(res.status).to.equal(403)
|
||||||
|
expect(res.body.result).to.equal(`error`)
|
||||||
|
expect(res.body.error).to.equal(`insufficientAccessLevel`)
|
||||||
|
}
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// - Clone person
|
// - Clone person
|
||||||
// - Clone person accross accounts of they are public
|
// - Clone person accross accounts of they are public
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue