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:
2024-02-01 11:37:57 +05:30
committed by Ashwin Phatak
co-authored by neeraj
parent ace27c7eae
commit 0dd6c7702a
13 changed files with 177 additions and 94 deletions
+54 -7
View File
@@ -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;
+10 -2
View File
@@ -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,
+3 -1
View File
@@ -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;
+2 -2
View File
@@ -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 {