diff --git a/app/client/src/AppRouter.tsx b/app/client/src/AppRouter.tsx index 44eab475d2..138d52cfb9 100644 --- a/app/client/src/AppRouter.tsx +++ b/app/client/src/AppRouter.tsx @@ -60,6 +60,7 @@ import TemplatesListLoader from "pages/Templates/loader"; import { fetchFeatureFlagsInit } from "actions/userActions"; import FeatureFlags from "entities/FeatureFlags"; import WDSPage from "components/wds/Showcase"; +import { getCurrentTenant } from "@appsmith/actions/tenantActions"; const SentryRoute = Sentry.withSentryRouting(Route); @@ -83,12 +84,13 @@ function AppRouter(props: { safeCrash: boolean; getCurrentUser: () => void; getFeatureFlags: () => void; + getCurrentTenant: () => void; currentTheme: Theme; safeCrashCode?: ERROR_CODES; featureFlags: FeatureFlags; setTheme: (theme: ThemeMode) => void; }) { - const { getCurrentUser, getFeatureFlags } = props; + const { getCurrentTenant, getCurrentUser, getFeatureFlags } = props; useEffect(() => { AnalyticsUtil.logEvent("ROUTE_CHANGE", { path: window.location.pathname }); const stopListener = history.listen((location: any) => { @@ -97,6 +99,7 @@ function AppRouter(props: { }); getCurrentUser(); getFeatureFlags(); + getCurrentTenant(); return stopListener; }, []); @@ -192,6 +195,7 @@ const mapDispatchToProps = (dispatch: any) => ({ }, getCurrentUser: () => dispatch(getCurrentUser()), getFeatureFlags: () => dispatch(fetchFeatureFlagsInit()), + getCurrentTenant: () => dispatch(getCurrentTenant()), }); export default connect(mapStateToProps, mapDispatchToProps)(AppRouter); diff --git a/app/client/src/ce/actions/tenantActions.ts b/app/client/src/ce/actions/tenantActions.ts new file mode 100644 index 0000000000..7622ab4de4 --- /dev/null +++ b/app/client/src/ce/actions/tenantActions.ts @@ -0,0 +1,5 @@ +import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants"; + +export const getCurrentTenant = () => ({ + type: ReduxActionTypes.FETCH_CURRENT_TENANT_CONFIG, +}); diff --git a/app/client/src/ce/api/TenantApi.ts b/app/client/src/ce/api/TenantApi.ts new file mode 100644 index 0000000000..8e31c42a89 --- /dev/null +++ b/app/client/src/ce/api/TenantApi.ts @@ -0,0 +1,21 @@ +import { AxiosPromise } from "axios"; +import Api from "api/Api"; +import { ApiResponse } from "api/ApiResponses"; + +export type FetchCurrentTenantConfigResponse = ApiResponse<{ + userPermissions: string[]; + tenantConfiguration: Record; + new: boolean; +}>; + +export class TenantApi extends Api { + static tenantsUrl = "v1/tenants"; + + static fetchCurrentTenantConfig(): AxiosPromise< + FetchCurrentTenantConfigResponse + > { + return Api.get(TenantApi.tenantsUrl + "/current"); + } +} + +export default TenantApi; diff --git a/app/client/src/ce/constants/ReduxActionConstants.tsx b/app/client/src/ce/constants/ReduxActionConstants.tsx index bbe4464c08..35f034a9e1 100644 --- a/app/client/src/ce/constants/ReduxActionConstants.tsx +++ b/app/client/src/ce/constants/ReduxActionConstants.tsx @@ -670,6 +670,8 @@ export const ReduxActionTypes = { INIT_TRIGGER_VALUES: "INIT_TRIGGER_VALUES", FETCH_TRIGGER_VALUES_INIT: "FETCH_TRIGGER_VALUES_INIT", FETCH_TRIGGER_VALUES_SUCCESS: "FETCH_TRIGGER_VALUES_SUCCESS", + FETCH_CURRENT_TENANT_CONFIG: "FETCH_CURRENT_TENANT_CONFIG", + FETCH_CURRENT_TENANT_CONFIG_SUCCESS: "FETCH_CURRENT_TENANT_CONFIG_SUCCESS", }; export type ReduxActionType = typeof ReduxActionTypes[keyof typeof ReduxActionTypes]; @@ -840,6 +842,7 @@ export const ReduxActionErrorTypes = { GET_TEMPLATE_ERROR: "GET_TEMPLATE_ERROR", GET_TEMPLATE_FILTERS_ERROR: "GET_TEMPLATE_FILTERS_ERROR", UPDATE_CUSTOM_SLUG_ERROR: "UPDATE_CUSTOM_SLUG_ERROR", + FETCH_CURRENT_TENANT_CONFIG_ERROR: "FETCH_CURRENT_TENANT_CONFIG_ERROR", }; export const ReduxFormActionTypes = { diff --git a/app/client/src/ce/reducers/index.tsx b/app/client/src/ce/reducers/index.tsx index c69b1a8642..d261d586bd 100644 --- a/app/client/src/ce/reducers/index.tsx +++ b/app/client/src/ce/reducers/index.tsx @@ -61,6 +61,9 @@ import SettingsReducer, { import { GuidedTourState } from "reducers/uiReducers/guidedTourReducer"; import { TriggerValuesEvaluationState } from "reducers/evaluationReducers/triggerReducer"; import { CanvasWidgetStructure } from "widgets/constants"; +import tenantReducer, { + TenantReduxState, +} from "@appsmith/reducers/tenantReducer"; export const reducerObject = { entities: entityReducer, @@ -68,6 +71,7 @@ export const reducerObject = { evaluations: evaluationsReducer, form: formReducer, settings: SettingsReducer, + tenant: tenantReducer, }; export interface AppState { @@ -137,4 +141,5 @@ export interface AppState { [key: string]: any; }; settings: SettingsReduxState; + tenant: TenantReduxState; } diff --git a/app/client/src/ce/reducers/tenantReducer.ts b/app/client/src/ce/reducers/tenantReducer.ts new file mode 100644 index 0000000000..a025ce2d3a --- /dev/null +++ b/app/client/src/ce/reducers/tenantReducer.ts @@ -0,0 +1,35 @@ +import { + ReduxAction, + ReduxActionErrorTypes, + ReduxActionTypes, +} from "@appsmith/constants/ReduxActionConstants"; +import { createReducer } from "utils/ReducerUtils"; + +export interface TenantReduxState { + userPermissions: string[]; + tenantConfiguration: Record; + new: boolean; +} + +export const initialState: TenantReduxState = { + userPermissions: [], + tenantConfiguration: {}, + new: false, +}; + +export const handlers = { + [ReduxActionTypes.FETCH_CURRENT_TENANT_CONFIG_SUCCESS]: ( + state: TenantReduxState, + action: ReduxAction, + ) => ({ + ...state, + ...action.payload, + }), + [ReduxActionErrorTypes.FETCH_CURRENT_TENANT_CONFIG_ERROR]: ( + state: TenantReduxState, + ) => ({ + ...state, + }), +}; + +export default createReducer(initialState, handlers); diff --git a/app/client/src/ce/sagas/index.tsx b/app/client/src/ce/sagas/index.tsx index 1862d45a0c..b734be67ee 100644 --- a/app/client/src/ce/sagas/index.tsx +++ b/app/client/src/ce/sagas/index.tsx @@ -39,6 +39,7 @@ import appThemingSaga from "sagas/AppThemingSaga"; import formEvaluationChangeListener from "sagas/FormEvaluationSaga"; import SuperUserSagas from "@appsmith/sagas/SuperUserSagas"; import PageVisibilitySaga from "sagas/PageVisibilitySagas"; +import tenantSagas from "@appsmith/sagas/tenantSagas"; export const sagas = [ initSagas, @@ -82,4 +83,5 @@ export const sagas = [ SuperUserSagas, appThemingSaga, PageVisibilitySaga, + tenantSagas, ]; diff --git a/app/client/src/ce/sagas/tenantSagas.tsx b/app/client/src/ce/sagas/tenantSagas.tsx new file mode 100644 index 0000000000..015e195c82 --- /dev/null +++ b/app/client/src/ce/sagas/tenantSagas.tsx @@ -0,0 +1,31 @@ +import TenantApi from "@appsmith/api/TenantApi"; +import { + ReduxActionErrorTypes, + ReduxActionTypes, +} from "@appsmith/constants/ReduxActionConstants"; +import { ApiResponse } from "api/ApiResponses"; +import { call, put } from "redux-saga/effects"; +import { validateResponse } from "sagas/ErrorSagas"; + +export function* fetchCurrentTenantConfigSaga() { + try { + const response: ApiResponse = yield call( + TenantApi.fetchCurrentTenantConfig, + ); + const isValidResponse: boolean = yield validateResponse(response); + + if (isValidResponse) { + yield put({ + type: ReduxActionTypes.FETCH_CURRENT_TENANT_CONFIG_SUCCESS, + payload: response.data, + }); + } + } catch (error) { + yield put({ + type: ReduxActionErrorTypes.FETCH_CURRENT_TENANT_CONFIG_ERROR, + payload: { + error, + }, + }); + } +} diff --git a/app/client/src/ce/selectors/tenantSelectors.tsx b/app/client/src/ce/selectors/tenantSelectors.tsx new file mode 100644 index 0000000000..687595572f --- /dev/null +++ b/app/client/src/ce/selectors/tenantSelectors.tsx @@ -0,0 +1,5 @@ +import { AppState } from "@appsmith/reducers"; + +export const getTenantPermissions = (state: AppState) => { + return state.tenant.userPermissions; +}; diff --git a/app/client/src/ee/actions/tenantActions.ts b/app/client/src/ee/actions/tenantActions.ts new file mode 100644 index 0000000000..e5fb6026b7 --- /dev/null +++ b/app/client/src/ee/actions/tenantActions.ts @@ -0,0 +1 @@ +export * from "ce/actions/tenantActions"; diff --git a/app/client/src/ee/api/TenantApi.ts b/app/client/src/ee/api/TenantApi.ts new file mode 100644 index 0000000000..5d2f188cd3 --- /dev/null +++ b/app/client/src/ee/api/TenantApi.ts @@ -0,0 +1,6 @@ +export * from "ce/api/TenantApi"; +import { TenantApi as CE_TenantApi } from "ce/api/TenantApi"; + +class TenantApi extends CE_TenantApi {} + +export default TenantApi; diff --git a/app/client/src/ee/reducers/tenantReducer.ts b/app/client/src/ee/reducers/tenantReducer.ts new file mode 100644 index 0000000000..a5ab731605 --- /dev/null +++ b/app/client/src/ee/reducers/tenantReducer.ts @@ -0,0 +1,5 @@ +export * from "ce/reducers/tenantReducer"; +import { handlers, initialState } from "ce/reducers/tenantReducer"; +import { createReducer } from "utils/ReducerUtils"; + +export default createReducer(initialState, handlers); diff --git a/app/client/src/ee/sagas/tenantSagas.tsx b/app/client/src/ee/sagas/tenantSagas.tsx new file mode 100644 index 0000000000..0748cb28ea --- /dev/null +++ b/app/client/src/ee/sagas/tenantSagas.tsx @@ -0,0 +1,13 @@ +export * from "ce/sagas/tenantSagas"; +import { ReduxActionTypes } from "ce/constants/ReduxActionConstants"; +import { fetchCurrentTenantConfigSaga } from "ce/sagas/tenantSagas"; +import { all, takeLatest } from "redux-saga/effects"; + +export default function* tenantSagas() { + yield all([ + takeLatest( + ReduxActionTypes.FETCH_CURRENT_TENANT_CONFIG, + fetchCurrentTenantConfigSaga, + ), + ]); +} diff --git a/app/client/src/ee/selectors/tenantSelectors.tsx b/app/client/src/ee/selectors/tenantSelectors.tsx new file mode 100644 index 0000000000..22a80dbfc9 --- /dev/null +++ b/app/client/src/ee/selectors/tenantSelectors.tsx @@ -0,0 +1 @@ +export * from "ce/selectors/tenantSelectors";