Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correção na desestruturação do email na criação de um convite #1

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
Warnings:

- You are about to drop the column `user_id` on the `invites` table. All the data in the column will be lost.

*/
-- DropForeignKey
ALTER TABLE "invites" DROP CONSTRAINT "invites_user_id_fkey";

-- AlterTable
ALTER TABLE "invites" DROP COLUMN "user_id",
ADD COLUMN "author_id" TEXT;

-- AddForeignKey
ALTER TABLE "invites" ADD CONSTRAINT "invites_author_id_fkey" FOREIGN KEY ("author_id") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
-- DropForeignKey
ALTER TABLE "accounts" DROP CONSTRAINT "accounts_user_id_fkey";

-- DropForeignKey
ALTER TABLE "invites" DROP CONSTRAINT "invites_organization_id_fkey";

-- DropForeignKey
ALTER TABLE "members" DROP CONSTRAINT "members_organization_id_fkey";

-- DropForeignKey
ALTER TABLE "members" DROP CONSTRAINT "members_user_id_fkey";

-- DropForeignKey
ALTER TABLE "projects" DROP CONSTRAINT "projects_organization_id_fkey";

-- DropForeignKey
ALTER TABLE "tokens" DROP CONSTRAINT "tokens_user_id_fkey";

-- AddForeignKey
ALTER TABLE "tokens" ADD CONSTRAINT "tokens_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "accounts" ADD CONSTRAINT "accounts_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "invites" ADD CONSTRAINT "invites_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "members" ADD CONSTRAINT "members_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "members" ADD CONSTRAINT "members_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "projects" ADD CONSTRAINT "projects_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
16 changes: 8 additions & 8 deletions apps/api/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ model Token {
type TokenType
createdAt DateTime @default(now()) @map("created_at")

user User @relation(fields: [userId], references: [id])
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String @map("user_id")

@@map("tokens")
Expand All @@ -50,7 +50,7 @@ model Account {
provider AccountProvider
providerAccountId String @unique @map("provider_account_id")

user User @relation(fields: [userId], references: [id])
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String @map("user_id")

@@unique([provider, userId])
Expand All @@ -69,10 +69,10 @@ model Invite {
role Role
createdAt DateTime @default(now()) @map("created_at")

author User? @relation(fields: [userId], references: [id])
userId String? @map("user_id")
author User? @relation(fields: [authorId], references: [id], onDelete: SetNull)
authorId String? @map("author_id")

organization Organization @relation(fields: [organizationId], references: [id])
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
organizationId String @map("organization_id")

@@unique([email, organizationId])
Expand All @@ -84,10 +84,10 @@ model Member {
id String @id @default(uuid())
role Role @default(MEMBER)

organization Organization @relation(fields: [organizationId], references: [id])
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
organizationId String @map("organization_id")

user User @relation(fields: [userId], references: [id])
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String @map("user_id")

@@unique([organizationId, userId])
Expand Down Expand Up @@ -123,7 +123,7 @@ model Project {
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")

organization Organization @relation(fields: [organizationId], references: [id])
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
organizationId String @map("organization_id")

owner User @relation(fields: [ownerId], references: [id])
Expand Down
23 changes: 15 additions & 8 deletions apps/api/src/http/routes/auth/reset-password.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,21 @@ export async function resetPassword(app: FastifyInstance) {

const passwordHash = await hash(password, 6)

await prisma.user.update({
where: {
id: tokenFromCode.userId,
},
data: {
passwordHash,
},
})
await prisma.$transaction([
prisma.user.update({
where: {
id: tokenFromCode.userId,
},
data: {
passwordHash,
},
}),
prisma.token.delete({
where: {
id: code,
},
}),
])

return reply.status(204).send()
},
Expand Down
88 changes: 88 additions & 0 deletions apps/api/src/http/routes/billing/get-organization-billing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import type { FastifyInstance } from 'fastify'
import type { ZodTypeProvider } from 'fastify-type-provider-zod'
import { z } from 'zod'

import { auth } from '@/http/middlewares/auth'
import { UnauthorizedError } from '@/http/routes/_errors/unauthorized-error'
import { prisma } from '@/lib/prisma'
import { getUserPermissions } from '@/utils/get-user-permissions'

export async function getOrganizationBilling(app: FastifyInstance) {
app
.withTypeProvider<ZodTypeProvider>()
.register(auth)
.get(
'/organizations/:slug/billing',
{
schema: {
tags: ['Billing'],
summary: 'Get billing information from organization',
security: [{ bearerAuth: [] }],
params: z.object({
slug: z.string(),
}),
response: {
200: z.object({
billing: z.object({
seats: z.object({
amount: z.number(),
unit: z.number(),
price: z.number(),
}),
projects: z.object({
amount: z.number(),
unit: z.number(),
price: z.number(),
}),
total: z.number(),
}),
}),
},
},
},
async (request) => {
const { slug } = request.params
const userId = await request.getCurrentUserId()
const { organization, membership } =
await request.getUserMembership(slug)

const { cannot } = getUserPermissions(userId, membership.role)

if (cannot('get', 'Billing')) {
throw new UnauthorizedError(
`You're not allowed to get billing details from this organization.`,
)
}

const [amountOfMembers, amountOfProjects] = await Promise.all([
prisma.member.count({
where: {
organizationId: organization.id,
role: { not: 'BILLING' },
},
}),
prisma.project.count({
where: {
organizationId: organization.id,
},
}),
])

return {
billing: {
seats: {
amount: amountOfMembers,
unit: 10,
price: amountOfMembers * 10,
},
projects: {
amount: amountOfProjects,
unit: 20,
price: amountOfProjects * 20,
},
total: amountOfMembers * 10 + amountOfProjects * 20,
},
}
},
)
}
74 changes: 74 additions & 0 deletions apps/api/src/http/routes/invites/accept-invite.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import type { FastifyInstance } from 'fastify'
import type { ZodTypeProvider } from 'fastify-type-provider-zod'
import { z } from 'zod'

import { auth } from '@/http/middlewares/auth'
import { BadRequestError } from '@/http/routes/_errors/bad-request-error'
import { prisma } from '@/lib/prisma'

export async function acceptInvite(app: FastifyInstance) {
app
.withTypeProvider<ZodTypeProvider>()
.register(auth)
.post(
'/invites/:inviteId',
{
schema: {
tags: ['Invites'],
summary: 'Accept an invite',
params: z.object({
inviteId: z.string().uuid(),
}),
response: {
204: z.null(),
},
},
},
async (request, reply) => {
const userId = await request.getCurrentUserId()
const { inviteId } = request.params

const invite = await prisma.invite.findUnique({
where: {
id: inviteId,
},
})

if (!invite) {
throw new BadRequestError('Invite not found or expired.')
}

const user = await prisma.user.findUnique({
where: {
id: userId,
},
})

if (!user) {
throw new BadRequestError('User not found.')
}

if (invite.email !== user.email) {
throw new BadRequestError('This invite belongs to another user.')
}

await prisma.$transaction([
prisma.member.create({
data: {
userId,
organizationId: invite.organizationId,
role: invite.role,
},
}),

prisma.invite.delete({
where: {
id: invite.id,
},
}),
])

return reply.status(204).send()
},
)
}
Loading