API: Add endpoint to check custom domain resolution (#6110)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import dns from "dns";
|
||||
import Router from "koa-router";
|
||||
import { parseDomain } from "@shared/utils/domains";
|
||||
import { getBaseDomain, parseDomain } from "@shared/utils/domains";
|
||||
import parseDocumentSlug from "@shared/utils/parseDocumentSlug";
|
||||
import parseMentionUrl from "@shared/utils/parseMentionUrl";
|
||||
import { isInternalUrl } from "@shared/utils/urls";
|
||||
@@ -7,7 +8,7 @@ import { NotFoundError, ValidationError } from "@server/errors";
|
||||
import auth from "@server/middlewares/authentication";
|
||||
import { rateLimiter } from "@server/middlewares/rateLimiter";
|
||||
import validate from "@server/middlewares/validate";
|
||||
import { Document, User } from "@server/models";
|
||||
import { Document, Share, Team, User } from "@server/models";
|
||||
import { authorize } from "@server/policies";
|
||||
import { presentDocument, presentMention } from "@server/presenters/unfurls";
|
||||
import presentUnfurl from "@server/presenters/unfurls/unfurl";
|
||||
@@ -84,4 +85,63 @@ router.post(
|
||||
}
|
||||
);
|
||||
|
||||
router.post(
|
||||
"urls.validateCustomDomain",
|
||||
rateLimiter(RateLimiterStrategy.OneHundredPerHour),
|
||||
auth(),
|
||||
validate(T.UrlsCheckCnameSchema),
|
||||
async (ctx: APIContext<T.UrlsCheckCnameReq>) => {
|
||||
const { hostname } = ctx.input.body;
|
||||
|
||||
const [team, share] = await Promise.all([
|
||||
Team.findOne({
|
||||
where: {
|
||||
domain: hostname,
|
||||
},
|
||||
}),
|
||||
Share.findOne({
|
||||
where: {
|
||||
domain: hostname,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
if (team || share) {
|
||||
throw ValidationError("Domain is already in use");
|
||||
}
|
||||
|
||||
let addresses;
|
||||
try {
|
||||
addresses = await new Promise<string[]>((resolve, reject) => {
|
||||
dns.resolveCname(hostname, (err, addresses) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
return resolve(addresses);
|
||||
});
|
||||
});
|
||||
} catch (err) {
|
||||
if (err.code === "ENOTFOUND") {
|
||||
throw NotFoundError("No CNAME record found");
|
||||
}
|
||||
|
||||
throw ValidationError("Invalid domain");
|
||||
}
|
||||
|
||||
if (addresses.length === 0) {
|
||||
throw ValidationError("No CNAME record found");
|
||||
}
|
||||
|
||||
const address = addresses[0];
|
||||
const likelyValid = address.endsWith(getBaseDomain());
|
||||
|
||||
if (!likelyValid) {
|
||||
throw ValidationError("CNAME is not configured correctly");
|
||||
}
|
||||
|
||||
ctx.body = {
|
||||
success: true,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
export default router;
|
||||
|
||||
Reference in New Issue
Block a user