feat: BigBlueButton video conferencing integration#29434
Conversation
Add BigBlueButton as a conferencing app in the app store. This integration enables users to create and manage BBB meetings directly from Cal.com. Key features: - BBB API client with SHA1 checksum authentication - Symmetric credential encryption via CALENDSO_ENCRYPTION_KEY - Full meeting lifecycle: create, update, delete, getRecordings - Setup form for server URL and shared secret collection - Comprehensive test suite with error path coverage (18 tests) - Support for team and individual installation Architecture follows the existing Jitsi conferencing pattern with: - VideoApiAdapter interface implementation - Zod schema validation for credentials - appsWithSetupForm routing system for non-OAuth apps - Proper admin access verification for team installs Closes calcom#1985
|
Welcome to Cal.diy, @q404365631! Thanks for opening this pull request. A few things to keep in mind:
A maintainer will review your PR soon. Thanks for contributing! |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
💤 Files with no reviewable changes (1)
🚧 Files skipped from review as they are similar to previous changes (4)
📝 WalkthroughWalkthroughThis PR introduces BigBlueButton video conferencing support to Cal.com. The implementation adds a low-level BBB API client with request signing and XML parsing, registers the app in the app store with metadata and schemas, provides a backend API route for validating and persisting BBB credentials, implements a VideoApiAdapter for meeting lifecycle operations, and wires a client-side setup form into the app installation flow. The setup form collects server URL and shared secret credentials, validates them against the BBB API, and encrypts them before storage. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
🧹 Nitpick comments (6)
packages/app-store/bigbluebuttonvideo/api/add.ts (1)
13-18: ⚡ Quick winTrim “what” comments and keep only rationale (“why”) comments.
Most comments in this handler restate the code flow. Please remove or rewrite them to capture non-obvious decisions only.
As per coding guidelines: "Only add code comments that explain why, not what" and "Never add comments that simply restate what the code does".
Also applies to: 26-26, 46-46, 51-51, 61-61, 70-70, 81-81
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/app-store/bigbluebuttonvideo/api/add.ts` around lines 13 - 18, The comments in the BigBlueButton installation handler (packages/app-store/bigbluebuttonvideo/api/add.ts — the POST handler function) are “what” comments that merely restate code flow; remove or replace them so only non-obvious rationale remains (explain why decisions were made, e.g., why you validate with getMeetings, why you encrypt the secret, any security assumptions or edge cases), and delete redundant inline comments around the credential validation, encryption/storage, and redirect logic (currently near the credential parsing, getMeetings call, encryption step, and redirect response). Ensure any retained comments explain intent or trade-offs rather than restating actions.packages/app-store/bigbluebuttonvideo/lib/VideoApiAdapter.ts (1)
17-24: ⚡ Quick winUse
ErrorWithCodefor credential/config validation failures.This helper throws plain
Errorfor missing env/config problems, which makes the adapter inconsistent with the repo’s non-tRPC error contract. Please switch these branches toErrorWithCodeso callers can handle credential/setup failures predictably.As per coding guidelines "Use
ErrorWithCodefor errors in non-tRPC files (services, repositories, utilities); useTRPCErroronly in tRPC routers".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/app-store/bigbluebuttonvideo/lib/VideoApiAdapter.ts` around lines 17 - 24, Replace the plain Error throws in VideoApiAdapter.ts with the project's ErrorWithCode so credential/config validation failures follow the repo's non-tRPC error contract: where encryptionKey is validated (the branch throwing "CALENDSO_ENCRYPTION_KEY environment variable is not set.") and where credentialKey type is checked (the branch throwing "Invalid credential key format."), throw new ErrorWithCode with an appropriate code (e.g., "BAD_REQUEST" or "INVALID_CREDENTIALS") and descriptive message; also add the ErrorWithCode import at the top of the file if not present.apps/web/components/apps/bigbluebuttonvideo/Setup.tsx (1)
20-20: ⚡ Quick winRemove “what” comments in the component.
These comments explain obvious behavior and should be removed (or replaced with “why” context only).
As per coding guidelines, "Only add code comments that explain why, not what" and "Never add comments that simply restate what the code does."
Also applies to: 28-31
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/components/apps/bigbluebuttonvideo/Setup.tsx` at line 20, Remove the comment(s) that state obvious facts (e.g. the /* 表单字段验证模式 */ and the similar comments at lines 28-31) from the Setup component; if additional context is needed, replace them with a brief "why" comment explaining intent or rationale for the validation mode/behavior used in the Setup.tsx component (reference the Setup component and any local validation-related variables/props to place the why-comment).apps/web/modules/apps/components/AppCard.tsx (1)
75-75: ⚡ Quick winRemove the inline “what” comment above the setup-form branch.
The code is already self-explanatory; keep comments only for rationale that isn't obvious from control flow.
As per coding guidelines, "Only add code comments that explain why, not what" and "Never add comments that simply restate what the code does."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/modules/apps/components/AppCard.tsx` at line 75, Remove the redundant inline “what” comment above the setup-form branch in the AppCard component: open the AppCard component (symbol AppCard) and delete the single-line Chinese comment that restates behavior for setup-form apps so only necessary rationale comments remain, keeping the control flow self-explanatory.apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts (1)
451-451: ⚡ Quick winDrop the explanatory inline comment or rewrite as rationale.
This comment restates the code path; keep comments only when they explain non-obvious intent/trade-offs.
As per coding guidelines, "Only add code comments that explain why, not what" and "Never add comments that simply restate what the code does."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/lib/apps/installation/`[[...step]]/getServerSideProps.ts at line 451, The inline comment "// 无凭证且 app 需要 setup form 时,重定向到 setup 页面采集凭证" in getServerSideProps is restating the code path; remove it or replace it with a brief rationale explaining the non-obvious intent (e.g., why redirecting here is required for UX/consistency or to avoid exposing partial app state). Locate the comment near the getServerSideProps handler in apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts and either delete that line or swap it for a one-sentence "why" comment referencing the redirect's purpose and any trade-offs (security/UX), not the "what".apps/web/components/apps/appsWithSetupForm.ts (1)
1-5: ⚡ Quick winRemove “what” comments or rewrite them to explain intent.
These comments currently restate behavior instead of rationale. Please remove them or rewrite to capture non-obvious design intent only.
As per coding guidelines, "Only add code comments that explain why, not what" and "Never add comments that simply restate what the code does."
Also applies to: 8-10, 15-18
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/components/apps/appsWithSetupForm.ts` around lines 1 - 5, The top-of-file comment blocks are "what" comments that restate behavior; remove or rewrite them to capture the rationale for the special-case list of app slugs (i.e., why certain non-OAuth apps require a custom setup form and must follow the setup flow instead of the auto-install flow). Update the comment(s) near the list(s) in appsWithSetupForm.ts (and the similar blocks referenced around the other comment ranges) to be terse and intent-focused: explain the non-obvious design decision or constraint (e.g., credential storage semantics, security or UX reasons, or upstream API differences) that necessitates using a setup form, rather than describing the behavior itself. Ensure the new comment references the list's purpose only in terms of the why, then remove any redundant explanatory lines.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/components/apps/bigbluebuttonvideo/Setup.tsx`:
- Line 83: Replace the hardcoded placeholder
"https://your-bbb-server.com/bigbluebutton" with a translatable key: add e.g.
"bigbluebutton.serverPlaceholder": "https://your-bbb-server.com/bigbluebutton"
to packages/i18n/locales/en/common.json, then in
apps/web/components/apps/bigbluebuttonvideo/Setup.tsx use the i18n translator
(e.g. useTranslation or t already in scope) to render the placeholder via
t('bigbluebutton.serverPlaceholder') instead of the literal string so the UI
string is localizable.
- Around line 37-44: The formSchema zod validator is defined but not wired into
useForm, so client-side validation isn't applied; update the useForm call (the
one creating form in Setup.tsx) to pass a resolver using zodResolver(formSchema)
(ensure zodResolver is imported) so that form validation runs before onSubmit
and FormValues matches the schema.
In `@apps/web/lib/apps/installation/`[[...step]]/getServerSideProps.ts:
- Around line 452-455: The getCredential branch that checks if (!credentialId &&
!appMetadata.isOAuth) calls setupFormRedirectFor(parsedAppSlug) and returns
setupRedirect directly, which violates the declared return type Promise<{
credentialId: number | null; redirect?: RedirectResult }>; instead, change that
branch to return an object with credentialId: null and redirect: setupRedirect
(i.e., return { credentialId: null, redirect: setupRedirect }) so the function
signature is honored while preserving the redirect behavior.
In `@packages/app-store/bigbluebuttonvideo/api/add.ts`:
- Around line 77-79: Replace the two throws that use new Error(...) with
ErrorWithCode so error handling is deterministic: where the handler checks
alreadyInstalled and currently does throw new Error("Already installed"), change
it to throw new ErrorWithCode("Already installed", "CONFLICT"); and where
credential creation failure currently throws new Error("Unable to create
credential") change it to throw new ErrorWithCode("Unable to create credential",
"INTERNAL"). Also add the required import for ErrorWithCode from the project
error utility and preserve the original messages and surrounding logic in the
same function (the checks referencing alreadyInstalled and the credential
creation path).
- Around line 71-76: The Prisma queries currently materialize full credential
rows; change prisma.credential.findFirst (used to set alreadyInstalled) to
select only non-sensitive fields (e.g., select: { id: true }) so you only check
existence, and likewise change prisma.credential.create to return only
non-sensitive fields (e.g., select: { id: true }) so credential.key is not
materialized unnecessarily; update the calls referencing
prisma.credential.findFirst and prisma.credential.create accordingly.
In `@packages/app-store/bigbluebuttonvideo/lib/bbbClient.test.ts`:
- Around line 37-41: The test for buildSignedUrl contains contradictory
assertions: one expects the URL to end with an empty checksum ("...?checksum=")
while the other expects a 40-char checksum; remove the exact-match assertion and
keep a single, consistent check (e.g., use
expect(url).toMatch(/\/api\/getMeetings\?checksum=[0-9a-f]{40}$/)) so the test
verifies the URL path and a valid SHA-1 checksum produced by buildSignedUrl
rather than an empty checksum.
In `@packages/app-store/bigbluebuttonvideo/lib/bbbClient.ts`:
- Around line 91-103: The fetch call that sets response (inside the try block in
bbbClient.ts) can throw on network/abort errors and currently escapes; wrap the
await fetch(...) in a try/catch (keeping the existing finally that calls
clearTimeout(timeoutId)) and in the catch convert any thrown error into a
BbbApiError (e.g., new BbbApiError(error.message or a short description,
"bbb_network_error")), preserving original error details if possible (as cause
or included in the message) so callers always receive a BbbApiError instead of
raw exceptions; reference the existing symbols response, controller.signal,
timeoutId, and BbbApiError when making the change.
- Around line 51-53: The XML validation check in bbbClient.ts is inverted:
XMLValidator.validate(xmlResponse) returns true for valid XML and an error
object for invalid XML, so replace the current negated check with a proper
comparison (e.g., let validation = XMLValidator.validate(xmlResponse); if
(validation !== true) throw new BbbApiError("BBB returned a malformed XML
response.", "malformed_xml_response");) referencing XMLValidator.validate,
xmlResponse, and BbbApiError to locate the change.
In `@packages/app-store/bigbluebuttonvideo/lib/VideoApiAdapter.ts`:
- Around line 86-95: The join URL for attendees is missing the required
BigBlueButton checksum—replace the direct buildUrl(...) usage in the
createMeeting and updateMeeting flows with the existing BBB signing utilities:
construct the same query string used for buildUrl (meetingID,
password/attendeePW, fullName) and pass it to buildChecksum or buildSignedUrl
together with bbbCredential.sharedSecret so the generated joinUrl includes the
checksum; update the call sites that currently call buildUrl(...) (referencing
buildUrl, meetingId, attendeePW, bbbCredential.sharedSecret) to use
buildSignedUrl/buildChecksum to produce a signed URL.
In `@packages/app-store/bigbluebuttonvideo/zod.ts`:
- Line 10: Update the zod string validator for sharedSecret to trim whitespace
before checking non-emptiness: replace the current z.string().min(1) for the
sharedSecret field with a transformed/trimmed string validator (e.g.,
z.string().transform(s => s.trim()).min(1)) so whitespace-only values are
rejected; modify the sharedSecret schema entry accordingly.
---
Nitpick comments:
In `@apps/web/components/apps/appsWithSetupForm.ts`:
- Around line 1-5: The top-of-file comment blocks are "what" comments that
restate behavior; remove or rewrite them to capture the rationale for the
special-case list of app slugs (i.e., why certain non-OAuth apps require a
custom setup form and must follow the setup flow instead of the auto-install
flow). Update the comment(s) near the list(s) in appsWithSetupForm.ts (and the
similar blocks referenced around the other comment ranges) to be terse and
intent-focused: explain the non-obvious design decision or constraint (e.g.,
credential storage semantics, security or UX reasons, or upstream API
differences) that necessitates using a setup form, rather than describing the
behavior itself. Ensure the new comment references the list's purpose only in
terms of the why, then remove any redundant explanatory lines.
In `@apps/web/components/apps/bigbluebuttonvideo/Setup.tsx`:
- Line 20: Remove the comment(s) that state obvious facts (e.g. the /* 表单字段验证模式
*/ and the similar comments at lines 28-31) from the Setup component; if
additional context is needed, replace them with a brief "why" comment explaining
intent or rationale for the validation mode/behavior used in the Setup.tsx
component (reference the Setup component and any local validation-related
variables/props to place the why-comment).
In `@apps/web/lib/apps/installation/`[[...step]]/getServerSideProps.ts:
- Line 451: The inline comment "// 无凭证且 app 需要 setup form 时,重定向到 setup 页面采集凭证"
in getServerSideProps is restating the code path; remove it or replace it with a
brief rationale explaining the non-obvious intent (e.g., why redirecting here is
required for UX/consistency or to avoid exposing partial app state). Locate the
comment near the getServerSideProps handler in
apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts and either
delete that line or swap it for a one-sentence "why" comment referencing the
redirect's purpose and any trade-offs (security/UX), not the "what".
In `@apps/web/modules/apps/components/AppCard.tsx`:
- Line 75: Remove the redundant inline “what” comment above the setup-form
branch in the AppCard component: open the AppCard component (symbol AppCard) and
delete the single-line Chinese comment that restates behavior for setup-form
apps so only necessary rationale comments remain, keeping the control flow
self-explanatory.
In `@packages/app-store/bigbluebuttonvideo/api/add.ts`:
- Around line 13-18: The comments in the BigBlueButton installation handler
(packages/app-store/bigbluebuttonvideo/api/add.ts — the POST handler function)
are “what” comments that merely restate code flow; remove or replace them so
only non-obvious rationale remains (explain why decisions were made, e.g., why
you validate with getMeetings, why you encrypt the secret, any security
assumptions or edge cases), and delete redundant inline comments around the
credential validation, encryption/storage, and redirect logic (currently near
the credential parsing, getMeetings call, encryption step, and redirect
response). Ensure any retained comments explain intent or trade-offs rather than
restating actions.
In `@packages/app-store/bigbluebuttonvideo/lib/VideoApiAdapter.ts`:
- Around line 17-24: Replace the plain Error throws in VideoApiAdapter.ts with
the project's ErrorWithCode so credential/config validation failures follow the
repo's non-tRPC error contract: where encryptionKey is validated (the branch
throwing "CALENDSO_ENCRYPTION_KEY environment variable is not set.") and where
credentialKey type is checked (the branch throwing "Invalid credential key
format."), throw new ErrorWithCode with an appropriate code (e.g., "BAD_REQUEST"
or "INVALID_CREDENTIALS") and descriptive message; also add the ErrorWithCode
import at the top of the file if not present.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 4495d7a2-4380-42e1-b485-23391125aeaa
⛔ Files ignored due to path filters (1)
packages/app-store/bigbluebuttonvideo/static/icon.svgis excluded by!**/*.svg
📒 Files selected for processing (24)
apps/web/components/apps/AppSetupPage.tsxapps/web/components/apps/appsWithSetupForm.tsapps/web/components/apps/bigbluebuttonvideo/Setup.tsxapps/web/lib/apps/installation/[[...step]]/getServerSideProps.tsapps/web/modules/apps/components/AppCard.tsxpackages/app-store/apps.keys-schemas.generated.tspackages/app-store/apps.metadata.generated.tspackages/app-store/apps.schemas.generated.tspackages/app-store/apps.server.generated.tspackages/app-store/bigbluebuttonvideo/DESCRIPTION.mdpackages/app-store/bigbluebuttonvideo/_metadata.tspackages/app-store/bigbluebuttonvideo/api/add.tspackages/app-store/bigbluebuttonvideo/api/index.tspackages/app-store/bigbluebuttonvideo/index.tspackages/app-store/bigbluebuttonvideo/lib/VideoApiAdapter.test.tspackages/app-store/bigbluebuttonvideo/lib/VideoApiAdapter.tspackages/app-store/bigbluebuttonvideo/lib/bbbClient.test.tspackages/app-store/bigbluebuttonvideo/lib/bbbClient.tspackages/app-store/bigbluebuttonvideo/lib/index.tspackages/app-store/bigbluebuttonvideo/package.jsonpackages/app-store/bigbluebuttonvideo/zod.tspackages/app-store/bookerApps.metadata.generated.tspackages/app-store/video.adapters.generated.tspackages/i18n/locales/en/common.json
| if (!credentialId && !appMetadata.isOAuth) { | ||
| const setupRedirect = setupFormRedirectFor(parsedAppSlug); | ||
| if (setupRedirect) return setupRedirect; | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify return statements inside getCredential and compare shape expectations.
rg -n "const getCredential|return \\{ credentialId|return setupRedirect|Promise<\\{ credentialId" apps/web/lib/apps/installation/[[...step]]/getServerSideProps.tsRepository: calcom/cal.diy
Length of output: 391
Fix getCredential return shape when redirecting to the setup form.
getCredential is typed to return Promise<{ credentialId: number | null; redirect?: RedirectResult }>, but the setupRedirect branch returns setupRedirect directly (missing credentialId, around lines 452–455), causing a TypeScript contract mismatch.
Suggested fix
if (!credentialId && !appMetadata.isOAuth) {
const setupRedirect = setupFormRedirectFor(parsedAppSlug);
- if (setupRedirect) return setupRedirect;
+ if (setupRedirect) return { credentialId: null, redirect: setupRedirect };
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (!credentialId && !appMetadata.isOAuth) { | |
| const setupRedirect = setupFormRedirectFor(parsedAppSlug); | |
| if (setupRedirect) return setupRedirect; | |
| } | |
| if (!credentialId && !appMetadata.isOAuth) { | |
| const setupRedirect = setupFormRedirectFor(parsedAppSlug); | |
| if (setupRedirect) return { credentialId: null, redirect: setupRedirect }; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/lib/apps/installation/`[[...step]]/getServerSideProps.ts around
lines 452 - 455, The getCredential branch that checks if (!credentialId &&
!appMetadata.isOAuth) calls setupFormRedirectFor(parsedAppSlug) and returns
setupRedirect directly, which violates the declared return type Promise<{
credentialId: number | null; redirect?: RedirectResult }>; instead, change that
branch to return an object with credentialId: null and redirect: setupRedirect
(i.e., return { credentialId: null, redirect: setupRedirect }) so the function
signature is honored while preserving the redirect behavior.
| const alreadyInstalled = await prisma.credential.findFirst({ | ||
| where: { | ||
| type: appType, | ||
| ...installForObject, | ||
| }, | ||
| }); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify credential queries in this handler and whether they use select/include.
rg -n -C3 'prisma\.credential\.(findFirst|create)\(' packages/app-store/bigbluebuttonvideo/api/add.tsRepository: calcom/cal.diy
Length of output: 438
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE="packages/app-store/bigbluebuttonvideo/api/add.ts"
echo "== findFirst block =="
nl -ba "$FILE" | sed -n '60,95p'
echo
echo "== create block =="
nl -ba "$FILE" | sed -n '90,140p'
echo
echo "== Any reference to installation/alreadyInstalled fields =="
rg -n "alreadyInstalled|installation" "$FILE" -nRepository: calcom/cal.diy
Length of output: 141
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE="packages/app-store/bigbluebuttonvideo/api/add.ts"
echo "== findFirst block (lines ~60-95) =="
cat -n "$FILE" | sed -n '60,95p'
echo
echo "== create block (lines ~88-140) =="
cat -n "$FILE" | sed -n '88,140p'
echo
echo "== Check select/include on prisma.credential.* in this file =="
rg -n --context 2 "prisma\.credential\.(findFirst|create)\(" "$FILE"
rg -n --context 2 "select\s*:\s*\{|include\s*:\s*\{" "$FILE"
echo
echo "== References to installation/alreadyInstalled in this file =="
rg -n "alreadyInstalled|installation" "$FILE"Repository: calcom/cal.diy
Length of output: 2671
Restrict Prisma credential queries to non-sensitive fields
prisma.credential.findFirstreturns the fullcredentialrow withoutselect; this should be limited to non-sensitive fields (e.g.,id) since it’s only used as a boolean check.prisma.credential.createalso returns the full row withoutselect; limit the returned fields (e.g.,id) socredential.keyisn’t materialized unnecessarily.
Proposed fix
- const alreadyInstalled = await prisma.credential.findFirst({
+ const alreadyInstalled = await prisma.credential.findFirst({
where: {
type: appType,
...installForObject,
},
+ select: { id: true },
});
@@
- const installation = await prisma.credential.create({
+ await prisma.credential.create({
data: {
type: appType,
key: encryptedKey as unknown as Prisma.JsonValue,
...installForObject,
appId: "bigbluebutton",
},
+ select: { id: true },
});
-
- if (!installation) {
- throw new Error("Unable to create user credential for bigbluebuttonvideo");
- }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/app-store/bigbluebuttonvideo/api/add.ts` around lines 71 - 76, The
Prisma queries currently materialize full credential rows; change
prisma.credential.findFirst (used to set alreadyInstalled) to select only
non-sensitive fields (e.g., select: { id: true }) so you only check existence,
and likewise change prisma.credential.create to return only non-sensitive fields
(e.g., select: { id: true }) so credential.key is not materialized
unnecessarily; update the calls referencing prisma.credential.findFirst and
prisma.credential.create accordingly.
| // 构建参会者加入链接:attendeePW 直接嵌入 URL | ||
| const joinUrl = buildUrl({ | ||
| baseUrl: bbbCredential.serverUrl, | ||
| path: `/api/join`, | ||
| queryParams: { | ||
| meetingID: meetingId, | ||
| password: attendeePW, | ||
| fullName: "Guest", | ||
| }, | ||
| }); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE="packages/app-store/bigbluebuttonvideo/lib/VideoApiAdapter.ts"
echo "== File context =="
wc -l "$FILE"
echo
echo "== Snippet around lines 70-120 =="
sed -n '70,120p' "$FILE" | cat -n
echo
echo "== Snippet around lines 130-200 =="
sed -n '130,200p' "$FILE" | cat -n
echo
echo "== Search for checksum/signing/join URL helpers in this file =="
rg -n "checksum|sign|signature|join.*checksum|api/join|buildUrl\\(" "$FILE" || true
echo
echo "== Search repo for any helper that generates BBB join/checksum URLs =="
rg -n "joinUrl|api/join|checksum" packages/app-store/bigbluebuttonvideo/lib || true
echo
echo "== Search repo for BigBlueButton signing implementation (Key/secret, query signing, HMAC, etc.) =="
rg -n "CALENDSO_ENCRYPTION_KEY|decryptCredentialKey|hmac|HMAC|crypto|md5\\(|sha1\\(|signature|checksum" packages/app-store/bigbluebuttonvideo/lib || trueRepository: calcom/cal.diy
Length of output: 10881
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE1="packages/app-store/bigbluebuttonvideo/lib/bbbClient.ts"
FILE2="packages/app-store/bigbluebuttonvideo/lib/VideoApiAdapter.ts"
echo "== bbbClient.ts (top) =="
sed -n '1,140p' "$FILE1" | cat -n
echo
echo "== VideoApiAdapter.ts (decryptCredentialKey) =="
sed -n '1,120p' "$FILE2" | cat -n
echo
echo "== VideoApiAdapter.ts (createMeeting joinUrl return) =="
sed -n '60,120p' "$FILE2" | cat -n
echo
echo "== VideoApiAdapter.ts (updateMeeting joinUrl return) =="
sed -n '120,190p' "$FILE2" | cat -n
echo
echo "== Search within VideoApiAdapter.ts for ErrorWithCode usage =="
rg -n "ErrorWithCode" "$FILE2" || trueRepository: calcom/cal.diy
Length of output: 13226
Sign the BBB /api/join URLs (missing checksum)
createMeeting and updateMeeting return join URLs built via buildUrl(...path: \/api/join`...)withmeetingID, password, and fullName, but **no checksum`**—so participant join links can fail.
// 构建参会者加入链接:attendeePW 直接嵌入 URL
const joinUrl = buildUrl({
baseUrl: bbbCredential.serverUrl,
path: `/api/join`,
queryParams: {
meetingID: meetingId,
password: attendeePW,
fullName: "Guest",
},
});Generate these join URLs using the existing BBB signing flow (e.g., buildSignedUrl/buildChecksum) with bbbCredential.sharedSecret and the exact queryString used in the URL. (Applies to both the createMeeting join URL and the updateMeeting join URL.)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/app-store/bigbluebuttonvideo/lib/VideoApiAdapter.ts` around lines 86
- 95, The join URL for attendees is missing the required BigBlueButton
checksum—replace the direct buildUrl(...) usage in the createMeeting and
updateMeeting flows with the existing BBB signing utilities: construct the same
query string used for buildUrl (meetingID, password/attendeePW, fullName) and
pass it to buildChecksum or buildSignedUrl together with
bbbCredential.sharedSecret so the generated joinUrl includes the checksum;
update the call sites that currently call buildUrl(...) (referencing buildUrl,
meetingId, attendeePW, bbbCredential.sharedSecret) to use
buildSignedUrl/buildChecksum to produce a signed URL.
|
|
- Add zodResolver to Setup form for proper validation - Trim sharedSecret in zod schema to prevent whitespace-only values - Fix XMLValidator return type check (true vs object with err) - Add network/abort error handling in callBbb with BbbApiError - Replace generic Error with ErrorWithCode in add.ts - Fix contradictory checksum assertion in bbbClient.test.ts - Move server URL placeholder to i18n keys
bandhan-majumder
left a comment
There was a problem hiding this comment.
please add a working demo in the description!
|
Thank u for ur contribution. Closing. please refer: #1985 (comment) |
Description
Add BigBlueButton as a conferencing app in the app store. This integration enables users to create and manage BBB meetings directly from Cal.diy.
Closes #1985
Changes
New Files (18)
Modified Files (10)
Architecture
Testing
/claim #1985