Skip to content

Commit

Permalink
Merge branch 'main' into event-limits-web-wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
ThyMinimalDev authored Sep 23, 2024
2 parents 153c2d2 + 2fb1408 commit c1fa51b
Show file tree
Hide file tree
Showing 103 changed files with 1,066 additions and 434 deletions.
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ assignees: ""
(Share it here.)

---

##### House rules

- If this issue has a `🚨 needs approval` label, don't start coding yet. Wait until a core member approves feature request by removing this label, then you can start coding.
- For clarity: Non-core member issues automatically get the `🚨 needs approval` label.
- Your feature ideas are invaluable to us! However, they undergo review to ensure alignment with the product's direction.
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ jobs:
test:
name: Unit
timeout-minutes: 20
runs-on: buildjet-2vcpu-ubuntu-2204
runs-on: buildjet-4vcpu-ubuntu-2204
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/dangerous-git-checkout
- uses: ./.github/actions/yarn-install
- run: yarn test
- run: yarn test -- --no-isolate
# We could add different timezones here that we need to run our tests in
- run: TZ=America/Los_Angeles yarn test -- --timeZoneDependentTestsOnly
- run: TZ=America/Los_Angeles yarn test -- --timeZoneDependentTestsOnly --no-isolate
- name: Run API v2 tests
working-directory: apps/api/v2
run: |
Expand Down
21 changes: 12 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,24 +177,25 @@ Do not commit your `yarn.lock` unless you've made changes to the `package.json`.

If your last commit has the `yarn.lock` file alongside other files and you only wish to uncommit the `yarn.lock`:

```bash
git checkout HEAD~1 yarn.lock
git commit -m "Revert yarn.lock changes"
```
```bash
git checkout HEAD~1 yarn.lock
git commit -m "Revert yarn.lock changes"
```

_NB_: You may have to bypass the pre-commit hook with by appending `--no-verify` to the git commit
If you've pushed the commit with the `yarn.lock`:

1. Correct the commit locally using the above method.
2. Carefully force push:
1. Correct the commit locally using the above method.
2. Carefully force push:

```bash
git push origin <your-branch-name> --force
```
```bash
git push origin <your-branch-name> --force
```

If `yarn.lock` was committed a while ago and there have been several commits since, you can use the following steps to revert just the `yarn.lock` changes without impacting the subsequent changes:

1. **Checkout a Previous Version**:

- Find the commit hash before the `yarn.lock` was unintentionally committed. You can do this by viewing the Git log:

```bash
Expand All @@ -208,13 +209,15 @@ If `yarn.lock` was committed a while ago and there have been several commits sin
```

2. **Commit the Reverted Version**:

- After checking out the previous version of the `yarn.lock`, commit this change:

```bash
git commit -m "Revert yarn.lock to its state before unintended changes"
```

3. **Proceed with Caution**:

- If you need to push this change, first pull the latest changes from your remote branch to ensure you're not overwriting other recent changes:
```bash
Expand Down
65 changes: 33 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ yarn dx
Add `NEXT_PUBLIC_LOGGER_LEVEL={level}` to your .env file to control the logging verbosity for all tRPC queries and mutations.\
Where {level} can be one of the following:
`0` for silly \
`1` for trace \
`2` for debug \
Expand All @@ -187,14 +187,14 @@ Where {level} can be one of the following:
When you set `NEXT_PUBLIC_LOGGER_LEVEL={level}` in your .env file, it enables logging at that level and higher. Here's how it works:

The logger will include all logs that are at the specified level or higher. For example: \

- If you set `NEXT_PUBLIC_LOGGER_LEVEL=2`, it will log from level 2 (debug) upwards, meaning levels 2 (debug), 3 (info), 4 (warn), 5 (error), and (fatal) will be logged. \
- If you set `NEXT_PUBLIC_LOGGER_LEVEL=3`, it will log from level 3 (info) upwards, meaning levels 3 (info), 4 (warn), 5 (error), and 6 (fatal) will be logged, but level 2 (debug) and level 1 (trace) will be ignored. \



```sh
echo 'NEXT_PUBLIC_LOGGER_LEVEL=3' >> .env
```

for Logger level to be set at info, for example.

#### Gitpod Setup
Expand Down Expand Up @@ -417,25 +417,25 @@ Cal.com, Inc. is a commercial open source company, which means some parts of thi
> [!NOTE]
> Our philosophy is simple, all "Singleplayer APIs" are open-source under AGPLv3. All commercial "Multiplayer APIs" are under a commercial license.

| | AGPLv3 | EE |
|---|---|---|
| Self-host for commercial purposes || |
| Clone privately |||
| Fork publicly |||
| Requires CLA | ||
| Official Support| ❌ ||
| Derivative work privately |||
| SSO |||
| Admin Panel |||
| Impersonation |||
| Managed Event Types |||
| Organizations |||
| Payments |||
| Platform |||
| Teams |||
| Users |||
| Video |||
| Workflows |||
| | AGPLv3 | EE |
| --------------------------------- | ------ | --- |
| Self-host for commercial purposes | | |
| Clone privately | ||
| Fork publicly | | |
| Requires CLA | ||
|  Official Support | ❌  | |
| Derivative work privately | | |
|  SSO | | |
| Admin Panel | | |
| Impersonation | | |
| Managed Event Types | | |
| Organizations | | |
| Payments | | |
| Platform | | |
| Teams | | |
| Users | | |
| Video | | |
| Workflows | | |

> [!TIP]
> We work closely with the community and always invite feedback about what should be open and what is fine to be commercial. This list is not set and stone and we have moved things from commercial to open in the past. Please open a [discussion](https://github.com/calcom/cal.com/discussions) if you feel like something is wrong.
Expand Down Expand Up @@ -531,17 +531,18 @@ following
1. Open [Zoom Marketplace](https://marketplace.zoom.us/) and sign in with your Zoom account.
2. On the upper right, click "Develop" => "Build App".
3. On "OAuth", select "Create".
3. Select "General App" , click "Create".
4. Name your App.
5. Choose "User-managed app" as the app type.
6. De-select the option to publish the app on the Zoom App Marketplace.
7. Click "Create".
8. Now copy the Client ID and Client Secret to your `.env` file into the `ZOOM_CLIENT_ID` and `ZOOM_CLIENT_SECRET` fields.
9. Set the Redirect URL for OAuth `<Cal.com URL>/api/integrations/zoomvideo/callback` replacing Cal.com URL with the URI at which your application runs.
10. Also add the redirect URL given above as an allow list URL and enable "Subdomain check". Make sure, it says "saved" below the form.
11. You don't need to provide basic information about your app. Instead click on "Scopes" and then on "+ Add Scopes". On the left, click the category "Meeting" and check the scope `meeting:write`.
12. Click "Done".
13. You're good to go. Now you can easily add your Zoom integration in the Cal.com settings.
5. Choose "User-managed app" for "Select how the app is managed".
6. De-select the option to publish the app on the Zoom App Marketplace, if asked.
7. Now copy the Client ID and Client Secret to your `.env` file into the `ZOOM_CLIENT_ID` and `ZOOM_CLIENT_SECRET` fields.
8. Set the "OAuth Redirect URL" under "OAuth Information" as `<Cal.com URL>/api/integrations/zoomvideo/callback` replacing Cal.com URL with the URI at which your application runs.
9. Also add the redirect URL given above as an allow list URL and enable "Subdomain check". Make sure, it says "saved" below the form.
10. You don't need to provide basic information about your app. Instead click on "Scopes" and then on "+ Add Scopes". On the left,
1. click the category "Meeting" and check the scope `meeting:write:meeting`.
2. click the category "User" and check the scope `user:read:settings`.
11. Click "Done".
12. You're good to go. Now you can easily add your Zoom integration in the Cal.com settings.
### Obtaining Daily API Credentials
Expand Down
26 changes: 25 additions & 1 deletion apps/api/v1/lib/validations/booking.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { z } from "zod";

import { _AttendeeModel, _BookingModel as Booking, _PaymentModel, _UserModel } from "@calcom/prisma/zod";
import {
_AttendeeModel,
_BookingModel as Booking,
_EventTypeModel,
_PaymentModel,
_TeamModel,
_UserModel,
} from "@calcom/prisma/zod";
import { extendedBookingCreateBody, iso8601 } from "@calcom/prisma/zod-utils";

import { schemaQueryUserId } from "./shared/queryUserId";
Expand Down Expand Up @@ -46,7 +53,23 @@ export const schemaBookingEditBodyParams = schemaBookingBaseBodyParams
.merge(schemaBookingEditParams)
.omit({ uid: true });

const teamSchema = _TeamModel.pick({
name: true,
slug: true,
});

export const schemaBookingReadPublic = Booking.extend({
eventType: _EventTypeModel
.pick({
title: true,
slug: true,
})
.merge(
z.object({
team: teamSchema.nullish(),
})
)
.nullish(),
attendees: z
.array(
_AttendeeModel.pick({
Expand Down Expand Up @@ -87,6 +110,7 @@ export const schemaBookingReadPublic = Booking.extend({
timeZone: true,
attendees: true,
user: true,
eventType: true,
payment: true,
metadata: true,
status: true,
Expand Down
12 changes: 12 additions & 0 deletions apps/api/v1/lib/validations/shared/queryExpandRelations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { z } from "zod";

const expandEnum = z.enum(["team"]);

export const schemaQuerySingleOrMultipleExpand = z
.union([
expandEnum, // Allow a single value from the enum
z.array(expandEnum).refine((arr) => new Set(arr).size === arr.length, {
message: "Array values must be unique",
}), // Allow an array of enum values, with uniqueness constraint
])
.optional();
15 changes: 14 additions & 1 deletion apps/api/v1/pages/api/bookings/[id]/_get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { defaultResponder } from "@calcom/lib/server";
import prisma from "@calcom/prisma";

import { schemaBookingReadPublic } from "~/lib/validations/booking";
import { schemaQuerySingleOrMultipleExpand } from "~/lib/validations/shared/queryExpandRelations";
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";

/**
Expand Down Expand Up @@ -89,9 +90,21 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
export async function getHandler(req: NextApiRequest) {
const { query } = req;
const { id } = schemaQueryIdParseInt.parse(query);

const queryFilterForExpand = schemaQuerySingleOrMultipleExpand.parse(req.query.expand);
const expand = Array.isArray(queryFilterForExpand)
? queryFilterForExpand
: queryFilterForExpand
? [queryFilterForExpand]
: [];
const booking = await prisma.booking.findUnique({
where: { id },
include: { attendees: true, user: true, payment: true },
include: {
attendees: true,
user: true,
payment: true,
eventType: expand.includes("team") ? { include: { team: true } } : false,
},
});
return { booking: schemaBookingReadPublic.parse(booking) };
}
Expand Down
9 changes: 9 additions & 0 deletions apps/api/v1/pages/api/bookings/_get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from "~/lib/utils/retrieveScopedAccessibleUsers";
import { schemaBookingGetParams, schemaBookingReadPublic } from "~/lib/validations/booking";
import { schemaQuerySingleOrMultipleAttendeeEmails } from "~/lib/validations/shared/queryAttendeeEmail";
import { schemaQuerySingleOrMultipleExpand } from "~/lib/validations/shared/queryExpandRelations";
import { schemaQuerySingleOrMultipleUserIds } from "~/lib/validations/shared/queryUserId";

/**
Expand Down Expand Up @@ -216,10 +217,18 @@ export async function handler(req: NextApiRequest) {
args.take = take;
args.skip = skip;
}
const queryFilterForExpand = schemaQuerySingleOrMultipleExpand.parse(req.query.expand);
const expand = Array.isArray(queryFilterForExpand)
? queryFilterForExpand
: queryFilterForExpand
? [queryFilterForExpand]
: [];

args.include = {
attendees: true,
user: true,
payment: true,
eventType: expand.includes("team") ? { include: { team: true } } : false,
};

const queryFilterForAttendeeEmails = schemaQuerySingleOrMultipleAttendeeEmails.parse(req.query);
Expand Down
24 changes: 23 additions & 1 deletion apps/api/v1/test/lib/bookings/_get.integration-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ describe("GET /api/bookings", async () => {

const responseData = await handler(req);
responseData.bookings.forEach((booking) => {
console.log(booking);
expect(new Date(booking.startTime).getTime()).toBeGreaterThanOrEqual(new Date().getTime());
});
});
Expand All @@ -188,4 +187,27 @@ describe("GET /api/bookings", async () => {
});
});
});

describe("Expand feature to add relational data in return payload", () => {
it("Returns only team data when expand=team is set", async () => {
const adminUser = await prisma.user.findFirstOrThrow({ where: { email: "owner1-acme@example.com" } });
const { req } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
method: "GET",
query: {
expand: "team",
},
pagination: DefaultPagination,
});

req.userId = adminUser.id;
req.isOrganizationOwnerOrAdmin = true;

const responseData = await handler(req);
console.log("bookings=>", responseData.bookings);
responseData.bookings.forEach((booking) => {
if (booking.id === 31) expect(booking.eventType?.team?.slug).toBe("team1");
if (booking.id === 19) expect(booking.eventType?.team).toBe(null);
});
});
});
});
4 changes: 2 additions & 2 deletions apps/api/v2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ Copy `.env.example` to `.env` and fill values.

## Add license Key to deployments table in DB

id, logo theme licenseKey agreedLicenseAt
1, null, null, 'c4234812-12ab-42s6-a1e3-55bedd4a5bb7', '2023-05-15 21:39:47.611'
id, logo theme licenseKey agreedLicenseAt
1, null, null, 'c4234812-12ab-42s6-a1e3-55bedd4a5bb7', '2023-05-15 21:39:47.611'

your CALCOM_LICENSE_KEY env var need to contain the same value

Expand Down
6 changes: 4 additions & 2 deletions apps/api/v2/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import appConfig from "@/config/app";
import { CustomThrottlerGuard } from "@/lib/throttler-guard";
import { AppLoggerMiddleware } from "@/middleware/app.logger.middleware";
import { RewriterMiddleware } from "@/middleware/app.rewrites.middleware";
import { JsonBodyMiddleware } from "@/middleware/body/json.body.middleware";
Expand All @@ -15,7 +16,7 @@ import { BullModule } from "@nestjs/bull";
import { MiddlewareConsumer, Module, NestModule, RequestMethod } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { APP_GUARD, APP_INTERCEPTOR } from "@nestjs/core";
import { seconds, ThrottlerGuard, ThrottlerModule } from "@nestjs/throttler";
import { seconds, ThrottlerModule } from "@nestjs/throttler";
import { ThrottlerStorageRedisService } from "nestjs-throttler-storage-redis";

import { AppController } from "./app.controller";
Expand All @@ -32,6 +33,7 @@ import { AppController } from "./app.controller";
BullModule.forRoot({
redis: `${process.env.REDIS_URL}${process.env.NODE_ENV === "production" ? "?tls=true" : ""}`,
}),
// Rate limiting here is handled by the CustomThrottlerGuard
ThrottlerModule.forRootAsync({
imports: [RedisModule],
inject: [RedisService],
Expand Down Expand Up @@ -59,7 +61,7 @@ import { AppController } from "./app.controller";
},
{
provide: APP_GUARD,
useClass: ThrottlerGuard,
useClass: CustomThrottlerGuard,
},
],
})
Expand Down
Loading

0 comments on commit c1fa51b

Please sign in to comment.