Add auth into who can edit a part

This commit is contained in:
Kurt Hutten
2020-11-07 21:44:12 +11:00
parent a009efafac
commit f6964c0f78
3 changed files with 41 additions and 16 deletions

View File

@@ -1,31 +1,43 @@
import { AuthenticationError, ForbiddenError, parseJWT } from '@redwoodjs/api' import { AuthenticationError, ForbiddenError, parseJWT } from '@redwoodjs/api'
import { db } from 'src/lib/db' import { db } from 'src/lib/db'
export const requireOwnership = async ({ id, userName } = {}) => { export const requireOwnership = async ({ userId, userName, partId } = {}) => {
// IMPORTANT, don't forget to await this function, as it will only block
// unwanted db actions if it has time to look up resources in the db.
if (!context.currentUser) { if (!context.currentUser) {
throw new AuthenticationError("You don't have permission to do that.") throw new AuthenticationError("You don't have permission to do that.")
} }
if(!id && !userName) { if(!userId && !userName && !partId) {
throw new ForbiddenError("You don't have access to do that.") 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')) { if(context.currentUser.roles?.includes('admin')) {
return return
} }
const user = await db.user.findOne({ const netlifyUserId = context.currentUser?.sub
where: { userName }, if(userId && userId !== netlifyUserId) {
})
console.log(user, 'USER')
if(!user) {
throw new ForbiddenError("You don't own this resource.") throw new ForbiddenError("You don't own this resource.")
} }
if(userName) {
const user = await db.user.findOne({
where: { userName },
})
if(!user || user.id !== netlifyUserId) {
throw new ForbiddenError("You don't own this resource.")
}
}
if(partId) {
const user = await db.part.findOne({
where: { id: partId },
}).user()
if(!user || user.id !== netlifyUserId) {
throw new ForbiddenError("You don't own this resource.")
}
}
} }

View File

@@ -1,5 +1,7 @@
import { db } from 'src/lib/db' import { db } from 'src/lib/db'
import { foreignKeyReplacement } from 'src/services/helpers' import { foreignKeyReplacement } from 'src/services/helpers'
import { requireAuth } from 'src/lib/auth'
import { requireOwnership } from 'src/lib/owner'
import { user } from 'src/services/users/users' import { user } from 'src/services/users/users'
export const parts = () => { export const parts = () => {
@@ -28,12 +30,15 @@ export const partByUserAndTitle = async ({ userName, partTitle }) => {
} }
export const createPart = async ({ input }) => { export const createPart = async ({ input }) => {
requireAuth()
return db.part.create({ return db.part.create({
data: foreignKeyReplacement(input), data: foreignKeyReplacement(input),
}) })
} }
export const updatePart = ({ id, input }) => { export const updatePart = async ({ id, input }) => {
requireAuth()
await requireOwnership({partId: id})
return db.part.update({ return db.part.update({
data: foreignKeyReplacement(input), data: foreignKeyReplacement(input),
where: { id }, where: { id },
@@ -41,6 +46,7 @@ export const updatePart = ({ id, input }) => {
} }
export const deletePart = ({ id }) => { export const deletePart = ({ id }) => {
requireAuth()
return db.part.delete({ return db.part.delete({
where: { id }, where: { id },
}) })

View File

@@ -1,6 +1,7 @@
import {useState, useEffect} from 'react' import {useState, useEffect} from 'react'
import Editor from "rich-markdown-editor"; import { useAuth } from '@redwoodjs/auth'
import { navigate, routes } from '@redwoodjs/router' import { navigate, routes } from '@redwoodjs/router'
import Editor from "rich-markdown-editor";
import ImageUploader from 'src/components/ImageUploader' import ImageUploader from 'src/components/ImageUploader'
import Breadcrumb from 'src/components/Breadcrumb' import Breadcrumb from 'src/components/Breadcrumb'
@@ -8,7 +9,13 @@ import EmojiReaction from 'src/components/EmojiReaction'
import Button from 'src/components/Button' import Button from 'src/components/Button'
const PartProfile = ({userPart, isEditable, onSave, loading, error}) => { const PartProfile = ({userPart, isEditable, onSave, loading, error}) => {
const { currentUser } = useAuth()
const canEdit = currentUser?.sub === userPart.id
const part = userPart?.Part const part = userPart?.Part
useEffect(() => {isEditable &&
!canEdit &&
navigate(routes.part2({userName: userPart.userName, partTitle: part.title}))},
[currentUser])
const [input, setInput] = useState({ const [input, setInput] = useState({
title: part.title, title: part.title,
mainImage: part.mainImage, mainImage: part.mainImage,
@@ -65,7 +72,7 @@ const PartProfile = ({userPart, isEditable, onSave, loading, error}) => {
> >
Open IDE Open IDE
</Button> </Button>
{true && <Button {canEdit && <Button
className="mt-4 ml-auto shadow-md hover:shadow-lg bg-indigo-200 relative z-20" className="mt-4 ml-auto shadow-md hover:shadow-lg bg-indigo-200 relative z-20"
shouldAnimateHover shouldAnimateHover
iconName={isEditable ? 'save' : 'pencil'} iconName={isEditable ? 'save' : 'pencil'}