chore: Move provisionSubdomain from Team model to teamCreator command

This commit is contained in:
Tom Moor
2022-06-22 11:09:20 +02:00
parent 88b3b50333
commit 6d4da176d1
4 changed files with 71 additions and 81 deletions

View File

@@ -26,6 +26,47 @@ describe("teamCreator", () => {
expect(isNewTeam).toEqual(true);
});
it("should set subdomain append if unavailable", async () => {
env.DEPLOYMENT = "hosted";
await buildTeam({
subdomain: "myteam",
});
const result = await teamCreator({
name: "Test team",
subdomain: "myteam",
avatarUrl: "http://example.com/logo.png",
authenticationProvider: {
name: "google",
providerId: "example.com",
},
});
expect(result.team.subdomain).toEqual("myteam1");
});
it("should increment subdomain append if unavailable", async () => {
env.DEPLOYMENT = "hosted";
await buildTeam({
subdomain: "myteam",
});
await buildTeam({
subdomain: "myteam1",
});
const result = await teamCreator({
name: "Test team",
subdomain: "myteam",
avatarUrl: "http://example.com/logo.png",
authenticationProvider: {
name: "google",
providerId: "example.com",
},
});
expect(result.team.subdomain).toEqual("myteam2");
});
describe("self hosted", () => {
it("should not allow creating multiple teams in installation", async () => {
env.DEPLOYMENT = undefined;

View File

@@ -1,3 +1,4 @@
import { sequelize } from "@server/database/sequelize";
import env from "@server/env";
import { DomainNotAllowedError, MaximumTeamsError } from "@server/errors";
import Logger from "@server/logging/Logger";
@@ -88,11 +89,8 @@ async function teamCreator({
});
}
const transaction = await Team.sequelize!.transaction();
let team;
try {
team = await Team.create(
const team = await sequelize.transaction(async (transaction) => {
return Team.create(
{
name,
avatarUrl,
@@ -103,14 +101,13 @@ async function teamCreator({
transaction,
}
);
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
});
// Note provisioning the subdomain is done outside of the transaction as
// it is allowed to fail and the team can still be created, it also requires
// failed queries as part of iteration
try {
await team.provisionSubdomain(subdomain);
await provisionSubdomain(team, subdomain);
} catch (err) {
Logger.error("Provisioning subdomain failed", err, {
teamId: team.id,
@@ -125,6 +122,28 @@ async function teamCreator({
};
}
async function provisionSubdomain(team: Team, requestedSubdomain: string) {
if (team.subdomain) {
return team.subdomain;
}
let subdomain = requestedSubdomain;
let append = 0;
for (;;) {
try {
await team.update({
subdomain,
});
break;
} catch (err) {
// subdomain was invalid or already used, try again
subdomain = `${requestedSubdomain}${++append}`;
}
}
return subdomain;
}
export default APM.traceFunction({
serviceName: "command",
spanName: "teamCreator",