diff --git a/cassandra-schema.cql b/cassandra-schema.cql
index afac7e05080..596495b57c0 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,
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 00000000000..8712db7b11d
--- /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
diff --git a/libs/galley-types/src/Galley/Types/Teams.hs b/libs/galley-types/src/Galley/Types/Teams.hs
index e77b04951b0..800f1e53b46 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 dc58b44845d..1e6c740d019 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 32aad3997e5..cc930367b0e 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
+ :<|> 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"
@@ -372,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
@@ -409,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 a59144b926d..69a40c03122 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,16 @@ type FeatureAPI =
:<|> From 'V5 ::> FeatureStatusPut '[] '() MlsE2EIdConfig
:<|> From 'V5 ::> FeatureStatusGet MlsMigrationConfig
:<|> From 'V5 ::> FeatureStatusPut '[] '() MlsMigrationConfig
+ :<|> 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
@@ -107,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/libs/wire-api/src/Wire/API/Team/Feature.hs b/libs/wire-api/src/Wire/API/Team/Feature.hs
index 7f47a1596f6..98cca4dffce 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
@@ -164,15 +166,17 @@ 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 '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' (if applicable) or
+-- 'docs/src/understand/team-feature-settings.md')
class IsFeatureConfig cfg where
type FeatureSymbol cfg :: Symbol
defFeatureStatus :: WithStatus cfg
@@ -202,7 +206,11 @@ data FeatureSingleton cfg where
FeatureSingletonExposeInvitationURLsToTeamAdminConfig :: FeatureSingleton ExposeInvitationURLsToTeamAdminConfig
FeatureSingletonOutlookCalIntegrationConfig :: FeatureSingleton OutlookCalIntegrationConfig
FeatureSingletonMlsE2EIdConfig :: FeatureSingleton MlsE2EIdConfig
- FeatureSingletonMlsMigration :: FeatureSingleton MlsMigrationConfig
+ FeatureSingletonMlsMigration ::
+ -- FUTUREWORK: rename to `FeatureSingletonMlsMigrationConfig` (or drop the `Config` from
+ -- all other constructors)
+ FeatureSingleton MlsMigrationConfig
+ FeatureSingletonEnforceFileDownloadLocationConfig :: FeatureSingleton EnforceFileDownloadLocationConfig
class FeatureTrivialConfig cfg where
trivialConfig :: cfg
@@ -1084,6 +1092,32 @@ instance IsFeatureConfig MlsMigrationConfig where
featureSingleton = FeatureSingletonMlsMigration
objectSchema = field "config" schema
+----------------------------------------------------------------------
+-- EnforceFileDownloadLocationConfig
+
+data EnforceFileDownloadLocationConfig = EnforceFileDownloadLocationConfig
+ { enforcedDownloadLocation :: Maybe Text
+ }
+ deriving stock (Eq, Show, Generic)
+
+instance RenderableSymbol EnforceFileDownloadLocationConfig where
+ renderSymbol = "EnforceFileDownloadLocationConfig"
+
+instance Arbitrary EnforceFileDownloadLocationConfig where
+ arbitrary = EnforceFileDownloadLocationConfig . fmap (cs . getPrintableString) <$> arbitrary
+
+instance ToSchema EnforceFileDownloadLocationConfig where
+ schema =
+ object "EnforceFileDownloadLocation" $
+ EnforceFileDownloadLocationConfig
+ <$> enforcedDownloadLocation .= maybe_ (optField "enforcedDownloadLocation" schema)
+
+instance IsFeatureConfig EnforceFileDownloadLocationConfig where
+ type FeatureSymbol EnforceFileDownloadLocationConfig = "enforceFileDownloadLocation"
+ defFeatureStatus = withStatus FeatureStatusDisabled LockStatusLocked (EnforceFileDownloadLocationConfig Nothing) FeatureTTLUnlimited
+ featureSingleton = FeatureSingletonEnforceFileDownloadLocationConfig
+ objectSchema = field "config" schema
+
----------------------------------------------------------------------
-- FeatureStatus
@@ -1161,7 +1195,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 +1223,7 @@ instance ToSchema AllFeatureConfigs where
<*> afcOutlookCalIntegration .= featureField
<*> afcMlsE2EId .= featureField
<*> afcMlsMigration .= featureField
+ <*> afcEnforceFileDownloadLocation .= featureField
where
featureField ::
forall cfg.
@@ -1216,5 +1252,6 @@ instance Arbitrary AllFeatureConfigs where
<*> arbitrary
<*> arbitrary
<*> arbitrary
+ <*> arbitrary
makeLenses ''ImplicitLockStatus
diff --git a/services/galley/galley.cabal b/services/galley/galley.cabal
index 6d63451aedc..8561169ce01 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 9d58f182d42..7f3bcf4de44 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 20ad5e4bef6..f2d2cd19e23 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 546365d456e..56e6ea71684 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 1bdecdd78b8..d9525c1386f 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 d9db6f33894..21eb3e0d06b 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 FeatureSingletonEnforceFileDownloadLocationConfig 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 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,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 FeatureSingletonEnforceFileDownloadLocationConfig 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
@@ -256,6 +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 FeatureSingletonEnforceFileDownloadLocationConfig tid = getLockStatusC "enforce_file_download_location_lock_status" tid
getFeatureLockStatus _ _ = pure Nothing
setFeatureLockStatus :: MonadClient m => FeatureSingleton cfg -> TeamId -> LockStatus -> m ()
@@ -267,6 +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 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 91ae2c3185b..4905617fa66 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/src/Galley/Schema/V90_EnforceFileDownloadLocationConfig.hs b/services/galley/src/Galley/Schema/V90_EnforceFileDownloadLocationConfig.hs
new file mode 100644
index 00000000000..b55842de725
--- /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 dbfed7255eb..a6d8955e388 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"
@@ -1057,7 +1062,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 +1540,11 @@ defaultMlsMigrationConfig =
finaliseRegardlessAfter = fmap fromUTCTimeMillis (readUTCTimeMillis "2029-10-17T00:00:00.000Z")
}
FeatureTTLUnlimited
+
+defaultEnforceFileDownloadLocationConfig :: WithStatus EnforceFileDownloadLocationConfig
+defaultEnforceFileDownloadLocationConfig =
+ withStatus
+ FeatureStatusDisabled
+ LockStatusLocked
+ (EnforceFileDownloadLocationConfig Nothing)
+ FeatureTTLUnlimited
diff --git a/tools/stern/src/Stern/API.hs b/tools/stern/src/Stern/API.hs
index c2c2619047b..772703e4d98 100644
--- a/tools/stern/src/Stern/API.hs
+++ b/tools/stern/src/Stern/API.hs
@@ -159,6 +159,9 @@ 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 @"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
:<|> Named @"put-team-billing-info" updateTeamBillingInfo
@@ -323,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),
@@ -337,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 79fccd55c61..55113e85177 100644
--- a/tools/stern/src/Stern/API/Routes.hs
+++ b/tools/stern/src/Stern/API/Routes.hs
@@ -322,6 +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"
+ ( 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"
diff --git a/tools/stern/src/Stern/Intra.hs b/tools/stern/src/Stern/Intra.hs
index 4d13739d167..685e6541236 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 657d7359fc5..12602fbfc24 100644
--- a/tools/stern/test/integration/API.hs
+++ b/tools/stern/test/integration/API.hs
@@ -99,7 +99,7 @@ tests s =
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 +334,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