diff --git a/api/src/functions/identity-signup.js b/api/src/functions/identity-signup.js index f816d78..1d0a003 100644 --- a/api/src/functions/identity-signup.js +++ b/api/src/functions/identity-signup.js @@ -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, diff --git a/api/src/lib/owner.js b/api/src/lib/owner.js new file mode 100644 index 0000000..7bb0046 --- /dev/null +++ b/api/src/lib/owner.js @@ -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.") + } + + +} diff --git a/api/src/services/users/users.js b/api/src/services/users/users.js index cde157a..ea9b88f 100644 --- a/api/src/services/users/users.js +++ b/api/src/services/users/users.js @@ -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 }, }) diff --git a/web/src/components/UserProfile/UserProfile.js b/web/src/components/UserProfile/UserProfile.js index ea9c971..9710e66 100644 --- a/web/src/components/UserProfile/UserProfile.js +++ b/web/src/components/UserProfile/UserProfile.js @@ -47,7 +47,7 @@ const UserProfile = ({user, isEditable, loading, onSave, error}) => {