Sfoglia il codice sorgente

Merge remote-tracking branch 'origin/master' into support/omit-appcontainer

Yuki Takei 3 anni fa
parent
commit
0a8a0f5782

+ 15 - 0
packages/app/resource/Contributor.js

@@ -12,6 +12,11 @@ const contributors = [
           { position: 'Soncho 2nd', name: 'yusuketk' },
           { position: 'Paladin', name: 'itizawa' },
           { position: 'Valkyrie', name: 'kaoritokashiki' },
+          { position: 'Slime', name: 'TatsuyaIse' },
+          { position: 'Knight', name: 'Yohei-Shiina' },
+          { position: 'Titan', name: 'ryoh15' },
+          { position: 'Haberion', name: 'hakumizuki' },
+          { position: 'Undefind', name: 'miya' },
         ],
       },
       {
@@ -37,6 +42,7 @@ const contributors = [
           { name: 'ryuichi-e' },
           { name: 'N1koge' },
           { name: 'Ertai87' },
+          { name: 'takayuki-t' },
           { name: 'zahmis' },
           { name: 'takeru0001' },
           { name: 'Shu Katabe' },
@@ -46,6 +52,15 @@ const contributors = [
           { name: 'stevenfukase' },
           { name: 'miya' },
           { name: 'kaho819' },
+          { name: 'yuto-oweseek' },
+          { name: 'maow89126' },
+          { name: 'kntowd' },
+          { name: 'yukendev' },
+          { name: 'asami-n' },
+          { name: 'ryohi15' },
+          { name: 'yoshiro-s' },
+          { name: 'kuimac' },
+          { name: 'akira-sugiyama' },
         ],
       },
     ],

+ 10 - 8
packages/app/src/client/services/AdminGoogleSecurityContainer.js

@@ -27,7 +27,7 @@ export default class AdminGoogleSecurityContainer extends Container {
       // set dummy value tile for using suspense
       googleClientId: this.dummyGoogleClientId,
       googleClientSecret: '',
-      isSameUsernameTreatedAsIdenticalUser: false,
+      isSameEmailTreatedAsIdenticalUser: false,
     };
 
 
@@ -43,7 +43,7 @@ export default class AdminGoogleSecurityContainer extends Container {
       this.setState({
         googleClientId: googleOAuth.googleClientId,
         googleClientSecret: googleOAuth.googleClientSecret,
-        isSameUsernameTreatedAsIdenticalUser: googleOAuth.isSameUsernameTreatedAsIdenticalUser,
+        isSameEmailTreatedAsIdenticalUser: googleOAuth.isSameEmailTreatedAsIdenticalUser,
       });
     }
     catch (err) {
@@ -75,20 +75,22 @@ export default class AdminGoogleSecurityContainer extends Container {
   }
 
   /**
-   * Switch isSameUsernameTreatedAsIdenticalUser
+   * Switch isSameEmailTreatedAsIdenticalUser
    */
-  switchIsSameUsernameTreatedAsIdenticalUser() {
-    this.setState({ isSameUsernameTreatedAsIdenticalUser: !this.state.isSameUsernameTreatedAsIdenticalUser });
+  switchIsSameEmailTreatedAsIdenticalUser() {
+    this.setState({ isSameEmailTreatedAsIdenticalUser: !this.state.isSameEmailTreatedAsIdenticalUser });
   }
 
+
   /**
    * Update googleSetting
    */
   async updateGoogleSetting() {
-    const { googleClientId, googleClientSecret, isSameUsernameTreatedAsIdenticalUser } = this.state;
+    const { googleClientId, googleClientSecret, isSameEmailTreatedAsIdenticalUser } = this.state;
+    console.log('updateGoogleSetting', isSameEmailTreatedAsIdenticalUser);
 
     let requestParams = {
-      googleClientId, googleClientSecret, isSameUsernameTreatedAsIdenticalUser,
+      googleClientId, googleClientSecret, isSameEmailTreatedAsIdenticalUser,
     };
 
     requestParams = await removeNullPropertyFromObject(requestParams);
@@ -98,7 +100,7 @@ export default class AdminGoogleSecurityContainer extends Container {
     this.setState({
       googleClientId: securitySettingParams.googleClientId,
       googleClientSecret: securitySettingParams.googleClientSecret,
-      isSameUsernameTreatedAsIdenticalUser: securitySettingParams.isSameUsernameTreatedAsIdenticalUser,
+      isSameEmailTreatedAsIdenticalUser: securitySettingParams.isSameEmailTreatedAsIdenticalUser,
     });
     return response;
   }

+ 7 - 5
packages/app/src/components/Admin/Security/GoogleSecuritySettingContents.jsx

@@ -1,14 +1,16 @@
 /* eslint-disable react/no-danger */
 import React from 'react';
+
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 
-import { withUnstatedContainers } from '../../UnstatedUtils';
-import { toastSuccess, toastError } from '~/client/util/apiNotification';
 
-import AppContainer from '~/client/services/AppContainer';
 import AdminGeneralSecurityContainer from '~/client/services/AdminGeneralSecurityContainer';
 import AdminGoogleSecurityContainer from '~/client/services/AdminGoogleSecurityContainer';
+import AppContainer from '~/client/services/AppContainer';
+import { toastSuccess, toastError } from '~/client/util/apiNotification';
+
+import { withUnstatedContainers } from '../../UnstatedUtils';
 
 class GoogleSecurityManagementContents extends React.Component {
 
@@ -135,8 +137,8 @@ class GoogleSecurityManagementContents extends React.Component {
                     id="bindByUserNameGoogle"
                     className="custom-control-input"
                     type="checkbox"
-                    checked={adminGoogleSecurityContainer.state.isSameUsernameTreatedAsIdenticalUser || false}
-                    onChange={() => { adminGoogleSecurityContainer.switchIsSameUsernameTreatedAsIdenticalUser() }}
+                    checked={adminGoogleSecurityContainer.state.isSameEmailTreatedAsIdenticalUser || false}
+                    onChange={() => { adminGoogleSecurityContainer.switchIsSameEmailTreatedAsIdenticalUser() }}
                   />
                   <label
                     className="custom-control-label"

+ 5 - 8
packages/app/src/components/PageEditor/EmojiPicker.tsx

@@ -23,14 +23,11 @@ const EmojiPicker: FC<Props> = (props: Props) => {
   // Set search emoji input and trigger search
   const searchEmoji = () => {
     const input = window.document.querySelector('[id^="emoji-mart-search"]') as HTMLInputElement;
-    if (emojiSearchText !== null) {
-
-      const valueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value')?.set;
-      valueSetter?.call(input, emojiSearchText);
-      const event = new Event('input', { bubbles: true });
-      input.dispatchEvent(event);
-      input.focus();
-    }
+    const valueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value')?.set;
+    valueSetter?.call(input, emojiSearchText);
+    const event = new Event('input', { bubbles: true });
+    input.dispatchEvent(event);
+    input.focus();
   };
 
   const selectEmoji = (emoji) => {

+ 18 - 9
packages/app/src/components/RevisionComparer/RevisionComparer.jsx

@@ -1,18 +1,19 @@
 import React, { useState } from 'react';
+
+import { pagePathUtils } from '@growi/core';
 import PropTypes from 'prop-types';
-import { withTranslation } from 'react-i18next';
 import { CopyToClipboard } from 'react-copy-to-clipboard';
+import { withTranslation } from 'react-i18next';
 import {
   Dropdown, DropdownToggle, DropdownMenu, DropdownItem,
 } from 'reactstrap';
 
-import { pagePathUtils } from '@growi/core';
-
-import { withUnstatedContainers } from '../UnstatedUtils';
 
 import RevisionComparerContainer from '~/client/services/RevisionComparerContainer';
 
 import RevisionDiff from '../PageHistory/RevisionDiff';
+import { withUnstatedContainers } from '../UnstatedUtils';
+
 
 const { encodeSpaces } = pagePathUtils;
 
@@ -32,16 +33,17 @@ const RevisionComparer = (props) => {
 
   const { t, revisionComparerContainer } = props;
 
+  const { path, pageId } = revisionComparerContainer.pageContainer.state;
+
   function toggleDropdown() {
     setDropdownOpen(!dropdownOpen);
   }
 
-  const pagePathUrl = () => {
+  const generateURL = (pathName) => {
     const { origin } = window.location;
-    const { path } = revisionComparerContainer.pageContainer.state;
     const { sourceRevision, targetRevision } = revisionComparerContainer.state;
 
-    const url = new URL(path, origin);
+    const url = new URL(pathName, origin);
 
     if (sourceRevision != null && targetRevision != null) {
       const urlParams = `${sourceRevision._id}...${targetRevision._id}`;
@@ -49,6 +51,7 @@ const RevisionComparer = (props) => {
     }
 
     return encodeSpaces(decodeURI(url));
+
   };
 
   const { sourceRevision, targetRevision } = revisionComparerContainer.state;
@@ -76,9 +79,15 @@ const RevisionComparer = (props) => {
           </DropdownToggle>
           <DropdownMenu positionFixed right modifiers={{ preventOverflow: { boundariesElement: undefined } }}>
             {/* Page path URL */}
-            <CopyToClipboard text={pagePathUrl()}>
+            <CopyToClipboard text={generateURL(path)}>
+              <DropdownItem className="px-3">
+                <DropdownItemContents title={t('copy_to_clipboard.Page URL')} contents={generateURL(path)} />
+              </DropdownItem>
+            </CopyToClipboard>
+            {/* Permanent Link URL */}
+            <CopyToClipboard text={generateURL(pageId)}>
               <DropdownItem className="px-3">
-                <DropdownItemContents title={t('copy_to_clipboard.Page URL')} contents={pagePathUrl()} />
+                <DropdownItemContents title={t('copy_to_clipboard.Permanent link')} contents={generateURL(pageId)} />
               </DropdownItem>
             </CopyToClipboard>
             <DropdownItem divider className="my-0"></DropdownItem>

+ 6 - 2
packages/app/src/components/Sidebar/CustomSidebar.tsx

@@ -57,7 +57,7 @@ const CustomSidebar: FC<Props> = (props: Props) => {
       }
 
       {
-        !isLoading && markdown != null ? (
+        (!isLoading && markdown != null) && (
           <div className="p-3">
             <RevisionRenderer
               growiRenderer={renderer}
@@ -66,7 +66,11 @@ const CustomSidebar: FC<Props> = (props: Props) => {
               additionalClassName="grw-custom-sidebar-content"
             />
           </div>
-        ) : (
+        )
+      }
+
+      {
+        (!isLoading && markdown === undefined) && (
           <SidebarNotFound />
         )
       }

+ 7 - 5
packages/app/src/server/routes/apiv3/security-setting.js

@@ -1,9 +1,9 @@
+import { PageDeleteConfigValue } from '~/interfaces/page-delete-config';
 import loggerFactory from '~/utils/logger';
 import { removeNullPropertyFromObject } from '~/utils/object-utils';
+import { validateDeleteConfigs, prepareDeleteConfigValuesForCalc } from '~/utils/page-delete-config';
 
-import { PageDeleteConfigValue } from '~/interfaces/page-delete-config';
 import { apiV3FormValidator } from '../../middlewares/apiv3-form-validator';
-import { validateDeleteConfigs, prepareDeleteConfigValuesForCalc } from '~/utils/page-delete-config';
 
 const logger = loggerFactory('growi:routes:apiv3:security-setting');
 
@@ -12,6 +12,7 @@ const express = require('express');
 const router = express.Router();
 
 const { body } = require('express-validator');
+
 const ErrorV3 = require('../../models/vo/error-apiv3');
 
 const validator = {
@@ -461,7 +462,7 @@ module.exports = (crowi) => {
       googleOAuth: {
         googleClientId: await crowi.configManager.getConfig('crowi', 'security:passport-google:clientId'),
         googleClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-google:clientSecret'),
-        isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-google:isSameUsernameTreatedAsIdenticalUser'),
+        isSameEmailTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-google:isSameEmailTreatedAsIdenticalUser'),
       },
       githubOAuth: {
         githubClientId: await crowi.configManager.getConfig('crowi', 'security:passport-github:clientId'),
@@ -1086,16 +1087,17 @@ module.exports = (crowi) => {
     const requestParams = {
       'security:passport-google:clientId': req.body.googleClientId,
       'security:passport-google:clientSecret': req.body.googleClientSecret,
-      'security:passport-google:isSameUsernameTreatedAsIdenticalUser': req.body.isSameUsernameTreatedAsIdenticalUser,
+      'security:passport-google:isSameEmailTreatedAsIdenticalUser': req.body.isSameEmailTreatedAsIdenticalUser,
     };
 
+
     try {
       await updateAndReloadStrategySettings('google', requestParams);
 
       const securitySettingParams = {
         googleClientId: await crowi.configManager.getConfig('crowi', 'security:passport-google:clientId'),
         googleClientSecret: await crowi.configManager.getConfig('crowi', 'security:passport-google:clientSecret'),
-        isSameUsernameTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-google:isSameUsernameTreatedAsIdenticalUser'),
+        isSameEmailTreatedAsIdenticalUser: await crowi.configManager.getConfig('crowi', 'security:passport-google:isSameEmailTreatedAsIdenticalUser'),
       };
       return res.apiv3({ securitySettingParams });
     }

+ 11 - 10
packages/app/src/server/service/passport.ts

@@ -1,22 +1,23 @@
-import urljoin from 'url-join';
-import luceneQueryParser from 'lucene-query-parser';
+import { IncomingMessage } from 'http';
 
+import axiosRetry from 'axios-retry';
+import luceneQueryParser from 'lucene-query-parser';
+import { Strategy as OidcStrategy, Issuer as OIDCIssuer, custom } from 'openid-client';
+import pRetry from 'p-retry';
 import passport from 'passport';
+import { Strategy as GitHubStrategy } from 'passport-github';
+import { Strategy as GoogleStrategy } from 'passport-google-oauth20';
+import { BasicStrategy } from 'passport-http';
 import LdapStrategy from 'passport-ldapauth';
 import { Strategy as LocalStrategy } from 'passport-local';
-import { Strategy as GoogleStrategy } from 'passport-google-oauth20';
-import { Strategy as GitHubStrategy } from 'passport-github';
-import { Strategy as TwitterStrategy } from 'passport-twitter';
-import { Strategy as OidcStrategy, Issuer as OIDCIssuer, custom } from 'openid-client';
 import { Profile, Strategy as SamlStrategy, VerifiedCallback } from 'passport-saml';
-import { BasicStrategy } from 'passport-http';
+import { Strategy as TwitterStrategy } from 'passport-twitter';
+import urljoin from 'url-join';
 
-import { IncomingMessage } from 'http';
-import axiosRetry from 'axios-retry';
-import pRetry from 'p-retry';
 import loggerFactory from '~/utils/logger';
 
 import S2sMessage from '../models/vo/s2s-message';
+
 import { S2sMessageHandlable } from './s2s-messaging/handlable';
 
 const logger = loggerFactory('growi:service:PassportService');