From c199e00a49d5230819a59d91e8599b7a193e39f1 Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Tue, 9 Nov 2021 14:35:57 +0100 Subject: [PATCH 01/28] Unlock payment route and functionality, no op cassandra impl yet json roundtrip test for PaymentStatus C* schema migration for self deleting messages payment status teamstore implementation for self deleting messages payment status removed unnecessary function dynamic lock/unlock payment status added payment status to feature with config models removed redundant description use PaymentStatusValue for API path removed redundant comment added roundtrip test for PaymentStatusValue updated API description make payment status in config optional golden tests include payment status, formatting generic set payment status error for locked payment status validate payment status while setting team feature status fix integration tests comments --- cabal.project.freeze | 1 + libs/wire-api/src/Wire/API/Swagger.hs | 1 + libs/wire-api/src/Wire/API/Team/Feature.hs | 102 ++++++++++++++++-- ...hConfig_20TeamFeatureAppLockConfig_team.hs | 23 +++- .../API/Golden/Manual/FeatureConfigEvent.hs | 1 + .../testObject_FeatureConfigEvent_3.json | 1 + ...fig_20TeamFeatureAppLockConfig_team_1.json | 1 + ...fig_20TeamFeatureAppLockConfig_team_2.json | 1 + .../unit/Test/Wire/API/Roundtrip/Aeson.hs | 2 + services/galley/galley.cabal | 1 + services/galley/schema/src/Main.hs | 6 +- .../V55_TeamFeatureWithConfigPaymentStatus.hs | 34 ++++++ services/galley/src/Galley/API/Error.hs | 5 + services/galley/src/Galley/API/Internal.hs | 20 +++- .../galley/src/Galley/API/Teams/Features.hs | 64 ++++++++--- services/galley/src/Galley/Cassandra.hs | 2 +- .../src/Galley/Cassandra/TeamFeatures.hs | 64 +++++++++-- .../galley/src/Galley/Data/TeamFeatures.hs | 26 ++++- .../src/Galley/Effects/TeamFeatureStore.hs | 32 ++++++ .../test/integration/API/Teams/Feature.hs | 23 ++-- 20 files changed, 364 insertions(+), 46 deletions(-) create mode 100644 services/galley/schema/src/V55_TeamFeatureWithConfigPaymentStatus.hs diff --git a/cabal.project.freeze b/cabal.project.freeze index 71ff635e0b..fbe3f3a2a0 100644 --- a/cabal.project.freeze +++ b/cabal.project.freeze @@ -1702,6 +1702,7 @@ constraints: any.AC-Angle ==1.0, any.polynomials-bernstein ==1.1.2, any.polyparse ==1.13, any.polysemy ==1.6.0.0, + any.polysemy-check ==0.8.1.0, any.polysemy-mocks ==0.1.0.0, any.polysemy-plugin ==0.2.5.2, any.pooled-io ==0.0.2.2, diff --git a/libs/wire-api/src/Wire/API/Swagger.hs b/libs/wire-api/src/Wire/API/Swagger.hs index f746c3465c..7ebdb1d9c8 100644 --- a/libs/wire-api/src/Wire/API/Swagger.hs +++ b/libs/wire-api/src/Wire/API/Swagger.hs @@ -129,6 +129,7 @@ models = Team.Feature.modelTeamFeatureAppLockConfig, Team.Feature.modelTeamFeatureClassifiedDomainsConfig, Team.Feature.modelTeamFeatureSelfDeletingMessagesConfig, + Team.Feature.modelPaymentStatus, Team.Invitation.modelTeamInvitation, Team.Invitation.modelTeamInvitationList, Team.Invitation.modelTeamInvitationRequest, diff --git a/libs/wire-api/src/Wire/API/Team/Feature.hs b/libs/wire-api/src/Wire/API/Team/Feature.hs index f466fe3102..9a349ed97d 100644 --- a/libs/wire-api/src/Wire/API/Team/Feature.hs +++ b/libs/wire-api/src/Wire/API/Team/Feature.hs @@ -32,6 +32,8 @@ module Wire.API.Team.Feature TeamFeatureStatusWithConfig (..), HasDeprecatedFeatureName (..), AllFeatureConfigs (..), + PaymentStatus (..), + PaymentStatusValue (..), defaultAppLockStatus, defaultClassifiedDomains, defaultSelfDeletingMessagesStatus, @@ -45,6 +47,7 @@ module Wire.API.Team.Feature modelTeamFeatureClassifiedDomainsConfig, modelTeamFeatureSelfDeletingMessagesConfig, modelForTeamFeature, + modelPaymentStatus, ) where @@ -52,8 +55,9 @@ import qualified Cassandra.CQL as Cass import Control.Lens.Combinators (dimap) import qualified Data.Aeson as Aeson import qualified Data.Attoparsec.ByteString as Parser -import Data.ByteString.Conversion (FromByteString (..), ToByteString (..), toByteString') +import Data.ByteString.Conversion (FromByteString (..), ToByteString (..), fromByteString, toByteString') import Data.Domain (Domain) +import Data.Either.Extra (maybeToEither) import Data.Kind (Constraint) import Data.Schema import Data.String.Conversions (cs) @@ -64,6 +68,7 @@ import qualified Data.Text.Encoding as T import Deriving.Aeson import GHC.TypeLits (Symbol) import Imports +import Servant (FromHttpApiData (..)) import Test.QuickCheck.Arbitrary (arbitrary) import Wire.API.Arbitrary (Arbitrary, GenericUniform (..)) @@ -304,11 +309,11 @@ modelForTeamFeature TeamFeatureSSO = modelTeamFeatureStatusNoConfig modelForTeamFeature TeamFeatureSearchVisibility = modelTeamFeatureStatusNoConfig modelForTeamFeature TeamFeatureValidateSAMLEmails = modelTeamFeatureStatusNoConfig modelForTeamFeature TeamFeatureDigitalSignatures = modelTeamFeatureStatusNoConfig -modelForTeamFeature name@TeamFeatureAppLock = modelTeamFeatureStatusWithConfig name modelTeamFeatureAppLockConfig +modelForTeamFeature name@TeamFeatureAppLock = modelTeamFeatureStatusWithConfig name modelTeamFeatureAppLockConfig modelPaymentStatus modelForTeamFeature TeamFeatureFileSharing = modelTeamFeatureStatusNoConfig -modelForTeamFeature name@TeamFeatureClassifiedDomains = modelTeamFeatureStatusWithConfig name modelTeamFeatureClassifiedDomainsConfig +modelForTeamFeature name@TeamFeatureClassifiedDomains = modelTeamFeatureStatusWithConfig name modelTeamFeatureClassifiedDomainsConfig modelPaymentStatus modelForTeamFeature TeamFeatureConferenceCalling = modelTeamFeatureStatusNoConfig -modelForTeamFeature name@TeamFeatureSelfDeletingMessages = modelTeamFeatureStatusWithConfig name modelTeamFeatureSelfDeletingMessagesConfig +modelForTeamFeature name@TeamFeatureSelfDeletingMessages = modelTeamFeatureStatusWithConfig name modelTeamFeatureSelfDeletingMessagesConfig modelPaymentStatus ---------------------------------------------------------------------- -- TeamFeatureStatusNoConfig @@ -339,19 +344,21 @@ instance ToSchema TeamFeatureStatusNoConfig where -- to recreate the config every time it's turned on. data TeamFeatureStatusWithConfig (cfg :: *) = TeamFeatureStatusWithConfig { tfwcStatus :: TeamFeatureStatusValue, - tfwcConfig :: cfg + tfwcConfig :: cfg, + tfwcPaymentStatus :: Maybe PaymentStatusValue --FUTUREWORK: remove payment status from set feature status request, it should only be part of the API response } deriving stock (Eq, Show, Generic, Typeable) deriving (ToJSON, FromJSON, S.ToSchema) via (Schema (TeamFeatureStatusWithConfig cfg)) instance Arbitrary cfg => Arbitrary (TeamFeatureStatusWithConfig cfg) where - arbitrary = TeamFeatureStatusWithConfig <$> arbitrary <*> arbitrary + arbitrary = TeamFeatureStatusWithConfig <$> arbitrary <*> arbitrary <*> arbitrary -modelTeamFeatureStatusWithConfig :: TeamFeatureName -> Doc.Model -> Doc.Model -modelTeamFeatureStatusWithConfig name cfgModel = Doc.defineModel (cs $ show name) $ do +modelTeamFeatureStatusWithConfig :: TeamFeatureName -> Doc.Model -> Doc.Model -> Doc.Model +modelTeamFeatureStatusWithConfig name cfgModel paymentStatusModel = Doc.defineModel (cs $ show name) $ do Doc.description $ "Status and config of " <> cs (show name) Doc.property "status" typeTeamFeatureStatusValue $ Doc.description "status" Doc.property "config" (Doc.ref cfgModel) $ Doc.description "config" + Doc.property "paymentStatus" (Doc.ref paymentStatusModel) $ Doc.description "payment status" instance ToSchema cfg => ToSchema (TeamFeatureStatusWithConfig cfg) where schema = @@ -359,6 +366,7 @@ instance ToSchema cfg => ToSchema (TeamFeatureStatusWithConfig cfg) where TeamFeatureStatusWithConfig <$> tfwcStatus .= field "status" schema <*> tfwcConfig .= field "config" schema + <*> tfwcPaymentStatus .= opt (field "paymentStatus" schema) ---------------------------------------------------------------------- -- TeamFeatureClassifiedDomainsConfig @@ -383,7 +391,11 @@ modelTeamFeatureClassifiedDomainsConfig = Doc.property "domains" (Doc.array Doc.string') $ Doc.description "domains" defaultClassifiedDomains :: TeamFeatureStatusWithConfig TeamFeatureClassifiedDomainsConfig -defaultClassifiedDomains = TeamFeatureStatusWithConfig TeamFeatureDisabled (TeamFeatureClassifiedDomainsConfig []) +defaultClassifiedDomains = + TeamFeatureStatusWithConfig + TeamFeatureDisabled + (TeamFeatureClassifiedDomainsConfig []) + $ Just PaymentLocked ---------------------------------------------------------------------- -- TeamFeatureAppLockConfig @@ -423,6 +435,7 @@ defaultAppLockStatus = TeamFeatureStatusWithConfig TeamFeatureEnabled (TeamFeatureAppLockConfig (EnforceAppLock False) 60) + $ Just PaymentLocked ---------------------------------------------------------------------- -- TeamFeatureSelfDeletingMessagesConfig @@ -450,6 +463,77 @@ defaultSelfDeletingMessagesStatus = TeamFeatureStatusWithConfig TeamFeatureEnabled (TeamFeatureSelfDeletingMessagesConfig 0) + $ Just PaymentLocked + +---------------------------------------------------------------------- +-- PaymentStatus + +instance FromHttpApiData PaymentStatusValue where + parseUrlPiece = maybeToEither "Invalid payment status" . fromByteString . cs + +data PaymentStatusValue = PaymentLocked | PaymentUnlocked + deriving stock (Eq, Show, Generic) + deriving (Arbitrary) via (GenericUniform PaymentStatusValue) + deriving (ToJSON, FromJSON, S.ToSchema) via (Schema PaymentStatusValue) + +newtype PaymentStatus = PaymentStatus + { paymentStatus :: PaymentStatusValue + } + deriving stock (Eq, Show, Generic) + deriving (FromJSON, ToJSON, S.ToSchema) via (Schema PaymentStatus) + deriving (Arbitrary) via (GenericUniform PaymentStatus) + +instance ToSchema PaymentStatus where + schema = + object "PaymentStatus" $ + PaymentStatus + <$> paymentStatus .= field "paymentStatus" schema + +modelPaymentStatus :: Doc.Model +modelPaymentStatus = + Doc.defineModel "PaymentStatus" $ do + Doc.property "paymentStatus" typePaymentStatusValue $ Doc.description "" + +typePaymentStatusValue :: Doc.DataType +typePaymentStatusValue = + Doc.string $ + Doc.enum + [ "locked", + "unlocked" + ] + +instance ToSchema PaymentStatusValue where + schema = + enum @Text "PaymentStatusValue" $ + mconcat + [ element "locked" PaymentLocked, + element "unlocked" PaymentUnlocked + ] + +instance ToByteString PaymentStatusValue where + builder PaymentLocked = "locked" + builder PaymentUnlocked = "unlocked" + +instance FromByteString PaymentStatusValue where + parser = + Parser.takeByteString >>= \b -> + case T.decodeUtf8' b of + Right "locked" -> pure PaymentLocked + Right "unlocked" -> pure PaymentUnlocked + Right t -> fail $ "Invalid PaymentStatusValue: " <> T.unpack t + Left e -> fail $ "Invalid PaymentStatusValue: " <> show e + +instance Cass.Cql PaymentStatusValue where + ctype = Cass.Tagged Cass.IntColumn + + fromCql (Cass.CqlInt n) = case n of + 0 -> pure PaymentLocked + 1 -> pure PaymentUnlocked + _ -> Left "fromCql: Invalid PaymentStatusValue" + fromCql _ = Left "fromCql: PaymentStatusValue: CqlInt expected" + + toCql PaymentLocked = Cass.CqlInt 0 + toCql PaymentUnlocked = Cass.CqlInt 1 ---------------------------------------------------------------------- -- internal diff --git a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team.hs b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team.hs index 4013a22392..20241d1700 100644 --- a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team.hs +++ b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team.hs @@ -18,9 +18,10 @@ -- with this program. If not, see . module Test.Wire.API.Golden.Generated.TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team where -import Imports (Bool (False, True)) +import Imports (Bool (False, True), Maybe (..)) import Wire.API.Team.Feature ( EnforceAppLock (EnforceAppLock), + PaymentStatusValue (..), TeamFeatureAppLockConfig (..), TeamFeatureStatusValue (TeamFeatureDisabled, TeamFeatureEnabled), TeamFeatureStatusWithConfig (..), @@ -31,6 +32,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_1 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_1 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, + tfwcPaymentStatus = Just PaymentLocked, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = -98} } @@ -40,6 +42,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_2 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_2 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, + tfwcPaymentStatus = Just PaymentUnlocked, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = 14} } @@ -49,6 +52,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_3 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_3 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = 92} } @@ -58,6 +62,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_4 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_4 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = 45} } @@ -67,6 +72,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_5 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_5 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = 119} } @@ -76,6 +82,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_6 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_6 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = -50} } @@ -85,6 +92,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_7 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_7 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = -50} } @@ -94,6 +102,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_8 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_8 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = -76} } @@ -103,6 +112,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_9 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_9 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = 96} } @@ -112,6 +122,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_10 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_10 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = 120} } @@ -121,6 +132,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_11 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_11 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = 62} } @@ -130,6 +142,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_12 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_12 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = -50} } @@ -139,6 +152,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_13 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_13 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = -99} } @@ -148,6 +162,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_14 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_14 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = -96} } @@ -157,6 +172,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_15 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_15 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = -12} } @@ -166,6 +182,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_16 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_16 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = -60} } @@ -175,6 +192,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_17 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_17 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = 100} } @@ -184,6 +202,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_18 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_18 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = 74} } @@ -193,6 +212,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_19 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_19 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = -125} } @@ -202,6 +222,7 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_20 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_20 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, + tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = 69} } diff --git a/libs/wire-api/test/golden/Test/Wire/API/Golden/Manual/FeatureConfigEvent.hs b/libs/wire-api/test/golden/Test/Wire/API/Golden/Manual/FeatureConfigEvent.hs index 2e5f9f85d3..23756080e4 100644 --- a/libs/wire-api/test/golden/Test/Wire/API/Golden/Manual/FeatureConfigEvent.hs +++ b/libs/wire-api/test/golden/Test/Wire/API/Golden/Manual/FeatureConfigEvent.hs @@ -19,5 +19,6 @@ testObject_FeatureConfigEvent_3 = ( TeamFeatureStatusWithConfig TeamFeatureDisabled (TeamFeatureAppLockConfig (EnforceAppLock True) 300) + $ Just PaymentLocked ) ) diff --git a/libs/wire-api/test/golden/testObject_FeatureConfigEvent_3.json b/libs/wire-api/test/golden/testObject_FeatureConfigEvent_3.json index 2a7c5fdfe0..f44a4c313d 100644 --- a/libs/wire-api/test/golden/testObject_FeatureConfigEvent_3.json +++ b/libs/wire-api/test/golden/testObject_FeatureConfigEvent_3.json @@ -4,6 +4,7 @@ "enforceAppLock": true, "inactivityTimeoutSecs": 300 }, + "paymentStatus": "locked", "status": "disabled" }, "name": "appLock", diff --git a/libs/wire-api/test/golden/testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_1.json b/libs/wire-api/test/golden/testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_1.json index 66a69f69b1..dbab959e8c 100644 --- a/libs/wire-api/test/golden/testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_1.json +++ b/libs/wire-api/test/golden/testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_1.json @@ -3,5 +3,6 @@ "enforceAppLock": false, "inactivityTimeoutSecs": -98 }, + "paymentStatus": "locked", "status": "disabled" } diff --git a/libs/wire-api/test/golden/testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_2.json b/libs/wire-api/test/golden/testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_2.json index e566224c5f..df4873983c 100644 --- a/libs/wire-api/test/golden/testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_2.json +++ b/libs/wire-api/test/golden/testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_2.json @@ -3,5 +3,6 @@ "enforceAppLock": false, "inactivityTimeoutSecs": 14 }, + "paymentStatus": "unlocked", "status": "enabled" } diff --git a/libs/wire-api/test/unit/Test/Wire/API/Roundtrip/Aeson.hs b/libs/wire-api/test/unit/Test/Wire/API/Roundtrip/Aeson.hs index 6e09181e54..4000a866e0 100644 --- a/libs/wire-api/test/unit/Test/Wire/API/Roundtrip/Aeson.hs +++ b/libs/wire-api/test/unit/Test/Wire/API/Roundtrip/Aeson.hs @@ -206,6 +206,8 @@ tests = testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.TeamFeatureConferenceCalling), testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.TeamFeatureSelfDeletingMessages), testRoundTrip @Team.Feature.TeamFeatureStatusValue, + testRoundTrip @Team.Feature.PaymentStatusValue, + testRoundTrip @Team.Feature.PaymentStatus, testRoundTrip @Team.Invitation.InvitationRequest, testRoundTrip @Team.Invitation.Invitation, testRoundTrip @Team.Invitation.InvitationList, diff --git a/services/galley/galley.cabal b/services/galley/galley.cabal index b1f68193ca..3f237fe667 100644 --- a/services/galley/galley.cabal +++ b/services/galley/galley.cabal @@ -437,6 +437,7 @@ executable galley-schema V52_FeatureConferenceCalling V53_AddRemoteConvStatus V54_TeamFeatureSelfDeletingMessages + V55_TeamFeatureWithConfigPaymentStatus Paths_galley hs-source-dirs: schema/src diff --git a/services/galley/schema/src/Main.hs b/services/galley/schema/src/Main.hs index 369a464436..59cb7758ac 100644 --- a/services/galley/schema/src/Main.hs +++ b/services/galley/schema/src/Main.hs @@ -57,6 +57,7 @@ import qualified V51_FeatureFileSharing import qualified V52_FeatureConferenceCalling import qualified V53_AddRemoteConvStatus import qualified V54_TeamFeatureSelfDeletingMessages +import qualified V55_TeamFeatureWithConfigPaymentStatus main :: IO () main = do @@ -99,9 +100,10 @@ main = do V51_FeatureFileSharing.migration, V52_FeatureConferenceCalling.migration, V53_AddRemoteConvStatus.migration, - V54_TeamFeatureSelfDeletingMessages.migration + V54_TeamFeatureSelfDeletingMessages.migration, + V55_TeamFeatureWithConfigPaymentStatus.migration -- When adding migrations here, don't forget to update - -- 'schemaVersion' in Galley.Data + -- 'schemaVersion' in Galley.Cassandra -- (see also docs/developer/cassandra-interaction.md) -- -- FUTUREWORK: once #1726 has made its way to master/production, diff --git a/services/galley/schema/src/V55_TeamFeatureWithConfigPaymentStatus.hs b/services/galley/schema/src/V55_TeamFeatureWithConfigPaymentStatus.hs new file mode 100644 index 0000000000..c96eb51f2d --- /dev/null +++ b/services/galley/schema/src/V55_TeamFeatureWithConfigPaymentStatus.hs @@ -0,0 +1,34 @@ +-- This file is part of the Wire Server implementation. +-- +-- Copyright (C) 2020 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 V55_TeamFeatureWithConfigPaymentStatus + ( migration, + ) +where + +import Cassandra.Schema +import Imports +import Text.RawString.QQ + +migration :: Migration +migration = Migration 55 "Add payment status config for team features with config" $ do + schema' + [r| ALTER TABLE team_features ADD ( + self_deleting_messages_payment_status int, + app_lock_payment_status int, + ) + |] diff --git a/services/galley/src/Galley/API/Error.hs b/services/galley/src/Galley/API/Error.hs index 34c6ec0d3c..6c1b604dfd 100644 --- a/services/galley/src/Galley/API/Error.hs +++ b/services/galley/src/Galley/API/Error.hs @@ -161,12 +161,14 @@ data TeamFeatureError | LegalHoldFeatureFlagNotEnabled | LegalHoldWhitelistedOnly | DisableSsoNotImplemented + | PaymentStatusLocked instance APIError TeamFeatureError where toWai AppLockinactivityTimeoutTooLow = inactivityTimeoutTooLow toWai LegalHoldFeatureFlagNotEnabled = legalHoldFeatureFlagNotEnabled toWai LegalHoldWhitelistedOnly = legalHoldWhitelistedOnly toWai DisableSsoNotImplemented = disableSsoNotImplemented + toWai PaymentStatusLocked = setTeamFeatureConfigPaymentStatusLocked data TeamNotificationError = InvalidTeamNotificationId @@ -458,6 +460,9 @@ noLegalHoldDeviceAllocated = mkError status404 "legalhold-no-device-allocated" " legalHoldCouldNotBlockConnections :: Error legalHoldCouldNotBlockConnections = mkError status500 "legalhold-internal" "legal hold service: could not block connections when resolving policy conflicts." +setTeamFeatureConfigPaymentStatusLocked :: Error +setTeamFeatureConfigPaymentStatusLocked = mkError status409 "payment-status-locked" "feature config cannot be updated when the payment status is locked" + disableSsoNotImplemented :: Error disableSsoNotImplemented = mkError diff --git a/services/galley/src/Galley/API/Internal.hs b/services/galley/src/Galley/API/Internal.hs index 5c5a555b92..34bf48d78e 100644 --- a/services/galley/src/Galley/API/Internal.hs +++ b/services/galley/src/Galley/API/Internal.hs @@ -52,6 +52,7 @@ import Galley.API.Util import Galley.App import Galley.Cassandra.Paging import qualified Galley.Data.Conversation as Data +import Galley.Data.TeamFeatures (HasPaymentStatusCol) import Galley.Effects import Galley.Effects.ClientStore import Galley.Effects.ConversationStore @@ -194,6 +195,9 @@ data InternalApi routes = InternalApi iTeamFeatureStatusSelfDeletingMessagesGet :: routes :- IFeatureStatusGet 'Public.TeamFeatureSelfDeletingMessages, + iTeamFeaturePaymentStatusSelfDeletingMessagesPut :: + routes + :- IFeatureStatusPaymentStatusPut 'Public.TeamFeatureSelfDeletingMessages, -- This endpoint can lead to the following events being sent: -- - MemberLeave event to members for all conversations the user was in iDeleteUser :: @@ -251,6 +255,16 @@ type IFeatureStatusPut featureName = :> ReqBody '[Servant.JSON] (Public.TeamFeatureStatus featureName) :> Put '[Servant.JSON] (Public.TeamFeatureStatus featureName) +type IFeatureStatusPaymentStatusPut featureName = + Summary (AppendSymbol "(Un-) lock payment for " (Public.KnownTeamFeatureNameSymbol featureName)) + :> "i" + :> "teams" + :> Capture "tid" TeamId + :> "features" + :> Public.KnownTeamFeatureNameSymbol featureName + :> Capture "paymentStatus" Public.PaymentStatusValue + :> Put '[Servant.JSON] Public.PaymentStatus + -- | A type for a GET endpoint for a feature with a deprecated path type IFeatureStatusDeprecatedGet featureName = Summary (AppendSymbol "[deprecated] Get config for " (Public.KnownTeamFeatureNameSymbol featureName)) @@ -303,6 +317,7 @@ servantSitemap = iTeamFeatureStatusConferenceCallingGet = iGetTeamFeature @'Public.TeamFeatureConferenceCalling Features.getConferenceCallingInternal, iTeamFeatureStatusSelfDeletingMessagesPut = iPutTeamFeature @'Public.TeamFeatureSelfDeletingMessages Features.setSelfDeletingMessagesInternal, iTeamFeatureStatusSelfDeletingMessagesGet = iGetTeamFeature @'Public.TeamFeatureSelfDeletingMessages Features.getSelfDeletingMessagesInternal, + iTeamFeaturePaymentStatusSelfDeletingMessagesPut = Features.setPaymentStatus @'Public.TeamFeatureSelfDeletingMessages (Features.setPaymentStatusInternal @'Public.TeamFeatureSelfDeletingMessages), iDeleteUser = rmUser, iConnect = Create.createConnectConversation, iUpsertOne2OneConversation = One2One.iUpsertOne2OneConversation @@ -327,11 +342,14 @@ iGetTeamFeature getter = Features.getFeatureStatus @a getter DontDoAuth iPutTeamFeature :: forall a r. ( Public.KnownTeamFeatureName a, + HasPaymentStatusCol a, Members '[ Error ActionError, Error NotATeamMember, Error TeamError, - TeamStore + Error TeamFeatureError, + TeamStore, + TeamFeatureStore ] r ) => diff --git a/services/galley/src/Galley/API/Teams/Features.hs b/services/galley/src/Galley/API/Teams/Features.hs index 19e49f76b1..be67bec628 100644 --- a/services/galley/src/Galley/API/Teams/Features.hs +++ b/services/galley/src/Galley/API/Teams/Features.hs @@ -39,7 +39,9 @@ module Galley.API.Teams.Features getConferenceCallingInternal, setConferenceCallingInternal, getSelfDeletingMessagesInternal, + setPaymentStatusInternal, setSelfDeletingMessagesInternal, + setPaymentStatus, DoAuth (..), GetFeatureInternalParam, ) @@ -117,11 +119,14 @@ getFeatureStatus getter doauth tid = do setFeatureStatus :: forall (a :: Public.TeamFeatureName) r. ( Public.KnownTeamFeatureName a, + HasPaymentStatusCol a, Members '[ Error ActionError, Error TeamError, Error NotATeamMember, - TeamStore + Error TeamFeatureError, + TeamStore, + TeamFeatureStore ] r ) => @@ -137,7 +142,31 @@ setFeatureStatus setter doauth tid status = do void $ permissionCheck (ChangeTeamFeature (Public.knownTeamFeatureName @a)) zusrMembership DontDoAuth -> assertTeamExists tid - setter tid status + maybePaymentStatus <- TeamFeatures.getPaymentStatus @a tid + case maybePaymentStatus of + Just (Public.PaymentStatus Public.PaymentLocked) -> throw PaymentStatusLocked + _ -> setter tid status + +-- | Setting payment status can only be done through the internal API and therefore doesn't require auth. +setPaymentStatus :: + forall (a :: Public.TeamFeatureName) r. + ( Public.KnownTeamFeatureName a, + HasPaymentStatusCol a, + Members + [ Error ActionError, + Error TeamError, + Error NotATeamMember, + TeamStore + ] + r + ) => + (TeamId -> Public.PaymentStatusValue -> Sem r Public.PaymentStatus) -> + TeamId -> + Public.PaymentStatusValue -> + Sem r Public.PaymentStatus +setPaymentStatus setter tid paymentStatusUpdate = do + assertTeamExists tid + setter tid paymentStatusUpdate -- | For individual users to get feature config for their account (personal or team). getFeatureConfig :: @@ -180,7 +209,7 @@ getAllFeatureConfigs :: Sem r AllFeatureConfigs getAllFeatureConfigs zusr = do mbTeam <- getOneUserTeam zusr - zusrMembership <- maybe (pure Nothing) ((flip getTeamMember zusr)) mbTeam + zusrMembership <- maybe (pure Nothing) (flip getTeamMember zusr) mbTeam let getStatus :: forall (a :: Public.TeamFeatureName) r. ( Public.KnownTeamFeatureName a, @@ -194,7 +223,7 @@ getAllFeatureConfigs zusr = do void $ permissionCheck (ViewTeamFeature (Public.knownTeamFeatureName @a)) zusrMembership status <- getter (maybe (Left (Just zusr)) Right mbTeam) let feature = Public.knownTeamFeatureName @a - pure $ (cs (toByteString' feature) Aeson..= status) + pure $ cs (toByteString' feature) Aeson..= status AllFeatureConfigs . HashMap.fromList <$> sequence @@ -268,7 +297,7 @@ getAllFeatures uid tid = do getStatus getter = do status <- getFeatureStatus @a getter (DoAuth uid) tid let feature = Public.knownTeamFeatureName @a - pure $ (cs (toByteString' feature) Aeson..= status) + pure $ cs (toByteString' feature) Aeson..= status getFeatureStatusNoConfig :: forall (a :: Public.TeamFeatureName) r. @@ -323,7 +352,7 @@ getSSOStatusInternal = setSSOStatusInternal :: Members '[Error TeamFeatureError, GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r => TeamId -> - (Public.TeamFeatureStatus 'Public.TeamFeatureSSO) -> + Public.TeamFeatureStatus 'Public.TeamFeatureSSO -> Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureSSO) setSSOStatusInternal = setFeatureStatusNoConfig @'Public.TeamFeatureSSO $ \case Public.TeamFeatureDisabled -> const (throw DisableSsoNotImplemented) @@ -346,7 +375,7 @@ getTeamSearchVisibilityAvailableInternal = setTeamSearchVisibilityAvailableInternal :: Members '[GundeckAccess, SearchVisibilityStore, TeamFeatureStore, TeamStore, P.TinyLog] r => TeamId -> - (Public.TeamFeatureStatus 'Public.TeamFeatureSearchVisibility) -> + Public.TeamFeatureStatus 'Public.TeamFeatureSearchVisibility -> Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureSearchVisibility) setTeamSearchVisibilityAvailableInternal = setFeatureStatusNoConfig @'Public.TeamFeatureSearchVisibility $ \case Public.TeamFeatureDisabled -> SearchVisibilityData.resetSearchVisibility @@ -369,7 +398,7 @@ getValidateSAMLEmailsInternal = setValidateSAMLEmailsInternal :: Members '[GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r => TeamId -> - (Public.TeamFeatureStatus 'Public.TeamFeatureValidateSAMLEmails) -> + Public.TeamFeatureStatus 'Public.TeamFeatureValidateSAMLEmails -> Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureValidateSAMLEmails) setValidateSAMLEmailsInternal = setFeatureStatusNoConfig @'Public.TeamFeatureValidateSAMLEmails $ \_ _ -> pure () @@ -518,7 +547,7 @@ setAppLockInternal tid status = do let pushEvent = pushFeatureConfigEvent tid $ Event.Event Event.Update Public.TeamFeatureAppLock (EdFeatureApplockChanged status) - (TeamFeatures.setApplockFeatureStatus tid status) <* pushEvent + TeamFeatures.setApplockFeatureStatus tid status <* pushEvent getClassifiedDomainsInternal :: Member (Input Opts) r => @@ -529,7 +558,7 @@ getClassifiedDomainsInternal _mbtid = do let config = globalConfig pure $ case Public.tfwcStatus config of Public.TeamFeatureDisabled -> - Public.TeamFeatureStatusWithConfig Public.TeamFeatureDisabled (Public.TeamFeatureClassifiedDomainsConfig []) + Public.TeamFeatureStatusWithConfig Public.TeamFeatureDisabled (Public.TeamFeatureClassifiedDomainsConfig []) (Just Public.PaymentLocked) Public.TeamFeatureEnabled -> config getConferenceCallingInternal :: @@ -559,7 +588,16 @@ getSelfDeletingMessagesInternal = \case Left _ -> pure Public.defaultSelfDeletingMessagesStatus Right tid -> TeamFeatures.getSelfDeletingMessagesStatus tid - <&> maybe Public.defaultSelfDeletingMessagesStatus id + <&> fromMaybe Public.defaultSelfDeletingMessagesStatus + +setPaymentStatusInternal :: + forall (a :: Public.TeamFeatureName) r. + (HasPaymentStatusCol a, Member TeamFeatureStore r) => + TeamId -> + Public.PaymentStatusValue -> + Sem r Public.PaymentStatus +setPaymentStatusInternal tid paymentStatus = + TeamFeatures.setPaymentStatus @a tid (Public.PaymentStatus paymentStatus) setSelfDeletingMessagesInternal :: Members '[GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r => @@ -570,7 +608,7 @@ setSelfDeletingMessagesInternal tid st = do let pushEvent = pushFeatureConfigEvent tid $ Event.Event Event.Update Public.TeamFeatureSelfDeletingMessages (EdFeatureSelfDeletingMessagesChanged st) - (TeamFeatures.setSelfDeletingMessagesStatus tid st) <* pushEvent + TeamFeatures.setSelfDeletingMessagesStatus tid st <* pushEvent pushFeatureConfigEvent :: Members '[GundeckAccess, TeamStore, P.TinyLog] r => @@ -588,7 +626,7 @@ pushFeatureConfigEvent tid event = do let recipients = membersToRecipients Nothing (memList ^. teamMembers) for_ (newPush (memList ^. teamMemberListType) Nothing (FeatureConfigEvent event) recipients) - (push1) + push1 -- | (Currently, we only have 'Public.TeamFeatureConferenceCalling' here, but we may have to -- extend this in the future.) diff --git a/services/galley/src/Galley/Cassandra.hs b/services/galley/src/Galley/Cassandra.hs index a32e4fdce1..83a0a5abd1 100644 --- a/services/galley/src/Galley/Cassandra.hs +++ b/services/galley/src/Galley/Cassandra.hs @@ -20,4 +20,4 @@ module Galley.Cassandra (schemaVersion) where import Imports schemaVersion :: Int32 -schemaVersion = 54 +schemaVersion = 55 diff --git a/services/galley/src/Galley/Cassandra/TeamFeatures.hs b/services/galley/src/Galley/Cassandra/TeamFeatures.hs index e723fe4768..78a7519efa 100644 --- a/services/galley/src/Galley/Cassandra/TeamFeatures.hs +++ b/services/galley/src/Galley/Cassandra/TeamFeatures.hs @@ -73,13 +73,13 @@ getApplockFeatureStatus tid = do let q = query1 select (params LocalQuorum (Identity tid)) mTuple <- retry x1 q pure $ - mTuple >>= \(mbStatusValue, mbEnforce, mbTimeout) -> - TeamFeatureStatusWithConfig <$> mbStatusValue <*> (TeamFeatureAppLockConfig <$> mbEnforce <*> mbTimeout) + mTuple >>= \(mbStatusValue, mbEnforce, mbTimeout, mbPaymentStatusValue) -> + TeamFeatureStatusWithConfig <$> mbStatusValue <*> (TeamFeatureAppLockConfig <$> mbEnforce <*> mbTimeout) <*> Just mbPaymentStatusValue where - select :: PrepQuery R (Identity TeamId) (Maybe TeamFeatureStatusValue, Maybe EnforceAppLock, Maybe Int32) + select :: PrepQuery R (Identity TeamId) (Maybe TeamFeatureStatusValue, Maybe EnforceAppLock, Maybe Int32, Maybe PaymentStatusValue) select = fromString $ - "select " <> statusCol @'TeamFeatureAppLock <> ", app_lock_enforce, app_lock_inactivity_timeout_secs " + "select " <> statusCol @'TeamFeatureAppLock <> ", app_lock_enforce, app_lock_inactivity_timeout_secs, app_lock_payment_status " <> "from team_features where team_id = ?" setApplockFeatureStatus :: @@ -110,15 +110,15 @@ getSelfDeletingMessagesStatus tid = do let q = query1 select (params LocalQuorum (Identity tid)) mTuple <- retry x1 q pure $ - mTuple >>= \(mbStatusValue, mbTimeout) -> - TeamFeatureStatusWithConfig <$> mbStatusValue <*> (TeamFeatureSelfDeletingMessagesConfig <$> mbTimeout) + mTuple >>= \(mbStatusValue, mbTimeout, mbPaymentStatusValue) -> + TeamFeatureStatusWithConfig <$> mbStatusValue <*> (TeamFeatureSelfDeletingMessagesConfig <$> mbTimeout) <*> Just mbPaymentStatusValue where - select :: PrepQuery R (Identity TeamId) (Maybe TeamFeatureStatusValue, Maybe Int32) + select :: PrepQuery R (Identity TeamId) (Maybe TeamFeatureStatusValue, Maybe Int32, Maybe PaymentStatusValue) select = fromString $ "select " <> statusCol @'TeamFeatureSelfDeletingMessages - <> ", self_deleting_messages_ttl " + <> ", self_deleting_messages_ttl, self_deleting_messages_payment_status " <> "from team_features where team_id = ?" setSelfDeletingMessagesStatus :: @@ -140,6 +140,52 @@ setSelfDeletingMessagesStatus tid status = do <> ", self_deleting_messages_ttl) " <> "values (?, ?, ?)" +setPaymentStatus :: + forall (a :: TeamFeatureName) m. + ( MonadClient m, + HasPaymentStatusCol a + ) => + Proxy a -> + TeamId -> + PaymentStatus -> + m PaymentStatus +setPaymentStatus _ tid (PaymentStatus paymentStatus) = + case paymentStatusCol @a of + Nothing -> pure $ PaymentStatus PaymentUnlocked -- todo: what should we do here? probably return an error, UpdatePaymentStatusNotAllowed or sth. similar + Just col -> do + retry x5 $ write insert (params LocalQuorum (tid, paymentStatus)) + pure (PaymentStatus paymentStatus) + where + insert :: PrepQuery W (TeamId, PaymentStatusValue) () + insert = + fromString $ + "insert into team_features (team_id, " + <> col + <> ") values (?, ?)" + +getPaymentStatus :: + forall (a :: TeamFeatureName) m. + ( MonadClient m, + HasPaymentStatusCol a + ) => + Proxy a -> + TeamId -> + m (Maybe PaymentStatus) +getPaymentStatus _ tid = + case paymentStatusCol @a of + Nothing -> pure Nothing + Just col -> do + let q = query1 select (params LocalQuorum (Identity tid)) + mTuple <- (>>= runIdentity) <$> retry x1 q + pure $ PaymentStatus <$> mTuple + where + select :: PrepQuery R (Identity TeamId) (Identity (Maybe PaymentStatusValue)) + select = + fromString $ + "select " + <> col + <> " from team_features where team_id = ?" + interpretTeamFeatureStoreToCassandra :: Members '[Embed IO, Input ClientState] r => Sem (TeamFeatureStore ': r) a -> @@ -147,6 +193,8 @@ interpretTeamFeatureStoreToCassandra :: interpretTeamFeatureStoreToCassandra = interpret $ \case GetFeatureStatusNoConfig' p tid -> embedClient $ getFeatureStatusNoConfig p tid SetFeatureStatusNoConfig' p tid value -> embedClient $ setFeatureStatusNoConfig p tid value + SetPaymentStatus' p tid value -> embedClient $ setPaymentStatus p tid value + GetPaymentStatus' p tid -> embedClient $ getPaymentStatus p tid GetApplockFeatureStatus tid -> embedClient $ getApplockFeatureStatus tid SetApplockFeatureStatus tid value -> embedClient $ setApplockFeatureStatus tid value GetSelfDeletingMessagesStatus tid -> embedClient $ getSelfDeletingMessagesStatus tid diff --git a/services/galley/src/Galley/Data/TeamFeatures.hs b/services/galley/src/Galley/Data/TeamFeatures.hs index e7ab337d0f..e620f7b45b 100644 --- a/services/galley/src/Galley/Data/TeamFeatures.hs +++ b/services/galley/src/Galley/Data/TeamFeatures.hs @@ -15,7 +15,7 @@ -- You should have received a copy of the GNU Affero General Public License along -- with this program. If not, see . -module Galley.Data.TeamFeatures (HasStatusCol (..)) where +module Galley.Data.TeamFeatures (HasStatusCol (..), HasPaymentStatusCol (..)) where import Imports import Wire.API.Team.Feature @@ -48,3 +48,27 @@ instance HasStatusCol 'TeamFeatureFileSharing where statusCol = "file_sharing" instance HasStatusCol 'TeamFeatureConferenceCalling where statusCol = "conference_calling" instance HasStatusCol 'TeamFeatureSelfDeletingMessages where statusCol = "self_deleting_messages_status" + +class HasPaymentStatusCol (a :: TeamFeatureName) where + paymentStatusCol :: Maybe String + +instance HasPaymentStatusCol 'TeamFeatureSelfDeletingMessages where + paymentStatusCol = Just "self_deleting_messages_payment_status" + +instance HasPaymentStatusCol 'TeamFeatureLegalHold where paymentStatusCol = Nothing + +instance HasPaymentStatusCol 'TeamFeatureSSO where paymentStatusCol = Nothing + +instance HasPaymentStatusCol 'TeamFeatureSearchVisibility where paymentStatusCol = Nothing + +instance HasPaymentStatusCol 'TeamFeatureValidateSAMLEmails where paymentStatusCol = Nothing + +instance HasPaymentStatusCol 'TeamFeatureDigitalSignatures where paymentStatusCol = Nothing + +instance HasPaymentStatusCol 'TeamFeatureAppLock where paymentStatusCol = Just "app_lock_payment_status" + +instance HasPaymentStatusCol 'TeamFeatureFileSharing where paymentStatusCol = Nothing + +instance HasPaymentStatusCol 'TeamFeatureClassifiedDomains where paymentStatusCol = Nothing + +instance HasPaymentStatusCol 'TeamFeatureConferenceCalling where paymentStatusCol = Nothing diff --git a/services/galley/src/Galley/Effects/TeamFeatureStore.hs b/services/galley/src/Galley/Effects/TeamFeatureStore.hs index d2910980f2..79b2f93602 100644 --- a/services/galley/src/Galley/Effects/TeamFeatureStore.hs +++ b/services/galley/src/Galley/Effects/TeamFeatureStore.hs @@ -23,6 +23,8 @@ module Galley.Effects.TeamFeatureStore setApplockFeatureStatus, getSelfDeletingMessagesStatus, setSelfDeletingMessagesStatus, + setPaymentStatus, + getPaymentStatus, ) where @@ -67,6 +69,21 @@ data TeamFeatureStore m a where TeamId -> TeamFeatureStatus 'TeamFeatureSelfDeletingMessages -> TeamFeatureStore m (TeamFeatureStatus 'TeamFeatureSelfDeletingMessages) + SetPaymentStatus' :: + forall (a :: TeamFeatureName) m. + ( HasPaymentStatusCol a + ) => + Proxy a -> + TeamId -> + PaymentStatus -> + TeamFeatureStore m PaymentStatus + GetPaymentStatus' :: + forall (a :: TeamFeatureName) m. + ( HasPaymentStatusCol a + ) => + Proxy a -> + TeamId -> + TeamFeatureStore m (Maybe PaymentStatus) makeSem ''TeamFeatureStore @@ -84,3 +101,18 @@ setFeatureStatusNoConfig :: TeamFeatureStatus a -> Sem r (TeamFeatureStatus a) setFeatureStatusNoConfig = setFeatureStatusNoConfig' (Proxy @a) + +setPaymentStatus :: + forall (a :: TeamFeatureName) r. + (Member TeamFeatureStore r, HasPaymentStatusCol a) => + TeamId -> + PaymentStatus -> + Sem r PaymentStatus +setPaymentStatus = setPaymentStatus' (Proxy @a) + +getPaymentStatus :: + forall (a :: TeamFeatureName) r. + (Member TeamFeatureStore r, HasPaymentStatusCol a) => + TeamId -> + Sem r (Maybe PaymentStatus) +getPaymentStatus = getPaymentStatus' (Proxy @a) diff --git a/services/galley/test/integration/API/Teams/Feature.hs b/services/galley/test/integration/API/Teams/Feature.hs index 76c5f7b408..d5620e120b 100644 --- a/services/galley/test/integration/API/Teams/Feature.hs +++ b/services/galley/test/integration/API/Teams/Feature.hs @@ -270,7 +270,8 @@ testClassifiedDomainsEnabled = do let expected = Public.TeamFeatureStatusWithConfig { Public.tfwcStatus = Public.TeamFeatureEnabled, - Public.tfwcConfig = Public.TeamFeatureClassifiedDomainsConfig [Domain "example.com"] + Public.tfwcConfig = Public.TeamFeatureClassifiedDomainsConfig [Domain "example.com"], + Public.tfwcPaymentStatus = Nothing } let getClassifiedDomainsFeatureConfig :: @@ -292,7 +293,8 @@ testClassifiedDomainsDisabled = do let expected = Public.TeamFeatureStatusWithConfig { Public.tfwcStatus = Public.TeamFeatureDisabled, - Public.tfwcConfig = Public.TeamFeatureClassifiedDomainsConfig [] + Public.tfwcConfig = Public.TeamFeatureClassifiedDomainsConfig [], + Public.tfwcPaymentStatus = Nothing } let getClassifiedDomainsFeatureConfig :: @@ -386,6 +388,7 @@ testSelfDeletingMessages = do Public.TeamFeatureStatusWithConfig @Public.TeamFeatureSelfDeletingMessagesConfig stat (Public.TeamFeatureSelfDeletingMessagesConfig tout) + Nothing personalUser <- Util.randomUser Util.getFeatureConfig Public.TeamFeatureSelfDeletingMessages personalUser @@ -446,19 +449,21 @@ testAllFeatures = do toS TeamFeatureAppLock .= Public.TeamFeatureStatusWithConfig TeamFeatureEnabled - (Public.TeamFeatureAppLockConfig (Public.EnforceAppLock False) (60 :: Int32)), + (Public.TeamFeatureAppLockConfig (Public.EnforceAppLock False) (60 :: Int32)) + Nothing, toS TeamFeatureFileSharing .= Public.TeamFeatureStatusNoConfig TeamFeatureEnabled, toS TeamFeatureClassifiedDomains .= Public.TeamFeatureStatusWithConfig TeamFeatureEnabled - (Public.TeamFeatureClassifiedDomainsConfig [Domain "example.com"]), + (Public.TeamFeatureClassifiedDomainsConfig [Domain "example.com"]) + Nothing, toS TeamFeatureConferenceCalling .= Public.TeamFeatureStatusNoConfig confCalling, toS TeamFeatureSelfDeletingMessages - .= ( Public.TeamFeatureStatusWithConfig @Public.TeamFeatureSelfDeletingMessagesConfig - TeamFeatureEnabled - (Public.TeamFeatureSelfDeletingMessagesConfig 0) - ) + .= Public.TeamFeatureStatusWithConfig @Public.TeamFeatureSelfDeletingMessagesConfig + TeamFeatureEnabled + (Public.TeamFeatureSelfDeletingMessagesConfig 0) + Nothing ] toS :: TeamFeatureName -> Text toS = TE.decodeUtf8 . toByteString' @@ -478,8 +483,6 @@ testFeatureConfigConsistency = do unless (allTeamFeaturesRes `Set.isSubsetOf` allFeaturesRes) $ liftIO $ expectationFailure (show allTeamFeaturesRes <> " is not a subset of " <> show allFeaturesRes) - - pure () where parseObjectKeys :: ResponseLBS -> TestM (Set.Set Text) parseObjectKeys res = do From a87fe0cc34f31662aa34cef2a4d4ccc9041bef22 Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Thu, 18 Nov 2021 10:37:27 +0100 Subject: [PATCH 02/28] removed payment status for app lock team feature from C* schema, and updated C* interpreter --- .../V55_TeamFeatureWithConfigPaymentStatus.hs | 5 ++- services/galley/src/Galley/API/Internal.hs | 4 +-- .../galley/src/Galley/API/Teams/Features.hs | 4 +-- .../src/Galley/Cassandra/TeamFeatures.hs | 31 +++++++++--------- .../galley/src/Galley/Data/TeamFeatures.hs | 32 +++++++++++-------- .../src/Galley/Effects/TeamFeatureStore.hs | 8 ++--- 6 files changed, 45 insertions(+), 39 deletions(-) diff --git a/services/galley/schema/src/V55_TeamFeatureWithConfigPaymentStatus.hs b/services/galley/schema/src/V55_TeamFeatureWithConfigPaymentStatus.hs index c96eb51f2d..20927e852f 100644 --- a/services/galley/schema/src/V55_TeamFeatureWithConfigPaymentStatus.hs +++ b/services/galley/schema/src/V55_TeamFeatureWithConfigPaymentStatus.hs @@ -25,10 +25,9 @@ import Imports import Text.RawString.QQ migration :: Migration -migration = Migration 55 "Add payment status config for team features with config" $ do +migration = Migration 55 "Add payment status config for self deleting messages team feature" $ do schema' [r| ALTER TABLE team_features ADD ( - self_deleting_messages_payment_status int, - app_lock_payment_status int, + self_deleting_messages_payment_status int ) |] diff --git a/services/galley/src/Galley/API/Internal.hs b/services/galley/src/Galley/API/Internal.hs index 34bf48d78e..54f4a6a7fa 100644 --- a/services/galley/src/Galley/API/Internal.hs +++ b/services/galley/src/Galley/API/Internal.hs @@ -52,7 +52,7 @@ import Galley.API.Util import Galley.App import Galley.Cassandra.Paging import qualified Galley.Data.Conversation as Data -import Galley.Data.TeamFeatures (HasPaymentStatusCol) +import Galley.Data.TeamFeatures (MaybeHasPaymentStatusCol) import Galley.Effects import Galley.Effects.ClientStore import Galley.Effects.ConversationStore @@ -342,7 +342,7 @@ iGetTeamFeature getter = Features.getFeatureStatus @a getter DontDoAuth iPutTeamFeature :: forall a r. ( Public.KnownTeamFeatureName a, - HasPaymentStatusCol a, + MaybeHasPaymentStatusCol a, Members '[ Error ActionError, Error NotATeamMember, diff --git a/services/galley/src/Galley/API/Teams/Features.hs b/services/galley/src/Galley/API/Teams/Features.hs index be67bec628..9d6aa6777d 100644 --- a/services/galley/src/Galley/API/Teams/Features.hs +++ b/services/galley/src/Galley/API/Teams/Features.hs @@ -119,7 +119,7 @@ getFeatureStatus getter doauth tid = do setFeatureStatus :: forall (a :: Public.TeamFeatureName) r. ( Public.KnownTeamFeatureName a, - HasPaymentStatusCol a, + MaybeHasPaymentStatusCol a, Members '[ Error ActionError, Error TeamError, @@ -592,7 +592,7 @@ getSelfDeletingMessagesInternal = \case setPaymentStatusInternal :: forall (a :: Public.TeamFeatureName) r. - (HasPaymentStatusCol a, Member TeamFeatureStore r) => + (MaybeHasPaymentStatusCol a, Member TeamFeatureStore r) => TeamId -> Public.PaymentStatusValue -> Sem r Public.PaymentStatus diff --git a/services/galley/src/Galley/Cassandra/TeamFeatures.hs b/services/galley/src/Galley/Cassandra/TeamFeatures.hs index 78a7519efa..fe56c81395 100644 --- a/services/galley/src/Galley/Cassandra/TeamFeatures.hs +++ b/services/galley/src/Galley/Cassandra/TeamFeatures.hs @@ -73,13 +73,13 @@ getApplockFeatureStatus tid = do let q = query1 select (params LocalQuorum (Identity tid)) mTuple <- retry x1 q pure $ - mTuple >>= \(mbStatusValue, mbEnforce, mbTimeout, mbPaymentStatusValue) -> - TeamFeatureStatusWithConfig <$> mbStatusValue <*> (TeamFeatureAppLockConfig <$> mbEnforce <*> mbTimeout) <*> Just mbPaymentStatusValue + mTuple >>= \(mbStatusValue, mbEnforce, mbTimeout) -> + TeamFeatureStatusWithConfig <$> mbStatusValue <*> (TeamFeatureAppLockConfig <$> mbEnforce <*> mbTimeout) <*> Nothing where - select :: PrepQuery R (Identity TeamId) (Maybe TeamFeatureStatusValue, Maybe EnforceAppLock, Maybe Int32, Maybe PaymentStatusValue) + select :: PrepQuery R (Identity TeamId) (Maybe TeamFeatureStatusValue, Maybe EnforceAppLock, Maybe Int32) select = fromString $ - "select " <> statusCol @'TeamFeatureAppLock <> ", app_lock_enforce, app_lock_inactivity_timeout_secs, app_lock_payment_status " + "select " <> statusCol @'TeamFeatureAppLock <> ", app_lock_enforce, app_lock_inactivity_timeout_secs " <> "from team_features where team_id = ?" setApplockFeatureStatus :: @@ -118,8 +118,9 @@ getSelfDeletingMessagesStatus tid = do fromString $ "select " <> statusCol @'TeamFeatureSelfDeletingMessages - <> ", self_deleting_messages_ttl, self_deleting_messages_payment_status " - <> "from team_features where team_id = ?" + <> ", self_deleting_messages_ttl, " + <> paymentStatusCol @'TeamFeatureSelfDeletingMessages + <> " from team_features where team_id = ?" setSelfDeletingMessagesStatus :: (MonadClient m) => @@ -143,16 +144,16 @@ setSelfDeletingMessagesStatus tid status = do setPaymentStatus :: forall (a :: TeamFeatureName) m. ( MonadClient m, - HasPaymentStatusCol a + MaybeHasPaymentStatusCol a ) => Proxy a -> TeamId -> PaymentStatus -> m PaymentStatus setPaymentStatus _ tid (PaymentStatus paymentStatus) = - case paymentStatusCol @a of - Nothing -> pure $ PaymentStatus PaymentUnlocked -- todo: what should we do here? probably return an error, UpdatePaymentStatusNotAllowed or sth. similar - Just col -> do + case maybePaymentStatusCol @a of + Nothing -> pure $ PaymentStatus PaymentUnlocked + Just paymentStatusColName -> do retry x5 $ write insert (params LocalQuorum (tid, paymentStatus)) pure (PaymentStatus paymentStatus) where @@ -160,21 +161,21 @@ setPaymentStatus _ tid (PaymentStatus paymentStatus) = insert = fromString $ "insert into team_features (team_id, " - <> col + <> paymentStatusColName <> ") values (?, ?)" getPaymentStatus :: forall (a :: TeamFeatureName) m. ( MonadClient m, - HasPaymentStatusCol a + MaybeHasPaymentStatusCol a ) => Proxy a -> TeamId -> m (Maybe PaymentStatus) getPaymentStatus _ tid = - case paymentStatusCol @a of + case maybePaymentStatusCol @a of Nothing -> pure Nothing - Just col -> do + Just paymentStatusColName -> do let q = query1 select (params LocalQuorum (Identity tid)) mTuple <- (>>= runIdentity) <$> retry x1 q pure $ PaymentStatus <$> mTuple @@ -183,7 +184,7 @@ getPaymentStatus _ tid = select = fromString $ "select " - <> col + <> paymentStatusColName <> " from team_features where team_id = ?" interpretTeamFeatureStoreToCassandra :: diff --git a/services/galley/src/Galley/Data/TeamFeatures.hs b/services/galley/src/Galley/Data/TeamFeatures.hs index e620f7b45b..8c16d26f8e 100644 --- a/services/galley/src/Galley/Data/TeamFeatures.hs +++ b/services/galley/src/Galley/Data/TeamFeatures.hs @@ -15,7 +15,7 @@ -- You should have received a copy of the GNU Affero General Public License along -- with this program. If not, see . -module Galley.Data.TeamFeatures (HasStatusCol (..), HasPaymentStatusCol (..)) where +module Galley.Data.TeamFeatures (HasStatusCol (..), HasPaymentStatusCol (..), MaybeHasPaymentStatusCol (..)) where import Imports import Wire.API.Team.Feature @@ -49,26 +49,32 @@ instance HasStatusCol 'TeamFeatureConferenceCalling where statusCol = "conferenc instance HasStatusCol 'TeamFeatureSelfDeletingMessages where statusCol = "self_deleting_messages_status" +---------------------------------------------------------------------- class HasPaymentStatusCol (a :: TeamFeatureName) where - paymentStatusCol :: Maybe String + paymentStatusCol :: String -instance HasPaymentStatusCol 'TeamFeatureSelfDeletingMessages where - paymentStatusCol = Just "self_deleting_messages_payment_status" +class MaybeHasPaymentStatusCol (a :: TeamFeatureName) where + maybePaymentStatusCol :: Maybe String + +instance {-# OVERLAPPABLE #-} HasPaymentStatusCol a => MaybeHasPaymentStatusCol a where + maybePaymentStatusCol = Just (paymentStatusCol @a) -instance HasPaymentStatusCol 'TeamFeatureLegalHold where paymentStatusCol = Nothing +---------------------------------------------------------------------- +instance HasPaymentStatusCol 'TeamFeatureSelfDeletingMessages where + paymentStatusCol = "self_deleting_messages_payment_status" -instance HasPaymentStatusCol 'TeamFeatureSSO where paymentStatusCol = Nothing +instance MaybeHasPaymentStatusCol 'TeamFeatureLegalHold where maybePaymentStatusCol = Nothing -instance HasPaymentStatusCol 'TeamFeatureSearchVisibility where paymentStatusCol = Nothing +instance MaybeHasPaymentStatusCol 'TeamFeatureSSO where maybePaymentStatusCol = Nothing -instance HasPaymentStatusCol 'TeamFeatureValidateSAMLEmails where paymentStatusCol = Nothing +instance MaybeHasPaymentStatusCol 'TeamFeatureSearchVisibility where maybePaymentStatusCol = Nothing -instance HasPaymentStatusCol 'TeamFeatureDigitalSignatures where paymentStatusCol = Nothing +instance MaybeHasPaymentStatusCol 'TeamFeatureValidateSAMLEmails where maybePaymentStatusCol = Nothing -instance HasPaymentStatusCol 'TeamFeatureAppLock where paymentStatusCol = Just "app_lock_payment_status" +instance MaybeHasPaymentStatusCol 'TeamFeatureDigitalSignatures where maybePaymentStatusCol = Nothing -instance HasPaymentStatusCol 'TeamFeatureFileSharing where paymentStatusCol = Nothing +instance MaybeHasPaymentStatusCol 'TeamFeatureAppLock where maybePaymentStatusCol = Nothing -instance HasPaymentStatusCol 'TeamFeatureClassifiedDomains where paymentStatusCol = Nothing +instance MaybeHasPaymentStatusCol 'TeamFeatureFileSharing where maybePaymentStatusCol = Nothing -instance HasPaymentStatusCol 'TeamFeatureConferenceCalling where paymentStatusCol = Nothing +instance MaybeHasPaymentStatusCol 'TeamFeatureConferenceCalling where maybePaymentStatusCol = Nothing diff --git a/services/galley/src/Galley/Effects/TeamFeatureStore.hs b/services/galley/src/Galley/Effects/TeamFeatureStore.hs index 79b2f93602..2e510dfc49 100644 --- a/services/galley/src/Galley/Effects/TeamFeatureStore.hs +++ b/services/galley/src/Galley/Effects/TeamFeatureStore.hs @@ -71,7 +71,7 @@ data TeamFeatureStore m a where TeamFeatureStore m (TeamFeatureStatus 'TeamFeatureSelfDeletingMessages) SetPaymentStatus' :: forall (a :: TeamFeatureName) m. - ( HasPaymentStatusCol a + ( MaybeHasPaymentStatusCol a ) => Proxy a -> TeamId -> @@ -79,7 +79,7 @@ data TeamFeatureStore m a where TeamFeatureStore m PaymentStatus GetPaymentStatus' :: forall (a :: TeamFeatureName) m. - ( HasPaymentStatusCol a + ( MaybeHasPaymentStatusCol a ) => Proxy a -> TeamId -> @@ -104,7 +104,7 @@ setFeatureStatusNoConfig = setFeatureStatusNoConfig' (Proxy @a) setPaymentStatus :: forall (a :: TeamFeatureName) r. - (Member TeamFeatureStore r, HasPaymentStatusCol a) => + (Member TeamFeatureStore r, MaybeHasPaymentStatusCol a) => TeamId -> PaymentStatus -> Sem r PaymentStatus @@ -112,7 +112,7 @@ setPaymentStatus = setPaymentStatus' (Proxy @a) getPaymentStatus :: forall (a :: TeamFeatureName) r. - (Member TeamFeatureStore r, HasPaymentStatusCol a) => + (Member TeamFeatureStore r, MaybeHasPaymentStatusCol a) => TeamId -> Sem r (Maybe PaymentStatus) getPaymentStatus = getPaymentStatus' (Proxy @a) From 9a09469846eb2b18f75e5ac7cd150aab5d6b0334 Mon Sep 17 00:00:00 2001 From: fisx Date: Thu, 18 Nov 2021 14:14:11 +0100 Subject: [PATCH 03/28] This is a delta for #1916 (#1935) * Fix swagger-1.2. * Simplify. --- libs/wire-api/src/Wire/API/Team/Feature.hs | 12 +++++------ services/galley/src/Galley/API/Internal.hs | 2 +- .../galley/src/Galley/API/Teams/Features.hs | 20 +++++-------------- 3 files changed, 12 insertions(+), 22 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Team/Feature.hs b/libs/wire-api/src/Wire/API/Team/Feature.hs index 9a349ed97d..7da702db99 100644 --- a/libs/wire-api/src/Wire/API/Team/Feature.hs +++ b/libs/wire-api/src/Wire/API/Team/Feature.hs @@ -309,11 +309,11 @@ modelForTeamFeature TeamFeatureSSO = modelTeamFeatureStatusNoConfig modelForTeamFeature TeamFeatureSearchVisibility = modelTeamFeatureStatusNoConfig modelForTeamFeature TeamFeatureValidateSAMLEmails = modelTeamFeatureStatusNoConfig modelForTeamFeature TeamFeatureDigitalSignatures = modelTeamFeatureStatusNoConfig -modelForTeamFeature name@TeamFeatureAppLock = modelTeamFeatureStatusWithConfig name modelTeamFeatureAppLockConfig modelPaymentStatus +modelForTeamFeature name@TeamFeatureAppLock = modelTeamFeatureStatusWithConfig name modelTeamFeatureAppLockConfig modelForTeamFeature TeamFeatureFileSharing = modelTeamFeatureStatusNoConfig -modelForTeamFeature name@TeamFeatureClassifiedDomains = modelTeamFeatureStatusWithConfig name modelTeamFeatureClassifiedDomainsConfig modelPaymentStatus +modelForTeamFeature name@TeamFeatureClassifiedDomains = modelTeamFeatureStatusWithConfig name modelTeamFeatureClassifiedDomainsConfig modelForTeamFeature TeamFeatureConferenceCalling = modelTeamFeatureStatusNoConfig -modelForTeamFeature name@TeamFeatureSelfDeletingMessages = modelTeamFeatureStatusWithConfig name modelTeamFeatureSelfDeletingMessagesConfig modelPaymentStatus +modelForTeamFeature name@TeamFeatureSelfDeletingMessages = modelTeamFeatureStatusWithConfig name modelTeamFeatureSelfDeletingMessagesConfig ---------------------------------------------------------------------- -- TeamFeatureStatusNoConfig @@ -353,12 +353,12 @@ data TeamFeatureStatusWithConfig (cfg :: *) = TeamFeatureStatusWithConfig instance Arbitrary cfg => Arbitrary (TeamFeatureStatusWithConfig cfg) where arbitrary = TeamFeatureStatusWithConfig <$> arbitrary <*> arbitrary <*> arbitrary -modelTeamFeatureStatusWithConfig :: TeamFeatureName -> Doc.Model -> Doc.Model -> Doc.Model -modelTeamFeatureStatusWithConfig name cfgModel paymentStatusModel = Doc.defineModel (cs $ show name) $ do +modelTeamFeatureStatusWithConfig :: TeamFeatureName -> Doc.Model -> Doc.Model +modelTeamFeatureStatusWithConfig name cfgModel = Doc.defineModel (cs $ show name) $ do Doc.description $ "Status and config of " <> cs (show name) Doc.property "status" typeTeamFeatureStatusValue $ Doc.description "status" Doc.property "config" (Doc.ref cfgModel) $ Doc.description "config" - Doc.property "paymentStatus" (Doc.ref paymentStatusModel) $ Doc.description "payment status" + Doc.property "paymentStatus" typePaymentStatusValue $ Doc.optional >> Doc.description "payment status" instance ToSchema cfg => ToSchema (TeamFeatureStatusWithConfig cfg) where schema = diff --git a/services/galley/src/Galley/API/Internal.hs b/services/galley/src/Galley/API/Internal.hs index 54f4a6a7fa..f6ec5c3b99 100644 --- a/services/galley/src/Galley/API/Internal.hs +++ b/services/galley/src/Galley/API/Internal.hs @@ -317,7 +317,7 @@ servantSitemap = iTeamFeatureStatusConferenceCallingGet = iGetTeamFeature @'Public.TeamFeatureConferenceCalling Features.getConferenceCallingInternal, iTeamFeatureStatusSelfDeletingMessagesPut = iPutTeamFeature @'Public.TeamFeatureSelfDeletingMessages Features.setSelfDeletingMessagesInternal, iTeamFeatureStatusSelfDeletingMessagesGet = iGetTeamFeature @'Public.TeamFeatureSelfDeletingMessages Features.getSelfDeletingMessagesInternal, - iTeamFeaturePaymentStatusSelfDeletingMessagesPut = Features.setPaymentStatus @'Public.TeamFeatureSelfDeletingMessages (Features.setPaymentStatusInternal @'Public.TeamFeatureSelfDeletingMessages), + iTeamFeaturePaymentStatusSelfDeletingMessagesPut = Features.setPaymentStatus @'Public.TeamFeatureSelfDeletingMessages, iDeleteUser = rmUser, iConnect = Create.createConnectConversation, iUpsertOne2OneConversation = One2One.iUpsertOne2OneConversation diff --git a/services/galley/src/Galley/API/Teams/Features.hs b/services/galley/src/Galley/API/Teams/Features.hs index 9d6aa6777d..3401b4c6d0 100644 --- a/services/galley/src/Galley/API/Teams/Features.hs +++ b/services/galley/src/Galley/API/Teams/Features.hs @@ -39,7 +39,6 @@ module Galley.API.Teams.Features getConferenceCallingInternal, setConferenceCallingInternal, getSelfDeletingMessagesInternal, - setPaymentStatusInternal, setSelfDeletingMessagesInternal, setPaymentStatus, DoAuth (..), @@ -151,22 +150,22 @@ setFeatureStatus setter doauth tid status = do setPaymentStatus :: forall (a :: Public.TeamFeatureName) r. ( Public.KnownTeamFeatureName a, - HasPaymentStatusCol a, + MaybeHasPaymentStatusCol a, Members [ Error ActionError, Error TeamError, Error NotATeamMember, - TeamStore + TeamStore, + TeamFeatureStore ] r ) => - (TeamId -> Public.PaymentStatusValue -> Sem r Public.PaymentStatus) -> TeamId -> Public.PaymentStatusValue -> Sem r Public.PaymentStatus -setPaymentStatus setter tid paymentStatusUpdate = do +setPaymentStatus tid paymentStatusUpdate = do assertTeamExists tid - setter tid paymentStatusUpdate + TeamFeatures.setPaymentStatus @a tid (Public.PaymentStatus paymentStatusUpdate) -- | For individual users to get feature config for their account (personal or team). getFeatureConfig :: @@ -590,15 +589,6 @@ getSelfDeletingMessagesInternal = \case TeamFeatures.getSelfDeletingMessagesStatus tid <&> fromMaybe Public.defaultSelfDeletingMessagesStatus -setPaymentStatusInternal :: - forall (a :: Public.TeamFeatureName) r. - (MaybeHasPaymentStatusCol a, Member TeamFeatureStore r) => - TeamId -> - Public.PaymentStatusValue -> - Sem r Public.PaymentStatus -setPaymentStatusInternal tid paymentStatus = - TeamFeatures.setPaymentStatus @a tid (Public.PaymentStatus paymentStatus) - setSelfDeletingMessagesInternal :: Members '[GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r => TeamId -> From 99824540a4461c3f7c4b8b7788722ab095108298 Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Thu, 18 Nov 2021 14:18:14 +0100 Subject: [PATCH 04/28] improve comment Co-authored-by: fisx --- libs/wire-api/src/Wire/API/Team/Feature.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/wire-api/src/Wire/API/Team/Feature.hs b/libs/wire-api/src/Wire/API/Team/Feature.hs index 7da702db99..4583397e0e 100644 --- a/libs/wire-api/src/Wire/API/Team/Feature.hs +++ b/libs/wire-api/src/Wire/API/Team/Feature.hs @@ -345,7 +345,7 @@ instance ToSchema TeamFeatureStatusNoConfig where data TeamFeatureStatusWithConfig (cfg :: *) = TeamFeatureStatusWithConfig { tfwcStatus :: TeamFeatureStatusValue, tfwcConfig :: cfg, - tfwcPaymentStatus :: Maybe PaymentStatusValue --FUTUREWORK: remove payment status from set feature status request, it should only be part of the API response + tfwcPaymentStatus :: Maybe PaymentStatusValue -- FUTUREWORK: remove payment status from set feature status request, it should only be part of the API response } deriving stock (Eq, Show, Generic, Typeable) deriving (ToJSON, FromJSON, S.ToSchema) via (Schema (TeamFeatureStatusWithConfig cfg)) From 0a51b92dacc6fc7c770dd77405dd72a14cbbcc8e Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Thu, 18 Nov 2021 14:24:20 +0100 Subject: [PATCH 05/28] simplification --- services/galley/src/Galley/API/Teams/Features.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/services/galley/src/Galley/API/Teams/Features.hs b/services/galley/src/Galley/API/Teams/Features.hs index 3401b4c6d0..33b9dd6188 100644 --- a/services/galley/src/Galley/API/Teams/Features.hs +++ b/services/galley/src/Galley/API/Teams/Features.hs @@ -556,8 +556,7 @@ getClassifiedDomainsInternal _mbtid = do globalConfig <- inputs (view (optSettings . setFeatureFlags . flagClassifiedDomains)) let config = globalConfig pure $ case Public.tfwcStatus config of - Public.TeamFeatureDisabled -> - Public.TeamFeatureStatusWithConfig Public.TeamFeatureDisabled (Public.TeamFeatureClassifiedDomainsConfig []) (Just Public.PaymentLocked) + Public.TeamFeatureDisabled -> Public.defaultClassifiedDomains Public.TeamFeatureEnabled -> config getConferenceCallingInternal :: From f0f50ccaea4d658eaf47cb2299af32d0374bde3f Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Thu, 18 Nov 2021 15:58:26 +0100 Subject: [PATCH 06/28] require HasPaymentStatusCol for setting the payment status --- .../galley/src/Galley/API/Teams/Features.hs | 2 +- .../src/Galley/Cassandra/TeamFeatures.hs | 25 ++++++++----------- .../src/Galley/Effects/TeamFeatureStore.hs | 4 +-- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/services/galley/src/Galley/API/Teams/Features.hs b/services/galley/src/Galley/API/Teams/Features.hs index 33b9dd6188..e5d2e5506b 100644 --- a/services/galley/src/Galley/API/Teams/Features.hs +++ b/services/galley/src/Galley/API/Teams/Features.hs @@ -150,7 +150,7 @@ setFeatureStatus setter doauth tid status = do setPaymentStatus :: forall (a :: Public.TeamFeatureName) r. ( Public.KnownTeamFeatureName a, - MaybeHasPaymentStatusCol a, + HasPaymentStatusCol a, Members [ Error ActionError, Error TeamError, diff --git a/services/galley/src/Galley/Cassandra/TeamFeatures.hs b/services/galley/src/Galley/Cassandra/TeamFeatures.hs index fe56c81395..9452ca31e3 100644 --- a/services/galley/src/Galley/Cassandra/TeamFeatures.hs +++ b/services/galley/src/Galley/Cassandra/TeamFeatures.hs @@ -144,25 +144,22 @@ setSelfDeletingMessagesStatus tid status = do setPaymentStatus :: forall (a :: TeamFeatureName) m. ( MonadClient m, - MaybeHasPaymentStatusCol a + HasPaymentStatusCol a ) => Proxy a -> TeamId -> PaymentStatus -> m PaymentStatus -setPaymentStatus _ tid (PaymentStatus paymentStatus) = - case maybePaymentStatusCol @a of - Nothing -> pure $ PaymentStatus PaymentUnlocked - Just paymentStatusColName -> do - retry x5 $ write insert (params LocalQuorum (tid, paymentStatus)) - pure (PaymentStatus paymentStatus) - where - insert :: PrepQuery W (TeamId, PaymentStatusValue) () - insert = - fromString $ - "insert into team_features (team_id, " - <> paymentStatusColName - <> ") values (?, ?)" +setPaymentStatus _ tid (PaymentStatus paymentStatus) = do + retry x5 $ write insert (params LocalQuorum (tid, paymentStatus)) + pure (PaymentStatus paymentStatus) + where + insert :: PrepQuery W (TeamId, PaymentStatusValue) () + insert = + fromString $ + "insert into team_features (team_id, " + <> paymentStatusCol @a + <> ") values (?, ?)" getPaymentStatus :: forall (a :: TeamFeatureName) m. diff --git a/services/galley/src/Galley/Effects/TeamFeatureStore.hs b/services/galley/src/Galley/Effects/TeamFeatureStore.hs index 2e510dfc49..f7b0188745 100644 --- a/services/galley/src/Galley/Effects/TeamFeatureStore.hs +++ b/services/galley/src/Galley/Effects/TeamFeatureStore.hs @@ -71,7 +71,7 @@ data TeamFeatureStore m a where TeamFeatureStore m (TeamFeatureStatus 'TeamFeatureSelfDeletingMessages) SetPaymentStatus' :: forall (a :: TeamFeatureName) m. - ( MaybeHasPaymentStatusCol a + ( HasPaymentStatusCol a ) => Proxy a -> TeamId -> @@ -104,7 +104,7 @@ setFeatureStatusNoConfig = setFeatureStatusNoConfig' (Proxy @a) setPaymentStatus :: forall (a :: TeamFeatureName) r. - (Member TeamFeatureStore r, MaybeHasPaymentStatusCol a) => + (Member TeamFeatureStore r, HasPaymentStatusCol a) => TeamId -> PaymentStatus -> Sem r PaymentStatus From c1a13073d89be0dfdf17674539005fc3f3a7d75b Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Thu, 18 Nov 2021 16:00:54 +0100 Subject: [PATCH 07/28] clean up --- services/galley/src/Galley/Cassandra/TeamFeatures.hs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/services/galley/src/Galley/Cassandra/TeamFeatures.hs b/services/galley/src/Galley/Cassandra/TeamFeatures.hs index 9452ca31e3..a3ad241795 100644 --- a/services/galley/src/Galley/Cassandra/TeamFeatures.hs +++ b/services/galley/src/Galley/Cassandra/TeamFeatures.hs @@ -157,9 +157,7 @@ setPaymentStatus _ tid (PaymentStatus paymentStatus) = do insert :: PrepQuery W (TeamId, PaymentStatusValue) () insert = fromString $ - "insert into team_features (team_id, " - <> paymentStatusCol @a - <> ") values (?, ?)" + "insert into team_features (team_id, " <> paymentStatusCol @a <> ") values (?, ?)" getPaymentStatus :: forall (a :: TeamFeatureName) m. From 17d6c54a7c5a45da2d22579ae4ae38d4c68564a9 Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Thu, 18 Nov 2021 18:13:46 +0100 Subject: [PATCH 08/28] FeatureStatus with and without PaymentStatus --- libs/galley-types/src/Galley/Types/Teams.hs | 10 +- .../src/Wire/API/Routes/Internal/Brig.hs | 4 +- .../src/Wire/API/Routes/Public/Galley.hs | 44 +++--- .../src/Wire/API/Routes/Public/LegalHold.hs | 4 +- libs/wire-api/src/Wire/API/Team/Feature.hs | 71 ++++++--- ...hConfig_20TeamFeatureAppLockConfig_team.hs | 23 +-- .../golden/Test/Wire/API/Golden/Generator.hs | 4 +- .../API/Golden/Manual/FeatureConfigEvent.hs | 1 - .../testObject_FeatureConfigEvent_3.json | 1 - ...fig_20TeamFeatureAppLockConfig_team_1.json | 1 - ...fig_20TeamFeatureAppLockConfig_team_2.json | 1 - .../unit/Test/Wire/API/Roundtrip/Aeson.hs | 21 +-- services/brig/src/Brig/IO/Intra.hs | 4 +- services/brig/src/Brig/Options.hs | 4 +- services/galley/galley.cabal | 1 + services/galley/src/Galley/API/Internal.hs | 82 +++++----- services/galley/src/Galley/API/Public.hs | 46 +++--- services/galley/src/Galley/API/Teams.hs | 2 +- .../galley/src/Galley/API/Teams/Features.hs | 140 +++++++++--------- .../src/Galley/Cassandra/TeamFeatures.hs | 22 +-- .../src/Galley/Effects/TeamFeatureStore.hs | 24 +-- services/galley/test/integration/API/Teams.hs | 6 +- .../test/integration/API/Teams/Feature.hs | 42 +++--- .../test/integration/API/Teams/LegalHold.hs | 6 +- .../API/Teams/LegalHold/DisabledByDefault.hs | 10 +- .../test/integration/API/Util/TeamFeature.hs | 8 +- services/spar/src/Spar/Intra/Galley.hs | 10 +- tools/stern/src/Stern/API.hs | 34 +++-- tools/stern/src/Stern/Intra.hs | 14 +- 29 files changed, 323 insertions(+), 317 deletions(-) diff --git a/libs/galley-types/src/Galley/Types/Teams.hs b/libs/galley-types/src/Galley/Types/Teams.hs index 8e727e90a1..bcd70f41f9 100644 --- a/libs/galley-types/src/Galley/Types/Teams.hs +++ b/libs/galley-types/src/Galley/Types/Teams.hs @@ -212,11 +212,11 @@ data FeatureFlags = FeatureFlags { _flagSSO :: !FeatureSSO, _flagLegalHold :: !FeatureLegalHold, _flagTeamSearchVisibility :: !FeatureTeamSearchVisibility, - _flagAppLockDefaults :: !(Defaults (TeamFeatureStatus 'TeamFeatureAppLock)), - _flagClassifiedDomains :: !(TeamFeatureStatus 'TeamFeatureClassifiedDomains), - _flagFileSharing :: !(Defaults (TeamFeatureStatus 'TeamFeatureFileSharing)), - _flagConferenceCalling :: !(Defaults (TeamFeatureStatus 'TeamFeatureConferenceCalling)), - _flagSelfDeletingMessages :: !(Defaults (TeamFeatureStatus 'TeamFeatureSelfDeletingMessages)) + _flagAppLockDefaults :: !(Defaults (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureAppLock)), + _flagClassifiedDomains :: !(TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureClassifiedDomains), + _flagFileSharing :: !(Defaults (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureFileSharing)), + _flagConferenceCalling :: !(Defaults (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureConferenceCalling)), + _flagSelfDeletingMessages :: !(Defaults (TeamFeatureStatus 'WithPaymentStatus 'TeamFeatureSelfDeletingMessages)) } deriving (Eq, Show, Generic) diff --git a/libs/wire-api/src/Wire/API/Routes/Internal/Brig.hs b/libs/wire-api/src/Wire/API/Routes/Internal/Brig.hs index 51e34b18d4..b97c6efbfa 100644 --- a/libs/wire-api/src/Wire/API/Routes/Internal/Brig.hs +++ b/libs/wire-api/src/Wire/API/Routes/Internal/Brig.hs @@ -66,7 +66,7 @@ type GetAccountFeatureConfig = :> Capture "uid" UserId :> "features" :> "conferenceCalling" - :> Get '[Servant.JSON] (ApiFt.TeamFeatureStatus 'ApiFt.TeamFeatureConferenceCalling) + :> Get '[Servant.JSON] (ApiFt.TeamFeatureStatus 'ApiFt.WithPaymentStatus 'ApiFt.TeamFeatureConferenceCalling) type PutAccountFeatureConfig = Summary @@ -75,7 +75,7 @@ type PutAccountFeatureConfig = :> Capture "uid" UserId :> "features" :> "conferenceCalling" - :> Servant.ReqBody '[Servant.JSON] (ApiFt.TeamFeatureStatus 'ApiFt.TeamFeatureConferenceCalling) + :> Servant.ReqBody '[Servant.JSON] (ApiFt.TeamFeatureStatus 'ApiFt.WithoutPaymentStatus 'ApiFt.TeamFeatureConferenceCalling) :> Put '[Servant.JSON] NoContent type DeleteAccountFeatureConfig = diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Galley.hs b/libs/wire-api/src/Wire/API/Routes/Public/Galley.hs index 7aafbfa7bf..afa0ba0272 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Galley.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Galley.hs @@ -623,7 +623,7 @@ data Api routes = Api :- FeatureStatusPut 'TeamFeatureSearchVisibility, teamFeatureStatusSearchVisibilityDeprecatedGet :: routes - :- FeatureStatusDeprecatedGet 'TeamFeatureSearchVisibility, + :- FeatureStatusDeprecatedGet 'WithoutPaymentStatus 'TeamFeatureSearchVisibility, teamFeatureStatusSearchVisibilityDeprecatedPut :: routes :- FeatureStatusDeprecatedPut 'TeamFeatureSearchVisibility, @@ -632,13 +632,13 @@ data Api routes = Api :- FeatureStatusGet 'TeamFeatureValidateSAMLEmails, teamFeatureStatusValidateSAMLEmailsDeprecatedGet :: routes - :- FeatureStatusDeprecatedGet 'TeamFeatureValidateSAMLEmails, + :- FeatureStatusDeprecatedGet 'WithoutPaymentStatus 'TeamFeatureValidateSAMLEmails, teamFeatureStatusDigitalSignaturesGet :: routes :- FeatureStatusGet 'TeamFeatureDigitalSignatures, teamFeatureStatusDigitalSignaturesDeprecatedGet :: routes - :- FeatureStatusDeprecatedGet 'TeamFeatureDigitalSignatures, + :- FeatureStatusDeprecatedGet 'WithoutPaymentStatus 'TeamFeatureDigitalSignatures, teamFeatureStatusAppLockGet :: routes :- FeatureStatusGet 'TeamFeatureAppLock, @@ -668,34 +668,34 @@ data Api routes = Api :- AllFeatureConfigsGet, featureConfigLegalHoldGet :: routes - :- FeatureConfigGet 'TeamFeatureLegalHold, + :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureLegalHold, featureConfigSSOGet :: routes - :- FeatureConfigGet 'TeamFeatureSSO, + :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureSSO, featureConfigSearchVisibilityGet :: routes - :- FeatureConfigGet 'TeamFeatureSearchVisibility, + :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureSearchVisibility, featureConfigValidateSAMLEmailsGet :: routes - :- FeatureConfigGet 'TeamFeatureValidateSAMLEmails, + :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureValidateSAMLEmails, featureConfigDigitalSignaturesGet :: routes - :- FeatureConfigGet 'TeamFeatureDigitalSignatures, + :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureDigitalSignatures, featureConfigAppLockGet :: routes - :- FeatureConfigGet 'TeamFeatureAppLock, + :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureAppLock, featureConfigFileSharingGet :: routes - :- FeatureConfigGet 'TeamFeatureFileSharing, + :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureFileSharing, featureConfigClassifiedDomainsGet :: routes - :- FeatureConfigGet 'TeamFeatureClassifiedDomains, + :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureClassifiedDomains, featureConfigConferenceCallingGet :: routes - :- FeatureConfigGet 'TeamFeatureConferenceCalling, + :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureConferenceCalling, featureConfigSelfDeletingMessagesGet :: routes - :- FeatureConfigGet 'TeamFeatureSelfDeletingMessages + :- FeatureConfigGet 'WithPaymentStatus 'TeamFeatureSelfDeletingMessages } deriving (Generic) @@ -708,7 +708,7 @@ type FeatureStatusGet featureName = :> Capture "tid" TeamId :> "features" :> KnownTeamFeatureNameSymbol featureName - :> Get '[Servant.JSON] (TeamFeatureStatus featureName) + :> Get '[Servant.JSON] (TeamFeatureStatus 'WithPaymentStatus featureName) type FeatureStatusPut featureName = Summary (AppendSymbol "Put config for " (KnownTeamFeatureNameSymbol featureName)) @@ -717,18 +717,18 @@ type FeatureStatusPut featureName = :> Capture "tid" TeamId :> "features" :> KnownTeamFeatureNameSymbol featureName - :> ReqBody '[Servant.JSON] (TeamFeatureStatus featureName) - :> Put '[Servant.JSON] (TeamFeatureStatus featureName) + :> ReqBody '[Servant.JSON] (TeamFeatureStatus 'WithoutPaymentStatus featureName) + :> Put '[Servant.JSON] (TeamFeatureStatus 'WithoutPaymentStatus featureName) -- | A type for a GET endpoint for a feature with a deprecated path -type FeatureStatusDeprecatedGet featureName = +type FeatureStatusDeprecatedGet ps featureName = Summary (AppendSymbol "[deprecated] Get config for " (KnownTeamFeatureNameSymbol featureName)) :> ZUser :> "teams" :> Capture "tid" TeamId :> "features" :> DeprecatedFeatureName featureName - :> Get '[Servant.JSON] (TeamFeatureStatus featureName) + :> Get '[Servant.JSON] (TeamFeatureStatus ps featureName) -- | A type for a PUT endpoint for a feature with a deprecated path type FeatureStatusDeprecatedPut featureName = @@ -738,15 +738,15 @@ type FeatureStatusDeprecatedPut featureName = :> Capture "tid" TeamId :> "features" :> DeprecatedFeatureName featureName - :> ReqBody '[Servant.JSON] (TeamFeatureStatus featureName) - :> Put '[Servant.JSON] (TeamFeatureStatus featureName) + :> ReqBody '[Servant.JSON] (TeamFeatureStatus 'WithoutPaymentStatus featureName) + :> Put '[Servant.JSON] (TeamFeatureStatus 'WithoutPaymentStatus featureName) -type FeatureConfigGet featureName = +type FeatureConfigGet ps featureName = Summary (AppendSymbol "Get feature config for feature " (KnownTeamFeatureNameSymbol featureName)) :> ZUser :> "feature-configs" :> KnownTeamFeatureNameSymbol featureName - :> Get '[Servant.JSON] (TeamFeatureStatus featureName) + :> Get '[Servant.JSON] (TeamFeatureStatus ps featureName) type AllFeatureConfigsGet = Summary "Get configurations of all features" diff --git a/libs/wire-api/src/Wire/API/Routes/Public/LegalHold.hs b/libs/wire-api/src/Wire/API/Routes/Public/LegalHold.hs index 6bb24b7543..67dd19e0bc 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/LegalHold.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/LegalHold.hs @@ -52,9 +52,9 @@ type PublicAPI = type InternalAPI = "i" :> "teams" :> Capture "tid" TeamId :> "legalhold" - :> Get '[JSON] (TeamFeatureStatus 'TeamFeatureLegalHold) + :> Get '[JSON] (TeamFeatureStatus 'WithPaymentStatus 'TeamFeatureLegalHold) :<|> "i" :> "teams" :> Capture "tid" TeamId :> "legalhold" - :> ReqBody '[JSON] (TeamFeatureStatus 'TeamFeatureLegalHold) + :> ReqBody '[JSON] (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureLegalHold) :> Put '[] NoContent swaggerDoc :: Swagger diff --git a/libs/wire-api/src/Wire/API/Team/Feature.hs b/libs/wire-api/src/Wire/API/Team/Feature.hs index 4583397e0e..f4c40b8dbf 100644 --- a/libs/wire-api/src/Wire/API/Team/Feature.hs +++ b/libs/wire-api/src/Wire/API/Team/Feature.hs @@ -30,10 +30,12 @@ module Wire.API.Team.Feature KnownTeamFeatureName (..), TeamFeatureStatusNoConfig (..), TeamFeatureStatusWithConfig (..), + TeamFeatureStatusWithConfigAndPaymentStatus (..), HasDeprecatedFeatureName (..), AllFeatureConfigs (..), PaymentStatus (..), PaymentStatusValue (..), + IncludePaymentStatus (..), defaultAppLockStatus, defaultClassifiedDomains, defaultSelfDeletingMessagesStatus, @@ -46,6 +48,7 @@ module Wire.API.Team.Feature modelTeamFeatureAppLockConfig, modelTeamFeatureClassifiedDomainsConfig, modelTeamFeatureSelfDeletingMessagesConfig, + modelTeamFeatureStatusWithConfigAndPaymentStatus, modelForTeamFeature, modelPaymentStatus, ) @@ -288,19 +291,22 @@ instance Cass.Cql TeamFeatureStatusValue where ---------------------------------------------------------------------- -- TeamFeatureStatus -type family TeamFeatureStatus (a :: TeamFeatureName) :: * where - TeamFeatureStatus 'TeamFeatureLegalHold = TeamFeatureStatusNoConfig - TeamFeatureStatus 'TeamFeatureSSO = TeamFeatureStatusNoConfig - TeamFeatureStatus 'TeamFeatureSearchVisibility = TeamFeatureStatusNoConfig - TeamFeatureStatus 'TeamFeatureValidateSAMLEmails = TeamFeatureStatusNoConfig - TeamFeatureStatus 'TeamFeatureDigitalSignatures = TeamFeatureStatusNoConfig - TeamFeatureStatus 'TeamFeatureAppLock = TeamFeatureStatusWithConfig TeamFeatureAppLockConfig - TeamFeatureStatus 'TeamFeatureFileSharing = TeamFeatureStatusNoConfig - TeamFeatureStatus 'TeamFeatureClassifiedDomains = TeamFeatureStatusWithConfig TeamFeatureClassifiedDomainsConfig - TeamFeatureStatus 'TeamFeatureConferenceCalling = TeamFeatureStatusNoConfig - TeamFeatureStatus 'TeamFeatureSelfDeletingMessages = TeamFeatureStatusWithConfig TeamFeatureSelfDeletingMessagesConfig +data IncludePaymentStatus = WithPaymentStatus | WithoutPaymentStatus -type FeatureHasNoConfig (a :: TeamFeatureName) = (TeamFeatureStatus a ~ TeamFeatureStatusNoConfig) :: Constraint +type family TeamFeatureStatus (ps :: IncludePaymentStatus) (a :: TeamFeatureName) :: * where + TeamFeatureStatus _ 'TeamFeatureLegalHold = TeamFeatureStatusNoConfig + TeamFeatureStatus _ 'TeamFeatureSSO = TeamFeatureStatusNoConfig + TeamFeatureStatus _ 'TeamFeatureSearchVisibility = TeamFeatureStatusNoConfig + TeamFeatureStatus _ 'TeamFeatureValidateSAMLEmails = TeamFeatureStatusNoConfig + TeamFeatureStatus _ 'TeamFeatureDigitalSignatures = TeamFeatureStatusNoConfig + TeamFeatureStatus _ 'TeamFeatureAppLock = TeamFeatureStatusWithConfig TeamFeatureAppLockConfig + TeamFeatureStatus _ 'TeamFeatureFileSharing = TeamFeatureStatusNoConfig + TeamFeatureStatus _ 'TeamFeatureClassifiedDomains = TeamFeatureStatusWithConfig TeamFeatureClassifiedDomainsConfig + TeamFeatureStatus _ 'TeamFeatureConferenceCalling = TeamFeatureStatusNoConfig + TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages = TeamFeatureStatusWithConfig TeamFeatureSelfDeletingMessagesConfig + TeamFeatureStatus 'WithPaymentStatus 'TeamFeatureSelfDeletingMessages = TeamFeatureStatusWithConfigAndPaymentStatus TeamFeatureSelfDeletingMessagesConfig + +type FeatureHasNoConfig (a :: TeamFeatureName) = (TeamFeatureStatus 'WithoutPaymentStatus a ~ TeamFeatureStatusNoConfig) :: Constraint -- if you add a new constructor here, don't forget to add it to the swagger (1.2) docs in "Wire.API.Swagger"! modelForTeamFeature :: TeamFeatureName -> Doc.Model @@ -344,21 +350,19 @@ instance ToSchema TeamFeatureStatusNoConfig where -- to recreate the config every time it's turned on. data TeamFeatureStatusWithConfig (cfg :: *) = TeamFeatureStatusWithConfig { tfwcStatus :: TeamFeatureStatusValue, - tfwcConfig :: cfg, - tfwcPaymentStatus :: Maybe PaymentStatusValue -- FUTUREWORK: remove payment status from set feature status request, it should only be part of the API response + tfwcConfig :: cfg } deriving stock (Eq, Show, Generic, Typeable) deriving (ToJSON, FromJSON, S.ToSchema) via (Schema (TeamFeatureStatusWithConfig cfg)) instance Arbitrary cfg => Arbitrary (TeamFeatureStatusWithConfig cfg) where - arbitrary = TeamFeatureStatusWithConfig <$> arbitrary <*> arbitrary <*> arbitrary + arbitrary = TeamFeatureStatusWithConfig <$> arbitrary <*> arbitrary modelTeamFeatureStatusWithConfig :: TeamFeatureName -> Doc.Model -> Doc.Model modelTeamFeatureStatusWithConfig name cfgModel = Doc.defineModel (cs $ show name) $ do Doc.description $ "Status and config of " <> cs (show name) Doc.property "status" typeTeamFeatureStatusValue $ Doc.description "status" Doc.property "config" (Doc.ref cfgModel) $ Doc.description "config" - Doc.property "paymentStatus" typePaymentStatusValue $ Doc.optional >> Doc.description "payment status" instance ToSchema cfg => ToSchema (TeamFeatureStatusWithConfig cfg) where schema = @@ -366,7 +370,32 @@ instance ToSchema cfg => ToSchema (TeamFeatureStatusWithConfig cfg) where TeamFeatureStatusWithConfig <$> tfwcStatus .= field "status" schema <*> tfwcConfig .= field "config" schema - <*> tfwcPaymentStatus .= opt (field "paymentStatus" schema) + +data TeamFeatureStatusWithConfigAndPaymentStatus (cfg :: *) = TeamFeatureStatusWithConfigAndPaymentStatus + { tfwcapsStatus :: TeamFeatureStatusValue, + tfwcapsConfig :: cfg, + tfwcapsPaymentStatus :: PaymentStatusValue + } + deriving stock (Eq, Show, Generic, Typeable) + deriving (ToJSON, FromJSON, S.ToSchema) via (Schema (TeamFeatureStatusWithConfigAndPaymentStatus cfg)) + +instance Arbitrary cfg => Arbitrary (TeamFeatureStatusWithConfigAndPaymentStatus cfg) where + arbitrary = TeamFeatureStatusWithConfigAndPaymentStatus <$> arbitrary <*> arbitrary <*> arbitrary + +modelTeamFeatureStatusWithConfigAndPaymentStatus :: TeamFeatureName -> Doc.Model -> Doc.Model +modelTeamFeatureStatusWithConfigAndPaymentStatus name cfgModel = Doc.defineModel (cs $ show name) $ do + Doc.description $ "Status and config of " <> cs (show name) + Doc.property "status" typeTeamFeatureStatusValue $ Doc.description "status" + Doc.property "config" (Doc.ref cfgModel) $ Doc.description "config" + Doc.property "paymentStatus" typePaymentStatusValue $ Doc.description "config" + +instance ToSchema cfg => ToSchema (TeamFeatureStatusWithConfigAndPaymentStatus cfg) where + schema = + object "TeamFeatureStatusWithConfigAndPaymentStatus" $ + TeamFeatureStatusWithConfigAndPaymentStatus + <$> tfwcapsStatus .= field "status" schema + <*> tfwcapsConfig .= field "config" schema + <*> tfwcapsPaymentStatus .= field "paymentStatus" schema ---------------------------------------------------------------------- -- TeamFeatureClassifiedDomainsConfig @@ -395,7 +424,6 @@ defaultClassifiedDomains = TeamFeatureStatusWithConfig TeamFeatureDisabled (TeamFeatureClassifiedDomainsConfig []) - $ Just PaymentLocked ---------------------------------------------------------------------- -- TeamFeatureAppLockConfig @@ -435,7 +463,6 @@ defaultAppLockStatus = TeamFeatureStatusWithConfig TeamFeatureEnabled (TeamFeatureAppLockConfig (EnforceAppLock False) 60) - $ Just PaymentLocked ---------------------------------------------------------------------- -- TeamFeatureSelfDeletingMessagesConfig @@ -458,12 +485,12 @@ modelTeamFeatureSelfDeletingMessagesConfig = Doc.defineModel "TeamFeatureSelfDeletingMessagesConfig" $ do Doc.property "enforcedTimeoutSeconds" Doc.int32' $ Doc.description "optional; default: `0` (no enforcement)" -defaultSelfDeletingMessagesStatus :: TeamFeatureStatusWithConfig TeamFeatureSelfDeletingMessagesConfig +defaultSelfDeletingMessagesStatus :: TeamFeatureStatusWithConfigAndPaymentStatus TeamFeatureSelfDeletingMessagesConfig defaultSelfDeletingMessagesStatus = - TeamFeatureStatusWithConfig + TeamFeatureStatusWithConfigAndPaymentStatus TeamFeatureEnabled (TeamFeatureSelfDeletingMessagesConfig 0) - $ Just PaymentLocked + PaymentLocked ---------------------------------------------------------------------- -- PaymentStatus diff --git a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team.hs b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team.hs index 20241d1700..4013a22392 100644 --- a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team.hs +++ b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generated/TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team.hs @@ -18,10 +18,9 @@ -- with this program. If not, see . module Test.Wire.API.Golden.Generated.TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team where -import Imports (Bool (False, True), Maybe (..)) +import Imports (Bool (False, True)) import Wire.API.Team.Feature ( EnforceAppLock (EnforceAppLock), - PaymentStatusValue (..), TeamFeatureAppLockConfig (..), TeamFeatureStatusValue (TeamFeatureDisabled, TeamFeatureEnabled), TeamFeatureStatusWithConfig (..), @@ -32,7 +31,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_1 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_1 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, - tfwcPaymentStatus = Just PaymentLocked, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = -98} } @@ -42,7 +40,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_2 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_2 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, - tfwcPaymentStatus = Just PaymentUnlocked, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = 14} } @@ -52,7 +49,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_3 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_3 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = 92} } @@ -62,7 +58,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_4 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_4 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = 45} } @@ -72,7 +67,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_5 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_5 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = 119} } @@ -82,7 +76,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_6 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_6 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = -50} } @@ -92,7 +85,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_7 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_7 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = -50} } @@ -102,7 +94,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_8 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_8 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = -76} } @@ -112,7 +103,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_9 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_9 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = 96} } @@ -122,7 +112,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_10 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_10 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = 120} } @@ -132,7 +121,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_11 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_11 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = 62} } @@ -142,7 +130,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_12 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_12 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = -50} } @@ -152,7 +139,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_13 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_13 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = -99} } @@ -162,7 +148,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_14 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_14 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = -96} } @@ -172,7 +157,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_15 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_15 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = -12} } @@ -182,7 +166,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_16 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_16 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = -60} } @@ -192,7 +175,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_17 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_17 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = 100} } @@ -202,7 +184,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_18 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_18 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = 74} } @@ -212,7 +193,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_19 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_19 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureDisabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock False, applockInactivityTimeoutSecs = -125} } @@ -222,7 +202,6 @@ testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_20 :: testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_20 = TeamFeatureStatusWithConfig { tfwcStatus = TeamFeatureEnabled, - tfwcPaymentStatus = Nothing, tfwcConfig = TeamFeatureAppLockConfig {applockEnforceAppLock = EnforceAppLock True, applockInactivityTimeoutSecs = 69} } diff --git a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generator.hs b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generator.hs index 4d022f0eac..3480c55814 100644 --- a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generator.hs +++ b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generator.hs @@ -328,8 +328,8 @@ generateTestModule = do generateBindingModule @Team.TeamDeleteData "team" ref generateBindingModule @Team.Conversation.TeamConversation "team" ref generateBindingModule @Team.Conversation.TeamConversationList "team" ref - generateBindingModule @(Team.Feature.TeamFeatureStatus 'Team.Feature.TeamFeatureLegalHold) "team" ref - generateBindingModule @(Team.Feature.TeamFeatureStatus 'Team.Feature.TeamFeatureAppLock) "team" ref + generateBindingModule @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureLegalHold) "team" ref + generateBindingModule @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureAppLock) "team" ref generateBindingModule @Team.Feature.TeamFeatureStatusValue "team" ref generateBindingModule @Team.Invitation.InvitationRequest "team" ref generateBindingModule @Team.Invitation.Invitation "team" ref diff --git a/libs/wire-api/test/golden/Test/Wire/API/Golden/Manual/FeatureConfigEvent.hs b/libs/wire-api/test/golden/Test/Wire/API/Golden/Manual/FeatureConfigEvent.hs index 23756080e4..2e5f9f85d3 100644 --- a/libs/wire-api/test/golden/Test/Wire/API/Golden/Manual/FeatureConfigEvent.hs +++ b/libs/wire-api/test/golden/Test/Wire/API/Golden/Manual/FeatureConfigEvent.hs @@ -19,6 +19,5 @@ testObject_FeatureConfigEvent_3 = ( TeamFeatureStatusWithConfig TeamFeatureDisabled (TeamFeatureAppLockConfig (EnforceAppLock True) 300) - $ Just PaymentLocked ) ) diff --git a/libs/wire-api/test/golden/testObject_FeatureConfigEvent_3.json b/libs/wire-api/test/golden/testObject_FeatureConfigEvent_3.json index f44a4c313d..2a7c5fdfe0 100644 --- a/libs/wire-api/test/golden/testObject_FeatureConfigEvent_3.json +++ b/libs/wire-api/test/golden/testObject_FeatureConfigEvent_3.json @@ -4,7 +4,6 @@ "enforceAppLock": true, "inactivityTimeoutSecs": 300 }, - "paymentStatus": "locked", "status": "disabled" }, "name": "appLock", diff --git a/libs/wire-api/test/golden/testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_1.json b/libs/wire-api/test/golden/testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_1.json index dbab959e8c..66a69f69b1 100644 --- a/libs/wire-api/test/golden/testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_1.json +++ b/libs/wire-api/test/golden/testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_1.json @@ -3,6 +3,5 @@ "enforceAppLock": false, "inactivityTimeoutSecs": -98 }, - "paymentStatus": "locked", "status": "disabled" } diff --git a/libs/wire-api/test/golden/testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_2.json b/libs/wire-api/test/golden/testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_2.json index df4873983c..e566224c5f 100644 --- a/libs/wire-api/test/golden/testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_2.json +++ b/libs/wire-api/test/golden/testObject_TeamFeatureStatusWithConfig_20TeamFeatureAppLockConfig_team_2.json @@ -3,6 +3,5 @@ "enforceAppLock": false, "inactivityTimeoutSecs": 14 }, - "paymentStatus": "unlocked", "status": "enabled" } diff --git a/libs/wire-api/test/unit/Test/Wire/API/Roundtrip/Aeson.hs b/libs/wire-api/test/unit/Test/Wire/API/Roundtrip/Aeson.hs index 4000a866e0..f9c67d7d30 100644 --- a/libs/wire-api/test/unit/Test/Wire/API/Roundtrip/Aeson.hs +++ b/libs/wire-api/test/unit/Test/Wire/API/Roundtrip/Aeson.hs @@ -195,16 +195,17 @@ tests = testRoundTrip @Team.TeamDeleteData, testRoundTrip @Team.Conversation.TeamConversation, testRoundTrip @Team.Conversation.TeamConversationList, - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.TeamFeatureLegalHold), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.TeamFeatureSSO), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.TeamFeatureSearchVisibility), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.TeamFeatureValidateSAMLEmails), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.TeamFeatureDigitalSignatures), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.TeamFeatureAppLock), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.TeamFeatureFileSharing), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.TeamFeatureClassifiedDomains), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.TeamFeatureConferenceCalling), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.TeamFeatureSelfDeletingMessages), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureLegalHold), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureSSO), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureSearchVisibility), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureValidateSAMLEmails), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureDigitalSignatures), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureAppLock), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureFileSharing), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureClassifiedDomains), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureConferenceCalling), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureSelfDeletingMessages), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithPaymentStatus 'Team.Feature.TeamFeatureSelfDeletingMessages), testRoundTrip @Team.Feature.TeamFeatureStatusValue, testRoundTrip @Team.Feature.PaymentStatusValue, testRoundTrip @Team.Feature.PaymentStatus, diff --git a/services/brig/src/Brig/IO/Intra.hs b/services/brig/src/Brig/IO/Intra.hs index df063cbdd0..f7192d3c36 100644 --- a/services/brig/src/Brig/IO/Intra.hs +++ b/services/brig/src/Brig/IO/Intra.hs @@ -121,7 +121,7 @@ import Wire.API.Federation.API.Brig import Wire.API.Federation.Client import Wire.API.Federation.Error (federationNotImplemented) import Wire.API.Message (UserClients) -import Wire.API.Team.Feature (TeamFeatureName (..), TeamFeatureStatus) +import Wire.API.Team.Feature (IncludePaymentStatus (..), TeamFeatureName (..), TeamFeatureStatus) import Wire.API.Team.LegalHold (LegalholdProtectee) ----------------------------------------------------------------------------- @@ -968,7 +968,7 @@ getTeamName tid = do . expect2xx -- | Calls 'Galley.API.getTeamFeatureStatusH'. -getTeamLegalHoldStatus :: TeamId -> AppIO (TeamFeatureStatus 'TeamFeatureLegalHold) +getTeamLegalHoldStatus :: TeamId -> AppIO (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureLegalHold) getTeamLegalHoldStatus tid = do debug $ remote "galley" . msg (val "Get legalhold settings") galleyRequest GET req >>= decodeBody "galley" diff --git a/services/brig/src/Brig/Options.hs b/services/brig/src/Brig/Options.hs index 7710b7608e..cd8d5f8603 100644 --- a/services/brig/src/Brig/Options.hs +++ b/services/brig/src/Brig/Options.hs @@ -508,8 +508,8 @@ data Settings = Settings -- they are grandfathered), and feature-specific extra data (eg., TLL for self-deleting -- messages). For now, we have something quick & simple. data AccountFeatureConfigs = AccountFeatureConfigs - { afcConferenceCallingDefNew :: !(ApiFT.TeamFeatureStatus 'ApiFT.TeamFeatureConferenceCalling), - afcConferenceCallingDefNull :: !(ApiFT.TeamFeatureStatus 'ApiFT.TeamFeatureConferenceCalling) + { afcConferenceCallingDefNew :: !(ApiFT.TeamFeatureStatus 'ApiFT.WithoutPaymentStatus 'ApiFT.TeamFeatureConferenceCalling), + afcConferenceCallingDefNull :: !(ApiFT.TeamFeatureStatus 'ApiFT.WithoutPaymentStatus 'ApiFT.TeamFeatureConferenceCalling) } deriving (Show, Eq, Generic) deriving (Arbitrary) via (GenericUniform AccountFeatureConfigs) diff --git a/services/galley/galley.cabal b/services/galley/galley.cabal index 3f237fe667..f2c0e83012 100644 --- a/services/galley/galley.cabal +++ b/services/galley/galley.cabal @@ -466,6 +466,7 @@ executable galley-schema ld-options: -static default-language: Haskell2010 +-- FUTUREWORK(Leif): rename to galley-tests here and in the package.yaml file test-suite galley-types-tests type: exitcode-stdio-1.0 main-is: Main.hs diff --git a/services/galley/src/Galley/API/Internal.hs b/services/galley/src/Galley/API/Internal.hs index f6ec5c3b99..76541fcc30 100644 --- a/services/galley/src/Galley/API/Internal.hs +++ b/services/galley/src/Galley/API/Internal.hs @@ -122,79 +122,79 @@ data InternalApi routes = InternalApi -- Viewing the config for features should be allowed for any admin. iTeamFeatureStatusSSOGet :: routes - :- IFeatureStatusGet 'Public.TeamFeatureSSO, + :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureSSO, iTeamFeatureStatusSSOPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureSSO, iTeamFeatureStatusLegalHoldGet :: routes - :- IFeatureStatusGet 'Public.TeamFeatureLegalHold, + :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureLegalHold, iTeamFeatureStatusLegalHoldPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureLegalHold, iTeamFeatureStatusSearchVisibilityGet :: routes - :- IFeatureStatusGet 'Public.TeamFeatureSearchVisibility, + :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureSearchVisibility, iTeamFeatureStatusSearchVisibilityPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureSearchVisibility, iTeamFeatureStatusSearchVisibilityDeprecatedGet :: routes - :- IFeatureStatusDeprecatedGet 'Public.TeamFeatureSearchVisibility, + :- IFeatureStatusDeprecatedGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureSearchVisibility, iTeamFeatureStatusSearchVisibilityDeprecatedPut :: routes :- IFeatureStatusDeprecatedPut 'Public.TeamFeatureSearchVisibility, iTeamFeatureStatusValidateSAMLEmailsGet :: routes - :- IFeatureStatusGet 'Public.TeamFeatureValidateSAMLEmails, + :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureValidateSAMLEmails, iTeamFeatureStatusValidateSAMLEmailsPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureValidateSAMLEmails, iTeamFeatureStatusValidateSAMLEmailsDeprecatedGet :: routes - :- IFeatureStatusDeprecatedGet 'Public.TeamFeatureValidateSAMLEmails, + :- IFeatureStatusDeprecatedGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureValidateSAMLEmails, iTeamFeatureStatusValidateSAMLEmailsDeprecatedPut :: routes :- IFeatureStatusDeprecatedPut 'Public.TeamFeatureValidateSAMLEmails, iTeamFeatureStatusDigitalSignaturesGet :: routes - :- IFeatureStatusGet 'Public.TeamFeatureDigitalSignatures, + :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureDigitalSignatures, iTeamFeatureStatusDigitalSignaturesPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureDigitalSignatures, iTeamFeatureStatusDigitalSignaturesDeprecatedGet :: routes - :- IFeatureStatusDeprecatedGet 'Public.TeamFeatureDigitalSignatures, + :- IFeatureStatusDeprecatedGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureDigitalSignatures, iTeamFeatureStatusDigitalSignaturesDeprecatedPut :: routes :- IFeatureStatusDeprecatedPut 'Public.TeamFeatureDigitalSignatures, iTeamFeatureStatusAppLockGet :: routes - :- IFeatureStatusGet 'Public.TeamFeatureAppLock, + :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureAppLock, iTeamFeatureStatusAppLockPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureAppLock, iTeamFeatureStatusFileSharingGet :: routes - :- IFeatureStatusGet 'Public.TeamFeatureFileSharing, + :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureFileSharing, iTeamFeatureStatusFileSharingPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureFileSharing, iTeamFeatureStatusClassifiedDomainsGet :: routes - :- IFeatureStatusGet 'Public.TeamFeatureClassifiedDomains, + :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureClassifiedDomains, iTeamFeatureStatusConferenceCallingPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureConferenceCalling, iTeamFeatureStatusConferenceCallingGet :: routes - :- IFeatureStatusGet 'Public.TeamFeatureConferenceCalling, + :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureConferenceCalling, iTeamFeatureStatusSelfDeletingMessagesPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureSelfDeletingMessages, iTeamFeatureStatusSelfDeletingMessagesGet :: routes - :- IFeatureStatusGet 'Public.TeamFeatureSelfDeletingMessages, + :- IFeatureStatusGet 'Public.WithPaymentStatus 'Public.TeamFeatureSelfDeletingMessages, iTeamFeaturePaymentStatusSelfDeletingMessagesPut :: routes :- IFeatureStatusPaymentStatusPut 'Public.TeamFeatureSelfDeletingMessages, @@ -236,14 +236,14 @@ data InternalApi routes = InternalApi type ServantAPI = ToServantApi InternalApi -type IFeatureStatusGet featureName = +type IFeatureStatusGet paymentStatus featureName = Summary (AppendSymbol "Get config for " (Public.KnownTeamFeatureNameSymbol featureName)) :> "i" :> "teams" :> Capture "tid" TeamId :> "features" :> Public.KnownTeamFeatureNameSymbol featureName - :> Get '[Servant.JSON] (Public.TeamFeatureStatus featureName) + :> Get '[Servant.JSON] (Public.TeamFeatureStatus paymentStatus featureName) type IFeatureStatusPut featureName = Summary (AppendSymbol "Put config for " (Public.KnownTeamFeatureNameSymbol featureName)) @@ -252,8 +252,8 @@ type IFeatureStatusPut featureName = :> Capture "tid" TeamId :> "features" :> Public.KnownTeamFeatureNameSymbol featureName - :> ReqBody '[Servant.JSON] (Public.TeamFeatureStatus featureName) - :> Put '[Servant.JSON] (Public.TeamFeatureStatus featureName) + :> ReqBody '[Servant.JSON] (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus featureName) + :> Put '[Servant.JSON] (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus featureName) type IFeatureStatusPaymentStatusPut featureName = Summary (AppendSymbol "(Un-) lock payment for " (Public.KnownTeamFeatureNameSymbol featureName)) @@ -266,14 +266,14 @@ type IFeatureStatusPaymentStatusPut featureName = :> Put '[Servant.JSON] Public.PaymentStatus -- | A type for a GET endpoint for a feature with a deprecated path -type IFeatureStatusDeprecatedGet featureName = +type IFeatureStatusDeprecatedGet paymentStatus featureName = Summary (AppendSymbol "[deprecated] Get config for " (Public.KnownTeamFeatureNameSymbol featureName)) :> "i" :> "teams" :> Capture "tid" TeamId :> "features" :> Public.DeprecatedFeatureName featureName - :> Get '[Servant.JSON] (Public.TeamFeatureStatus featureName) + :> Get '[Servant.JSON] (Public.TeamFeatureStatus paymentStatus featureName) -- | A type for a PUT endpoint for a feature with a deprecated path type IFeatureStatusDeprecatedPut featureName = @@ -283,8 +283,8 @@ type IFeatureStatusDeprecatedPut featureName = :> Capture "tid" TeamId :> "features" :> Public.DeprecatedFeatureName featureName - :> ReqBody '[Servant.JSON] (Public.TeamFeatureStatus featureName) - :> Put '[Servant.JSON] (Public.TeamFeatureStatus featureName) + :> ReqBody '[Servant.JSON] (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus featureName) + :> Put '[Servant.JSON] (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus featureName) servantSitemap :: ServerT ServantAPI (Sem GalleyEffects) servantSitemap = @@ -292,31 +292,31 @@ servantSitemap = InternalApi { iStatusGet = pure NoContent, iStatusHead = pure NoContent, - iTeamFeatureStatusSSOGet = iGetTeamFeature @'Public.TeamFeatureSSO Features.getSSOStatusInternal, + iTeamFeatureStatusSSOGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO Features.getSSOStatusInternal, iTeamFeatureStatusSSOPut = iPutTeamFeature @'Public.TeamFeatureSSO Features.setSSOStatusInternal, - iTeamFeatureStatusLegalHoldGet = iGetTeamFeature @'Public.TeamFeatureLegalHold Features.getLegalholdStatusInternal, + iTeamFeatureStatusLegalHoldGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold Features.getLegalholdStatusInternal, iTeamFeatureStatusLegalHoldPut = iPutTeamFeature @'Public.TeamFeatureLegalHold (Features.setLegalholdStatusInternal @InternalPaging), - iTeamFeatureStatusSearchVisibilityGet = iGetTeamFeature @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal, + iTeamFeatureStatusSearchVisibilityGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal, iTeamFeatureStatusSearchVisibilityPut = iPutTeamFeature @'Public.TeamFeatureLegalHold Features.setTeamSearchVisibilityAvailableInternal, - iTeamFeatureStatusSearchVisibilityDeprecatedGet = iGetTeamFeature @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal, + iTeamFeatureStatusSearchVisibilityDeprecatedGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal, iTeamFeatureStatusSearchVisibilityDeprecatedPut = iPutTeamFeature @'Public.TeamFeatureLegalHold Features.setTeamSearchVisibilityAvailableInternal, - iTeamFeatureStatusValidateSAMLEmailsGet = iGetTeamFeature @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal, + iTeamFeatureStatusValidateSAMLEmailsGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal, iTeamFeatureStatusValidateSAMLEmailsPut = iPutTeamFeature @'Public.TeamFeatureValidateSAMLEmails Features.setValidateSAMLEmailsInternal, - iTeamFeatureStatusValidateSAMLEmailsDeprecatedGet = iGetTeamFeature @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal, + iTeamFeatureStatusValidateSAMLEmailsDeprecatedGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal, iTeamFeatureStatusValidateSAMLEmailsDeprecatedPut = iPutTeamFeature @'Public.TeamFeatureValidateSAMLEmails Features.setValidateSAMLEmailsInternal, - iTeamFeatureStatusDigitalSignaturesGet = iGetTeamFeature @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal, + iTeamFeatureStatusDigitalSignaturesGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal, iTeamFeatureStatusDigitalSignaturesPut = iPutTeamFeature @'Public.TeamFeatureDigitalSignatures Features.setDigitalSignaturesInternal, - iTeamFeatureStatusDigitalSignaturesDeprecatedGet = iGetTeamFeature @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal, + iTeamFeatureStatusDigitalSignaturesDeprecatedGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal, iTeamFeatureStatusDigitalSignaturesDeprecatedPut = iPutTeamFeature @'Public.TeamFeatureDigitalSignatures Features.setDigitalSignaturesInternal, - iTeamFeatureStatusAppLockGet = iGetTeamFeature @'Public.TeamFeatureAppLock Features.getAppLockInternal, + iTeamFeatureStatusAppLockGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureAppLock Features.getAppLockInternal, iTeamFeatureStatusAppLockPut = iPutTeamFeature @'Public.TeamFeatureAppLock Features.setAppLockInternal, - iTeamFeatureStatusFileSharingGet = iGetTeamFeature @'Public.TeamFeatureFileSharing Features.getFileSharingInternal, + iTeamFeatureStatusFileSharingGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureFileSharing Features.getFileSharingInternal, iTeamFeatureStatusFileSharingPut = iPutTeamFeature @'Public.TeamFeatureFileSharing Features.setFileSharingInternal, - iTeamFeatureStatusClassifiedDomainsGet = iGetTeamFeature @'Public.TeamFeatureClassifiedDomains Features.getClassifiedDomainsInternal, + iTeamFeatureStatusClassifiedDomainsGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureClassifiedDomains Features.getClassifiedDomainsInternal, iTeamFeatureStatusConferenceCallingPut = iPutTeamFeature @'Public.TeamFeatureConferenceCalling Features.setConferenceCallingInternal, - iTeamFeatureStatusConferenceCallingGet = iGetTeamFeature @'Public.TeamFeatureConferenceCalling Features.getConferenceCallingInternal, + iTeamFeatureStatusConferenceCallingGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling Features.getConferenceCallingInternal, iTeamFeatureStatusSelfDeletingMessagesPut = iPutTeamFeature @'Public.TeamFeatureSelfDeletingMessages Features.setSelfDeletingMessagesInternal, - iTeamFeatureStatusSelfDeletingMessagesGet = iGetTeamFeature @'Public.TeamFeatureSelfDeletingMessages Features.getSelfDeletingMessagesInternal, + iTeamFeatureStatusSelfDeletingMessagesGet = iGetTeamFeature @'Public.WithPaymentStatus @'Public.TeamFeatureSelfDeletingMessages Features.getSelfDeletingMessagesInternal, iTeamFeaturePaymentStatusSelfDeletingMessagesPut = Features.setPaymentStatus @'Public.TeamFeatureSelfDeletingMessages, iDeleteUser = rmUser, iConnect = Create.createConnectConversation, @@ -324,7 +324,7 @@ servantSitemap = } iGetTeamFeature :: - forall a r. + forall ps a r. ( Public.KnownTeamFeatureName a, Members '[ Error ActionError, @@ -334,10 +334,10 @@ iGetTeamFeature :: ] r ) => - (Features.GetFeatureInternalParam -> Sem r (Public.TeamFeatureStatus a)) -> + (Features.GetFeatureInternalParam -> Sem r (Public.TeamFeatureStatus ps a)) -> TeamId -> - Sem r (Public.TeamFeatureStatus a) -iGetTeamFeature getter = Features.getFeatureStatus @a getter DontDoAuth + Sem r (Public.TeamFeatureStatus ps a) +iGetTeamFeature getter = Features.getFeatureStatus @ps @a getter DontDoAuth iPutTeamFeature :: forall a r. @@ -353,10 +353,10 @@ iPutTeamFeature :: ] r ) => - (TeamId -> Public.TeamFeatureStatus a -> Sem r (Public.TeamFeatureStatus a)) -> + (TeamId -> Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a -> Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a)) -> TeamId -> - Public.TeamFeatureStatus a -> - Sem r (Public.TeamFeatureStatus a) + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) iPutTeamFeature setter = Features.setFeatureStatus @a setter DontDoAuth sitemap :: Routes a (Sem GalleyEffects) () diff --git a/services/galley/src/Galley/API/Public.hs b/services/galley/src/Galley/API/Public.hs index 3027ba070a..632873f5f5 100644 --- a/services/galley/src/Galley/API/Public.hs +++ b/services/galley/src/Galley/API/Public.hs @@ -117,70 +117,70 @@ servantSitemap = GalleyAPI.postOtrMessageUnqualified = Update.postOtrMessageUnqualified, GalleyAPI.postProteusMessage = Update.postProteusMessage, GalleyAPI.teamFeatureStatusSSOGet = - getFeatureStatus @'Public.TeamFeatureSSO Features.getSSOStatusInternal + getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO Features.getSSOStatusInternal . DoAuth, GalleyAPI.teamFeatureStatusLegalHoldGet = - getFeatureStatus @'Public.TeamFeatureLegalHold Features.getLegalholdStatusInternal + getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold Features.getLegalholdStatusInternal . DoAuth, GalleyAPI.teamFeatureStatusLegalHoldPut = setFeatureStatus @'Public.TeamFeatureLegalHold (Features.setLegalholdStatusInternal @InternalPaging) . DoAuth, GalleyAPI.teamFeatureStatusSearchVisibilityGet = - getFeatureStatus @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal + getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal . DoAuth, GalleyAPI.teamFeatureStatusSearchVisibilityPut = setFeatureStatus @'Public.TeamFeatureSearchVisibility Features.setTeamSearchVisibilityAvailableInternal . DoAuth, GalleyAPI.teamFeatureStatusSearchVisibilityDeprecatedGet = - getFeatureStatus @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal + getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal . DoAuth, GalleyAPI.teamFeatureStatusSearchVisibilityDeprecatedPut = setFeatureStatus @'Public.TeamFeatureSearchVisibility Features.setTeamSearchVisibilityAvailableInternal . DoAuth, GalleyAPI.teamFeatureStatusValidateSAMLEmailsGet = - getFeatureStatus @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal + getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal . DoAuth, GalleyAPI.teamFeatureStatusValidateSAMLEmailsDeprecatedGet = - getFeatureStatus @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal + getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal . DoAuth, GalleyAPI.teamFeatureStatusDigitalSignaturesGet = - getFeatureStatus @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal + getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal . DoAuth, GalleyAPI.teamFeatureStatusDigitalSignaturesDeprecatedGet = - getFeatureStatus @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal + getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal . DoAuth, GalleyAPI.teamFeatureStatusAppLockGet = - getFeatureStatus @'Public.TeamFeatureAppLock Features.getAppLockInternal + getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureAppLock Features.getAppLockInternal . DoAuth, GalleyAPI.teamFeatureStatusAppLockPut = setFeatureStatus @'Public.TeamFeatureAppLock Features.setAppLockInternal . DoAuth, GalleyAPI.teamFeatureStatusFileSharingGet = - getFeatureStatus @'Public.TeamFeatureFileSharing Features.getFileSharingInternal . DoAuth, + getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureFileSharing Features.getFileSharingInternal . DoAuth, GalleyAPI.teamFeatureStatusFileSharingPut = setFeatureStatus @'Public.TeamFeatureFileSharing Features.setFileSharingInternal . DoAuth, GalleyAPI.teamFeatureStatusClassifiedDomainsGet = - getFeatureStatus @'Public.TeamFeatureClassifiedDomains Features.getClassifiedDomainsInternal + getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureClassifiedDomains Features.getClassifiedDomainsInternal . DoAuth, GalleyAPI.teamFeatureStatusConferenceCallingGet = - getFeatureStatus @'Public.TeamFeatureConferenceCalling Features.getConferenceCallingInternal + getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling Features.getConferenceCallingInternal . DoAuth, GalleyAPI.teamFeatureStatusSelfDeletingMessagesGet = - getFeatureStatus @'Public.TeamFeatureSelfDeletingMessages Features.getSelfDeletingMessagesInternal + getFeatureStatus @'Public.WithPaymentStatus @'Public.TeamFeatureSelfDeletingMessages Features.getSelfDeletingMessagesInternal . DoAuth, GalleyAPI.teamFeatureStatusSelfDeletingMessagesPut = setFeatureStatus @'Public.TeamFeatureSelfDeletingMessages Features.setSelfDeletingMessagesInternal . DoAuth, GalleyAPI.featureAllFeatureConfigsGet = Features.getAllFeatureConfigs, - GalleyAPI.featureConfigLegalHoldGet = Features.getFeatureConfig @'Public.TeamFeatureLegalHold Features.getLegalholdStatusInternal, - GalleyAPI.featureConfigSSOGet = Features.getFeatureConfig @'Public.TeamFeatureSSO Features.getSSOStatusInternal, - GalleyAPI.featureConfigSearchVisibilityGet = Features.getFeatureConfig @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal, - GalleyAPI.featureConfigValidateSAMLEmailsGet = Features.getFeatureConfig @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal, - GalleyAPI.featureConfigDigitalSignaturesGet = Features.getFeatureConfig @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal, - GalleyAPI.featureConfigAppLockGet = Features.getFeatureConfig @'Public.TeamFeatureAppLock Features.getAppLockInternal, - GalleyAPI.featureConfigFileSharingGet = Features.getFeatureConfig @'Public.TeamFeatureFileSharing Features.getFileSharingInternal, - GalleyAPI.featureConfigClassifiedDomainsGet = Features.getFeatureConfig @'Public.TeamFeatureClassifiedDomains Features.getClassifiedDomainsInternal, - GalleyAPI.featureConfigConferenceCallingGet = Features.getFeatureConfig @'Public.TeamFeatureConferenceCalling Features.getConferenceCallingInternal, - GalleyAPI.featureConfigSelfDeletingMessagesGet = Features.getFeatureConfig @'Public.TeamFeatureSelfDeletingMessages Features.getSelfDeletingMessagesInternal + GalleyAPI.featureConfigLegalHoldGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold Features.getLegalholdStatusInternal, + GalleyAPI.featureConfigSSOGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO Features.getSSOStatusInternal, + GalleyAPI.featureConfigSearchVisibilityGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal, + GalleyAPI.featureConfigValidateSAMLEmailsGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal, + GalleyAPI.featureConfigDigitalSignaturesGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal, + GalleyAPI.featureConfigAppLockGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureAppLock Features.getAppLockInternal, + GalleyAPI.featureConfigFileSharingGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureFileSharing Features.getFileSharingInternal, + GalleyAPI.featureConfigClassifiedDomainsGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureClassifiedDomains Features.getClassifiedDomainsInternal, + GalleyAPI.featureConfigConferenceCallingGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling Features.getConferenceCallingInternal, + GalleyAPI.featureConfigSelfDeletingMessagesGet = Features.getFeatureConfig @'Public.WithPaymentStatus @'Public.TeamFeatureSelfDeletingMessages Features.getSelfDeletingMessagesInternal } sitemap :: Routes ApiBuilder (Sem GalleyEffects) () diff --git a/services/galley/src/Galley/API/Teams.hs b/services/galley/src/Galley/API/Teams.hs index ce9b1ef65b..ab74d16933 100644 --- a/services/galley/src/Galley/API/Teams.hs +++ b/services/galley/src/Galley/API/Teams.hs @@ -1522,7 +1522,7 @@ canUserJoinTeam tid = do getTeamSearchVisibilityAvailableInternal :: Members '[Input Opts, TeamFeatureStore] r => TeamId -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureSearchVisibility) + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSearchVisibility) getTeamSearchVisibilityAvailableInternal tid = do -- TODO: This is just redundant given there is a decent default defConfig <- do diff --git a/services/galley/src/Galley/API/Teams/Features.hs b/services/galley/src/Galley/API/Teams/Features.hs index e5d2e5506b..e225e12808 100644 --- a/services/galley/src/Galley/API/Teams/Features.hs +++ b/services/galley/src/Galley/API/Teams/Features.hs @@ -91,7 +91,7 @@ data DoAuth = DoAuth UserId | DontDoAuth -- | For team-settings, to administrate team feature configuration. Here we have an admin uid -- and a team id, but no uid of the member for which the feature config holds. getFeatureStatus :: - forall (a :: Public.TeamFeatureName) r. + forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName) r. ( Public.KnownTeamFeatureName a, Members '[ Error ActionError, @@ -101,10 +101,10 @@ getFeatureStatus :: ] r ) => - (GetFeatureInternalParam -> Sem r (Public.TeamFeatureStatus a)) -> + (GetFeatureInternalParam -> Sem r (Public.TeamFeatureStatus ps a)) -> DoAuth -> TeamId -> - Sem r (Public.TeamFeatureStatus a) + Sem r (Public.TeamFeatureStatus ps a) getFeatureStatus getter doauth tid = do case doauth of DoAuth uid -> do @@ -129,11 +129,11 @@ setFeatureStatus :: ] r ) => - (TeamId -> Public.TeamFeatureStatus a -> Sem r (Public.TeamFeatureStatus a)) -> + (TeamId -> Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a -> Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a)) -> DoAuth -> TeamId -> - Public.TeamFeatureStatus a -> - Sem r (Public.TeamFeatureStatus a) + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) setFeatureStatus setter doauth tid status = do case doauth of DoAuth uid -> do @@ -169,7 +169,7 @@ setPaymentStatus tid paymentStatusUpdate = do -- | For individual users to get feature config for their account (personal or team). getFeatureConfig :: - forall (a :: Public.TeamFeatureName) r. + forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName) r. ( Public.KnownTeamFeatureName a, Members '[ Error ActionError, @@ -179,9 +179,9 @@ getFeatureConfig :: ] r ) => - (GetFeatureInternalParam -> Sem r (Public.TeamFeatureStatus a)) -> + (GetFeatureInternalParam -> Sem r (Public.TeamFeatureStatus ps a)) -> UserId -> - Sem r (Public.TeamFeatureStatus a) + Sem r (Public.TeamFeatureStatus ps a) getFeatureConfig getter zusr = do mbTeam <- getOneUserTeam zusr case mbTeam of @@ -210,12 +210,12 @@ getAllFeatureConfigs zusr = do mbTeam <- getOneUserTeam zusr zusrMembership <- maybe (pure Nothing) (flip getTeamMember zusr) mbTeam let getStatus :: - forall (a :: Public.TeamFeatureName) r. + forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName) r. ( Public.KnownTeamFeatureName a, - Aeson.ToJSON (Public.TeamFeatureStatus a), + Aeson.ToJSON (Public.TeamFeatureStatus ps a), Members '[Error ActionError, Error TeamError, Error NotATeamMember, TeamStore] r ) => - (GetFeatureInternalParam -> Sem r (Public.TeamFeatureStatus a)) -> + (GetFeatureInternalParam -> Sem r (Public.TeamFeatureStatus ps a)) -> Sem r (Text, Aeson.Value) getStatus getter = do when (isJust mbTeam) $ do @@ -226,16 +226,16 @@ getAllFeatureConfigs zusr = do AllFeatureConfigs . HashMap.fromList <$> sequence - [ getStatus @'Public.TeamFeatureLegalHold getLegalholdStatusInternal, - getStatus @'Public.TeamFeatureSSO getSSOStatusInternal, - getStatus @'Public.TeamFeatureSearchVisibility getTeamSearchVisibilityAvailableInternal, - getStatus @'Public.TeamFeatureValidateSAMLEmails getValidateSAMLEmailsInternal, - getStatus @'Public.TeamFeatureDigitalSignatures getDigitalSignaturesInternal, - getStatus @'Public.TeamFeatureAppLock getAppLockInternal, - getStatus @'Public.TeamFeatureFileSharing getFileSharingInternal, - getStatus @'Public.TeamFeatureClassifiedDomains getClassifiedDomainsInternal, - getStatus @'Public.TeamFeatureConferenceCalling getConferenceCallingInternal, - getStatus @'Public.TeamFeatureSelfDeletingMessages getSelfDeletingMessagesInternal + [ getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold getLegalholdStatusInternal, + getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO getSSOStatusInternal, + getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility getTeamSearchVisibilityAvailableInternal, + getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails getValidateSAMLEmailsInternal, + getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures getDigitalSignaturesInternal, + getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureAppLock getAppLockInternal, + getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureFileSharing getFileSharingInternal, + getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureClassifiedDomains getClassifiedDomainsInternal, + getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling getConferenceCallingInternal, + getStatus @'Public.WithPaymentStatus @'Public.TeamFeatureSelfDeletingMessages getSelfDeletingMessagesInternal ] getAllFeaturesH :: @@ -274,27 +274,27 @@ getAllFeatures :: getAllFeatures uid tid = do Aeson.object <$> sequence - [ getStatus @'Public.TeamFeatureSSO getSSOStatusInternal, - getStatus @'Public.TeamFeatureLegalHold getLegalholdStatusInternal, - getStatus @'Public.TeamFeatureSearchVisibility getTeamSearchVisibilityAvailableInternal, - getStatus @'Public.TeamFeatureValidateSAMLEmails getValidateSAMLEmailsInternal, - getStatus @'Public.TeamFeatureDigitalSignatures getDigitalSignaturesInternal, - getStatus @'Public.TeamFeatureAppLock getAppLockInternal, - getStatus @'Public.TeamFeatureFileSharing getFileSharingInternal, - getStatus @'Public.TeamFeatureClassifiedDomains getClassifiedDomainsInternal, - getStatus @'Public.TeamFeatureConferenceCalling getConferenceCallingInternal, - getStatus @'Public.TeamFeatureSelfDeletingMessages getSelfDeletingMessagesInternal + [ getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO getSSOStatusInternal, + getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold getLegalholdStatusInternal, + getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility getTeamSearchVisibilityAvailableInternal, + getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails getValidateSAMLEmailsInternal, + getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures getDigitalSignaturesInternal, + getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureAppLock getAppLockInternal, + getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureFileSharing getFileSharingInternal, + getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureClassifiedDomains getClassifiedDomainsInternal, + getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling getConferenceCallingInternal, + getStatus @'Public.WithPaymentStatus @'Public.TeamFeatureSelfDeletingMessages getSelfDeletingMessagesInternal ] where getStatus :: - forall (a :: Public.TeamFeatureName). + forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName). ( Public.KnownTeamFeatureName a, - Aeson.ToJSON (Public.TeamFeatureStatus a) + Aeson.ToJSON (Public.TeamFeatureStatus ps a) ) => - (GetFeatureInternalParam -> Sem r (Public.TeamFeatureStatus a)) -> + (GetFeatureInternalParam -> Sem r (Public.TeamFeatureStatus ps a)) -> Sem r (Text, Aeson.Value) getStatus getter = do - status <- getFeatureStatus @a getter (DoAuth uid) tid + status <- getFeatureStatus @ps @a getter (DoAuth uid) tid let feature = Public.knownTeamFeatureName @a pure $ cs (toByteString' feature) Aeson..= status @@ -306,7 +306,7 @@ getFeatureStatusNoConfig :: ) => Sem r Public.TeamFeatureStatusValue -> TeamId -> - Sem r (Public.TeamFeatureStatus a) + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) getFeatureStatusNoConfig getDefault tid = do defaultStatus <- Public.TeamFeatureStatusNoConfig <$> getDefault fromMaybe defaultStatus <$> TeamFeatures.getFeatureStatusNoConfig @a tid @@ -320,8 +320,8 @@ setFeatureStatusNoConfig :: ) => (Public.TeamFeatureStatusValue -> TeamId -> Sem r ()) -> TeamId -> - Public.TeamFeatureStatus a -> - Sem r (Public.TeamFeatureStatus a) + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) setFeatureStatusNoConfig applyState tid status = do applyState (Public.tfwoStatus status) tid newStatus <- TeamFeatures.setFeatureStatusNoConfig @a tid status @@ -336,7 +336,7 @@ type GetFeatureInternalParam = Either (Maybe UserId) TeamId getSSOStatusInternal :: Members '[Input Opts, TeamFeatureStore] r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureSSO) + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSSO) getSSOStatusInternal = either (const $ Public.TeamFeatureStatusNoConfig <$> getDef) @@ -351,8 +351,8 @@ getSSOStatusInternal = setSSOStatusInternal :: Members '[Error TeamFeatureError, GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r => TeamId -> - Public.TeamFeatureStatus 'Public.TeamFeatureSSO -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureSSO) + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSSO -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSSO) setSSOStatusInternal = setFeatureStatusNoConfig @'Public.TeamFeatureSSO $ \case Public.TeamFeatureDisabled -> const (throw DisableSsoNotImplemented) Public.TeamFeatureEnabled -> const (pure ()) @@ -360,7 +360,7 @@ setSSOStatusInternal = setFeatureStatusNoConfig @'Public.TeamFeatureSSO $ \case getTeamSearchVisibilityAvailableInternal :: Members '[Input Opts, TeamFeatureStore] r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureSearchVisibility) + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSearchVisibility) getTeamSearchVisibilityAvailableInternal = either (const $ Public.TeamFeatureStatusNoConfig <$> getDef) @@ -374,8 +374,8 @@ getTeamSearchVisibilityAvailableInternal = setTeamSearchVisibilityAvailableInternal :: Members '[GundeckAccess, SearchVisibilityStore, TeamFeatureStore, TeamStore, P.TinyLog] r => TeamId -> - Public.TeamFeatureStatus 'Public.TeamFeatureSearchVisibility -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureSearchVisibility) + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSearchVisibility -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSearchVisibility) setTeamSearchVisibilityAvailableInternal = setFeatureStatusNoConfig @'Public.TeamFeatureSearchVisibility $ \case Public.TeamFeatureDisabled -> SearchVisibilityData.resetSearchVisibility Public.TeamFeatureEnabled -> const (pure ()) @@ -383,7 +383,7 @@ setTeamSearchVisibilityAvailableInternal = setFeatureStatusNoConfig @'Public.Tea getValidateSAMLEmailsInternal :: Member TeamFeatureStore r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureValidateSAMLEmails) + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureValidateSAMLEmails) getValidateSAMLEmailsInternal = either (const $ Public.TeamFeatureStatusNoConfig <$> getDef) @@ -397,14 +397,14 @@ getValidateSAMLEmailsInternal = setValidateSAMLEmailsInternal :: Members '[GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r => TeamId -> - Public.TeamFeatureStatus 'Public.TeamFeatureValidateSAMLEmails -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureValidateSAMLEmails) + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureValidateSAMLEmails -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureValidateSAMLEmails) setValidateSAMLEmailsInternal = setFeatureStatusNoConfig @'Public.TeamFeatureValidateSAMLEmails $ \_ _ -> pure () getDigitalSignaturesInternal :: Member TeamFeatureStore r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureDigitalSignatures) + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureDigitalSignatures) getDigitalSignaturesInternal = either (const $ Public.TeamFeatureStatusNoConfig <$> getDef) @@ -418,14 +418,14 @@ getDigitalSignaturesInternal = setDigitalSignaturesInternal :: Members '[GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r => TeamId -> - Public.TeamFeatureStatus 'Public.TeamFeatureDigitalSignatures -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureDigitalSignatures) + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureDigitalSignatures -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureDigitalSignatures) setDigitalSignaturesInternal = setFeatureStatusNoConfig @'Public.TeamFeatureDigitalSignatures $ \_ _ -> pure () getLegalholdStatusInternal :: Members '[LegalHoldStore, TeamFeatureStore, TeamStore] r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureLegalHold) + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureLegalHold) getLegalholdStatusInternal (Left _) = pure $ Public.TeamFeatureStatusNoConfig Public.TeamFeatureDisabled getLegalholdStatusInternal (Right tid) = do @@ -468,8 +468,8 @@ setLegalholdStatusInternal :: r ) => TeamId -> - Public.TeamFeatureStatus 'Public.TeamFeatureLegalHold -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureLegalHold) + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureLegalHold -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureLegalHold) setLegalholdStatusInternal tid status@(Public.tfwoStatus -> statusValue) = do do -- this extra do is to encapsulate the assertions running before the actual operation. @@ -494,7 +494,7 @@ setLegalholdStatusInternal tid status@(Public.tfwoStatus -> statusValue) = do getFileSharingInternal :: Members '[Input Opts, TeamFeatureStore] r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureFileSharing) + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureFileSharing) getFileSharingInternal = getFeatureStatusWithDefaultConfig @'Public.TeamFeatureFileSharing flagFileSharing . either (const Nothing) Just @@ -505,9 +505,9 @@ getFeatureStatusWithDefaultConfig :: FeatureHasNoConfig a, Members '[Input Opts, TeamFeatureStore] r ) => - Lens' FeatureFlags (Defaults (Public.TeamFeatureStatus a)) -> + Lens' FeatureFlags (Defaults (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a)) -> Maybe TeamId -> - Sem r (Public.TeamFeatureStatus a) + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) getFeatureStatusWithDefaultConfig lens' = maybe (Public.TeamFeatureStatusNoConfig <$> getDef) @@ -521,14 +521,14 @@ getFeatureStatusWithDefaultConfig lens' = setFileSharingInternal :: Members '[GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r => TeamId -> - Public.TeamFeatureStatus 'Public.TeamFeatureFileSharing -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureFileSharing) + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureFileSharing -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureFileSharing) setFileSharingInternal = setFeatureStatusNoConfig @'Public.TeamFeatureFileSharing $ \_status _tid -> pure () getAppLockInternal :: Members '[Input Opts, TeamFeatureStore] r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureAppLock) + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureAppLock) getAppLockInternal mbtid = do Defaults defaultStatus <- inputs (view (optSettings . setFeatureFlags . flagAppLockDefaults)) status <- @@ -538,8 +538,8 @@ getAppLockInternal mbtid = do setAppLockInternal :: Members '[GundeckAccess, TeamFeatureStore, TeamStore, Error TeamFeatureError, P.TinyLog] r => TeamId -> - Public.TeamFeatureStatus 'Public.TeamFeatureAppLock -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureAppLock) + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureAppLock -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureAppLock) setAppLockInternal tid status = do when (Public.applockInactivityTimeoutSecs (Public.tfwcConfig status) < 30) $ throw AppLockinactivityTimeoutTooLow @@ -551,7 +551,7 @@ setAppLockInternal tid status = do getClassifiedDomainsInternal :: Member (Input Opts) r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureClassifiedDomains) + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureClassifiedDomains) getClassifiedDomainsInternal _mbtid = do globalConfig <- inputs (view (optSettings . setFeatureFlags . flagClassifiedDomains)) let config = globalConfig @@ -562,7 +562,7 @@ getClassifiedDomainsInternal _mbtid = do getConferenceCallingInternal :: Members '[BrigAccess, Input Opts, TeamFeatureStore] r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureConferenceCalling) + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureConferenceCalling) getConferenceCallingInternal (Left (Just uid)) = do getFeatureConfigViaAccount @'Public.TeamFeatureConferenceCalling uid getConferenceCallingInternal (Left Nothing) = do @@ -573,15 +573,15 @@ getConferenceCallingInternal (Right tid) = do setConferenceCallingInternal :: Members '[GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r => TeamId -> - Public.TeamFeatureStatus 'Public.TeamFeatureConferenceCalling -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureConferenceCalling) + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureConferenceCalling -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureConferenceCalling) setConferenceCallingInternal = setFeatureStatusNoConfig @'Public.TeamFeatureConferenceCalling $ \_status _tid -> pure () getSelfDeletingMessagesInternal :: Member TeamFeatureStore r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureSelfDeletingMessages) + Sem r (Public.TeamFeatureStatus 'Public.WithPaymentStatus 'Public.TeamFeatureSelfDeletingMessages) getSelfDeletingMessagesInternal = \case Left _ -> pure Public.defaultSelfDeletingMessagesStatus Right tid -> @@ -591,8 +591,8 @@ getSelfDeletingMessagesInternal = \case setSelfDeletingMessagesInternal :: Members '[GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r => TeamId -> - Public.TeamFeatureStatus 'Public.TeamFeatureSelfDeletingMessages -> - Sem r (Public.TeamFeatureStatus 'Public.TeamFeatureSelfDeletingMessages) + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSelfDeletingMessages -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSelfDeletingMessages) setSelfDeletingMessagesInternal tid st = do let pushEvent = pushFeatureConfigEvent tid $ @@ -624,5 +624,5 @@ getFeatureConfigViaAccount :: Member BrigAccess r ) => UserId -> - Sem r (Public.TeamFeatureStatus flag) + Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus flag) getFeatureConfigViaAccount = getAccountFeatureConfigClient diff --git a/services/galley/src/Galley/Cassandra/TeamFeatures.hs b/services/galley/src/Galley/Cassandra/TeamFeatures.hs index a3ad241795..7f1bb44a65 100644 --- a/services/galley/src/Galley/Cassandra/TeamFeatures.hs +++ b/services/galley/src/Galley/Cassandra/TeamFeatures.hs @@ -37,7 +37,7 @@ getFeatureStatusNoConfig :: ) => Proxy a -> TeamId -> - m (Maybe (TeamFeatureStatus a)) + m (Maybe (TeamFeatureStatus 'WithoutPaymentStatus a)) getFeatureStatusNoConfig _ tid = do let q = query1 select (params LocalQuorum (Identity tid)) mStatusValue <- (>>= runIdentity) <$> retry x1 q @@ -54,8 +54,8 @@ setFeatureStatusNoConfig :: ) => Proxy a -> TeamId -> - TeamFeatureStatus a -> - m (TeamFeatureStatus a) + TeamFeatureStatus 'WithoutPaymentStatus a -> + m (TeamFeatureStatus 'WithoutPaymentStatus a) setFeatureStatusNoConfig _ tid status = do let flag = tfwoStatus status retry x5 $ write insert (params LocalQuorum (tid, flag)) @@ -68,13 +68,13 @@ getApplockFeatureStatus :: forall m. (MonadClient m) => TeamId -> - m (Maybe (TeamFeatureStatus 'TeamFeatureAppLock)) + m (Maybe (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureAppLock)) getApplockFeatureStatus tid = do let q = query1 select (params LocalQuorum (Identity tid)) mTuple <- retry x1 q pure $ mTuple >>= \(mbStatusValue, mbEnforce, mbTimeout) -> - TeamFeatureStatusWithConfig <$> mbStatusValue <*> (TeamFeatureAppLockConfig <$> mbEnforce <*> mbTimeout) <*> Nothing + TeamFeatureStatusWithConfig <$> mbStatusValue <*> (TeamFeatureAppLockConfig <$> mbEnforce <*> mbTimeout) where select :: PrepQuery R (Identity TeamId) (Maybe TeamFeatureStatusValue, Maybe EnforceAppLock, Maybe Int32) select = @@ -85,8 +85,8 @@ getApplockFeatureStatus tid = do setApplockFeatureStatus :: (MonadClient m) => TeamId -> - TeamFeatureStatus 'TeamFeatureAppLock -> - m (TeamFeatureStatus 'TeamFeatureAppLock) + TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureAppLock -> + m (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureAppLock) setApplockFeatureStatus tid status = do let statusValue = tfwcStatus status enforce = applockEnforceAppLock . tfwcConfig $ status @@ -105,13 +105,13 @@ getSelfDeletingMessagesStatus :: forall m. (MonadClient m) => TeamId -> - m (Maybe (TeamFeatureStatus 'TeamFeatureSelfDeletingMessages)) + m (Maybe (TeamFeatureStatus 'WithPaymentStatus 'TeamFeatureSelfDeletingMessages)) getSelfDeletingMessagesStatus tid = do let q = query1 select (params LocalQuorum (Identity tid)) mTuple <- retry x1 q pure $ mTuple >>= \(mbStatusValue, mbTimeout, mbPaymentStatusValue) -> - TeamFeatureStatusWithConfig <$> mbStatusValue <*> (TeamFeatureSelfDeletingMessagesConfig <$> mbTimeout) <*> Just mbPaymentStatusValue + TeamFeatureStatusWithConfigAndPaymentStatus <$> mbStatusValue <*> (TeamFeatureSelfDeletingMessagesConfig <$> mbTimeout) <*> mbPaymentStatusValue where select :: PrepQuery R (Identity TeamId) (Maybe TeamFeatureStatusValue, Maybe Int32, Maybe PaymentStatusValue) select = @@ -125,8 +125,8 @@ getSelfDeletingMessagesStatus tid = do setSelfDeletingMessagesStatus :: (MonadClient m) => TeamId -> - TeamFeatureStatus 'TeamFeatureSelfDeletingMessages -> - m (TeamFeatureStatus 'TeamFeatureSelfDeletingMessages) + TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages -> + m (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages) setSelfDeletingMessagesStatus tid status = do let statusValue = tfwcStatus status timeout = sdmEnforcedTimeoutSeconds . tfwcConfig $ status diff --git a/services/galley/src/Galley/Effects/TeamFeatureStore.hs b/services/galley/src/Galley/Effects/TeamFeatureStore.hs index f7b0188745..2412e563dd 100644 --- a/services/galley/src/Galley/Effects/TeamFeatureStore.hs +++ b/services/galley/src/Galley/Effects/TeamFeatureStore.hs @@ -44,7 +44,7 @@ data TeamFeatureStore m a where ) => Proxy a -> TeamId -> - TeamFeatureStore m (Maybe (TeamFeatureStatus a)) + TeamFeatureStore m (Maybe (TeamFeatureStatus 'WithoutPaymentStatus a)) -- the proxy argument makes sure that makeSem below generates type-inference-friendly code SetFeatureStatusNoConfig' :: forall (a :: TeamFeatureName) m. @@ -53,22 +53,22 @@ data TeamFeatureStore m a where ) => Proxy a -> TeamId -> - TeamFeatureStatus a -> - TeamFeatureStore m (TeamFeatureStatus a) + TeamFeatureStatus 'WithoutPaymentStatus a -> + TeamFeatureStore m (TeamFeatureStatus 'WithoutPaymentStatus a) GetApplockFeatureStatus :: TeamId -> - TeamFeatureStore m (Maybe (TeamFeatureStatus 'TeamFeatureAppLock)) + TeamFeatureStore m (Maybe (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureAppLock)) SetApplockFeatureStatus :: TeamId -> - TeamFeatureStatus 'TeamFeatureAppLock -> - TeamFeatureStore m (TeamFeatureStatus 'TeamFeatureAppLock) + TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureAppLock -> + TeamFeatureStore m (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureAppLock) GetSelfDeletingMessagesStatus :: TeamId -> - TeamFeatureStore m (Maybe (TeamFeatureStatus 'TeamFeatureSelfDeletingMessages)) + TeamFeatureStore m (Maybe (TeamFeatureStatus 'WithPaymentStatus 'TeamFeatureSelfDeletingMessages)) SetSelfDeletingMessagesStatus :: TeamId -> - TeamFeatureStatus 'TeamFeatureSelfDeletingMessages -> - TeamFeatureStore m (TeamFeatureStatus 'TeamFeatureSelfDeletingMessages) + TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages -> + TeamFeatureStore m (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages) SetPaymentStatus' :: forall (a :: TeamFeatureName) m. ( HasPaymentStatusCol a @@ -91,15 +91,15 @@ getFeatureStatusNoConfig :: forall (a :: TeamFeatureName) r. (Member TeamFeatureStore r, FeatureHasNoConfig a, HasStatusCol a) => TeamId -> - Sem r (Maybe (TeamFeatureStatus a)) + Sem r (Maybe (TeamFeatureStatus 'WithoutPaymentStatus a)) getFeatureStatusNoConfig = getFeatureStatusNoConfig' (Proxy @a) setFeatureStatusNoConfig :: forall (a :: TeamFeatureName) r. (Member TeamFeatureStore r, FeatureHasNoConfig a, HasStatusCol a) => TeamId -> - TeamFeatureStatus a -> - Sem r (TeamFeatureStatus a) + TeamFeatureStatus 'WithoutPaymentStatus a -> + Sem r (TeamFeatureStatus 'WithoutPaymentStatus a) setFeatureStatusNoConfig = setFeatureStatusNoConfig' (Proxy @a) setPaymentStatus :: diff --git a/services/galley/test/integration/API/Teams.hs b/services/galley/test/integration/API/Teams.hs index 43985abb00..9aa7a3c4e4 100644 --- a/services/galley/test/integration/API/Teams.hs +++ b/services/galley/test/integration/API/Teams.hs @@ -355,7 +355,7 @@ testEnableSSOPerTeam = do assertQueue "create team" tActivate let check :: HasCallStack => String -> Public.TeamFeatureStatusValue -> TestM () check msg enabledness = do - status :: Public.TeamFeatureStatus 'Public.TeamFeatureSSO <- responseJsonUnsafe <$> (getSSOEnabledInternal tid (getSSOEnabledInternal tid TestM () @@ -382,10 +382,10 @@ testEnableSSOPerTeam = do testEnableTeamSearchVisibilityPerTeam :: TestM () testEnableTeamSearchVisibilityPerTeam = do g <- view tsGalley - (tid, owner, (member : _)) <- Util.createBindingTeamWithMembers 2 + (tid, owner, member : _) <- Util.createBindingTeamWithMembers 2 let check :: (HasCallStack, MonadCatch m, MonadIO m, Monad m, MonadHttp m) => String -> Public.TeamFeatureStatusValue -> m () check msg enabledness = do - status :: Public.TeamFeatureStatus 'Public.TeamFeatureSearchVisibility <- responseJsonUnsafe <$> (Util.getTeamSearchVisibilityAvailableInternal g tid (Util.getTeamSearchVisibilityAvailableInternal g tid UserId -> TeamId -> - Public.TeamFeatureStatus 'Public.TeamFeatureClassifiedDomains -> + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureClassifiedDomains -> m () getClassifiedDomains member tid = assertFlagWithConfig @Public.TeamFeatureClassifiedDomainsConfig $ @@ -258,7 +258,7 @@ getClassifiedDomains member tid = getClassifiedDomainsInternal :: (HasCallStack, HasGalley m, MonadIO m, MonadHttp m, MonadCatch m) => TeamId -> - Public.TeamFeatureStatus 'Public.TeamFeatureClassifiedDomains -> + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureClassifiedDomains -> m () getClassifiedDomainsInternal tid = assertFlagWithConfig @Public.TeamFeatureClassifiedDomainsConfig $ @@ -270,14 +270,13 @@ testClassifiedDomainsEnabled = do let expected = Public.TeamFeatureStatusWithConfig { Public.tfwcStatus = Public.TeamFeatureEnabled, - Public.tfwcConfig = Public.TeamFeatureClassifiedDomainsConfig [Domain "example.com"], - Public.tfwcPaymentStatus = Nothing + Public.tfwcConfig = Public.TeamFeatureClassifiedDomainsConfig [Domain "example.com"] } let getClassifiedDomainsFeatureConfig :: (HasCallStack, HasGalley m, MonadIO m, MonadHttp m, MonadCatch m) => UserId -> - Public.TeamFeatureStatus 'Public.TeamFeatureClassifiedDomains -> + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureClassifiedDomains -> m () getClassifiedDomainsFeatureConfig uid = do assertFlagWithConfig @Public.TeamFeatureClassifiedDomainsConfig $ @@ -293,14 +292,13 @@ testClassifiedDomainsDisabled = do let expected = Public.TeamFeatureStatusWithConfig { Public.tfwcStatus = Public.TeamFeatureDisabled, - Public.tfwcConfig = Public.TeamFeatureClassifiedDomainsConfig [], - Public.tfwcPaymentStatus = Nothing + Public.tfwcConfig = Public.TeamFeatureClassifiedDomainsConfig [] } let getClassifiedDomainsFeatureConfig :: (HasCallStack, HasGalley m, MonadIO m, MonadHttp m, MonadCatch m) => UserId -> - Public.TeamFeatureStatus 'Public.TeamFeatureClassifiedDomains -> + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureClassifiedDomains -> m () getClassifiedDomainsFeatureConfig uid = do assertFlagWithConfig @Public.TeamFeatureClassifiedDomainsConfig $ @@ -318,13 +316,13 @@ testClassifiedDomainsDisabled = do getClassifiedDomainsFeatureConfig member expected testSimpleFlag :: - forall (a :: Public.TeamFeatureName). + forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName). ( HasCallStack, Typeable a, Public.FeatureHasNoConfig a, Public.KnownTeamFeatureName a, - FromJSON (Public.TeamFeatureStatus a), - ToJSON (Public.TeamFeatureStatus a) + FromJSON (Public.TeamFeatureStatus ps a), + ToJSON (Public.TeamFeatureStatus ps a) ) => Public.TeamFeatureStatusValue -> TestM () @@ -383,12 +381,11 @@ testSimpleFlag defaultValue = do testSelfDeletingMessages :: TestM () testSelfDeletingMessages = do -- personal users - let setting :: TeamFeatureStatusValue -> Int32 -> Public.TeamFeatureStatus 'Public.TeamFeatureSelfDeletingMessages + let setting :: TeamFeatureStatusValue -> Int32 -> Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSelfDeletingMessages setting stat tout = Public.TeamFeatureStatusWithConfig @Public.TeamFeatureSelfDeletingMessagesConfig stat (Public.TeamFeatureSelfDeletingMessagesConfig tout) - Nothing personalUser <- Util.randomUser Util.getFeatureConfig Public.TeamFeatureSelfDeletingMessages personalUser @@ -449,21 +446,18 @@ testAllFeatures = do toS TeamFeatureAppLock .= Public.TeamFeatureStatusWithConfig TeamFeatureEnabled - (Public.TeamFeatureAppLockConfig (Public.EnforceAppLock False) (60 :: Int32)) - Nothing, + (Public.TeamFeatureAppLockConfig (Public.EnforceAppLock False) (60 :: Int32)), toS TeamFeatureFileSharing .= Public.TeamFeatureStatusNoConfig TeamFeatureEnabled, toS TeamFeatureClassifiedDomains .= Public.TeamFeatureStatusWithConfig TeamFeatureEnabled - (Public.TeamFeatureClassifiedDomainsConfig [Domain "example.com"]) - Nothing, + (Public.TeamFeatureClassifiedDomainsConfig [Domain "example.com"]), toS TeamFeatureConferenceCalling .= Public.TeamFeatureStatusNoConfig confCalling, toS TeamFeatureSelfDeletingMessages .= Public.TeamFeatureStatusWithConfig @Public.TeamFeatureSelfDeletingMessagesConfig TeamFeatureEnabled (Public.TeamFeatureSelfDeletingMessagesConfig 0) - Nothing ] toS :: TeamFeatureName -> Text toS = TE.decodeUtf8 . toByteString' @@ -507,7 +501,7 @@ assertFlagNoConfig :: ( HasCallStack, Typeable a, Public.FeatureHasNoConfig a, - FromJSON (Public.TeamFeatureStatus a), + FromJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a), Public.KnownTeamFeatureName a ) => TestM ResponseLBS -> @@ -517,7 +511,7 @@ assertFlagNoConfig res expected = do res !!! do statusCode === const 200 ( fmap Public.tfwoStatus - . responseJsonEither @(Public.TeamFeatureStatus a) + . responseJsonEither @(Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) ) === const (Right expected) diff --git a/services/galley/test/integration/API/Teams/LegalHold.hs b/services/galley/test/integration/API/Teams/LegalHold.hs index 7ccefd4ea6..052ab80952 100644 --- a/services/galley/test/integration/API/Teams/LegalHold.hs +++ b/services/galley/test/integration/API/Teams/LegalHold.hs @@ -566,14 +566,14 @@ testEnablePerTeam = withTeam $ \owner tid -> do addTeamMemberInternal tid member (rolePermissions RoleMember) Nothing ensureQueueEmpty do - status :: Public.TeamFeatureStatus 'Public.TeamFeatureLegalHold <- responseJsonUnsafe <$> (getEnabled tid (getEnabled tid (getEnabled tid (getEnabled tid do @@ -585,7 +585,7 @@ testEnablePerTeam = withTeam $ \owner tid -> do liftIO $ assertEqual "User legal hold status should be enabled" UserLegalHoldEnabled status do putEnabled' id tid Public.TeamFeatureDisabled !!! testResponse 403 (Just "legalhold-whitelisted-only") - status :: Public.TeamFeatureStatus 'Public.TeamFeatureLegalHold <- responseJsonUnsafe <$> (getEnabled tid (getEnabled tid (getEnabled tid (getEnabled tid (getEnabled tid (getEnabled tid do @@ -554,7 +554,7 @@ testEnablePerTeam = do liftIO $ assertEqual "User legal hold status should be enabled" UserLegalHoldEnabled status do putEnabled tid Public.TeamFeatureDisabled -- disable again - status :: Public.TeamFeatureStatus 'Public.TeamFeatureLegalHold <- responseJsonUnsafe <$> (getEnabled tid (getEnabled tid (getEnabled tid (getEnabled tid (getEnabled tid (getEnabled tid (Request -> Request) -> TeamId -> - (Public.TeamFeatureStatus a) -> + (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) -> TestM () putTeamFeatureFlagInternal reqmod tid status = do g <- view tsGalley @@ -168,12 +168,12 @@ putTeamFeatureFlagInternalWithGalleyAndMod :: MonadHttp m, HasCallStack, Public.KnownTeamFeatureName a, - ToJSON (Public.TeamFeatureStatus a) + ToJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) ) => (Request -> Request) -> (Request -> Request) -> TeamId -> - (Public.TeamFeatureStatus a) -> + (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) -> m () putTeamFeatureFlagInternalWithGalleyAndMod galley reqmod tid status = void . put $ diff --git a/services/spar/src/Spar/Intra/Galley.hs b/services/spar/src/Spar/Intra/Galley.hs index d8a0bc6291..53184e0e15 100644 --- a/services/spar/src/Spar/Intra/Galley.hs +++ b/services/spar/src/Spar/Intra/Galley.hs @@ -31,7 +31,13 @@ import Imports import Network.HTTP.Types.Method import Spar.Error import qualified System.Logger.Class as Log -import Wire.API.Team.Feature (TeamFeatureName (..), TeamFeatureStatus, TeamFeatureStatusNoConfig (..), TeamFeatureStatusValue (..)) +import Wire.API.Team.Feature + ( IncludePaymentStatus (..), + TeamFeatureName (..), + TeamFeatureStatus, + TeamFeatureStatusNoConfig (..), + TeamFeatureStatusValue (..), + ) ---------------------------------------------------------------------- @@ -88,7 +94,7 @@ isEmailValidationEnabledTeam tid = do resp <- call $ method GET . paths ["i", "teams", toByteString' tid, "features", "validateSAMLemails"] pure ( (statusCode resp == 200) - && ( responseJsonMaybe @(TeamFeatureStatus 'TeamFeatureValidateSAMLEmails) resp + && ( responseJsonMaybe @(TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureValidateSAMLEmails) resp == Just (TeamFeatureStatusNoConfig TeamFeatureEnabled) ) ) diff --git a/tools/stern/src/Stern/API.hs b/tools/stern/src/Stern/API.hs index 27e8e72709..3e8b44aa98 100644 --- a/tools/stern/src/Stern/API.hs +++ b/tools/stern/src/Stern/API.hs @@ -361,7 +361,7 @@ routes = do Doc.description "team feature status (enabled or disabled)" Doc.response 200 "Team feature flag status" Doc.end - mkFeaturePutGetRoute @'Public.TeamFeatureAppLock + mkFeaturePutGetRoute @'Public.WithoutPaymentStatus @'Public.TeamFeatureAppLock -- These endpoints should be part of team settings. Until then, we access them from here -- for authorized personnel to enable/disable this on the team's behalf @@ -592,27 +592,27 @@ getTeamAdminInfo :: TeamId -> Handler Response getTeamAdminInfo = liftM (json . toAdminInfo) . Intra.getTeamInfo getTeamFeatureFlagH :: - forall (a :: Public.TeamFeatureName). + forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName). ( Public.KnownTeamFeatureName a, - FromJSON (Public.TeamFeatureStatus a), - ToJSON (Public.TeamFeatureStatus a), - Typeable (Public.TeamFeatureStatus a) + FromJSON (Public.TeamFeatureStatus ps a), + ToJSON (Public.TeamFeatureStatus ps a), + Typeable (Public.TeamFeatureStatus ps a) ) => TeamId -> Handler Response getTeamFeatureFlagH tid = - json <$> Intra.getTeamFeatureFlag @a tid + json <$> Intra.getTeamFeatureFlag @ps @a tid setTeamFeatureFlagH :: forall (a :: Public.TeamFeatureName). ( Public.KnownTeamFeatureName a, - FromJSON (Public.TeamFeatureStatus a), - ToJSON (Public.TeamFeatureStatus a) + FromJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a), + ToJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) ) => - TeamId ::: JsonRequest (Public.TeamFeatureStatus a) ::: JSON -> + TeamId ::: JsonRequest (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) ::: JSON -> Handler Response setTeamFeatureFlagH (tid ::: req ::: _) = do - status :: Public.TeamFeatureStatus a <- parseBody req !>> mkError status400 "client-error" + status :: Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a <- parseBody req !>> mkError status400 "client-error" empty <$ Intra.setTeamFeatureFlag @a tid status getTeamFeatureFlagNoConfigH :: @@ -753,17 +753,19 @@ noSuchUser :: Maybe a -> Handler a noSuchUser = ifNothing (mkError status404 "no-user" "No such user") mkFeaturePutGetRoute :: - forall (a :: Public.TeamFeatureName). + forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName). ( Public.KnownTeamFeatureName a, - FromJSON (Public.TeamFeatureStatus a), - ToJSON (Public.TeamFeatureStatus a), - Typeable (Public.TeamFeatureStatus a) + FromJSON (Public.TeamFeatureStatus ps a), + FromJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a), + ToJSON (Public.TeamFeatureStatus ps a), + ToJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a), + Typeable (Public.TeamFeatureStatus ps a) ) => Routes Doc.ApiBuilder Handler () mkFeaturePutGetRoute = do let featureName = Public.knownTeamFeatureName @a - get ("/teams/:tid/features/" <> toByteString' featureName) (continue (getTeamFeatureFlagH @a)) $ + get ("/teams/:tid/features/" <> toByteString' featureName) (continue (getTeamFeatureFlagH @ps @a)) $ capture "tid" document "GET" "getTeamFeatureFlag" $ do summary "Shows whether a feature flag is enabled or not for a given team." @@ -774,7 +776,7 @@ mkFeaturePutGetRoute = do put ("/teams/:tid/features/" <> toByteString' featureName) (continue (setTeamFeatureFlagH @a)) $ capture "tid" - .&. jsonRequest @(Public.TeamFeatureStatus a) + .&. jsonRequest @(Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) .&. accept "application" "json" document "PUT" "setTeamFeatureFlag" $ do summary "Disable / enable feature flag for a given team" diff --git a/tools/stern/src/Stern/Intra.hs b/tools/stern/src/Stern/Intra.hs index e930aa76e0..4f8ffde988 100644 --- a/tools/stern/src/Stern/Intra.hs +++ b/tools/stern/src/Stern/Intra.hs @@ -452,13 +452,13 @@ setBlacklistStatus status emailOrPhone = do statusToMethod True = POST getTeamFeatureFlag :: - forall (a :: Public.TeamFeatureName). + forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName). ( Public.KnownTeamFeatureName a, - Typeable (Public.TeamFeatureStatus a), - FromJSON (Public.TeamFeatureStatus a) + Typeable (Public.TeamFeatureStatus ps a), + FromJSON (Public.TeamFeatureStatus ps a) ) => TeamId -> - Handler (Public.TeamFeatureStatus a) + Handler (Public.TeamFeatureStatus ps a) getTeamFeatureFlag tid = do info $ msg "Getting team feature status" gly <- view galley @@ -467,17 +467,17 @@ getTeamFeatureFlag tid = do . paths ["/i/teams", toByteString' tid, "features", toByteString' (Public.knownTeamFeatureName @a)] resp <- catchRpcErrors $ rpc' "galley" gly req case Bilge.statusCode resp of - 200 -> pure $ responseJsonUnsafe @(Public.TeamFeatureStatus a) resp + 200 -> pure $ responseJsonUnsafe @(Public.TeamFeatureStatus ps a) resp 404 -> throwE (mkError status404 "bad-upstream" "team doesnt exist") _ -> throwE (mkError status502 "bad-upstream" "bad response") setTeamFeatureFlag :: forall (a :: Public.TeamFeatureName). ( Public.KnownTeamFeatureName a, - ToJSON (Public.TeamFeatureStatus a) + ToJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) ) => TeamId -> - Public.TeamFeatureStatus a -> + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a -> Handler () setTeamFeatureFlag tid status = do info $ msg "Setting team feature status" From 9d419ba97a59b975aeef5482e055b472636f228d Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Mon, 22 Nov 2021 15:39:35 +0100 Subject: [PATCH 09/28] integration tests + implementation of business logic --- services/galley/src/Galley/API/Internal.hs | 2 +- .../galley/src/Galley/API/Teams/Features.hs | 45 ++++++++---- .../src/Galley/Cassandra/TeamFeatures.hs | 11 ++- .../src/Galley/Effects/TeamFeatureStore.hs | 2 +- services/galley/test/integration/API/Teams.hs | 4 +- .../test/integration/API/Teams/Feature.hs | 72 +++++++++++++------ .../test/integration/API/Util/TeamFeature.hs | 42 +++++++---- 7 files changed, 121 insertions(+), 57 deletions(-) diff --git a/services/galley/src/Galley/API/Internal.hs b/services/galley/src/Galley/API/Internal.hs index 76541fcc30..18a3949345 100644 --- a/services/galley/src/Galley/API/Internal.hs +++ b/services/galley/src/Galley/API/Internal.hs @@ -599,7 +599,7 @@ rmUser lusr conn = do for_ (maybeList1 (catMaybes pp)) - (push) + push -- FUTUREWORK: This could be optimized to reduce the number of RPCs -- made. When a team is deleted the burst of RPCs created here could diff --git a/services/galley/src/Galley/API/Teams/Features.hs b/services/galley/src/Galley/API/Teams/Features.hs index e225e12808..815c2c309f 100644 --- a/services/galley/src/Galley/API/Teams/Features.hs +++ b/services/galley/src/Galley/API/Teams/Features.hs @@ -123,7 +123,6 @@ setFeatureStatus :: '[ Error ActionError, Error TeamError, Error NotATeamMember, - Error TeamFeatureError, TeamStore, TeamFeatureStore ] @@ -141,10 +140,7 @@ setFeatureStatus setter doauth tid status = do void $ permissionCheck (ChangeTeamFeature (Public.knownTeamFeatureName @a)) zusrMembership DontDoAuth -> assertTeamExists tid - maybePaymentStatus <- TeamFeatures.getPaymentStatus @a tid - case maybePaymentStatus of - Just (Public.PaymentStatus Public.PaymentLocked) -> throw PaymentStatusLocked - _ -> setter tid status + setter tid status -- | Setting payment status can only be done through the internal API and therefore doesn't require auth. setPaymentStatus :: @@ -584,20 +580,43 @@ getSelfDeletingMessagesInternal :: Sem r (Public.TeamFeatureStatus 'Public.WithPaymentStatus 'Public.TeamFeatureSelfDeletingMessages) getSelfDeletingMessagesInternal = \case Left _ -> pure Public.defaultSelfDeletingMessagesStatus - Right tid -> - TeamFeatures.getSelfDeletingMessagesStatus tid - <&> fromMaybe Public.defaultSelfDeletingMessagesStatus + Right tid -> do + maybePaymentStatus <- TeamFeatures.getPaymentStatus @'Public.TeamFeatureSelfDeletingMessages tid + maybeFeatureStatus <- TeamFeatures.getSelfDeletingMessagesStatus tid + pure $ case (maybePaymentStatus, maybeFeatureStatus) of + (Just (Public.PaymentStatus Public.PaymentUnlocked), Just featureStatus) -> + Public.TeamFeatureStatusWithConfigAndPaymentStatus + (Public.tfwcStatus featureStatus) + (Public.tfwcConfig featureStatus) + Public.PaymentUnlocked + (Just (Public.PaymentStatus Public.PaymentUnlocked), Nothing) -> + Public.TeamFeatureStatusWithConfigAndPaymentStatus + (Public.tfwcapsStatus Public.defaultSelfDeletingMessagesStatus) + (Public.tfwcapsConfig Public.defaultSelfDeletingMessagesStatus) + Public.PaymentUnlocked + _ -> Public.defaultSelfDeletingMessagesStatus setSelfDeletingMessagesInternal :: - Members '[GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r => + Members + '[ GundeckAccess, + TeamStore, + TeamFeatureStore, + P.TinyLog, + Error TeamFeatureError + ] + r => TeamId -> Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSelfDeletingMessages -> Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSelfDeletingMessages) setSelfDeletingMessagesInternal tid st = do - let pushEvent = - pushFeatureConfigEvent tid $ - Event.Event Event.Update Public.TeamFeatureSelfDeletingMessages (EdFeatureSelfDeletingMessagesChanged st) - TeamFeatures.setSelfDeletingMessagesStatus tid st <* pushEvent + maybePaymentStatus <- TeamFeatures.getPaymentStatus @'Public.TeamFeatureSelfDeletingMessages tid + case maybePaymentStatus of + Just (Public.PaymentStatus Public.PaymentUnlocked) -> do + let pushEvent = + pushFeatureConfigEvent tid $ + Event.Event Event.Update Public.TeamFeatureSelfDeletingMessages (EdFeatureSelfDeletingMessagesChanged st) + TeamFeatures.setSelfDeletingMessagesStatus tid st <* pushEvent + _ -> throw PaymentStatusLocked pushFeatureConfigEvent :: Members '[GundeckAccess, TeamStore, P.TinyLog] r => diff --git a/services/galley/src/Galley/Cassandra/TeamFeatures.hs b/services/galley/src/Galley/Cassandra/TeamFeatures.hs index 7f1bb44a65..b71651bf72 100644 --- a/services/galley/src/Galley/Cassandra/TeamFeatures.hs +++ b/services/galley/src/Galley/Cassandra/TeamFeatures.hs @@ -105,21 +105,20 @@ getSelfDeletingMessagesStatus :: forall m. (MonadClient m) => TeamId -> - m (Maybe (TeamFeatureStatus 'WithPaymentStatus 'TeamFeatureSelfDeletingMessages)) + m (Maybe (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages)) getSelfDeletingMessagesStatus tid = do let q = query1 select (params LocalQuorum (Identity tid)) mTuple <- retry x1 q pure $ - mTuple >>= \(mbStatusValue, mbTimeout, mbPaymentStatusValue) -> - TeamFeatureStatusWithConfigAndPaymentStatus <$> mbStatusValue <*> (TeamFeatureSelfDeletingMessagesConfig <$> mbTimeout) <*> mbPaymentStatusValue + mTuple >>= \(mbStatusValue, mbTimeout) -> + TeamFeatureStatusWithConfig <$> mbStatusValue <*> (TeamFeatureSelfDeletingMessagesConfig <$> mbTimeout) where - select :: PrepQuery R (Identity TeamId) (Maybe TeamFeatureStatusValue, Maybe Int32, Maybe PaymentStatusValue) + select :: PrepQuery R (Identity TeamId) (Maybe TeamFeatureStatusValue, Maybe Int32) select = fromString $ "select " <> statusCol @'TeamFeatureSelfDeletingMessages - <> ", self_deleting_messages_ttl, " - <> paymentStatusCol @'TeamFeatureSelfDeletingMessages + <> ", self_deleting_messages_ttl" <> " from team_features where team_id = ?" setSelfDeletingMessagesStatus :: diff --git a/services/galley/src/Galley/Effects/TeamFeatureStore.hs b/services/galley/src/Galley/Effects/TeamFeatureStore.hs index 2412e563dd..cc9338574c 100644 --- a/services/galley/src/Galley/Effects/TeamFeatureStore.hs +++ b/services/galley/src/Galley/Effects/TeamFeatureStore.hs @@ -64,7 +64,7 @@ data TeamFeatureStore m a where TeamFeatureStore m (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureAppLock) GetSelfDeletingMessagesStatus :: TeamId -> - TeamFeatureStore m (Maybe (TeamFeatureStatus 'WithPaymentStatus 'TeamFeatureSelfDeletingMessages)) + TeamFeatureStore m (Maybe (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages)) SetSelfDeletingMessagesStatus :: TeamId -> TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages -> diff --git a/services/galley/test/integration/API/Teams.hs b/services/galley/test/integration/API/Teams.hs index 9aa7a3c4e4..8ff360dd57 100644 --- a/services/galley/test/integration/API/Teams.hs +++ b/services/galley/test/integration/API/Teams.hs @@ -1877,7 +1877,7 @@ postCryptoBroadcastMessage100OrMaxConns = do (201, 200, 0, (x : xs)) -> return (x, xs) (201, 200, _, _) -> createAndConnectUserWhileLimitNotReached alice (remaining -1) ((uid, cid) : acc) pk (403, 403, _, []) -> error "Need to connect with at least 1 user" - (403, 403, _, (x : xs)) -> return (x, xs) + (403, 403, _, x : xs) -> return (x, xs) (xxx, yyy, _, _) -> error ("Unexpected while connecting users: " ++ show xxx ++ " and " ++ show yyy) newTeamMember' :: Permissions -> UserId -> TeamMember @@ -1892,7 +1892,7 @@ getSSOEnabledInternal :: HasCallStack => TeamId -> TestM ResponseLBS getSSOEnabledInternal = Util.getTeamFeatureFlagInternal Public.TeamFeatureSSO putSSOEnabledInternal :: HasCallStack => TeamId -> Public.TeamFeatureStatusValue -> TestM () -putSSOEnabledInternal tid statusValue = Util.putTeamFeatureFlagInternal @'Public.TeamFeatureSSO expect2xx tid (Public.TeamFeatureStatusNoConfig statusValue) +putSSOEnabledInternal tid statusValue = void $ Util.putTeamFeatureFlagInternal @'Public.TeamFeatureSSO expect2xx tid (Public.TeamFeatureStatusNoConfig statusValue) getSearchVisibility :: HasCallStack => (Request -> Request) -> UserId -> TeamId -> (MonadIO m, MonadHttp m) => m ResponseLBS getSearchVisibility g uid tid = do diff --git a/services/galley/test/integration/API/Teams/Feature.hs b/services/galley/test/integration/API/Teams/Feature.hs index 298768ef69..0586a7bd9c 100644 --- a/services/galley/test/integration/API/Teams/Feature.hs +++ b/services/galley/test/integration/API/Teams/Feature.hs @@ -68,7 +68,7 @@ tests s = test s "All features" testAllFeatures, test s "Feature Configs / Team Features Consistency" testFeatureConfigConsistency, test s "ConferenceCalling" $ testSimpleFlag @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling Public.TeamFeatureEnabled, - test s "SelfDeletingMessages" $ testSelfDeletingMessages + test s "SelfDeletingMessages" testSelfDeletingMessages ] testSSO :: TestM () @@ -87,7 +87,7 @@ testSSO = do getSSOInternal :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () getSSOInternal = assertFlagNoConfig @'Public.TeamFeatureSSO $ Util.getTeamFeatureFlagInternal Public.TeamFeatureSSO tid setSSOInternal :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () - setSSOInternal = Util.putTeamFeatureFlagInternal @'Public.TeamFeatureSSO expect2xx tid . Public.TeamFeatureStatusNoConfig + setSSOInternal = void . Util.putTeamFeatureFlagInternal @'Public.TeamFeatureSSO expect2xx tid . Public.TeamFeatureStatusNoConfig assertFlagForbidden $ Util.getTeamFeatureFlag Public.TeamFeatureSSO nonMember tid @@ -127,7 +127,7 @@ testLegalHold = do getLegalHoldFeatureConfig = assertFlagNoConfig @'Public.TeamFeatureLegalHold $ Util.getFeatureConfig Public.TeamFeatureLegalHold member setLegalHoldInternal :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () - setLegalHoldInternal = Util.putTeamFeatureFlagInternal @'Public.TeamFeatureLegalHold expect2xx tid . Public.TeamFeatureStatusNoConfig + setLegalHoldInternal = void . Util.putTeamFeatureFlagInternal @'Public.TeamFeatureLegalHold expect2xx tid . Public.TeamFeatureStatusNoConfig getLegalHold Public.TeamFeatureDisabled getLegalHoldInternal Public.TeamFeatureDisabled @@ -349,7 +349,7 @@ testSimpleFlag defaultValue = do setFlagInternal :: Public.TeamFeatureStatusValue -> TestM () setFlagInternal statusValue = - Util.putTeamFeatureFlagInternal @a expect2xx tid (Public.TeamFeatureStatusNoConfig statusValue) + void $ Util.putTeamFeatureFlagInternal @a expect2xx tid (Public.TeamFeatureStatusNoConfig statusValue) assertFlagForbidden $ Util.getTeamFeatureFlag feature nonMember tid @@ -381,31 +381,39 @@ testSimpleFlag defaultValue = do testSelfDeletingMessages :: TestM () testSelfDeletingMessages = do -- personal users - let setting :: TeamFeatureStatusValue -> Int32 -> Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSelfDeletingMessages - setting stat tout = + let settingWithOutPaymentStatus :: TeamFeatureStatusValue -> Int32 -> Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSelfDeletingMessages + settingWithOutPaymentStatus stat tout = Public.TeamFeatureStatusWithConfig @Public.TeamFeatureSelfDeletingMessagesConfig stat (Public.TeamFeatureSelfDeletingMessagesConfig tout) + settingWithPaymentStatus :: TeamFeatureStatusValue -> Int32 -> Public.PaymentStatusValue -> Public.TeamFeatureStatus 'Public.WithPaymentStatus 'Public.TeamFeatureSelfDeletingMessages + settingWithPaymentStatus stat tout paymentStatus = + Public.TeamFeatureStatusWithConfigAndPaymentStatus @Public.TeamFeatureSelfDeletingMessagesConfig + stat + (Public.TeamFeatureSelfDeletingMessagesConfig tout) + paymentStatus personalUser <- Util.randomUser Util.getFeatureConfig Public.TeamFeatureSelfDeletingMessages personalUser - !!! responseJsonEither === const (Right $ setting TeamFeatureEnabled 0) + !!! responseJsonEither === const (Right $ settingWithPaymentStatus TeamFeatureEnabled 0 Public.PaymentLocked) -- team users galley <- view tsGalley (owner, tid, []) <- Util.createBindingTeamWithNMembers 0 - let checkSet :: TeamFeatureStatusValue -> Int32 -> TestM () - checkSet stat tout = do - Util.putTeamFeatureFlagInternal @'Public.TeamFeatureSelfDeletingMessages - galley - tid - (setting stat tout) + let checkSet :: TeamFeatureStatusValue -> Int32 -> Int -> TestM () + checkSet stat tout expectedStatusCode = + do + Util.putTeamFeatureFlagInternal @'Public.TeamFeatureSelfDeletingMessages + galley + tid + (settingWithOutPaymentStatus stat tout) + !!! statusCode === const expectedStatusCode -- internal, public (/team/:tid/features), and team-agnostic (/feature-configs). - checkGet :: HasCallStack => TeamFeatureStatusValue -> Int32 -> TestM () - checkGet stat tout = do - let expected = setting stat tout + checkGet :: HasCallStack => TeamFeatureStatusValue -> Int32 -> Public.PaymentStatusValue -> TestM () + checkGet stat tout paymentStatus = do + let expected = settingWithPaymentStatus stat tout paymentStatus forM_ [ Util.getTeamFeatureFlagInternal Public.TeamFeatureSelfDeletingMessages tid, Util.getTeamFeatureFlagWithGalley Public.TeamFeatureSelfDeletingMessages galley owner tid, @@ -413,11 +421,30 @@ testSelfDeletingMessages = do ] (!!! responseJsonEither === const (Right expected)) - checkGet TeamFeatureEnabled 0 - checkSet TeamFeatureDisabled 0 - checkGet TeamFeatureDisabled 0 - checkSet TeamFeatureEnabled 30 - checkGet TeamFeatureEnabled 30 + checkSetPaymentStatus :: HasCallStack => Public.PaymentStatusValue -> TestM () + checkSetPaymentStatus status = + do + Util.setPaymentStatusInternal @'Public.TeamFeatureSelfDeletingMessages galley tid status + !!! statusCode === const 200 + + checkGet TeamFeatureEnabled 0 Public.PaymentLocked + checkSet TeamFeatureDisabled 0 409 + checkGet TeamFeatureEnabled 0 Public.PaymentLocked + checkSet TeamFeatureEnabled 30 409 + checkGet TeamFeatureEnabled 0 Public.PaymentLocked + checkSetPaymentStatus Public.PaymentUnlocked + checkGet TeamFeatureEnabled 0 Public.PaymentUnlocked + checkSet TeamFeatureDisabled 0 200 + checkGet TeamFeatureDisabled 0 Public.PaymentUnlocked + checkSet TeamFeatureEnabled 30 200 + checkGet TeamFeatureEnabled 30 Public.PaymentUnlocked + checkSet TeamFeatureDisabled 30 200 + checkGet TeamFeatureDisabled 30 Public.PaymentUnlocked + checkSetPaymentStatus Public.PaymentLocked + checkGet TeamFeatureEnabled 0 Public.PaymentLocked + checkSet TeamFeatureEnabled 50 409 + checkSetPaymentStatus Public.PaymentUnlocked + checkGet TeamFeatureDisabled 30 Public.PaymentUnlocked -- | Call 'GET /teams/:tid/features' and 'GET /feature-configs', and check if all -- features are there. @@ -455,9 +482,10 @@ testAllFeatures = do toS TeamFeatureConferenceCalling .= Public.TeamFeatureStatusNoConfig confCalling, toS TeamFeatureSelfDeletingMessages - .= Public.TeamFeatureStatusWithConfig @Public.TeamFeatureSelfDeletingMessagesConfig + .= Public.TeamFeatureStatusWithConfigAndPaymentStatus @Public.TeamFeatureSelfDeletingMessagesConfig TeamFeatureEnabled (Public.TeamFeatureSelfDeletingMessagesConfig 0) + Public.PaymentLocked ] toS :: TeamFeatureName -> Text toS = TE.decodeUtf8 . toByteString' diff --git a/services/galley/test/integration/API/Util/TeamFeature.hs b/services/galley/test/integration/API/Util/TeamFeature.hs index 6ae7b747e1..bdd7c2d8dc 100644 --- a/services/galley/test/integration/API/Util/TeamFeature.hs +++ b/services/galley/test/integration/API/Util/TeamFeature.hs @@ -51,12 +51,13 @@ putTeamSearchVisibilityAvailableInternal :: Public.TeamFeatureStatusValue -> (MonadIO m, MonadHttp m) => m () putTeamSearchVisibilityAvailableInternal g tid statusValue = - putTeamFeatureFlagInternalWithGalleyAndMod - @'Public.TeamFeatureSearchVisibility - g - expect2xx - tid - (Public.TeamFeatureStatusNoConfig statusValue) + void $ + putTeamFeatureFlagInternalWithGalleyAndMod + @'Public.TeamFeatureSearchVisibility + g + expect2xx + tid + (Public.TeamFeatureStatusNoConfig statusValue) putLegalHoldEnabledInternal' :: HasCallStack => @@ -65,7 +66,7 @@ putLegalHoldEnabledInternal' :: Public.TeamFeatureStatusValue -> TestM () putLegalHoldEnabledInternal' g tid statusValue = - putTeamFeatureFlagInternal @'Public.TeamFeatureLegalHold g tid (Public.TeamFeatureStatusNoConfig statusValue) + void $ putTeamFeatureFlagInternal @'Public.TeamFeatureLegalHold g tid (Public.TeamFeatureStatusNoConfig statusValue) -------------------------------------------------------------------------------- @@ -156,8 +157,8 @@ putTeamFeatureFlagInternal :: ) => (Request -> Request) -> TeamId -> - (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) -> - TestM () + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a -> + TestM ResponseLBS putTeamFeatureFlagInternal reqmod tid status = do g <- view tsGalley putTeamFeatureFlagInternalWithGalleyAndMod @a g reqmod tid status @@ -173,11 +174,28 @@ putTeamFeatureFlagInternalWithGalleyAndMod :: (Request -> Request) -> (Request -> Request) -> TeamId -> - (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) -> - m () + Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a -> + m ResponseLBS putTeamFeatureFlagInternalWithGalleyAndMod galley reqmod tid status = - void . put $ + put $ galley . paths ["i", "teams", toByteString' tid, "features", toByteString' (Public.knownTeamFeatureName @a)] . json status . reqmod + +setPaymentStatusInternal :: + forall (a :: Public.TeamFeatureName). + ( HasCallStack, + Public.KnownTeamFeatureName a, + ToJSON Public.PaymentStatusValue + ) => + (Request -> Request) -> + TeamId -> + Public.PaymentStatusValue -> + TestM ResponseLBS +setPaymentStatusInternal reqmod tid paymentStatus = do + galley <- view tsGalley + put $ + galley + . paths ["i", "teams", toByteString' tid, "features", toByteString' (Public.knownTeamFeatureName @a), toByteString' paymentStatus] + . reqmod From d235a3fe284a4a0639665faa94bdca081acbe33d Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Tue, 23 Nov 2021 12:13:51 +0100 Subject: [PATCH 10/28] reduce # of db roundtrips --- services/galley/src/Galley/API/Teams/Features.hs | 7 +++---- .../galley/src/Galley/Cassandra/TeamFeatures.hs | 15 +++++++++------ .../galley/src/Galley/Effects/TeamFeatureStore.hs | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/services/galley/src/Galley/API/Teams/Features.hs b/services/galley/src/Galley/API/Teams/Features.hs index 815c2c309f..c88525755c 100644 --- a/services/galley/src/Galley/API/Teams/Features.hs +++ b/services/galley/src/Galley/API/Teams/Features.hs @@ -581,15 +581,14 @@ getSelfDeletingMessagesInternal :: getSelfDeletingMessagesInternal = \case Left _ -> pure Public.defaultSelfDeletingMessagesStatus Right tid -> do - maybePaymentStatus <- TeamFeatures.getPaymentStatus @'Public.TeamFeatureSelfDeletingMessages tid - maybeFeatureStatus <- TeamFeatures.getSelfDeletingMessagesStatus tid + (maybeFeatureStatus, maybePaymentStatus) <- TeamFeatures.getSelfDeletingMessagesStatus tid pure $ case (maybePaymentStatus, maybeFeatureStatus) of - (Just (Public.PaymentStatus Public.PaymentUnlocked), Just featureStatus) -> + (Just Public.PaymentUnlocked, Just featureStatus) -> Public.TeamFeatureStatusWithConfigAndPaymentStatus (Public.tfwcStatus featureStatus) (Public.tfwcConfig featureStatus) Public.PaymentUnlocked - (Just (Public.PaymentStatus Public.PaymentUnlocked), Nothing) -> + (Just Public.PaymentUnlocked, Nothing) -> Public.TeamFeatureStatusWithConfigAndPaymentStatus (Public.tfwcapsStatus Public.defaultSelfDeletingMessagesStatus) (Public.tfwcapsConfig Public.defaultSelfDeletingMessagesStatus) diff --git a/services/galley/src/Galley/Cassandra/TeamFeatures.hs b/services/galley/src/Galley/Cassandra/TeamFeatures.hs index b71651bf72..f0a1a5b3a5 100644 --- a/services/galley/src/Galley/Cassandra/TeamFeatures.hs +++ b/services/galley/src/Galley/Cassandra/TeamFeatures.hs @@ -105,20 +105,23 @@ getSelfDeletingMessagesStatus :: forall m. (MonadClient m) => TeamId -> - m (Maybe (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages)) + m (Maybe (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages), Maybe PaymentStatusValue) getSelfDeletingMessagesStatus tid = do let q = query1 select (params LocalQuorum (Identity tid)) mTuple <- retry x1 q - pure $ - mTuple >>= \(mbStatusValue, mbTimeout) -> - TeamFeatureStatusWithConfig <$> mbStatusValue <*> (TeamFeatureSelfDeletingMessagesConfig <$> mbTimeout) + pure + ( mTuple >>= \(mbStatusValue, mbTimeout, _) -> + TeamFeatureStatusWithConfig <$> mbStatusValue <*> (TeamFeatureSelfDeletingMessagesConfig <$> mbTimeout), + mTuple >>= \(_, _, mbPaymentStatus) -> mbPaymentStatus + ) where - select :: PrepQuery R (Identity TeamId) (Maybe TeamFeatureStatusValue, Maybe Int32) + select :: PrepQuery R (Identity TeamId) (Maybe TeamFeatureStatusValue, Maybe Int32, Maybe PaymentStatusValue) select = fromString $ "select " <> statusCol @'TeamFeatureSelfDeletingMessages - <> ", self_deleting_messages_ttl" + <> ", self_deleting_messages_ttl, " + <> paymentStatusCol @'TeamFeatureSelfDeletingMessages <> " from team_features where team_id = ?" setSelfDeletingMessagesStatus :: diff --git a/services/galley/src/Galley/Effects/TeamFeatureStore.hs b/services/galley/src/Galley/Effects/TeamFeatureStore.hs index cc9338574c..410795d1e3 100644 --- a/services/galley/src/Galley/Effects/TeamFeatureStore.hs +++ b/services/galley/src/Galley/Effects/TeamFeatureStore.hs @@ -64,7 +64,7 @@ data TeamFeatureStore m a where TeamFeatureStore m (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureAppLock) GetSelfDeletingMessagesStatus :: TeamId -> - TeamFeatureStore m (Maybe (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages)) + TeamFeatureStore m (Maybe (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages), Maybe PaymentStatusValue) SetSelfDeletingMessagesStatus :: TeamId -> TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages -> From 80b9b8ca9e90df0695ddf4c6a082126e94e8b938 Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Tue, 23 Nov 2021 12:51:47 +0100 Subject: [PATCH 11/28] renamed migration --- libs/wire-api/src/Wire/API/Team/Feature.hs | 4 ++-- services/galley/galley.cabal | 2 +- services/galley/schema/src/Main.hs | 4 ++-- ...mentStatus.hs => V55_SelfDeletingMessagesPaymentStatus.hs} | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) rename services/galley/schema/src/{V55_TeamFeatureWithConfigPaymentStatus.hs => V55_SelfDeletingMessagesPaymentStatus.hs} (96%) diff --git a/libs/wire-api/src/Wire/API/Team/Feature.hs b/libs/wire-api/src/Wire/API/Team/Feature.hs index f4c40b8dbf..e94dce05c6 100644 --- a/libs/wire-api/src/Wire/API/Team/Feature.hs +++ b/libs/wire-api/src/Wire/API/Team/Feature.hs @@ -280,8 +280,8 @@ instance Cass.Cql TeamFeatureStatusValue where ctype = Cass.Tagged Cass.IntColumn fromCql (Cass.CqlInt n) = case n of - 0 -> pure $ TeamFeatureDisabled - 1 -> pure $ TeamFeatureEnabled + 0 -> pure TeamFeatureDisabled + 1 -> pure TeamFeatureEnabled _ -> Left "fromCql: Invalid TeamFeatureStatusValue" fromCql _ = Left "fromCql: TeamFeatureStatusValue: CqlInt expected" diff --git a/services/galley/galley.cabal b/services/galley/galley.cabal index f2c0e83012..045fb684d7 100644 --- a/services/galley/galley.cabal +++ b/services/galley/galley.cabal @@ -437,7 +437,7 @@ executable galley-schema V52_FeatureConferenceCalling V53_AddRemoteConvStatus V54_TeamFeatureSelfDeletingMessages - V55_TeamFeatureWithConfigPaymentStatus + V55_SelfDeletingMessagesPaymentStatus Paths_galley hs-source-dirs: schema/src diff --git a/services/galley/schema/src/Main.hs b/services/galley/schema/src/Main.hs index 59cb7758ac..0184638f75 100644 --- a/services/galley/schema/src/Main.hs +++ b/services/galley/schema/src/Main.hs @@ -57,7 +57,7 @@ import qualified V51_FeatureFileSharing import qualified V52_FeatureConferenceCalling import qualified V53_AddRemoteConvStatus import qualified V54_TeamFeatureSelfDeletingMessages -import qualified V55_TeamFeatureWithConfigPaymentStatus +import qualified V55_SelfDeletingMessagesPaymentStatus main :: IO () main = do @@ -101,7 +101,7 @@ main = do V52_FeatureConferenceCalling.migration, V53_AddRemoteConvStatus.migration, V54_TeamFeatureSelfDeletingMessages.migration, - V55_TeamFeatureWithConfigPaymentStatus.migration + V55_SelfDeletingMessagesPaymentStatus.migration -- When adding migrations here, don't forget to update -- 'schemaVersion' in Galley.Cassandra -- (see also docs/developer/cassandra-interaction.md) diff --git a/services/galley/schema/src/V55_TeamFeatureWithConfigPaymentStatus.hs b/services/galley/schema/src/V55_SelfDeletingMessagesPaymentStatus.hs similarity index 96% rename from services/galley/schema/src/V55_TeamFeatureWithConfigPaymentStatus.hs rename to services/galley/schema/src/V55_SelfDeletingMessagesPaymentStatus.hs index 20927e852f..fa7ed93e8b 100644 --- a/services/galley/schema/src/V55_TeamFeatureWithConfigPaymentStatus.hs +++ b/services/galley/schema/src/V55_SelfDeletingMessagesPaymentStatus.hs @@ -15,7 +15,7 @@ -- You should have received a copy of the GNU Affero General Public License along -- with this program. If not, see . -module V55_TeamFeatureWithConfigPaymentStatus +module V55_SelfDeletingMessagesPaymentStatus ( migration, ) where From 95fc91adef2ada55ff304d7b845df59d213181f7 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Tue, 23 Nov 2021 21:32:19 +0100 Subject: [PATCH 12/28] Simplify. --- tools/stern/src/Stern/API.hs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/tools/stern/src/Stern/API.hs b/tools/stern/src/Stern/API.hs index 3e8b44aa98..fe27d5e3fa 100644 --- a/tools/stern/src/Stern/API.hs +++ b/tools/stern/src/Stern/API.hs @@ -361,7 +361,7 @@ routes = do Doc.description "team feature status (enabled or disabled)" Doc.response 200 "Team feature flag status" Doc.end - mkFeaturePutGetRoute @'Public.WithoutPaymentStatus @'Public.TeamFeatureAppLock + mkFeaturePutGetRoute @'Public.TeamFeatureAppLock -- These endpoints should be part of team settings. Until then, we access them from here -- for authorized personnel to enable/disable this on the team's behalf @@ -592,16 +592,16 @@ getTeamAdminInfo :: TeamId -> Handler Response getTeamAdminInfo = liftM (json . toAdminInfo) . Intra.getTeamInfo getTeamFeatureFlagH :: - forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName). + forall (a :: Public.TeamFeatureName). ( Public.KnownTeamFeatureName a, - FromJSON (Public.TeamFeatureStatus ps a), - ToJSON (Public.TeamFeatureStatus ps a), - Typeable (Public.TeamFeatureStatus ps a) + FromJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a), + ToJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a), + Typeable (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) ) => TeamId -> Handler Response getTeamFeatureFlagH tid = - json <$> Intra.getTeamFeatureFlag @ps @a tid + json <$> Intra.getTeamFeatureFlag @'Public.WithoutPaymentStatus @a tid setTeamFeatureFlagH :: forall (a :: Public.TeamFeatureName). @@ -753,19 +753,17 @@ noSuchUser :: Maybe a -> Handler a noSuchUser = ifNothing (mkError status404 "no-user" "No such user") mkFeaturePutGetRoute :: - forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName). + forall (a :: Public.TeamFeatureName). ( Public.KnownTeamFeatureName a, - FromJSON (Public.TeamFeatureStatus ps a), FromJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a), - ToJSON (Public.TeamFeatureStatus ps a), ToJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a), - Typeable (Public.TeamFeatureStatus ps a) + Typeable (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) ) => Routes Doc.ApiBuilder Handler () mkFeaturePutGetRoute = do let featureName = Public.knownTeamFeatureName @a - get ("/teams/:tid/features/" <> toByteString' featureName) (continue (getTeamFeatureFlagH @ps @a)) $ + get ("/teams/:tid/features/" <> toByteString' featureName) (continue (getTeamFeatureFlagH @a)) $ capture "tid" document "GET" "getTeamFeatureFlag" $ do summary "Shows whether a feature flag is enabled or not for a given team." From 187da9230438363c38a712feb1107f2a5024c06b Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Tue, 23 Nov 2021 22:24:33 +0100 Subject: [PATCH 13/28] Factor out feature locking function. --- .../galley/src/Galley/API/Teams/Features.hs | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/services/galley/src/Galley/API/Teams/Features.hs b/services/galley/src/Galley/API/Teams/Features.hs index c88525755c..7d5548f06d 100644 --- a/services/galley/src/Galley/API/Teams/Features.hs +++ b/services/galley/src/Galley/API/Teams/Features.hs @@ -608,14 +608,26 @@ setSelfDeletingMessagesInternal :: Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSelfDeletingMessages -> Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSelfDeletingMessages) setSelfDeletingMessagesInternal tid st = do - maybePaymentStatus <- TeamFeatures.getPaymentStatus @'Public.TeamFeatureSelfDeletingMessages tid - case maybePaymentStatus of - Just (Public.PaymentStatus Public.PaymentUnlocked) -> do - let pushEvent = - pushFeatureConfigEvent tid $ - Event.Event Event.Update Public.TeamFeatureSelfDeletingMessages (EdFeatureSelfDeletingMessagesChanged st) - TeamFeatures.setSelfDeletingMessagesStatus tid st <* pushEvent - _ -> throw PaymentStatusLocked + guardPaymentStatus @'Public.TeamFeatureSelfDeletingMessages tid (Public.PaymentStatus Public.PaymentLocked) + let pushEvent = + pushFeatureConfigEvent tid $ + Event.Event Event.Update Public.TeamFeatureSelfDeletingMessages (EdFeatureSelfDeletingMessagesChanged st) + TeamFeatures.setSelfDeletingMessagesStatus tid st <* pushEvent + +-- TODO(fisx): move this function to a more suitable place / module. +guardPaymentStatus :: + forall (a :: Public.TeamFeatureName) r. + ( MaybeHasPaymentStatusCol a, + Member TeamFeatureStore r, + Member (Error TeamFeatureError) r + ) => + TeamId -> + Public.PaymentStatus -> -- FUTUREWORK(fisx): move this into its own type class and infer from `a`? + Sem r () +guardPaymentStatus tid defPaymentStatus = do + (TeamFeatures.getPaymentStatus @a tid <&> fromMaybe defPaymentStatus) >>= \case + Public.PaymentStatus Public.PaymentUnlocked -> pure () + Public.PaymentStatus Public.PaymentLocked -> throw PaymentStatusLocked pushFeatureConfigEvent :: Members '[GundeckAccess, TeamStore, P.TinyLog] r => From 1a2b7dc57f022a4f84beea37f4edf27be5da819d Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Wed, 24 Nov 2021 11:36:47 +0100 Subject: [PATCH 14/28] FeatureHasNoConfig with PaymentStatus parameter --- libs/wire-api/src/Wire/API/Team/Feature.hs | 2 +- services/galley/src/Galley/API/LegalHold.hs | 2 +- services/galley/src/Galley/API/Teams.hs | 2 +- .../galley/src/Galley/API/Teams/Features.hs | 56 +++++++++---------- .../src/Galley/Cassandra/TeamFeatures.hs | 24 ++++---- .../src/Galley/Effects/TeamFeatureStore.hs | 36 ++++++------ services/galley/test/integration/API/Teams.hs | 2 +- .../test/integration/API/Teams/Feature.hs | 36 ++++++------ .../test/integration/API/Util/TeamFeature.hs | 17 +++--- 9 files changed, 91 insertions(+), 86 deletions(-) diff --git a/libs/wire-api/src/Wire/API/Team/Feature.hs b/libs/wire-api/src/Wire/API/Team/Feature.hs index e94dce05c6..9997ae8042 100644 --- a/libs/wire-api/src/Wire/API/Team/Feature.hs +++ b/libs/wire-api/src/Wire/API/Team/Feature.hs @@ -306,7 +306,7 @@ type family TeamFeatureStatus (ps :: IncludePaymentStatus) (a :: TeamFeatureName TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages = TeamFeatureStatusWithConfig TeamFeatureSelfDeletingMessagesConfig TeamFeatureStatus 'WithPaymentStatus 'TeamFeatureSelfDeletingMessages = TeamFeatureStatusWithConfigAndPaymentStatus TeamFeatureSelfDeletingMessagesConfig -type FeatureHasNoConfig (a :: TeamFeatureName) = (TeamFeatureStatus 'WithoutPaymentStatus a ~ TeamFeatureStatusNoConfig) :: Constraint +type FeatureHasNoConfig (ps :: IncludePaymentStatus) (a :: TeamFeatureName) = (TeamFeatureStatus ps a ~ TeamFeatureStatusNoConfig) :: Constraint -- if you add a new constructor here, don't forget to add it to the swagger (1.2) docs in "Wire.API.Swagger"! modelForTeamFeature :: TeamFeatureName -> Doc.Model diff --git a/services/galley/src/Galley/API/LegalHold.hs b/services/galley/src/Galley/API/LegalHold.hs index 5bbe62a236..7fff48d3ac 100644 --- a/services/galley/src/Galley/API/LegalHold.hs +++ b/services/galley/src/Galley/API/LegalHold.hs @@ -103,7 +103,7 @@ isLegalHoldEnabledForTeam tid = do pure False FeatureLegalHoldDisabledByDefault -> do statusValue <- - Public.tfwoStatus <$$> TeamFeatures.getFeatureStatusNoConfig @'Public.TeamFeatureLegalHold tid + Public.tfwoStatus <$$> TeamFeatures.getFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold tid return $ case statusValue of Just Public.TeamFeatureEnabled -> True Just Public.TeamFeatureDisabled -> False diff --git a/services/galley/src/Galley/API/Teams.hs b/services/galley/src/Galley/API/Teams.hs index ab74d16933..cdfff7d636 100644 --- a/services/galley/src/Galley/API/Teams.hs +++ b/services/galley/src/Galley/API/Teams.hs @@ -1532,7 +1532,7 @@ getTeamSearchVisibilityAvailableInternal tid = do FeatureTeamSearchVisibilityDisabledByDefault -> Public.TeamFeatureDisabled fromMaybe defConfig - <$> TeamFeatures.getFeatureStatusNoConfig @'Public.TeamFeatureSearchVisibility tid + <$> TeamFeatures.getFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility tid -- | Modify and get visibility type for a team (internal, no user permission checks) getSearchVisibilityInternalH :: diff --git a/services/galley/src/Galley/API/Teams/Features.hs b/services/galley/src/Galley/API/Teams/Features.hs index c88525755c..4a59acf794 100644 --- a/services/galley/src/Galley/API/Teams/Features.hs +++ b/services/galley/src/Galley/API/Teams/Features.hs @@ -295,32 +295,32 @@ getAllFeatures uid tid = do pure $ cs (toByteString' feature) Aeson..= status getFeatureStatusNoConfig :: - forall (a :: Public.TeamFeatureName) r. - ( Public.FeatureHasNoConfig a, + forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName) r. + ( Public.FeatureHasNoConfig ps a, HasStatusCol a, Member TeamFeatureStore r ) => Sem r Public.TeamFeatureStatusValue -> TeamId -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) + Sem r (Public.TeamFeatureStatus ps a) getFeatureStatusNoConfig getDefault tid = do defaultStatus <- Public.TeamFeatureStatusNoConfig <$> getDefault - fromMaybe defaultStatus <$> TeamFeatures.getFeatureStatusNoConfig @a tid + fromMaybe defaultStatus <$> TeamFeatures.getFeatureStatusNoConfig @ps @a tid setFeatureStatusNoConfig :: - forall (a :: Public.TeamFeatureName) r. + forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName) r. ( Public.KnownTeamFeatureName a, - Public.FeatureHasNoConfig a, + Public.FeatureHasNoConfig ps a, HasStatusCol a, Members '[GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r ) => (Public.TeamFeatureStatusValue -> TeamId -> Sem r ()) -> TeamId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) + Public.TeamFeatureStatus ps a -> + Sem r (Public.TeamFeatureStatus ps a) setFeatureStatusNoConfig applyState tid status = do applyState (Public.tfwoStatus status) tid - newStatus <- TeamFeatures.setFeatureStatusNoConfig @a tid status + newStatus <- TeamFeatures.setFeatureStatusNoConfig @ps @a tid status pushFeatureConfigEvent tid $ Event.Event Event.Update (Public.knownTeamFeatureName @a) (EdFeatureWithoutConfigChanged newStatus) pure newStatus @@ -336,7 +336,7 @@ getSSOStatusInternal :: getSSOStatusInternal = either (const $ Public.TeamFeatureStatusNoConfig <$> getDef) - (getFeatureStatusNoConfig @'Public.TeamFeatureSSO getDef) + (getFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO getDef) where getDef :: Member (Input Opts) r => Sem r Public.TeamFeatureStatusValue getDef = @@ -349,7 +349,7 @@ setSSOStatusInternal :: TeamId -> Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSSO -> Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSSO) -setSSOStatusInternal = setFeatureStatusNoConfig @'Public.TeamFeatureSSO $ \case +setSSOStatusInternal = setFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO $ \case Public.TeamFeatureDisabled -> const (throw DisableSsoNotImplemented) Public.TeamFeatureEnabled -> const (pure ()) @@ -360,7 +360,7 @@ getTeamSearchVisibilityAvailableInternal :: getTeamSearchVisibilityAvailableInternal = either (const $ Public.TeamFeatureStatusNoConfig <$> getDef) - (getFeatureStatusNoConfig @'Public.TeamFeatureSearchVisibility getDef) + (getFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility getDef) where getDef = do inputs (view (optSettings . setFeatureFlags . flagTeamSearchVisibility)) <&> \case @@ -372,7 +372,7 @@ setTeamSearchVisibilityAvailableInternal :: TeamId -> Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSearchVisibility -> Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSearchVisibility) -setTeamSearchVisibilityAvailableInternal = setFeatureStatusNoConfig @'Public.TeamFeatureSearchVisibility $ \case +setTeamSearchVisibilityAvailableInternal = setFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility $ \case Public.TeamFeatureDisabled -> SearchVisibilityData.resetSearchVisibility Public.TeamFeatureEnabled -> const (pure ()) @@ -383,7 +383,7 @@ getValidateSAMLEmailsInternal :: getValidateSAMLEmailsInternal = either (const $ Public.TeamFeatureStatusNoConfig <$> getDef) - (getFeatureStatusNoConfig @'Public.TeamFeatureValidateSAMLEmails getDef) + (getFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails getDef) where -- FUTUREWORK: we may also want to get a default from the server config file here, like for -- sso, and team search visibility. @@ -395,7 +395,7 @@ setValidateSAMLEmailsInternal :: TeamId -> Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureValidateSAMLEmails -> Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureValidateSAMLEmails) -setValidateSAMLEmailsInternal = setFeatureStatusNoConfig @'Public.TeamFeatureValidateSAMLEmails $ \_ _ -> pure () +setValidateSAMLEmailsInternal = setFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails $ \_ _ -> pure () getDigitalSignaturesInternal :: Member TeamFeatureStore r => @@ -404,7 +404,7 @@ getDigitalSignaturesInternal :: getDigitalSignaturesInternal = either (const $ Public.TeamFeatureStatusNoConfig <$> getDef) - (getFeatureStatusNoConfig @'Public.TeamFeatureDigitalSignatures getDef) + (getFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures getDef) where -- FUTUREWORK: we may also want to get a default from the server config file here, like for -- sso, and team search visibility. @@ -416,7 +416,7 @@ setDigitalSignaturesInternal :: TeamId -> Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureDigitalSignatures -> Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureDigitalSignatures) -setDigitalSignaturesInternal = setFeatureStatusNoConfig @'Public.TeamFeatureDigitalSignatures $ \_ _ -> pure () +setDigitalSignaturesInternal = setFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures $ \_ _ -> pure () getLegalholdStatusInternal :: Members '[LegalHoldStore, TeamFeatureStore, TeamStore] r => @@ -485,29 +485,29 @@ setLegalholdStatusInternal tid status@(Public.tfwoStatus -> statusValue) = do Public.TeamFeatureDisabled -> removeSettings' @p tid Public.TeamFeatureEnabled -> do ensureNotTooLargeToActivateLegalHold tid - TeamFeatures.setFeatureStatusNoConfig @'Public.TeamFeatureLegalHold tid status + TeamFeatures.setFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold tid status getFileSharingInternal :: Members '[Input Opts, TeamFeatureStore] r => GetFeatureInternalParam -> Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureFileSharing) getFileSharingInternal = - getFeatureStatusWithDefaultConfig @'Public.TeamFeatureFileSharing flagFileSharing . either (const Nothing) Just + getFeatureStatusWithDefaultConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureFileSharing flagFileSharing . either (const Nothing) Just getFeatureStatusWithDefaultConfig :: - forall (a :: TeamFeatureName) r. + forall (ps :: Public.IncludePaymentStatus) (a :: TeamFeatureName) r. ( KnownTeamFeatureName a, HasStatusCol a, - FeatureHasNoConfig a, + FeatureHasNoConfig ps a, Members '[Input Opts, TeamFeatureStore] r ) => - Lens' FeatureFlags (Defaults (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a)) -> + Lens' FeatureFlags (Defaults (Public.TeamFeatureStatus ps a)) -> Maybe TeamId -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) + Sem r (Public.TeamFeatureStatus ps a) getFeatureStatusWithDefaultConfig lens' = maybe (Public.TeamFeatureStatusNoConfig <$> getDef) - (getFeatureStatusNoConfig @a getDef) + (getFeatureStatusNoConfig @ps @a getDef) where getDef :: Sem r Public.TeamFeatureStatusValue getDef = @@ -519,7 +519,7 @@ setFileSharingInternal :: TeamId -> Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureFileSharing -> Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureFileSharing) -setFileSharingInternal = setFeatureStatusNoConfig @'Public.TeamFeatureFileSharing $ \_status _tid -> pure () +setFileSharingInternal = setFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureFileSharing $ \_status _tid -> pure () getAppLockInternal :: Members '[Input Opts, TeamFeatureStore] r => @@ -562,9 +562,9 @@ getConferenceCallingInternal :: getConferenceCallingInternal (Left (Just uid)) = do getFeatureConfigViaAccount @'Public.TeamFeatureConferenceCalling uid getConferenceCallingInternal (Left Nothing) = do - getFeatureStatusWithDefaultConfig @'Public.TeamFeatureConferenceCalling flagConferenceCalling Nothing + getFeatureStatusWithDefaultConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling flagConferenceCalling Nothing getConferenceCallingInternal (Right tid) = do - getFeatureStatusWithDefaultConfig @'Public.TeamFeatureConferenceCalling flagConferenceCalling (Just tid) + getFeatureStatusWithDefaultConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling flagConferenceCalling (Just tid) setConferenceCallingInternal :: Members '[GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r => @@ -572,7 +572,7 @@ setConferenceCallingInternal :: Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureConferenceCalling -> Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureConferenceCalling) setConferenceCallingInternal = - setFeatureStatusNoConfig @'Public.TeamFeatureConferenceCalling $ \_status _tid -> pure () + setFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling $ \_status _tid -> pure () getSelfDeletingMessagesInternal :: Member TeamFeatureStore r => diff --git a/services/galley/src/Galley/Cassandra/TeamFeatures.hs b/services/galley/src/Galley/Cassandra/TeamFeatures.hs index f0a1a5b3a5..3c1442e703 100644 --- a/services/galley/src/Galley/Cassandra/TeamFeatures.hs +++ b/services/galley/src/Galley/Cassandra/TeamFeatures.hs @@ -30,15 +30,16 @@ import Polysemy.Input import Wire.API.Team.Feature getFeatureStatusNoConfig :: - forall (a :: TeamFeatureName) m. + forall (ps :: IncludePaymentStatus) (a :: TeamFeatureName) m. ( MonadClient m, - FeatureHasNoConfig a, + FeatureHasNoConfig ps a, HasStatusCol a ) => + Proxy ps -> Proxy a -> TeamId -> - m (Maybe (TeamFeatureStatus 'WithoutPaymentStatus a)) -getFeatureStatusNoConfig _ tid = do + m (Maybe (TeamFeatureStatus ps a)) +getFeatureStatusNoConfig _ _ tid = do let q = query1 select (params LocalQuorum (Identity tid)) mStatusValue <- (>>= runIdentity) <$> retry x1 q pure $ TeamFeatureStatusNoConfig <$> mStatusValue @@ -47,16 +48,17 @@ getFeatureStatusNoConfig _ tid = do select = fromString $ "select " <> statusCol @a <> " from team_features where team_id = ?" setFeatureStatusNoConfig :: - forall (a :: TeamFeatureName) m. + forall (ps :: IncludePaymentStatus) (a :: TeamFeatureName) m. ( MonadClient m, - FeatureHasNoConfig a, + FeatureHasNoConfig ps a, HasStatusCol a ) => + Proxy ps -> Proxy a -> TeamId -> - TeamFeatureStatus 'WithoutPaymentStatus a -> - m (TeamFeatureStatus 'WithoutPaymentStatus a) -setFeatureStatusNoConfig _ tid status = do + TeamFeatureStatus ps a -> + m (TeamFeatureStatus ps a) +setFeatureStatusNoConfig _ _ tid status = do let flag = tfwoStatus status retry x5 $ write insert (params LocalQuorum (tid, flag)) pure status @@ -189,8 +191,8 @@ interpretTeamFeatureStoreToCassandra :: Sem (TeamFeatureStore ': r) a -> Sem r a interpretTeamFeatureStoreToCassandra = interpret $ \case - GetFeatureStatusNoConfig' p tid -> embedClient $ getFeatureStatusNoConfig p tid - SetFeatureStatusNoConfig' p tid value -> embedClient $ setFeatureStatusNoConfig p tid value + GetFeatureStatusNoConfig' ps tfn tid -> embedClient $ getFeatureStatusNoConfig ps tfn tid + SetFeatureStatusNoConfig' ps tfn tid value -> embedClient $ setFeatureStatusNoConfig ps tfn tid value SetPaymentStatus' p tid value -> embedClient $ setPaymentStatus p tid value GetPaymentStatus' p tid -> embedClient $ getPaymentStatus p tid GetApplockFeatureStatus tid -> embedClient $ getApplockFeatureStatus tid diff --git a/services/galley/src/Galley/Effects/TeamFeatureStore.hs b/services/galley/src/Galley/Effects/TeamFeatureStore.hs index 410795d1e3..3ad19f0c01 100644 --- a/services/galley/src/Galley/Effects/TeamFeatureStore.hs +++ b/services/galley/src/Galley/Effects/TeamFeatureStore.hs @@ -38,26 +38,28 @@ import Wire.API.Team.Feature data TeamFeatureStore m a where -- the proxy argument makes sure that makeSem below generates type-inference-friendly code GetFeatureStatusNoConfig' :: - forall (a :: TeamFeatureName) m. - ( FeatureHasNoConfig a, + forall (ps :: IncludePaymentStatus) (a :: TeamFeatureName) m. + ( FeatureHasNoConfig ps a, HasStatusCol a ) => + Proxy ps -> Proxy a -> TeamId -> - TeamFeatureStore m (Maybe (TeamFeatureStatus 'WithoutPaymentStatus a)) + TeamFeatureStore m (Maybe (TeamFeatureStatus ps a)) -- the proxy argument makes sure that makeSem below generates type-inference-friendly code SetFeatureStatusNoConfig' :: - forall (a :: TeamFeatureName) m. - ( FeatureHasNoConfig a, + forall (ps :: IncludePaymentStatus) (a :: TeamFeatureName) m. + ( FeatureHasNoConfig ps a, HasStatusCol a ) => + Proxy ps -> Proxy a -> TeamId -> - TeamFeatureStatus 'WithoutPaymentStatus a -> - TeamFeatureStore m (TeamFeatureStatus 'WithoutPaymentStatus a) + TeamFeatureStatus ps a -> + TeamFeatureStore m (TeamFeatureStatus ps a) GetApplockFeatureStatus :: TeamId -> - TeamFeatureStore m (Maybe (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureAppLock)) + TeamFeatureStore m (Maybe (TeamFeatureStatus ps 'TeamFeatureAppLock)) SetApplockFeatureStatus :: TeamId -> TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureAppLock -> @@ -88,19 +90,19 @@ data TeamFeatureStore m a where makeSem ''TeamFeatureStore getFeatureStatusNoConfig :: - forall (a :: TeamFeatureName) r. - (Member TeamFeatureStore r, FeatureHasNoConfig a, HasStatusCol a) => + forall (ps :: IncludePaymentStatus) (a :: TeamFeatureName) r. + (Member TeamFeatureStore r, FeatureHasNoConfig ps a, HasStatusCol a) => TeamId -> - Sem r (Maybe (TeamFeatureStatus 'WithoutPaymentStatus a)) -getFeatureStatusNoConfig = getFeatureStatusNoConfig' (Proxy @a) + Sem r (Maybe (TeamFeatureStatus ps a)) +getFeatureStatusNoConfig = getFeatureStatusNoConfig' (Proxy @ps) (Proxy @a) setFeatureStatusNoConfig :: - forall (a :: TeamFeatureName) r. - (Member TeamFeatureStore r, FeatureHasNoConfig a, HasStatusCol a) => + forall (ps :: IncludePaymentStatus) (a :: TeamFeatureName) r. + (Member TeamFeatureStore r, FeatureHasNoConfig ps a, HasStatusCol a) => TeamId -> - TeamFeatureStatus 'WithoutPaymentStatus a -> - Sem r (TeamFeatureStatus 'WithoutPaymentStatus a) -setFeatureStatusNoConfig = setFeatureStatusNoConfig' (Proxy @a) + TeamFeatureStatus ps a -> + Sem r (TeamFeatureStatus ps a) +setFeatureStatusNoConfig = setFeatureStatusNoConfig' (Proxy @ps) (Proxy @a) setPaymentStatus :: forall (a :: TeamFeatureName) r. diff --git a/services/galley/test/integration/API/Teams.hs b/services/galley/test/integration/API/Teams.hs index 8ff360dd57..f539707b41 100644 --- a/services/galley/test/integration/API/Teams.hs +++ b/services/galley/test/integration/API/Teams.hs @@ -1892,7 +1892,7 @@ getSSOEnabledInternal :: HasCallStack => TeamId -> TestM ResponseLBS getSSOEnabledInternal = Util.getTeamFeatureFlagInternal Public.TeamFeatureSSO putSSOEnabledInternal :: HasCallStack => TeamId -> Public.TeamFeatureStatusValue -> TestM () -putSSOEnabledInternal tid statusValue = void $ Util.putTeamFeatureFlagInternal @'Public.TeamFeatureSSO expect2xx tid (Public.TeamFeatureStatusNoConfig statusValue) +putSSOEnabledInternal tid statusValue = void $ Util.putTeamFeatureFlagInternal @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO expect2xx tid (Public.TeamFeatureStatusNoConfig statusValue) getSearchVisibility :: HasCallStack => (Request -> Request) -> UserId -> TeamId -> (MonadIO m, MonadHttp m) => m ResponseLBS getSearchVisibility g uid tid = do diff --git a/services/galley/test/integration/API/Teams/Feature.hs b/services/galley/test/integration/API/Teams/Feature.hs index 0586a7bd9c..a7eb49e792 100644 --- a/services/galley/test/integration/API/Teams/Feature.hs +++ b/services/galley/test/integration/API/Teams/Feature.hs @@ -81,13 +81,13 @@ testSSO = do Util.addTeamMember owner tid member (rolePermissions RoleMember) Nothing let getSSO :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () - getSSO = assertFlagNoConfig @'Public.TeamFeatureSSO $ Util.getTeamFeatureFlag Public.TeamFeatureSSO member tid + getSSO = assertFlagNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO $ Util.getTeamFeatureFlag Public.TeamFeatureSSO member tid getSSOFeatureConfig :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () - getSSOFeatureConfig = assertFlagNoConfig @'Public.TeamFeatureSSO $ Util.getFeatureConfig Public.TeamFeatureSSO member + getSSOFeatureConfig = assertFlagNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO $ Util.getFeatureConfig Public.TeamFeatureSSO member getSSOInternal :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () - getSSOInternal = assertFlagNoConfig @'Public.TeamFeatureSSO $ Util.getTeamFeatureFlagInternal Public.TeamFeatureSSO tid + getSSOInternal = assertFlagNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO $ Util.getTeamFeatureFlagInternal Public.TeamFeatureSSO tid setSSOInternal :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () - setSSOInternal = void . Util.putTeamFeatureFlagInternal @'Public.TeamFeatureSSO expect2xx tid . Public.TeamFeatureStatusNoConfig + setSSOInternal = void . Util.putTeamFeatureFlagInternal @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO expect2xx tid . Public.TeamFeatureStatusNoConfig assertFlagForbidden $ Util.getTeamFeatureFlag Public.TeamFeatureSSO nonMember tid @@ -121,13 +121,13 @@ testLegalHold = do Util.addTeamMember owner tid member (rolePermissions RoleMember) Nothing let getLegalHold :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () - getLegalHold = assertFlagNoConfig @'Public.TeamFeatureLegalHold $ Util.getTeamFeatureFlag Public.TeamFeatureLegalHold member tid + getLegalHold = assertFlagNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold $ Util.getTeamFeatureFlag Public.TeamFeatureLegalHold member tid getLegalHoldInternal :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () - getLegalHoldInternal = assertFlagNoConfig @'Public.TeamFeatureLegalHold $ Util.getTeamFeatureFlagInternal Public.TeamFeatureLegalHold tid - getLegalHoldFeatureConfig = assertFlagNoConfig @'Public.TeamFeatureLegalHold $ Util.getFeatureConfig Public.TeamFeatureLegalHold member + getLegalHoldInternal = assertFlagNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold $ Util.getTeamFeatureFlagInternal Public.TeamFeatureLegalHold tid + getLegalHoldFeatureConfig = assertFlagNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold $ Util.getFeatureConfig Public.TeamFeatureLegalHold member setLegalHoldInternal :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () - setLegalHoldInternal = void . Util.putTeamFeatureFlagInternal @'Public.TeamFeatureLegalHold expect2xx tid . Public.TeamFeatureStatusNoConfig + setLegalHoldInternal = void . Util.putTeamFeatureFlagInternal @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold expect2xx tid . Public.TeamFeatureStatusNoConfig getLegalHold Public.TeamFeatureDisabled getLegalHoldInternal Public.TeamFeatureDisabled @@ -319,9 +319,9 @@ testSimpleFlag :: forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName). ( HasCallStack, Typeable a, - Public.FeatureHasNoConfig a, + Public.FeatureHasNoConfig ps a, Public.KnownTeamFeatureName a, - FromJSON (Public.TeamFeatureStatus ps a), + FromJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a), ToJSON (Public.TeamFeatureStatus ps a) ) => Public.TeamFeatureStatusValue -> @@ -337,19 +337,19 @@ testSimpleFlag defaultValue = do let getFlag :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () getFlag expected = - flip (assertFlagNoConfig @a) expected $ Util.getTeamFeatureFlag feature member tid + flip (assertFlagNoConfig @ps @a) expected $ Util.getTeamFeatureFlag feature member tid getFeatureConfig :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () getFeatureConfig expected = - flip (assertFlagNoConfig @a) expected $ Util.getFeatureConfig feature member + flip (assertFlagNoConfig @ps @a) expected $ Util.getFeatureConfig feature member getFlagInternal :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () getFlagInternal expected = - flip (assertFlagNoConfig @a) expected $ Util.getTeamFeatureFlagInternal feature tid + flip (assertFlagNoConfig @ps @a) expected $ Util.getTeamFeatureFlagInternal feature tid setFlagInternal :: Public.TeamFeatureStatusValue -> TestM () setFlagInternal statusValue = - void $ Util.putTeamFeatureFlagInternal @a expect2xx tid (Public.TeamFeatureStatusNoConfig statusValue) + void $ Util.putTeamFeatureFlagInternal @ps @a expect2xx tid (Public.TeamFeatureStatusNoConfig statusValue) assertFlagForbidden $ Util.getTeamFeatureFlag feature nonMember tid @@ -404,7 +404,7 @@ testSelfDeletingMessages = do let checkSet :: TeamFeatureStatusValue -> Int32 -> Int -> TestM () checkSet stat tout expectedStatusCode = do - Util.putTeamFeatureFlagInternal @'Public.TeamFeatureSelfDeletingMessages + Util.putTeamFeatureFlagInternal @'Public.WithoutPaymentStatus @'Public.TeamFeatureSelfDeletingMessages galley tid (settingWithOutPaymentStatus stat tout) @@ -525,10 +525,10 @@ assertFlagForbidden res = do fmap label . responseJsonMaybe === const (Just "no-team-member") assertFlagNoConfig :: - forall (a :: Public.TeamFeatureName). + forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName). ( HasCallStack, Typeable a, - Public.FeatureHasNoConfig a, + Public.FeatureHasNoConfig ps a, FromJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a), Public.KnownTeamFeatureName a ) => @@ -539,7 +539,7 @@ assertFlagNoConfig res expected = do res !!! do statusCode === const 200 ( fmap Public.tfwoStatus - . responseJsonEither @(Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) + . responseJsonEither @(Public.TeamFeatureStatus ps a) ) === const (Right expected) diff --git a/services/galley/test/integration/API/Util/TeamFeature.hs b/services/galley/test/integration/API/Util/TeamFeature.hs index bdd7c2d8dc..d984212b4d 100644 --- a/services/galley/test/integration/API/Util/TeamFeature.hs +++ b/services/galley/test/integration/API/Util/TeamFeature.hs @@ -53,6 +53,7 @@ putTeamSearchVisibilityAvailableInternal :: putTeamSearchVisibilityAvailableInternal g tid statusValue = void $ putTeamFeatureFlagInternalWithGalleyAndMod + @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility g expect2xx @@ -66,7 +67,7 @@ putLegalHoldEnabledInternal' :: Public.TeamFeatureStatusValue -> TestM () putLegalHoldEnabledInternal' g tid statusValue = - void $ putTeamFeatureFlagInternal @'Public.TeamFeatureLegalHold g tid (Public.TeamFeatureStatusNoConfig statusValue) + void $ putTeamFeatureFlagInternal @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold g tid (Public.TeamFeatureStatusNoConfig statusValue) -------------------------------------------------------------------------------- @@ -150,31 +151,31 @@ getAllFeatureConfigsWithGalley galley uid = do . zUser uid putTeamFeatureFlagInternal :: - forall (a :: Public.TeamFeatureName). + forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName). ( HasCallStack, Public.KnownTeamFeatureName a, - ToJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) + ToJSON (Public.TeamFeatureStatus ps a) ) => (Request -> Request) -> TeamId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a -> + Public.TeamFeatureStatus ps a -> TestM ResponseLBS putTeamFeatureFlagInternal reqmod tid status = do g <- view tsGalley - putTeamFeatureFlagInternalWithGalleyAndMod @a g reqmod tid status + putTeamFeatureFlagInternalWithGalleyAndMod @ps @a g reqmod tid status putTeamFeatureFlagInternalWithGalleyAndMod :: - forall (a :: Public.TeamFeatureName) m. + forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName) m. ( MonadIO m, MonadHttp m, HasCallStack, Public.KnownTeamFeatureName a, - ToJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) + ToJSON (Public.TeamFeatureStatus ps a) ) => (Request -> Request) -> (Request -> Request) -> TeamId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a -> + Public.TeamFeatureStatus ps a -> m ResponseLBS putTeamFeatureFlagInternalWithGalleyAndMod galley reqmod tid status = put $ From d37484a3f54819e4253e91b753379b5d5f538cbe Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Wed, 24 Nov 2021 11:42:43 +0100 Subject: [PATCH 15/28] remove comment Co-authored-by: fisx --- services/galley/galley.cabal | 1 - 1 file changed, 1 deletion(-) diff --git a/services/galley/galley.cabal b/services/galley/galley.cabal index 045fb684d7..d239a0aa92 100644 --- a/services/galley/galley.cabal +++ b/services/galley/galley.cabal @@ -466,7 +466,6 @@ executable galley-schema ld-options: -static default-language: Haskell2010 --- FUTUREWORK(Leif): rename to galley-tests here and in the package.yaml file test-suite galley-types-tests type: exitcode-stdio-1.0 main-is: Main.hs From f3d8cdd97228f05f05f3f2ad88dad0e03b762339 Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Wed, 24 Nov 2021 11:44:56 +0100 Subject: [PATCH 16/28] additional roundtrip test Co-authored-by: fisx --- libs/wire-api/test/unit/Test/Wire/API/Roundtrip/Aeson.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/wire-api/test/unit/Test/Wire/API/Roundtrip/Aeson.hs b/libs/wire-api/test/unit/Test/Wire/API/Roundtrip/Aeson.hs index f9c67d7d30..220c31e50c 100644 --- a/libs/wire-api/test/unit/Test/Wire/API/Roundtrip/Aeson.hs +++ b/libs/wire-api/test/unit/Test/Wire/API/Roundtrip/Aeson.hs @@ -206,6 +206,7 @@ tests = testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureConferenceCalling), testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureSelfDeletingMessages), testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithPaymentStatus 'Team.Feature.TeamFeatureSelfDeletingMessages), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureSelfDeletingMessages), testRoundTrip @Team.Feature.TeamFeatureStatusValue, testRoundTrip @Team.Feature.PaymentStatusValue, testRoundTrip @Team.Feature.PaymentStatus, From f1f35f696928c363432a98d0458a5c54ab854eeb Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Wed, 24 Nov 2021 12:25:01 +0100 Subject: [PATCH 17/28] typo Co-authored-by: fisx --- services/galley/src/Galley/API/Internal.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/galley/src/Galley/API/Internal.hs b/services/galley/src/Galley/API/Internal.hs index 18a3949345..1b4e930c64 100644 --- a/services/galley/src/Galley/API/Internal.hs +++ b/services/galley/src/Galley/API/Internal.hs @@ -256,7 +256,7 @@ type IFeatureStatusPut featureName = :> Put '[Servant.JSON] (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus featureName) type IFeatureStatusPaymentStatusPut featureName = - Summary (AppendSymbol "(Un-) lock payment for " (Public.KnownTeamFeatureNameSymbol featureName)) + Summary (AppendSymbol "(Un-)lock payment for " (Public.KnownTeamFeatureNameSymbol featureName)) :> "i" :> "teams" :> Capture "tid" TeamId From d401ddaffa56bb61355311871103767b5ace5d27 Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Wed, 24 Nov 2021 12:29:05 +0100 Subject: [PATCH 18/28] clean up Co-authored-by: fisx --- services/galley/src/Galley/API/Teams/Features.hs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/services/galley/src/Galley/API/Teams/Features.hs b/services/galley/src/Galley/API/Teams/Features.hs index 2152e010f5..569614b123 100644 --- a/services/galley/src/Galley/API/Teams/Features.hs +++ b/services/galley/src/Galley/API/Teams/Features.hs @@ -589,10 +589,7 @@ getSelfDeletingMessagesInternal = \case (Public.tfwcConfig featureStatus) Public.PaymentUnlocked (Just Public.PaymentUnlocked, Nothing) -> - Public.TeamFeatureStatusWithConfigAndPaymentStatus - (Public.tfwcapsStatus Public.defaultSelfDeletingMessagesStatus) - (Public.tfwcapsConfig Public.defaultSelfDeletingMessagesStatus) - Public.PaymentUnlocked + Public.defaultSelfDeletingMessagesStatus {Public.tfwcapsPaymentStatus = Public.PaymentUnlocked} _ -> Public.defaultSelfDeletingMessagesStatus setSelfDeletingMessagesInternal :: From b268c100f4e8d9c42888e08b10fb62aaad0aaf47 Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Wed, 24 Nov 2021 12:35:46 +0100 Subject: [PATCH 19/28] more explicit pattern match --- services/galley/src/Galley/API/Teams/Features.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/galley/src/Galley/API/Teams/Features.hs b/services/galley/src/Galley/API/Teams/Features.hs index 569614b123..5783a34b0d 100644 --- a/services/galley/src/Galley/API/Teams/Features.hs +++ b/services/galley/src/Galley/API/Teams/Features.hs @@ -590,7 +590,8 @@ getSelfDeletingMessagesInternal = \case Public.PaymentUnlocked (Just Public.PaymentUnlocked, Nothing) -> Public.defaultSelfDeletingMessagesStatus {Public.tfwcapsPaymentStatus = Public.PaymentUnlocked} - _ -> Public.defaultSelfDeletingMessagesStatus + (Just Public.PaymentLocked, _) -> Public.defaultSelfDeletingMessagesStatus + (Nothing, _) -> Public.defaultSelfDeletingMessagesStatus setSelfDeletingMessagesInternal :: Members From 743da2f6bce1e9e017b69a9eba735f2d0272b9e7 Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Wed, 24 Nov 2021 12:56:13 +0100 Subject: [PATCH 20/28] simplify payment status to payment status value --- services/galley/src/Galley/API/Teams/Features.hs | 8 ++++---- services/galley/src/Galley/Cassandra/TeamFeatures.hs | 5 ++--- services/galley/src/Galley/Effects/TeamFeatureStore.hs | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/services/galley/src/Galley/API/Teams/Features.hs b/services/galley/src/Galley/API/Teams/Features.hs index 5783a34b0d..625e5426d6 100644 --- a/services/galley/src/Galley/API/Teams/Features.hs +++ b/services/galley/src/Galley/API/Teams/Features.hs @@ -606,7 +606,7 @@ setSelfDeletingMessagesInternal :: Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSelfDeletingMessages -> Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSelfDeletingMessages) setSelfDeletingMessagesInternal tid st = do - guardPaymentStatus @'Public.TeamFeatureSelfDeletingMessages tid (Public.PaymentStatus Public.PaymentLocked) + guardPaymentStatus @'Public.TeamFeatureSelfDeletingMessages tid Public.PaymentLocked let pushEvent = pushFeatureConfigEvent tid $ Event.Event Event.Update Public.TeamFeatureSelfDeletingMessages (EdFeatureSelfDeletingMessagesChanged st) @@ -620,12 +620,12 @@ guardPaymentStatus :: Member (Error TeamFeatureError) r ) => TeamId -> - Public.PaymentStatus -> -- FUTUREWORK(fisx): move this into its own type class and infer from `a`? + Public.PaymentStatusValue -> -- FUTUREWORK(fisx): move this into its own type class and infer from `a`? Sem r () guardPaymentStatus tid defPaymentStatus = do (TeamFeatures.getPaymentStatus @a tid <&> fromMaybe defPaymentStatus) >>= \case - Public.PaymentStatus Public.PaymentUnlocked -> pure () - Public.PaymentStatus Public.PaymentLocked -> throw PaymentStatusLocked + Public.PaymentUnlocked -> pure () + Public.PaymentLocked -> throw PaymentStatusLocked pushFeatureConfigEvent :: Members '[GundeckAccess, TeamStore, P.TinyLog] r => diff --git a/services/galley/src/Galley/Cassandra/TeamFeatures.hs b/services/galley/src/Galley/Cassandra/TeamFeatures.hs index 3c1442e703..4fb91eaafd 100644 --- a/services/galley/src/Galley/Cassandra/TeamFeatures.hs +++ b/services/galley/src/Galley/Cassandra/TeamFeatures.hs @@ -170,14 +170,13 @@ getPaymentStatus :: ) => Proxy a -> TeamId -> - m (Maybe PaymentStatus) + m (Maybe PaymentStatusValue) getPaymentStatus _ tid = case maybePaymentStatusCol @a of Nothing -> pure Nothing Just paymentStatusColName -> do let q = query1 select (params LocalQuorum (Identity tid)) - mTuple <- (>>= runIdentity) <$> retry x1 q - pure $ PaymentStatus <$> mTuple + (>>= runIdentity) <$> retry x1 q where select :: PrepQuery R (Identity TeamId) (Identity (Maybe PaymentStatusValue)) select = diff --git a/services/galley/src/Galley/Effects/TeamFeatureStore.hs b/services/galley/src/Galley/Effects/TeamFeatureStore.hs index 3ad19f0c01..9be53b4734 100644 --- a/services/galley/src/Galley/Effects/TeamFeatureStore.hs +++ b/services/galley/src/Galley/Effects/TeamFeatureStore.hs @@ -85,7 +85,7 @@ data TeamFeatureStore m a where ) => Proxy a -> TeamId -> - TeamFeatureStore m (Maybe PaymentStatus) + TeamFeatureStore m (Maybe PaymentStatusValue) makeSem ''TeamFeatureStore @@ -116,5 +116,5 @@ getPaymentStatus :: forall (a :: TeamFeatureName) r. (Member TeamFeatureStore r, MaybeHasPaymentStatusCol a) => TeamId -> - Sem r (Maybe PaymentStatus) + Sem r (Maybe PaymentStatusValue) getPaymentStatus = getPaymentStatus' (Proxy @a) From 151f7124adb6281204336e00e61ff1a7dc0fdb94 Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Wed, 24 Nov 2021 12:56:58 +0100 Subject: [PATCH 21/28] typo Co-authored-by: fisx --- services/galley/test/integration/API/Teams/Feature.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/galley/test/integration/API/Teams/Feature.hs b/services/galley/test/integration/API/Teams/Feature.hs index a7eb49e792..6a06eeccd7 100644 --- a/services/galley/test/integration/API/Teams/Feature.hs +++ b/services/galley/test/integration/API/Teams/Feature.hs @@ -381,8 +381,8 @@ testSimpleFlag defaultValue = do testSelfDeletingMessages :: TestM () testSelfDeletingMessages = do -- personal users - let settingWithOutPaymentStatus :: TeamFeatureStatusValue -> Int32 -> Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSelfDeletingMessages - settingWithOutPaymentStatus stat tout = + let settingWithoutPaymentStatus :: TeamFeatureStatusValue -> Int32 -> Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSelfDeletingMessages + settingWithoutPaymentStatus stat tout = Public.TeamFeatureStatusWithConfig @Public.TeamFeatureSelfDeletingMessagesConfig stat (Public.TeamFeatureSelfDeletingMessagesConfig tout) From fe9fce95c45fd44f6881685b088f554b142ddeb7 Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Wed, 24 Nov 2021 13:13:25 +0100 Subject: [PATCH 22/28] changelog --- .../get-feature-config-seld-del-msgs-with-payment-status | 1 + changelog.d/1-api-changes/set-payment-status-self-del-msgs | 1 + changelog.d/2-features/set-payment-status-for-self-del-msgs | 1 + 3 files changed, 3 insertions(+) create mode 100644 changelog.d/1-api-changes/get-feature-config-seld-del-msgs-with-payment-status create mode 100644 changelog.d/1-api-changes/set-payment-status-self-del-msgs create mode 100644 changelog.d/2-features/set-payment-status-for-self-del-msgs diff --git a/changelog.d/1-api-changes/get-feature-config-seld-del-msgs-with-payment-status b/changelog.d/1-api-changes/get-feature-config-seld-del-msgs-with-payment-status new file mode 100644 index 0000000000..28b3679e34 --- /dev/null +++ b/changelog.d/1-api-changes/get-feature-config-seld-del-msgs-with-payment-status @@ -0,0 +1 @@ +get team feature config for self deleting messages response includes payment status diff --git a/changelog.d/1-api-changes/set-payment-status-self-del-msgs b/changelog.d/1-api-changes/set-payment-status-self-del-msgs new file mode 100644 index 0000000000..89029f4ca4 --- /dev/null +++ b/changelog.d/1-api-changes/set-payment-status-self-del-msgs @@ -0,0 +1 @@ +new internal endpoints for setting the payment status of self deleting messages diff --git a/changelog.d/2-features/set-payment-status-for-self-del-msgs b/changelog.d/2-features/set-payment-status-for-self-del-msgs new file mode 100644 index 0000000000..6798a7b24d --- /dev/null +++ b/changelog.d/2-features/set-payment-status-for-self-del-msgs @@ -0,0 +1 @@ +payment status for the self deleting messages feature can be set internally by ibis and customer support From 1f0c70181c5886c6b33930432cfd9594420f0440 Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Wed, 24 Nov 2021 13:20:57 +0100 Subject: [PATCH 23/28] update schema docs --- docs/reference/cassandra-schema.cql | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/reference/cassandra-schema.cql b/docs/reference/cassandra-schema.cql index 7b70e2f464..ec307eb446 100644 --- a/docs/reference/cassandra-schema.cql +++ b/docs/reference/cassandra-schema.cql @@ -422,6 +422,7 @@ CREATE TABLE galley_test.team_features ( file_sharing int, legalhold_status int, search_visibility_status int, + self_deleting_messages_payment_status int, self_deleting_messages_status int, self_deleting_messages_ttl int, sso_status int, From 43b1be00c7cfbadf9da82dbe884ed8d89bb3b120 Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Wed, 24 Nov 2021 15:11:04 +0100 Subject: [PATCH 24/28] typo --- services/galley/test/integration/API/Teams/Feature.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/galley/test/integration/API/Teams/Feature.hs b/services/galley/test/integration/API/Teams/Feature.hs index 6a06eeccd7..9af553bbca 100644 --- a/services/galley/test/integration/API/Teams/Feature.hs +++ b/services/galley/test/integration/API/Teams/Feature.hs @@ -407,7 +407,7 @@ testSelfDeletingMessages = do Util.putTeamFeatureFlagInternal @'Public.WithoutPaymentStatus @'Public.TeamFeatureSelfDeletingMessages galley tid - (settingWithOutPaymentStatus stat tout) + (settingWithoutPaymentStatus stat tout) !!! statusCode === const expectedStatusCode -- internal, public (/team/:tid/features), and team-agnostic (/feature-configs). From e7cbecc1720e102579cfb4ff5d8a664a0cc1ba86 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 24 Nov 2021 21:10:36 +0100 Subject: [PATCH 25/28] s/payment/lock/gi; (it turns out there is more than one reason to lock a feature from configuration, eg., because it is configured for the site and shouldn't be changed by team admins.) --- ...e-config-seld-del-msgs-with-payment-status | 2 +- .../set-payment-status-self-del-msgs | 2 +- .../set-payment-status-for-self-del-msgs | 2 +- docs/reference/cassandra-schema.cql | 3 +- libs/galley-types/src/Galley/Types/Teams.hs | 10 +- .../src/Wire/API/Routes/Internal/Brig.hs | 4 +- .../src/Wire/API/Routes/Public/Galley.hs | 36 ++-- .../src/Wire/API/Routes/Public/LegalHold.hs | 4 +- libs/wire-api/src/Wire/API/Swagger.hs | 2 +- libs/wire-api/src/Wire/API/Team/Feature.hs | 130 ++++++------ .../golden/Test/Wire/API/Golden/Generator.hs | 4 +- .../unit/Test/Wire/API/Roundtrip/Aeson.hs | 28 +-- services/brig/src/Brig/IO/Intra.hs | 4 +- services/brig/src/Brig/Options.hs | 4 +- services/galley/galley.cabal | 2 +- services/galley/schema/src/Main.hs | 4 +- ... => V55_SelfDeletingMessagesLockStatus.hs} | 4 +- services/galley/src/Galley/API/Error.hs | 8 +- services/galley/src/Galley/API/Internal.hs | 92 ++++---- services/galley/src/Galley/API/LegalHold.hs | 2 +- services/galley/src/Galley/API/Public.hs | 46 ++-- services/galley/src/Galley/API/Teams.hs | 4 +- .../galley/src/Galley/API/Teams/Features.hs | 196 +++++++++--------- .../src/Galley/Cassandra/TeamFeatures.hs | 60 +++--- .../galley/src/Galley/Data/TeamFeatures.hs | 34 +-- .../src/Galley/Effects/TeamFeatureStore.hs | 54 ++--- services/galley/test/integration/API/Teams.hs | 6 +- .../test/integration/API/Teams/Feature.hs | 98 ++++----- .../test/integration/API/Teams/LegalHold.hs | 6 +- .../API/Teams/LegalHold/DisabledByDefault.hs | 10 +- .../test/integration/API/Util/TeamFeature.hs | 18 +- services/spar/src/Spar/Intra/Galley.hs | 4 +- tools/stern/src/Stern/API.hs | 24 +-- tools/stern/src/Stern/Intra.hs | 6 +- 34 files changed, 456 insertions(+), 457 deletions(-) rename services/galley/schema/src/{V55_SelfDeletingMessagesPaymentStatus.hs => V55_SelfDeletingMessagesLockStatus.hs} (91%) diff --git a/changelog.d/1-api-changes/get-feature-config-seld-del-msgs-with-payment-status b/changelog.d/1-api-changes/get-feature-config-seld-del-msgs-with-payment-status index 28b3679e34..d1855d92dd 100644 --- a/changelog.d/1-api-changes/get-feature-config-seld-del-msgs-with-payment-status +++ b/changelog.d/1-api-changes/get-feature-config-seld-del-msgs-with-payment-status @@ -1 +1 @@ -get team feature config for self deleting messages response includes payment status +get team feature config for self deleting messages response includes lock status diff --git a/changelog.d/1-api-changes/set-payment-status-self-del-msgs b/changelog.d/1-api-changes/set-payment-status-self-del-msgs index 89029f4ca4..3cca58aab4 100644 --- a/changelog.d/1-api-changes/set-payment-status-self-del-msgs +++ b/changelog.d/1-api-changes/set-payment-status-self-del-msgs @@ -1 +1 @@ -new internal endpoints for setting the payment status of self deleting messages +new internal endpoints for setting the lock status of self deleting messages diff --git a/changelog.d/2-features/set-payment-status-for-self-del-msgs b/changelog.d/2-features/set-payment-status-for-self-del-msgs index 6798a7b24d..1b0c9e647b 100644 --- a/changelog.d/2-features/set-payment-status-for-self-del-msgs +++ b/changelog.d/2-features/set-payment-status-for-self-del-msgs @@ -1 +1 @@ -payment status for the self deleting messages feature can be set internally by ibis and customer support +Lock status for the self deleting messages feature can be set internally by ibis and customer support diff --git a/docs/reference/cassandra-schema.cql b/docs/reference/cassandra-schema.cql index ec307eb446..ddecfdc218 100644 --- a/docs/reference/cassandra-schema.cql +++ b/docs/reference/cassandra-schema.cql @@ -422,7 +422,7 @@ CREATE TABLE galley_test.team_features ( file_sharing int, legalhold_status int, search_visibility_status int, - self_deleting_messages_payment_status int, + self_deleting_messages_lock_status int, self_deleting_messages_status int, self_deleting_messages_ttl int, sso_status int, @@ -1798,4 +1798,3 @@ CREATE TABLE spar_test.user ( AND min_index_interval = 128 AND read_repair_chance = 0.0 AND speculative_retry = '99PERCENTILE'; - diff --git a/libs/galley-types/src/Galley/Types/Teams.hs b/libs/galley-types/src/Galley/Types/Teams.hs index bcd70f41f9..d1b0d1851a 100644 --- a/libs/galley-types/src/Galley/Types/Teams.hs +++ b/libs/galley-types/src/Galley/Types/Teams.hs @@ -212,11 +212,11 @@ data FeatureFlags = FeatureFlags { _flagSSO :: !FeatureSSO, _flagLegalHold :: !FeatureLegalHold, _flagTeamSearchVisibility :: !FeatureTeamSearchVisibility, - _flagAppLockDefaults :: !(Defaults (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureAppLock)), - _flagClassifiedDomains :: !(TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureClassifiedDomains), - _flagFileSharing :: !(Defaults (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureFileSharing)), - _flagConferenceCalling :: !(Defaults (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureConferenceCalling)), - _flagSelfDeletingMessages :: !(Defaults (TeamFeatureStatus 'WithPaymentStatus 'TeamFeatureSelfDeletingMessages)) + _flagAppLockDefaults :: !(Defaults (TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureAppLock)), + _flagClassifiedDomains :: !(TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureClassifiedDomains), + _flagFileSharing :: !(Defaults (TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureFileSharing)), + _flagConferenceCalling :: !(Defaults (TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureConferenceCalling)), + _flagSelfDeletingMessages :: !(Defaults (TeamFeatureStatus 'WithLockStatus 'TeamFeatureSelfDeletingMessages)) } deriving (Eq, Show, Generic) diff --git a/libs/wire-api/src/Wire/API/Routes/Internal/Brig.hs b/libs/wire-api/src/Wire/API/Routes/Internal/Brig.hs index b97c6efbfa..5027a55405 100644 --- a/libs/wire-api/src/Wire/API/Routes/Internal/Brig.hs +++ b/libs/wire-api/src/Wire/API/Routes/Internal/Brig.hs @@ -66,7 +66,7 @@ type GetAccountFeatureConfig = :> Capture "uid" UserId :> "features" :> "conferenceCalling" - :> Get '[Servant.JSON] (ApiFt.TeamFeatureStatus 'ApiFt.WithPaymentStatus 'ApiFt.TeamFeatureConferenceCalling) + :> Get '[Servant.JSON] (ApiFt.TeamFeatureStatus 'ApiFt.WithLockStatus 'ApiFt.TeamFeatureConferenceCalling) type PutAccountFeatureConfig = Summary @@ -75,7 +75,7 @@ type PutAccountFeatureConfig = :> Capture "uid" UserId :> "features" :> "conferenceCalling" - :> Servant.ReqBody '[Servant.JSON] (ApiFt.TeamFeatureStatus 'ApiFt.WithoutPaymentStatus 'ApiFt.TeamFeatureConferenceCalling) + :> Servant.ReqBody '[Servant.JSON] (ApiFt.TeamFeatureStatus 'ApiFt.WithoutLockStatus 'ApiFt.TeamFeatureConferenceCalling) :> Put '[Servant.JSON] NoContent type DeleteAccountFeatureConfig = diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Galley.hs b/libs/wire-api/src/Wire/API/Routes/Public/Galley.hs index afa0ba0272..ff1dc2ed87 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Galley.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Galley.hs @@ -623,7 +623,7 @@ data Api routes = Api :- FeatureStatusPut 'TeamFeatureSearchVisibility, teamFeatureStatusSearchVisibilityDeprecatedGet :: routes - :- FeatureStatusDeprecatedGet 'WithoutPaymentStatus 'TeamFeatureSearchVisibility, + :- FeatureStatusDeprecatedGet 'WithoutLockStatus 'TeamFeatureSearchVisibility, teamFeatureStatusSearchVisibilityDeprecatedPut :: routes :- FeatureStatusDeprecatedPut 'TeamFeatureSearchVisibility, @@ -632,13 +632,13 @@ data Api routes = Api :- FeatureStatusGet 'TeamFeatureValidateSAMLEmails, teamFeatureStatusValidateSAMLEmailsDeprecatedGet :: routes - :- FeatureStatusDeprecatedGet 'WithoutPaymentStatus 'TeamFeatureValidateSAMLEmails, + :- FeatureStatusDeprecatedGet 'WithoutLockStatus 'TeamFeatureValidateSAMLEmails, teamFeatureStatusDigitalSignaturesGet :: routes :- FeatureStatusGet 'TeamFeatureDigitalSignatures, teamFeatureStatusDigitalSignaturesDeprecatedGet :: routes - :- FeatureStatusDeprecatedGet 'WithoutPaymentStatus 'TeamFeatureDigitalSignatures, + :- FeatureStatusDeprecatedGet 'WithoutLockStatus 'TeamFeatureDigitalSignatures, teamFeatureStatusAppLockGet :: routes :- FeatureStatusGet 'TeamFeatureAppLock, @@ -668,34 +668,34 @@ data Api routes = Api :- AllFeatureConfigsGet, featureConfigLegalHoldGet :: routes - :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureLegalHold, + :- FeatureConfigGet 'WithoutLockStatus 'TeamFeatureLegalHold, featureConfigSSOGet :: routes - :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureSSO, + :- FeatureConfigGet 'WithoutLockStatus 'TeamFeatureSSO, featureConfigSearchVisibilityGet :: routes - :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureSearchVisibility, + :- FeatureConfigGet 'WithoutLockStatus 'TeamFeatureSearchVisibility, featureConfigValidateSAMLEmailsGet :: routes - :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureValidateSAMLEmails, + :- FeatureConfigGet 'WithoutLockStatus 'TeamFeatureValidateSAMLEmails, featureConfigDigitalSignaturesGet :: routes - :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureDigitalSignatures, + :- FeatureConfigGet 'WithoutLockStatus 'TeamFeatureDigitalSignatures, featureConfigAppLockGet :: routes - :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureAppLock, + :- FeatureConfigGet 'WithoutLockStatus 'TeamFeatureAppLock, featureConfigFileSharingGet :: routes - :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureFileSharing, + :- FeatureConfigGet 'WithoutLockStatus 'TeamFeatureFileSharing, featureConfigClassifiedDomainsGet :: routes - :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureClassifiedDomains, + :- FeatureConfigGet 'WithoutLockStatus 'TeamFeatureClassifiedDomains, featureConfigConferenceCallingGet :: routes - :- FeatureConfigGet 'WithoutPaymentStatus 'TeamFeatureConferenceCalling, + :- FeatureConfigGet 'WithoutLockStatus 'TeamFeatureConferenceCalling, featureConfigSelfDeletingMessagesGet :: routes - :- FeatureConfigGet 'WithPaymentStatus 'TeamFeatureSelfDeletingMessages + :- FeatureConfigGet 'WithLockStatus 'TeamFeatureSelfDeletingMessages } deriving (Generic) @@ -708,7 +708,7 @@ type FeatureStatusGet featureName = :> Capture "tid" TeamId :> "features" :> KnownTeamFeatureNameSymbol featureName - :> Get '[Servant.JSON] (TeamFeatureStatus 'WithPaymentStatus featureName) + :> Get '[Servant.JSON] (TeamFeatureStatus 'WithLockStatus featureName) type FeatureStatusPut featureName = Summary (AppendSymbol "Put config for " (KnownTeamFeatureNameSymbol featureName)) @@ -717,8 +717,8 @@ type FeatureStatusPut featureName = :> Capture "tid" TeamId :> "features" :> KnownTeamFeatureNameSymbol featureName - :> ReqBody '[Servant.JSON] (TeamFeatureStatus 'WithoutPaymentStatus featureName) - :> Put '[Servant.JSON] (TeamFeatureStatus 'WithoutPaymentStatus featureName) + :> ReqBody '[Servant.JSON] (TeamFeatureStatus 'WithoutLockStatus featureName) + :> Put '[Servant.JSON] (TeamFeatureStatus 'WithoutLockStatus featureName) -- | A type for a GET endpoint for a feature with a deprecated path type FeatureStatusDeprecatedGet ps featureName = @@ -738,8 +738,8 @@ type FeatureStatusDeprecatedPut featureName = :> Capture "tid" TeamId :> "features" :> DeprecatedFeatureName featureName - :> ReqBody '[Servant.JSON] (TeamFeatureStatus 'WithoutPaymentStatus featureName) - :> Put '[Servant.JSON] (TeamFeatureStatus 'WithoutPaymentStatus featureName) + :> ReqBody '[Servant.JSON] (TeamFeatureStatus 'WithoutLockStatus featureName) + :> Put '[Servant.JSON] (TeamFeatureStatus 'WithoutLockStatus featureName) type FeatureConfigGet ps featureName = Summary (AppendSymbol "Get feature config for feature " (KnownTeamFeatureNameSymbol featureName)) diff --git a/libs/wire-api/src/Wire/API/Routes/Public/LegalHold.hs b/libs/wire-api/src/Wire/API/Routes/Public/LegalHold.hs index 67dd19e0bc..6c3db162ae 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/LegalHold.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/LegalHold.hs @@ -52,9 +52,9 @@ type PublicAPI = type InternalAPI = "i" :> "teams" :> Capture "tid" TeamId :> "legalhold" - :> Get '[JSON] (TeamFeatureStatus 'WithPaymentStatus 'TeamFeatureLegalHold) + :> Get '[JSON] (TeamFeatureStatus 'WithLockStatus 'TeamFeatureLegalHold) :<|> "i" :> "teams" :> Capture "tid" TeamId :> "legalhold" - :> ReqBody '[JSON] (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureLegalHold) + :> ReqBody '[JSON] (TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureLegalHold) :> Put '[] NoContent swaggerDoc :: Swagger diff --git a/libs/wire-api/src/Wire/API/Swagger.hs b/libs/wire-api/src/Wire/API/Swagger.hs index 7ebdb1d9c8..6816085161 100644 --- a/libs/wire-api/src/Wire/API/Swagger.hs +++ b/libs/wire-api/src/Wire/API/Swagger.hs @@ -129,7 +129,7 @@ models = Team.Feature.modelTeamFeatureAppLockConfig, Team.Feature.modelTeamFeatureClassifiedDomainsConfig, Team.Feature.modelTeamFeatureSelfDeletingMessagesConfig, - Team.Feature.modelPaymentStatus, + Team.Feature.modelLockStatus, Team.Invitation.modelTeamInvitation, Team.Invitation.modelTeamInvitationList, Team.Invitation.modelTeamInvitationRequest, diff --git a/libs/wire-api/src/Wire/API/Team/Feature.hs b/libs/wire-api/src/Wire/API/Team/Feature.hs index 9997ae8042..32b4f5f505 100644 --- a/libs/wire-api/src/Wire/API/Team/Feature.hs +++ b/libs/wire-api/src/Wire/API/Team/Feature.hs @@ -30,12 +30,12 @@ module Wire.API.Team.Feature KnownTeamFeatureName (..), TeamFeatureStatusNoConfig (..), TeamFeatureStatusWithConfig (..), - TeamFeatureStatusWithConfigAndPaymentStatus (..), + TeamFeatureStatusWithConfigAndLockStatus (..), HasDeprecatedFeatureName (..), AllFeatureConfigs (..), - PaymentStatus (..), - PaymentStatusValue (..), - IncludePaymentStatus (..), + LockStatus (..), + LockStatusValue (..), + IncludeLockStatus (..), defaultAppLockStatus, defaultClassifiedDomains, defaultSelfDeletingMessagesStatus, @@ -48,9 +48,9 @@ module Wire.API.Team.Feature modelTeamFeatureAppLockConfig, modelTeamFeatureClassifiedDomainsConfig, modelTeamFeatureSelfDeletingMessagesConfig, - modelTeamFeatureStatusWithConfigAndPaymentStatus, + modelTeamFeatureStatusWithConfigAndLockStatus, modelForTeamFeature, - modelPaymentStatus, + modelLockStatus, ) where @@ -291,9 +291,9 @@ instance Cass.Cql TeamFeatureStatusValue where ---------------------------------------------------------------------- -- TeamFeatureStatus -data IncludePaymentStatus = WithPaymentStatus | WithoutPaymentStatus +data IncludeLockStatus = WithLockStatus | WithoutLockStatus -type family TeamFeatureStatus (ps :: IncludePaymentStatus) (a :: TeamFeatureName) :: * where +type family TeamFeatureStatus (ps :: IncludeLockStatus) (a :: TeamFeatureName) :: * where TeamFeatureStatus _ 'TeamFeatureLegalHold = TeamFeatureStatusNoConfig TeamFeatureStatus _ 'TeamFeatureSSO = TeamFeatureStatusNoConfig TeamFeatureStatus _ 'TeamFeatureSearchVisibility = TeamFeatureStatusNoConfig @@ -303,10 +303,10 @@ type family TeamFeatureStatus (ps :: IncludePaymentStatus) (a :: TeamFeatureName TeamFeatureStatus _ 'TeamFeatureFileSharing = TeamFeatureStatusNoConfig TeamFeatureStatus _ 'TeamFeatureClassifiedDomains = TeamFeatureStatusWithConfig TeamFeatureClassifiedDomainsConfig TeamFeatureStatus _ 'TeamFeatureConferenceCalling = TeamFeatureStatusNoConfig - TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages = TeamFeatureStatusWithConfig TeamFeatureSelfDeletingMessagesConfig - TeamFeatureStatus 'WithPaymentStatus 'TeamFeatureSelfDeletingMessages = TeamFeatureStatusWithConfigAndPaymentStatus TeamFeatureSelfDeletingMessagesConfig + TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureSelfDeletingMessages = TeamFeatureStatusWithConfig TeamFeatureSelfDeletingMessagesConfig + TeamFeatureStatus 'WithLockStatus 'TeamFeatureSelfDeletingMessages = TeamFeatureStatusWithConfigAndLockStatus TeamFeatureSelfDeletingMessagesConfig -type FeatureHasNoConfig (ps :: IncludePaymentStatus) (a :: TeamFeatureName) = (TeamFeatureStatus ps a ~ TeamFeatureStatusNoConfig) :: Constraint +type FeatureHasNoConfig (ps :: IncludeLockStatus) (a :: TeamFeatureName) = (TeamFeatureStatus ps a ~ TeamFeatureStatusNoConfig) :: Constraint -- if you add a new constructor here, don't forget to add it to the swagger (1.2) docs in "Wire.API.Swagger"! modelForTeamFeature :: TeamFeatureName -> Doc.Model @@ -371,31 +371,31 @@ instance ToSchema cfg => ToSchema (TeamFeatureStatusWithConfig cfg) where <$> tfwcStatus .= field "status" schema <*> tfwcConfig .= field "config" schema -data TeamFeatureStatusWithConfigAndPaymentStatus (cfg :: *) = TeamFeatureStatusWithConfigAndPaymentStatus +data TeamFeatureStatusWithConfigAndLockStatus (cfg :: *) = TeamFeatureStatusWithConfigAndLockStatus { tfwcapsStatus :: TeamFeatureStatusValue, tfwcapsConfig :: cfg, - tfwcapsPaymentStatus :: PaymentStatusValue + tfwcapsLockStatus :: LockStatusValue } deriving stock (Eq, Show, Generic, Typeable) - deriving (ToJSON, FromJSON, S.ToSchema) via (Schema (TeamFeatureStatusWithConfigAndPaymentStatus cfg)) + deriving (ToJSON, FromJSON, S.ToSchema) via (Schema (TeamFeatureStatusWithConfigAndLockStatus cfg)) -instance Arbitrary cfg => Arbitrary (TeamFeatureStatusWithConfigAndPaymentStatus cfg) where - arbitrary = TeamFeatureStatusWithConfigAndPaymentStatus <$> arbitrary <*> arbitrary <*> arbitrary +instance Arbitrary cfg => Arbitrary (TeamFeatureStatusWithConfigAndLockStatus cfg) where + arbitrary = TeamFeatureStatusWithConfigAndLockStatus <$> arbitrary <*> arbitrary <*> arbitrary -modelTeamFeatureStatusWithConfigAndPaymentStatus :: TeamFeatureName -> Doc.Model -> Doc.Model -modelTeamFeatureStatusWithConfigAndPaymentStatus name cfgModel = Doc.defineModel (cs $ show name) $ do +modelTeamFeatureStatusWithConfigAndLockStatus :: TeamFeatureName -> Doc.Model -> Doc.Model +modelTeamFeatureStatusWithConfigAndLockStatus name cfgModel = Doc.defineModel (cs $ show name) $ do Doc.description $ "Status and config of " <> cs (show name) Doc.property "status" typeTeamFeatureStatusValue $ Doc.description "status" Doc.property "config" (Doc.ref cfgModel) $ Doc.description "config" - Doc.property "paymentStatus" typePaymentStatusValue $ Doc.description "config" + Doc.property "lockStatus" typeLockStatusValue $ Doc.description "config" -instance ToSchema cfg => ToSchema (TeamFeatureStatusWithConfigAndPaymentStatus cfg) where +instance ToSchema cfg => ToSchema (TeamFeatureStatusWithConfigAndLockStatus cfg) where schema = - object "TeamFeatureStatusWithConfigAndPaymentStatus" $ - TeamFeatureStatusWithConfigAndPaymentStatus + object "TeamFeatureStatusWithConfigAndLockStatus" $ + TeamFeatureStatusWithConfigAndLockStatus <$> tfwcapsStatus .= field "status" schema <*> tfwcapsConfig .= field "config" schema - <*> tfwcapsPaymentStatus .= field "paymentStatus" schema + <*> tfwcapsLockStatus .= field "lockStatus" schema ---------------------------------------------------------------------- -- TeamFeatureClassifiedDomainsConfig @@ -485,82 +485,82 @@ modelTeamFeatureSelfDeletingMessagesConfig = Doc.defineModel "TeamFeatureSelfDeletingMessagesConfig" $ do Doc.property "enforcedTimeoutSeconds" Doc.int32' $ Doc.description "optional; default: `0` (no enforcement)" -defaultSelfDeletingMessagesStatus :: TeamFeatureStatusWithConfigAndPaymentStatus TeamFeatureSelfDeletingMessagesConfig +defaultSelfDeletingMessagesStatus :: TeamFeatureStatusWithConfigAndLockStatus TeamFeatureSelfDeletingMessagesConfig defaultSelfDeletingMessagesStatus = - TeamFeatureStatusWithConfigAndPaymentStatus + TeamFeatureStatusWithConfigAndLockStatus TeamFeatureEnabled (TeamFeatureSelfDeletingMessagesConfig 0) - PaymentLocked + Locked ---------------------------------------------------------------------- --- PaymentStatus +-- LockStatus -instance FromHttpApiData PaymentStatusValue where - parseUrlPiece = maybeToEither "Invalid payment status" . fromByteString . cs +instance FromHttpApiData LockStatusValue where + parseUrlPiece = maybeToEither "Invalid lock status" . fromByteString . cs -data PaymentStatusValue = PaymentLocked | PaymentUnlocked +data LockStatusValue = Locked | Unlocked deriving stock (Eq, Show, Generic) - deriving (Arbitrary) via (GenericUniform PaymentStatusValue) - deriving (ToJSON, FromJSON, S.ToSchema) via (Schema PaymentStatusValue) + deriving (Arbitrary) via (GenericUniform LockStatusValue) + deriving (ToJSON, FromJSON, S.ToSchema) via (Schema LockStatusValue) -newtype PaymentStatus = PaymentStatus - { paymentStatus :: PaymentStatusValue +newtype LockStatus = LockStatus + { lockStatus :: LockStatusValue } deriving stock (Eq, Show, Generic) - deriving (FromJSON, ToJSON, S.ToSchema) via (Schema PaymentStatus) - deriving (Arbitrary) via (GenericUniform PaymentStatus) + deriving (FromJSON, ToJSON, S.ToSchema) via (Schema LockStatus) + deriving (Arbitrary) via (GenericUniform LockStatus) -instance ToSchema PaymentStatus where +instance ToSchema LockStatus where schema = - object "PaymentStatus" $ - PaymentStatus - <$> paymentStatus .= field "paymentStatus" schema + object "LockStatus" $ + LockStatus + <$> lockStatus .= field "lockStatus" schema -modelPaymentStatus :: Doc.Model -modelPaymentStatus = - Doc.defineModel "PaymentStatus" $ do - Doc.property "paymentStatus" typePaymentStatusValue $ Doc.description "" +modelLockStatus :: Doc.Model +modelLockStatus = + Doc.defineModel "LockStatus" $ do + Doc.property "lockStatus" typeLockStatusValue $ Doc.description "" -typePaymentStatusValue :: Doc.DataType -typePaymentStatusValue = +typeLockStatusValue :: Doc.DataType +typeLockStatusValue = Doc.string $ Doc.enum [ "locked", "unlocked" ] -instance ToSchema PaymentStatusValue where +instance ToSchema LockStatusValue where schema = - enum @Text "PaymentStatusValue" $ + enum @Text "LockStatusValue" $ mconcat - [ element "locked" PaymentLocked, - element "unlocked" PaymentUnlocked + [ element "locked" Locked, + element "unlocked" Unlocked ] -instance ToByteString PaymentStatusValue where - builder PaymentLocked = "locked" - builder PaymentUnlocked = "unlocked" +instance ToByteString LockStatusValue where + builder Locked = "locked" + builder Unlocked = "unlocked" -instance FromByteString PaymentStatusValue where +instance FromByteString LockStatusValue where parser = Parser.takeByteString >>= \b -> case T.decodeUtf8' b of - Right "locked" -> pure PaymentLocked - Right "unlocked" -> pure PaymentUnlocked - Right t -> fail $ "Invalid PaymentStatusValue: " <> T.unpack t - Left e -> fail $ "Invalid PaymentStatusValue: " <> show e + Right "locked" -> pure Locked + Right "unlocked" -> pure Unlocked + Right t -> fail $ "Invalid LockStatusValue: " <> T.unpack t + Left e -> fail $ "Invalid LockStatusValue: " <> show e -instance Cass.Cql PaymentStatusValue where +instance Cass.Cql LockStatusValue where ctype = Cass.Tagged Cass.IntColumn fromCql (Cass.CqlInt n) = case n of - 0 -> pure PaymentLocked - 1 -> pure PaymentUnlocked - _ -> Left "fromCql: Invalid PaymentStatusValue" - fromCql _ = Left "fromCql: PaymentStatusValue: CqlInt expected" + 0 -> pure Locked + 1 -> pure Unlocked + _ -> Left "fromCql: Invalid LockStatusValue" + fromCql _ = Left "fromCql: LockStatusValue: CqlInt expected" - toCql PaymentLocked = Cass.CqlInt 0 - toCql PaymentUnlocked = Cass.CqlInt 1 + toCql Locked = Cass.CqlInt 0 + toCql Unlocked = Cass.CqlInt 1 ---------------------------------------------------------------------- -- internal diff --git a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generator.hs b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generator.hs index 3480c55814..e4daf3da24 100644 --- a/libs/wire-api/test/golden/Test/Wire/API/Golden/Generator.hs +++ b/libs/wire-api/test/golden/Test/Wire/API/Golden/Generator.hs @@ -328,8 +328,8 @@ generateTestModule = do generateBindingModule @Team.TeamDeleteData "team" ref generateBindingModule @Team.Conversation.TeamConversation "team" ref generateBindingModule @Team.Conversation.TeamConversationList "team" ref - generateBindingModule @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureLegalHold) "team" ref - generateBindingModule @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureAppLock) "team" ref + generateBindingModule @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutLockStatus 'Team.Feature.TeamFeatureLegalHold) "team" ref + generateBindingModule @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutLockStatus 'Team.Feature.TeamFeatureAppLock) "team" ref generateBindingModule @Team.Feature.TeamFeatureStatusValue "team" ref generateBindingModule @Team.Invitation.InvitationRequest "team" ref generateBindingModule @Team.Invitation.Invitation "team" ref diff --git a/libs/wire-api/test/unit/Test/Wire/API/Roundtrip/Aeson.hs b/libs/wire-api/test/unit/Test/Wire/API/Roundtrip/Aeson.hs index 220c31e50c..0550101690 100644 --- a/libs/wire-api/test/unit/Test/Wire/API/Roundtrip/Aeson.hs +++ b/libs/wire-api/test/unit/Test/Wire/API/Roundtrip/Aeson.hs @@ -195,21 +195,21 @@ tests = testRoundTrip @Team.TeamDeleteData, testRoundTrip @Team.Conversation.TeamConversation, testRoundTrip @Team.Conversation.TeamConversationList, - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureLegalHold), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureSSO), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureSearchVisibility), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureValidateSAMLEmails), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureDigitalSignatures), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureAppLock), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureFileSharing), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureClassifiedDomains), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureConferenceCalling), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureSelfDeletingMessages), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithPaymentStatus 'Team.Feature.TeamFeatureSelfDeletingMessages), - testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutPaymentStatus 'Team.Feature.TeamFeatureSelfDeletingMessages), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutLockStatus 'Team.Feature.TeamFeatureLegalHold), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutLockStatus 'Team.Feature.TeamFeatureSSO), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutLockStatus 'Team.Feature.TeamFeatureSearchVisibility), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutLockStatus 'Team.Feature.TeamFeatureValidateSAMLEmails), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutLockStatus 'Team.Feature.TeamFeatureDigitalSignatures), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutLockStatus 'Team.Feature.TeamFeatureAppLock), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutLockStatus 'Team.Feature.TeamFeatureFileSharing), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutLockStatus 'Team.Feature.TeamFeatureClassifiedDomains), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutLockStatus 'Team.Feature.TeamFeatureConferenceCalling), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutLockStatus 'Team.Feature.TeamFeatureSelfDeletingMessages), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithLockStatus 'Team.Feature.TeamFeatureSelfDeletingMessages), + testRoundTrip @(Team.Feature.TeamFeatureStatus 'Team.Feature.WithoutLockStatus 'Team.Feature.TeamFeatureSelfDeletingMessages), testRoundTrip @Team.Feature.TeamFeatureStatusValue, - testRoundTrip @Team.Feature.PaymentStatusValue, - testRoundTrip @Team.Feature.PaymentStatus, + testRoundTrip @Team.Feature.LockStatusValue, + testRoundTrip @Team.Feature.LockStatus, testRoundTrip @Team.Invitation.InvitationRequest, testRoundTrip @Team.Invitation.Invitation, testRoundTrip @Team.Invitation.InvitationList, diff --git a/services/brig/src/Brig/IO/Intra.hs b/services/brig/src/Brig/IO/Intra.hs index f7192d3c36..3a906829fe 100644 --- a/services/brig/src/Brig/IO/Intra.hs +++ b/services/brig/src/Brig/IO/Intra.hs @@ -121,7 +121,7 @@ import Wire.API.Federation.API.Brig import Wire.API.Federation.Client import Wire.API.Federation.Error (federationNotImplemented) import Wire.API.Message (UserClients) -import Wire.API.Team.Feature (IncludePaymentStatus (..), TeamFeatureName (..), TeamFeatureStatus) +import Wire.API.Team.Feature (IncludeLockStatus (..), TeamFeatureName (..), TeamFeatureStatus) import Wire.API.Team.LegalHold (LegalholdProtectee) ----------------------------------------------------------------------------- @@ -968,7 +968,7 @@ getTeamName tid = do . expect2xx -- | Calls 'Galley.API.getTeamFeatureStatusH'. -getTeamLegalHoldStatus :: TeamId -> AppIO (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureLegalHold) +getTeamLegalHoldStatus :: TeamId -> AppIO (TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureLegalHold) getTeamLegalHoldStatus tid = do debug $ remote "galley" . msg (val "Get legalhold settings") galleyRequest GET req >>= decodeBody "galley" diff --git a/services/brig/src/Brig/Options.hs b/services/brig/src/Brig/Options.hs index cd8d5f8603..874fd3a4a1 100644 --- a/services/brig/src/Brig/Options.hs +++ b/services/brig/src/Brig/Options.hs @@ -508,8 +508,8 @@ data Settings = Settings -- they are grandfathered), and feature-specific extra data (eg., TLL for self-deleting -- messages). For now, we have something quick & simple. data AccountFeatureConfigs = AccountFeatureConfigs - { afcConferenceCallingDefNew :: !(ApiFT.TeamFeatureStatus 'ApiFT.WithoutPaymentStatus 'ApiFT.TeamFeatureConferenceCalling), - afcConferenceCallingDefNull :: !(ApiFT.TeamFeatureStatus 'ApiFT.WithoutPaymentStatus 'ApiFT.TeamFeatureConferenceCalling) + { afcConferenceCallingDefNew :: !(ApiFT.TeamFeatureStatus 'ApiFT.WithoutLockStatus 'ApiFT.TeamFeatureConferenceCalling), + afcConferenceCallingDefNull :: !(ApiFT.TeamFeatureStatus 'ApiFT.WithoutLockStatus 'ApiFT.TeamFeatureConferenceCalling) } deriving (Show, Eq, Generic) deriving (Arbitrary) via (GenericUniform AccountFeatureConfigs) diff --git a/services/galley/galley.cabal b/services/galley/galley.cabal index d239a0aa92..d6247bd175 100644 --- a/services/galley/galley.cabal +++ b/services/galley/galley.cabal @@ -437,7 +437,7 @@ executable galley-schema V52_FeatureConferenceCalling V53_AddRemoteConvStatus V54_TeamFeatureSelfDeletingMessages - V55_SelfDeletingMessagesPaymentStatus + V55_SelfDeletingMessagesLockStatus Paths_galley hs-source-dirs: schema/src diff --git a/services/galley/schema/src/Main.hs b/services/galley/schema/src/Main.hs index 0184638f75..e6bed34716 100644 --- a/services/galley/schema/src/Main.hs +++ b/services/galley/schema/src/Main.hs @@ -57,7 +57,7 @@ import qualified V51_FeatureFileSharing import qualified V52_FeatureConferenceCalling import qualified V53_AddRemoteConvStatus import qualified V54_TeamFeatureSelfDeletingMessages -import qualified V55_SelfDeletingMessagesPaymentStatus +import qualified V55_SelfDeletingMessagesLockStatus main :: IO () main = do @@ -101,7 +101,7 @@ main = do V52_FeatureConferenceCalling.migration, V53_AddRemoteConvStatus.migration, V54_TeamFeatureSelfDeletingMessages.migration, - V55_SelfDeletingMessagesPaymentStatus.migration + V55_SelfDeletingMessagesLockStatus.migration -- When adding migrations here, don't forget to update -- 'schemaVersion' in Galley.Cassandra -- (see also docs/developer/cassandra-interaction.md) diff --git a/services/galley/schema/src/V55_SelfDeletingMessagesPaymentStatus.hs b/services/galley/schema/src/V55_SelfDeletingMessagesLockStatus.hs similarity index 91% rename from services/galley/schema/src/V55_SelfDeletingMessagesPaymentStatus.hs rename to services/galley/schema/src/V55_SelfDeletingMessagesLockStatus.hs index fa7ed93e8b..58e6169069 100644 --- a/services/galley/schema/src/V55_SelfDeletingMessagesPaymentStatus.hs +++ b/services/galley/schema/src/V55_SelfDeletingMessagesLockStatus.hs @@ -15,7 +15,7 @@ -- You should have received a copy of the GNU Affero General Public License along -- with this program. If not, see . -module V55_SelfDeletingMessagesPaymentStatus +module V55_SelfDeletingMessagesLockStatus ( migration, ) where @@ -28,6 +28,6 @@ migration :: Migration migration = Migration 55 "Add payment status config for self deleting messages team feature" $ do schema' [r| ALTER TABLE team_features ADD ( - self_deleting_messages_payment_status int + self_deleting_messages_lock_status int ) |] diff --git a/services/galley/src/Galley/API/Error.hs b/services/galley/src/Galley/API/Error.hs index 6c1b604dfd..2f49164b8b 100644 --- a/services/galley/src/Galley/API/Error.hs +++ b/services/galley/src/Galley/API/Error.hs @@ -161,14 +161,14 @@ data TeamFeatureError | LegalHoldFeatureFlagNotEnabled | LegalHoldWhitelistedOnly | DisableSsoNotImplemented - | PaymentStatusLocked + | FeatureLocked instance APIError TeamFeatureError where toWai AppLockinactivityTimeoutTooLow = inactivityTimeoutTooLow toWai LegalHoldFeatureFlagNotEnabled = legalHoldFeatureFlagNotEnabled toWai LegalHoldWhitelistedOnly = legalHoldWhitelistedOnly toWai DisableSsoNotImplemented = disableSsoNotImplemented - toWai PaymentStatusLocked = setTeamFeatureConfigPaymentStatusLocked + toWai FeatureLocked = setTeamFeatureConfigFeatureLocked data TeamNotificationError = InvalidTeamNotificationId @@ -460,8 +460,8 @@ noLegalHoldDeviceAllocated = mkError status404 "legalhold-no-device-allocated" " legalHoldCouldNotBlockConnections :: Error legalHoldCouldNotBlockConnections = mkError status500 "legalhold-internal" "legal hold service: could not block connections when resolving policy conflicts." -setTeamFeatureConfigPaymentStatusLocked :: Error -setTeamFeatureConfigPaymentStatusLocked = mkError status409 "payment-status-locked" "feature config cannot be updated when the payment status is locked" +setTeamFeatureConfigFeatureLocked :: Error +setTeamFeatureConfigFeatureLocked = mkError status409 "feature-locked" "feature config cannot be updated (eg., because it is configured to be locked, or because you need to upgrade your plan)" disableSsoNotImplemented :: Error disableSsoNotImplemented = diff --git a/services/galley/src/Galley/API/Internal.hs b/services/galley/src/Galley/API/Internal.hs index 1b4e930c64..5d870c0ddd 100644 --- a/services/galley/src/Galley/API/Internal.hs +++ b/services/galley/src/Galley/API/Internal.hs @@ -52,7 +52,7 @@ import Galley.API.Util import Galley.App import Galley.Cassandra.Paging import qualified Galley.Data.Conversation as Data -import Galley.Data.TeamFeatures (MaybeHasPaymentStatusCol) +import Galley.Data.TeamFeatures (MaybeHasLockStatusCol) import Galley.Effects import Galley.Effects.ClientStore import Galley.Effects.ConversationStore @@ -122,82 +122,82 @@ data InternalApi routes = InternalApi -- Viewing the config for features should be allowed for any admin. iTeamFeatureStatusSSOGet :: routes - :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureSSO, + :- IFeatureStatusGet 'Public.WithoutLockStatus 'Public.TeamFeatureSSO, iTeamFeatureStatusSSOPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureSSO, iTeamFeatureStatusLegalHoldGet :: routes - :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureLegalHold, + :- IFeatureStatusGet 'Public.WithoutLockStatus 'Public.TeamFeatureLegalHold, iTeamFeatureStatusLegalHoldPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureLegalHold, iTeamFeatureStatusSearchVisibilityGet :: routes - :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureSearchVisibility, + :- IFeatureStatusGet 'Public.WithoutLockStatus 'Public.TeamFeatureSearchVisibility, iTeamFeatureStatusSearchVisibilityPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureSearchVisibility, iTeamFeatureStatusSearchVisibilityDeprecatedGet :: routes - :- IFeatureStatusDeprecatedGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureSearchVisibility, + :- IFeatureStatusDeprecatedGet 'Public.WithoutLockStatus 'Public.TeamFeatureSearchVisibility, iTeamFeatureStatusSearchVisibilityDeprecatedPut :: routes :- IFeatureStatusDeprecatedPut 'Public.TeamFeatureSearchVisibility, iTeamFeatureStatusValidateSAMLEmailsGet :: routes - :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureValidateSAMLEmails, + :- IFeatureStatusGet 'Public.WithoutLockStatus 'Public.TeamFeatureValidateSAMLEmails, iTeamFeatureStatusValidateSAMLEmailsPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureValidateSAMLEmails, iTeamFeatureStatusValidateSAMLEmailsDeprecatedGet :: routes - :- IFeatureStatusDeprecatedGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureValidateSAMLEmails, + :- IFeatureStatusDeprecatedGet 'Public.WithoutLockStatus 'Public.TeamFeatureValidateSAMLEmails, iTeamFeatureStatusValidateSAMLEmailsDeprecatedPut :: routes :- IFeatureStatusDeprecatedPut 'Public.TeamFeatureValidateSAMLEmails, iTeamFeatureStatusDigitalSignaturesGet :: routes - :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureDigitalSignatures, + :- IFeatureStatusGet 'Public.WithoutLockStatus 'Public.TeamFeatureDigitalSignatures, iTeamFeatureStatusDigitalSignaturesPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureDigitalSignatures, iTeamFeatureStatusDigitalSignaturesDeprecatedGet :: routes - :- IFeatureStatusDeprecatedGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureDigitalSignatures, + :- IFeatureStatusDeprecatedGet 'Public.WithoutLockStatus 'Public.TeamFeatureDigitalSignatures, iTeamFeatureStatusDigitalSignaturesDeprecatedPut :: routes :- IFeatureStatusDeprecatedPut 'Public.TeamFeatureDigitalSignatures, iTeamFeatureStatusAppLockGet :: routes - :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureAppLock, + :- IFeatureStatusGet 'Public.WithoutLockStatus 'Public.TeamFeatureAppLock, iTeamFeatureStatusAppLockPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureAppLock, iTeamFeatureStatusFileSharingGet :: routes - :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureFileSharing, + :- IFeatureStatusGet 'Public.WithoutLockStatus 'Public.TeamFeatureFileSharing, iTeamFeatureStatusFileSharingPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureFileSharing, iTeamFeatureStatusClassifiedDomainsGet :: routes - :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureClassifiedDomains, + :- IFeatureStatusGet 'Public.WithoutLockStatus 'Public.TeamFeatureClassifiedDomains, iTeamFeatureStatusConferenceCallingPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureConferenceCalling, iTeamFeatureStatusConferenceCallingGet :: routes - :- IFeatureStatusGet 'Public.WithoutPaymentStatus 'Public.TeamFeatureConferenceCalling, + :- IFeatureStatusGet 'Public.WithoutLockStatus 'Public.TeamFeatureConferenceCalling, iTeamFeatureStatusSelfDeletingMessagesPut :: routes :- IFeatureStatusPut 'Public.TeamFeatureSelfDeletingMessages, iTeamFeatureStatusSelfDeletingMessagesGet :: routes - :- IFeatureStatusGet 'Public.WithPaymentStatus 'Public.TeamFeatureSelfDeletingMessages, - iTeamFeaturePaymentStatusSelfDeletingMessagesPut :: + :- IFeatureStatusGet 'Public.WithLockStatus 'Public.TeamFeatureSelfDeletingMessages, + iTeamFeatureLockStatusSelfDeletingMessagesPut :: routes - :- IFeatureStatusPaymentStatusPut 'Public.TeamFeatureSelfDeletingMessages, + :- IFeatureStatusLockStatusPut 'Public.TeamFeatureSelfDeletingMessages, -- This endpoint can lead to the following events being sent: -- - MemberLeave event to members for all conversations the user was in iDeleteUser :: @@ -236,14 +236,14 @@ data InternalApi routes = InternalApi type ServantAPI = ToServantApi InternalApi -type IFeatureStatusGet paymentStatus featureName = +type IFeatureStatusGet lockStatus featureName = Summary (AppendSymbol "Get config for " (Public.KnownTeamFeatureNameSymbol featureName)) :> "i" :> "teams" :> Capture "tid" TeamId :> "features" :> Public.KnownTeamFeatureNameSymbol featureName - :> Get '[Servant.JSON] (Public.TeamFeatureStatus paymentStatus featureName) + :> Get '[Servant.JSON] (Public.TeamFeatureStatus lockStatus featureName) type IFeatureStatusPut featureName = Summary (AppendSymbol "Put config for " (Public.KnownTeamFeatureNameSymbol featureName)) @@ -252,28 +252,28 @@ type IFeatureStatusPut featureName = :> Capture "tid" TeamId :> "features" :> Public.KnownTeamFeatureNameSymbol featureName - :> ReqBody '[Servant.JSON] (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus featureName) - :> Put '[Servant.JSON] (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus featureName) + :> ReqBody '[Servant.JSON] (Public.TeamFeatureStatus 'Public.WithoutLockStatus featureName) + :> Put '[Servant.JSON] (Public.TeamFeatureStatus 'Public.WithoutLockStatus featureName) -type IFeatureStatusPaymentStatusPut featureName = - Summary (AppendSymbol "(Un-)lock payment for " (Public.KnownTeamFeatureNameSymbol featureName)) +type IFeatureStatusLockStatusPut featureName = + Summary (AppendSymbol "(Un-)lock " (Public.KnownTeamFeatureNameSymbol featureName)) :> "i" :> "teams" :> Capture "tid" TeamId :> "features" :> Public.KnownTeamFeatureNameSymbol featureName - :> Capture "paymentStatus" Public.PaymentStatusValue - :> Put '[Servant.JSON] Public.PaymentStatus + :> Capture "lockStatus" Public.LockStatusValue + :> Put '[Servant.JSON] Public.LockStatus -- | A type for a GET endpoint for a feature with a deprecated path -type IFeatureStatusDeprecatedGet paymentStatus featureName = +type IFeatureStatusDeprecatedGet lockStatus featureName = Summary (AppendSymbol "[deprecated] Get config for " (Public.KnownTeamFeatureNameSymbol featureName)) :> "i" :> "teams" :> Capture "tid" TeamId :> "features" :> Public.DeprecatedFeatureName featureName - :> Get '[Servant.JSON] (Public.TeamFeatureStatus paymentStatus featureName) + :> Get '[Servant.JSON] (Public.TeamFeatureStatus lockStatus featureName) -- | A type for a PUT endpoint for a feature with a deprecated path type IFeatureStatusDeprecatedPut featureName = @@ -283,8 +283,8 @@ type IFeatureStatusDeprecatedPut featureName = :> Capture "tid" TeamId :> "features" :> Public.DeprecatedFeatureName featureName - :> ReqBody '[Servant.JSON] (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus featureName) - :> Put '[Servant.JSON] (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus featureName) + :> ReqBody '[Servant.JSON] (Public.TeamFeatureStatus 'Public.WithoutLockStatus featureName) + :> Put '[Servant.JSON] (Public.TeamFeatureStatus 'Public.WithoutLockStatus featureName) servantSitemap :: ServerT ServantAPI (Sem GalleyEffects) servantSitemap = @@ -292,32 +292,32 @@ servantSitemap = InternalApi { iStatusGet = pure NoContent, iStatusHead = pure NoContent, - iTeamFeatureStatusSSOGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO Features.getSSOStatusInternal, + iTeamFeatureStatusSSOGet = iGetTeamFeature @'Public.WithoutLockStatus @'Public.TeamFeatureSSO Features.getSSOStatusInternal, iTeamFeatureStatusSSOPut = iPutTeamFeature @'Public.TeamFeatureSSO Features.setSSOStatusInternal, - iTeamFeatureStatusLegalHoldGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold Features.getLegalholdStatusInternal, + iTeamFeatureStatusLegalHoldGet = iGetTeamFeature @'Public.WithoutLockStatus @'Public.TeamFeatureLegalHold Features.getLegalholdStatusInternal, iTeamFeatureStatusLegalHoldPut = iPutTeamFeature @'Public.TeamFeatureLegalHold (Features.setLegalholdStatusInternal @InternalPaging), - iTeamFeatureStatusSearchVisibilityGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal, + iTeamFeatureStatusSearchVisibilityGet = iGetTeamFeature @'Public.WithoutLockStatus @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal, iTeamFeatureStatusSearchVisibilityPut = iPutTeamFeature @'Public.TeamFeatureLegalHold Features.setTeamSearchVisibilityAvailableInternal, - iTeamFeatureStatusSearchVisibilityDeprecatedGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal, + iTeamFeatureStatusSearchVisibilityDeprecatedGet = iGetTeamFeature @'Public.WithoutLockStatus @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal, iTeamFeatureStatusSearchVisibilityDeprecatedPut = iPutTeamFeature @'Public.TeamFeatureLegalHold Features.setTeamSearchVisibilityAvailableInternal, - iTeamFeatureStatusValidateSAMLEmailsGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal, + iTeamFeatureStatusValidateSAMLEmailsGet = iGetTeamFeature @'Public.WithoutLockStatus @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal, iTeamFeatureStatusValidateSAMLEmailsPut = iPutTeamFeature @'Public.TeamFeatureValidateSAMLEmails Features.setValidateSAMLEmailsInternal, - iTeamFeatureStatusValidateSAMLEmailsDeprecatedGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal, + iTeamFeatureStatusValidateSAMLEmailsDeprecatedGet = iGetTeamFeature @'Public.WithoutLockStatus @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal, iTeamFeatureStatusValidateSAMLEmailsDeprecatedPut = iPutTeamFeature @'Public.TeamFeatureValidateSAMLEmails Features.setValidateSAMLEmailsInternal, - iTeamFeatureStatusDigitalSignaturesGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal, + iTeamFeatureStatusDigitalSignaturesGet = iGetTeamFeature @'Public.WithoutLockStatus @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal, iTeamFeatureStatusDigitalSignaturesPut = iPutTeamFeature @'Public.TeamFeatureDigitalSignatures Features.setDigitalSignaturesInternal, - iTeamFeatureStatusDigitalSignaturesDeprecatedGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal, + iTeamFeatureStatusDigitalSignaturesDeprecatedGet = iGetTeamFeature @'Public.WithoutLockStatus @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal, iTeamFeatureStatusDigitalSignaturesDeprecatedPut = iPutTeamFeature @'Public.TeamFeatureDigitalSignatures Features.setDigitalSignaturesInternal, - iTeamFeatureStatusAppLockGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureAppLock Features.getAppLockInternal, + iTeamFeatureStatusAppLockGet = iGetTeamFeature @'Public.WithoutLockStatus @'Public.TeamFeatureAppLock Features.getAppLockInternal, iTeamFeatureStatusAppLockPut = iPutTeamFeature @'Public.TeamFeatureAppLock Features.setAppLockInternal, - iTeamFeatureStatusFileSharingGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureFileSharing Features.getFileSharingInternal, + iTeamFeatureStatusFileSharingGet = iGetTeamFeature @'Public.WithoutLockStatus @'Public.TeamFeatureFileSharing Features.getFileSharingInternal, iTeamFeatureStatusFileSharingPut = iPutTeamFeature @'Public.TeamFeatureFileSharing Features.setFileSharingInternal, - iTeamFeatureStatusClassifiedDomainsGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureClassifiedDomains Features.getClassifiedDomainsInternal, + iTeamFeatureStatusClassifiedDomainsGet = iGetTeamFeature @'Public.WithoutLockStatus @'Public.TeamFeatureClassifiedDomains Features.getClassifiedDomainsInternal, iTeamFeatureStatusConferenceCallingPut = iPutTeamFeature @'Public.TeamFeatureConferenceCalling Features.setConferenceCallingInternal, - iTeamFeatureStatusConferenceCallingGet = iGetTeamFeature @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling Features.getConferenceCallingInternal, + iTeamFeatureStatusConferenceCallingGet = iGetTeamFeature @'Public.WithoutLockStatus @'Public.TeamFeatureConferenceCalling Features.getConferenceCallingInternal, iTeamFeatureStatusSelfDeletingMessagesPut = iPutTeamFeature @'Public.TeamFeatureSelfDeletingMessages Features.setSelfDeletingMessagesInternal, - iTeamFeatureStatusSelfDeletingMessagesGet = iGetTeamFeature @'Public.WithPaymentStatus @'Public.TeamFeatureSelfDeletingMessages Features.getSelfDeletingMessagesInternal, - iTeamFeaturePaymentStatusSelfDeletingMessagesPut = Features.setPaymentStatus @'Public.TeamFeatureSelfDeletingMessages, + iTeamFeatureStatusSelfDeletingMessagesGet = iGetTeamFeature @'Public.WithLockStatus @'Public.TeamFeatureSelfDeletingMessages Features.getSelfDeletingMessagesInternal, + iTeamFeatureLockStatusSelfDeletingMessagesPut = Features.setLockStatus @'Public.TeamFeatureSelfDeletingMessages, iDeleteUser = rmUser, iConnect = Create.createConnectConversation, iUpsertOne2OneConversation = One2One.iUpsertOne2OneConversation @@ -342,7 +342,7 @@ iGetTeamFeature getter = Features.getFeatureStatus @ps @a getter DontDoAuth iPutTeamFeature :: forall a r. ( Public.KnownTeamFeatureName a, - MaybeHasPaymentStatusCol a, + MaybeHasLockStatusCol a, Members '[ Error ActionError, Error NotATeamMember, @@ -353,10 +353,10 @@ iPutTeamFeature :: ] r ) => - (TeamId -> Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a -> Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a)) -> + (TeamId -> Public.TeamFeatureStatus 'Public.WithoutLockStatus a -> Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus a)) -> TeamId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) + Public.TeamFeatureStatus 'Public.WithoutLockStatus a -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus a) iPutTeamFeature setter = Features.setFeatureStatus @a setter DontDoAuth sitemap :: Routes a (Sem GalleyEffects) () diff --git a/services/galley/src/Galley/API/LegalHold.hs b/services/galley/src/Galley/API/LegalHold.hs index 7fff48d3ac..051d82c30a 100644 --- a/services/galley/src/Galley/API/LegalHold.hs +++ b/services/galley/src/Galley/API/LegalHold.hs @@ -103,7 +103,7 @@ isLegalHoldEnabledForTeam tid = do pure False FeatureLegalHoldDisabledByDefault -> do statusValue <- - Public.tfwoStatus <$$> TeamFeatures.getFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold tid + Public.tfwoStatus <$$> TeamFeatures.getFeatureStatusNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureLegalHold tid return $ case statusValue of Just Public.TeamFeatureEnabled -> True Just Public.TeamFeatureDisabled -> False diff --git a/services/galley/src/Galley/API/Public.hs b/services/galley/src/Galley/API/Public.hs index 632873f5f5..fa6eb5e7a5 100644 --- a/services/galley/src/Galley/API/Public.hs +++ b/services/galley/src/Galley/API/Public.hs @@ -117,70 +117,70 @@ servantSitemap = GalleyAPI.postOtrMessageUnqualified = Update.postOtrMessageUnqualified, GalleyAPI.postProteusMessage = Update.postProteusMessage, GalleyAPI.teamFeatureStatusSSOGet = - getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO Features.getSSOStatusInternal + getFeatureStatus @'Public.WithoutLockStatus @'Public.TeamFeatureSSO Features.getSSOStatusInternal . DoAuth, GalleyAPI.teamFeatureStatusLegalHoldGet = - getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold Features.getLegalholdStatusInternal + getFeatureStatus @'Public.WithoutLockStatus @'Public.TeamFeatureLegalHold Features.getLegalholdStatusInternal . DoAuth, GalleyAPI.teamFeatureStatusLegalHoldPut = setFeatureStatus @'Public.TeamFeatureLegalHold (Features.setLegalholdStatusInternal @InternalPaging) . DoAuth, GalleyAPI.teamFeatureStatusSearchVisibilityGet = - getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal + getFeatureStatus @'Public.WithoutLockStatus @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal . DoAuth, GalleyAPI.teamFeatureStatusSearchVisibilityPut = setFeatureStatus @'Public.TeamFeatureSearchVisibility Features.setTeamSearchVisibilityAvailableInternal . DoAuth, GalleyAPI.teamFeatureStatusSearchVisibilityDeprecatedGet = - getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal + getFeatureStatus @'Public.WithoutLockStatus @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal . DoAuth, GalleyAPI.teamFeatureStatusSearchVisibilityDeprecatedPut = setFeatureStatus @'Public.TeamFeatureSearchVisibility Features.setTeamSearchVisibilityAvailableInternal . DoAuth, GalleyAPI.teamFeatureStatusValidateSAMLEmailsGet = - getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal + getFeatureStatus @'Public.WithoutLockStatus @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal . DoAuth, GalleyAPI.teamFeatureStatusValidateSAMLEmailsDeprecatedGet = - getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal + getFeatureStatus @'Public.WithoutLockStatus @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal . DoAuth, GalleyAPI.teamFeatureStatusDigitalSignaturesGet = - getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal + getFeatureStatus @'Public.WithoutLockStatus @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal . DoAuth, GalleyAPI.teamFeatureStatusDigitalSignaturesDeprecatedGet = - getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal + getFeatureStatus @'Public.WithoutLockStatus @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal . DoAuth, GalleyAPI.teamFeatureStatusAppLockGet = - getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureAppLock Features.getAppLockInternal + getFeatureStatus @'Public.WithoutLockStatus @'Public.TeamFeatureAppLock Features.getAppLockInternal . DoAuth, GalleyAPI.teamFeatureStatusAppLockPut = setFeatureStatus @'Public.TeamFeatureAppLock Features.setAppLockInternal . DoAuth, GalleyAPI.teamFeatureStatusFileSharingGet = - getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureFileSharing Features.getFileSharingInternal . DoAuth, + getFeatureStatus @'Public.WithoutLockStatus @'Public.TeamFeatureFileSharing Features.getFileSharingInternal . DoAuth, GalleyAPI.teamFeatureStatusFileSharingPut = setFeatureStatus @'Public.TeamFeatureFileSharing Features.setFileSharingInternal . DoAuth, GalleyAPI.teamFeatureStatusClassifiedDomainsGet = - getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureClassifiedDomains Features.getClassifiedDomainsInternal + getFeatureStatus @'Public.WithoutLockStatus @'Public.TeamFeatureClassifiedDomains Features.getClassifiedDomainsInternal . DoAuth, GalleyAPI.teamFeatureStatusConferenceCallingGet = - getFeatureStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling Features.getConferenceCallingInternal + getFeatureStatus @'Public.WithoutLockStatus @'Public.TeamFeatureConferenceCalling Features.getConferenceCallingInternal . DoAuth, GalleyAPI.teamFeatureStatusSelfDeletingMessagesGet = - getFeatureStatus @'Public.WithPaymentStatus @'Public.TeamFeatureSelfDeletingMessages Features.getSelfDeletingMessagesInternal + getFeatureStatus @'Public.WithLockStatus @'Public.TeamFeatureSelfDeletingMessages Features.getSelfDeletingMessagesInternal . DoAuth, GalleyAPI.teamFeatureStatusSelfDeletingMessagesPut = setFeatureStatus @'Public.TeamFeatureSelfDeletingMessages Features.setSelfDeletingMessagesInternal . DoAuth, GalleyAPI.featureAllFeatureConfigsGet = Features.getAllFeatureConfigs, - GalleyAPI.featureConfigLegalHoldGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold Features.getLegalholdStatusInternal, - GalleyAPI.featureConfigSSOGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO Features.getSSOStatusInternal, - GalleyAPI.featureConfigSearchVisibilityGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal, - GalleyAPI.featureConfigValidateSAMLEmailsGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal, - GalleyAPI.featureConfigDigitalSignaturesGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal, - GalleyAPI.featureConfigAppLockGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureAppLock Features.getAppLockInternal, - GalleyAPI.featureConfigFileSharingGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureFileSharing Features.getFileSharingInternal, - GalleyAPI.featureConfigClassifiedDomainsGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureClassifiedDomains Features.getClassifiedDomainsInternal, - GalleyAPI.featureConfigConferenceCallingGet = Features.getFeatureConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling Features.getConferenceCallingInternal, - GalleyAPI.featureConfigSelfDeletingMessagesGet = Features.getFeatureConfig @'Public.WithPaymentStatus @'Public.TeamFeatureSelfDeletingMessages Features.getSelfDeletingMessagesInternal + GalleyAPI.featureConfigLegalHoldGet = Features.getFeatureConfig @'Public.WithoutLockStatus @'Public.TeamFeatureLegalHold Features.getLegalholdStatusInternal, + GalleyAPI.featureConfigSSOGet = Features.getFeatureConfig @'Public.WithoutLockStatus @'Public.TeamFeatureSSO Features.getSSOStatusInternal, + GalleyAPI.featureConfigSearchVisibilityGet = Features.getFeatureConfig @'Public.WithoutLockStatus @'Public.TeamFeatureSearchVisibility Features.getTeamSearchVisibilityAvailableInternal, + GalleyAPI.featureConfigValidateSAMLEmailsGet = Features.getFeatureConfig @'Public.WithoutLockStatus @'Public.TeamFeatureValidateSAMLEmails Features.getValidateSAMLEmailsInternal, + GalleyAPI.featureConfigDigitalSignaturesGet = Features.getFeatureConfig @'Public.WithoutLockStatus @'Public.TeamFeatureDigitalSignatures Features.getDigitalSignaturesInternal, + GalleyAPI.featureConfigAppLockGet = Features.getFeatureConfig @'Public.WithoutLockStatus @'Public.TeamFeatureAppLock Features.getAppLockInternal, + GalleyAPI.featureConfigFileSharingGet = Features.getFeatureConfig @'Public.WithoutLockStatus @'Public.TeamFeatureFileSharing Features.getFileSharingInternal, + GalleyAPI.featureConfigClassifiedDomainsGet = Features.getFeatureConfig @'Public.WithoutLockStatus @'Public.TeamFeatureClassifiedDomains Features.getClassifiedDomainsInternal, + GalleyAPI.featureConfigConferenceCallingGet = Features.getFeatureConfig @'Public.WithoutLockStatus @'Public.TeamFeatureConferenceCalling Features.getConferenceCallingInternal, + GalleyAPI.featureConfigSelfDeletingMessagesGet = Features.getFeatureConfig @'Public.WithLockStatus @'Public.TeamFeatureSelfDeletingMessages Features.getSelfDeletingMessagesInternal } sitemap :: Routes ApiBuilder (Sem GalleyEffects) () diff --git a/services/galley/src/Galley/API/Teams.hs b/services/galley/src/Galley/API/Teams.hs index cdfff7d636..5f06956348 100644 --- a/services/galley/src/Galley/API/Teams.hs +++ b/services/galley/src/Galley/API/Teams.hs @@ -1522,7 +1522,7 @@ canUserJoinTeam tid = do getTeamSearchVisibilityAvailableInternal :: Members '[Input Opts, TeamFeatureStore] r => TeamId -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSearchVisibility) + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureSearchVisibility) getTeamSearchVisibilityAvailableInternal tid = do -- TODO: This is just redundant given there is a decent default defConfig <- do @@ -1532,7 +1532,7 @@ getTeamSearchVisibilityAvailableInternal tid = do FeatureTeamSearchVisibilityDisabledByDefault -> Public.TeamFeatureDisabled fromMaybe defConfig - <$> TeamFeatures.getFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility tid + <$> TeamFeatures.getFeatureStatusNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureSearchVisibility tid -- | Modify and get visibility type for a team (internal, no user permission checks) getSearchVisibilityInternalH :: diff --git a/services/galley/src/Galley/API/Teams/Features.hs b/services/galley/src/Galley/API/Teams/Features.hs index 625e5426d6..f0249377b5 100644 --- a/services/galley/src/Galley/API/Teams/Features.hs +++ b/services/galley/src/Galley/API/Teams/Features.hs @@ -40,7 +40,7 @@ module Galley.API.Teams.Features setConferenceCallingInternal, getSelfDeletingMessagesInternal, setSelfDeletingMessagesInternal, - setPaymentStatus, + setLockStatus, DoAuth (..), GetFeatureInternalParam, ) @@ -91,7 +91,7 @@ data DoAuth = DoAuth UserId | DontDoAuth -- | For team-settings, to administrate team feature configuration. Here we have an admin uid -- and a team id, but no uid of the member for which the feature config holds. getFeatureStatus :: - forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName) r. + forall (ps :: Public.IncludeLockStatus) (a :: Public.TeamFeatureName) r. ( Public.KnownTeamFeatureName a, Members '[ Error ActionError, @@ -118,7 +118,7 @@ getFeatureStatus getter doauth tid = do setFeatureStatus :: forall (a :: Public.TeamFeatureName) r. ( Public.KnownTeamFeatureName a, - MaybeHasPaymentStatusCol a, + MaybeHasLockStatusCol a, Members '[ Error ActionError, Error TeamError, @@ -128,11 +128,11 @@ setFeatureStatus :: ] r ) => - (TeamId -> Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a -> Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a)) -> + (TeamId -> Public.TeamFeatureStatus 'Public.WithoutLockStatus a -> Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus a)) -> DoAuth -> TeamId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) + Public.TeamFeatureStatus 'Public.WithoutLockStatus a -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus a) setFeatureStatus setter doauth tid status = do case doauth of DoAuth uid -> do @@ -142,11 +142,11 @@ setFeatureStatus setter doauth tid status = do assertTeamExists tid setter tid status --- | Setting payment status can only be done through the internal API and therefore doesn't require auth. -setPaymentStatus :: +-- | Setting lock status can only be done through the internal API and therefore doesn't require auth. +setLockStatus :: forall (a :: Public.TeamFeatureName) r. ( Public.KnownTeamFeatureName a, - HasPaymentStatusCol a, + HasLockStatusCol a, Members [ Error ActionError, Error TeamError, @@ -157,15 +157,15 @@ setPaymentStatus :: r ) => TeamId -> - Public.PaymentStatusValue -> - Sem r Public.PaymentStatus -setPaymentStatus tid paymentStatusUpdate = do + Public.LockStatusValue -> + Sem r Public.LockStatus +setLockStatus tid lockStatusUpdate = do assertTeamExists tid - TeamFeatures.setPaymentStatus @a tid (Public.PaymentStatus paymentStatusUpdate) + TeamFeatures.setLockStatus @a tid (Public.LockStatus lockStatusUpdate) -- | For individual users to get feature config for their account (personal or team). getFeatureConfig :: - forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName) r. + forall (ps :: Public.IncludeLockStatus) (a :: Public.TeamFeatureName) r. ( Public.KnownTeamFeatureName a, Members '[ Error ActionError, @@ -206,7 +206,7 @@ getAllFeatureConfigs zusr = do mbTeam <- getOneUserTeam zusr zusrMembership <- maybe (pure Nothing) (flip getTeamMember zusr) mbTeam let getStatus :: - forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName) r. + forall (ps :: Public.IncludeLockStatus) (a :: Public.TeamFeatureName) r. ( Public.KnownTeamFeatureName a, Aeson.ToJSON (Public.TeamFeatureStatus ps a), Members '[Error ActionError, Error TeamError, Error NotATeamMember, TeamStore] r @@ -222,16 +222,16 @@ getAllFeatureConfigs zusr = do AllFeatureConfigs . HashMap.fromList <$> sequence - [ getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold getLegalholdStatusInternal, - getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO getSSOStatusInternal, - getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility getTeamSearchVisibilityAvailableInternal, - getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails getValidateSAMLEmailsInternal, - getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures getDigitalSignaturesInternal, - getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureAppLock getAppLockInternal, - getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureFileSharing getFileSharingInternal, - getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureClassifiedDomains getClassifiedDomainsInternal, - getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling getConferenceCallingInternal, - getStatus @'Public.WithPaymentStatus @'Public.TeamFeatureSelfDeletingMessages getSelfDeletingMessagesInternal + [ getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureLegalHold getLegalholdStatusInternal, + getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureSSO getSSOStatusInternal, + getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureSearchVisibility getTeamSearchVisibilityAvailableInternal, + getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureValidateSAMLEmails getValidateSAMLEmailsInternal, + getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureDigitalSignatures getDigitalSignaturesInternal, + getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureAppLock getAppLockInternal, + getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureFileSharing getFileSharingInternal, + getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureClassifiedDomains getClassifiedDomainsInternal, + getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureConferenceCalling getConferenceCallingInternal, + getStatus @'Public.WithLockStatus @'Public.TeamFeatureSelfDeletingMessages getSelfDeletingMessagesInternal ] getAllFeaturesH :: @@ -270,20 +270,20 @@ getAllFeatures :: getAllFeatures uid tid = do Aeson.object <$> sequence - [ getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO getSSOStatusInternal, - getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold getLegalholdStatusInternal, - getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility getTeamSearchVisibilityAvailableInternal, - getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails getValidateSAMLEmailsInternal, - getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures getDigitalSignaturesInternal, - getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureAppLock getAppLockInternal, - getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureFileSharing getFileSharingInternal, - getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureClassifiedDomains getClassifiedDomainsInternal, - getStatus @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling getConferenceCallingInternal, - getStatus @'Public.WithPaymentStatus @'Public.TeamFeatureSelfDeletingMessages getSelfDeletingMessagesInternal + [ getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureSSO getSSOStatusInternal, + getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureLegalHold getLegalholdStatusInternal, + getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureSearchVisibility getTeamSearchVisibilityAvailableInternal, + getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureValidateSAMLEmails getValidateSAMLEmailsInternal, + getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureDigitalSignatures getDigitalSignaturesInternal, + getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureAppLock getAppLockInternal, + getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureFileSharing getFileSharingInternal, + getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureClassifiedDomains getClassifiedDomainsInternal, + getStatus @'Public.WithoutLockStatus @'Public.TeamFeatureConferenceCalling getConferenceCallingInternal, + getStatus @'Public.WithLockStatus @'Public.TeamFeatureSelfDeletingMessages getSelfDeletingMessagesInternal ] where getStatus :: - forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName). + forall (ps :: Public.IncludeLockStatus) (a :: Public.TeamFeatureName). ( Public.KnownTeamFeatureName a, Aeson.ToJSON (Public.TeamFeatureStatus ps a) ) => @@ -295,7 +295,7 @@ getAllFeatures uid tid = do pure $ cs (toByteString' feature) Aeson..= status getFeatureStatusNoConfig :: - forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName) r. + forall (ps :: Public.IncludeLockStatus) (a :: Public.TeamFeatureName) r. ( Public.FeatureHasNoConfig ps a, HasStatusCol a, Member TeamFeatureStore r @@ -308,7 +308,7 @@ getFeatureStatusNoConfig getDefault tid = do fromMaybe defaultStatus <$> TeamFeatures.getFeatureStatusNoConfig @ps @a tid setFeatureStatusNoConfig :: - forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName) r. + forall (ps :: Public.IncludeLockStatus) (a :: Public.TeamFeatureName) r. ( Public.KnownTeamFeatureName a, Public.FeatureHasNoConfig ps a, HasStatusCol a, @@ -332,11 +332,11 @@ type GetFeatureInternalParam = Either (Maybe UserId) TeamId getSSOStatusInternal :: Members '[Input Opts, TeamFeatureStore] r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSSO) + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureSSO) getSSOStatusInternal = either (const $ Public.TeamFeatureStatusNoConfig <$> getDef) - (getFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO getDef) + (getFeatureStatusNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureSSO getDef) where getDef :: Member (Input Opts) r => Sem r Public.TeamFeatureStatusValue getDef = @@ -347,20 +347,20 @@ getSSOStatusInternal = setSSOStatusInternal :: Members '[Error TeamFeatureError, GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r => TeamId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSSO -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSSO) -setSSOStatusInternal = setFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO $ \case + Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureSSO -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureSSO) +setSSOStatusInternal = setFeatureStatusNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureSSO $ \case Public.TeamFeatureDisabled -> const (throw DisableSsoNotImplemented) Public.TeamFeatureEnabled -> const (pure ()) getTeamSearchVisibilityAvailableInternal :: Members '[Input Opts, TeamFeatureStore] r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSearchVisibility) + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureSearchVisibility) getTeamSearchVisibilityAvailableInternal = either (const $ Public.TeamFeatureStatusNoConfig <$> getDef) - (getFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility getDef) + (getFeatureStatusNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureSearchVisibility getDef) where getDef = do inputs (view (optSettings . setFeatureFlags . flagTeamSearchVisibility)) <&> \case @@ -370,20 +370,20 @@ getTeamSearchVisibilityAvailableInternal = setTeamSearchVisibilityAvailableInternal :: Members '[GundeckAccess, SearchVisibilityStore, TeamFeatureStore, TeamStore, P.TinyLog] r => TeamId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSearchVisibility -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSearchVisibility) -setTeamSearchVisibilityAvailableInternal = setFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSearchVisibility $ \case + Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureSearchVisibility -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureSearchVisibility) +setTeamSearchVisibilityAvailableInternal = setFeatureStatusNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureSearchVisibility $ \case Public.TeamFeatureDisabled -> SearchVisibilityData.resetSearchVisibility Public.TeamFeatureEnabled -> const (pure ()) getValidateSAMLEmailsInternal :: Member TeamFeatureStore r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureValidateSAMLEmails) + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureValidateSAMLEmails) getValidateSAMLEmailsInternal = either (const $ Public.TeamFeatureStatusNoConfig <$> getDef) - (getFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails getDef) + (getFeatureStatusNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureValidateSAMLEmails getDef) where -- FUTUREWORK: we may also want to get a default from the server config file here, like for -- sso, and team search visibility. @@ -393,18 +393,18 @@ getValidateSAMLEmailsInternal = setValidateSAMLEmailsInternal :: Members '[GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r => TeamId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureValidateSAMLEmails -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureValidateSAMLEmails) -setValidateSAMLEmailsInternal = setFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails $ \_ _ -> pure () + Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureValidateSAMLEmails -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureValidateSAMLEmails) +setValidateSAMLEmailsInternal = setFeatureStatusNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureValidateSAMLEmails $ \_ _ -> pure () getDigitalSignaturesInternal :: Member TeamFeatureStore r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureDigitalSignatures) + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureDigitalSignatures) getDigitalSignaturesInternal = either (const $ Public.TeamFeatureStatusNoConfig <$> getDef) - (getFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures getDef) + (getFeatureStatusNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureDigitalSignatures getDef) where -- FUTUREWORK: we may also want to get a default from the server config file here, like for -- sso, and team search visibility. @@ -414,14 +414,14 @@ getDigitalSignaturesInternal = setDigitalSignaturesInternal :: Members '[GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r => TeamId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureDigitalSignatures -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureDigitalSignatures) -setDigitalSignaturesInternal = setFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures $ \_ _ -> pure () + Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureDigitalSignatures -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureDigitalSignatures) +setDigitalSignaturesInternal = setFeatureStatusNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureDigitalSignatures $ \_ _ -> pure () getLegalholdStatusInternal :: Members '[LegalHoldStore, TeamFeatureStore, TeamStore] r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureLegalHold) + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureLegalHold) getLegalholdStatusInternal (Left _) = pure $ Public.TeamFeatureStatusNoConfig Public.TeamFeatureDisabled getLegalholdStatusInternal (Right tid) = do @@ -464,8 +464,8 @@ setLegalholdStatusInternal :: r ) => TeamId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureLegalHold -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureLegalHold) + Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureLegalHold -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureLegalHold) setLegalholdStatusInternal tid status@(Public.tfwoStatus -> statusValue) = do do -- this extra do is to encapsulate the assertions running before the actual operation. @@ -485,17 +485,17 @@ setLegalholdStatusInternal tid status@(Public.tfwoStatus -> statusValue) = do Public.TeamFeatureDisabled -> removeSettings' @p tid Public.TeamFeatureEnabled -> do ensureNotTooLargeToActivateLegalHold tid - TeamFeatures.setFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold tid status + TeamFeatures.setFeatureStatusNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureLegalHold tid status getFileSharingInternal :: Members '[Input Opts, TeamFeatureStore] r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureFileSharing) + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureFileSharing) getFileSharingInternal = - getFeatureStatusWithDefaultConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureFileSharing flagFileSharing . either (const Nothing) Just + getFeatureStatusWithDefaultConfig @'Public.WithoutLockStatus @'Public.TeamFeatureFileSharing flagFileSharing . either (const Nothing) Just getFeatureStatusWithDefaultConfig :: - forall (ps :: Public.IncludePaymentStatus) (a :: TeamFeatureName) r. + forall (ps :: Public.IncludeLockStatus) (a :: TeamFeatureName) r. ( KnownTeamFeatureName a, HasStatusCol a, FeatureHasNoConfig ps a, @@ -517,14 +517,14 @@ getFeatureStatusWithDefaultConfig lens' = setFileSharingInternal :: Members '[GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r => TeamId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureFileSharing -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureFileSharing) -setFileSharingInternal = setFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureFileSharing $ \_status _tid -> pure () + Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureFileSharing -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureFileSharing) +setFileSharingInternal = setFeatureStatusNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureFileSharing $ \_status _tid -> pure () getAppLockInternal :: Members '[Input Opts, TeamFeatureStore] r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureAppLock) + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureAppLock) getAppLockInternal mbtid = do Defaults defaultStatus <- inputs (view (optSettings . setFeatureFlags . flagAppLockDefaults)) status <- @@ -534,8 +534,8 @@ getAppLockInternal mbtid = do setAppLockInternal :: Members '[GundeckAccess, TeamFeatureStore, TeamStore, Error TeamFeatureError, P.TinyLog] r => TeamId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureAppLock -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureAppLock) + Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureAppLock -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureAppLock) setAppLockInternal tid status = do when (Public.applockInactivityTimeoutSecs (Public.tfwcConfig status) < 30) $ throw AppLockinactivityTimeoutTooLow @@ -547,7 +547,7 @@ setAppLockInternal tid status = do getClassifiedDomainsInternal :: Member (Input Opts) r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureClassifiedDomains) + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureClassifiedDomains) getClassifiedDomainsInternal _mbtid = do globalConfig <- inputs (view (optSettings . setFeatureFlags . flagClassifiedDomains)) let config = globalConfig @@ -558,39 +558,39 @@ getClassifiedDomainsInternal _mbtid = do getConferenceCallingInternal :: Members '[BrigAccess, Input Opts, TeamFeatureStore] r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureConferenceCalling) + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureConferenceCalling) getConferenceCallingInternal (Left (Just uid)) = do getFeatureConfigViaAccount @'Public.TeamFeatureConferenceCalling uid getConferenceCallingInternal (Left Nothing) = do - getFeatureStatusWithDefaultConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling flagConferenceCalling Nothing + getFeatureStatusWithDefaultConfig @'Public.WithoutLockStatus @'Public.TeamFeatureConferenceCalling flagConferenceCalling Nothing getConferenceCallingInternal (Right tid) = do - getFeatureStatusWithDefaultConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling flagConferenceCalling (Just tid) + getFeatureStatusWithDefaultConfig @'Public.WithoutLockStatus @'Public.TeamFeatureConferenceCalling flagConferenceCalling (Just tid) setConferenceCallingInternal :: Members '[GundeckAccess, TeamFeatureStore, TeamStore, P.TinyLog] r => TeamId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureConferenceCalling -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureConferenceCalling) + Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureConferenceCalling -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureConferenceCalling) setConferenceCallingInternal = - setFeatureStatusNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling $ \_status _tid -> pure () + setFeatureStatusNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureConferenceCalling $ \_status _tid -> pure () getSelfDeletingMessagesInternal :: Member TeamFeatureStore r => GetFeatureInternalParam -> - Sem r (Public.TeamFeatureStatus 'Public.WithPaymentStatus 'Public.TeamFeatureSelfDeletingMessages) + Sem r (Public.TeamFeatureStatus 'Public.WithLockStatus 'Public.TeamFeatureSelfDeletingMessages) getSelfDeletingMessagesInternal = \case Left _ -> pure Public.defaultSelfDeletingMessagesStatus Right tid -> do - (maybeFeatureStatus, maybePaymentStatus) <- TeamFeatures.getSelfDeletingMessagesStatus tid - pure $ case (maybePaymentStatus, maybeFeatureStatus) of - (Just Public.PaymentUnlocked, Just featureStatus) -> - Public.TeamFeatureStatusWithConfigAndPaymentStatus + (maybeFeatureStatus, maybeLockStatus) <- TeamFeatures.getSelfDeletingMessagesStatus tid + pure $ case (maybeLockStatus, maybeFeatureStatus) of + (Just Public.Unlocked, Just featureStatus) -> + Public.TeamFeatureStatusWithConfigAndLockStatus (Public.tfwcStatus featureStatus) (Public.tfwcConfig featureStatus) - Public.PaymentUnlocked - (Just Public.PaymentUnlocked, Nothing) -> - Public.defaultSelfDeletingMessagesStatus {Public.tfwcapsPaymentStatus = Public.PaymentUnlocked} - (Just Public.PaymentLocked, _) -> Public.defaultSelfDeletingMessagesStatus + Public.Unlocked + (Just Public.Unlocked, Nothing) -> + Public.defaultSelfDeletingMessagesStatus {Public.tfwcapsLockStatus = Public.Unlocked} + (Just Public.Locked, _) -> Public.defaultSelfDeletingMessagesStatus (Nothing, _) -> Public.defaultSelfDeletingMessagesStatus setSelfDeletingMessagesInternal :: @@ -603,29 +603,29 @@ setSelfDeletingMessagesInternal :: ] r => TeamId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSelfDeletingMessages -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSelfDeletingMessages) + Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureSelfDeletingMessages -> + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureSelfDeletingMessages) setSelfDeletingMessagesInternal tid st = do - guardPaymentStatus @'Public.TeamFeatureSelfDeletingMessages tid Public.PaymentLocked + guardLockStatus @'Public.TeamFeatureSelfDeletingMessages tid Public.Locked let pushEvent = pushFeatureConfigEvent tid $ Event.Event Event.Update Public.TeamFeatureSelfDeletingMessages (EdFeatureSelfDeletingMessagesChanged st) TeamFeatures.setSelfDeletingMessagesStatus tid st <* pushEvent -- TODO(fisx): move this function to a more suitable place / module. -guardPaymentStatus :: +guardLockStatus :: forall (a :: Public.TeamFeatureName) r. - ( MaybeHasPaymentStatusCol a, + ( MaybeHasLockStatusCol a, Member TeamFeatureStore r, Member (Error TeamFeatureError) r ) => TeamId -> - Public.PaymentStatusValue -> -- FUTUREWORK(fisx): move this into its own type class and infer from `a`? + Public.LockStatusValue -> -- FUTUREWORK(fisx): move this into its own type class and infer from `a`? Sem r () -guardPaymentStatus tid defPaymentStatus = do - (TeamFeatures.getPaymentStatus @a tid <&> fromMaybe defPaymentStatus) >>= \case - Public.PaymentUnlocked -> pure () - Public.PaymentLocked -> throw PaymentStatusLocked +guardLockStatus tid defLockStatus = do + (TeamFeatures.getLockStatus @a tid <&> fromMaybe defLockStatus) >>= \case + Public.Unlocked -> pure () + Public.Locked -> throw FeatureLocked pushFeatureConfigEvent :: Members '[GundeckAccess, TeamStore, P.TinyLog] r => @@ -652,5 +652,5 @@ getFeatureConfigViaAccount :: Member BrigAccess r ) => UserId -> - Sem r (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus flag) + Sem r (Public.TeamFeatureStatus 'Public.WithoutLockStatus flag) getFeatureConfigViaAccount = getAccountFeatureConfigClient diff --git a/services/galley/src/Galley/Cassandra/TeamFeatures.hs b/services/galley/src/Galley/Cassandra/TeamFeatures.hs index 4fb91eaafd..c72d549f65 100644 --- a/services/galley/src/Galley/Cassandra/TeamFeatures.hs +++ b/services/galley/src/Galley/Cassandra/TeamFeatures.hs @@ -30,7 +30,7 @@ import Polysemy.Input import Wire.API.Team.Feature getFeatureStatusNoConfig :: - forall (ps :: IncludePaymentStatus) (a :: TeamFeatureName) m. + forall (ps :: IncludeLockStatus) (a :: TeamFeatureName) m. ( MonadClient m, FeatureHasNoConfig ps a, HasStatusCol a @@ -48,7 +48,7 @@ getFeatureStatusNoConfig _ _ tid = do select = fromString $ "select " <> statusCol @a <> " from team_features where team_id = ?" setFeatureStatusNoConfig :: - forall (ps :: IncludePaymentStatus) (a :: TeamFeatureName) m. + forall (ps :: IncludeLockStatus) (a :: TeamFeatureName) m. ( MonadClient m, FeatureHasNoConfig ps a, HasStatusCol a @@ -70,7 +70,7 @@ getApplockFeatureStatus :: forall m. (MonadClient m) => TeamId -> - m (Maybe (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureAppLock)) + m (Maybe (TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureAppLock)) getApplockFeatureStatus tid = do let q = query1 select (params LocalQuorum (Identity tid)) mTuple <- retry x1 q @@ -87,8 +87,8 @@ getApplockFeatureStatus tid = do setApplockFeatureStatus :: (MonadClient m) => TeamId -> - TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureAppLock -> - m (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureAppLock) + TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureAppLock -> + m (TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureAppLock) setApplockFeatureStatus tid status = do let statusValue = tfwcStatus status enforce = applockEnforceAppLock . tfwcConfig $ status @@ -107,30 +107,30 @@ getSelfDeletingMessagesStatus :: forall m. (MonadClient m) => TeamId -> - m (Maybe (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages), Maybe PaymentStatusValue) + m (Maybe (TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureSelfDeletingMessages), Maybe LockStatusValue) getSelfDeletingMessagesStatus tid = do let q = query1 select (params LocalQuorum (Identity tid)) mTuple <- retry x1 q pure ( mTuple >>= \(mbStatusValue, mbTimeout, _) -> TeamFeatureStatusWithConfig <$> mbStatusValue <*> (TeamFeatureSelfDeletingMessagesConfig <$> mbTimeout), - mTuple >>= \(_, _, mbPaymentStatus) -> mbPaymentStatus + mTuple >>= \(_, _, mbLockStatus) -> mbLockStatus ) where - select :: PrepQuery R (Identity TeamId) (Maybe TeamFeatureStatusValue, Maybe Int32, Maybe PaymentStatusValue) + select :: PrepQuery R (Identity TeamId) (Maybe TeamFeatureStatusValue, Maybe Int32, Maybe LockStatusValue) select = fromString $ "select " <> statusCol @'TeamFeatureSelfDeletingMessages <> ", self_deleting_messages_ttl, " - <> paymentStatusCol @'TeamFeatureSelfDeletingMessages + <> lockStatusCol @'TeamFeatureSelfDeletingMessages <> " from team_features where team_id = ?" setSelfDeletingMessagesStatus :: (MonadClient m) => TeamId -> - TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages -> - m (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages) + TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureSelfDeletingMessages -> + m (TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureSelfDeletingMessages) setSelfDeletingMessagesStatus tid status = do let statusValue = tfwcStatus status timeout = sdmEnforcedTimeoutSeconds . tfwcConfig $ status @@ -145,44 +145,44 @@ setSelfDeletingMessagesStatus tid status = do <> ", self_deleting_messages_ttl) " <> "values (?, ?, ?)" -setPaymentStatus :: +setLockStatus :: forall (a :: TeamFeatureName) m. ( MonadClient m, - HasPaymentStatusCol a + HasLockStatusCol a ) => Proxy a -> TeamId -> - PaymentStatus -> - m PaymentStatus -setPaymentStatus _ tid (PaymentStatus paymentStatus) = do - retry x5 $ write insert (params LocalQuorum (tid, paymentStatus)) - pure (PaymentStatus paymentStatus) + LockStatus -> + m LockStatus +setLockStatus _ tid (LockStatus lockStatus) = do + retry x5 $ write insert (params LocalQuorum (tid, lockStatus)) + pure (LockStatus lockStatus) where - insert :: PrepQuery W (TeamId, PaymentStatusValue) () + insert :: PrepQuery W (TeamId, LockStatusValue) () insert = fromString $ - "insert into team_features (team_id, " <> paymentStatusCol @a <> ") values (?, ?)" + "insert into team_features (team_id, " <> lockStatusCol @a <> ") values (?, ?)" -getPaymentStatus :: +getLockStatus :: forall (a :: TeamFeatureName) m. ( MonadClient m, - MaybeHasPaymentStatusCol a + MaybeHasLockStatusCol a ) => Proxy a -> TeamId -> - m (Maybe PaymentStatusValue) -getPaymentStatus _ tid = - case maybePaymentStatusCol @a of + m (Maybe LockStatusValue) +getLockStatus _ tid = + case maybeLockStatusCol @a of Nothing -> pure Nothing - Just paymentStatusColName -> do + Just lockStatusColName -> do let q = query1 select (params LocalQuorum (Identity tid)) (>>= runIdentity) <$> retry x1 q where - select :: PrepQuery R (Identity TeamId) (Identity (Maybe PaymentStatusValue)) + select :: PrepQuery R (Identity TeamId) (Identity (Maybe LockStatusValue)) select = fromString $ "select " - <> paymentStatusColName + <> lockStatusColName <> " from team_features where team_id = ?" interpretTeamFeatureStoreToCassandra :: @@ -192,8 +192,8 @@ interpretTeamFeatureStoreToCassandra :: interpretTeamFeatureStoreToCassandra = interpret $ \case GetFeatureStatusNoConfig' ps tfn tid -> embedClient $ getFeatureStatusNoConfig ps tfn tid SetFeatureStatusNoConfig' ps tfn tid value -> embedClient $ setFeatureStatusNoConfig ps tfn tid value - SetPaymentStatus' p tid value -> embedClient $ setPaymentStatus p tid value - GetPaymentStatus' p tid -> embedClient $ getPaymentStatus p tid + SetLockStatus' p tid value -> embedClient $ setLockStatus p tid value + GetLockStatus' p tid -> embedClient $ getLockStatus p tid GetApplockFeatureStatus tid -> embedClient $ getApplockFeatureStatus tid SetApplockFeatureStatus tid value -> embedClient $ setApplockFeatureStatus tid value GetSelfDeletingMessagesStatus tid -> embedClient $ getSelfDeletingMessagesStatus tid diff --git a/services/galley/src/Galley/Data/TeamFeatures.hs b/services/galley/src/Galley/Data/TeamFeatures.hs index 8c16d26f8e..65a6cc6648 100644 --- a/services/galley/src/Galley/Data/TeamFeatures.hs +++ b/services/galley/src/Galley/Data/TeamFeatures.hs @@ -15,7 +15,7 @@ -- You should have received a copy of the GNU Affero General Public License along -- with this program. If not, see . -module Galley.Data.TeamFeatures (HasStatusCol (..), HasPaymentStatusCol (..), MaybeHasPaymentStatusCol (..)) where +module Galley.Data.TeamFeatures (HasStatusCol (..), HasLockStatusCol (..), MaybeHasLockStatusCol (..)) where import Imports import Wire.API.Team.Feature @@ -50,31 +50,31 @@ instance HasStatusCol 'TeamFeatureConferenceCalling where statusCol = "conferenc instance HasStatusCol 'TeamFeatureSelfDeletingMessages where statusCol = "self_deleting_messages_status" ---------------------------------------------------------------------- -class HasPaymentStatusCol (a :: TeamFeatureName) where - paymentStatusCol :: String +class HasLockStatusCol (a :: TeamFeatureName) where + lockStatusCol :: String -class MaybeHasPaymentStatusCol (a :: TeamFeatureName) where - maybePaymentStatusCol :: Maybe String +class MaybeHasLockStatusCol (a :: TeamFeatureName) where + maybeLockStatusCol :: Maybe String -instance {-# OVERLAPPABLE #-} HasPaymentStatusCol a => MaybeHasPaymentStatusCol a where - maybePaymentStatusCol = Just (paymentStatusCol @a) +instance {-# OVERLAPPABLE #-} HasLockStatusCol a => MaybeHasLockStatusCol a where + maybeLockStatusCol = Just (lockStatusCol @a) ---------------------------------------------------------------------- -instance HasPaymentStatusCol 'TeamFeatureSelfDeletingMessages where - paymentStatusCol = "self_deleting_messages_payment_status" +instance HasLockStatusCol 'TeamFeatureSelfDeletingMessages where + lockStatusCol = "self_deleting_messages_lock_status" -instance MaybeHasPaymentStatusCol 'TeamFeatureLegalHold where maybePaymentStatusCol = Nothing +instance MaybeHasLockStatusCol 'TeamFeatureLegalHold where maybeLockStatusCol = Nothing -instance MaybeHasPaymentStatusCol 'TeamFeatureSSO where maybePaymentStatusCol = Nothing +instance MaybeHasLockStatusCol 'TeamFeatureSSO where maybeLockStatusCol = Nothing -instance MaybeHasPaymentStatusCol 'TeamFeatureSearchVisibility where maybePaymentStatusCol = Nothing +instance MaybeHasLockStatusCol 'TeamFeatureSearchVisibility where maybeLockStatusCol = Nothing -instance MaybeHasPaymentStatusCol 'TeamFeatureValidateSAMLEmails where maybePaymentStatusCol = Nothing +instance MaybeHasLockStatusCol 'TeamFeatureValidateSAMLEmails where maybeLockStatusCol = Nothing -instance MaybeHasPaymentStatusCol 'TeamFeatureDigitalSignatures where maybePaymentStatusCol = Nothing +instance MaybeHasLockStatusCol 'TeamFeatureDigitalSignatures where maybeLockStatusCol = Nothing -instance MaybeHasPaymentStatusCol 'TeamFeatureAppLock where maybePaymentStatusCol = Nothing +instance MaybeHasLockStatusCol 'TeamFeatureAppLock where maybeLockStatusCol = Nothing -instance MaybeHasPaymentStatusCol 'TeamFeatureFileSharing where maybePaymentStatusCol = Nothing +instance MaybeHasLockStatusCol 'TeamFeatureFileSharing where maybeLockStatusCol = Nothing -instance MaybeHasPaymentStatusCol 'TeamFeatureConferenceCalling where maybePaymentStatusCol = Nothing +instance MaybeHasLockStatusCol 'TeamFeatureConferenceCalling where maybeLockStatusCol = Nothing diff --git a/services/galley/src/Galley/Effects/TeamFeatureStore.hs b/services/galley/src/Galley/Effects/TeamFeatureStore.hs index 9be53b4734..8e5673ba24 100644 --- a/services/galley/src/Galley/Effects/TeamFeatureStore.hs +++ b/services/galley/src/Galley/Effects/TeamFeatureStore.hs @@ -23,8 +23,8 @@ module Galley.Effects.TeamFeatureStore setApplockFeatureStatus, getSelfDeletingMessagesStatus, setSelfDeletingMessagesStatus, - setPaymentStatus, - getPaymentStatus, + setLockStatus, + getLockStatus, ) where @@ -38,7 +38,7 @@ import Wire.API.Team.Feature data TeamFeatureStore m a where -- the proxy argument makes sure that makeSem below generates type-inference-friendly code GetFeatureStatusNoConfig' :: - forall (ps :: IncludePaymentStatus) (a :: TeamFeatureName) m. + forall (ps :: IncludeLockStatus) (a :: TeamFeatureName) m. ( FeatureHasNoConfig ps a, HasStatusCol a ) => @@ -48,7 +48,7 @@ data TeamFeatureStore m a where TeamFeatureStore m (Maybe (TeamFeatureStatus ps a)) -- the proxy argument makes sure that makeSem below generates type-inference-friendly code SetFeatureStatusNoConfig' :: - forall (ps :: IncludePaymentStatus) (a :: TeamFeatureName) m. + forall (ps :: IncludeLockStatus) (a :: TeamFeatureName) m. ( FeatureHasNoConfig ps a, HasStatusCol a ) => @@ -62,59 +62,59 @@ data TeamFeatureStore m a where TeamFeatureStore m (Maybe (TeamFeatureStatus ps 'TeamFeatureAppLock)) SetApplockFeatureStatus :: TeamId -> - TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureAppLock -> - TeamFeatureStore m (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureAppLock) + TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureAppLock -> + TeamFeatureStore m (TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureAppLock) GetSelfDeletingMessagesStatus :: TeamId -> - TeamFeatureStore m (Maybe (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages), Maybe PaymentStatusValue) + TeamFeatureStore m (Maybe (TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureSelfDeletingMessages), Maybe LockStatusValue) SetSelfDeletingMessagesStatus :: TeamId -> - TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages -> - TeamFeatureStore m (TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureSelfDeletingMessages) - SetPaymentStatus' :: + TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureSelfDeletingMessages -> + TeamFeatureStore m (TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureSelfDeletingMessages) + SetLockStatus' :: forall (a :: TeamFeatureName) m. - ( HasPaymentStatusCol a + ( HasLockStatusCol a ) => Proxy a -> TeamId -> - PaymentStatus -> - TeamFeatureStore m PaymentStatus - GetPaymentStatus' :: + LockStatus -> + TeamFeatureStore m LockStatus + GetLockStatus' :: forall (a :: TeamFeatureName) m. - ( MaybeHasPaymentStatusCol a + ( MaybeHasLockStatusCol a ) => Proxy a -> TeamId -> - TeamFeatureStore m (Maybe PaymentStatusValue) + TeamFeatureStore m (Maybe LockStatusValue) makeSem ''TeamFeatureStore getFeatureStatusNoConfig :: - forall (ps :: IncludePaymentStatus) (a :: TeamFeatureName) r. + forall (ps :: IncludeLockStatus) (a :: TeamFeatureName) r. (Member TeamFeatureStore r, FeatureHasNoConfig ps a, HasStatusCol a) => TeamId -> Sem r (Maybe (TeamFeatureStatus ps a)) getFeatureStatusNoConfig = getFeatureStatusNoConfig' (Proxy @ps) (Proxy @a) setFeatureStatusNoConfig :: - forall (ps :: IncludePaymentStatus) (a :: TeamFeatureName) r. + forall (ps :: IncludeLockStatus) (a :: TeamFeatureName) r. (Member TeamFeatureStore r, FeatureHasNoConfig ps a, HasStatusCol a) => TeamId -> TeamFeatureStatus ps a -> Sem r (TeamFeatureStatus ps a) setFeatureStatusNoConfig = setFeatureStatusNoConfig' (Proxy @ps) (Proxy @a) -setPaymentStatus :: +setLockStatus :: forall (a :: TeamFeatureName) r. - (Member TeamFeatureStore r, HasPaymentStatusCol a) => + (Member TeamFeatureStore r, HasLockStatusCol a) => TeamId -> - PaymentStatus -> - Sem r PaymentStatus -setPaymentStatus = setPaymentStatus' (Proxy @a) + LockStatus -> + Sem r LockStatus +setLockStatus = setLockStatus' (Proxy @a) -getPaymentStatus :: +getLockStatus :: forall (a :: TeamFeatureName) r. - (Member TeamFeatureStore r, MaybeHasPaymentStatusCol a) => + (Member TeamFeatureStore r, MaybeHasLockStatusCol a) => TeamId -> - Sem r (Maybe PaymentStatusValue) -getPaymentStatus = getPaymentStatus' (Proxy @a) + Sem r (Maybe LockStatusValue) +getLockStatus = getLockStatus' (Proxy @a) diff --git a/services/galley/test/integration/API/Teams.hs b/services/galley/test/integration/API/Teams.hs index f539707b41..a1edf78225 100644 --- a/services/galley/test/integration/API/Teams.hs +++ b/services/galley/test/integration/API/Teams.hs @@ -355,7 +355,7 @@ testEnableSSOPerTeam = do assertQueue "create team" tActivate let check :: HasCallStack => String -> Public.TeamFeatureStatusValue -> TestM () check msg enabledness = do - status :: Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSSO <- responseJsonUnsafe <$> (getSSOEnabledInternal tid (getSSOEnabledInternal tid TestM () @@ -385,7 +385,7 @@ testEnableTeamSearchVisibilityPerTeam = do (tid, owner, member : _) <- Util.createBindingTeamWithMembers 2 let check :: (HasCallStack, MonadCatch m, MonadIO m, Monad m, MonadHttp m) => String -> Public.TeamFeatureStatusValue -> m () check msg enabledness = do - status :: Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSearchVisibility <- responseJsonUnsafe <$> (Util.getTeamSearchVisibilityAvailableInternal g tid (Util.getTeamSearchVisibilityAvailableInternal g tid TeamId -> TestM ResponseLBS getSSOEnabledInternal = Util.getTeamFeatureFlagInternal Public.TeamFeatureSSO putSSOEnabledInternal :: HasCallStack => TeamId -> Public.TeamFeatureStatusValue -> TestM () -putSSOEnabledInternal tid statusValue = void $ Util.putTeamFeatureFlagInternal @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO expect2xx tid (Public.TeamFeatureStatusNoConfig statusValue) +putSSOEnabledInternal tid statusValue = void $ Util.putTeamFeatureFlagInternal @'Public.WithoutLockStatus @'Public.TeamFeatureSSO expect2xx tid (Public.TeamFeatureStatusNoConfig statusValue) getSearchVisibility :: HasCallStack => (Request -> Request) -> UserId -> TeamId -> (MonadIO m, MonadHttp m) => m ResponseLBS getSearchVisibility g uid tid = do diff --git a/services/galley/test/integration/API/Teams/Feature.hs b/services/galley/test/integration/API/Teams/Feature.hs index 9af553bbca..0c3d293b9c 100644 --- a/services/galley/test/integration/API/Teams/Feature.hs +++ b/services/galley/test/integration/API/Teams/Feature.hs @@ -60,14 +60,14 @@ tests s = [ test s "SSO" testSSO, test s "LegalHold" testLegalHold, test s "SearchVisibility" testSearchVisibility, - test s "DigitalSignatures" $ testSimpleFlag @'Public.WithoutPaymentStatus @'Public.TeamFeatureDigitalSignatures Public.TeamFeatureDisabled, - test s "ValidateSAMLEmails" $ testSimpleFlag @'Public.WithoutPaymentStatus @'Public.TeamFeatureValidateSAMLEmails Public.TeamFeatureDisabled, - test s "FileSharing" $ testSimpleFlag @'Public.WithoutPaymentStatus @'Public.TeamFeatureFileSharing Public.TeamFeatureEnabled, + test s "DigitalSignatures" $ testSimpleFlag @'Public.WithoutLockStatus @'Public.TeamFeatureDigitalSignatures Public.TeamFeatureDisabled, + test s "ValidateSAMLEmails" $ testSimpleFlag @'Public.WithoutLockStatus @'Public.TeamFeatureValidateSAMLEmails Public.TeamFeatureDisabled, + test s "FileSharing" $ testSimpleFlag @'Public.WithoutLockStatus @'Public.TeamFeatureFileSharing Public.TeamFeatureEnabled, test s "Classified Domains (enabled)" testClassifiedDomainsEnabled, test s "Classified Domains (disabled)" testClassifiedDomainsDisabled, test s "All features" testAllFeatures, test s "Feature Configs / Team Features Consistency" testFeatureConfigConsistency, - test s "ConferenceCalling" $ testSimpleFlag @'Public.WithoutPaymentStatus @'Public.TeamFeatureConferenceCalling Public.TeamFeatureEnabled, + test s "ConferenceCalling" $ testSimpleFlag @'Public.WithoutLockStatus @'Public.TeamFeatureConferenceCalling Public.TeamFeatureEnabled, test s "SelfDeletingMessages" testSelfDeletingMessages ] @@ -81,13 +81,13 @@ testSSO = do Util.addTeamMember owner tid member (rolePermissions RoleMember) Nothing let getSSO :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () - getSSO = assertFlagNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO $ Util.getTeamFeatureFlag Public.TeamFeatureSSO member tid + getSSO = assertFlagNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureSSO $ Util.getTeamFeatureFlag Public.TeamFeatureSSO member tid getSSOFeatureConfig :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () - getSSOFeatureConfig = assertFlagNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO $ Util.getFeatureConfig Public.TeamFeatureSSO member + getSSOFeatureConfig = assertFlagNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureSSO $ Util.getFeatureConfig Public.TeamFeatureSSO member getSSOInternal :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () - getSSOInternal = assertFlagNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO $ Util.getTeamFeatureFlagInternal Public.TeamFeatureSSO tid + getSSOInternal = assertFlagNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureSSO $ Util.getTeamFeatureFlagInternal Public.TeamFeatureSSO tid setSSOInternal :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () - setSSOInternal = void . Util.putTeamFeatureFlagInternal @'Public.WithoutPaymentStatus @'Public.TeamFeatureSSO expect2xx tid . Public.TeamFeatureStatusNoConfig + setSSOInternal = void . Util.putTeamFeatureFlagInternal @'Public.WithoutLockStatus @'Public.TeamFeatureSSO expect2xx tid . Public.TeamFeatureStatusNoConfig assertFlagForbidden $ Util.getTeamFeatureFlag Public.TeamFeatureSSO nonMember tid @@ -121,13 +121,13 @@ testLegalHold = do Util.addTeamMember owner tid member (rolePermissions RoleMember) Nothing let getLegalHold :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () - getLegalHold = assertFlagNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold $ Util.getTeamFeatureFlag Public.TeamFeatureLegalHold member tid + getLegalHold = assertFlagNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureLegalHold $ Util.getTeamFeatureFlag Public.TeamFeatureLegalHold member tid getLegalHoldInternal :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () - getLegalHoldInternal = assertFlagNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold $ Util.getTeamFeatureFlagInternal Public.TeamFeatureLegalHold tid - getLegalHoldFeatureConfig = assertFlagNoConfig @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold $ Util.getFeatureConfig Public.TeamFeatureLegalHold member + getLegalHoldInternal = assertFlagNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureLegalHold $ Util.getTeamFeatureFlagInternal Public.TeamFeatureLegalHold tid + getLegalHoldFeatureConfig = assertFlagNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureLegalHold $ Util.getFeatureConfig Public.TeamFeatureLegalHold member setLegalHoldInternal :: HasCallStack => Public.TeamFeatureStatusValue -> TestM () - setLegalHoldInternal = void . Util.putTeamFeatureFlagInternal @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold expect2xx tid . Public.TeamFeatureStatusNoConfig + setLegalHoldInternal = void . Util.putTeamFeatureFlagInternal @'Public.WithoutLockStatus @'Public.TeamFeatureLegalHold expect2xx tid . Public.TeamFeatureStatusNoConfig getLegalHold Public.TeamFeatureDisabled getLegalHoldInternal Public.TeamFeatureDisabled @@ -249,7 +249,7 @@ getClassifiedDomains :: (HasCallStack, HasGalley m, MonadIO m, MonadHttp m, MonadCatch m) => UserId -> TeamId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureClassifiedDomains -> + Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureClassifiedDomains -> m () getClassifiedDomains member tid = assertFlagWithConfig @Public.TeamFeatureClassifiedDomainsConfig $ @@ -258,7 +258,7 @@ getClassifiedDomains member tid = getClassifiedDomainsInternal :: (HasCallStack, HasGalley m, MonadIO m, MonadHttp m, MonadCatch m) => TeamId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureClassifiedDomains -> + Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureClassifiedDomains -> m () getClassifiedDomainsInternal tid = assertFlagWithConfig @Public.TeamFeatureClassifiedDomainsConfig $ @@ -276,7 +276,7 @@ testClassifiedDomainsEnabled = do let getClassifiedDomainsFeatureConfig :: (HasCallStack, HasGalley m, MonadIO m, MonadHttp m, MonadCatch m) => UserId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureClassifiedDomains -> + Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureClassifiedDomains -> m () getClassifiedDomainsFeatureConfig uid = do assertFlagWithConfig @Public.TeamFeatureClassifiedDomainsConfig $ @@ -298,7 +298,7 @@ testClassifiedDomainsDisabled = do let getClassifiedDomainsFeatureConfig :: (HasCallStack, HasGalley m, MonadIO m, MonadHttp m, MonadCatch m) => UserId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureClassifiedDomains -> + Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureClassifiedDomains -> m () getClassifiedDomainsFeatureConfig uid = do assertFlagWithConfig @Public.TeamFeatureClassifiedDomainsConfig $ @@ -316,12 +316,12 @@ testClassifiedDomainsDisabled = do getClassifiedDomainsFeatureConfig member expected testSimpleFlag :: - forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName). + forall (ps :: Public.IncludeLockStatus) (a :: Public.TeamFeatureName). ( HasCallStack, Typeable a, Public.FeatureHasNoConfig ps a, Public.KnownTeamFeatureName a, - FromJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a), + FromJSON (Public.TeamFeatureStatus 'Public.WithoutLockStatus a), ToJSON (Public.TeamFeatureStatus ps a) ) => Public.TeamFeatureStatusValue -> @@ -381,21 +381,21 @@ testSimpleFlag defaultValue = do testSelfDeletingMessages :: TestM () testSelfDeletingMessages = do -- personal users - let settingWithoutPaymentStatus :: TeamFeatureStatusValue -> Int32 -> Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureSelfDeletingMessages - settingWithoutPaymentStatus stat tout = + let settingWithoutLockStatus :: TeamFeatureStatusValue -> Int32 -> Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureSelfDeletingMessages + settingWithoutLockStatus stat tout = Public.TeamFeatureStatusWithConfig @Public.TeamFeatureSelfDeletingMessagesConfig stat (Public.TeamFeatureSelfDeletingMessagesConfig tout) - settingWithPaymentStatus :: TeamFeatureStatusValue -> Int32 -> Public.PaymentStatusValue -> Public.TeamFeatureStatus 'Public.WithPaymentStatus 'Public.TeamFeatureSelfDeletingMessages - settingWithPaymentStatus stat tout paymentStatus = - Public.TeamFeatureStatusWithConfigAndPaymentStatus @Public.TeamFeatureSelfDeletingMessagesConfig + settingWithLockStatus :: TeamFeatureStatusValue -> Int32 -> Public.LockStatusValue -> Public.TeamFeatureStatus 'Public.WithLockStatus 'Public.TeamFeatureSelfDeletingMessages + settingWithLockStatus stat tout lockStatus = + Public.TeamFeatureStatusWithConfigAndLockStatus @Public.TeamFeatureSelfDeletingMessagesConfig stat (Public.TeamFeatureSelfDeletingMessagesConfig tout) - paymentStatus + lockStatus personalUser <- Util.randomUser Util.getFeatureConfig Public.TeamFeatureSelfDeletingMessages personalUser - !!! responseJsonEither === const (Right $ settingWithPaymentStatus TeamFeatureEnabled 0 Public.PaymentLocked) + !!! responseJsonEither === const (Right $ settingWithLockStatus TeamFeatureEnabled 0 Public.Locked) -- team users galley <- view tsGalley @@ -404,16 +404,16 @@ testSelfDeletingMessages = do let checkSet :: TeamFeatureStatusValue -> Int32 -> Int -> TestM () checkSet stat tout expectedStatusCode = do - Util.putTeamFeatureFlagInternal @'Public.WithoutPaymentStatus @'Public.TeamFeatureSelfDeletingMessages + Util.putTeamFeatureFlagInternal @'Public.WithoutLockStatus @'Public.TeamFeatureSelfDeletingMessages galley tid - (settingWithoutPaymentStatus stat tout) + (settingWithoutLockStatus stat tout) !!! statusCode === const expectedStatusCode -- internal, public (/team/:tid/features), and team-agnostic (/feature-configs). - checkGet :: HasCallStack => TeamFeatureStatusValue -> Int32 -> Public.PaymentStatusValue -> TestM () - checkGet stat tout paymentStatus = do - let expected = settingWithPaymentStatus stat tout paymentStatus + checkGet :: HasCallStack => TeamFeatureStatusValue -> Int32 -> Public.LockStatusValue -> TestM () + checkGet stat tout lockStatus = do + let expected = settingWithLockStatus stat tout lockStatus forM_ [ Util.getTeamFeatureFlagInternal Public.TeamFeatureSelfDeletingMessages tid, Util.getTeamFeatureFlagWithGalley Public.TeamFeatureSelfDeletingMessages galley owner tid, @@ -421,30 +421,30 @@ testSelfDeletingMessages = do ] (!!! responseJsonEither === const (Right expected)) - checkSetPaymentStatus :: HasCallStack => Public.PaymentStatusValue -> TestM () - checkSetPaymentStatus status = + checkSetLockStatus :: HasCallStack => Public.LockStatusValue -> TestM () + checkSetLockStatus status = do - Util.setPaymentStatusInternal @'Public.TeamFeatureSelfDeletingMessages galley tid status + Util.setLockStatusInternal @'Public.TeamFeatureSelfDeletingMessages galley tid status !!! statusCode === const 200 - checkGet TeamFeatureEnabled 0 Public.PaymentLocked + checkGet TeamFeatureEnabled 0 Public.Locked checkSet TeamFeatureDisabled 0 409 - checkGet TeamFeatureEnabled 0 Public.PaymentLocked + checkGet TeamFeatureEnabled 0 Public.Locked checkSet TeamFeatureEnabled 30 409 - checkGet TeamFeatureEnabled 0 Public.PaymentLocked - checkSetPaymentStatus Public.PaymentUnlocked - checkGet TeamFeatureEnabled 0 Public.PaymentUnlocked + checkGet TeamFeatureEnabled 0 Public.Locked + checkSetLockStatus Public.Unlocked + checkGet TeamFeatureEnabled 0 Public.Unlocked checkSet TeamFeatureDisabled 0 200 - checkGet TeamFeatureDisabled 0 Public.PaymentUnlocked + checkGet TeamFeatureDisabled 0 Public.Unlocked checkSet TeamFeatureEnabled 30 200 - checkGet TeamFeatureEnabled 30 Public.PaymentUnlocked + checkGet TeamFeatureEnabled 30 Public.Unlocked checkSet TeamFeatureDisabled 30 200 - checkGet TeamFeatureDisabled 30 Public.PaymentUnlocked - checkSetPaymentStatus Public.PaymentLocked - checkGet TeamFeatureEnabled 0 Public.PaymentLocked + checkGet TeamFeatureDisabled 30 Public.Unlocked + checkSetLockStatus Public.Locked + checkGet TeamFeatureEnabled 0 Public.Locked checkSet TeamFeatureEnabled 50 409 - checkSetPaymentStatus Public.PaymentUnlocked - checkGet TeamFeatureDisabled 30 Public.PaymentUnlocked + checkSetLockStatus Public.Unlocked + checkGet TeamFeatureDisabled 30 Public.Unlocked -- | Call 'GET /teams/:tid/features' and 'GET /feature-configs', and check if all -- features are there. @@ -482,10 +482,10 @@ testAllFeatures = do toS TeamFeatureConferenceCalling .= Public.TeamFeatureStatusNoConfig confCalling, toS TeamFeatureSelfDeletingMessages - .= Public.TeamFeatureStatusWithConfigAndPaymentStatus @Public.TeamFeatureSelfDeletingMessagesConfig + .= Public.TeamFeatureStatusWithConfigAndLockStatus @Public.TeamFeatureSelfDeletingMessagesConfig TeamFeatureEnabled (Public.TeamFeatureSelfDeletingMessagesConfig 0) - Public.PaymentLocked + Public.Locked ] toS :: TeamFeatureName -> Text toS = TE.decodeUtf8 . toByteString' @@ -525,11 +525,11 @@ assertFlagForbidden res = do fmap label . responseJsonMaybe === const (Just "no-team-member") assertFlagNoConfig :: - forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName). + forall (ps :: Public.IncludeLockStatus) (a :: Public.TeamFeatureName). ( HasCallStack, Typeable a, Public.FeatureHasNoConfig ps a, - FromJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a), + FromJSON (Public.TeamFeatureStatus 'Public.WithoutLockStatus a), Public.KnownTeamFeatureName a ) => TestM ResponseLBS -> diff --git a/services/galley/test/integration/API/Teams/LegalHold.hs b/services/galley/test/integration/API/Teams/LegalHold.hs index 052ab80952..d44974b5f7 100644 --- a/services/galley/test/integration/API/Teams/LegalHold.hs +++ b/services/galley/test/integration/API/Teams/LegalHold.hs @@ -566,14 +566,14 @@ testEnablePerTeam = withTeam $ \owner tid -> do addTeamMemberInternal tid member (rolePermissions RoleMember) Nothing ensureQueueEmpty do - status :: Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureLegalHold <- responseJsonUnsafe <$> (getEnabled tid (getEnabled tid (getEnabled tid (getEnabled tid do @@ -585,7 +585,7 @@ testEnablePerTeam = withTeam $ \owner tid -> do liftIO $ assertEqual "User legal hold status should be enabled" UserLegalHoldEnabled status do putEnabled' id tid Public.TeamFeatureDisabled !!! testResponse 403 (Just "legalhold-whitelisted-only") - status :: Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureLegalHold <- responseJsonUnsafe <$> (getEnabled tid (getEnabled tid (getEnabled tid (getEnabled tid (getEnabled tid (getEnabled tid do @@ -554,7 +554,7 @@ testEnablePerTeam = do liftIO $ assertEqual "User legal hold status should be enabled" UserLegalHoldEnabled status do putEnabled tid Public.TeamFeatureDisabled -- disable again - status :: Public.TeamFeatureStatus 'Public.WithoutPaymentStatus 'Public.TeamFeatureLegalHold <- responseJsonUnsafe <$> (getEnabled tid (getEnabled tid (getEnabled tid (getEnabled tid (getEnabled tid (getEnabled tid TestM () putLegalHoldEnabledInternal' g tid statusValue = - void $ putTeamFeatureFlagInternal @'Public.WithoutPaymentStatus @'Public.TeamFeatureLegalHold g tid (Public.TeamFeatureStatusNoConfig statusValue) + void $ putTeamFeatureFlagInternal @'Public.WithoutLockStatus @'Public.TeamFeatureLegalHold g tid (Public.TeamFeatureStatusNoConfig statusValue) -------------------------------------------------------------------------------- @@ -151,7 +151,7 @@ getAllFeatureConfigsWithGalley galley uid = do . zUser uid putTeamFeatureFlagInternal :: - forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName). + forall (ps :: Public.IncludeLockStatus) (a :: Public.TeamFeatureName). ( HasCallStack, Public.KnownTeamFeatureName a, ToJSON (Public.TeamFeatureStatus ps a) @@ -165,7 +165,7 @@ putTeamFeatureFlagInternal reqmod tid status = do putTeamFeatureFlagInternalWithGalleyAndMod @ps @a g reqmod tid status putTeamFeatureFlagInternalWithGalleyAndMod :: - forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName) m. + forall (ps :: Public.IncludeLockStatus) (a :: Public.TeamFeatureName) m. ( MonadIO m, MonadHttp m, HasCallStack, @@ -184,19 +184,19 @@ putTeamFeatureFlagInternalWithGalleyAndMod galley reqmod tid status = . json status . reqmod -setPaymentStatusInternal :: +setLockStatusInternal :: forall (a :: Public.TeamFeatureName). ( HasCallStack, Public.KnownTeamFeatureName a, - ToJSON Public.PaymentStatusValue + ToJSON Public.LockStatusValue ) => (Request -> Request) -> TeamId -> - Public.PaymentStatusValue -> + Public.LockStatusValue -> TestM ResponseLBS -setPaymentStatusInternal reqmod tid paymentStatus = do +setLockStatusInternal reqmod tid lockStatus = do galley <- view tsGalley put $ galley - . paths ["i", "teams", toByteString' tid, "features", toByteString' (Public.knownTeamFeatureName @a), toByteString' paymentStatus] + . paths ["i", "teams", toByteString' tid, "features", toByteString' (Public.knownTeamFeatureName @a), toByteString' lockStatus] . reqmod diff --git a/services/spar/src/Spar/Intra/Galley.hs b/services/spar/src/Spar/Intra/Galley.hs index 53184e0e15..f4984b2b05 100644 --- a/services/spar/src/Spar/Intra/Galley.hs +++ b/services/spar/src/Spar/Intra/Galley.hs @@ -32,7 +32,7 @@ import Network.HTTP.Types.Method import Spar.Error import qualified System.Logger.Class as Log import Wire.API.Team.Feature - ( IncludePaymentStatus (..), + ( IncludeLockStatus (..), TeamFeatureName (..), TeamFeatureStatus, TeamFeatureStatusNoConfig (..), @@ -94,7 +94,7 @@ isEmailValidationEnabledTeam tid = do resp <- call $ method GET . paths ["i", "teams", toByteString' tid, "features", "validateSAMLemails"] pure ( (statusCode resp == 200) - && ( responseJsonMaybe @(TeamFeatureStatus 'WithoutPaymentStatus 'TeamFeatureValidateSAMLEmails) resp + && ( responseJsonMaybe @(TeamFeatureStatus 'WithoutLockStatus 'TeamFeatureValidateSAMLEmails) resp == Just (TeamFeatureStatusNoConfig TeamFeatureEnabled) ) ) diff --git a/tools/stern/src/Stern/API.hs b/tools/stern/src/Stern/API.hs index fe27d5e3fa..ead623edff 100644 --- a/tools/stern/src/Stern/API.hs +++ b/tools/stern/src/Stern/API.hs @@ -594,25 +594,25 @@ getTeamAdminInfo = liftM (json . toAdminInfo) . Intra.getTeamInfo getTeamFeatureFlagH :: forall (a :: Public.TeamFeatureName). ( Public.KnownTeamFeatureName a, - FromJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a), - ToJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a), - Typeable (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) + FromJSON (Public.TeamFeatureStatus 'Public.WithoutLockStatus a), + ToJSON (Public.TeamFeatureStatus 'Public.WithoutLockStatus a), + Typeable (Public.TeamFeatureStatus 'Public.WithoutLockStatus a) ) => TeamId -> Handler Response getTeamFeatureFlagH tid = - json <$> Intra.getTeamFeatureFlag @'Public.WithoutPaymentStatus @a tid + json <$> Intra.getTeamFeatureFlag @'Public.WithoutLockStatus @a tid setTeamFeatureFlagH :: forall (a :: Public.TeamFeatureName). ( Public.KnownTeamFeatureName a, - FromJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a), - ToJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) + FromJSON (Public.TeamFeatureStatus 'Public.WithoutLockStatus a), + ToJSON (Public.TeamFeatureStatus 'Public.WithoutLockStatus a) ) => - TeamId ::: JsonRequest (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) ::: JSON -> + TeamId ::: JsonRequest (Public.TeamFeatureStatus 'Public.WithoutLockStatus a) ::: JSON -> Handler Response setTeamFeatureFlagH (tid ::: req ::: _) = do - status :: Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a <- parseBody req !>> mkError status400 "client-error" + status :: Public.TeamFeatureStatus 'Public.WithoutLockStatus a <- parseBody req !>> mkError status400 "client-error" empty <$ Intra.setTeamFeatureFlag @a tid status getTeamFeatureFlagNoConfigH :: @@ -755,9 +755,9 @@ noSuchUser = ifNothing (mkError status404 "no-user" "No such user") mkFeaturePutGetRoute :: forall (a :: Public.TeamFeatureName). ( Public.KnownTeamFeatureName a, - FromJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a), - ToJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a), - Typeable (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) + FromJSON (Public.TeamFeatureStatus 'Public.WithoutLockStatus a), + ToJSON (Public.TeamFeatureStatus 'Public.WithoutLockStatus a), + Typeable (Public.TeamFeatureStatus 'Public.WithoutLockStatus a) ) => Routes Doc.ApiBuilder Handler () mkFeaturePutGetRoute = do @@ -774,7 +774,7 @@ mkFeaturePutGetRoute = do put ("/teams/:tid/features/" <> toByteString' featureName) (continue (setTeamFeatureFlagH @a)) $ capture "tid" - .&. jsonRequest @(Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) + .&. jsonRequest @(Public.TeamFeatureStatus 'Public.WithoutLockStatus a) .&. accept "application" "json" document "PUT" "setTeamFeatureFlag" $ do summary "Disable / enable feature flag for a given team" diff --git a/tools/stern/src/Stern/Intra.hs b/tools/stern/src/Stern/Intra.hs index 4f8ffde988..2139f16750 100644 --- a/tools/stern/src/Stern/Intra.hs +++ b/tools/stern/src/Stern/Intra.hs @@ -452,7 +452,7 @@ setBlacklistStatus status emailOrPhone = do statusToMethod True = POST getTeamFeatureFlag :: - forall (ps :: Public.IncludePaymentStatus) (a :: Public.TeamFeatureName). + forall (ps :: Public.IncludeLockStatus) (a :: Public.TeamFeatureName). ( Public.KnownTeamFeatureName a, Typeable (Public.TeamFeatureStatus ps a), FromJSON (Public.TeamFeatureStatus ps a) @@ -474,10 +474,10 @@ getTeamFeatureFlag tid = do setTeamFeatureFlag :: forall (a :: Public.TeamFeatureName). ( Public.KnownTeamFeatureName a, - ToJSON (Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a) + ToJSON (Public.TeamFeatureStatus 'Public.WithoutLockStatus a) ) => TeamId -> - Public.TeamFeatureStatus 'Public.WithoutPaymentStatus a -> + Public.TeamFeatureStatus 'Public.WithoutLockStatus a -> Handler () setTeamFeatureFlag tid status = do info $ msg "Setting team feature status" From 56d787bcbea6801d36f62bcc6c0abd87ec2c9db4 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Thu, 25 Nov 2021 10:04:56 +0100 Subject: [PATCH 26/28] Make default behavior on-prem-compatible. --- changelog.d/0-release-notes/pr-1937 | 1 + libs/wire-api/src/Wire/API/Team/Feature.hs | 2 +- .../galley/src/Galley/API/Teams/Features.hs | 24 ++++++++++++------- .../test/integration/API/Teams/Feature.hs | 21 ++++++++++++++-- 4 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 changelog.d/0-release-notes/pr-1937 diff --git a/changelog.d/0-release-notes/pr-1937 b/changelog.d/0-release-notes/pr-1937 new file mode 100644 index 0000000000..85e7a39820 --- /dev/null +++ b/changelog.d/0-release-notes/pr-1937 @@ -0,0 +1 @@ +If you have `selfDeletingMessages` configured in `galley.yaml`, add `lockStatus: unlocked`. diff --git a/libs/wire-api/src/Wire/API/Team/Feature.hs b/libs/wire-api/src/Wire/API/Team/Feature.hs index 32b4f5f505..aa1bdc8972 100644 --- a/libs/wire-api/src/Wire/API/Team/Feature.hs +++ b/libs/wire-api/src/Wire/API/Team/Feature.hs @@ -490,7 +490,7 @@ defaultSelfDeletingMessagesStatus = TeamFeatureStatusWithConfigAndLockStatus TeamFeatureEnabled (TeamFeatureSelfDeletingMessagesConfig 0) - Locked + Unlocked ---------------------------------------------------------------------- -- LockStatus diff --git a/services/galley/src/Galley/API/Teams/Features.hs b/services/galley/src/Galley/API/Teams/Features.hs index f0249377b5..9c1650a29b 100644 --- a/services/galley/src/Galley/API/Teams/Features.hs +++ b/services/galley/src/Galley/API/Teams/Features.hs @@ -575,23 +575,29 @@ setConferenceCallingInternal = setFeatureStatusNoConfig @'Public.WithoutLockStatus @'Public.TeamFeatureConferenceCalling $ \_status _tid -> pure () getSelfDeletingMessagesInternal :: - Member TeamFeatureStore r => + forall r. + ( Member (Input Opts) r, + Member TeamFeatureStore r + ) => GetFeatureInternalParam -> Sem r (Public.TeamFeatureStatus 'Public.WithLockStatus 'Public.TeamFeatureSelfDeletingMessages) getSelfDeletingMessagesInternal = \case - Left _ -> pure Public.defaultSelfDeletingMessagesStatus + Left _ -> getCfgDefault Right tid -> do - (maybeFeatureStatus, maybeLockStatus) <- TeamFeatures.getSelfDeletingMessagesStatus tid - pure $ case (maybeLockStatus, maybeFeatureStatus) of - (Just Public.Unlocked, Just featureStatus) -> + cfgDefault <- getCfgDefault + let defLockStatus = Public.tfwcapsLockStatus cfgDefault + (maybeFeatureStatus, fromMaybe defLockStatus -> lockStatus) <- TeamFeatures.getSelfDeletingMessagesStatus tid + pure $ case (lockStatus, maybeFeatureStatus) of + (Public.Unlocked, Just featureStatus) -> Public.TeamFeatureStatusWithConfigAndLockStatus (Public.tfwcStatus featureStatus) (Public.tfwcConfig featureStatus) Public.Unlocked - (Just Public.Unlocked, Nothing) -> - Public.defaultSelfDeletingMessagesStatus {Public.tfwcapsLockStatus = Public.Unlocked} - (Just Public.Locked, _) -> Public.defaultSelfDeletingMessagesStatus - (Nothing, _) -> Public.defaultSelfDeletingMessagesStatus + (Public.Unlocked, Nothing) -> cfgDefault {Public.tfwcapsLockStatus = Public.Unlocked} + (Public.Locked, _) -> cfgDefault {Public.tfwcapsLockStatus = Public.Locked} + where + getCfgDefault :: Sem r (Public.TeamFeatureStatusWithConfigAndLockStatus Public.TeamFeatureSelfDeletingMessagesConfig) + getCfgDefault = input <&> view (optSettings . setFeatureFlags . flagSelfDeletingMessages . unDefaults) setSelfDeletingMessagesInternal :: Members diff --git a/services/galley/test/integration/API/Teams/Feature.hs b/services/galley/test/integration/API/Teams/Feature.hs index 0c3d293b9c..1d94054f71 100644 --- a/services/galley/test/integration/API/Teams/Feature.hs +++ b/services/galley/test/integration/API/Teams/Feature.hs @@ -22,7 +22,7 @@ import qualified API.Util as Util import qualified API.Util.TeamFeature as Util import Bilge import Bilge.Assert -import Control.Lens (over, view) +import Control.Lens (over, to, view) import Control.Monad.Catch (MonadCatch) import Data.Aeson (FromJSON, ToJSON, object, (.=)) import qualified Data.Aeson as Aeson @@ -380,6 +380,16 @@ testSimpleFlag defaultValue = do testSelfDeletingMessages :: TestM () testSelfDeletingMessages = do + defLockStatus :: Public.LockStatusValue <- + view + ( tsGConf + . optSettings + . setFeatureFlags + . flagSelfDeletingMessages + . unDefaults + . to Public.tfwcapsLockStatus + ) + -- personal users let settingWithoutLockStatus :: TeamFeatureStatusValue -> Int32 -> Public.TeamFeatureStatus 'Public.WithoutLockStatus 'Public.TeamFeatureSelfDeletingMessages settingWithoutLockStatus stat tout = @@ -395,7 +405,7 @@ testSelfDeletingMessages = do personalUser <- Util.randomUser Util.getFeatureConfig Public.TeamFeatureSelfDeletingMessages personalUser - !!! responseJsonEither === const (Right $ settingWithLockStatus TeamFeatureEnabled 0 Public.Locked) + !!! responseJsonEither === const (Right $ settingWithLockStatus TeamFeatureEnabled 0 defLockStatus) -- team users galley <- view tsGalley @@ -427,6 +437,13 @@ testSelfDeletingMessages = do Util.setLockStatusInternal @'Public.TeamFeatureSelfDeletingMessages galley tid status !!! statusCode === const 200 + -- test that the default lock status comes from `galley.yaml`. + -- use this to change `galley.integration.yaml` locally and manually test that conf file + -- parsing works as expected. + checkGet TeamFeatureEnabled 0 defLockStatus + + -- now don't worry about what's in the config, write something to cassandra, and test with that. + checkSetLockStatus Public.Locked checkGet TeamFeatureEnabled 0 Public.Locked checkSet TeamFeatureDisabled 0 409 checkGet TeamFeatureEnabled 0 Public.Locked From 9cb5dcd98d4225bd422c05644a47bd2a6dbf2e65 Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Thu, 25 Nov 2021 16:36:51 +0100 Subject: [PATCH 27/28] fix integrationtest, regenerate cql docs --- docs/reference/cassandra-schema.cql | 1 + .../test/integration/API/Teams/Feature.hs | 20 ++++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/docs/reference/cassandra-schema.cql b/docs/reference/cassandra-schema.cql index ddecfdc218..43505d0d58 100644 --- a/docs/reference/cassandra-schema.cql +++ b/docs/reference/cassandra-schema.cql @@ -1798,3 +1798,4 @@ CREATE TABLE spar_test.user ( AND min_index_interval = 128 AND read_repair_chance = 0.0 AND speculative_retry = '99PERCENTILE'; + diff --git a/services/galley/test/integration/API/Teams/Feature.hs b/services/galley/test/integration/API/Teams/Feature.hs index 1d94054f71..15879c948e 100644 --- a/services/galley/test/integration/API/Teams/Feature.hs +++ b/services/galley/test/integration/API/Teams/Feature.hs @@ -467,20 +467,30 @@ testSelfDeletingMessages = do -- features are there. testAllFeatures :: TestM () testAllFeatures = do + defLockStatus :: Public.LockStatusValue <- + view + ( tsGConf + . optSettings + . setFeatureFlags + . flagSelfDeletingMessages + . unDefaults + . to Public.tfwcapsLockStatus + ) + (_owner, tid, member : _) <- Util.createBindingTeamWithNMembers 1 Util.getAllTeamFeatures member tid !!! do statusCode === const 200 - responseJsonMaybe === const (Just (expected TeamFeatureEnabled {- determined by default in galley -})) + responseJsonMaybe === const (Just (expected TeamFeatureEnabled defLockStatus {- determined by default in galley -})) Util.getAllTeamFeaturesPersonal member !!! do statusCode === const 200 - responseJsonMaybe === const (Just (expected TeamFeatureEnabled {- determined by default in galley -})) + responseJsonMaybe === const (Just (expected TeamFeatureEnabled defLockStatus{- determined by default in galley -})) randomPersonalUser <- Util.randomUser Util.getAllTeamFeaturesPersonal randomPersonalUser !!! do statusCode === const 200 - responseJsonMaybe === const (Just (expected TeamFeatureEnabled {- determined by 'getAfcConferenceCallingDefNew' in brig -})) + responseJsonMaybe === const (Just (expected TeamFeatureEnabled defLockStatus{- determined by 'getAfcConferenceCallingDefNew' in brig -})) where - expected confCalling = + expected confCalling lockState = object [ toS TeamFeatureLegalHold .= Public.TeamFeatureStatusNoConfig TeamFeatureDisabled, toS TeamFeatureSSO .= Public.TeamFeatureStatusNoConfig TeamFeatureDisabled, @@ -502,7 +512,7 @@ testAllFeatures = do .= Public.TeamFeatureStatusWithConfigAndLockStatus @Public.TeamFeatureSelfDeletingMessagesConfig TeamFeatureEnabled (Public.TeamFeatureSelfDeletingMessagesConfig 0) - Public.Locked + lockState ] toS :: TeamFeatureName -> Text toS = TE.decodeUtf8 . toByteString' From 7369d682ad43b3ac69e848d039f20cbcfef85b07 Mon Sep 17 00:00:00 2001 From: Leif Battermann Date: Thu, 25 Nov 2021 17:04:27 +0100 Subject: [PATCH 28/28] formatting --- services/galley/test/integration/API/Teams/Feature.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/galley/test/integration/API/Teams/Feature.hs b/services/galley/test/integration/API/Teams/Feature.hs index 15879c948e..ba2a64110d 100644 --- a/services/galley/test/integration/API/Teams/Feature.hs +++ b/services/galley/test/integration/API/Teams/Feature.hs @@ -483,12 +483,12 @@ testAllFeatures = do responseJsonMaybe === const (Just (expected TeamFeatureEnabled defLockStatus {- determined by default in galley -})) Util.getAllTeamFeaturesPersonal member !!! do statusCode === const 200 - responseJsonMaybe === const (Just (expected TeamFeatureEnabled defLockStatus{- determined by default in galley -})) + responseJsonMaybe === const (Just (expected TeamFeatureEnabled defLockStatus {- determined by default in galley -})) randomPersonalUser <- Util.randomUser Util.getAllTeamFeaturesPersonal randomPersonalUser !!! do statusCode === const 200 - responseJsonMaybe === const (Just (expected TeamFeatureEnabled defLockStatus{- determined by 'getAfcConferenceCallingDefNew' in brig -})) + responseJsonMaybe === const (Just (expected TeamFeatureEnabled defLockStatus {- determined by 'getAfcConferenceCallingDefNew' in brig -})) where expected confCalling lockState = object