Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@devkiran
Copy link
Collaborator

@devkiran devkiran commented Aug 28, 2025

Summary by CodeRabbit

  • New Features

    • Clearer, more actionable error messages when a domain is missing, invalid, or already in use.
    • Immediate validation feedback in the add/edit domain form.
  • Bug Fixes

    • Stricter domain validation to prevent reserved domains (e.g., dub.co, dub.sh, d.to and their subdomains).
    • Case-insensitive checks to reduce false positives/negatives and ensure consistent validation results.
    • Improved detection of existing domains to avoid duplicates.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 28, 2025

Walkthrough

Refactors domain validation by extracting isValidDomain into a new module, updates imports accordingly, and introduces validateDomain and domainExists in utils.ts to orchestrate syntax validation and database existence checks. No behavioral changes to existing routes or UI usage aside from the new import path.

Changes

Cohort / File(s) Summary
Import source update
apps/web/app/api/domains/.../validate/route.ts, apps/web/ui/domains/add-edit-domain-form.tsx
Switch isValidDomain import from @/lib/api/domains to @/lib/api/domains/is-valid-domain; usage unchanged.
New validation module
apps/web/lib/api/domains/is-valid-domain.ts
Adds isValidDomain(domain: string) using validDomainRegex and blacklist exclusions (dub.co, dub.sh, d.to and their subdomains), case-insensitive.
Validation orchestration & DB check
apps/web/lib/api/domains/utils.ts
Removes local isValidDomain export; adds validateDomain(domain) to coordinate input checks, syntax validation, and uniqueness; adds domainExists(domain) using Prisma; updates public exports.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Caller
  participant Utils as utils.validateDomain
  participant Syntax as is-valid-domain.isValidDomain
  participant DB as Prisma

  Caller->>Utils: validateDomain(domain)
  alt Missing/invalid input
    Utils-->>Caller: { error: "...", code: "unprocessable_entity" }
  else Input present
    Utils->>Syntax: isValidDomain(domain)
    alt Invalid syntax
      Utils-->>Caller: { error: "...", code: "unprocessable_entity" }
    else Valid syntax
      Utils->>DB: domainExists(domain)
      alt Exists
        Utils-->>Caller: { error: "...", code: "conflict" }
      else Not found
        Utils-->>Caller: { error: null }
      end
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

A whisk of whiskers, I validate and hop,
New paths for checks, a tidy little swap.
Regex carrots, blacklist burrowed deep,
Prisma peeks to see which fields we keep.
All set—no d.to in this plot—
I thump approve: ship it, trot! 🥕🛠️

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-qstash-warning

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbit in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbit in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbit gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbit read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbit help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbit ignore or @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbit summary or @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbit or @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@vercel
Copy link
Contributor

vercel bot commented Aug 28, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
dub Ready Ready Preview Aug 28, 2025 11:30am

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/lib/api/domains/utils.ts (1)

5-19: Normalize once; pass normalized value through validation and existence checks

Prevents case/whitespace/trailing-dot mismatches between validation and DB lookup.

Apply:

 export const validateDomain = async (
   domain: string,
 ): Promise<{ error: string | null; code?: DubApiError["code"] }> => {
-  if (!domain || typeof domain !== "string") {
+  if (!domain || typeof domain !== "string") {
     return { error: "Missing domain", code: "unprocessable_entity" };
   }
-  if (!isValidDomain(domain)) {
+  const normalized = domain.trim().replace(/\.$/, "").toLowerCase();
+  if (!isValidDomain(normalized)) {
     return { error: "Invalid domain", code: "unprocessable_entity" };
   }
-  const exists = await domainExists(domain);
+  const exists = await domainExists(normalized);
   if (exists) {
     return { error: "Domain is already in use.", code: "conflict" };
   }
   return { error: null };
 };
🧹 Nitpick comments (4)
apps/web/lib/api/domains/is-valid-domain.ts (1)

3-9: Normalize input and tighten blacklist to prevent edge-case bypasses

Trim, lowercase, and strip a trailing dot before checks; require at least one subdomain label for the blacklist entries.

Apply:

-import { validDomainRegex } from "@dub/utils";
-
-export const isValidDomain = (domain: string) => {
-  return (
-    validDomainRegex.test(domain) &&
-    // make sure the domain doesn't contain dub.co/dub.sh/d.to
-    !/^(dub\.co|.*\.dub\.co|dub\.sh|.*\.dub\.sh|d\.to|.*\.d\.to)$/i.test(domain)
-  );
-};
+import { validDomainRegex } from "@dub/utils";
+
+const DISALLOWED = /^(dub\.co|.+\.dub\.co|dub\.sh|.+\.dub\.sh|d\.to|.+\.d\.to)$/i;
+
+export const isValidDomain = (domain: string) => {
+  const normalized = domain.trim().replace(/\.$/, "").toLowerCase();
+  return validDomainRegex.test(normalized) && !DISALLOWED.test(normalized);
+};
apps/web/app/api/domains/[domain]/validate/route.ts (1)

7-7: Typo in comment: “valdiate” → “validate”

Apply the rename as in the diff above.

apps/web/lib/api/domains/utils.ts (2)

21-31: Consider enforcing server-only usage of this module

Add server-only guard to prevent accidental client bundling.

Apply at the top of the file:

+import "server-only";
 import { prisma } from "@dub/prisma";

21-31: Optional: add a unique index on domain.slug (if not already present)

Avoids race conditions on existence checks and speeds lookups.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4d203fe and 1433b87.

📒 Files selected for processing (4)
  • apps/web/app/api/domains/[domain]/validate/route.ts (1 hunks)
  • apps/web/lib/api/domains/is-valid-domain.ts (1 hunks)
  • apps/web/lib/api/domains/utils.ts (1 hunks)
  • apps/web/ui/domains/add-edit-domain-form.tsx (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (6)
apps/web/lib/api/domains/is-valid-domain.ts (1)

1-9: Client-safe extraction of isValidDomain — LGTM

Isolating validation into a pure module removes server-only deps from the client path and should address the QStash warning.

apps/web/ui/domains/add-edit-domain-form.tsx (2)

1-1: Good: import narrowed to a client-safe module

This avoids pulling server-only code (e.g., QStash) into the client bundle.


1-1: No remaining client-side imports of @/lib/api/domains – all occurrences are confined to server-only API routes under apps/web/app/api, so the UI code no longer pulls from the server-only barrel.

apps/web/app/api/domains/[domain]/validate/route.ts (1)

33-78: Optional SSRF hardening: add private/link-local IP guard before fetch
I didn’t find any existing isPrivateIP-style utilities in apps/web; consider resolving the domain (e.g., via dns.lookup), checking the returned IP against private and link-local ranges, and skipping the HTTP HEAD fetch if it’s in a forbidden range—retaining the 3 s timeouts and extracting this into a shared helper.

apps/web/lib/api/domains/utils.ts (2)

3-3: Good: server-only validator is no longer exported from here

This reduces accidental client imports from the barrel.


21-31: Ensure slug normalization (lowercasing) on write and read
Write-side calls (e.g. prisma.domain.create({ data: { slug: domain } })) pass raw values with no .toLowerCase() and no DB-level lowercase enforcement was found; add slug: domain.toLowerCase() (or a schema constraint) on both writes and in domainExists to avoid case-sensitive lookup failures.

@steven-tey steven-tey merged commit c76796f into main Aug 28, 2025
10 checks passed
@steven-tey steven-tey deleted the fix-qstash-warning branch August 28, 2025 15:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants