diff --git a/apps/app/package.json b/apps/app/package.json
index c35b8556daa..0f67168c0c5 100644
--- a/apps/app/package.json
+++ b/apps/app/package.json
@@ -1,6 +1,6 @@
{
"name": "@growi/app",
- "version": "7.3.6",
+ "version": "7.3.7-RC.0",
"license": "MIT",
"private": "true",
"scripts": {
diff --git a/apps/app/src/client/components/Admin/AdminHome/AdminHome.jsx b/apps/app/src/client/components/Admin/AdminHome/AdminHome.jsx
index 5e735a5a930..fc43abd8c32 100644
--- a/apps/app/src/client/components/Admin/AdminHome/AdminHome.jsx
+++ b/apps/app/src/client/components/Admin/AdminHome/AdminHome.jsx
@@ -17,6 +17,7 @@ import { withUnstatedContainers } from '../../UnstatedUtils';
import { EnvVarsTable } from './EnvVarsTable';
import SystemInfomationTable from './SystemInfomationTable';
+
const logger = loggerFactory('growi:admin');
const AdminHome = (props) => {
@@ -59,7 +60,7 @@ const AdminHome = (props) => {
)
}
{
- // Alert message will be displayed in case that V5 migration has not been compleated
+ // Alert message will be displayed in case that V5 migration has not been compleated
(migrationStatus != null && !migrationStatus.isV5Compatible)
&& (
@@ -90,7 +91,7 @@ const AdminHome = (props) => {
{t('admin:admin_top.env_var_priority')}
{/* eslint-disable-next-line react/no-danger */}
- {adminHomeContainer.state.envVars &&
}
+
diff --git a/apps/app/src/client/components/Admin/AdminHome/EnvVarsTable.tsx b/apps/app/src/client/components/Admin/AdminHome/EnvVarsTable.tsx
index 9a25953ae46..ccb5d46cbcb 100644
--- a/apps/app/src/client/components/Admin/AdminHome/EnvVarsTable.tsx
+++ b/apps/app/src/client/components/Admin/AdminHome/EnvVarsTable.tsx
@@ -1,13 +1,20 @@
import React, { type JSX } from 'react';
+import { LoadingSpinner } from '@growi/ui/dist/components';
+
type EnvVarsTableProps = {
- envVars: Record,
+ envVars?: Record,
}
export const EnvVarsTable: React.FC = (props: EnvVarsTableProps) => {
+ const { envVars } = props;
+ if (envVars == null) {
+ return ;
+ }
+
const envVarRows: JSX.Element[] = [];
- for (const [key, value] of Object.entries(props.envVars)) {
+ for (const [key, value] of Object.entries(envVars ?? {})) {
if (value != null) {
envVarRows.push(
diff --git a/apps/app/src/client/components/Admin/AdminHome/SystemInfomationTable.tsx b/apps/app/src/client/components/Admin/AdminHome/SystemInfomationTable.tsx
index e1ef6a63cfd..c1ce1241987 100644
--- a/apps/app/src/client/components/Admin/AdminHome/SystemInfomationTable.tsx
+++ b/apps/app/src/client/components/Admin/AdminHome/SystemInfomationTable.tsx
@@ -1,5 +1,7 @@
import React from 'react';
+import { LoadingSpinner } from '@growi/ui/dist/components';
+
import AdminHomeContainer from '~/client/services/AdminHomeContainer';
import { withUnstatedContainers } from '../../UnstatedUtils';
@@ -17,7 +19,7 @@ const SystemInformationTable = (props: Props) => {
} = adminHomeContainer.state;
if (growiVersion == null || nodeVersion == null || npmVersion == null || pnpmVersion == null) {
- return <>>;
+ return ;
}
return (
diff --git a/apps/app/src/client/components/Admin/Security/GitHubSecuritySettingContents.jsx b/apps/app/src/client/components/Admin/Security/GitHubSecuritySettingContents.jsx
index 7474880988d..332e64c68f6 100644
--- a/apps/app/src/client/components/Admin/Security/GitHubSecuritySettingContents.jsx
+++ b/apps/app/src/client/components/Admin/Security/GitHubSecuritySettingContents.jsx
@@ -36,9 +36,11 @@ const GitHubSecurityManagementContents = (props) => {
const onClickSubmit = useCallback(async(data) => {
try {
- await adminGitHubSecurityContainer.changeGitHubClientId(data.githubClientId ?? '');
- await adminGitHubSecurityContainer.changeGitHubClientSecret(data.githubClientSecret ?? '');
- await adminGitHubSecurityContainer.updateGitHubSetting();
+ await adminGitHubSecurityContainer.updateGitHubSetting({
+ githubClientId: data.githubClientId ?? '',
+ githubClientSecret: data.githubClientSecret ?? '',
+ isSameUsernameTreatedAsIdenticalUser: adminGitHubSecurityContainer.state.isSameUsernameTreatedAsIdenticalUser,
+ });
await adminGeneralSecurityContainer.retrieveSetupStratedies();
toastSuccess(t('security_settings.OAuth.GitHub.updated_github'));
}
diff --git a/apps/app/src/client/components/Admin/Security/GoogleSecuritySettingContents.jsx b/apps/app/src/client/components/Admin/Security/GoogleSecuritySettingContents.jsx
index 8dc8dacb1f4..9af4d5ccfa0 100644
--- a/apps/app/src/client/components/Admin/Security/GoogleSecuritySettingContents.jsx
+++ b/apps/app/src/client/components/Admin/Security/GoogleSecuritySettingContents.jsx
@@ -34,9 +34,11 @@ const GoogleSecurityManagementContents = (props) => {
const onClickSubmit = useCallback(async(data) => {
try {
- await adminGoogleSecurityContainer.changeGoogleClientId(data.googleClientId ?? '');
- await adminGoogleSecurityContainer.changeGoogleClientSecret(data.googleClientSecret ?? '');
- await adminGoogleSecurityContainer.updateGoogleSetting();
+ await adminGoogleSecurityContainer.updateGoogleSetting({
+ googleClientId: data.googleClientId ?? '',
+ googleClientSecret: data.googleClientSecret ?? '',
+ isSameEmailTreatedAsIdenticalUser: adminGoogleSecurityContainer.state.isSameEmailTreatedAsIdenticalUser,
+ });
await adminGeneralSecurityContainer.retrieveSetupStratedies();
toastSuccess(t('security_settings.OAuth.Google.updated_google'));
}
diff --git a/apps/app/src/client/components/Admin/Security/LdapSecuritySettingContents.tsx b/apps/app/src/client/components/Admin/Security/LdapSecuritySettingContents.tsx
index b5fd949025a..743e41b0087 100644
--- a/apps/app/src/client/components/Admin/Security/LdapSecuritySettingContents.tsx
+++ b/apps/app/src/client/components/Admin/Security/LdapSecuritySettingContents.tsx
@@ -56,17 +56,20 @@ const LdapSecuritySettingContents = (props: Props) => {
const onSubmit = useCallback(async(data) => {
try {
- await adminLdapSecurityContainer.changeServerUrl(data.serverUrl);
- await adminLdapSecurityContainer.changeBindDN(data.ldapBindDN);
- await adminLdapSecurityContainer.changeBindDNPassword(data.ldapBindDNPassword);
- await adminLdapSecurityContainer.changeSearchFilter(data.ldapSearchFilter);
- await adminLdapSecurityContainer.changeAttrMapUsername(data.ldapAttrMapUsername);
- await adminLdapSecurityContainer.changeAttrMapMail(data.ldapAttrMapMail);
- await adminLdapSecurityContainer.changeAttrMapName(data.ldapAttrMapName);
- await adminLdapSecurityContainer.changeGroupSearchBase(data.ldapGroupSearchBase);
- await adminLdapSecurityContainer.changeGroupSearchFilter(data.ldapGroupSearchFilter);
- await adminLdapSecurityContainer.changeGroupDnProperty(data.ldapGroupDnProperty);
- await adminLdapSecurityContainer.updateLdapSetting();
+ await adminLdapSecurityContainer.updateLdapSetting({
+ serverUrl: data.serverUrl,
+ isUserBind: adminLdapSecurityContainer.state.isUserBind,
+ ldapBindDN: data.ldapBindDN,
+ ldapBindDNPassword: data.ldapBindDNPassword,
+ ldapSearchFilter: data.ldapSearchFilter,
+ ldapAttrMapUsername: data.ldapAttrMapUsername,
+ isSameUsernameTreatedAsIdenticalUser: adminLdapSecurityContainer.state.isSameUsernameTreatedAsIdenticalUser,
+ ldapAttrMapMail: data.ldapAttrMapMail,
+ ldapAttrMapName: data.ldapAttrMapName,
+ ldapGroupSearchBase: data.ldapGroupSearchBase,
+ ldapGroupSearchFilter: data.ldapGroupSearchFilter,
+ ldapGroupDnProperty: data.ldapGroupDnProperty,
+ });
await adminGeneralSecurityContainer.retrieveSetupStratedies();
toastSuccess(t('security_settings.ldap.updated_ldap'));
}
diff --git a/apps/app/src/client/components/Admin/Security/LocalSecuritySettingContents.tsx b/apps/app/src/client/components/Admin/Security/LocalSecuritySettingContents.tsx
index f42f4dab685..b34c7a10b36 100644
--- a/apps/app/src/client/components/Admin/Security/LocalSecuritySettingContents.tsx
+++ b/apps/app/src/client/components/Admin/Security/LocalSecuritySettingContents.tsx
@@ -38,8 +38,12 @@ const LocalSecuritySettingContents = (props: Props): JSX.Element => {
const onSubmit = useCallback(async(data) => {
try {
- await adminLocalSecurityContainer.changeRegistrationWhitelist(data.registrationWhitelist);
- await adminLocalSecurityContainer.updateLocalSecuritySetting();
+ await adminLocalSecurityContainer.updateLocalSecuritySetting({
+ registrationMode: adminLocalSecurityContainer.state.registrationMode,
+ registrationWhitelist: data.registrationWhitelist.split('\n'),
+ isPasswordResetEnabled: adminLocalSecurityContainer.state.isPasswordResetEnabled,
+ isEmailAuthenticationEnabled: adminLocalSecurityContainer.state.isEmailAuthenticationEnabled,
+ });
await adminGeneralSecurityContainer.retrieveSetupStratedies();
toastSuccess(t('security_settings.updated_general_security_setting'));
}
diff --git a/apps/app/src/client/components/Admin/Security/OidcSecuritySettingContents.tsx b/apps/app/src/client/components/Admin/Security/OidcSecuritySettingContents.tsx
index a70fbbcd8b9..fb3af745fc0 100644
--- a/apps/app/src/client/components/Admin/Security/OidcSecuritySettingContents.tsx
+++ b/apps/app/src/client/components/Admin/Security/OidcSecuritySettingContents.tsx
@@ -68,23 +68,26 @@ const OidcSecurityManagementContents = (props: Props) => {
const onSubmit = useCallback(async(data) => {
try {
- await adminOidcSecurityContainer.changeOidcProviderName(data.oidcProviderName);
- await adminOidcSecurityContainer.changeOidcIssuerHost(data.oidcIssuerHost);
- await adminOidcSecurityContainer.changeOidcClientId(data.oidcClientId);
- await adminOidcSecurityContainer.changeOidcClientSecret(data.oidcClientSecret);
- await adminOidcSecurityContainer.changeOidcAuthorizationEndpoint(data.oidcAuthorizationEndpoint);
- await adminOidcSecurityContainer.changeOidcTokenEndpoint(data.oidcTokenEndpoint);
- await adminOidcSecurityContainer.changeOidcRevocationEndpoint(data.oidcRevocationEndpoint);
- await adminOidcSecurityContainer.changeOidcIntrospectionEndpoint(data.oidcIntrospectionEndpoint);
- await adminOidcSecurityContainer.changeOidcUserInfoEndpoint(data.oidcUserInfoEndpoint);
- await adminOidcSecurityContainer.changeOidcEndSessionEndpoint(data.oidcEndSessionEndpoint);
- await adminOidcSecurityContainer.changeOidcRegistrationEndpoint(data.oidcRegistrationEndpoint);
- await adminOidcSecurityContainer.changeOidcJWKSUri(data.oidcJWKSUri);
- await adminOidcSecurityContainer.changeOidcAttrMapId(data.oidcAttrMapId);
- await adminOidcSecurityContainer.changeOidcAttrMapUserName(data.oidcAttrMapUserName);
- await adminOidcSecurityContainer.changeOidcAttrMapName(data.oidcAttrMapName);
- await adminOidcSecurityContainer.changeOidcAttrMapEmail(data.oidcAttrMapEmail);
- await adminOidcSecurityContainer.updateOidcSetting();
+ await adminOidcSecurityContainer.updateOidcSetting({
+ oidcProviderName: data.oidcProviderName,
+ oidcIssuerHost: data.oidcIssuerHost,
+ oidcClientId: data.oidcClientId,
+ oidcClientSecret: data.oidcClientSecret,
+ oidcAuthorizationEndpoint: data.oidcAuthorizationEndpoint,
+ oidcTokenEndpoint: data.oidcTokenEndpoint,
+ oidcRevocationEndpoint: data.oidcRevocationEndpoint,
+ oidcIntrospectionEndpoint: data.oidcIntrospectionEndpoint,
+ oidcUserInfoEndpoint: data.oidcUserInfoEndpoint,
+ oidcEndSessionEndpoint: data.oidcEndSessionEndpoint,
+ oidcRegistrationEndpoint: data.oidcRegistrationEndpoint,
+ oidcJWKSUri: data.oidcJWKSUri,
+ oidcAttrMapId: data.oidcAttrMapId,
+ oidcAttrMapUserName: data.oidcAttrMapUserName,
+ oidcAttrMapName: data.oidcAttrMapName,
+ oidcAttrMapEmail: data.oidcAttrMapEmail,
+ isSameUsernameTreatedAsIdenticalUser: adminOidcSecurityContainer.state.isSameUsernameTreatedAsIdenticalUser,
+ isSameEmailTreatedAsIdenticalUser: adminOidcSecurityContainer.state.isSameEmailTreatedAsIdenticalUser,
+ });
await adminGeneralSecurityContainer.retrieveSetupStratedies();
toastSuccess(t('security_settings.OAuth.OIDC.updated_oidc'));
}
diff --git a/apps/app/src/client/components/Admin/Security/SamlSecuritySettingContents.tsx b/apps/app/src/client/components/Admin/Security/SamlSecuritySettingContents.tsx
index e11b60e2f3b..8eb3a5f05e3 100644
--- a/apps/app/src/client/components/Admin/Security/SamlSecuritySettingContents.tsx
+++ b/apps/app/src/client/components/Admin/Security/SamlSecuritySettingContents.tsx
@@ -46,18 +46,20 @@ const SamlSecurityManagementContents = (props: Props) => {
}, [adminSamlSecurityContainer.state, reset]);
const onSubmit = useCallback(async(data) => {
- adminSamlSecurityContainer.changeSamlEntryPoint(data.samlEntryPoint);
- adminSamlSecurityContainer.changeSamlIssuer(data.samlIssuer);
- adminSamlSecurityContainer.changeSamlCert(data.samlCert);
- adminSamlSecurityContainer.changeSamlAttrMapId(data.samlAttrMapId);
- adminSamlSecurityContainer.changeSamlAttrMapUserName(data.samlAttrMapUsername);
- adminSamlSecurityContainer.changeSamlAttrMapMail(data.samlAttrMapMail);
- adminSamlSecurityContainer.changeSamlAttrMapFirstName(data.samlAttrMapFirstName);
- adminSamlSecurityContainer.changeSamlAttrMapLastName(data.samlAttrMapLastName);
- adminSamlSecurityContainer.changeSamlABLCRule(data.samlABLCRule);
-
try {
- await adminSamlSecurityContainer.updateSamlSetting();
+ await adminSamlSecurityContainer.updateSamlSetting({
+ samlEntryPoint: data.samlEntryPoint,
+ samlIssuer: data.samlIssuer,
+ samlCert: data.samlCert,
+ samlAttrMapId: data.samlAttrMapId,
+ samlAttrMapUsername: data.samlAttrMapUsername,
+ samlAttrMapMail: data.samlAttrMapMail,
+ samlAttrMapFirstName: data.samlAttrMapFirstName,
+ samlAttrMapLastName: data.samlAttrMapLastName,
+ isSameUsernameTreatedAsIdenticalUser: adminSamlSecurityContainer.state.isSameUsernameTreatedAsIdenticalUser,
+ isSameEmailTreatedAsIdenticalUser: adminSamlSecurityContainer.state.isSameEmailTreatedAsIdenticalUser,
+ samlABLCRule: data.samlABLCRule,
+ });
toastSuccess(t('security_settings.SAML.updated_saml'));
}
catch (err) {
diff --git a/apps/app/src/client/components/Admin/Security/SecuritySetting/index.tsx b/apps/app/src/client/components/Admin/Security/SecuritySetting/index.tsx
index f12eef8df6f..ac04ce83f5c 100644
--- a/apps/app/src/client/components/Admin/Security/SecuritySetting/index.tsx
+++ b/apps/app/src/client/components/Admin/Security/SecuritySetting/index.tsx
@@ -36,10 +36,21 @@ const SecuritySettingComponent: React.FC = ({ adminGeneralSecurityContain
const onSubmit = useCallback(async(data: FormData) => {
try {
- // Update sessionMaxAge from form data
- await adminGeneralSecurityContainer.setSessionMaxAge(data.sessionMaxAge);
- // Save all security settings
- await adminGeneralSecurityContainer.updateGeneralSecuritySetting();
+ // Save all security settings with form data
+ await adminGeneralSecurityContainer.updateGeneralSecuritySetting({
+ sessionMaxAge: data.sessionMaxAge,
+ restrictGuestMode: adminGeneralSecurityContainer.state.currentRestrictGuestMode,
+ pageDeletionAuthority: adminGeneralSecurityContainer.state.currentPageDeletionAuthority,
+ pageCompleteDeletionAuthority: adminGeneralSecurityContainer.state.currentPageCompleteDeletionAuthority,
+ pageRecursiveDeletionAuthority: adminGeneralSecurityContainer.state.currentPageRecursiveDeletionAuthority,
+ pageRecursiveCompleteDeletionAuthority: adminGeneralSecurityContainer.state.currentPageRecursiveCompleteDeletionAuthority,
+ isAllGroupMembershipRequiredForPageCompleteDeletion: adminGeneralSecurityContainer.state.isAllGroupMembershipRequiredForPageCompleteDeletion,
+ hideRestrictedByGroup: adminGeneralSecurityContainer.state.currentGroupRestrictionDisplayMode === 'Hidden',
+ hideRestrictedByOwner: adminGeneralSecurityContainer.state.currentOwnerRestrictionDisplayMode === 'Hidden',
+ isUsersHomepageDeletionEnabled: adminGeneralSecurityContainer.state.isUsersHomepageDeletionEnabled,
+ isForceDeleteUserHomepageOnUserDeletion: adminGeneralSecurityContainer.state.isForceDeleteUserHomepageOnUserDeletion,
+ isRomUserAllowedToComment: adminGeneralSecurityContainer.state.isRomUserAllowedToComment,
+ });
toastSuccess(t('security_settings.updated_general_security_setting'));
}
catch (err) {
diff --git a/apps/app/src/client/services/AdminGeneralSecurityContainer.js b/apps/app/src/client/services/AdminGeneralSecurityContainer.js
index 72cafa823e4..6561d8d1c89 100644
--- a/apps/app/src/client/services/AdminGeneralSecurityContainer.js
+++ b/apps/app/src/client/services/AdminGeneralSecurityContainer.js
@@ -239,9 +239,22 @@ export default class AdminGeneralSecurityContainer extends Container {
* @memberOf AdminGeneralSecuritySContainer
* @return {string} Appearance
*/
- async updateGeneralSecuritySetting() {
-
- let requestParams = {
+ async updateGeneralSecuritySetting(formData) {
+
+ let requestParams = formData != null ? {
+ sessionMaxAge: formData.sessionMaxAge,
+ restrictGuestMode: formData.restrictGuestMode,
+ pageDeletionAuthority: formData.pageDeletionAuthority,
+ pageCompleteDeletionAuthority: formData.pageCompleteDeletionAuthority,
+ pageRecursiveDeletionAuthority: formData.pageRecursiveDeletionAuthority,
+ pageRecursiveCompleteDeletionAuthority: formData.pageRecursiveCompleteDeletionAuthority,
+ isAllGroupMembershipRequiredForPageCompleteDeletion: formData.isAllGroupMembershipRequiredForPageCompleteDeletion,
+ hideRestrictedByGroup: formData.hideRestrictedByGroup,
+ hideRestrictedByOwner: formData.hideRestrictedByOwner,
+ isUsersHomepageDeletionEnabled: formData.isUsersHomepageDeletionEnabled,
+ isForceDeleteUserHomepageOnUserDeletion: formData.isForceDeleteUserHomepageOnUserDeletion,
+ isRomUserAllowedToComment: formData.isRomUserAllowedToComment,
+ } : {
sessionMaxAge: this.state.sessionMaxAge,
restrictGuestMode: this.state.currentRestrictGuestMode,
pageDeletionAuthority: this.state.currentPageDeletionAuthority,
diff --git a/apps/app/src/client/services/AdminGitHubSecurityContainer.js b/apps/app/src/client/services/AdminGitHubSecurityContainer.js
index 32db1855a6f..256533c04e4 100644
--- a/apps/app/src/client/services/AdminGitHubSecurityContainer.js
+++ b/apps/app/src/client/services/AdminGitHubSecurityContainer.js
@@ -61,20 +61,6 @@ export default class AdminGitHubSecurityContainer extends Container {
return 'AdminGitHubSecurityContainer';
}
- /**
- * Change githubClientId
- */
- changeGitHubClientId(value) {
- this.setState({ githubClientId: value });
- }
-
- /**
- * Change githubClientSecret
- */
- changeGitHubClientSecret(value) {
- this.setState({ githubClientSecret: value });
- }
-
/**
* Switch isSameUsernameTreatedAsIdenticalUser
*/
@@ -85,10 +71,16 @@ export default class AdminGitHubSecurityContainer extends Container {
/**
* Update githubSetting
*/
- async updateGitHubSetting() {
- const { githubClientId, githubClientSecret, isSameUsernameTreatedAsIdenticalUser } = this.state;
-
- let requestParams = { githubClientId, githubClientSecret, isSameUsernameTreatedAsIdenticalUser };
+ async updateGitHubSetting(formData) {
+ let requestParams = formData != null ? {
+ githubClientId: formData.githubClientId,
+ githubClientSecret: formData.githubClientSecret,
+ isSameUsernameTreatedAsIdenticalUser: formData.isSameUsernameTreatedAsIdenticalUser,
+ } : {
+ githubClientId: this.state.githubClientId,
+ githubClientSecret: this.state.githubClientSecret,
+ isSameUsernameTreatedAsIdenticalUser: this.state.isSameUsernameTreatedAsIdenticalUser,
+ };
requestParams = await removeNullPropertyFromObject(requestParams);
const response = await apiv3Put('/security-setting/github-oauth', requestParams);
diff --git a/apps/app/src/client/services/AdminGoogleSecurityContainer.js b/apps/app/src/client/services/AdminGoogleSecurityContainer.js
index 797f50af6d3..b5e606998c0 100644
--- a/apps/app/src/client/services/AdminGoogleSecurityContainer.js
+++ b/apps/app/src/client/services/AdminGoogleSecurityContainer.js
@@ -62,20 +62,6 @@ export default class AdminGoogleSecurityContainer extends Container {
return 'AdminGoogleSecurityContainer';
}
- /**
- * Change googleClientId
- */
- changeGoogleClientId(value) {
- this.setState({ googleClientId: value });
- }
-
- /**
- * Change googleClientSecret
- */
- changeGoogleClientSecret(value) {
- this.setState({ googleClientSecret: value });
- }
-
/**
* Switch isSameEmailTreatedAsIdenticalUser
*/
@@ -87,11 +73,15 @@ export default class AdminGoogleSecurityContainer extends Container {
/**
* Update googleSetting
*/
- async updateGoogleSetting() {
- const { googleClientId, googleClientSecret, isSameEmailTreatedAsIdenticalUser } = this.state;
-
- let requestParams = {
- googleClientId, googleClientSecret, isSameEmailTreatedAsIdenticalUser,
+ async updateGoogleSetting(formData) {
+ let requestParams = formData != null ? {
+ googleClientId: formData.googleClientId,
+ googleClientSecret: formData.googleClientSecret,
+ isSameEmailTreatedAsIdenticalUser: formData.isSameEmailTreatedAsIdenticalUser,
+ } : {
+ googleClientId: this.state.googleClientId,
+ googleClientSecret: this.state.googleClientSecret,
+ isSameEmailTreatedAsIdenticalUser: this.state.isSameEmailTreatedAsIdenticalUser,
};
requestParams = await removeNullPropertyFromObject(requestParams);
diff --git a/apps/app/src/client/services/AdminLdapSecurityContainer.js b/apps/app/src/client/services/AdminLdapSecurityContainer.js
index 4f049ee133b..cb90568ed0f 100644
--- a/apps/app/src/client/services/AdminLdapSecurityContainer.js
+++ b/apps/app/src/client/services/AdminLdapSecurityContainer.js
@@ -78,13 +78,6 @@ export default class AdminLdapSecurityContainer extends Container {
return 'AdminLdapSecurityContainer';
}
- /**
- * Change serverUrl
- */
- changeServerUrl(serverUrl) {
- this.setState({ serverUrl });
- }
-
/**
* Change ldapBindMode
* @param {boolean} isUserBind true: User Bind, false: Admin Bind
@@ -93,34 +86,6 @@ export default class AdminLdapSecurityContainer extends Container {
this.setState({ isUserBind });
}
- /**
- * Change bindDN
- */
- changeBindDN(ldapBindDN) {
- this.setState({ ldapBindDN });
- }
-
- /**
- * Change bindDNPassword
- */
- changeBindDNPassword(ldapBindDNPassword) {
- this.setState({ ldapBindDNPassword });
- }
-
- /**
- * Change ldapSearchFilter
- */
- changeSearchFilter(ldapSearchFilter) {
- this.setState({ ldapSearchFilter });
- }
-
- /**
- * Change ldapAttrMapUsername
- */
- changeAttrMapUsername(ldapAttrMapUsername) {
- this.setState({ ldapAttrMapUsername });
- }
-
/**
* Switch is same username treated as identical user
*/
@@ -128,63 +93,36 @@ export default class AdminLdapSecurityContainer extends Container {
this.setState({ isSameUsernameTreatedAsIdenticalUser: !this.state.isSameUsernameTreatedAsIdenticalUser });
}
- /**
- * Change ldapAttrMapMail
- */
- changeAttrMapMail(ldapAttrMapMail) {
- this.setState({ ldapAttrMapMail });
- }
-
- /**
- * Change ldapAttrMapName
- */
- changeAttrMapName(ldapAttrMapName) {
- this.setState({ ldapAttrMapName });
- }
-
- /**
- * Change ldapGroupSearchBase
- */
- changeGroupSearchBase(ldapGroupSearchBase) {
- this.setState({ ldapGroupSearchBase });
- }
-
- /**
- * Change ldapGroupSearchFilter
- */
- changeGroupSearchFilter(ldapGroupSearchFilter) {
- this.setState({ ldapGroupSearchFilter });
- }
-
- /**
- * Change ldapGroupDnProperty
- */
- changeGroupDnProperty(ldapGroupDnProperty) {
- this.setState({ ldapGroupDnProperty });
- }
-
/**
* Update ldap option
*/
- async updateLdapSetting() {
- const {
- serverUrl, isUserBind, ldapBindDN, ldapBindDNPassword, ldapSearchFilter, ldapAttrMapUsername, isSameUsernameTreatedAsIdenticalUser,
- ldapAttrMapMail, ldapAttrMapName, ldapGroupSearchBase, ldapGroupSearchFilter, ldapGroupDnProperty,
- } = this.state;
-
- let requestParams = {
- serverUrl,
- isUserBind,
- ldapBindDN,
- ldapBindDNPassword,
- ldapSearchFilter,
- ldapAttrMapUsername,
- isSameUsernameTreatedAsIdenticalUser,
- ldapAttrMapMail,
- ldapAttrMapName,
- ldapGroupSearchBase,
- ldapGroupSearchFilter,
- ldapGroupDnProperty,
+ async updateLdapSetting(formData) {
+ let requestParams = formData != null ? {
+ serverUrl: formData.serverUrl,
+ isUserBind: formData.isUserBind,
+ ldapBindDN: formData.ldapBindDN,
+ ldapBindDNPassword: formData.ldapBindDNPassword,
+ ldapSearchFilter: formData.ldapSearchFilter,
+ ldapAttrMapUsername: formData.ldapAttrMapUsername,
+ isSameUsernameTreatedAsIdenticalUser: formData.isSameUsernameTreatedAsIdenticalUser,
+ ldapAttrMapMail: formData.ldapAttrMapMail,
+ ldapAttrMapName: formData.ldapAttrMapName,
+ ldapGroupSearchBase: formData.ldapGroupSearchBase,
+ ldapGroupSearchFilter: formData.ldapGroupSearchFilter,
+ ldapGroupDnProperty: formData.ldapGroupDnProperty,
+ } : {
+ serverUrl: this.state.serverUrl,
+ isUserBind: this.state.isUserBind,
+ ldapBindDN: this.state.ldapBindDN,
+ ldapBindDNPassword: this.state.ldapBindDNPassword,
+ ldapSearchFilter: this.state.ldapSearchFilter,
+ ldapAttrMapUsername: this.state.ldapAttrMapUsername,
+ isSameUsernameTreatedAsIdenticalUser: this.state.isSameUsernameTreatedAsIdenticalUser,
+ ldapAttrMapMail: this.state.ldapAttrMapMail,
+ ldapAttrMapName: this.state.ldapAttrMapName,
+ ldapGroupSearchBase: this.state.ldapGroupSearchBase,
+ ldapGroupSearchFilter: this.state.ldapGroupSearchFilter,
+ ldapGroupDnProperty: this.state.ldapGroupDnProperty,
};
requestParams = await removeNullPropertyFromObject(requestParams);
diff --git a/apps/app/src/client/services/AdminLocalSecurityContainer.js b/apps/app/src/client/services/AdminLocalSecurityContainer.js
index b13089b4adb..a1314d9da7d 100644
--- a/apps/app/src/client/services/AdminLocalSecurityContainer.js
+++ b/apps/app/src/client/services/AdminLocalSecurityContainer.js
@@ -71,13 +71,6 @@ export default class AdminLocalSecurityContainer extends Container {
this.setState({ registrationMode: value });
}
- /**
- * Change registration whitelist
- */
- changeRegistrationWhitelist(value) {
- this.setState({ registrationWhitelist: value.split('\n') });
- }
-
/**
* Switch password reset enabled
*/
@@ -95,14 +88,19 @@ export default class AdminLocalSecurityContainer extends Container {
/**
* update local security setting
*/
- async updateLocalSecuritySetting() {
- const { registrationWhitelist, isPasswordResetEnabled, isEmailAuthenticationEnabled } = this.state;
- const response = await apiv3Put('/security-setting/local-setting', {
+ async updateLocalSecuritySetting(formData) {
+ const requestParams = formData != null ? {
+ registrationMode: formData.registrationMode,
+ registrationWhitelist: formData.registrationWhitelist,
+ isPasswordResetEnabled: formData.isPasswordResetEnabled,
+ isEmailAuthenticationEnabled: formData.isEmailAuthenticationEnabled,
+ } : {
registrationMode: this.state.registrationMode,
- registrationWhitelist,
- isPasswordResetEnabled,
- isEmailAuthenticationEnabled,
- });
+ registrationWhitelist: this.state.registrationWhitelist,
+ isPasswordResetEnabled: this.state.isPasswordResetEnabled,
+ isEmailAuthenticationEnabled: this.state.isEmailAuthenticationEnabled,
+ };
+ const response = await apiv3Put('/security-setting/local-setting', requestParams);
const { localSettingParams } = response.data;
diff --git a/apps/app/src/client/services/AdminOidcSecurityContainer.js b/apps/app/src/client/services/AdminOidcSecurityContainer.js
index 2d0fec1c08b..04f5c8e6f7b 100644
--- a/apps/app/src/client/services/AdminOidcSecurityContainer.js
+++ b/apps/app/src/client/services/AdminOidcSecurityContainer.js
@@ -89,118 +89,6 @@ export default class AdminOidcSecurityContainer extends Container {
return 'AdminOidcSecurityContainer';
}
- /**
- * Change oidcProviderName
- */
- changeOidcProviderName(inputValue) {
- this.setState({ oidcProviderName: inputValue });
- }
-
- /**
- * Change oidcIssuerHost
- */
- changeOidcIssuerHost(inputValue) {
- this.setState({ oidcIssuerHost: inputValue });
- }
-
- /**
- * Change oidcAuthorizationEndpoint
- */
- changeOidcAuthorizationEndpoint(inputValue) {
- this.setState({ oidcAuthorizationEndpoint: inputValue });
- }
-
- /**
- * Change oidcTokenEndpoint
- */
- changeOidcTokenEndpoint(inputValue) {
- this.setState({ oidcTokenEndpoint: inputValue });
- }
-
- /**
- * Change oidcRevocationEndpoint
- */
- changeOidcRevocationEndpoint(inputValue) {
- this.setState({ oidcRevocationEndpoint: inputValue });
- }
-
- /**
- * Change oidcIntrospectionEndpoint
- */
- changeOidcIntrospectionEndpoint(inputValue) {
- this.setState({ oidcIntrospectionEndpoint: inputValue });
- }
-
- /**
- * Change oidcUserInfoEndpoint
- */
- changeOidcUserInfoEndpoint(inputValue) {
- this.setState({ oidcUserInfoEndpoint: inputValue });
- }
-
- /**
- * Change oidcEndSessionEndpoint
- */
- changeOidcEndSessionEndpoint(inputValue) {
- this.setState({ oidcEndSessionEndpoint: inputValue });
- }
-
- /**
- * Change oidcRegistrationEndpoint
- */
- changeOidcRegistrationEndpoint(inputValue) {
- this.setState({ oidcRegistrationEndpoint: inputValue });
- }
-
- /**
- * Change oidcJWKSUri
- */
- changeOidcJWKSUri(inputValue) {
- this.setState({ oidcJWKSUri: inputValue });
- }
-
- /**
- * Change oidcClientId
- */
- changeOidcClientId(inputValue) {
- this.setState({ oidcClientId: inputValue });
- }
-
- /**
- * Change oidcClientSecret
- */
- changeOidcClientSecret(inputValue) {
- this.setState({ oidcClientSecret: inputValue });
- }
-
- /**
- * Change oidcAttrMapId
- */
- changeOidcAttrMapId(inputValue) {
- this.setState({ oidcAttrMapId: inputValue });
- }
-
- /**
- * Change oidcAttrMapUserName
- */
- changeOidcAttrMapUserName(inputValue) {
- this.setState({ oidcAttrMapUserName: inputValue });
- }
-
- /**
- * Change oidcAttrMapName
- */
- changeOidcAttrMapName(inputValue) {
- this.setState({ oidcAttrMapName: inputValue });
- }
-
- /**
- * Change oidcAttrMapEmail
- */
- changeOidcAttrMapEmail(inputValue) {
- this.setState({ oidcAttrMapEmail: inputValue });
- }
-
/**
* Switch sameUsernameTreatedAsIdenticalUser
*/
@@ -218,47 +106,45 @@ export default class AdminOidcSecurityContainer extends Container {
/**
* Update OpenID Connect
*/
- async updateOidcSetting() {
- const {
- oidcProviderName,
- oidcIssuerHost,
- oidcAuthorizationEndpoint,
- oidcTokenEndpoint,
- oidcRevocationEndpoint,
- oidcIntrospectionEndpoint,
- oidcUserInfoEndpoint,
- oidcEndSessionEndpoint,
- oidcRegistrationEndpoint,
- oidcJWKSUri,
- oidcClientId,
- oidcClientSecret,
- oidcAttrMapId,
- oidcAttrMapUserName,
- oidcAttrMapName,
- oidcAttrMapEmail,
- isSameUsernameTreatedAsIdenticalUser,
- isSameEmailTreatedAsIdenticalUser,
- } = this.state;
-
- let requestParams = {
- oidcProviderName,
- oidcIssuerHost,
- oidcAuthorizationEndpoint,
- oidcTokenEndpoint,
- oidcRevocationEndpoint,
- oidcIntrospectionEndpoint,
- oidcUserInfoEndpoint,
- oidcEndSessionEndpoint,
- oidcRegistrationEndpoint,
- oidcJWKSUri,
- oidcClientId,
- oidcClientSecret,
- oidcAttrMapId,
- oidcAttrMapUserName,
- oidcAttrMapName,
- oidcAttrMapEmail,
- isSameUsernameTreatedAsIdenticalUser,
- isSameEmailTreatedAsIdenticalUser,
+ async updateOidcSetting(formData) {
+ let requestParams = formData != null ? {
+ oidcProviderName: formData.oidcProviderName,
+ oidcIssuerHost: formData.oidcIssuerHost,
+ oidcAuthorizationEndpoint: formData.oidcAuthorizationEndpoint,
+ oidcTokenEndpoint: formData.oidcTokenEndpoint,
+ oidcRevocationEndpoint: formData.oidcRevocationEndpoint,
+ oidcIntrospectionEndpoint: formData.oidcIntrospectionEndpoint,
+ oidcUserInfoEndpoint: formData.oidcUserInfoEndpoint,
+ oidcEndSessionEndpoint: formData.oidcEndSessionEndpoint,
+ oidcRegistrationEndpoint: formData.oidcRegistrationEndpoint,
+ oidcJWKSUri: formData.oidcJWKSUri,
+ oidcClientId: formData.oidcClientId,
+ oidcClientSecret: formData.oidcClientSecret,
+ oidcAttrMapId: formData.oidcAttrMapId,
+ oidcAttrMapUserName: formData.oidcAttrMapUserName,
+ oidcAttrMapName: formData.oidcAttrMapName,
+ oidcAttrMapEmail: formData.oidcAttrMapEmail,
+ isSameUsernameTreatedAsIdenticalUser: formData.isSameUsernameTreatedAsIdenticalUser,
+ isSameEmailTreatedAsIdenticalUser: formData.isSameEmailTreatedAsIdenticalUser,
+ } : {
+ oidcProviderName: this.state.oidcProviderName,
+ oidcIssuerHost: this.state.oidcIssuerHost,
+ oidcAuthorizationEndpoint: this.state.oidcAuthorizationEndpoint,
+ oidcTokenEndpoint: this.state.oidcTokenEndpoint,
+ oidcRevocationEndpoint: this.state.oidcRevocationEndpoint,
+ oidcIntrospectionEndpoint: this.state.oidcIntrospectionEndpoint,
+ oidcUserInfoEndpoint: this.state.oidcUserInfoEndpoint,
+ oidcEndSessionEndpoint: this.state.oidcEndSessionEndpoint,
+ oidcRegistrationEndpoint: this.state.oidcRegistrationEndpoint,
+ oidcJWKSUri: this.state.oidcJWKSUri,
+ oidcClientId: this.state.oidcClientId,
+ oidcClientSecret: this.state.oidcClientSecret,
+ oidcAttrMapId: this.state.oidcAttrMapId,
+ oidcAttrMapUserName: this.state.oidcAttrMapUserName,
+ oidcAttrMapName: this.state.oidcAttrMapName,
+ oidcAttrMapEmail: this.state.oidcAttrMapEmail,
+ isSameUsernameTreatedAsIdenticalUser: this.state.isSameUsernameTreatedAsIdenticalUser,
+ isSameEmailTreatedAsIdenticalUser: this.state.isSameEmailTreatedAsIdenticalUser,
};
requestParams = await removeNullPropertyFromObject(requestParams);
diff --git a/apps/app/src/client/services/AdminSamlSecurityContainer.js b/apps/app/src/client/services/AdminSamlSecurityContainer.js
index cceef3769ab..587d141ca24 100644
--- a/apps/app/src/client/services/AdminSamlSecurityContainer.js
+++ b/apps/app/src/client/services/AdminSamlSecurityContainer.js
@@ -98,62 +98,6 @@ export default class AdminSamlSecurityContainer extends Container {
return 'AdminSamlSecurityContainer';
}
- /**
- * Change samlEntryPoint
- */
- changeSamlEntryPoint(inputValue) {
- this.setState({ samlEntryPoint: inputValue });
- }
-
- /**
- * Change samlIssuer
- */
- changeSamlIssuer(inputValue) {
- this.setState({ samlIssuer: inputValue });
- }
-
- /**
- * Change samlCert
- */
- changeSamlCert(inputValue) {
- this.setState({ samlCert: inputValue });
- }
-
- /**
- * Change samlAttrMapId
- */
- changeSamlAttrMapId(inputValue) {
- this.setState({ samlAttrMapId: inputValue });
- }
-
- /**
- * Change samlAttrMapUsername
- */
- changeSamlAttrMapUserName(inputValue) {
- this.setState({ samlAttrMapUsername: inputValue });
- }
-
- /**
- * Change samlAttrMapMail
- */
- changeSamlAttrMapMail(inputValue) {
- this.setState({ samlAttrMapMail: inputValue });
- }
-
- /**
- * Change samlAttrMapFirstName
- */
- changeSamlAttrMapFirstName(inputValue) {
- this.setState({ samlAttrMapFirstName: inputValue });
- }
-
- /**
- * Change samlAttrMapLastName
- */
- changeSamlAttrMapLastName(inputValue) {
- this.setState({ samlAttrMapLastName: inputValue });
- }
-
/**
* Switch isSameUsernameTreatedAsIdenticalUser
*/
@@ -168,19 +112,24 @@ export default class AdminSamlSecurityContainer extends Container {
this.setState({ isSameEmailTreatedAsIdenticalUser: !this.state.isSameEmailTreatedAsIdenticalUser });
}
- /**
- * Change samlABLCRule
- */
- changeSamlABLCRule(inputValue) {
- this.setState({ samlABLCRule: inputValue });
- }
-
/**
* Update saml option
*/
- async updateSamlSetting() {
-
- let requestParams = {
+ async updateSamlSetting(formData) {
+
+ let requestParams = formData != null ? {
+ entryPoint: formData.samlEntryPoint,
+ issuer: formData.samlIssuer,
+ cert: formData.samlCert,
+ attrMapId: formData.samlAttrMapId,
+ attrMapUsername: formData.samlAttrMapUsername,
+ attrMapMail: formData.samlAttrMapMail,
+ attrMapFirstName: formData.samlAttrMapFirstName,
+ attrMapLastName: formData.samlAttrMapLastName,
+ isSameUsernameTreatedAsIdenticalUser: formData.isSameUsernameTreatedAsIdenticalUser,
+ isSameEmailTreatedAsIdenticalUser: formData.isSameEmailTreatedAsIdenticalUser,
+ ABLCRule: formData.samlABLCRule,
+ } : {
entryPoint: this.state.samlEntryPoint,
issuer: this.state.samlIssuer,
cert: this.state.samlCert,
diff --git a/apps/pdf-converter/.env b/apps/pdf-converter/.env
index 12c220c7936..09d0bad128c 100644
--- a/apps/pdf-converter/.env
+++ b/apps/pdf-converter/.env
@@ -1 +1,2 @@
PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium
+PUPPETEER_CLUSTER_CONFIG={"maxConcurrency":1, "concurrency": 2}
diff --git a/apps/pdf-converter/docker/README.md b/apps/pdf-converter/docker/README.md
index d5c3feb11c0..96359d7eb8f 100644
--- a/apps/pdf-converter/docker/README.md
+++ b/apps/pdf-converter/docker/README.md
@@ -5,10 +5,10 @@ GROWI PDF Converter Official docker image
[](https://github.com/growilabs/growi/actions/workflows/ci-pdf-converter.yml) [](https://hub.docker.com/r/growilabs/pdf-converter/)
-Supported tags and respective Dockerfile links
+Dockerfile link
------------------------------------------------
-* [`1.0.0`, `latest` (Dockerfile)](https://github.com/growilabs/growi/blob/master/apps/pdf-converter/docker/Dockerfile)
+https://github.com/growilabs/growi/blob/master/apps/pdf-converter/docker/Dockerfile
What is GROWI PDF Converter used for?
diff --git a/apps/pdf-converter/package.json b/apps/pdf-converter/package.json
index 57e06468be4..c1c0b133af9 100644
--- a/apps/pdf-converter/package.json
+++ b/apps/pdf-converter/package.json
@@ -1,6 +1,6 @@
{
"name": "@growi/pdf-converter",
- "version": "1.1.3-RC.0",
+ "version": "1.2.1-RC.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"license": "MIT",
diff --git a/apps/pdf-converter/src/service/pdf-convert.ts b/apps/pdf-converter/src/service/pdf-convert.ts
index d9fa1526c77..e94da6f2e3f 100644
--- a/apps/pdf-converter/src/service/pdf-convert.ts
+++ b/apps/pdf-converter/src/service/pdf-convert.ts
@@ -5,6 +5,7 @@ import { pipeline as pipelinePromise } from 'node:stream/promises';
import { OnInit } from '@tsed/common';
import { Service } from '@tsed/di';
import { Logger } from '@tsed/logger';
+import type { PuppeteerNodeLaunchOptions } from 'puppeteer';
import { Cluster } from 'puppeteer-cluster';
interface PageInfo {
@@ -37,8 +38,6 @@ interface JobInfo {
class PdfConvertService implements OnInit {
private puppeteerCluster: Cluster | undefined;
- private maxConcurrency = 1;
-
private convertRetryLimit = 5;
private tmpOutputRootDir = '/tmp/page-bulk-export';
@@ -292,15 +291,8 @@ class PdfConvertService implements OnInit {
private async initPuppeteerCluster(): Promise {
if (process.env.SKIP_PUPPETEER_INIT === 'true') return;
- this.puppeteerCluster = await Cluster.launch({
- concurrency: Cluster.CONCURRENCY_PAGE,
- maxConcurrency: this.maxConcurrency,
- workerCreationDelay: 10000,
- puppeteerOptions: {
- // ref) https://github.com/growilabs/growi/pull/10192
- args: ['--no-sandbox'],
- },
- });
+ const config = this.getPuppeteerClusterConfig();
+ this.puppeteerCluster = await Cluster.launch(config);
await this.puppeteerCluster.task(async ({ page, data: htmlString }) => {
await page.setContent(htmlString, { waitUntil: 'domcontentloaded' });
@@ -326,6 +318,51 @@ class PdfConvertService implements OnInit {
});
}
+ /**
+ * Get puppeteer cluster configuration from environment variable
+ * @returns merged cluster configuration
+ */
+ private getPuppeteerClusterConfig(): Record {
+ // Default cluster configuration
+ const defaultConfig = {
+ concurrency: Cluster.CONCURRENCY_CONTEXT,
+ maxConcurrency: 1,
+ workerCreationDelay: 10000,
+ // Puppeteer options (not configurable for security reasons)
+ // ref) https://github.com/growilabs/growi/pull/10192
+ puppeteerOptions: {
+ args: ['--no-sandbox'],
+ },
+ };
+
+ // Parse configuration from environment variable
+ let customConfig: Record = {};
+ if (process.env.PUPPETEER_CLUSTER_CONFIG) {
+ try {
+ customConfig = JSON.parse(process.env.PUPPETEER_CLUSTER_CONFIG);
+ } catch (err) {
+ this.logger.warn(
+ 'Failed to parse PUPPETEER_CLUSTER_CONFIG, using default values',
+ err,
+ );
+ }
+ }
+
+ // Remove puppeteerOptions from custom config if present (not allowed for security)
+ if (customConfig.puppeteerOptions) {
+ this.logger.warn(
+ 'puppeteerOptions configuration is not allowed for security reasons and will be ignored',
+ );
+ delete customConfig.puppeteerOptions;
+ }
+
+ // Merge configurations (customConfig overrides defaultConfig, except puppeteerOptions)
+ return {
+ ...defaultConfig,
+ ...customConfig,
+ };
+ }
+
/**
* Get parent path from given path
* @param path target path
diff --git a/apps/slackbot-proxy/package.json b/apps/slackbot-proxy/package.json
index 8ecad4b984e..17eb33af3fd 100644
--- a/apps/slackbot-proxy/package.json
+++ b/apps/slackbot-proxy/package.json
@@ -1,6 +1,6 @@
{
"name": "@growi/slackbot-proxy",
- "version": "7.3.6-slackbot-proxy.0",
+ "version": "7.3.7-slackbot-proxy.0",
"license": "MIT",
"private": "true",
"scripts": {
diff --git a/package.json b/package.json
index 62e1561ead6..dd887c266f2 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "growi",
- "version": "7.3.6",
+ "version": "7.3.7-RC.0",
"description": "Team collaboration software using markdown",
"license": "MIT",
"private": "true",