Merge remote-tracking branch 'origin/appbuilder/sprint-9' into feat/phone-input-mod

This commit is contained in:
Shaurya Sharma 2025-03-18 21:53:19 +05:30
commit 7dc87f8ba5
28 changed files with 118 additions and 85 deletions

View file

@ -52,7 +52,7 @@ jobs:
run: |
git submodule update --init --recursive
git submodule foreach --recursive '
git checkout ${{ env.BRANCH_NAME }} 2>/dev/null || git checkout modularisation/v3'
git checkout ${{ env.BRANCH_NAME }} 2>/dev/null || git checkout main'
- name: Set up Docker

View file

@ -50,7 +50,7 @@ jobs:
run: |
git submodule update --init --recursive
git submodule foreach --recursive '
git checkout ${{ env.BRANCH_NAME }} 2>/dev/null || git checkout modularisation/v3'
git checkout ${{ env.BRANCH_NAME }} 2>/dev/null || git checkout main'
- name: Set up Docker
uses: docker-practice/actions-setup-docker@master

4
.gitmodules vendored
View file

@ -1,8 +1,8 @@
[submodule "frontend/ee"]
path = frontend/ee
url = https://github.com/ToolJet/ee-frontend.git
branch = modularisation/v3
branch = main
[submodule "server/ee"]
path = server/ee
url = https://github.com/ToolJet/ee-server.git
branch = modularisation/v3
branch = main

View file

@ -10,7 +10,7 @@ RUN mkdir -p /app
WORKDIR /app
ARG CUSTOM_GITHUB_TOKEN
ARG BRANCH_NAME=modularisation/v3
ARG BRANCH_NAME=main
# Clone and checkout the frontend repository
RUN git config --global url."https://x-access-token:${CUSTOM_GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"

View file

@ -11,7 +11,7 @@ WORKDIR /app
# Set GitHub token and branch as build arguments
ARG CUSTOM_GITHUB_TOKEN
ARG BRANCH_NAME=modularisation/v3
ARG BRANCH_NAME=main
# Clone and checkout the frontend repository
RUN git config --global url."https://x-access-token:${CUSTOM_GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"
@ -21,7 +21,7 @@ RUN git config --global http.postBuffer 524288000
RUN git clone https://github.com/ToolJet/ToolJet.git .
# The branch name needs to be changed the branch with modularisation in CE repo
RUN git checkout modularisation/v3
RUN git checkout main
RUN git submodule update --init --recursive

@ -1 +1 @@
Subproject commit 6da03a83bd7a804f102b143351e59cc518898411
Subproject commit d93ee7e1318f044ef2327671b8b257648071453d

View file

@ -56,8 +56,8 @@ const TJDBCodeEditor = (props) => {
const handleOnChange = (value) => {
if (value === '') {
setErrorState(true);
setError('JSON cannot be empty');
setErrorState(false);
setError(null);
setCurrentValue(value);
return;
}
@ -150,7 +150,7 @@ const TJDBCodeEditor = (props) => {
className="cm-codehinter position-relative"
style={{
width: '100%',
height: isOpen ? '350px' : 'auto',
height: isOpen ? '350p' : 'auto',
}}
>
<div className={`cm-codehinter ${darkMode && 'cm-codehinter-dark-themed'}`}>
@ -178,7 +178,7 @@ const TJDBCodeEditor = (props) => {
<CodeMirror
value={currentValue}
placeholder={placeholder}
height={isOpen ? '350px' : '32px'}
height={isOpen ? '32px' : '32px'}
maxHeight={'350px'}
width="100%"
theme={theme}

View file

@ -7,7 +7,7 @@ import { getWorkspaceId, decodeEntities } from '@/_helpers/utils';
import { ButtonSolid } from '@/_ui/AppButton/AppButton';
import { useDataSources, useGlobalDataSources, useSampleDataSource } from '@/_stores/dataSourcesStore';
import { useDataQueriesActions } from '@/_stores/dataQueriesStore';
import { staticDataSources as staticDatasources } from '../constants';
import { defaultSources, staticDataSources as staticDatasources } from '../constants';
import { useQueryPanelActions } from '@/_stores/queryPanelStore';
import Search from '@/_ui/Icon/solidIcons/Search';
import { Tooltip } from 'react-tooltip';
@ -135,7 +135,7 @@ function DataSourceSelect({ isDisabled, selectRef, closePopup, workflowDataSourc
<div>
<DataSourceIcon source={source} height={16} />{' '}
<span data-cy={`ds-${source.name.toLowerCase()}`} className="ms-1 small" style={{ fontSize: '13px' }}>
{source.name}
{defaultSources[cleanWord(source.name)].name}
</span>
</div>
),
@ -178,6 +178,10 @@ function DataSourceSelect({ isDisabled, selectRef, closePopup, workflowDataSourc
}
};
function cleanWord(word) {
return word.replace(/default/g, '');
}
return (
<div>
<Select

View file

@ -7,6 +7,7 @@ import { getWorkspaceId } from '@/_helpers/utils';
import { navigate } from '@/AppBuilder/_utils/misc';
import queryString from 'query-string';
import { replaceEntityReferencesWithIds } from '../utils';
import _ from 'lodash';
const initialState = {
app: {},
@ -124,10 +125,14 @@ export const createAppSlice = (set, get) => ({
setComponentNameIdMapping('canvas');
setQueryMapping('canvas');
const isLicenseValid =
!_.get(license, 'featureAccess.licenseStatus.isExpired', true) &&
_.get(license, 'featureAccess.licenseStatus.isLicenseValid', false);
const appId = get().app.appId;
const filteredQueryParams = queryParams.filter(([key, value]) => {
if (!value) return false;
if (key === 'env' && !license.isLicenseValid()) return false;
if (key === 'env' && isLicenseValid) return false;
return true;
});

View file

@ -136,7 +136,6 @@ export const createEnvironmentsAndVersionsSlice = (set, get) => ({
updateVersionNameAction: async (appId, versionId, versionName, onSuccess, onFailure) => {
try {
await appVersionService.save(appId, versionId, { name: versionName });
console.log('happening');
set((state) => {
if (state.selectedVersion && state.selectedVersion.id === versionId) {
@ -177,7 +176,7 @@ export const createEnvironmentsAndVersionsSlice = (set, get) => ({
appVersionsLazyLoaded: false,
selectedEnvironment: response.editorEnvironment,
appVersionEnvironment: response.appVersionEnvironment,
environments: response.environments,
environments: response?.environments?.length ? response.environments : get().environments,
};
if (state.selectedVersion?.id === versionId) {
@ -241,7 +240,6 @@ export const createEnvironmentsAndVersionsSlice = (set, get) => ({
useStore.getState()?.license?.featureAccess
),
};
console.log({ environment, get: get().appVersionEnvironment });
const versionIsAvailableInEnvironment = environment?.priority <= get().currentAppVersionEnvironment?.priority;
if (!versionIsAvailableInEnvironment) {
@ -252,7 +250,7 @@ export const createEnvironmentsAndVersionsSlice = (set, get) => ({
});
selectedVersion = response.editorVersion;
const appVersionEnvironment = get().environments.find(
(environment) => environment.id === selectedVersion.current_environment_id
(environment) => environment.id === selectedVersion.currentEnvironmentId
);
//TODO: need to check if this is needed

View file

@ -628,7 +628,6 @@ button {
.inspector {
padding: 0px !important;
.form-control-plaintext {
padding: 0;
color: var(--slate12);

View file

@ -69,7 +69,7 @@ const useCEOnboardingStore = create(
createNewOnboardingApp: async () => {
const session = authenticationService.currentSessionValue;
const app = await appsService.createApp({ name: 'My App' });
const app = await appsService.createApp({ name: 'My App', type: 'front-end' });
const appId = app?.id;
utils.clearPageHistory();
const path = getSubpath()
@ -80,7 +80,7 @@ const useCEOnboardingStore = create(
setAccountCreated: (value) => set({ accountCreated: value }),
resumeSignupOnboarding: async (callBack = (resumeOnboardingSession = false) => { }) => {
resumeSignupOnboarding: async (callBack = (resumeOnboardingSession = false) => {}) => {
return callBack(false);
},
}))

@ -1 +1 @@
Subproject commit 4a7ef99d60c0b1c98558dafc73fbf72e05daf6cb
Subproject commit 1da04eef696345ce9f35d42af92e5d6de992cd85

View file

@ -20,7 +20,7 @@ export class AppEnvironmentService implements IAppEnvironmentService {
async init(editingVersionId: string, organizationId: string): Promise<IAppEnvironmentResponse> {
return await dbTransactionWrap(async (manager: EntityManager) => {
const editorVersion = await manager.findOne(AppVersion, {
select: ['id', 'name', 'appId'],
select: ['id', 'name', 'currentEnvironmentId', 'appId'],
where: { id: editingVersionId },
});
return await this.appEnvironmentUtilService.init(editorVersion, organizationId, false, manager);

View file

@ -119,7 +119,7 @@ export class AppEnvironmentUtilService implements IAppEnvironmentUtilService {
return {
name: result.appVersion_name,
id: result.appVersion_id,
currentEnvironmentId: result.appVersion_currentEnvironmentId,
currentEnvironmentId: result.appVersion_current_environment_id,
};
}

View file

@ -11,7 +11,7 @@ export interface IAuthUtilService {
[key: string]: any;
}>;
verifyToken(token: string): any;
getSSOConfigs(ssoType: SSOType.GOOGLE | SSOType.GIT | SSOType.OPENID): Promise<Partial<SSOConfigs>>;
getSSOConfigs(ssoType: SSOType.GOOGLE | SSOType.GIT): Promise<Partial<SSOConfigs>>;
getInstanceSSOConfigsOfType(ssoType: SSOType.GOOGLE | SSOType.GIT | SSOType.OPENID): Promise<DeepPartial<SSOConfigs>>;
syncUserAndGroups(
userResponse: UserResponse,

View file

@ -16,6 +16,9 @@ import { SSOResponseRepository } from '@modules/auth/oauth/repository/sso-respon
import { FeatureAbilityFactory } from './ability';
import { AbilityService } from '@modules/ability/service';
import { AbilityUtilService } from '@modules/ability/util.service';
import { GroupPermissionsRepository } from '@modules/group-permissions/repository';
import { SetupOrganizationsModule } from '@modules/setup-organization/module';
import { SSOConfigsRepository } from '@modules/login-configs/repository';
@Module({})
export class AuthModule {
@ -31,6 +34,7 @@ export class AuthModule {
const { GoogleOAuthService } = await import(`${importPath}/auth/oauth/util-services/google-oauth.service`);
const { OidcOAuthService } = await import(`${importPath}/auth/oauth/util-services/oidc-auth.service`);
const { LdapService } = await import(`${importPath}/auth/oauth/util-services/ldap.service`);
const { AppEnvironmentUtilService } = await import(`${importPath}/app-environments/util.service`);
return {
module: AuthModule,
@ -45,6 +49,7 @@ export class AuthModule {
await SessionModule.register(configs),
await OrganizationUsersModule.register(configs),
await LoginConfigsModule.register(configs),
await SetupOrganizationsModule.register(configs),
],
controllers: [AuthController, OauthController],
providers: [
@ -64,6 +69,9 @@ export class AuthModule {
FeatureAbilityFactory,
AbilityService,
AbilityUtilService,
AppEnvironmentUtilService,
GroupPermissionsRepository,
SSOConfigsRepository,
],
exports: [AuthUtilService],
};

View file

@ -36,6 +36,7 @@ import { OrganizationUsersRepository } from '@modules/organization-users/reposit
import { LicenseUserService } from '@modules/licensing/services/user.service';
import { OnboardingUtilService } from '@modules/onboarding/util.service';
import { SessionUtilService } from '@modules/session/util.service';
import { SetupOrganizationsUtilService } from '@modules/setup-organization/util.service';
const uuid = require('uuid');
@Injectable()
@ -56,7 +57,8 @@ export class OauthService implements IOAuthService {
protected readonly organizationUsersRepository: OrganizationUsersRepository,
protected readonly licenseUserService: LicenseUserService,
protected readonly onboardingUtilService: OnboardingUtilService,
protected readonly sessionUtilService: SessionUtilService
protected readonly sessionUtilService: SessionUtilService,
protected readonly setupOrganizationsUtilService: SetupOrganizationsUtilService
) {}
async signIn(
@ -172,21 +174,26 @@ export class OauthService implements IOAuthService {
// Not logging in to specific organization, creating new
const { name, slug } = generateNextNameAndSlug('My workspace');
defaultOrganization = await this.organizationRepository.createOne(name, slug, manager);
defaultOrganization = await this.setupOrganizationsUtilService.create(name, slug, null, manager);
userDetails = await this.userRepository.createOne(
userDetails = await this.userRepository.createOrUpdate(
{
firstName: userResponse.firstName,
lastName: userResponse.lastName,
email: userResponse.email,
userType: USER_ROLE.ADMIN,
defaultOrganizationId: defaultOrganization.id,
...getUserStatusAndSource(lifecycleEvents.USER_SSO_VERIFY, sso),
...getUserStatusAndSource(lifecycleEvents.USER_SSO_ACTIVATE, sso),
},
manager
);
await this.organizationUsersRepository.createOne(userDetails, defaultOrganization, false, manager);
await this.organizationUsersUtilService.attachUserGroup(
[USER_ROLE.ADMIN],
defaultOrganization.id,
userDetails.id,
manager
);
await this.organizationUsersRepository.createOne(userDetails, defaultOrganization, true, manager);
organizationDetails = defaultOrganization;
} else if (userDetails) {
// Finding organization to be loaded
@ -213,7 +220,7 @@ export class OauthService implements IOAuthService {
if (!isInviteRedirect) {
// no SSO login enabled organization available for user - creating new one
const { name, slug } = generateNextNameAndSlug('My workspace');
organizationDetails = await this.organizationRepository.createOne(name, slug, manager);
organizationDetails = await this.setupOrganizationsUtilService.create(name, slug, null, manager);
await this.userRepository.updateOne(
userDetails.id,
{ defaultOrganizationId: organizationDetails.id },

View file

@ -25,7 +25,6 @@ import { dbTransactionWrap } from 'src/helpers/database.helper';
import { DeepPartial } from 'typeorm';
import { SSOType } from '../../entities/sso_config.entity';
import { LicenseTermsService } from '../licensing/interfaces/IService';
import { LICENSE_FIELD } from '../licensing/constants';
import { GroupPermissionsUtilService } from '../group-permissions/util.service';
import { App } from '../../entities/app.entity';
import { In } from 'typeorm';
@ -38,7 +37,6 @@ import { RolesRepository } from '@modules/roles/repository';
import { GroupPermissions } from '@entities/group_permissions.entity';
import { ProfileUtilService } from '@modules/profile/util.service';
import { OrganizationUsersRepository } from '@modules/organization-users/repository';
import { InstanceSSOConfigMap } from '@modules/login-configs/types';
import { SessionUtilService } from '@modules/session/util.service';
import { OnboardingStatus } from '@modules/onboarding/constants';
import { IAuthUtilService } from './interfaces/IUtilService';
@ -152,11 +150,11 @@ export class AuthUtilService implements IAuthUtilService {
defaultOrganization = await this.organizationRepository.createOne(name, slug, manager);
}
const { source, status } = getUserStatusAndSource(lifecycleEvents.USER_SSO_VERIFY, sso);
const { source, status } = getUserStatusAndSource(lifecycleEvents.USER_SSO_ACTIVATE, sso);
/* Default password for sso-signed workspace user */
const password = uuid.v4();
user = await this.userRepository.createOne(
user = await this.userRepository.createOrUpdate(
{
firstName,
lastName,
@ -164,9 +162,8 @@ export class AuthUtilService implements IAuthUtilService {
source,
status,
password,
organizationId: organization.id,
role: USER_ROLE.END_USER,
defaultOrganizationId: defaultOrganization?.id,
defaultOrganizationId: defaultOrganization?.id || organization.id,
},
manager
);
@ -193,45 +190,32 @@ export class AuthUtilService implements IAuthUtilService {
// Setting up default organization
await this.organizationUsersRepository.createOne(user, defaultOrganization, true, manager);
}
await this.organizationUsersUtilService.attachUserGroup([USER_ROLE.END_USER], organization.id, user.id, manager); //localhost:8082/login/tooljets-workspace?redirectTo=/
return user;
}
async getSSOConfigs(ssoType: SSOType.GOOGLE | SSOType.GIT | SSOType.OPENID): Promise<Partial<SSOConfigs>> {
const ssoConfigs = await this.getInstanceSSOConfigsOfType(ssoType);
const oidcEnabled = await this.licenseTermsService.getLicenseTerms(LICENSE_FIELD.OIDC);
// Create a map from the ssoConfig object
const ssoConfigMap: InstanceSSOConfigMap = {
[ssoConfigs.sso]: {
enabled: ssoConfigs.enabled,
configs: ssoConfigs.configs,
},
};
async getSSOConfigs(ssoType: SSOType.GOOGLE | SSOType.GIT): Promise<Partial<SSOConfigs>> {
switch (ssoType) {
case SSOType.GOOGLE:
return {
enabled: ssoConfigMap.google.enabled || false,
configs: ssoConfigMap.google.configs || {},
enabled: !!this.configService.get<string>('SSO_GOOGLE_OAUTH2_CLIENT_ID'),
configs: { clientId: this.configService.get<string>('SSO_GOOGLE_OAUTH2_CLIENT_ID') },
};
case SSOType.GIT:
return {
enabled: ssoConfigMap.git.enabled || false,
configs: ssoConfigMap.git.configs || {},
};
case SSOType.OPENID:
return {
enabled: ssoConfigMap.openid.enabled && oidcEnabled,
configs: ssoConfigMap.openid.configs || {},
enabled: !!this.configService.get<string>('SSO_GIT_OAUTH2_CLIENT_ID'),
configs: {
clientId: this.configService.get<string>('SSO_GIT_OAUTH2_CLIENT_ID'),
clientSecret: this.configService.get<string>('SSO_GIT_OAUTH2_CLIENT_SECRET'),
hostName: this.configService.get<string>('SSO_GIT_OAUTH2_HOST'),
},
};
default:
return;
}
}
async getInstanceSSOConfigsOfType(
ssoType: SSOType.GOOGLE | SSOType.GIT | SSOType.OPENID
): Promise<DeepPartial<SSOConfigs>> {
async getInstanceSSOConfigsOfType(ssoType: SSOType.GOOGLE | SSOType.GIT): Promise<DeepPartial<SSOConfigs>> {
const instanceSettings = await this.instanceSettingsUtilService.getSettings([
INSTANCE_SYSTEM_SETTINGS.ALLOWED_DOMAINS,
INSTANCE_SYSTEM_SETTINGS.ENABLE_SIGNUP,

View file

@ -20,7 +20,6 @@ import { GroupUsers } from '@entities/group_users.entity';
import { USER_STATUS, WORKSPACE_USER_STATUS } from '@modules/users/constants/lifecycle';
import { User } from '@entities/user.entity';
import { DATA_BASE_CONSTRAINTS } from './constants/error';
@Injectable()
export class GroupPermissionsRepository extends Repository<GroupPermissions> {
constructor(private dataSource: DataSource) {

View file

@ -52,8 +52,9 @@ export class GroupPermissionsUtilService implements IGroupPermissionsUtilService
validateAddGroupUserOperation(group: GroupPermissions) {
if (!group || Object.keys(group)?.length === 0) throw new BadRequestException(ERROR_HANDLER.GROUP_NOT_EXIST);
if (group.type == GROUP_PERMISSIONS_TYPE.DEFAULT)
throw new MethodNotAllowedException(ERROR_HANDLER.ADD_GROUP_USER_DEFAULT_GROUP);
//commented out the default group check because for enable signup cases, user is added to default admin group
// if (group.type == GROUP_PERMISSIONS_TYPE.DEFAULT)
// throw new MethodNotAllowedException(ERROR_HANDLER.ADD_GROUP_USER_DEFAULT_GROUP);
}
validateDeleteGroupUserOperation(group: GroupPermissions, organizationId: string) {
@ -94,11 +95,14 @@ export class GroupPermissionsUtilService implements IGroupPermissionsUtilService
return await dbTransactionWrap(async (manager: EntityManager) => {
// Get Group details
const group = await this.groupPermissionsRepository.getGroup({
id,
organizationId,
...(!isLicenseValid ? noLicenseFilter : {}),
});
const group = await this.groupPermissionsRepository.getGroup(
{
id,
organizationId,
...(!isLicenseValid ? noLicenseFilter : {}),
},
manager
);
if (!isLicenseValid) {
if (group.name !== USER_ROLE.END_USER) {

View file

@ -45,11 +45,12 @@ export const INSTANCE_SETTINGS_ENCRYPTION_KEY = 'instance_settings';
export function getDefaultInstanceSettings() {
return {
[INSTANCE_SYSTEM_SETTINGS.ENABLE_SIGNUP]: process.env.SSO_DISABLE_SIGNUPS,
[INSTANCE_SYSTEM_SETTINGS.ENABLE_SIGNUP]: process.env.DISABLE_SIGNUPS === 'false' ? 'true' : 'false',
[INSTANCE_SYSTEM_SETTINGS.ENABLE_WORKSPACE_LOGIN_CONFIGURATION]: 'true',
[INSTANCE_USER_SETTINGS.ALLOW_PERSONAL_WORKSPACE]: 'true',
[INSTANCE_USER_SETTINGS.ENABLE_MULTIPLAYER_EDITING]: process.env.ENABLE_MULTIPLAYER_EDITING,
[INSTANCE_USER_SETTINGS.ENABLE_COMMENTS]: process.env.COMMENT_FEATURE_ENABLE,
[INSTANCE_USER_SETTINGS.ENABLE_MULTIPLAYER_EDITING]:
process.env.ENABLE_MULTIPLAYER_EDITING === 'true' ? 'true' : 'false',
[INSTANCE_USER_SETTINGS.ENABLE_COMMENTS]: process.env.COMMENT_FEATURE_ENABLE === 'true' ? 'true' : 'false',
[INSTANCE_SYSTEM_SETTINGS.SMTP_PORT]: process.env.SMTP_PORT,
[INSTANCE_SYSTEM_SETTINGS.SMTP_DOMAIN]: process.env.SMTP_DOMAIN,
[INSTANCE_SYSTEM_SETTINGS.SMTP_USERNAME]: process.env.SMTP_USERNAME,

View file

@ -575,7 +575,7 @@ export class OnboardingUtilService implements IOnboardingUtilService {
): Promise<User> {
return dbTransactionWrap(async (manager: EntityManager) => {
// Create the user
const user = await this.userRepository.createOne(userParams, manager);
const user = await this.userRepository.createOrUpdate(userParams, manager);
// Add the role for the user in the specified organization
await this.rolesUtilService.addUserRole(organizationId, { role, userId: user.id }, manager);

View file

@ -40,7 +40,6 @@ import { SessionUtilService } from '@modules/session/util.service';
import { SetupOrganizationsUtilService } from '@modules/setup-organization/util.service';
import { IOrganizationUsersUtilService } from './interfaces/IUtilService';
import { EventEmitter2 } from '@nestjs/event-emitter';
@Injectable()
export class OrganizationUsersUtilService implements IOrganizationUsersUtilService {
constructor(
@ -147,8 +146,18 @@ export class OrganizationUsersUtilService implements IOrganizationUsersUtilServi
try {
for (const addGroup of groups) {
const orgGroupPermission = await this.groupPermissionsRepository.getGroup(
{
organizationId: organizationId,
name: addGroup,
},
manager
);
if (!orgGroupPermission) {
throw new BadRequestException(`${addGroup} group does not exist for current organization`);
}
await this.groupPermissionsUtilService.addUsersToGroup(
{ allowRoleChange: false, userIds: [userId], groupId: addGroup },
{ allowRoleChange: false, userIds: [userId], groupId: orgGroupPermission.id },
organizationId,
manager
);
@ -223,7 +232,7 @@ export class OrganizationUsersUtilService implements IOrganizationUsersUtilServi
return await dbTransactionWrap(async (manager: EntityManager) => {
const userType = (await manager.count(User)) === 0 ? USER_TYPE.INSTANCE : USER_TYPE.WORKSPACE;
return await this.userRepository.createOne(
return await this.userRepository.createOrUpdate(
{
email,
firstName,

View file

@ -9,12 +9,13 @@ export class OrganizationsModule {
const { OrganizationsService } = await import(`${importPath}/organizations/service`);
const { OrganizationsController } = await import(`${importPath}/organizations/controller`);
const { FeatureAbilityFactory } = await import(`${importPath}/organizations/ability`);
const { AppEnvironmentUtilService } = await import(`${importPath}/app-environments/util.service`);
return {
module: OrganizationsModule,
imports: [await InstanceSettingsModule.register(configs)],
controllers: [OrganizationsController],
providers: [OrganizationsService, OrganizationRepository, FeatureAbilityFactory],
providers: [OrganizationsService, OrganizationRepository, FeatureAbilityFactory, AppEnvironmentUtilService],
};
}
}

View file

@ -9,7 +9,7 @@ import { RolesModule } from '@modules/roles/module';
import { ThemesModule } from '@modules/organization-themes/module';
import { SessionModule } from '@modules/session/module';
import { InstanceSettingsModule } from '@modules/instance-settings/module';
import { TooljetDbTableOperationsService } from '@modules/tooljet-db/services/tooljet-db-table-operations.service';
import { TooljetDbModule } from '@modules/tooljet-db/module';
export class SetupOrganizationsModule {
static async register(configs?: { IS_GET_CONTEXT: boolean }): Promise<DynamicModule> {
@ -29,6 +29,7 @@ export class SetupOrganizationsModule {
await ThemesModule.register(configs),
await SessionModule.register(configs),
await InstanceSettingsModule.register(configs),
await TooljetDbModule.register(configs),
],
controllers: [SetupOrganizationsController],
providers: [
@ -37,7 +38,7 @@ export class SetupOrganizationsModule {
OrganizationRepository,
OrganizationUsersRepository,
FeatureAbilityFactory,
TooljetDbTableOperationsService,
TooljetDbModule,
],
exports: [SetupOrganizationsUtilService],
};

View file

@ -86,9 +86,18 @@ export class UserRepository extends Repository<User> {
};
}
createOne(user: Partial<User>, manager?: EntityManager): Promise<User> {
return dbTransactionWrap((manager: EntityManager) => {
return manager.save(manager.create(User, user));
async createOrUpdate(user: Partial<User>, manager?: EntityManager): Promise<User> {
//not using upsert because hook is not supported for password digest
return dbTransactionWrap(async (manager: EntityManager) => {
const existingUser = await manager.findOne(User, { where: { email: user.email } });
if (existingUser) {
Object.assign(existingUser, user);
return manager.save(User, existingUser);
} else {
const newUser = manager.create(User, user);
return manager.save(User, newUser);
}
}, manager || this.manager);
}

View file

@ -42,7 +42,7 @@ export class VersionUtilService implements IVersionUtilService {
async updateVersion(appVersion: AppVersion, appVersionUpdateDto: AppVersionUpdateDto) {
const editableParams = {};
const { globalSettings, homePageId, pageSettings } = appVersion;
const { globalSettings, homePageId, pageSettings, name } = appVersion;
if (appVersionUpdateDto?.homePageId && homePageId !== appVersionUpdateDto.homePageId) {
editableParams['homePageId'] = appVersionUpdateDto.homePageId;
@ -65,6 +65,10 @@ export class VersionUtilService implements IVersionUtilService {
editableParams['showViewerNavigation'] = appVersionUpdateDto.showViewerNavigation;
}
if (appVersionUpdateDto?.name && name !== appVersionUpdateDto.name) {
editableParams['name'] = appVersionUpdateDto.name;
}
await this.versionRepository.update(appVersion.id, editableParams);
return;
}