AdminPage.tsx 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. import React, { ReactNode } from 'react';
  2. import { isClient, objectIdUtils } from '@growi/core';
  3. import {
  4. NextPage, GetServerSideProps, GetServerSidePropsContext,
  5. } from 'next';
  6. import { useTranslation } from 'next-i18next';
  7. import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
  8. import dynamic from 'next/dynamic';
  9. import { useRouter } from 'next/router';
  10. import { Container, Provider } from 'unstated';
  11. import AdminAppContainer from '~/client/services/AdminAppContainer';
  12. import AdminBasicSecurityContainer from '~/client/services/AdminBasicSecurityContainer';
  13. import AdminCustomizeContainer from '~/client/services/AdminCustomizeContainer';
  14. import AdminExternalAccountsContainer from '~/client/services/AdminExternalAccountsContainer';
  15. import AdminGeneralSecurityContainer from '~/client/services/AdminGeneralSecurityContainer';
  16. import AdminGitHubSecurityContainer from '~/client/services/AdminGitHubSecurityContainer';
  17. import AdminGoogleSecurityContainer from '~/client/services/AdminGoogleSecurityContainer';
  18. import AdminHomeContainer from '~/client/services/AdminHomeContainer';
  19. import AdminImportContainer from '~/client/services/AdminImportContainer';
  20. import AdminLdapSecurityContainer from '~/client/services/AdminLdapSecurityContainer';
  21. import AdminLocalSecurityContainer from '~/client/services/AdminLocalSecurityContainer';
  22. import AdminMarkDownContainer from '~/client/services/AdminMarkDownContainer';
  23. import AdminNotificationContainer from '~/client/services/AdminNotificationContainer';
  24. import AdminOidcSecurityContainer from '~/client/services/AdminOidcSecurityContainer';
  25. import AdminSamlSecurityContainer from '~/client/services/AdminSamlSecurityContainer';
  26. import AdminSlackIntegrationLegacyContainer from '~/client/services/AdminSlackIntegrationLegacyContainer';
  27. import AdminTwitterSecurityContainer from '~/client/services/AdminTwitterSecurityContainer';
  28. import AdminUsersContainer from '~/client/services/AdminUsersContainer';
  29. import { SupportedActionType } from '~/interfaces/activity';
  30. import { CrowiRequest } from '~/interfaces/crowi-request';
  31. import {
  32. CommonProps, getServerSideCommonProps, getNextI18NextConfig, useCustomTitle,
  33. } from '~/pages/utils/commons';
  34. // import PluginUtils from '~/server/plugins/plugin-utils';
  35. import ConfigLoader from '~/server/service/config-loader';
  36. import {
  37. useCurrentUser, /* useSearchServiceConfigured, */ useIsAclEnabled, useIsMailerSetup, useIsSearchServiceReachable, useSiteUrl,
  38. useAuditLogEnabled, useAuditLogAvailableActions, useIsSearchPage, useCustomizeTitle,
  39. } from '~/stores/context';
  40. import { useIsMaintenanceMode } from '~/stores/maintenanceMode';
  41. // import { useEnvVars } from '~/stores/admin-context';
  42. // const AdminHome = dynamic(() => import('./AdminHome/AdminHome'), { ssr: false });
  43. // const AppSettingsPageContents = dynamic(() => import('./App/AppSettingsPageContents'), { ssr: false });
  44. // const SecurityManagement = dynamic(() => import('./Security/SecurityManagement'), { ssr: false });
  45. // const MarkDownSettingContents = dynamic(() => import('./MarkdownSetting/MarkDownSettingContents'), { ssr: false });
  46. // const CustomizeSettingContents = dynamic(() => import('./Customize/Customize'), { ssr: false });
  47. // const DataImportPageContents = dynamic(() => import('./ImportData/ImportDataPageContents'), { ssr: false });
  48. // const ExportArchiveDataPage = dynamic(() => import('./ExportArchiveDataPage'), { ssr: false });
  49. // const NotificationSetting = dynamic(() => import('./Notification/NotificationSetting'), { ssr: false });
  50. // const ManageGlobalNotification = dynamic(() => import('./Notification/ManageGlobalNotification'), { ssr: false });
  51. // const SlackIntegration = dynamic(() => import('./SlackIntegration/SlackIntegration'), { ssr: false });
  52. // const LegacySlackIntegration = dynamic(() => import('./LegacySlackIntegration/LegacySlackIntegration'), { ssr: false });
  53. // const UserManagement = dynamic(() => import('./UserManagement'), { ssr: false });
  54. // const ManageExternalAccount = dynamic(() => import('./ManageExternalAccount'), { ssr: false });
  55. // const ElasticsearchManagement = dynamic(() => import('./ElasticsearchManagement/ElasticsearchManagement'), { ssr: false });
  56. // const UserGroupDetailPage = dynamic(() => import('./UserGroupDetail/UserGroupDetailPage'), { ssr: false });
  57. const AdminLayout = dynamic(() => import('../Layout/AdminLayout'), { ssr: false });
  58. // // named export
  59. // const UserGroupPage = dynamic(() => import('./UserGroup/UserGroupPage').then(mod => mod.UserGroupPage), { ssr: false });
  60. // const AuditLogManagement = dynamic(() => import('./AuditLogManagement').then(mod => mod.AuditLogManagement), { ssr: false });
  61. // const pluginUtils = new PluginUtils();
  62. type Props = CommonProps & {
  63. currentUser: any,
  64. title: string
  65. component: ReactNode,
  66. nodeVersion: string,
  67. npmVersion: string,
  68. yarnVersion: string,
  69. installedPlugins: any,
  70. envVars: any,
  71. isAclEnabled: boolean,
  72. isSearchServiceConfigured: boolean,
  73. isSearchServiceReachable: boolean,
  74. isMailerSetup: boolean,
  75. auditLogEnabled: boolean,
  76. auditLogAvailableActions: SupportedActionType[],
  77. customizeTitle: string,
  78. siteUrl: string,
  79. };
  80. const AdminPage: NextPage<Props> = (props: Props) => {
  81. console.log({ adminPageProps: props });
  82. // const { t } = useTranslation('admin');
  83. // const router = useRouter();
  84. // const { path } = router.query;
  85. // const pagePathKeys: string[] = Array.isArray(path) ? path : ['home'];
  86. /*
  87. * Set userGroupId as a adminPagesMap key
  88. * eg) In case that url is `/user-group-detail/62e8388a9a649bea5e703ef7`, userGroupId will be 62e8388a9a649bea5e703ef7
  89. */
  90. // let userGroupId;
  91. // const [firstPath, secondPath] = pagePathKeys;
  92. // if (firstPath === 'user-group-detail') {
  93. // userGroupId = objectIdUtils.isValidObjectId(secondPath) ? secondPath : undefined;
  94. // }
  95. // TODO: refactoring adminPagesMap => https://redmine.weseek.co.jp/issues/102694
  96. // const adminPagesMap = {
  97. // home: {
  98. // title: t('wiki_management_home_page'),
  99. // component: <AdminHome
  100. // nodeVersion={props.nodeVersion}
  101. // npmVersion={props.npmVersion}
  102. // yarnVersion={props.yarnVersion}
  103. // installedPlugins={props.installedPlugins}
  104. // />,
  105. // },
  106. // app: {
  107. // title: t('commons:headers.app_settings'),
  108. // component: <AppSettingsPageContents />,
  109. // },
  110. // security: {
  111. // title: t('security_settings.security_settings'),
  112. // component: <SecurityManagement />,
  113. // },
  114. // markdown: {
  115. // title: t('markdown_settings.markdown_settings'),
  116. // component: <MarkDownSettingContents />,
  117. // },
  118. // customize: {
  119. // title: t('customize_settings.customize_settings'),
  120. // component: <CustomizeSettingContents />,
  121. // },
  122. // importer: {
  123. // title: t('importer_management.import_data'),
  124. // component: <DataImportPageContents />,
  125. // },
  126. // export: {
  127. // title: t('export_archive_data'),
  128. // component: <ExportArchiveDataPage />,
  129. // },
  130. // notification: {
  131. // title: t('external_notification.external_notification'),
  132. // component: <NotificationSetting />,
  133. // },
  134. // 'global-notification': {
  135. // new: {
  136. // title: t('external_notification.external_notification'),
  137. // component: <ManageGlobalNotification />,
  138. // },
  139. // },
  140. // 'slack-integration': {
  141. // title: t('slack_integration.slack_integration'),
  142. // component: <SlackIntegration />,
  143. // },
  144. // 'slack-integration-legacy': {
  145. // title: t('slack_integration_legacy.slack_integration_legacy'),
  146. // component: <LegacySlackIntegration />,
  147. // },
  148. // users: {
  149. // title: t('user_management.user_management'),
  150. // component: <UserManagement />,
  151. // 'external-accounts': {
  152. // title: t('user_management.external_account'),
  153. // component: <ManageExternalAccount />,
  154. // },
  155. // },
  156. // 'user-groups': {
  157. // title: t('user_group_management.user_group_management'),
  158. // component: <UserGroupPage />,
  159. // },
  160. // 'user-group-detail': {
  161. // [userGroupId]: {
  162. // title: t('user_group_management.user_group_management'),
  163. // component: <UserGroupDetailPage userGroupId={userGroupId} />,
  164. // },
  165. // },
  166. // search: {
  167. // title: t('full_text_search_management.full_text_search_management'),
  168. // component: <ElasticsearchManagement />,
  169. // },
  170. // 'audit-log': {
  171. // title: t('audit_log_management.audit_log'),
  172. // component: <AuditLogManagement />,
  173. // },
  174. // };
  175. // const getTargetPageToRender = (pagesMap, keys): {title: string, component: JSX.Element} => {
  176. // return keys.reduce((pagesMap, key) => {
  177. // return pagesMap[key];
  178. // }, pagesMap);
  179. // };
  180. // const targetPage = getTargetPageToRender(adminPagesMap, pagePathKeys);
  181. useIsSearchPage(false);
  182. useCurrentUser(props.currentUser != null ? JSON.parse(props.currentUser) : null);
  183. useIsMailerSetup(props.isMailerSetup);
  184. useIsMaintenanceMode(props.isMaintenanceMode);
  185. // useSearchServiceConfigured(props.isSearchServiceConfigured);
  186. useIsSearchServiceReachable(props.isSearchServiceReachable);
  187. useIsAclEnabled(props.isAclEnabled);
  188. useSiteUrl(props.siteUrl);
  189. // useEnvVars(props.envVars);
  190. useAuditLogEnabled(props.auditLogEnabled);
  191. useAuditLogAvailableActions(props.auditLogAvailableActions);
  192. useCustomizeTitle(props.customizeTitle);
  193. const injectableContainers: Container<any>[] = [];
  194. if (isClient()) {
  195. // Create unstated container instances (except Security)
  196. const adminAppContainer = new AdminAppContainer();
  197. const adminImportContainer = new AdminImportContainer();
  198. const adminHomeContainer = new AdminHomeContainer();
  199. const adminCustomizeContainer = new AdminCustomizeContainer();
  200. const adminUsersContainer = new AdminUsersContainer();
  201. const adminExternalAccountsContainer = new AdminExternalAccountsContainer();
  202. const adminNotificationContainer = new AdminNotificationContainer();
  203. const adminSlackIntegrationLegacyContainer = new AdminSlackIntegrationLegacyContainer();
  204. const adminMarkDownContainer = new AdminMarkDownContainer();
  205. injectableContainers.push(
  206. adminAppContainer,
  207. adminImportContainer,
  208. adminHomeContainer,
  209. adminCustomizeContainer,
  210. adminUsersContainer,
  211. adminExternalAccountsContainer,
  212. adminNotificationContainer,
  213. adminSlackIntegrationLegacyContainer,
  214. adminMarkDownContainer,
  215. );
  216. }
  217. const adminSecurityContainers: Container<any>[] = [];
  218. if (isClient()) {
  219. const adminSecuritySettingElem = document.getElementById('admin-security-setting');
  220. if (adminSecuritySettingElem != null) {
  221. // Create unstated container instances (Security)
  222. const adminGeneralSecurityContainer = new AdminGeneralSecurityContainer();
  223. const adminLocalSecurityContainer = new AdminLocalSecurityContainer();
  224. const adminLdapSecurityContainer = new AdminLdapSecurityContainer();
  225. const adminSamlSecurityContainer = new AdminSamlSecurityContainer();
  226. const adminOidcSecurityContainer = new AdminOidcSecurityContainer();
  227. const adminBasicSecurityContainer = new AdminBasicSecurityContainer();
  228. const adminGoogleSecurityContainer = new AdminGoogleSecurityContainer();
  229. const adminGitHubSecurityContainer = new AdminGitHubSecurityContainer();
  230. const adminTwitterSecurityContainer = new AdminTwitterSecurityContainer();
  231. adminSecurityContainers.push(
  232. adminGeneralSecurityContainer,
  233. adminLocalSecurityContainer,
  234. adminLdapSecurityContainer,
  235. adminSamlSecurityContainer,
  236. adminOidcSecurityContainer,
  237. adminBasicSecurityContainer,
  238. adminGoogleSecurityContainer,
  239. adminGitHubSecurityContainer,
  240. adminTwitterSecurityContainer,
  241. );
  242. }
  243. }
  244. return (
  245. <Provider inject={[...injectableContainers, ...adminSecurityContainers]}>
  246. <AdminLayout title={useCustomTitle(props, props.title)} componentTitle={props.title} >
  247. {props.component}
  248. </AdminLayout>
  249. </Provider>
  250. );
  251. };
  252. // async function injectServerConfigurations(context: GetServerSidePropsContext, props: Props): Promise<void> {
  253. // const req: CrowiRequest = context.req as CrowiRequest;
  254. // const { crowi } = req;
  255. // const {
  256. // appService, mailService, aclService, searchService, activityService,
  257. // } = crowi;
  258. // props.siteUrl = appService.getSiteUrl();
  259. // props.nodeVersion = crowi.runtimeVersions.versions.node ? crowi.runtimeVersions.versions.node.version.version : null;
  260. // props.npmVersion = crowi.runtimeVersions.versions.npm ? crowi.runtimeVersions.versions.npm.version.version : null;
  261. // props.yarnVersion = crowi.runtimeVersions.versions.yarn ? crowi.runtimeVersions.versions.yarn.version.version : null;
  262. // props.installedPlugins = pluginUtils.listPlugins();
  263. // props.envVars = await ConfigLoader.getEnvVarsForDisplay(true);
  264. // props.isAclEnabled = aclService.isAclEnabled();
  265. // props.isSearchServiceConfigured = searchService.isConfigured;
  266. // props.isSearchServiceReachable = searchService.isReachable;
  267. // props.isMailerSetup = mailService.isMailerSetup;
  268. // props.auditLogEnabled = crowi.configManager.getConfig('crowi', 'app:auditLogEnabled');
  269. // props.auditLogAvailableActions = activityService.getAvailableActions(false);
  270. // props.customizeTitle = crowi.configManager.getConfig('crowi', 'customize:title');
  271. // }
  272. // /**
  273. // * for Server Side Translations
  274. // * @param context
  275. // * @param props
  276. // * @param namespacesRequired
  277. // */
  278. // async function injectNextI18NextConfigurations(context: GetServerSidePropsContext, props: Props, namespacesRequired?: string[] | undefined): Promise<void> {
  279. // // preload all languages because of language lists in user setting
  280. // const nextI18NextConfig = await getNextI18NextConfig(serverSideTranslations, context, namespacesRequired, true);
  281. // props._nextI18Next = nextI18NextConfig._nextI18Next;
  282. // }
  283. // export const getServerSideProps: GetServerSideProps = async(context: GetServerSidePropsContext) => {
  284. // const req: CrowiRequest = context.req as CrowiRequest;
  285. // const { user } = req;
  286. // const result = await getServerSideCommonProps(context);
  287. // // check for presence
  288. // // see: https://github.com/vercel/next.js/issues/19271#issuecomment-730006862
  289. // if (!('props' in result)) {
  290. // throw new Error('invalid getSSP result');
  291. // }
  292. // const props: Props = result.props as Props;
  293. // if (user != null) {
  294. // // props.currentUser = JSON.stringify(user.toObject());
  295. // props.currentUser = JSON.stringify(user);
  296. // }
  297. // injectServerConfigurations(context, props);
  298. // await injectNextI18NextConfigurations(context, props, ['admin', 'commons']);
  299. // return {
  300. // props,
  301. // };
  302. // };
  303. export default AdminPage;