forked from cerc-io/snowballtools-base
Implement functionality for editing domain (#57)
* Make use of domain id for redirecting domains * Add checks in backend to prevent chain redirecting and editing redirected domain * Add self relation to domain entity and use it to create and edit domains * Add self referencing relation to initialize db script * Add redirectToId column in domain entity * Remove isRedirected flag from domain entity * Refactor edit domain dialog box * Use dummy data for repository --------- Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
committed by
Ashwin Phatak
co-authored by
neeraj
parent
ace27c7eae
commit
0dd6c7702a
@@ -378,24 +378,22 @@ export class Database {
|
||||
|
||||
const primaryDomainDetails = {
|
||||
...domainDetails,
|
||||
isRedirected: false,
|
||||
branch: currentProject.prodBranch,
|
||||
project: currentProject
|
||||
};
|
||||
|
||||
const primaryDomain = domainRepository.create(primaryDomainDetails as DeepPartial<Domain>);
|
||||
const savedPrimaryDomain = await domainRepository.save(primaryDomain);
|
||||
|
||||
const domainArr = domainDetails.name.split('www.');
|
||||
|
||||
const redirectedDomainDetails = {
|
||||
name: domainArr.length > 1 ? domainArr[1] : `www.${domainArr[0]}`,
|
||||
isRedirected: true,
|
||||
branch: currentProject.prodBranch,
|
||||
project: currentProject
|
||||
project: currentProject,
|
||||
redirectTo: savedPrimaryDomain
|
||||
};
|
||||
|
||||
const savedPrimaryDomain = await domainRepository.save(primaryDomain);
|
||||
|
||||
const redirectedDomain = domainRepository.create(redirectedDomainDetails as DeepPartial<Domain>);
|
||||
const savedRedirectedDomain = await domainRepository.save(redirectedDomain);
|
||||
|
||||
@@ -406,6 +404,9 @@ export class Database {
|
||||
const domainRepository = this.dataSource.getRepository(Domain);
|
||||
|
||||
const domains = await domainRepository.find({
|
||||
relations: {
|
||||
redirectTo: true
|
||||
},
|
||||
where: {
|
||||
project: {
|
||||
id: projectId
|
||||
@@ -416,10 +417,56 @@ export class Database {
|
||||
return domains;
|
||||
}
|
||||
|
||||
async updateDomainById (domainId: string, updates: DeepPartial<Domain>): Promise<boolean> {
|
||||
async updateDomainById (domainId: string, data: DeepPartial<Domain>): Promise<boolean> {
|
||||
const domainRepository = this.dataSource.getRepository(Domain);
|
||||
|
||||
const updateResult = await domainRepository.update({ id: Number(domainId) }, updates);
|
||||
const domain = await domainRepository.findOne({
|
||||
where: {
|
||||
id: Number(domainId)
|
||||
}
|
||||
});
|
||||
|
||||
const newDomain: DeepPartial<Domain> = {
|
||||
...data
|
||||
};
|
||||
|
||||
if (domain === null) {
|
||||
throw new Error(`Error finding domain with id ${domainId}`);
|
||||
}
|
||||
|
||||
const domainsRedirectedFrom = await domainRepository.find({
|
||||
where: {
|
||||
project: {
|
||||
id: domain.projectId
|
||||
},
|
||||
redirectToId: domain.id
|
||||
}
|
||||
});
|
||||
|
||||
// If there are domains redirecting to current domain, only branch of current domain can be updated
|
||||
if (domainsRedirectedFrom.length > 0 && data.branch === domain.branch) {
|
||||
throw new Error('Remove all redirects to this domain before updating');
|
||||
}
|
||||
|
||||
if (data.redirectToId) {
|
||||
const redirectedDomain = await domainRepository.findOne({
|
||||
where: {
|
||||
id: Number(data.redirectToId)
|
||||
}
|
||||
});
|
||||
|
||||
if (redirectedDomain === null) {
|
||||
throw new Error('Could not find Domain to redirect to');
|
||||
}
|
||||
|
||||
if (redirectedDomain.redirectToId) {
|
||||
throw new Error('Unable to redirect to the domain because it is already redirecting elsewhere. Redirects cannot be chained.');
|
||||
}
|
||||
|
||||
newDomain.redirectTo = redirectedDomain;
|
||||
}
|
||||
|
||||
const updateResult = await domainRepository.update({ id: Number(domainId) }, newDomain);
|
||||
|
||||
if (updateResult.affected) {
|
||||
return updateResult.affected > 0;
|
||||
|
||||
@@ -20,6 +20,9 @@ export class Domain {
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: number;
|
||||
|
||||
@Column('varchar')
|
||||
projectId!: string;
|
||||
|
||||
@ManyToOne(() => Project, { onDelete: 'CASCADE' })
|
||||
@JoinColumn({ name: 'projectId' })
|
||||
project!: Project;
|
||||
@@ -30,8 +33,13 @@ export class Domain {
|
||||
@Column('varchar', { length: 255 })
|
||||
name!: string;
|
||||
|
||||
@Column('boolean', { default: false })
|
||||
isRedirected!: boolean;
|
||||
@Column('int', { nullable: true })
|
||||
redirectToId!: number;
|
||||
|
||||
@ManyToOne(() => Domain)
|
||||
@JoinColumn({ name: 'redirectToId' })
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
redirectTo!: Domain | null;
|
||||
|
||||
@Column({
|
||||
enum: Status,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import debug from 'debug';
|
||||
import assert from 'assert';
|
||||
import { DeepPartial } from 'typeorm';
|
||||
|
||||
import { OAuthApp } from '@octokit/oauth-app';
|
||||
|
||||
@@ -7,6 +8,7 @@ import { Database } from './database';
|
||||
import { deploymentToGqlType, projectMemberToGqlType, projectToGqlType, environmentVariableToGqlType, isUserOwner } from './utils';
|
||||
import { Environment } from './entity/Deployment';
|
||||
import { Permission } from './entity/ProjectMember';
|
||||
import { Domain } from './entity/Domain';
|
||||
|
||||
const log = debug('snowball:database');
|
||||
|
||||
@@ -233,7 +235,7 @@ export const createResolvers = async (db: Database, app: OAuthApp): Promise<any>
|
||||
}
|
||||
},
|
||||
|
||||
updateDomain: async (_: any, { domainId, domainDetails }: { domainId: string, domainDetails: {name?: string, isRedirected?: boolean, branch?: string }}) => {
|
||||
updateDomain: async (_: any, { domainId, domainDetails }: { domainId: string, domainDetails: DeepPartial<Domain>}) => {
|
||||
try {
|
||||
await db.updateDomainById(domainId, domainDetails);
|
||||
return true;
|
||||
|
||||
@@ -98,7 +98,7 @@ type Domain {
|
||||
id: String!
|
||||
branch: String!
|
||||
name: String!
|
||||
isRedirected: Boolean!
|
||||
redirectTo: Domain
|
||||
status: DomainStatus!
|
||||
createdAt: String!
|
||||
updatedAt: String!
|
||||
@@ -163,8 +163,8 @@ input AddDomainInput {
|
||||
|
||||
input UpdateDomainInput {
|
||||
name: String
|
||||
isRedirected: Boolean
|
||||
branch: String
|
||||
redirectToId: String
|
||||
}
|
||||
|
||||
input UpdateEnvironmentVariableInput {
|
||||
|
||||
Vendored
-27
@@ -3,63 +3,36 @@
|
||||
"projectIndex": 0,
|
||||
"name": "randomurl.snowballtools.xyz",
|
||||
"status": "Live",
|
||||
"isRedirected": false,
|
||||
"branch": "main"
|
||||
},
|
||||
{
|
||||
"projectIndex": 0,
|
||||
"name": "saugatt.com",
|
||||
"status": "Pending",
|
||||
"isRedirected": false,
|
||||
"branch": "test"
|
||||
},
|
||||
{
|
||||
"projectIndex": 0,
|
||||
"name": "www.saugatt.com",
|
||||
"status": "Pending",
|
||||
"isRedirected": true,
|
||||
"branch": "test"
|
||||
},
|
||||
{
|
||||
"projectIndex": 1,
|
||||
"name": "randomurl.snowballtools.xyz",
|
||||
"status": "Live",
|
||||
"isRedirected": false,
|
||||
"branch": "main"
|
||||
},
|
||||
{
|
||||
"projectIndex": 1,
|
||||
"name": "saugatt.com",
|
||||
"status": "Pending",
|
||||
"isRedirected": false,
|
||||
"branch": "test"
|
||||
},
|
||||
{
|
||||
"projectIndex": 1,
|
||||
"name": "www.saugatt.com",
|
||||
"status": "Pending",
|
||||
"isRedirected": true,
|
||||
"branch": "test"
|
||||
},
|
||||
{
|
||||
"projectIndex": 2,
|
||||
"name": "randomurl.snowballtools.xyz",
|
||||
"status": "Live",
|
||||
"isRedirected": false,
|
||||
"branch": "main"
|
||||
},
|
||||
{
|
||||
"projectIndex": 2,
|
||||
"name": "saugatt.com",
|
||||
"status": "Pending",
|
||||
"isRedirected": false,
|
||||
"branch": "test"
|
||||
},
|
||||
{
|
||||
"projectIndex": 2,
|
||||
"name": "www.saugatt.com",
|
||||
"status": "Pending",
|
||||
"isRedirected": true,
|
||||
"branch": "test"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
[
|
||||
{
|
||||
"projectIndex": 0,
|
||||
"name": "www.saugatt.com",
|
||||
"status": "Pending",
|
||||
"redirectToIndex": 1,
|
||||
"branch": "test"
|
||||
},
|
||||
{
|
||||
"projectIndex": 1,
|
||||
"name": "www.saugatt.com",
|
||||
"status": "Pending",
|
||||
"redirectToIndex": 3,
|
||||
"branch": "test"
|
||||
},
|
||||
{
|
||||
"projectIndex": 2,
|
||||
"name": "www.saugatt.com",
|
||||
"status": "Pending",
|
||||
"redirectToIndex": 5,
|
||||
"branch": "test"
|
||||
}
|
||||
]
|
||||
@@ -22,9 +22,10 @@ const PROJECT_DATA_PATH = './fixtures/projects.json';
|
||||
const ORGANIZATION_DATA_PATH = './fixtures/organizations.json';
|
||||
const USER_ORGANIZATION_DATA_PATH = './fixtures/user-orgnizations.json';
|
||||
const PROJECT_MEMBER_DATA_PATH = './fixtures/project-members.json';
|
||||
const DOMAIN_DATA_PATH = './fixtures/domains.json';
|
||||
const PRIMARY_DOMAIN_DATA_PATH = './fixtures/primary-domains.json';
|
||||
const DEPLOYMENT_DATA_PATH = './fixtures/deployments.json';
|
||||
const ENVIRONMENT_VARIABLE_DATA_PATH = './fixtures/environment-variables.json';
|
||||
const REDIRECTED_DOMAIN_DATA_PATH = './fixtures/redirected-domains.json';
|
||||
|
||||
const loadAndSaveData = async <Entity extends ObjectLiteral>(entityType: EntityTarget<Entity>, dataSource: DataSource, filePath: string, relations?: any | undefined) => {
|
||||
const entitiesData = await fs.readFile(filePath, 'utf-8');
|
||||
@@ -54,6 +55,8 @@ const loadAndSaveData = async <Entity extends ObjectLiteral>(entityType: EntityT
|
||||
};
|
||||
|
||||
const generateTestData = async (dataSource: DataSource) => {
|
||||
const domainRepository = await dataSource.getRepository(Domain);
|
||||
|
||||
const savedUsers = await loadAndSaveData(User, dataSource, path.resolve(__dirname, USER_DATA_PATH));
|
||||
const savedOrgs = await loadAndSaveData(Organization, dataSource, path.resolve(__dirname, ORGANIZATION_DATA_PATH));
|
||||
|
||||
@@ -64,11 +67,20 @@ const generateTestData = async (dataSource: DataSource) => {
|
||||
|
||||
const savedProjects = await loadAndSaveData(Project, dataSource, path.resolve(__dirname, PROJECT_DATA_PATH), projectRelations);
|
||||
|
||||
const domainRelations = {
|
||||
const domainPrimaryRelations = {
|
||||
project: savedProjects
|
||||
};
|
||||
|
||||
const savedDomains = await loadAndSaveData(Domain, dataSource, path.resolve(__dirname, DOMAIN_DATA_PATH), domainRelations);
|
||||
const savedPrimaryDomains = await loadAndSaveData(Domain, dataSource, path.resolve(__dirname, PRIMARY_DOMAIN_DATA_PATH), domainPrimaryRelations);
|
||||
|
||||
const domainRedirectedRelations = {
|
||||
project: savedProjects,
|
||||
redirectTo: savedPrimaryDomains
|
||||
};
|
||||
|
||||
await loadAndSaveData(Domain, dataSource, path.resolve(__dirname, REDIRECTED_DOMAIN_DATA_PATH), domainRedirectedRelations);
|
||||
|
||||
const savedDomains = await domainRepository.find();
|
||||
|
||||
const userOrganizationRelations = {
|
||||
member: savedUsers,
|
||||
|
||||
Reference in New Issue
Block a user