diff --git a/docs/de/user/admin/assets/administration-settings-general.png b/docs/de/user/admin/assets/administration-settings-general.png index bdf3fa828b..66ee64da36 100644 Binary files a/docs/de/user/admin/assets/administration-settings-general.png and b/docs/de/user/admin/assets/administration-settings-general.png differ diff --git a/docs/de/user/admin/settings.md b/docs/de/user/admin/settings.md index a093db4394..12c4873687 100644 --- a/docs/de/user/admin/settings.md +++ b/docs/de/user/admin/settings.md @@ -43,6 +43,9 @@ Die URL des RSS Release Feed des SCM-Managers. Darüber wird über die neue SCM- #### User converter Ist der Benutzer Konverter aktiviert, werden alle internen Benutzer beim Einloggen über ein externes System automatisch zu externen Benutzern konvertiert. Nach dem Konvertieren können sich die Benutzer nicht mehr mit dem lokalen SCM-Manager Passwort einloggen, sondern nur noch über das Fremdsystem. +#### Datei Suche +Die Dateisuche ermöglicht es Dateipfade in Repositories zu suchen. Bei sehr großen Repositories kann die Suche zu Speicherproblemen führen. In diesem Fall kann die Suchfunktion hier deaktiviert werden. + #### Fallback E-Mail Domain Name Dieser Domain Name wird genutzt, wenn für einen User eine E-Mail-Adresse benötigt wird, für den keine hinterlegt ist. Diese Domain wird nicht zum Versenden von E-Mails genutzt und auch keine anderweitige Verbindung aufgebaut. diff --git a/docs/en/user/admin/assets/administration-settings-general.png b/docs/en/user/admin/assets/administration-settings-general.png index 0026223639..09e3b99c83 100644 Binary files a/docs/en/user/admin/assets/administration-settings-general.png and b/docs/en/user/admin/assets/administration-settings-general.png differ diff --git a/docs/en/user/admin/settings.md b/docs/en/user/admin/settings.md index 19147475f3..1d83718161 100644 --- a/docs/en/user/admin/settings.md +++ b/docs/en/user/admin/settings.md @@ -39,9 +39,12 @@ Example: If anonymous access is enabled and the "_anonymous" user has full acces #### Release Feed Url The url of the RSS Release Feed for SCM-Manager. This provides up-to-date version information. To disable this feature just leave the url blank. -#### User converter +#### User Converter Internal users will automatically be converted to external on their first login using an external system. After conversion the users may only log in using the external system. +#### File Search +File paths can be searched inside repositories. For very big repositories, the search may lead to memory issues. In this case, the search function can be disabled here. + #### Fallback Mail Domain Name This domain name will be used to create email addresses for users without one when needed. It will not be used to send mails nor will be accessed otherwise. diff --git a/gradle/changelog/deactivate_file_search.yaml b/gradle/changelog/deactivate_file_search.yaml new file mode 100644 index 0000000000..6378235e20 --- /dev/null +++ b/gradle/changelog/deactivate_file_search.yaml @@ -0,0 +1,2 @@ +- type: added + description: Make file search deactivatable via global config diff --git a/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java b/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java index b676803d81..42373dd91b 100644 --- a/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java +++ b/scm-core/src/main/java/sonia/scm/config/ScmConfiguration.java @@ -221,6 +221,14 @@ public class ScmConfiguration implements Configuration { @XmlElement(name = "api-keys") private boolean enabledApiKeys = true; + /** + * Enables file search inside repositories. + * + * @since 2.45.0 + */ + @XmlElement(name = "file-search") + private boolean enabledFileSearch = true; + @XmlElement(name = "namespace-strategy") private String namespaceStrategy = "UsernameNamespaceStrategy"; @@ -500,6 +508,14 @@ public class ScmConfiguration implements Configuration { return enableProxy; } + /** + * Returns {@code true} if the repository file search is enabled. + * + * @return {@code true} if the api keys is enabled + * @since 2.45.0 + */ + public boolean isEnabledFileSearch() { return enabledFileSearch; } + public boolean isForceBaseUrl() { return forceBaseUrl; } @@ -711,6 +727,16 @@ public class ScmConfiguration implements Configuration { this.enabledApiKeys = enabledApiKeys; } + /** + * Set {@code true} to enable file search for repositories. + * + * @param enabledFileSearch {@code true} to enable file search for repositories + * @since 2.45.0 + */ + public void setEnabledFileSearch(boolean enabledFileSearch) { + this.enabledFileSearch = enabledFileSearch; + } + public void setNamespaceStrategy(String namespaceStrategy) { this.namespaceStrategy = namespaceStrategy; } diff --git a/scm-ui/ui-api/src/config.test.ts b/scm-ui/ui-api/src/config.test.ts index 604d9f9136..07e2986bd1 100644 --- a/scm-ui/ui-api/src/config.test.ts +++ b/scm-ui/ui-api/src/config.test.ts @@ -42,6 +42,7 @@ describe("Test config hooks", () => { enabledUserConverter: false, enabledXsrfProtection: false, enabledApiKeys: false, + enabledFileSearch: true, forceBaseUrl: false, loginAttemptLimit: 0, loginAttemptLimitTimeout: 0, @@ -62,9 +63,9 @@ describe("Test config hooks", () => { skipFailedAuthenticators: false, _links: { update: { - href: "/config" - } - } + href: "/config", + }, + }, }; afterEach(() => { @@ -77,7 +78,7 @@ describe("Test config hooks", () => { setIndexLink(queryClient, "config", "/config"); fetchMock.get("/api/v2/config", config); const { result, waitFor } = renderHook(() => useConfig(), { - wrapper: createWrapper(undefined, queryClient) + wrapper: createWrapper(undefined, queryClient), }); await waitFor(() => !!result.current.data); expect(result.current.data).toEqual(config); @@ -91,15 +92,15 @@ describe("Test config hooks", () => { const newConfig = { ...config, - baseUrl: "/hog" + baseUrl: "/hog", }; fetchMock.putOnce("/api/v2/config", { - status: 200 + status: 200, }); const { result, waitForNextUpdate } = renderHook(() => useUpdateConfig(), { - wrapper: createWrapper(undefined, queryClient) + wrapper: createWrapper(undefined, queryClient), }); await act(() => { diff --git a/scm-ui/ui-types/src/Config.ts b/scm-ui/ui-types/src/Config.ts index 8d94d83aa2..b26c1ec55d 100644 --- a/scm-ui/ui-types/src/Config.ts +++ b/scm-ui/ui-types/src/Config.ts @@ -54,4 +54,5 @@ export type Config = HalRepresentation & { mailDomainName: string; emergencyContacts: string[]; enabledApiKeys: boolean; + enabledFileSearch: boolean; }; diff --git a/scm-ui/ui-webapp/public/locales/de/config.json b/scm-ui/ui-webapp/public/locales/de/config.json index 9961a5f261..d2128a9a19 100644 --- a/scm-ui/ui-webapp/public/locales/de/config.json +++ b/scm-ui/ui-webapp/public/locales/de/config.json @@ -57,6 +57,9 @@ "login-attempt-limit": "Limit für Anmeldeversuche", "login-attempt-limit-timeout": "Timeout bei fehlgeschlagenen Anmeldeversuchen" }, + "function-settings": { + "name": "Funktionen" + }, "general-settings": { "realm-description": "Realm Beschreibung", "disable-grouping-grid": "Gruppen deaktivieren", @@ -74,6 +77,7 @@ "enabled-xsrf-protection": "XSRF Protection aktivieren", "enabled-user-converter": "Benutzer Konverter aktivieren", "enabled-api-keys": "API Schlüssel aktivieren", + "enabled-file-search": "Dateisuche aktivieren", "namespace-strategy": "Namespace Strategie", "login-info-url": "Login Info URL", "emergencyContacts": { @@ -110,6 +114,7 @@ "enableXsrfProtectionHelpText": "Xsrf Cookie Protection aktivieren. Hinweis: Dieses Feature befindet sich noch im Experimentalstatus.", "enabledUserConverterHelpText": "Benutzer Konverter aktivieren. Interne Benutzer werden beim Einloggen über ein Fremdsystem zu externen Benutzern konvertiert.", "enabledApiKeysHelpText": "API Schlüssel aktivieren. Alle Benutzer dürfen API Schlüssel als zusätzliche Methode zur Authentifizierung nutzen.", + "enabledFileSearchHelpText": "Dateisuche aktivieren. Dateipfade können innerhalb eines Repositories im Source Viewer gesucht werden.", "nameSpaceStrategyHelpText": "Strategie für Namespaces.", "loginInfoUrlHelpText": "URL zu der Login Information (Plugin und Feature Tipps auf der Login Seite). Um die Login Information zu deaktivieren, kann das Feld leer gelassen werden." } diff --git a/scm-ui/ui-webapp/public/locales/en/config.json b/scm-ui/ui-webapp/public/locales/en/config.json index b68d3684ee..437c5ae12c 100644 --- a/scm-ui/ui-webapp/public/locales/en/config.json +++ b/scm-ui/ui-webapp/public/locales/en/config.json @@ -57,6 +57,9 @@ "login-attempt-limit": "Login Attempt Limit", "login-attempt-limit-timeout": "Login Attempt Limit Timeout" }, + "function-settings": { + "name": "Functions" + }, "general-settings": { "realm-description": "Realm Description", "disable-grouping-grid": "Disable Grouping Grid", @@ -74,6 +77,7 @@ "enabled-xsrf-protection": "Enabled XSRF Protection", "enabled-user-converter": "Enabled User Converter", "enabled-api-keys": "Enabled API Keys", + "enabled-file-search": "Enabled File Search", "namespace-strategy": "Namespace Strategy", "login-info-url": "Login Info URL", "emergencyContacts": { @@ -110,6 +114,7 @@ "enableXsrfProtectionHelpText": "Enable XSRF Cookie Protection. Note: This feature is still experimental.", "enabledUserConverterHelpText": "Enable User Converter. Internal users will automatically be converted to external on their first login using an external system.", "enabledApiKeysHelpText": "Enable API Keys. API Keys can be used as additional authentication method by every user.", + "enabledFileSearchHelpText": "Enable file search. File paths can be searched inside a single repository on the source viewer.", "nameSpaceStrategyHelpText": "The namespace strategy.", "loginInfoUrlHelpText": "URL to login information (plugin and feature tips at login page). If this is omitted, no login information will be displayed." } diff --git a/scm-ui/ui-webapp/src/admin/components/form/BaseUrlSettings.tsx b/scm-ui/ui-webapp/src/admin/components/form/BaseUrlSettings.tsx index 72e8866588..fe78f8a963 100644 --- a/scm-ui/ui-webapp/src/admin/components/form/BaseUrlSettings.tsx +++ b/scm-ui/ui-webapp/src/admin/components/form/BaseUrlSettings.tsx @@ -38,10 +38,10 @@ class BaseUrlSettings extends React.Component { const { t, baseUrl, forceBaseUrl, hasUpdatePermission } = this.props; return ( -
+ <>
-
+
{ />
-
+ ); } diff --git a/scm-ui/ui-webapp/src/admin/components/form/ConfigForm.tsx b/scm-ui/ui-webapp/src/admin/components/form/ConfigForm.tsx index 63f55a2fa4..ed28589d05 100644 --- a/scm-ui/ui-webapp/src/admin/components/form/ConfigForm.tsx +++ b/scm-ui/ui-webapp/src/admin/components/form/ConfigForm.tsx @@ -30,6 +30,7 @@ import GeneralSettings from "./GeneralSettings"; import BaseUrlSettings from "./BaseUrlSettings"; import LoginAttempt from "./LoginAttempt"; import PluginSettings from "./PluginSettings"; +import FunctionSettings from "./FunctionSettings"; type Props = { submitForm: (p: Config) => void; @@ -46,7 +47,7 @@ const ConfigForm: FC = ({ loading, configReadPermission, configUpdatePermission, - namespaceStrategies + namespaceStrategies, }) => { const [t] = useTranslation("config"); const [innerConfig, setInnerConfig] = useState({ @@ -77,7 +78,7 @@ const ConfigForm: FC = ({ mailDomainName: "", emergencyContacts: [], enabledApiKeys: true, - _links: {} + _links: {}, }); const [showNotification, setShowNotification] = useState(false); const [changed, setChanged] = useState(false); @@ -86,7 +87,7 @@ const ConfigForm: FC = ({ loginAttemptLimit: boolean; }>({ loginAttemptLimitTimeout: false, - loginAttemptLimit: false + loginAttemptLimit: false, }); useEffect(() => { @@ -149,14 +150,20 @@ const ConfigForm: FC = ({ releaseFeedUrl={innerConfig.releaseFeedUrl} mailDomainName={innerConfig.mailDomainName} enabledXsrfProtection={innerConfig.enabledXsrfProtection} - enabledUserConverter={innerConfig.enabledUserConverter} - enabledApiKeys={innerConfig.enabledApiKeys} emergencyContacts={innerConfig.emergencyContacts} namespaceStrategy={innerConfig.namespaceStrategy} onChange={onChange} hasUpdatePermission={configUpdatePermission} />
+ +
= ({ + enabledFileSearch, + enabledUserConverter, + enabledApiKeys, + onChange, + hasUpdatePermission, +}) => { + const { t } = useTranslation("config"); + + const handleEnabledApiKeysChange = (value: boolean) => { + onChange(true, value, "enabledApiKeys"); + }; + const handleEnabledUserConverterChange = (value: boolean) => { + onChange(true, value, "enabledUserConverter"); + }; + const handleEnabledFileSearchChange = (value: boolean) => { + onChange(true, value, "enabledFileSearch"); + }; + + return ( + <> + +
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+ + ); +}; + +export default FunctionSettings; diff --git a/scm-ui/ui-webapp/src/admin/components/form/GeneralSettings.tsx b/scm-ui/ui-webapp/src/admin/components/form/GeneralSettings.tsx index ec9cb73369..14a466f259 100644 --- a/scm-ui/ui-webapp/src/admin/components/form/GeneralSettings.tsx +++ b/scm-ui/ui-webapp/src/admin/components/form/GeneralSettings.tsx @@ -41,8 +41,6 @@ type Props = { releaseFeedUrl: string; mailDomainName: string; enabledXsrfProtection: boolean; - enabledUserConverter: boolean; - enabledApiKeys: boolean; emergencyContacts: string[]; namespaceStrategy: string; namespaceStrategies?: NamespaceStrategies; @@ -58,8 +56,6 @@ const GeneralSettings: FC = ({ releaseFeedUrl, mailDomainName, enabledXsrfProtection, - enabledUserConverter, - enabledApiKeys, emergencyContacts, namespaceStrategy, namespaceStrategies, @@ -79,9 +75,6 @@ const GeneralSettings: FC = ({ const handleEnabledXsrfProtectionChange = (value: boolean) => { onChange(true, value, "enabledXsrfProtection"); }; - const handleEnabledUserConverterChange = (value: boolean) => { - onChange(true, value, "enabledUserConverter"); - }; const handleAnonymousMode = (value: string) => { onChange(true, value as AnonymousMode, "anonymousMode"); }; @@ -97,9 +90,6 @@ const GeneralSettings: FC = ({ const handleMailDomainNameChange = (value: string) => { onChange(true, value, "mailDomainName"); }; - const handleEnabledApiKeysChange = (value: boolean) => { - onChange(true, value, "enabledApiKeys"); - }; const handleEmergencyContactsChange = (p: Option[]) => { onChange( true, @@ -111,7 +101,7 @@ const GeneralSettings: FC = ({ return (
-
+
= ({ helpText={t("help.realmDescriptionHelpText")} />
-
+
+
+
= ({
-
+
= ({ helpText={t("help.loginInfoUrlHelpText")} />
-
+
+
+
= ({
-
+