Skip to content

Commit e481010

Browse files
committed
fix sendOtpAction logic
1 parent 63f62d7 commit e481010

11 files changed

Lines changed: 171 additions & 186 deletions

File tree

apps/web/.env.example

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,6 @@ PLAIN_WEBHOOK_SECRET=
140140
###### DUB.CO INTERNAL USE ONLY ######
141141
######################################
142142

143-
# For the official Dub app
144-
NEXT_PUBLIC_IS_DUB=
145-
146143
# For storing vector embeddings (/api/support/chat)
147144
UPSTASH_VECTOR_REST_URL=
148145
UPSTASH_VECTOR_REST_TOKEN=

apps/web/lib/actions/send-otp.ts

Lines changed: 43 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -38,56 +38,52 @@ export const sendOtpAction = actionClient
3838
throw new Error("Too many requests. Please try again later.");
3939
}
4040

41-
if (email.includes("+") && isGenericEmail(email)) {
42-
throw new Error(
43-
"Email addresses with + are not allowed. Please use your work email instead.",
44-
);
45-
}
41+
const isGenericEmailWithPlus = email.includes("+") && isGenericEmail(email);
4642

47-
const domain = email.split("@")[1];
43+
const emailDomain = email.split("@")[1];
4844

49-
if (process.env.NEXT_PUBLIC_IS_DUB) {
50-
const [isDisposable, emailDomainTerms] = await Promise.all([
51-
redis.sismember("disposableEmailDomains", domain),
52-
process.env.EDGE_CONFIG ? get("emailDomainTerms") : [],
53-
]);
45+
const [isDisposable, emailDomainTerms] = await Promise.all([
46+
redis.sismember("disposableEmailDomains", emailDomain),
47+
process.env.EDGE_CONFIG ? get("emailDomainTerms") : [],
48+
]);
5449

55-
// Only build the regex if we have at least one term; otherwise set to null
56-
const blacklistedEmailDomainTermsRegex =
57-
emailDomainTerms && Array.isArray(emailDomainTerms)
58-
? new RegExp(
59-
emailDomainTerms
60-
.map((term: string) =>
61-
term.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"),
62-
) // replace special characters with escape sequences
63-
.join("|"),
64-
)
65-
: null;
66-
67-
if (
68-
isDisposable ||
69-
(blacklistedEmailDomainTermsRegex &&
70-
blacklistedEmailDomainTermsRegex.test(domain))
71-
) {
72-
// edge case: the user already has a partner account on Dub with this email address,
73-
// or they have an existing application for a program, we can allow them to continue
74-
const [isPartnerAccount, hasExistingApplications] = await Promise.all([
75-
prisma.partner.findUnique({
76-
where: {
77-
email,
78-
},
79-
}),
80-
prisma.programApplication.findFirst({
81-
where: {
82-
email,
83-
},
84-
}),
85-
]);
86-
if (!isPartnerAccount && !hasExistingApplications) {
87-
throw new Error(
88-
"Invalid email address – please use your work email instead. If you think this is a mistake, please contact us at dub.co/support",
89-
);
90-
}
50+
// Only build the regex if we have at least one term; otherwise set to null
51+
const blacklistedEmailDomainTermsRegex =
52+
emailDomainTerms && Array.isArray(emailDomainTerms)
53+
? new RegExp(
54+
emailDomainTerms
55+
.map((term: string) =>
56+
term.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"),
57+
) // replace special characters with escape sequences
58+
.join("|"),
59+
)
60+
: null;
61+
62+
// if any of the flags match, run one final edge case check, before throwing an error
63+
if (
64+
isGenericEmailWithPlus ||
65+
isDisposable ||
66+
(blacklistedEmailDomainTermsRegex &&
67+
blacklistedEmailDomainTermsRegex.test(emailDomain))
68+
) {
69+
// edge case: the user already has a partner account on Dub with this email address,
70+
// or they have an existing application for a program, we can allow them to continue
71+
const [isPartnerAccount, hasExistingApplications] = await Promise.all([
72+
prisma.partner.findUnique({
73+
where: {
74+
email,
75+
},
76+
}),
77+
prisma.programApplication.findFirst({
78+
where: {
79+
email,
80+
},
81+
}),
82+
]);
83+
if (!isPartnerAccount && !hasExistingApplications) {
84+
throw new Error(
85+
"Invalid email address – please use your work email instead. If you think this is a mistake, please contact us at dub.co/support",
86+
);
9187
}
9288
}
9389

apps/web/lib/analytics/get-analytics.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ export const getAnalytics = async (params: AnalyticsFilters) => {
7070
: `SUM(${event}) as ${event}`;
7171

7272
const response = await conn.execute(
73-
`SELECT ${aggregateColumns} FROM Link WHERE id IN (${linkIdPlaceholders})`,
74-
normalizedLinkId.values,
73+
`SELECT ${aggregateColumns} FROM Link WHERE id IN (${linkIdPlaceholders}) AND projectId = ?`,
74+
[...normalizedLinkId.values, workspaceId],
7575
);
7676

7777
return analyticsResponse["count"].parse(response.rows[0]);

apps/web/lib/api/links/utils/key-checks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export async function keyChecks({
4141
};
4242
}
4343

44-
if (isDubDomain(domain) && process.env.NEXT_PUBLIC_IS_DUB) {
44+
if (isDubDomain(domain)) {
4545
if (domain === "dub.sh" || domain === "dub.link") {
4646
if (DEFAULT_REDIRECTS[key] || RESERVED_SLUGS.includes(key)) {
4747
return {

apps/web/lib/edge-config/get-feature-flags.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const getFeatureFlags = async ({
1919
analyticsSettingsSiteVisitTracking: false,
2020
};
2121

22-
if (!process.env.NEXT_PUBLIC_IS_DUB || !process.env.EDGE_CONFIG) {
22+
if (!process.env.EDGE_CONFIG) {
2323
// return all features as true if edge config is not available
2424
return Object.fromEntries(
2525
Object.entries(workspaceFeatures).map(([key, _v]) => [key, true]),

apps/web/lib/edge-config/is-blacklisted-domain.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { getAll } from "@vercel/edge-config";
22

33
export const isBlacklistedDomain = async (domain: string): Promise<boolean> => {
4-
if (!process.env.NEXT_PUBLIC_IS_DUB || !process.env.EDGE_CONFIG) {
4+
if (!process.env.EDGE_CONFIG) {
55
return false;
66
}
77

apps/web/lib/edge-config/is-blacklisted-email.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { get } from "@vercel/edge-config";
22

33
export const isBlacklistedEmail = async (email: string | string[]) => {
4-
if (!process.env.NEXT_PUBLIC_IS_DUB || !process.env.EDGE_CONFIG) {
4+
if (!process.env.EDGE_CONFIG) {
55
return false;
66
}
77

apps/web/lib/edge-config/is-blacklisted-key.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { get } from "@vercel/edge-config";
22

33
export const isBlacklistedKey = async (key: string) => {
4-
if (!process.env.NEXT_PUBLIC_IS_DUB || !process.env.EDGE_CONFIG) {
4+
if (!process.env.EDGE_CONFIG) {
55
return false;
66
}
77

apps/web/lib/edge-config/is-blacklisted-referrer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { getDomainWithoutWWW } from "@dub/utils";
22
import { get } from "@vercel/edge-config";
33

44
export const isBlacklistedReferrer = async (referrer: string | null) => {
5-
if (!process.env.NEXT_PUBLIC_IS_DUB || !process.env.EDGE_CONFIG) {
5+
if (!process.env.EDGE_CONFIG) {
66
return false;
77
}
88

apps/web/lib/edge-config/is-reserved-username.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { get } from "@vercel/edge-config";
55
* Check if a username is reserved – should only be available on Pro+
66
*/
77
export const isReservedUsername = async (key: string) => {
8-
if (!process.env.NEXT_PUBLIC_IS_DUB || !process.env.EDGE_CONFIG) {
8+
if (!process.env.EDGE_CONFIG) {
99
return false;
1010
}
1111

0 commit comments

Comments
 (0)