From 9132bee89f94724b4f05595f1a3f86283eb4016b Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 13 Dec 2023 22:52:01 +0100 Subject: [PATCH 01/10] New team feature EnforceFileDownloadLocation. --- libs/galley-types/src/Galley/Types/Teams.hs | 9 +++- .../test/unit/Test/Galley/Types.hs | 1 + .../src/Wire/API/Routes/Internal/Galley.hs | 5 ++ .../Wire/API/Routes/Public/Galley/Feature.hs | 2 + libs/wire-api/src/Wire/API/Team/Feature.hs | 48 ++++++++++++++++--- services/galley/galley.cabal | 1 + services/galley/src/Galley/API/Internal.hs | 4 ++ .../galley/src/Galley/API/Public/Feature.hs | 2 + .../galley/src/Galley/API/Teams/Features.hs | 2 + .../src/Galley/API/Teams/Features/Get.hs | 13 ++++- .../src/Galley/Cassandra/TeamFeatures.hs | 13 +++++ .../V90_EnforceFileDownloadLocationConfig.hs | 35 ++++++++++++++ .../test/integration/API/Teams/Feature.hs | 11 ++++- 13 files changed, 134 insertions(+), 12 deletions(-) create mode 100644 services/galley/src/Galley/Schema/V90_EnforceFileDownloadLocationConfig.hs diff --git a/libs/galley-types/src/Galley/Types/Teams.hs b/libs/galley-types/src/Galley/Types/Teams.hs index e77b04951b..800f1e53b4 100644 --- a/libs/galley-types/src/Galley/Types/Teams.hs +++ b/libs/galley-types/src/Galley/Types/Teams.hs @@ -42,6 +42,7 @@ module Galley.Types.Teams flagMLS, flagMlsE2EId, flagMlsMigration, + flagEnforceFileDownloadLocation, Defaults (..), ImplicitLockStatus (..), unImplicitLockStatus, @@ -165,7 +166,8 @@ data FeatureFlags = FeatureFlags _flagMLS :: !(Defaults (WithStatus MLSConfig)), _flagOutlookCalIntegration :: !(Defaults (WithStatus OutlookCalIntegrationConfig)), _flagMlsE2EId :: !(Defaults (WithStatus MlsE2EIdConfig)), - _flagMlsMigration :: !(Defaults (WithStatus MlsMigrationConfig)) + _flagMlsMigration :: !(Defaults (WithStatus MlsMigrationConfig)), + _flagEnforceFileDownloadLocation :: !(Defaults (WithStatus EnforceFileDownloadLocationConfig)) } deriving (Eq, Show, Generic) @@ -218,6 +220,7 @@ instance FromJSON FeatureFlags where <*> (fromMaybe (Defaults (defFeatureStatus @OutlookCalIntegrationConfig)) <$> (obj .:? "outlookCalIntegration")) <*> (fromMaybe (Defaults (defFeatureStatus @MlsE2EIdConfig)) <$> (obj .:? "mlsE2EId")) <*> (fromMaybe (Defaults (defFeatureStatus @MlsMigrationConfig)) <$> (obj .:? "mlsMigration")) + <*> (fromMaybe (Defaults (defFeatureStatus @EnforceFileDownloadLocationConfig)) <$> (obj .:? "enforceFileDownloadLocation")) where withImplicitLockStatusOrDefault :: forall cfg. (IsFeatureConfig cfg, Schema.ToSchema cfg) => Object -> Key -> A.Parser (Defaults (ImplicitLockStatus cfg)) withImplicitLockStatusOrDefault obj fieldName = fromMaybe (Defaults (ImplicitLockStatus (defFeatureStatus @cfg))) <$> obj .:? fieldName @@ -241,6 +244,7 @@ instance ToJSON FeatureFlags where outlookCalIntegration mlsE2EId mlsMigration + enforceFileDownloadLocation ) = object [ "sso" .= sso, @@ -258,7 +262,8 @@ instance ToJSON FeatureFlags where "mls" .= mls, "outlookCalIntegration" .= outlookCalIntegration, "mlsE2EId" .= mlsE2EId, - "mlsMigration" .= mlsMigration + "mlsMigration" .= mlsMigration, + "enforceFileDownloadLocation" .= enforceFileDownloadLocation ] instance FromJSON FeatureSSO where diff --git a/libs/galley-types/test/unit/Test/Galley/Types.hs b/libs/galley-types/test/unit/Test/Galley/Types.hs index dc58b44845..1e6c740d01 100644 --- a/libs/galley-types/test/unit/Test/Galley/Types.hs +++ b/libs/galley-types/test/unit/Test/Galley/Types.hs @@ -99,6 +99,7 @@ instance Arbitrary FeatureFlags where <*> arbitrary <*> arbitrary <*> arbitrary + <*> arbitrary where unlocked :: ImplicitLockStatus a -> ImplicitLockStatus a unlocked = ImplicitLockStatus . Public.setLockStatus Public.LockStatusUnlocked . _unImplicitLockStatus diff --git a/libs/wire-api/src/Wire/API/Routes/Internal/Galley.hs b/libs/wire-api/src/Wire/API/Routes/Internal/Galley.hs index 32aad3997e..5998cb5f88 100644 --- a/libs/wire-api/src/Wire/API/Routes/Internal/Galley.hs +++ b/libs/wire-api/src/Wire/API/Routes/Internal/Galley.hs @@ -160,6 +160,11 @@ type IFeatureAPI = :<|> IFeatureStatusPut '[] '() MlsMigrationConfig :<|> IFeatureStatusPatch '[] '() MlsMigrationConfig :<|> IFeatureStatusLockStatusPut MlsMigrationConfig + -- EnforceFileDownloadLocationConfig + :<|> IFeatureStatusGet EnforceFileDownloadLocationConfig + :<|> IFeatureStatusPut '[] '() EnforceFileDownloadLocationConfig + :<|> IFeatureStatusPatch '[] '() EnforceFileDownloadLocationConfig + :<|> IFeatureStatusLockStatusPut EnforceFileDownloadLocationConfig -- all feature configs :<|> Named "feature-configs-internal" diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Galley/Feature.hs b/libs/wire-api/src/Wire/API/Routes/Public/Galley/Feature.hs index a59144b926..3bbaa1cb9b 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Galley/Feature.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Galley/Feature.hs @@ -91,6 +91,8 @@ type FeatureAPI = :<|> From 'V5 ::> FeatureStatusPut '[] '() MlsE2EIdConfig :<|> From 'V5 ::> FeatureStatusGet MlsMigrationConfig :<|> From 'V5 ::> FeatureStatusPut '[] '() MlsMigrationConfig + :<|> From 'V5 ::> FeatureStatusGet EnforceFileDownloadLocationConfig + :<|> From 'V5 ::> FeatureStatusPut '[] '() EnforceFileDownloadLocationConfig :<|> AllFeatureConfigsUserGet :<|> AllFeatureConfigsTeamGet :<|> FeatureConfigDeprecatedGet "The usage of this endpoint was removed in iOS in version 3.101. It is not used by team management, or webapp, and is potentially used by the old Android client as of June 2022" LegalholdConfig diff --git a/libs/wire-api/src/Wire/API/Team/Feature.hs b/libs/wire-api/src/Wire/API/Team/Feature.hs index 7f47a1596f..5c8357c343 100644 --- a/libs/wire-api/src/Wire/API/Team/Feature.hs +++ b/libs/wire-api/src/Wire/API/Team/Feature.hs @@ -81,6 +81,7 @@ module Wire.API.Team.Feature OutlookCalIntegrationConfig (..), MlsE2EIdConfig (..), MlsMigrationConfig (..), + EnforceFileDownloadLocationConfig (..), AllFeatureConfigs (..), unImplicitLockStatus, ImplicitLockStatus (..), @@ -112,6 +113,7 @@ import Deriving.Aeson import GHC.TypeLits import Imports import Servant (FromHttpApiData (..), ToHttpApiData (..)) +import Test.QuickCheck (getPrintableString) import Test.QuickCheck.Arbitrary (arbitrary) import Test.QuickCheck.Gen (suchThat) import Wire.API.Conversation.Protocol @@ -128,11 +130,11 @@ import Wire.Arbitrary (Arbitrary, GenericUniform (..)) -- **Config**. If your feature doesn't have a config besides -- being enabled/disabled, locked/unlocked, then the config should be a unit -- type, e.g. **data MyFeatureConfig = MyFeatureConfig**. Add a singleton for --- the new data type. Implement type classes 'ToSchema', 'IsFeatureConfig' and --- 'Arbitrary'. If your feature doesn't have a config implement --- 'FeatureTrivialConfig'. +-- the new data type. Implement type classes 'RenderableSymbol', 'ToSchema', +-- 'IsFeatureConfig' and 'Arbitrary'. If your feature doesn't have a config +-- implement 'FeatureTrivialConfig'. -- --- 2. Add the config to to 'AllFeatureConfigs'. +-- 2. Add the config to 'AllFeatureConfigs'. -- -- 3. If your feature is configurable on a per-team basis, add a schema -- migration in galley and extend 'getFeatureStatus' and similar functions in @@ -147,7 +149,7 @@ import Wire.Arbitrary (Arbitrary, GenericUniform (..)) -- and setting (with side-effects). Note that we don't have to check the -- lockstatus inside 'setConfigForTeam' because the lockstatus is checked in -- 'setFeatureStatus' before which is the public API for setting the feature --- status. Also extend FeaturePersistentAllFeatures. +-- status. -- -- 6. Add public routes to Wire.API.Routes.Public.Galley.Feature: -- 'FeatureStatusGet', 'FeatureStatusPut' (optional). Then implement them in @@ -172,7 +174,9 @@ import Wire.Arbitrary (Arbitrary, GenericUniform (..)) -- - add the defaults to 'charts/galley/values.yaml' -- - optionally add config for CI to 'hack/helm_vars/wire-server/values.yaml' -- --- 12. Add a section to the documentation at an appropriate place (e.g. 'docs/src/developer/reference/config-options.md' or 'docs/src/understand/team-feature-settings.md') +-- 12. Add a section to the documentation at an appropriate place +-- (e.g. 'docs/src/developer/reference/config-options.md' or +-- 'docs/src/understand/team-feature-settings.md') class IsFeatureConfig cfg where type FeatureSymbol cfg :: Symbol defFeatureStatus :: WithStatus cfg @@ -203,6 +207,7 @@ data FeatureSingleton cfg where FeatureSingletonOutlookCalIntegrationConfig :: FeatureSingleton OutlookCalIntegrationConfig FeatureSingletonMlsE2EIdConfig :: FeatureSingleton MlsE2EIdConfig FeatureSingletonMlsMigration :: FeatureSingleton MlsMigrationConfig + FeatureSingletonEnforceFileDownloadLocation :: FeatureSingleton EnforceFileDownloadLocationConfig class FeatureTrivialConfig cfg where trivialConfig :: cfg @@ -1084,6 +1089,32 @@ instance IsFeatureConfig MlsMigrationConfig where featureSingleton = FeatureSingletonMlsMigration objectSchema = field "config" schema +---------------------------------------------------------------------- +-- EnforceFileDownloadLocationConfig + +data EnforceFileDownloadLocationConfig = EnforceFileDownloadLocationConfig + { enforcedDownloadLocation :: Text + } + deriving stock (Eq, Show, Generic) + +instance RenderableSymbol EnforceFileDownloadLocationConfig where + renderSymbol = "EnforceFileDownloadLocationConfig" + +instance Arbitrary EnforceFileDownloadLocationConfig where + arbitrary = EnforceFileDownloadLocationConfig . cs . getPrintableString <$> arbitrary + +instance ToSchema EnforceFileDownloadLocationConfig where + schema = + object "EnforceFileDownloadLocation" $ + EnforceFileDownloadLocationConfig + <$> enforcedDownloadLocation .= field "enforcedDownloadLocation" schema + +instance IsFeatureConfig EnforceFileDownloadLocationConfig where + type FeatureSymbol EnforceFileDownloadLocationConfig = "enforceFileDownloadLocation" + defFeatureStatus = withStatus FeatureStatusDisabled LockStatusLocked (EnforceFileDownloadLocationConfig "") FeatureTTLUnlimited + featureSingleton = FeatureSingletonEnforceFileDownloadLocation + objectSchema = field "config" schema + ---------------------------------------------------------------------- -- FeatureStatus @@ -1161,7 +1192,8 @@ data AllFeatureConfigs = AllFeatureConfigs afcExposeInvitationURLsToTeamAdmin :: WithStatus ExposeInvitationURLsToTeamAdminConfig, afcOutlookCalIntegration :: WithStatus OutlookCalIntegrationConfig, afcMlsE2EId :: WithStatus MlsE2EIdConfig, - afcMlsMigration :: WithStatus MlsMigrationConfig + afcMlsMigration :: WithStatus MlsMigrationConfig, + afcEnforceFileDownloadLocation :: WithStatus EnforceFileDownloadLocationConfig } deriving stock (Eq, Show) deriving (FromJSON, ToJSON, S.ToSchema) via (Schema AllFeatureConfigs) @@ -1188,6 +1220,7 @@ instance ToSchema AllFeatureConfigs where <*> afcOutlookCalIntegration .= featureField <*> afcMlsE2EId .= featureField <*> afcMlsMigration .= featureField + <*> afcEnforceFileDownloadLocation .= featureField where featureField :: forall cfg. @@ -1216,5 +1249,6 @@ instance Arbitrary AllFeatureConfigs where <*> arbitrary <*> arbitrary <*> arbitrary + <*> arbitrary makeLenses ''ImplicitLockStatus diff --git a/services/galley/galley.cabal b/services/galley/galley.cabal index 6d63451aed..8561169ce0 100644 --- a/services/galley/galley.cabal +++ b/services/galley/galley.cabal @@ -274,6 +274,7 @@ library Galley.Schema.V87_TeamFeatureSupportedProtocols Galley.Schema.V88_RemoveMemberClientAndTruncateMLSGroupMemberClient Galley.Schema.V89_MlsLockStatus + Galley.Schema.V90_EnforceFileDownloadLocationConfig Galley.Types.Clients Galley.Types.ToUserRole Galley.Types.UserList diff --git a/services/galley/src/Galley/API/Internal.hs b/services/galley/src/Galley/API/Internal.hs index 9d58f182d4..7f3bcf4de4 100644 --- a/services/galley/src/Galley/API/Internal.hs +++ b/services/galley/src/Galley/API/Internal.hs @@ -235,6 +235,10 @@ featureAPI = <@> mkNamedAPI @'("iput", MlsMigrationConfig) setFeatureStatusInternal <@> mkNamedAPI @'("ipatch", MlsMigrationConfig) patchFeatureStatusInternal <@> mkNamedAPI @'("ilock", MlsMigrationConfig) (updateLockStatus @MlsMigrationConfig) + <@> mkNamedAPI @'("iget", EnforceFileDownloadLocationConfig) (getFeatureStatus DontDoAuth) + <@> mkNamedAPI @'("iput", EnforceFileDownloadLocationConfig) setFeatureStatusInternal + <@> mkNamedAPI @'("ipatch", EnforceFileDownloadLocationConfig) patchFeatureStatusInternal + <@> mkNamedAPI @'("ilock", EnforceFileDownloadLocationConfig) (updateLockStatus @EnforceFileDownloadLocationConfig) <@> mkNamedAPI @"feature-configs-internal" (maybe getAllFeatureConfigsForServer getAllFeatureConfigsForUser) waiInternalSitemap :: Routes a (Sem GalleyEffects) () diff --git a/services/galley/src/Galley/API/Public/Feature.hs b/services/galley/src/Galley/API/Public/Feature.hs index 20ad5e4bef..f2d2cd19e2 100644 --- a/services/galley/src/Galley/API/Public/Feature.hs +++ b/services/galley/src/Galley/API/Public/Feature.hs @@ -65,6 +65,8 @@ featureAPI = <@> mkNamedAPI @'("put", MlsE2EIdConfig) (setFeatureStatus . DoAuth) <@> mkNamedAPI @'("get", MlsMigrationConfig) (getFeatureStatus . DoAuth) <@> mkNamedAPI @'("put", MlsMigrationConfig) (setFeatureStatus . DoAuth) + <@> mkNamedAPI @'("get", EnforceFileDownloadLocationConfig) (getFeatureStatus . DoAuth) + <@> mkNamedAPI @'("put", EnforceFileDownloadLocationConfig) (setFeatureStatus . DoAuth) <@> mkNamedAPI @"get-all-feature-configs-for-user" getAllFeatureConfigsForUser <@> mkNamedAPI @"get-all-feature-configs-for-team" getAllFeatureConfigsForTeam <@> mkNamedAPI @'("get-config", LegalholdConfig) getFeatureStatusForUser diff --git a/services/galley/src/Galley/API/Teams/Features.hs b/services/galley/src/Galley/API/Teams/Features.hs index 546365d456..56e6ea7168 100644 --- a/services/galley/src/Galley/API/Teams/Features.hs +++ b/services/galley/src/Galley/API/Teams/Features.hs @@ -393,3 +393,5 @@ instance SetFeatureConfig MlsMigrationConfig where ) $ throw MLSProtocolMismatch persistAndPushEvent tid wsnl + +instance SetFeatureConfig EnforceFileDownloadLocationConfig diff --git a/services/galley/src/Galley/API/Teams/Features/Get.hs b/services/galley/src/Galley/API/Teams/Features/Get.hs index 1bdecdd78b..d9525c1386 100644 --- a/services/galley/src/Galley/API/Teams/Features/Get.hs +++ b/services/galley/src/Galley/API/Teams/Features/Get.hs @@ -238,6 +238,7 @@ getAllFeatureConfigsForServer = <*> getConfigForServer @OutlookCalIntegrationConfig <*> getConfigForServer @MlsE2EIdConfig <*> getConfigForServer @MlsMigrationConfig + <*> getConfigForServer @EnforceFileDownloadLocationConfig getAllFeatureConfigsUser :: forall r. @@ -272,6 +273,7 @@ getAllFeatureConfigsUser uid = <*> getConfigForUser @OutlookCalIntegrationConfig uid <*> getConfigForUser @MlsE2EIdConfig uid <*> getConfigForUser @MlsMigrationConfig uid + <*> getConfigForUser @EnforceFileDownloadLocationConfig uid getAllFeatureConfigsTeam :: forall r. @@ -302,6 +304,7 @@ getAllFeatureConfigsTeam tid = <*> getConfigForTeam @OutlookCalIntegrationConfig tid <*> getConfigForTeam @MlsE2EIdConfig tid <*> getConfigForTeam @MlsMigrationConfig tid + <*> getConfigForTeam @EnforceFileDownloadLocationConfig tid -- | Note: this is an internal function which doesn't cover all features, e.g. LegalholdConfig genericGetConfigForTeam :: @@ -490,8 +493,14 @@ instance GetFeatureConfig MlsMigrationConfig where getConfigForServer = input <&> view (settings . featureFlags . flagMlsMigration . unDefaults) --- -- | If second factor auth is enabled, make sure that end-points that don't support it, but should, are blocked completely. (This is a workaround until we have 2FA for those end-points as well.) --- -- +instance GetFeatureConfig EnforceFileDownloadLocationConfig where + getConfigForServer = + input <&> view (settings . featureFlags . flagEnforceFileDownloadLocation . unDefaults) + +-- | If second factor auth is enabled, make sure that end-points that don't support it, but +-- should, are blocked completely. (This is a workaround until we have 2FA for those +-- end-points as well.) +-- -- This function exists to resolve a cyclic dependency. guardSecondFactorDisabled :: forall r a. diff --git a/services/galley/src/Galley/Cassandra/TeamFeatures.hs b/services/galley/src/Galley/Cassandra/TeamFeatures.hs index d9db6f3389..449654e29c 100644 --- a/services/galley/src/Galley/Cassandra/TeamFeatures.hs +++ b/services/galley/src/Galley/Cassandra/TeamFeatures.hs @@ -159,6 +159,16 @@ getFeatureConfig FeatureSingletonMlsMigration tid = do select = "select mls_migration_status, mls_migration_start_time, mls_migration_finalise_regardless_after from team_features where team_id = ?" getFeatureConfig FeatureSingletonExposeInvitationURLsToTeamAdminConfig tid = getTrivialConfigC "expose_invitation_urls_to_team_admin" tid getFeatureConfig FeatureSingletonOutlookCalIntegrationConfig tid = getTrivialConfigC "outlook_cal_integration_status" tid +getFeatureConfig FeatureSingletonEnforceFileDownloadLocation tid = do + let q = query1 select (params LocalQuorum (Identity tid)) + retry x1 q <&> \case + Nothing -> Nothing + Just (Nothing, _) -> Nothing + Just (Just fs, mbLocation) -> + Just $ WithStatusNoLock fs (EnforceFileDownloadLocationConfig $ fromMaybe "" mbLocation) FeatureTTLUnlimited + where + select :: PrepQuery R (Identity TeamId) (Maybe FeatureStatus, Maybe Text) + select = "select enforce_file_download_location_status, enforce_file_download_location from team_features where team_id = ?" setFeatureConfig :: MonadClient m => FeatureSingleton cfg -> TeamId -> WithStatusNoLock cfg -> m () setFeatureConfig FeatureSingletonLegalholdConfig tid statusNoLock = setFeatureStatusC "legalhold_status" tid (wssStatus statusNoLock) @@ -246,6 +256,7 @@ setFeatureConfig FeatureSingletonMlsMigration tid status = do "insert into team_features (team_id, mls_migration_status, mls_migration_start_time, mls_migration_finalise_regardless_after) values (?, ?, ?, ?)" setFeatureConfig FeatureSingletonExposeInvitationURLsToTeamAdminConfig tid statusNoLock = setFeatureStatusC "expose_invitation_urls_to_team_admin" tid (wssStatus statusNoLock) setFeatureConfig FeatureSingletonOutlookCalIntegrationConfig tid statusNoLock = setFeatureStatusC "outlook_cal_integration_status" tid (wssStatus statusNoLock) +setFeatureConfig FeatureSingletonEnforceFileDownloadLocation tid statusNoLock = undefined getFeatureLockStatus :: MonadClient m => FeatureSingleton cfg -> TeamId -> m (Maybe LockStatus) getFeatureLockStatus FeatureSingletonFileSharingConfig tid = getLockStatusC "file_sharing_lock_status" tid @@ -256,6 +267,7 @@ getFeatureLockStatus FeatureSingletonMlsE2EIdConfig tid = getLockStatusC "mls_e2 getFeatureLockStatus FeatureSingletonMlsMigration tid = getLockStatusC "mls_migration_lock_status" tid getFeatureLockStatus FeatureSingletonOutlookCalIntegrationConfig tid = getLockStatusC "outlook_cal_integration_lock_status" tid getFeatureLockStatus FeatureSingletonMLSConfig tid = getLockStatusC "mls_lock_status" tid +getFeatureLockStatus FeatureSingletonEnforceFileDownloadLocation tid = undefined getFeatureLockStatus _ _ = pure Nothing setFeatureLockStatus :: MonadClient m => FeatureSingleton cfg -> TeamId -> LockStatus -> m () @@ -267,6 +279,7 @@ setFeatureLockStatus FeatureSingletonMlsE2EIdConfig tid status = setLockStatusC setFeatureLockStatus FeatureSingletonMlsMigration tid status = setLockStatusC "mls_migration_lock_status" tid status setFeatureLockStatus FeatureSingletonOutlookCalIntegrationConfig tid status = setLockStatusC "outlook_cal_integration_lock_status" tid status setFeatureLockStatus FeatureSingletonMLSConfig tid status = setLockStatusC "mls_lock_status" tid status +setFeatureLockStatus FeatureSingletonEnforceFileDownloadLocation tid status = undefined setFeatureLockStatus _ _tid _status = pure () getTrivialConfigC :: diff --git a/services/galley/src/Galley/Schema/V90_EnforceFileDownloadLocationConfig.hs b/services/galley/src/Galley/Schema/V90_EnforceFileDownloadLocationConfig.hs new file mode 100644 index 0000000000..b55842de72 --- /dev/null +++ b/services/galley/src/Galley/Schema/V90_EnforceFileDownloadLocationConfig.hs @@ -0,0 +1,35 @@ +-- This file is part of the Wire Server implementation. +-- +-- Copyright (C) 2023 Wire Swiss GmbH +-- +-- This program is free software: you can redistribute it and/or modify it under +-- the terms of the GNU Affero General Public License as published by the Free +-- Software Foundation, either version 3 of the License, or (at your option) any +-- later version. +-- +-- This program is distributed in the hope that it will be useful, but WITHOUT +-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +-- details. +-- +-- You should have received a copy of the GNU Affero General Public License along +-- with this program. If not, see . +module Galley.Schema.V90_EnforceFileDownloadLocationConfig + ( migration, + ) +where + +import Cassandra.Schema +import Imports +import Text.RawString.QQ + +migration :: Migration +migration = + Migration 90 "Add fields for EnforceFileDownloadLocationConfig" $ + schema' + [r| ALTER TABLE team_features ADD ( + enforce_file_download_location_lock_status int, + enforce_file_download_location_status int, + enforce_file_download_location text + ) + |] diff --git a/services/galley/test/integration/API/Teams/Feature.hs b/services/galley/test/integration/API/Teams/Feature.hs index dbfed7255e..76da749103 100644 --- a/services/galley/test/integration/API/Teams/Feature.hs +++ b/services/galley/test/integration/API/Teams/Feature.hs @@ -1057,7 +1057,8 @@ testAllFeatures = do afcExposeInvitationURLsToTeamAdmin = withStatus FeatureStatusDisabled LockStatusLocked ExposeInvitationURLsToTeamAdminConfig FeatureTTLUnlimited, afcOutlookCalIntegration = withStatus FeatureStatusDisabled LockStatusLocked OutlookCalIntegrationConfig FeatureTTLUnlimited, afcMlsE2EId = withStatus FeatureStatusDisabled LockStatusUnlocked (wsConfig defFeatureStatus) FeatureTTLUnlimited, - afcMlsMigration = defaultMlsMigrationConfig + afcMlsMigration = defaultMlsMigrationConfig, + afcEnforceFileDownloadLocation = defaultEnforceFileDownloadLocationConfig } testFeatureConfigConsistency :: TestM () @@ -1534,3 +1535,11 @@ defaultMlsMigrationConfig = finaliseRegardlessAfter = fmap fromUTCTimeMillis (readUTCTimeMillis "2029-10-17T00:00:00.000Z") } FeatureTTLUnlimited + +defaultEnforceFileDownloadLocationConfig :: WithStatus EnforceFileDownloadLocationConfig +defaultEnforceFileDownloadLocationConfig = + withStatus + FeatureStatusDisabled + LockStatusLocked + (EnforceFileDownloadLocationConfig "*") + FeatureTTLUnlimited From a8102f497db41a3d69d7046c141a682af03fc35e Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Tue, 2 Jan 2024 11:09:43 +0100 Subject: [PATCH 02/10] Make path option a Maybe. Implement feature setters, getters. --- libs/wire-api/src/Wire/API/Team/Feature.hs | 8 ++++---- .../galley/src/Galley/Cassandra/TeamFeatures.hs | 16 ++++++++++++---- .../galley/test/integration/API/Teams/Feature.hs | 2 +- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Team/Feature.hs b/libs/wire-api/src/Wire/API/Team/Feature.hs index 5c8357c343..9cfc54f56f 100644 --- a/libs/wire-api/src/Wire/API/Team/Feature.hs +++ b/libs/wire-api/src/Wire/API/Team/Feature.hs @@ -1093,7 +1093,7 @@ instance IsFeatureConfig MlsMigrationConfig where -- EnforceFileDownloadLocationConfig data EnforceFileDownloadLocationConfig = EnforceFileDownloadLocationConfig - { enforcedDownloadLocation :: Text + { enforcedDownloadLocation :: Maybe Text } deriving stock (Eq, Show, Generic) @@ -1101,17 +1101,17 @@ instance RenderableSymbol EnforceFileDownloadLocationConfig where renderSymbol = "EnforceFileDownloadLocationConfig" instance Arbitrary EnforceFileDownloadLocationConfig where - arbitrary = EnforceFileDownloadLocationConfig . cs . getPrintableString <$> arbitrary + arbitrary = EnforceFileDownloadLocationConfig . fmap (cs . getPrintableString) <$> arbitrary instance ToSchema EnforceFileDownloadLocationConfig where schema = object "EnforceFileDownloadLocation" $ EnforceFileDownloadLocationConfig - <$> enforcedDownloadLocation .= field "enforcedDownloadLocation" schema + <$> enforcedDownloadLocation .= maybe_ (optField "enforcedDownloadLocation" schema) instance IsFeatureConfig EnforceFileDownloadLocationConfig where type FeatureSymbol EnforceFileDownloadLocationConfig = "enforceFileDownloadLocation" - defFeatureStatus = withStatus FeatureStatusDisabled LockStatusLocked (EnforceFileDownloadLocationConfig "") FeatureTTLUnlimited + defFeatureStatus = withStatus FeatureStatusDisabled LockStatusLocked (EnforceFileDownloadLocationConfig Nothing) FeatureTTLUnlimited featureSingleton = FeatureSingletonEnforceFileDownloadLocation objectSchema = field "config" schema diff --git a/services/galley/src/Galley/Cassandra/TeamFeatures.hs b/services/galley/src/Galley/Cassandra/TeamFeatures.hs index 449654e29c..4ed5cbd581 100644 --- a/services/galley/src/Galley/Cassandra/TeamFeatures.hs +++ b/services/galley/src/Galley/Cassandra/TeamFeatures.hs @@ -165,7 +165,7 @@ getFeatureConfig FeatureSingletonEnforceFileDownloadLocation tid = do Nothing -> Nothing Just (Nothing, _) -> Nothing Just (Just fs, mbLocation) -> - Just $ WithStatusNoLock fs (EnforceFileDownloadLocationConfig $ fromMaybe "" mbLocation) FeatureTTLUnlimited + Just $ WithStatusNoLock fs (EnforceFileDownloadLocationConfig mbLocation) FeatureTTLUnlimited where select :: PrepQuery R (Identity TeamId) (Maybe FeatureStatus, Maybe Text) select = "select enforce_file_download_location_status, enforce_file_download_location from team_features where team_id = ?" @@ -256,7 +256,15 @@ setFeatureConfig FeatureSingletonMlsMigration tid status = do "insert into team_features (team_id, mls_migration_status, mls_migration_start_time, mls_migration_finalise_regardless_after) values (?, ?, ?, ?)" setFeatureConfig FeatureSingletonExposeInvitationURLsToTeamAdminConfig tid statusNoLock = setFeatureStatusC "expose_invitation_urls_to_team_admin" tid (wssStatus statusNoLock) setFeatureConfig FeatureSingletonOutlookCalIntegrationConfig tid statusNoLock = setFeatureStatusC "outlook_cal_integration_status" tid (wssStatus statusNoLock) -setFeatureConfig FeatureSingletonEnforceFileDownloadLocation tid statusNoLock = undefined +setFeatureConfig FeatureSingletonEnforceFileDownloadLocation tid status = do + let statusValue = wssStatus status + config = wssConfig status + + retry x5 $ write insert (params LocalQuorum (tid, statusValue, config.enforcedDownloadLocation)) + where + insert :: PrepQuery W (TeamId, FeatureStatus, Maybe Text) () + insert = + "insert into team_features (team_id, enforce_file_download_location_status, enforce_file_download_location) values (?, ?, ?)" getFeatureLockStatus :: MonadClient m => FeatureSingleton cfg -> TeamId -> m (Maybe LockStatus) getFeatureLockStatus FeatureSingletonFileSharingConfig tid = getLockStatusC "file_sharing_lock_status" tid @@ -267,7 +275,7 @@ getFeatureLockStatus FeatureSingletonMlsE2EIdConfig tid = getLockStatusC "mls_e2 getFeatureLockStatus FeatureSingletonMlsMigration tid = getLockStatusC "mls_migration_lock_status" tid getFeatureLockStatus FeatureSingletonOutlookCalIntegrationConfig tid = getLockStatusC "outlook_cal_integration_lock_status" tid getFeatureLockStatus FeatureSingletonMLSConfig tid = getLockStatusC "mls_lock_status" tid -getFeatureLockStatus FeatureSingletonEnforceFileDownloadLocation tid = undefined +getFeatureLockStatus FeatureSingletonEnforceFileDownloadLocation tid = getLockStatusC "enforce_file_download_location_lock_status" tid getFeatureLockStatus _ _ = pure Nothing setFeatureLockStatus :: MonadClient m => FeatureSingleton cfg -> TeamId -> LockStatus -> m () @@ -279,7 +287,7 @@ setFeatureLockStatus FeatureSingletonMlsE2EIdConfig tid status = setLockStatusC setFeatureLockStatus FeatureSingletonMlsMigration tid status = setLockStatusC "mls_migration_lock_status" tid status setFeatureLockStatus FeatureSingletonOutlookCalIntegrationConfig tid status = setLockStatusC "outlook_cal_integration_lock_status" tid status setFeatureLockStatus FeatureSingletonMLSConfig tid status = setLockStatusC "mls_lock_status" tid status -setFeatureLockStatus FeatureSingletonEnforceFileDownloadLocation tid status = undefined +setFeatureLockStatus FeatureSingletonEnforceFileDownloadLocation tid status = setLockStatusC "enforce_file_download_location_lock_status" tid status setFeatureLockStatus _ _tid _status = pure () getTrivialConfigC :: diff --git a/services/galley/test/integration/API/Teams/Feature.hs b/services/galley/test/integration/API/Teams/Feature.hs index 76da749103..ff8cd77a50 100644 --- a/services/galley/test/integration/API/Teams/Feature.hs +++ b/services/galley/test/integration/API/Teams/Feature.hs @@ -1541,5 +1541,5 @@ defaultEnforceFileDownloadLocationConfig = withStatus FeatureStatusDisabled LockStatusLocked - (EnforceFileDownloadLocationConfig "*") + (EnforceFileDownloadLocationConfig Nothing) FeatureTTLUnlimited From d7100f3513b0cc568988ad47e7fbc8d7b6c46872 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Tue, 2 Jan 2024 11:27:49 +0100 Subject: [PATCH 03/10] Fixup 9132bee89f94724b4f05595f1a3f86283eb4016b --- libs/wire-api/src/Wire/API/Team/Feature.hs | 15 +++++++++------ .../galley/src/Galley/Cassandra/TeamFeatures.hs | 8 ++++---- services/galley/src/Galley/Schema/Run.hs | 4 +++- .../galley/test/integration/API/Teams/Feature.hs | 7 ++++++- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Team/Feature.hs b/libs/wire-api/src/Wire/API/Team/Feature.hs index 9cfc54f56f..98cca4dffc 100644 --- a/libs/wire-api/src/Wire/API/Team/Feature.hs +++ b/libs/wire-api/src/Wire/API/Team/Feature.hs @@ -166,16 +166,16 @@ import Wire.Arbitrary (Arbitrary, GenericUniform (..)) -- (https://github.com/wireapp/wire-server/pull/1811, -- https://github.com/wireapp/wire-server/pull/1818) -- --- 10. Extend the integration tests with cases +-- 10. Extend the integration tests with cases. -- --- 11. Edit/update the configurations: +-- 11. If applicable, edit/update the configurations: -- - optionally add the config for local integration tests to 'galley.integration.yaml' -- - add a config mapping to 'charts/galley/templates/configmap.yaml' -- - add the defaults to 'charts/galley/values.yaml' -- - optionally add config for CI to 'hack/helm_vars/wire-server/values.yaml' -- -- 12. Add a section to the documentation at an appropriate place --- (e.g. 'docs/src/developer/reference/config-options.md' or +-- (e.g. 'docs/src/developer/reference/config-options.md' (if applicable) or -- 'docs/src/understand/team-feature-settings.md') class IsFeatureConfig cfg where type FeatureSymbol cfg :: Symbol @@ -206,8 +206,11 @@ data FeatureSingleton cfg where FeatureSingletonExposeInvitationURLsToTeamAdminConfig :: FeatureSingleton ExposeInvitationURLsToTeamAdminConfig FeatureSingletonOutlookCalIntegrationConfig :: FeatureSingleton OutlookCalIntegrationConfig FeatureSingletonMlsE2EIdConfig :: FeatureSingleton MlsE2EIdConfig - FeatureSingletonMlsMigration :: FeatureSingleton MlsMigrationConfig - FeatureSingletonEnforceFileDownloadLocation :: FeatureSingleton EnforceFileDownloadLocationConfig + FeatureSingletonMlsMigration :: + -- FUTUREWORK: rename to `FeatureSingletonMlsMigrationConfig` (or drop the `Config` from + -- all other constructors) + FeatureSingleton MlsMigrationConfig + FeatureSingletonEnforceFileDownloadLocationConfig :: FeatureSingleton EnforceFileDownloadLocationConfig class FeatureTrivialConfig cfg where trivialConfig :: cfg @@ -1112,7 +1115,7 @@ instance ToSchema EnforceFileDownloadLocationConfig where instance IsFeatureConfig EnforceFileDownloadLocationConfig where type FeatureSymbol EnforceFileDownloadLocationConfig = "enforceFileDownloadLocation" defFeatureStatus = withStatus FeatureStatusDisabled LockStatusLocked (EnforceFileDownloadLocationConfig Nothing) FeatureTTLUnlimited - featureSingleton = FeatureSingletonEnforceFileDownloadLocation + featureSingleton = FeatureSingletonEnforceFileDownloadLocationConfig objectSchema = field "config" schema ---------------------------------------------------------------------- diff --git a/services/galley/src/Galley/Cassandra/TeamFeatures.hs b/services/galley/src/Galley/Cassandra/TeamFeatures.hs index 4ed5cbd581..21eb3e0d06 100644 --- a/services/galley/src/Galley/Cassandra/TeamFeatures.hs +++ b/services/galley/src/Galley/Cassandra/TeamFeatures.hs @@ -159,7 +159,7 @@ getFeatureConfig FeatureSingletonMlsMigration tid = do select = "select mls_migration_status, mls_migration_start_time, mls_migration_finalise_regardless_after from team_features where team_id = ?" getFeatureConfig FeatureSingletonExposeInvitationURLsToTeamAdminConfig tid = getTrivialConfigC "expose_invitation_urls_to_team_admin" tid getFeatureConfig FeatureSingletonOutlookCalIntegrationConfig tid = getTrivialConfigC "outlook_cal_integration_status" tid -getFeatureConfig FeatureSingletonEnforceFileDownloadLocation tid = do +getFeatureConfig FeatureSingletonEnforceFileDownloadLocationConfig tid = do let q = query1 select (params LocalQuorum (Identity tid)) retry x1 q <&> \case Nothing -> Nothing @@ -256,7 +256,7 @@ setFeatureConfig FeatureSingletonMlsMigration tid status = do "insert into team_features (team_id, mls_migration_status, mls_migration_start_time, mls_migration_finalise_regardless_after) values (?, ?, ?, ?)" setFeatureConfig FeatureSingletonExposeInvitationURLsToTeamAdminConfig tid statusNoLock = setFeatureStatusC "expose_invitation_urls_to_team_admin" tid (wssStatus statusNoLock) setFeatureConfig FeatureSingletonOutlookCalIntegrationConfig tid statusNoLock = setFeatureStatusC "outlook_cal_integration_status" tid (wssStatus statusNoLock) -setFeatureConfig FeatureSingletonEnforceFileDownloadLocation tid status = do +setFeatureConfig FeatureSingletonEnforceFileDownloadLocationConfig tid status = do let statusValue = wssStatus status config = wssConfig status @@ -275,7 +275,7 @@ getFeatureLockStatus FeatureSingletonMlsE2EIdConfig tid = getLockStatusC "mls_e2 getFeatureLockStatus FeatureSingletonMlsMigration tid = getLockStatusC "mls_migration_lock_status" tid getFeatureLockStatus FeatureSingletonOutlookCalIntegrationConfig tid = getLockStatusC "outlook_cal_integration_lock_status" tid getFeatureLockStatus FeatureSingletonMLSConfig tid = getLockStatusC "mls_lock_status" tid -getFeatureLockStatus FeatureSingletonEnforceFileDownloadLocation tid = getLockStatusC "enforce_file_download_location_lock_status" tid +getFeatureLockStatus FeatureSingletonEnforceFileDownloadLocationConfig tid = getLockStatusC "enforce_file_download_location_lock_status" tid getFeatureLockStatus _ _ = pure Nothing setFeatureLockStatus :: MonadClient m => FeatureSingleton cfg -> TeamId -> LockStatus -> m () @@ -287,7 +287,7 @@ setFeatureLockStatus FeatureSingletonMlsE2EIdConfig tid status = setLockStatusC setFeatureLockStatus FeatureSingletonMlsMigration tid status = setLockStatusC "mls_migration_lock_status" tid status setFeatureLockStatus FeatureSingletonOutlookCalIntegrationConfig tid status = setLockStatusC "outlook_cal_integration_lock_status" tid status setFeatureLockStatus FeatureSingletonMLSConfig tid status = setLockStatusC "mls_lock_status" tid status -setFeatureLockStatus FeatureSingletonEnforceFileDownloadLocation tid status = setLockStatusC "enforce_file_download_location_lock_status" tid status +setFeatureLockStatus FeatureSingletonEnforceFileDownloadLocationConfig tid status = setLockStatusC "enforce_file_download_location_lock_status" tid status setFeatureLockStatus _ _tid _status = pure () getTrivialConfigC :: diff --git a/services/galley/src/Galley/Schema/Run.hs b/services/galley/src/Galley/Schema/Run.hs index 91ae2c3185..4905617fa6 100644 --- a/services/galley/src/Galley/Schema/Run.hs +++ b/services/galley/src/Galley/Schema/Run.hs @@ -90,6 +90,7 @@ import Galley.Schema.V86_TeamFeatureMlsMigration qualified as V86_TeamFeatureMls import Galley.Schema.V87_TeamFeatureSupportedProtocols qualified as V87_TeamFeatureSupportedProtocols import Galley.Schema.V88_RemoveMemberClientAndTruncateMLSGroupMemberClient qualified as V88_RemoveMemberClientAndTruncateMLSGroupMemberClient import Galley.Schema.V89_MlsLockStatus qualified as V89_MlsLockStatus +import Galley.Schema.V90_EnforceFileDownloadLocationConfig qualified as V90_EnforceFileDownloadLocationConfig import Imports import Options.Applicative import System.Logger.Extended qualified as Log @@ -180,7 +181,8 @@ migrations = V86_TeamFeatureMlsMigration.migration, V87_TeamFeatureSupportedProtocols.migration, V88_RemoveMemberClientAndTruncateMLSGroupMemberClient.migration, - V89_MlsLockStatus.migration + V89_MlsLockStatus.migration, + V90_EnforceFileDownloadLocationConfig.migration -- FUTUREWORK: once #1726 has made its way to master/production, -- the 'message' field in connections table can be dropped. -- See also https://github.com/wireapp/wire-server/pull/1747/files diff --git a/services/galley/test/integration/API/Teams/Feature.hs b/services/galley/test/integration/API/Teams/Feature.hs index ff8cd77a50..a6d8955e38 100644 --- a/services/galley/test/integration/API/Teams/Feature.hs +++ b/services/galley/test/integration/API/Teams/Feature.hs @@ -110,6 +110,8 @@ tests s = ), test s "MlsMigration feature config" $ testNonTrivialConfigNoTTL defaultMlsMigrationConfig, + test s "EnforceFileDownloadLocation feature config" $ + testNonTrivialConfigNoTTL (defFeatureStatus @EnforceFileDownloadLocationConfig), testGroup "Patch" [ -- Note: `SSOConfig` and `LegalHoldConfig` may not be able to be reset @@ -150,7 +152,10 @@ tests s = testPatch AssertLockStatusChange FeatureStatusEnabled (SelfDeletingMessagesConfig 0), test s (unpack $ featureNameBS @OutlookCalIntegrationConfig) $ testPatch AssertLockStatusChange FeatureStatusDisabled OutlookCalIntegrationConfig, - test s (unpack $ featureNameBS @MlsE2EIdConfig) $ testPatchWithArbitrary AssertLockStatusChange FeatureStatusDisabled (wsConfig (defFeatureStatus @MlsE2EIdConfig)) + test s (unpack $ featureNameBS @MlsE2EIdConfig) $ + testPatchWithArbitrary AssertLockStatusChange FeatureStatusDisabled (wsConfig (defFeatureStatus @MlsE2EIdConfig)), + test s (unpack $ featureNameBS @EnforceFileDownloadLocationConfig) $ + testPatchWithArbitrary AssertLockStatusChange FeatureStatusDisabled (wsConfig (defFeatureStatus @EnforceFileDownloadLocationConfig)) ], testGroup "ExposeInvitationURLsToTeamAdmin" From 9ae393df4137231cf667897baf6284c6b8a689b4 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Tue, 2 Jan 2024 12:09:41 +0100 Subject: [PATCH 04/10] Add backoffice/stern routes. --- tools/stern/src/Stern/API.hs | 2 ++ tools/stern/src/Stern/API/Routes.hs | 2 ++ tools/stern/src/Stern/Intra.hs | 2 +- tools/stern/test/integration/API.hs | 5 +++-- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/stern/src/Stern/API.hs b/tools/stern/src/Stern/API.hs index c2c2619047..a75fb752f2 100644 --- a/tools/stern/src/Stern/API.hs +++ b/tools/stern/src/Stern/API.hs @@ -159,6 +159,8 @@ sitemap' = :<|> Named @"get-route-outlook-cal-config" (mkFeatureGetRoute @OutlookCalIntegrationConfig) :<|> Named @"lock-unlock-route-outlook-cal-config" (mkFeatureLockUnlockRouteTrivialConfigNoTTL @OutlookCalIntegrationConfig) :<|> Named @"put-route-outlook-cal-config" (mkFeaturePutRouteTrivialConfigNoTTL @OutlookCalIntegrationConfig) + :<|> Named @"get-route-enforce-file-download-location" (mkFeatureGetRoute @EnforceFileDownloadLocationConfig) + :<|> Named @"put-route-enforce-file-download-location" (mkFeaturePutRoute @EnforceFileDownloadLocationConfig) :<|> Named @"get-team-invoice" getTeamInvoice :<|> Named @"get-team-billing-info" getTeamBillingInfo :<|> Named @"put-team-billing-info" updateTeamBillingInfo diff --git a/tools/stern/src/Stern/API/Routes.hs b/tools/stern/src/Stern/API/Routes.hs index 79fccd55c6..71944ddef8 100644 --- a/tools/stern/src/Stern/API/Routes.hs +++ b/tools/stern/src/Stern/API/Routes.hs @@ -322,6 +322,8 @@ type SternAPI = :<|> Named "get-route-outlook-cal-config" (MkFeatureGetRoute OutlookCalIntegrationConfig) :<|> Named "lock-unlock-route-outlook-cal-config" (MkFeatureLockUnlockRouteTrivialConfigNoTTL OutlookCalIntegrationConfig) :<|> Named "put-route-outlook-cal-config" (MkFeaturePutRouteTrivialConfigNoTTL OutlookCalIntegrationConfig) + :<|> Named "get-route-enforce-file-download-location" (MkFeatureGetRoute EnforceFileDownloadLocationConfig) + :<|> Named "put-route-enforce-file-download-location" (MkFeaturePutRoute EnforceFileDownloadLocationConfig) :<|> Named "get-team-invoice" ( Summary "Get a specific invoice by Number" diff --git a/tools/stern/src/Stern/Intra.hs b/tools/stern/src/Stern/Intra.hs index 4d13739d16..685e654123 100644 --- a/tools/stern/src/Stern/Intra.hs +++ b/tools/stern/src/Stern/Intra.hs @@ -560,7 +560,7 @@ setTeamFeatureFlag tid status = do resp <- catchRpcErrors $ rpc' "galley" gly req case statusCode resp of 200 -> pure () - 404 -> throwE (mkError status404 "bad-upstream" "team doesnt exist") + 404 -> throwE (mkError status404 "bad-upstream" "team does not exist") 403 -> throwE (mkError status403 "bad-upstream" "legal hold config cannot be changed") _ -> throwE (mkError status502 "bad-upstream" (errorMessage resp)) where diff --git a/tools/stern/test/integration/API.hs b/tools/stern/test/integration/API.hs index 657d7359fc..8a79612119 100644 --- a/tools/stern/test/integration/API.hs +++ b/tools/stern/test/integration/API.hs @@ -93,13 +93,14 @@ tests s = test s "GET /teams/:tid/features/classifiedDomains" $ testGetFeatureConfig @ClassifiedDomainsConfig (Just FeatureStatusEnabled), test s "GET /teams/:tid/features/outlookCalIntegration" $ testFeatureStatus @OutlookCalIntegrationConfig, test s "PUT /teams/:tid/features/outlookCalIntegration{,'?lockOrUnlock'}" $ testFeatureStatusWithLock @OutlookCalIntegrationConfig, + test s "GET /teams/:tid/features/enforceFileDownloadLocation" $ testFeatureStatus @EnforceFileDownloadLocationConfig, test s "GET /i/consent" testGetConsentLog, test s "GET /teams/:id" testGetTeamInfo, test s "GET i/user/meta-info?id=..." testGetUserMetaInfo, test s "/teams/:tid/search-visibility" testSearchVisibility, test s "/sso-domain-redirect" testRudSsoDomainRedirect, test s "i/oauth/clients" testCrudOAuthClient - -- The following endpoints can not be tested because they require ibis: + -- The following endpoints can not be tested here because they require ibis: -- - `GET /teams/:tid/billing` -- - `GET /teams/:tid/invoice/:inr` -- - `PUT /teams/:tid/billing` @@ -334,7 +335,7 @@ testFeatureStatusOptTtl mTtl = do liftIO $ cfg @?= defFeatureStatus @cfg when (wsLockStatus cfg == LockStatusLocked) $ unlockFeature @cfg tid let newStatus = if wsStatus cfg == FeatureStatusEnabled then FeatureStatusDisabled else FeatureStatusEnabled - void $ putFeatureStatus @cfg tid newStatus mTtl + putFeatureStatus @cfg tid newStatus mTtl !!! const 200 === statusCode cfg' <- getFeatureConfig @cfg tid liftIO $ wsStatus cfg' @?= newStatus From d274c696bb34da4c48c28f2062927248c446205a Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Tue, 2 Jan 2024 18:44:59 +0100 Subject: [PATCH 05/10] Add lock route to stern. --- tools/stern/src/Stern/API.hs | 9 +++++++-- tools/stern/src/Stern/API/Routes.hs | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/stern/src/Stern/API.hs b/tools/stern/src/Stern/API.hs index a75fb752f2..772703e4d9 100644 --- a/tools/stern/src/Stern/API.hs +++ b/tools/stern/src/Stern/API.hs @@ -160,6 +160,7 @@ sitemap' = :<|> Named @"lock-unlock-route-outlook-cal-config" (mkFeatureLockUnlockRouteTrivialConfigNoTTL @OutlookCalIntegrationConfig) :<|> Named @"put-route-outlook-cal-config" (mkFeaturePutRouteTrivialConfigNoTTL @OutlookCalIntegrationConfig) :<|> Named @"get-route-enforce-file-download-location" (mkFeatureGetRoute @EnforceFileDownloadLocationConfig) + :<|> Named @"lock-unlock-route-enforce-file-download-location" (mkFeatureLockUnlockRouteTrivialConfigNoTTL @EnforceFileDownloadLocationConfig) :<|> Named @"put-route-enforce-file-download-location" (mkFeaturePutRoute @EnforceFileDownloadLocationConfig) :<|> Named @"get-team-invoice" getTeamInvoice :<|> Named @"get-team-billing-info" getTeamBillingInfo @@ -325,8 +326,12 @@ mkFeaturePutRoute :: mkFeaturePutRoute tid payload = NoContent <$ Intra.setTeamFeatureFlag @cfg tid payload type MkFeaturePutConstraints cfg = + ( MkFeaturePutLockConstraints cfg, + FeatureTrivialConfig cfg + ) + +type MkFeaturePutLockConstraints cfg = ( IsFeatureConfig cfg, - FeatureTrivialConfig cfg, KnownSymbol (FeatureSymbol cfg), ToSchema cfg, FromJSON (WithStatusNoLock cfg), @@ -339,7 +344,7 @@ mkFeaturePutRouteTrivialConfigNoTTL :: mkFeaturePutRouteTrivialConfigNoTTL tid status = mkFeaturePutRouteTrivialConfig @cfg tid status Nothing mkFeatureLockUnlockRouteTrivialConfigNoTTL :: - forall cfg. (MkFeaturePutConstraints cfg) => TeamId -> LockStatus -> Handler NoContent + forall cfg. (MkFeaturePutLockConstraints cfg) => TeamId -> LockStatus -> Handler NoContent mkFeatureLockUnlockRouteTrivialConfigNoTTL tid lstat = NoContent <$ Intra.setTeamFeatureLockStatus @cfg tid lstat mkFeaturePutRouteTrivialConfigWithTTL :: diff --git a/tools/stern/src/Stern/API/Routes.hs b/tools/stern/src/Stern/API/Routes.hs index 71944ddef8..9fc68ca4dd 100644 --- a/tools/stern/src/Stern/API/Routes.hs +++ b/tools/stern/src/Stern/API/Routes.hs @@ -323,6 +323,7 @@ type SternAPI = :<|> Named "lock-unlock-route-outlook-cal-config" (MkFeatureLockUnlockRouteTrivialConfigNoTTL OutlookCalIntegrationConfig) :<|> Named "put-route-outlook-cal-config" (MkFeaturePutRouteTrivialConfigNoTTL OutlookCalIntegrationConfig) :<|> Named "get-route-enforce-file-download-location" (MkFeatureGetRoute EnforceFileDownloadLocationConfig) + :<|> Named "lock-unlock-route-enforce-file-download-location" (MkFeatureLockUnlockRouteTrivialConfigNoTTL EnforceFileDownloadLocationConfig) :<|> Named "put-route-enforce-file-download-location" (MkFeaturePutRoute EnforceFileDownloadLocationConfig) :<|> Named "get-team-invoice" From c72c4023d70ca256456268bb8f210ce68182f3f0 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Tue, 2 Jan 2024 20:54:05 +0100 Subject: [PATCH 06/10] Add swagger docs. --- .../src/Wire/API/Routes/Internal/Galley.hs | 25 +++++++++++------ .../Wire/API/Routes/Public/Galley/Feature.hs | 28 +++++++++++++++---- tools/stern/src/Stern/API/Routes.hs | 21 ++++++++++++-- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Routes/Internal/Galley.hs b/libs/wire-api/src/Wire/API/Routes/Internal/Galley.hs index 5998cb5f88..cc930367b0 100644 --- a/libs/wire-api/src/Wire/API/Routes/Internal/Galley.hs +++ b/libs/wire-api/src/Wire/API/Routes/Internal/Galley.hs @@ -161,10 +161,10 @@ type IFeatureAPI = :<|> IFeatureStatusPatch '[] '() MlsMigrationConfig :<|> IFeatureStatusLockStatusPut MlsMigrationConfig -- EnforceFileDownloadLocationConfig - :<|> IFeatureStatusGet EnforceFileDownloadLocationConfig - :<|> IFeatureStatusPut '[] '() EnforceFileDownloadLocationConfig - :<|> IFeatureStatusPatch '[] '() EnforceFileDownloadLocationConfig - :<|> IFeatureStatusLockStatusPut EnforceFileDownloadLocationConfig + :<|> IFeatureStatusGetWithDesc EnforceFileDownloadLocationConfig "

Custom feature: only supported for some decidated on-prem systems.

" + :<|> IFeatureStatusPutWithDesc '[] '() EnforceFileDownloadLocationConfig "

Custom feature: only supported for some decidated on-prem systems.

" + :<|> IFeatureStatusPatchWithDesc '[] '() EnforceFileDownloadLocationConfig "

Custom feature: only supported for some decidated on-prem systems.

" + :<|> IFeatureStatusLockStatusPutWithDesc EnforceFileDownloadLocationConfig "

Custom feature: only supported for some decidated on-prem systems.

" -- all feature configs :<|> Named "feature-configs-internal" @@ -377,11 +377,17 @@ type ITeamsAPIBase = ) ) -type IFeatureStatusGet f = Named '("iget", f) (FeatureStatusBaseGet f) +type IFeatureStatusGet f = IFeatureStatusGetWithDesc f "" -type IFeatureStatusPut calls errs f = Named '("iput", f) (ApplyMods calls (FeatureStatusBasePutInternal errs f)) +type IFeatureStatusGetWithDesc f desc = Named '("iget", f) (Description desc :> FeatureStatusBaseGet f) -type IFeatureStatusPatch calls errs f = Named '("ipatch", f) (ApplyMods calls (FeatureStatusBasePatchInternal errs f)) +type IFeatureStatusPut calls errs f = IFeatureStatusPutWithDesc calls errs f "" + +type IFeatureStatusPutWithDesc calls errs f desc = Named '("iput", f) (ApplyMods calls (Description desc :> FeatureStatusBasePutInternal errs f)) + +type IFeatureStatusPatch calls errs f = IFeatureStatusPatchWithDesc calls errs f "" + +type IFeatureStatusPatchWithDesc calls errs f desc = Named '("ipatch", f) (ApplyMods calls (Description desc :> FeatureStatusBasePatchInternal errs f)) type FeatureStatusBasePutInternal errs featureConfig = FeatureStatusBaseInternal @@ -414,10 +420,13 @@ type FeatureStatusBaseInternal desc errs featureConfig a = :> FeatureSymbol featureConfig :> a -type IFeatureStatusLockStatusPut featureName = +type IFeatureStatusLockStatusPut featureName = IFeatureStatusLockStatusPutWithDesc featureName "" + +type IFeatureStatusLockStatusPutWithDesc featureName desc = Named '("ilock", featureName) ( Summary (AppendSymbol "(Un-)lock " (FeatureSymbol featureName)) + :> Description desc :> CanThrow 'NotATeamMember :> CanThrow 'TeamNotFound :> "teams" diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Galley/Feature.hs b/libs/wire-api/src/Wire/API/Routes/Public/Galley/Feature.hs index 3bbaa1cb9b..69a40c0312 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Galley/Feature.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Galley/Feature.hs @@ -91,8 +91,16 @@ type FeatureAPI = :<|> From 'V5 ::> FeatureStatusPut '[] '() MlsE2EIdConfig :<|> From 'V5 ::> FeatureStatusGet MlsMigrationConfig :<|> From 'V5 ::> FeatureStatusPut '[] '() MlsMigrationConfig - :<|> From 'V5 ::> FeatureStatusGet EnforceFileDownloadLocationConfig - :<|> From 'V5 ::> FeatureStatusPut '[] '() EnforceFileDownloadLocationConfig + :<|> From 'V5 + ::> FeatureStatusGetWithDesc + EnforceFileDownloadLocationConfig + "

Custom feature: only supported for some decidated on-prem systems.

" + :<|> From 'V5 + ::> FeatureStatusPutWithDesc + '[] + '() + EnforceFileDownloadLocationConfig + "

Custom feature: only supported for some decidated on-prem systems.

" :<|> AllFeatureConfigsUserGet :<|> AllFeatureConfigsTeamGet :<|> FeatureConfigDeprecatedGet "The usage of this endpoint was removed in iOS in version 3.101. It is not used by team management, or webapp, and is potentially used by the old Android client as of June 2022" LegalholdConfig @@ -109,15 +117,23 @@ type FeatureAPI = :<|> FeatureConfigDeprecatedGet "The usage of this endpoint was removed in iOS in version 3.101. It is used by team management, webapp, and potentially the old Android client as of June 2022" SndFactorPasswordChallengeConfig :<|> FeatureConfigDeprecatedGet "The usage of this endpoint was removed in iOS in version 3.101. It is used by team management, webapp, and potentially the old Android client as of June 2022" MLSConfig -type FeatureStatusGet f = +type FeatureStatusGet f = FeatureStatusGetWithDesc f "" + +type FeatureStatusGetWithDesc f desc = Named '("get", f) - (ZUser :> FeatureStatusBaseGet f) + ( Description desc + :> (ZUser :> FeatureStatusBaseGet f) + ) -type FeatureStatusPut segs errs f = +type FeatureStatusPut segs errs f = FeatureStatusPutWithDesc segs errs f "" + +type FeatureStatusPutWithDesc segs errs f desc = Named '("put", f) - (ApplyMods segs (ZUser :> FeatureStatusBasePutPublic errs f)) + ( Description desc + :> (ApplyMods segs (ZUser :> FeatureStatusBasePutPublic errs f)) + ) type FeatureStatusDeprecatedGet d f = Named diff --git a/tools/stern/src/Stern/API/Routes.hs b/tools/stern/src/Stern/API/Routes.hs index 9fc68ca4dd..55113e8517 100644 --- a/tools/stern/src/Stern/API/Routes.hs +++ b/tools/stern/src/Stern/API/Routes.hs @@ -322,9 +322,24 @@ type SternAPI = :<|> Named "get-route-outlook-cal-config" (MkFeatureGetRoute OutlookCalIntegrationConfig) :<|> Named "lock-unlock-route-outlook-cal-config" (MkFeatureLockUnlockRouteTrivialConfigNoTTL OutlookCalIntegrationConfig) :<|> Named "put-route-outlook-cal-config" (MkFeaturePutRouteTrivialConfigNoTTL OutlookCalIntegrationConfig) - :<|> Named "get-route-enforce-file-download-location" (MkFeatureGetRoute EnforceFileDownloadLocationConfig) - :<|> Named "lock-unlock-route-enforce-file-download-location" (MkFeatureLockUnlockRouteTrivialConfigNoTTL EnforceFileDownloadLocationConfig) - :<|> Named "put-route-enforce-file-download-location" (MkFeaturePutRoute EnforceFileDownloadLocationConfig) + :<|> Named + "get-route-enforce-file-download-location" + ( Description + "

Custom feature: only supported for some decidated on-prem systems.

" + :> MkFeatureGetRoute EnforceFileDownloadLocationConfig + ) + :<|> Named + "lock-unlock-route-enforce-file-download-location" + ( Description + "

Custom feature: only supported for some decidated on-prem systems.

" + :> MkFeatureLockUnlockRouteTrivialConfigNoTTL EnforceFileDownloadLocationConfig + ) + :<|> Named + "put-route-enforce-file-download-location" + ( Description + "

Custom feature: only supported for some dedicated on-prem systems.

" + :> MkFeaturePutRoute EnforceFileDownloadLocationConfig + ) :<|> Named "get-team-invoice" ( Summary "Get a specific invoice by Number" From c7474ca39497776294a9662bce273ccf5e2c23ef Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 3 Jan 2024 09:50:47 +0100 Subject: [PATCH 07/10] Changelog. --- ...ake-the-standard-file-download-location-configuration-visible | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5-internal/WPB-5627-Backend-Option-to-make-the-standard-file-download-location-configuration-visible diff --git a/changelog.d/5-internal/WPB-5627-Backend-Option-to-make-the-standard-file-download-location-configuration-visible b/changelog.d/5-internal/WPB-5627-Backend-Option-to-make-the-standard-file-download-location-configuration-visible new file mode 100644 index 0000000000..8712db7b11 --- /dev/null +++ b/changelog.d/5-internal/WPB-5627-Backend-Option-to-make-the-standard-file-download-location-configuration-visible @@ -0,0 +1 @@ +Add custom feature flag; only supported for some on-prem installations; locked & disabled by default \ No newline at end of file From 1baf5d7a2a8b82725cf4251e2513af953be93c87 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 3 Jan 2024 10:26:26 +0100 Subject: [PATCH 08/10] Update cassandra schema. --- cassandra-schema.cql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cassandra-schema.cql b/cassandra-schema.cql index afac7e0508..596495b57c 100644 --- a/cassandra-schema.cql +++ b/cassandra-schema.cql @@ -1191,6 +1191,9 @@ CREATE TABLE galley_test.team_features ( app_lock_status int, conference_calling int, digital_signatures int, + enforce_file_download_location text, + enforce_file_download_location_lock_status int, + enforce_file_download_location_status int, expose_invitation_urls_to_team_admin int, file_sharing int, file_sharing_lock_status int, From cebbbd0bd9d87ff1306552e956066c51657607e7 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 3 Jan 2024 10:33:12 +0100 Subject: [PATCH 09/10] Remove broken test (manual testing shows it works). --- tools/stern/test/integration/API.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/stern/test/integration/API.hs b/tools/stern/test/integration/API.hs index 8a79612119..12602fbfc2 100644 --- a/tools/stern/test/integration/API.hs +++ b/tools/stern/test/integration/API.hs @@ -93,7 +93,6 @@ tests s = test s "GET /teams/:tid/features/classifiedDomains" $ testGetFeatureConfig @ClassifiedDomainsConfig (Just FeatureStatusEnabled), test s "GET /teams/:tid/features/outlookCalIntegration" $ testFeatureStatus @OutlookCalIntegrationConfig, test s "PUT /teams/:tid/features/outlookCalIntegration{,'?lockOrUnlock'}" $ testFeatureStatusWithLock @OutlookCalIntegrationConfig, - test s "GET /teams/:tid/features/enforceFileDownloadLocation" $ testFeatureStatus @EnforceFileDownloadLocationConfig, test s "GET /i/consent" testGetConsentLog, test s "GET /teams/:id" testGetTeamInfo, test s "GET i/user/meta-info?id=..." testGetUserMetaInfo, From 0da9bc59df47a48e84230b7a11b7f57f13c9bd82 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Thu, 4 Jan 2024 13:58:32 +0100 Subject: [PATCH 10/10] hi ci