Add server side ownership enforcement for profile editing

This commit is contained in:
Kurt Hutten
2020-11-06 20:12:46 +11:00
parent c0cd79f48b
commit 9ab61924dc
4 changed files with 66 additions and 6 deletions

View File

@@ -1,4 +1,5 @@
// import { createUserInsecure } from 'src/services/users/users.js'
import { createUserInsecure } from 'src/services/users/users.js'
import { db } from 'src/lib/db'
export const handler = async (req, _context) => {
const body = JSON.parse(req.body)
@@ -61,12 +62,27 @@ export const handler = async (req, _context) => {
// image: '',
// bio: ''
// }
const generateUniqueUserName = async (seed, count = 0) => {
const isUnique = !(await db.user.findOne({
where: { userName: seed },
}))
if(isUnique) {
return seed
}
count += 1
const newSeed = count === 1 ? `${seed}_${count}` : seed.slice(0,-1) + count
return generateUniqueUserName(newSeed, count)
}
const userNameSeed = email.split('@')[0]
const userName = await generateUniqueUserName(userNameSeed) // TODO maybe come up with a better default userName?
const input = {
email,
bio: 'default bio'
// full_name: user.user_metadata.full_name
userName,
name: user.user_metadata && user.user_metadata.full_name,
id: user.id,
}
// await createUserInsecure({input})
await createUserInsecure({input})
return {
statusCode: 200,

31
api/src/lib/owner.js Normal file
View File

@@ -0,0 +1,31 @@
import { AuthenticationError, ForbiddenError, parseJWT } from '@redwoodjs/api'
import { db } from 'src/lib/db'
export const requireOwnership = async ({ id, userName } = {}) => {
if (!context.currentUser) {
throw new AuthenticationError("You don't have permission to do that.")
}
if(!id && !userName) {
throw new ForbiddenError("You don't have access to do that.")
}
const netlifyUserId = context.currentUser?.sub
if(id && id !== netlifyUserId) {
throw new ForbiddenError("You don't own this resource.")
}
if(context.currentUser.roles?.includes('admin')) {
return
}
const user = await db.user.findOne({
where: { userName },
})
console.log(user, 'USER')
if(!user) {
throw new ForbiddenError("You don't own this resource.")
}
}

View File

@@ -1,35 +1,47 @@
import { db } from 'src/lib/db'
import { requireAuth } from 'src/lib/auth'
import { requireOwnership } from 'src/lib/owner'
export const users = () => {
requireAuth({ role: 'admin' })
return db.user.findMany()
}
export const user = ({ id }) => {
requireAuth()
return db.user.findOne({
where: { id },
})
}
export const userName = ({ userName }) => {
requireAuth()
return db.user.findOne({
where: { userName },
})
}
export const createUser = ({ input }) => {
requireAuth({ role: 'admin' })
createUserInsecure({input})
}
export const createUserInsecure = ({ input }) => {
return db.user.create({
data: input,
})
}
export const updateUser = ({ id, input }) => {
requireAuth()
return db.user.update({
data: input,
where: { id },
})
}
export const updateUserByUserName = ({ userName, input }) => {
export const updateUserByUserName = async ({ userName, input }) => {
requireAuth()
await requireOwnership({userName})
return db.user.update({
data: input,
where: { userName },
@@ -37,6 +49,7 @@ export const updateUserByUserName = ({ userName, input }) => {
}
export const deleteUser = ({ id }) => {
requireAuth({ role: 'admin' })
return db.user.delete({
where: { id },
})