-
Notifications
You must be signed in to change notification settings - Fork 1
Domain fixes #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Domain fixes #17
Changes from all commits
2d2ce81
4ec61f0
4a0ae1a
45a73f9
a9068ef
1396f16
08c29a4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,7 @@ export async function createInbox({ | |
| ? new mongoose.Types.ObjectId(domain_id) | ||
| : undefined; | ||
| inbox.name = name; | ||
| inbox.email = email || await getNewRandomInboxEmail({ name }); | ||
| inbox.email = email || `${name.replace(/[^a-zA-Z0-9]/g, "-")}@${process.env.DEFAULT_EMAIL_DOMAIN}`; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainRisk of duplicate emails without uniqueness check. The deterministic email generation can create duplicate emails when multiple inboxes share the same name. The previous Additionally, names containing only non-alphanumeric characters (e.g., Verify whether the Inbox schema enforces a unique constraint on the email field: If no unique constraint exists, either:
If a unique constraint does exist, the 🏁 Script executed: #!/bin/bash
# Description: Check if the Inbox schema has a unique constraint on the email field
# Search for the Inbox schema definition
ast-grep --pattern 'email: {
$$$
}'
# Also search for unique index definitions
rg -n --type=ts -A5 -B5 'email.*unique|unique.*email' api/db/mongo/schemas/Length of output: 410 🏁 Script executed: #!/bin/bash
# Description: Verify getNewRandomInboxEmail usage and error handling
# Search for all calls to getNewRandomInboxEmail
echo "=== Searching for getNewRandomInboxEmail usage ==="
rg -n '\bgetNewRandomInboxEmail\b' --type=ts
# Check context around line 22 for error handling
echo "=== Checking context around line 21-22 for error handling ==="
sed -n '15,35p' api/controllers/InboxController.ts
# Search for try-catch or error handling around save operations
echo "=== Searching for error handling patterns in InboxController ==="
rg -n --type=ts -A3 '\.save\(' api/controllers/InboxController.tsLength of output: 1309 🏁 Script executed: #!/bin/bash
# Description: Check getNewRandomInboxEmail usage in AuthController
echo "=== AuthController usage of getNewRandomInboxEmail ==="
rg -n --type=ts -B5 -A5 'getNewRandomInboxEmail' api/controllers/AuthController.tsLength of output: 605 🏁 Script executed: #!/bin/bash
# Description: Search entire AuthController for getNewRandomInboxEmail function calls
echo "=== Full AuthController file ==="
cat api/controllers/AuthController.ts | grep -n "getNewRandomInboxEmail"Length of output: 124 Error handling required for duplicate email constraint violations and invalid email format edge case. The Inbox schema does enforce a unique constraint on the email field (confirmed at
Additionally, the 🤖 Prompt for AI Agents |
||
| await inbox.save(); | ||
| return inbox; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -9,6 +9,10 @@ import { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getDomainsByOrganizationId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| verifyDomainDNS, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } from "../../../controllers/DomainController"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getDomainVerificationDkimAttributes, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getDomainVerificationStatus, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } from "../../../controllers/SESController"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+12
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainVerify if The import includes Run this script to verify the usage: 🏁 Script executed: #!/bin/bash
# Description: Check if getDomainVerificationStatus is used in this routes file
# Search for usage of getDomainVerificationStatus in the file
rg -n 'getDomainVerificationStatus' api/routes/v1/domains/index.tsLength of output: 33 Length of output: 0 Length of output: 53 Remove the unused Verification confirms that 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const router = Router({ mergeParams: true }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -28,7 +32,9 @@ router.post( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .isString() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .trim() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .notEmpty() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .matches(/^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .matches( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .withMessage("Invalid domain name format"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expressValidatorMiddleware, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -82,6 +88,52 @@ router.post( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.get( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/:domainId/dns", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| req: Request<{ organizationId: string; domainId: string }, {}, {}>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| res: Response | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const domain = await getDomainByOrganizationIdAndName({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| organizationId: req.organization._id.toString(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: req.params.domainId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!domain) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return res.status(404).json({ error: "Domain not found" }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const verifiedDomainDkimAttributes = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await getDomainVerificationDkimAttributes({ domain: domain.name }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!verifiedDomainDkimAttributes.DkimTokens) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return res.status(400).json({ error: "Failed to get DKIM attributes" }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return res.json([ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: "MX", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: "@", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: "inbound-smtp.us-east-2.amazonaws.com", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: "TXT", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: "@", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: "v=spf1 include:amazonses.com ~all", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: "TXT", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: "_dmarc", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: "v=DMARC1; p=reject;", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+112
to
+127
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: Hardcoded AWS region and email policies. Several hardcoded values create deployment and configuration concerns:
Consider extracting these values to environment variables or configuration: + // In a config file or from environment variables
+ const AWS_SES_REGION = process.env.AWS_SES_REGION || 'us-east-2';
+ const SPF_POLICY = process.env.SPF_POLICY || 'v=spf1 include:amazonses.com ~all';
+ const DMARC_POLICY = process.env.DMARC_POLICY || 'v=DMARC1; p=reject;';
return res.json([
{
type: "MX",
name: "@",
- value: "inbound-smtp.us-east-2.amazonaws.com",
+ value: `inbound-smtp.${AWS_SES_REGION}.amazonaws.com`,
},
{
type: "TXT",
name: "@",
- value: "v=spf1 include:amazonses.com ~all",
+ value: SPF_POLICY,
},
{
type: "TXT",
name: "_dmarc",
- value: "v=DMARC1; p=reject;",
+ value: DMARC_POLICY,
},📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...verifiedDomainDkimAttributes.DkimTokens.map((token) => ({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: "CNAME", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: `${token}_domainkey.${domain.name}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: `${token}.dkim.amazonses.com`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| })) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.delete( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "/:domainId", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
TXT lookup only inspects the first TXT RR; consider flattening all records
resolveTxtreturnsstring[][], butgetDNSTXTRecordscurrently returns onlyrecords[0] ?? []. If the DMARC TXT is not in the first RR,verifyDomainDNSwill never see it. Prefer flattening all strings:export async function getDNSTXTRecords({ domain, }: { domain: string; }): Promise<string[]> { try { - const records = await resolveTxt(domain); - return records[0] ?? []; + const records = await resolveTxt(domain); + return records.flat(); } catch (error) { console.error('Error resolving TXT records:', error); return []; } }Also applies to: 17-29
🤖 Prompt for AI Agents