feat: ✨ lock member default availability#22136
feat: ✨ lock member default availability#22136shaun-ak wants to merge 89 commits intocalcom:mainfrom
Conversation
|
@shaun-ak is attempting to deploy a commit to the cal Team on Vercel. A member of the Team first needs to authorize it. |
Graphite Automations"Add consumer team as reviewer" took an action on this PR • (06/30/25)1 reviewer was added to this PR based on Keith Williams's automation. "Add community label" took an action on this PR • (06/30/25)1 label was added to this PR based on Keith Williams's automation. |
There was a problem hiding this comment.
cubic found 3 issues across 13 files. Review them in cubic.dev
React with 👍 or 👎 to teach cubic. Tag @cubic-dev-ai to give specific feedback.
packages/trpc/server/routers/viewer/availability/schedule/create.handler.ts
Outdated
Show resolved
Hide resolved
Devanshusharma2005
left a comment
There was a problem hiding this comment.
Hey can you please address the issues suggested by the cubic
|
hey @Devanshusharma2005 , I have addressed the review comments by cubic. Also added a video for reference. |
There was a problem hiding this comment.
cubic reviewed 13 files and found no issues. Review PR in cubic.dev.
Devanshusharma2005
left a comment
There was a problem hiding this comment.
okay . Lets wait for @anikdhabal review too.
kart1ka
left a comment
There was a problem hiding this comment.
Left a comment. Need clarification from the team. The rest of the code looks good to me.
packages/trpc/server/routers/viewer/availability/schedule/create.handler.ts
Outdated
Show resolved
Hide resolved
kart1ka
left a comment
There was a problem hiding this comment.
In a team inside an org, when a team admin/owner tries to update their own default availability, no error is shown. Default Availability does not update but on the frontend no error is shown.
|
@shaun-ak you can check the docs here: https://cal.com/docs/self-hosting/license-key |
|
Hey @kart1ka , I am trying to use the key from docs but getting "Invalid License Key" error. |
| }); | ||
|
|
||
| // Update all schedules to the new timezone (excluding default if locked) | ||
| const schedulesToUpdate = hasLockedAvailability |
There was a problem hiding this comment.
While local testing, I found that if we update timezone or travel schedule timezone from general > settings, then not only the timezone of default availability but also the timezones of other schedules are not getting updated, that should not be the case, the schedulesToUpdate code change fixes that.
Note: in case of locked default availability, only the timezone of default availability should not be updated on profile timezone change.
This was working previously, but maybe some new code change in main branch caused this side effect.
There was a problem hiding this comment.
Checked in main branch, all other availability timezones do not get updated and only the default one gets updated.
I checked in this branch so thought that default availability was not getting updated.
What should actually happen, I am confused here.
There was a problem hiding this comment.
4 issues found across 26 files
Prompt for AI agents (all 4 issues)
Understand the root cause of the following 4 issues and fix them.
<file name="apps/web/app/api/cron/changeTimeZone/route.ts">
<violation number="1" location="apps/web/app/api/cron/changeTimeZone/route.ts:102">
If the stored defaultScheduleId points to a deleted schedule, this new update() call will throw and halt the cron job. A schedule-less findUnique returns null, the guard treats it as falsy, and update() now raises instead of no-op. Consider using updateMany or checking for null before updating.</violation>
</file>
<file name="apps/api/v1/pages/api/teams/[teamId]/_patch.ts">
<violation number="1" location="apps/api/v1/pages/api/teams/[teamId]/_patch.ts:102">
Enabling lockDefaultAvailability should permit the same request that assigns a parent team—otherwise legitimate updates (setting parentId and enabling the lock together) fail because the guard only inspects the current team.parentId.</violation>
</file>
<file name="packages/lib/lockedDefaultAvailability.test.ts">
<violation number="1" location="packages/lib/lockedDefaultAvailability.test.ts:15">
The mock for "@calcom/prisma" only provides a default export, so the named prisma import used by the implementation is undefined; this causes the tested functions to throw before assertions run.</violation>
</file>
<file name="packages/trpc/server/routers/viewer/me/updateProfile.handler.ts">
<violation number="1" location="packages/trpc/server/routers/viewer/me/updateProfile.handler.ts:284">
Updating all schedules' timeZone here overrides any non-default schedule that was intentionally in a different timezone (the old code only touched the default schedule). Please restrict the timezone change to the default schedule and skip it when the lock is active.</violation>
</file>
React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.
# Conflicts: # apps/web/public/static/locales/en/common.json # packages/features/schedules/repositories/ScheduleRepository.ts # packages/lib/schedules/updateSchedule.ts
2nd.test.1.1.mp4 |
There was a problem hiding this comment.
4 issues found across 27 files
Prompt for AI agents (all 4 issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="apps/web/app/api/cron/changeTimeZone/route.ts">
<violation number="1" location="apps/web/app/api/cron/changeTimeZone/route.ts:84">
When a locked default schedule lacks a stored timezone, this cron path writes the new travel timezone (`timeZone`) into it, so the first travel update overwrites the supposedly locked schedule. Use the user’s previous timezone instead so the lock is preserved.</violation>
</file>
<file name="apps/api/v1/pages/api/teams/[teamId]/_patch.ts">
<violation number="1" location="apps/api/v1/pages/api/teams/[teamId]/_patch.ts:102">
`lockDefaultAvailability` can’t be enabled in the same request that assigns the team to an organization because the guard checks the old `team.parentId` rather than the pending `data.parentId`. Consider validating against `data.parentId ?? team.parentId` so simultaneous updates succeed.</violation>
</file>
<file name="packages/features/schedules/components/NewScheduleButton.tsx">
<violation number="1" location="packages/features/schedules/components/NewScheduleButton.tsx:41">
Preserve the actual `lockedDefaultAvailability` flag instead of forcing it to `false`, otherwise locked teams briefly see default-changing actions for newly created schedules.</violation>
</file>
<file name="packages/platform/atoms/availability/AvailabilitySettings.tsx">
<violation number="1" location="packages/platform/atoms/availability/AvailabilitySettings.tsx:285">
Locking a default schedule only disables adding overrides, but editing/deleting existing overrides stays enabled, so the "locked" state can still be bypassed.</violation>
</file>
Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR
| }, | ||
| }, | ||
| data: { | ||
| timeZone: timeZone, |
There was a problem hiding this comment.
When a locked default schedule lacks a stored timezone, this cron path writes the new travel timezone (timeZone) into it, so the first travel update overwrites the supposedly locked schedule. Use the user’s previous timezone instead so the lock is preserved.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/web/app/api/cron/changeTimeZone/route.ts, line 84:
<comment>When a locked default schedule lacks a stored timezone, this cron path writes the new travel timezone (`timeZone`) into it, so the first travel update overwrites the supposedly locked schedule. Use the user’s previous timezone instead so the lock is preserved.</comment>
<file context>
@@ -54,14 +58,58 @@ async function postHandler(request: NextRequest) {
+ },
+ },
+ data: {
+ timeZone: timeZone,
+ },
+ });
</file context>
| ...schedule, | ||
| isDefault: false, | ||
| availability: [], | ||
| lockedDefaultAvailability: false, |
There was a problem hiding this comment.
Preserve the actual lockedDefaultAvailability flag instead of forcing it to false, otherwise locked teams briefly see default-changing actions for newly created schedules.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/features/schedules/components/NewScheduleButton.tsx, line 41:
<comment>Preserve the actual `lockedDefaultAvailability` flag instead of forcing it to `false`, otherwise locked teams briefly see default-changing actions for newly created schedules.</comment>
<file context>
@@ -34,7 +34,12 @@ export function NewScheduleButton({
+ ...schedule,
+ isDefault: false,
+ availability: [],
+ lockedDefaultAvailability: false,
+ };
if (!data)
</file context>
| lockedDefaultAvailability: false, | |
| lockedDefaultAvailability: schedule.lockedDefaultAvailability ?? data?.schedules?.[0]?.lockedDefaultAvailability ?? false, |
| StartIcon="plus" | ||
| data-testid="add-override"> | ||
| data-testid="add-override" | ||
| disabled={disabled}> |
There was a problem hiding this comment.
Locking a default schedule only disables adding overrides, but editing/deleting existing overrides stays enabled, so the "locked" state can still be bypassed.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/platform/atoms/availability/AvailabilitySettings.tsx, line 285:
<comment>Locking a default schedule only disables adding overrides, but editing/deleting existing overrides stays enabled, so the "locked" state can still be bypassed.</comment>
<file context>
@@ -263,7 +281,8 @@ const DateOverride = ({
StartIcon="plus"
- data-testid="add-override">
+ data-testid="add-override"
+ disabled={disabled}>
{t("add_an_override")}
</Button>
</file context>
pallava-joshi
left a comment
There was a problem hiding this comment.
can you please check on cubic suggestions too
Devin AI is resolving merge conflictsThis PR has merge conflicts with the Devin will:
If you prefer to resolve conflicts manually, you can close the Devin session and handle it yourself. |
Resolved conflicts in: - apps/web/app/api/cron/changeTimeZone/route.ts - apps/web/public/static/locales/en/common.json - packages/features/schedules/components/ScheduleListItem.tsx - packages/features/schedules/repositories/ScheduleRepository.ts - packages/platform/atoms/availability/AvailabilitySettings.tsx - packages/trpc/server/routers/viewer/availability/list.handler.ts - packages/trpc/server/routers/viewer/availability/schedule/delete.handler.ts - packages/trpc/server/routers/viewer/me/updateProfile.handler.ts Conflict resolutions: - Updated imports to use new ScheduleRepository from features package - Updated HostRepository import to new location in features package - Preserved locked default availability feature while adopting upstream changes - Combined PR's locked availability checks with upstream's dialog-based delete confirmation - Merged upstream's formHasChanges disabled state with PR's locked availability disabled state Co-Authored-By: unknown <>
Devin AI is completing this stale PRThis PR by @shaun-ak has been marked as stale. A Devin session has been created to complete the remaining work. Devin will review the PR, address any feedback, and push updates to complete this PR. |
- Fix small-screen 'Set to default' switch disabled condition by removing redundant 'value' check that prevented toggling when already checked - Fix effectiveParentId check in teams API to consider data.parentId when setting lockDefaultAvailability in the same request - Fix timezone change guard in updateProfile to only trigger when timeZone is explicitly provided in input, preventing false positives Co-authored-by: shaun-ak <shaun-ak@users.noreply.github.com> Co-Authored-By: unknown <>
Summary of ChangesI've addressed the following review feedback items in this PR: Fixes Applied
CI StatusThe PR requires a maintainer to add the This PR was completed by Devin on behalf of the Cal.com team. Original work by @shaun-ak. Link to Devin run: https://app.devin.ai/sessions/e0191b1a0baf41ca80dd8f3688df8ee2 |
What does this PR do?
Video Demo (if applicable):
Screen.Recording.2025-07-01.at.8.57.37.AM.mp4
Mandatory Tasks (DO NOT REMOVE)
Summary by cubic
Added an organization-only team setting to lock default availability, preventing members from editing, deleting, or changing the timezone of their default schedule unless they are an admin or owner. Members can still create additional schedules.
Written for commit 923b7b2. Summary will update on new commits.