Skip to content

Commit

Permalink
🚧 clip関連のAPIを実装
Browse files Browse the repository at this point in the history
- GET /users/clips
- POST /users/clips
- GET /users/clips/:id
- PATCH /users/clips/:id
- DELETE /users/clips/:id
  • Loading branch information
cp-20 committed Jul 31, 2023
1 parent b086ffb commit 1e78fbe
Show file tree
Hide file tree
Showing 7 changed files with 226 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { deleteUserClipById } from '@/server/handlers/users/[id]/clips/[clipId]/delete';
import { getUserClipById } from '@/server/handlers/users/[id]/clips/[clipId]/get';
import { updateUserClipById } from '@/server/handlers/users/[id]/clips/[clipId]/patch';

export const GET = getUserClipById;

export const PATCH = updateUserClipById;

export const DELETE = deleteUserClipById;
6 changes: 6 additions & 0 deletions packages/web/src/pages/api/v1/users/[id]/clips/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { getUserClips } from '@/server/handlers/users/[id]/clips/get';
import { postUserClips } from '@/server/handlers/users/[id]/clips/post';

export const GET = getUserClips;

export const POST = postUserClips;
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Prisma } from '@prisma/client';
import { createPagesServerClient } from '@supabase/auth-helpers-nextjs';
import type { NextApiHandler } from 'next';
import { z } from 'zod';
import { prisma } from '@/features/database/prismaClient';

const deleteUserClipByIdSchema = z.object({
id: z.string(),
clipId: z.number().int(),
});

export const deleteUserClipById: NextApiHandler = async (req, res) => {
const query = deleteUserClipByIdSchema.safeParse(req.query);
if (!query.success) {
return res.status(400).json({ error: query.error });
}
const { id, clipId } = query.data;

const supabaseClient = createPagesServerClient({ req, res });
const session = await supabaseClient.auth.getSession();

if (session.data.session === null || session.error !== null) {
return res.status(401).json({ message: 'Unauthorized' });
}

if (session.data.session.user.id !== id) {
return res.status(403).json({ message: 'Forbidden' });
}

try {
const clip = await prisma.clips.delete({
where: {
id: clipId,
},
});
return res.status(200).json({ clip });
} catch (err) {
if (err instanceof Prisma.PrismaClientKnownRequestError) {
if (err.code === 'P2015') {
res.status(404).json({ message: 'Not Found' });
}

// TODO: 他のエラーコードのときのエラーハンドリング
}
}
};
37 changes: 37 additions & 0 deletions packages/web/src/server/handlers/users/[id]/clips/[clipId]/get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { createPagesServerClient } from '@supabase/auth-helpers-nextjs';
import type { NextApiHandler } from 'next';
import { z } from 'zod';
import { prisma } from '@/features/database/prismaClient';

const getUserClipByIdSchema = z.object({
id: z.string(),
clipId: z.number().int(),
});

export const getUserClipById: NextApiHandler = async (req, res) => {
const query = getUserClipByIdSchema.safeParse(req.query);
if (!query.success) {
return res.status(400).json({ error: query.error });
}
const { id, clipId } = query.data;

const supabaseClient = createPagesServerClient({ req, res });
const session = await supabaseClient.auth.getSession();

if (session.data.session === null || session.error !== null) {
return res.status(401).json({ message: 'Unauthorized' });
}

if (session.data.session.user.id !== id) {
return res.status(403).json({ message: 'Forbidden' });
}

const clip = await prisma.clips.findFirst({
where: {
authorId: id,
id: clipId,
},
});

return res.status(200).json({ clip });
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Prisma } from '@prisma/client';
import { createPagesServerClient } from '@supabase/auth-helpers-nextjs';
import type { NextApiHandler } from 'next';
import { z } from 'zod';
import { prisma } from '@/features/database/prismaClient';

const updateUserClipByIdSchema = z.object({
id: z.string(),
clipId: z.number().int(),
clip: z
.object({
status: z.number().int().min(0).max(2),
progress: z.number().int().min(0).max(100),
comment: z.string(),
})
.partial(),
});

export const updateUserClipById: NextApiHandler = async (req, res) => {
const query = updateUserClipByIdSchema.safeParse(req.query);
if (!query.success) {
return res.status(400).json({ error: query.error });
}
const { id, clipId, clip: clipData } = query.data;

const supabaseClient = createPagesServerClient({ req, res });
const session = await supabaseClient.auth.getSession();

if (session.data.session === null || session.error !== null) {
return res.status(401).json({ message: 'Unauthorized' });
}

if (session.data.session.user.id !== id) {
return res.status(403).json({ message: 'Forbidden' });
}

try {
const clip = await prisma.clips.update({
where: {
id: clipId,
},
data: clipData,
});
return res.status(200).json({ clip });
} catch (err) {
if (err instanceof Prisma.PrismaClientKnownRequestError) {
if (err.code === 'P2015') {
res.status(404).json({ message: 'Not Found' });
}

// TODO: 他のエラーコードのときのエラーハンドリング
}
}
};
35 changes: 35 additions & 0 deletions packages/web/src/server/handlers/users/[id]/clips/get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { createPagesServerClient } from '@supabase/auth-helpers-nextjs';
import type { NextApiHandler } from 'next';
import { z } from 'zod';
import { prisma } from '@/features/database/prismaClient';

const getUserClipsSchema = z.object({
id: z.string(),
});

export const getUserClips: NextApiHandler = async (req, res) => {
const query = getUserClipsSchema.safeParse(req.query);
if (!query.success) {
return res.status(400).json({ error: query.error });
}
const { id } = query.data;

const supabaseClient = createPagesServerClient({ req, res });
const session = await supabaseClient.auth.getSession();

if (session.data.session === null || session.error !== null) {
return res.status(401).json({ message: 'Unauthorized' });
}

if (session.data.session.user.id !== id) {
return res.status(403).json({ message: 'Forbidden' });
}

const clips = await prisma.clips.findMany({
where: {
authorId: id,
},
});

return res.status(200).json({ clips });
};
39 changes: 39 additions & 0 deletions packages/web/src/server/handlers/users/[id]/clips/post.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { createPagesServerClient } from '@supabase/auth-helpers-nextjs';
import type { NextApiHandler } from 'next';
import { z } from 'zod';
import { prisma } from '@/features/database/prismaClient';

const postUserClipsSchema = z.object({
id: z.string(),
articleId: z.number().int(),
});

export const postUserClips: NextApiHandler = async (req, res) => {
const query = postUserClipsSchema.safeParse(req.query);
if (!query.success) {
return res.status(400).json({ error: query.error });
}
const { id, articleId } = query.data;

const supabaseClient = createPagesServerClient({ req, res });
const session = await supabaseClient.auth.getSession();

if (session.data.session === null || session.error !== null) {
return res.status(401).json({ message: 'Unauthorized' });
}

if (session.data.session.user.id !== id) {
return res.status(403).json({ message: 'Forbidden' });
}

const clip = await prisma.clips.create({
data: {
status: 0,
progress: 0,
authorId: id,
articleId,
},
});

return res.status(200).json({ clip });
};

0 comments on commit 1e78fbe

Please sign in to comment.