feat: improve api key endpoints, add users endpoint
This commit is contained in:
@@ -3,7 +3,7 @@ import { z } from "zod";
|
||||
|
||||
const schemaApiKey = z
|
||||
.object({
|
||||
expiresAt: z.date().optional(), // default is 30 days
|
||||
expiresAt: z.string().transform((date: string) => new Date(date)).optional(), // default is 30 days
|
||||
note: z.string().min(1).optional(),
|
||||
})
|
||||
.strict(); // Adding strict so that we can disallow passing in extra fields
|
||||
|
||||
@@ -7,7 +7,7 @@ const schemaQueryId = z
|
||||
.object({
|
||||
// since nextjs parses query params as strings,
|
||||
// we need to cast them to numbers using z.transform() and parseInt()
|
||||
id: z.string().uuid()
|
||||
id: z.string()
|
||||
})
|
||||
.strict();
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import { withValidation } from "next-validations";
|
||||
import { schemaEventType } from "./eventType";
|
||||
// import { schemaCredential } from "./credential";
|
||||
// import { schemaMembership } from "./membership";
|
||||
// import { schemaBooking } from "./booking";
|
||||
// import { schemaSchedule } from "./schedule";
|
||||
// import { schemaSelectedCalendar } from "./selectedCalendar";
|
||||
// import { schemaAvailability } from "./availability";
|
||||
// import { schemaWebhook } from "./webhook";
|
||||
|
||||
import { z } from "zod";
|
||||
import { schemaApiKey } from "./apiKey";
|
||||
|
||||
const schemaUser = z
|
||||
.object({
|
||||
username: z.string().min(3),
|
||||
name: z.string().min(3),
|
||||
email: z.string().email(), // max is a full day.
|
||||
emailVerified: z.date().optional(),
|
||||
password: z.string().optional(),
|
||||
bio: z.string().min(3).optional(),
|
||||
avatar: z.string().optional(),
|
||||
timeZone: z.string().default("Europe/London"),
|
||||
weekStart: z.string().default("Sunday"),
|
||||
bufferTime: z.number().default(0),
|
||||
hideBranding: z.boolean().default(false),
|
||||
theme: z.string().optional(),
|
||||
trialEndsAt: z.date().optional(),
|
||||
eventTypes: z.array((schemaEventType)).optional(),
|
||||
// credentials: z.array((schemaCredentials)).optional(),
|
||||
// teams: z.array((schemaMembership)).optional(),
|
||||
// bookings: z.array((schemaBooking)).optional(),
|
||||
// schedules: z.array((schemaSchedule)).optional(),
|
||||
defaultScheduleId: z.number().optional(),
|
||||
// selectedCalendars: z.array((schemaSelectedCalendar)).optional(),
|
||||
completedOnboarding: z.boolean().default(false),
|
||||
locale: z.string().optional(),
|
||||
timeFormat: z.number().optional().default(12),
|
||||
twoFactorEnabled: z.boolean().default(false),
|
||||
twoFactorSecret: z.string().optional(),
|
||||
identityProvider: z.enum(["CAL", "SAML", "GOOGLE"]).optional().default("CAL"),
|
||||
identityProviderId: z.string().optional(),
|
||||
// availavility: z.array((schemaAvailavility)).optional(),
|
||||
invitedTo: z.number().optional(),
|
||||
plan: z.enum(['FREE', 'TRIAL', 'PRO']).default("TRIAL"),
|
||||
// webhooks: z.array((schemaWebhook)).optional(),
|
||||
brandColor: z.string().default("#292929"),
|
||||
darkBrandColor: z.string().default("#fafafa"),
|
||||
// destinationCalendar: z.instanceof(schemaEventType).optional(), // FIXME: instanceof doesnt work here
|
||||
away: z.boolean().default(false),
|
||||
metadata: z.object({}).optional(),
|
||||
verified: z.boolean().default(false),
|
||||
apiKeys: z.array((schemaApiKey)).optional(),
|
||||
})
|
||||
.strict(); // Adding strict so that we can disallow passing in extra fields
|
||||
const withValidUser = withValidation({
|
||||
schema: schemaUser,
|
||||
type: "Zod",
|
||||
mode: "body",
|
||||
});
|
||||
|
||||
export { schemaUser, withValidUser };
|
||||
@@ -9,7 +9,7 @@ type ResponseData = {
|
||||
|
||||
export default async function apiKey(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
try {
|
||||
const apiKeys = await prisma.apiKey.findMany({ where: { id: `${req.query.eventTypeId}` } });
|
||||
const apiKeys = await prisma.apiKey.findMany({});
|
||||
res.status(200).json({ data: { ...apiKeys } });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
||||
@@ -16,10 +16,17 @@ async function createApiKey(req: NextApiRequest, res: NextApiResponse<ResponseDa
|
||||
const safe = schemaApiKey.safeParse(body);
|
||||
if (safe.success && safe.data) {
|
||||
await prisma.apiKey
|
||||
.create({ data: { ...safe.data, user: { connect: { id: 1 } }
|
||||
}})
|
||||
.create({
|
||||
data: {
|
||||
...safe.data, user: { connect: { id: 1 } }
|
||||
}
|
||||
})
|
||||
.then((apiKey) => res.status(201).json({ data: apiKey }))
|
||||
.catch((error) => res.status(400).json({ message: "Could not create apiKey", error: error }));
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
res.status(400).json({ message: "Could not create apiKey", error: error })
|
||||
}
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
|
||||
@@ -9,7 +9,7 @@ type ResponseData = {
|
||||
|
||||
export default async function eventType(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
try {
|
||||
const eventTypes = await prisma.eventType.findMany({ where: { id: Number(req.query.eventTypeId) } });
|
||||
const eventTypes = await prisma.eventType.findMany();
|
||||
res.status(200).json({ data: { ...eventTypes } });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaQueryId, withValidQueryIdTransformParseInt } from "@lib/validations/queryIdTransformParseInt";
|
||||
|
||||
|
||||
type ResponseData = {
|
||||
message?: string;
|
||||
error?: unknown;
|
||||
};
|
||||
|
||||
export async function user(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, method } = req;
|
||||
const safe = await schemaQueryId.safeParse(query);
|
||||
if (safe.success) {
|
||||
if (method === "DELETE") {
|
||||
// DELETE WILL DELETE THE EVENT TYPE
|
||||
prisma.user
|
||||
.delete({ where: { id: safe.data.id } })
|
||||
.then(() => {
|
||||
// We only remove the user type from the database if there's an existing resource.
|
||||
res.status(200).json({ message: `user-type with id: ${safe.data.id} deleted successfully` });
|
||||
})
|
||||
.catch((error) => {
|
||||
// This catches the error thrown by prisma.user.delete() if the resource is not found.
|
||||
res.status(400).json({ message: `Resource with id:${safe.data.id} was not found`, error: error });
|
||||
});
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only DELETE Method allowed in /user-types/[id]/delete endpoint" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default withValidQueryIdTransformParseInt(user);
|
||||
@@ -0,0 +1,37 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { User } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaUser, withValidUser } from "@lib/validations/user";
|
||||
import { schemaQueryId, withValidQueryIdTransformParseInt } from "@lib/validations/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
data?: User;
|
||||
message?: string;
|
||||
error?: unknown;
|
||||
};
|
||||
|
||||
export async function editUser(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, body, method } = req;
|
||||
const safeQuery = await schemaQueryId.safeParse(query);
|
||||
const safeBody = await schemaUser.safeParse(body);
|
||||
|
||||
if (method === "PATCH") {
|
||||
if (safeQuery.success && safeBody.success) {
|
||||
await prisma.user.update({
|
||||
where: { id: safeQuery.data.id },
|
||||
data: safeBody.data,
|
||||
}).then(user => {
|
||||
res.status(200).json({ data: user });
|
||||
}).catch(error => {
|
||||
res.status(404).json({ message: `Event type with ID ${safeQuery.data.id} not found and wasn't updated`, error })
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only PATCH Method allowed for updating user-types" });
|
||||
}
|
||||
}
|
||||
|
||||
export default withValidQueryIdTransformParseInt(withValidUser(editUser));
|
||||
@@ -0,0 +1,31 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { User } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaQueryId, withValidQueryIdTransformParseInt } from "@lib/validations/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
data?: User;
|
||||
message?: string;
|
||||
error?: unknown;
|
||||
};
|
||||
|
||||
export async function user(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, method } = req;
|
||||
const safe = await schemaQueryId.safeParse(query);
|
||||
if (safe.success) {
|
||||
if (method === "GET") {
|
||||
const user = await prisma.user.findUnique({ where: { id: safe.data.id } });
|
||||
|
||||
if (user) res.status(200).json({ data: user });
|
||||
if (!user) res.status(404).json({ message: "Event type not found" });
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only GET Method allowed" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default withValidQueryIdTransformParseInt(user);
|
||||
@@ -0,0 +1,19 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { User } from "@calcom/prisma/client";import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
type ResponseData = {
|
||||
data?: User[];
|
||||
error?: unknown;
|
||||
};
|
||||
|
||||
export default async function user(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
try {
|
||||
const users = await prisma.user.findMany();
|
||||
res.status(200).json({ data: { ...users } });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
// FIXME: Add zod for validation/error handling
|
||||
res.status(400).json({ error: error });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { User } from "@calcom/prisma/client";import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaUser, withValidUser } from "@lib/validations/user";
|
||||
|
||||
type ResponseData = {
|
||||
data?: User;
|
||||
message?: string;
|
||||
error?: string;
|
||||
};
|
||||
|
||||
async function createUser(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { body, method } = req;
|
||||
if (method === "POST") {
|
||||
const safe = schemaUser.safeParse(body);
|
||||
if (safe.success && safe.data) {
|
||||
await prisma.user
|
||||
.create({ data: safe.data })
|
||||
.then((user) => res.status(201).json({ data: user }))
|
||||
.catch((error) => res.status(400).json({ message: "Could not create user type", error: error }));
|
||||
}
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ error: "Only POST Method allowed" });
|
||||
}
|
||||
}
|
||||
|
||||
export default withValidUser(createUser);
|
||||
Reference in New Issue
Block a user