fix: normalize domain casing

Fix domain casing normalization for configured domains and inbound recipient domains.
This commit is contained in:
Hging
2026-05-16 18:35:39 +08:00
committed by GitHub
parent 8324b133fb
commit add0124cfd
26 changed files with 641 additions and 86 deletions
+109 -7
View File
@@ -137,12 +137,97 @@ export const getStringArray = (
return value;
}
export const trimLower = (
value: string | undefined | null
): string => {
return getStringValue(value).trim().toLowerCase();
}
export const normalizeDomain = (
value: string | undefined | null
): string => {
return trimLower(value);
}
export const normalizeDomains = (domains: string[]): string[] => {
return domains
.map((domain) => normalizeDomain(domain))
.filter((domain) => domain.length > 0);
}
export const getMailDomain = (
value: string | undefined | null
): string => {
const address = getStringValue(value).trim();
const atIndex = address.lastIndexOf("@");
if (atIndex < 0) {
return "";
}
return normalizeDomain(address.slice(atIndex + 1));
}
export const normalizeAddressDomain = (
value: string | undefined | null
): string => {
const address = getStringValue(value).trim();
const atIndex = address.lastIndexOf("@");
if (atIndex < 0) {
return address;
}
const localPart = address.slice(0, atIndex).trim();
const domain = normalizeDomain(address.slice(atIndex + 1));
if (!localPart || !domain) {
return address;
}
return `${localPart}@${domain}`;
}
export const includesDomain = (
domains: string[] | undefined | null,
domain: string | undefined | null
): boolean => {
const normalizedDomain = normalizeDomain(domain);
if (!normalizedDomain || !domains || domains.length === 0) {
return false;
}
return normalizeDomains(domains).includes(normalizedDomain);
}
export const isDomainOrSubdomain = (
domain: string | undefined | null,
allowDomain: string | undefined | null
): boolean => {
const normalizedDomain = normalizeDomain(domain);
const normalizedAllowDomain = normalizeDomain(allowDomain);
if (!normalizedDomain || !normalizedAllowDomain) {
return false;
}
return normalizedDomain === normalizedAllowDomain
|| normalizedDomain.endsWith(`.${normalizedAllowDomain}`);
}
export const getDomainMapValue = <T>(
valueMap: Record<string, T> | undefined | null,
domain: string | undefined | null
): T | null => {
const normalizedDomain = normalizeDomain(domain);
if (!normalizedDomain || !valueMap) {
return null;
}
for (const [key, value] of Object.entries(valueMap)) {
if (normalizeDomain(key) === normalizedDomain) {
return value;
}
}
return null;
}
export const getDefaultDomains = (c: Context<HonoCustomType>): string[] => {
if (c.env.DEFAULT_DOMAINS == undefined || c.env.DEFAULT_DOMAINS == null) {
return getDomains(c);
}
const domains = getStringArray(c.env.DEFAULT_DOMAINS);
return domains || getDomains(c);
const domains = normalizeDomains(getStringArray(c.env.DEFAULT_DOMAINS));
return domains.length > 0 ? domains : getDomains(c);
}
export const getDomains = (c: Context<HonoCustomType>): string[] => {
@@ -152,36 +237,46 @@ export const getDomains = (c: Context<HonoCustomType>): string[] => {
// check if DOMAINS is an array, if not use json.parse
if (!Array.isArray(c.env.DOMAINS)) {
try {
return JSON.parse(c.env.DOMAINS);
return normalizeDomains(JSON.parse(c.env.DOMAINS));
} catch (e) {
console.error("Failed to parse DOMAINS", e);
return [];
}
}
return c.env.DOMAINS;
return normalizeDomains(c.env.DOMAINS);
}
export const getRandomSubdomainDomains = (c: Context<HonoCustomType>): string[] => {
if (!c.env.RANDOM_SUBDOMAIN_DOMAINS) {
return [];
}
return getStringArray(c.env.RANDOM_SUBDOMAIN_DOMAINS);
return normalizeDomains(getStringArray(c.env.RANDOM_SUBDOMAIN_DOMAINS));
}
export const getUserRoles = (c: Context<HonoCustomType>): UserRole[] => {
if (!c.env.USER_ROLES) {
return [];
}
const normalizeRoles = (roles: UserRole[]): UserRole[] => {
return roles.map((role) => ({
...role,
domains: Array.isArray(role.domains)
? normalizeDomains(role.domains)
: typeof role.domains === "string"
? normalizeDomains([role.domains])
: role.domains,
}));
};
// check if USER_ROLES is an array, if not use json.parse
if (!Array.isArray(c.env.USER_ROLES)) {
try {
return JSON.parse(c.env.USER_ROLES);
return normalizeRoles(JSON.parse(c.env.USER_ROLES));
} catch (e) {
console.error("Failed to parse USER_ROLES", e);
return [];
}
}
return c.env.USER_ROLES;
return normalizeRoles(c.env.USER_ROLES);
}
export const getAnotherWorkerList = (c: Context<HonoCustomType>): AnotherWorker[] => {
@@ -414,6 +509,13 @@ export default {
getBooleanValue,
getIntValue,
getStringArray,
trimLower,
normalizeDomain,
normalizeDomains,
getMailDomain,
normalizeAddressDomain,
includesDomain,
getDomainMapValue,
getDefaultDomains,
getDomains,
getRandomSubdomainDomains,