feat(*): allow to select auth providers + add multiworkspace with subdomain management (#8656)
## Summary Add support for multi-workspace feature and adjust configurations and states accordingly. - Introduced new state isMultiWorkspaceEnabledState. - Updated ClientConfigProviderEffect component to handle multi-workspace. - Modified GraphQL schema and queries to include multi-workspace related configurations. - Adjusted server environment variables and their respective documentation to support multi-workspace toggle. - Updated server-side logic to handle new multi-workspace configurations and conditions.
This commit is contained in:
@ -0,0 +1,27 @@
|
||||
import { getDomainNameByEmail } from 'src/utils/get-domain-name-by-email';
|
||||
|
||||
describe('getDomainNameByEmail', () => {
|
||||
it('should return the domain name for a valid email', () => {
|
||||
expect(getDomainNameByEmail('user@example.com')).toBe('example.com');
|
||||
});
|
||||
|
||||
it('should throw an error if email is empty', () => {
|
||||
expect(() => getDomainNameByEmail('')).toThrow('Email is required');
|
||||
});
|
||||
|
||||
it('should throw an error if email does not contain "@"', () => {
|
||||
expect(() => getDomainNameByEmail('userexample.com')).toThrow(
|
||||
'Invalid email format',
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error if email has more than one "@"', () => {
|
||||
expect(() => getDomainNameByEmail('user@example@com')).toThrow(
|
||||
'Invalid email format',
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error if domain part is empty', () => {
|
||||
expect(() => getDomainNameByEmail('user@')).toThrow('Invalid email format');
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,24 @@
|
||||
import { isWorkEmail } from 'src/utils/is-work-email';
|
||||
|
||||
describe('isWorkEmail', () => {
|
||||
it('should return true for a work email', () => {
|
||||
expect(isWorkEmail('user@company.com')).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for a personal email', () => {
|
||||
expect(isWorkEmail('user@gmail.com')).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for an empty email string', () => {
|
||||
expect(isWorkEmail('')).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for an email with undefined domain', () => {
|
||||
// Assuming getDomainNameByEmail(email) returns undefined if no domain.
|
||||
expect(isWorkEmail('user@')).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for an invalid email format', () => {
|
||||
expect(isWorkEmail('invalid-email')).toBe(false);
|
||||
});
|
||||
});
|
||||
19
packages/twenty-server/src/utils/get-domain-name-by-email.ts
Normal file
19
packages/twenty-server/src/utils/get-domain-name-by-email.ts
Normal file
@ -0,0 +1,19 @@
|
||||
export const getDomainNameByEmail = (email: string) => {
|
||||
if (!email) {
|
||||
throw new Error('Email is required');
|
||||
}
|
||||
|
||||
const fields = email.split('@');
|
||||
|
||||
if (fields.length !== 2) {
|
||||
throw new Error('Invalid email format');
|
||||
}
|
||||
|
||||
const domain = fields[1];
|
||||
|
||||
if (!domain) {
|
||||
throw new Error('Invalid email format');
|
||||
}
|
||||
|
||||
return domain;
|
||||
};
|
||||
@ -1,21 +1,10 @@
|
||||
import { emailProvidersSet } from 'src/utils/email-providers';
|
||||
import { getDomainNameByEmail } from 'src/utils/get-domain-name-by-email';
|
||||
|
||||
export const isWorkEmail = (email: string) => {
|
||||
if (!email) {
|
||||
try {
|
||||
return !emailProvidersSet.has(getDomainNameByEmail(email));
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const fields = email.split('@');
|
||||
|
||||
if (fields.length !== 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const domain = fields[1];
|
||||
|
||||
if (!domain) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !emailProvidersSet.has(domain);
|
||||
};
|
||||
|
||||
33
packages/twenty-server/src/utils/workspace-url.util.ts
Normal file
33
packages/twenty-server/src/utils/workspace-url.util.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { isDefined } from 'src/utils/is-defined';
|
||||
|
||||
export const buildWorkspaceURL = (
|
||||
baseUrl: string,
|
||||
subdomain: string | null,
|
||||
{
|
||||
withPathname,
|
||||
withSearchParams,
|
||||
}: {
|
||||
withPathname?: string;
|
||||
withSearchParams?: Record<string, string | number>;
|
||||
} = {},
|
||||
) => {
|
||||
const url = new URL(baseUrl);
|
||||
|
||||
if (subdomain && subdomain.length > 0) {
|
||||
url.hostname = subdomain + '.' + url.hostname;
|
||||
}
|
||||
|
||||
if (withPathname) {
|
||||
url.pathname = withPathname;
|
||||
}
|
||||
|
||||
if (withSearchParams) {
|
||||
Object.entries(withSearchParams).forEach(([key, value]) => {
|
||||
if (isDefined(value)) {
|
||||
url.searchParams.set(key, value.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return url;
|
||||
};
|
||||
Reference in New Issue
Block a user