Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelog.d/5-internal/feature-singletons
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Use feature singletons in TeamFeatureStore

49 changes: 44 additions & 5 deletions libs/wire-api/src/Wire/API/Team/Feature.hs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ module Wire.API.Team.Feature
defFeatureStatusNoLock,
computeFeatureConfigForTeamUser,
IsFeatureConfig (..),
FeatureSingleton (..),
FeatureTrivialConfig (..),
HasDeprecatedFeatureName (..),
LockStatusResponse (..),
Expand Down Expand Up @@ -124,15 +125,16 @@ import Wire.Arbitrary (Arbitrary, GenericUniform (..))
-- 1. Add a data type for your feature's "config" part, naming convention:
-- **<NameOfFeature>Config**. If your feature doesn't have a config besides
-- being enabled/disabled, locked/unlocked, then the config should be a unit
-- type, e.g. **data MyFeatureConfig = MyFeatureConfig**. Implement type classes
-- 'ToSchema', 'IsFeatureConfig' and 'Arbitrary'. If your feature doesn't have a
-- config implement 'FeatureTrivialConfig'.
-- type, e.g. **data MyFeatureConfig = MyFeatureConfig**. Add a singleton for
-- the new data type. Implement type classes 'ToSchema', 'IsFeatureConfig' and
-- 'Arbitrary'. If your feature doesn't have a config implement
-- 'FeatureTrivialConfig'.
--
-- 2. Add the config to to 'AllFeatureConfigs'.
--
-- 3. If your feature is configurable on a per-team basis, add a schema
-- migration in galley and add 'FeatureStatusCassandra' instance in
-- Galley.Cassandra.TeamFeatures together with a schema migration
-- migration in galley and extend 'getFeatureStatus' and similar functions in
-- Galley.Cassandra.TeamFeatures
--
-- 4. Add the feature to the config schema of galley in Galley.Types.Teams.
-- and extend the Arbitrary instance of FeatureConfigs in the unit tests Test.Galley.Types
Expand Down Expand Up @@ -167,13 +169,33 @@ import Wire.Arbitrary (Arbitrary, GenericUniform (..))
class IsFeatureConfig cfg where
type FeatureSymbol cfg :: Symbol
defFeatureStatus :: WithStatus cfg
featureSingleton :: FeatureSingleton cfg

objectSchema ::
-- | Should be "pure MyFeatureConfig" if the feature doesn't have config,
-- which results in a trivial empty schema and the "config" field being
-- omitted/ignored in the JSON encoder / parser.
ObjectSchema SwaggerDoc cfg

data FeatureSingleton cfg where
FeatureSingletonGuestLinksConfig :: FeatureSingleton GuestLinksConfig
FeatureSingletonLegalholdConfig :: FeatureSingleton LegalholdConfig
FeatureSingletonSSOConfig :: FeatureSingleton SSOConfig
FeatureSingletonSearchVisibilityAvailableConfig :: FeatureSingleton SearchVisibilityAvailableConfig
FeatureSingletonValidateSAMLEmailsConfig :: FeatureSingleton ValidateSAMLEmailsConfig
FeatureSingletonDigitalSignaturesConfig :: FeatureSingleton DigitalSignaturesConfig
FeatureSingletonConferenceCallingConfig :: FeatureSingleton ConferenceCallingConfig
FeatureSingletonSndFactorPasswordChallengeConfig :: FeatureSingleton SndFactorPasswordChallengeConfig
FeatureSingletonSearchVisibilityInboundConfig :: FeatureSingleton SearchVisibilityInboundConfig
FeatureSingletonClassifiedDomainsConfig :: FeatureSingleton ClassifiedDomainsConfig
FeatureSingletonAppLockConfig :: FeatureSingleton AppLockConfig
FeatureSingletonSelfDeletingMessagesConfig :: FeatureSingleton SelfDeletingMessagesConfig
FeatureSingletonFileSharingConfig :: FeatureSingleton FileSharingConfig
FeatureSingletonMLSConfig :: FeatureSingleton MLSConfig
FeatureSingletonExposeInvitationURLsToTeamAdminConfig :: FeatureSingleton ExposeInvitationURLsToTeamAdminConfig
FeatureSingletonOutlookCalIntegrationConfig :: FeatureSingleton OutlookCalIntegrationConfig
FeatureSingletonMlsE2EIdConfig :: FeatureSingleton MlsE2EIdConfig

class FeatureTrivialConfig cfg where
trivialConfig :: cfg

Expand Down Expand Up @@ -552,6 +574,7 @@ instance ToSchema GuestLinksConfig where
instance IsFeatureConfig GuestLinksConfig where
type FeatureSymbol GuestLinksConfig = "conversationGuestLinks"
defFeatureStatus = withStatus FeatureStatusEnabled LockStatusUnlocked GuestLinksConfig FeatureTTLUnlimited
featureSingleton = FeatureSingletonGuestLinksConfig

objectSchema = pure GuestLinksConfig

Expand All @@ -568,6 +591,7 @@ data LegalholdConfig = LegalholdConfig
instance IsFeatureConfig LegalholdConfig where
type FeatureSymbol LegalholdConfig = "legalhold"
defFeatureStatus = withStatus FeatureStatusDisabled LockStatusUnlocked LegalholdConfig FeatureTTLUnlimited
featureSingleton = FeatureSingletonLegalholdConfig
objectSchema = pure LegalholdConfig

instance ToSchema LegalholdConfig where
Expand All @@ -586,6 +610,7 @@ data SSOConfig = SSOConfig
instance IsFeatureConfig SSOConfig where
type FeatureSymbol SSOConfig = "sso"
defFeatureStatus = withStatus FeatureStatusDisabled LockStatusUnlocked SSOConfig FeatureTTLUnlimited
featureSingleton = FeatureSingletonSSOConfig
objectSchema = pure SSOConfig

instance ToSchema SSOConfig where
Expand All @@ -606,6 +631,7 @@ data SearchVisibilityAvailableConfig = SearchVisibilityAvailableConfig
instance IsFeatureConfig SearchVisibilityAvailableConfig where
type FeatureSymbol SearchVisibilityAvailableConfig = "searchVisibility"
defFeatureStatus = withStatus FeatureStatusDisabled LockStatusUnlocked SearchVisibilityAvailableConfig FeatureTTLUnlimited
featureSingleton = FeatureSingletonSearchVisibilityAvailableConfig
objectSchema = pure SearchVisibilityAvailableConfig

instance ToSchema SearchVisibilityAvailableConfig where
Expand All @@ -630,6 +656,7 @@ instance ToSchema ValidateSAMLEmailsConfig where
instance IsFeatureConfig ValidateSAMLEmailsConfig where
type FeatureSymbol ValidateSAMLEmailsConfig = "validateSAMLemails"
defFeatureStatus = withStatus FeatureStatusEnabled LockStatusUnlocked ValidateSAMLEmailsConfig FeatureTTLUnlimited
featureSingleton = FeatureSingletonValidateSAMLEmailsConfig
objectSchema = pure ValidateSAMLEmailsConfig

instance HasDeprecatedFeatureName ValidateSAMLEmailsConfig where
Expand All @@ -648,6 +675,7 @@ data DigitalSignaturesConfig = DigitalSignaturesConfig
instance IsFeatureConfig DigitalSignaturesConfig where
type FeatureSymbol DigitalSignaturesConfig = "digitalSignatures"
defFeatureStatus = withStatus FeatureStatusDisabled LockStatusUnlocked DigitalSignaturesConfig FeatureTTLUnlimited
featureSingleton = FeatureSingletonDigitalSignaturesConfig
objectSchema = pure DigitalSignaturesConfig

instance HasDeprecatedFeatureName DigitalSignaturesConfig where
Expand All @@ -669,6 +697,7 @@ data ConferenceCallingConfig = ConferenceCallingConfig
instance IsFeatureConfig ConferenceCallingConfig where
type FeatureSymbol ConferenceCallingConfig = "conferenceCalling"
defFeatureStatus = withStatus FeatureStatusEnabled LockStatusUnlocked ConferenceCallingConfig FeatureTTLUnlimited
featureSingleton = FeatureSingletonConferenceCallingConfig
objectSchema = pure ConferenceCallingConfig

instance ToSchema ConferenceCallingConfig where
Expand All @@ -690,6 +719,7 @@ instance ToSchema SndFactorPasswordChallengeConfig where
instance IsFeatureConfig SndFactorPasswordChallengeConfig where
type FeatureSymbol SndFactorPasswordChallengeConfig = "sndFactorPasswordChallenge"
defFeatureStatus = withStatus FeatureStatusDisabled LockStatusLocked SndFactorPasswordChallengeConfig FeatureTTLUnlimited
featureSingleton = FeatureSingletonSndFactorPasswordChallengeConfig
objectSchema = pure SndFactorPasswordChallengeConfig

instance FeatureTrivialConfig SndFactorPasswordChallengeConfig where
Expand All @@ -706,6 +736,7 @@ data SearchVisibilityInboundConfig = SearchVisibilityInboundConfig
instance IsFeatureConfig SearchVisibilityInboundConfig where
type FeatureSymbol SearchVisibilityInboundConfig = "searchVisibilityInbound"
defFeatureStatus = withStatus FeatureStatusDisabled LockStatusUnlocked SearchVisibilityInboundConfig FeatureTTLUnlimited
featureSingleton = FeatureSingletonSearchVisibilityInboundConfig
objectSchema = pure SearchVisibilityInboundConfig

instance ToSchema SearchVisibilityInboundConfig where
Expand Down Expand Up @@ -740,6 +771,7 @@ instance IsFeatureConfig ClassifiedDomainsConfig where
LockStatusUnlocked
(ClassifiedDomainsConfig [])
FeatureTTLUnlimited
featureSingleton = FeatureSingletonClassifiedDomainsConfig
objectSchema = field "config" schema

----------------------------------------------------------------------
Expand Down Expand Up @@ -769,6 +801,7 @@ instance IsFeatureConfig AppLockConfig where
LockStatusUnlocked
(AppLockConfig (EnforceAppLock False) 60)
FeatureTTLUnlimited
featureSingleton = FeatureSingletonAppLockConfig
objectSchema = field "config" schema

newtype EnforceAppLock = EnforceAppLock Bool
Expand All @@ -789,6 +822,7 @@ data FileSharingConfig = FileSharingConfig
instance IsFeatureConfig FileSharingConfig where
type FeatureSymbol FileSharingConfig = "fileSharing"
defFeatureStatus = withStatus FeatureStatusEnabled LockStatusUnlocked FileSharingConfig FeatureTTLUnlimited
featureSingleton = FeatureSingletonFileSharingConfig
objectSchema = pure FileSharingConfig

instance ToSchema FileSharingConfig where
Expand Down Expand Up @@ -821,6 +855,7 @@ instance IsFeatureConfig SelfDeletingMessagesConfig where
LockStatusUnlocked
(SelfDeletingMessagesConfig 0)
FeatureTTLUnlimited
featureSingleton = FeatureSingletonSelfDeletingMessagesConfig
objectSchema = field "config" schema

----------------------------------------------------------------------
Expand Down Expand Up @@ -849,6 +884,7 @@ instance IsFeatureConfig MLSConfig where
defFeatureStatus =
let config = MLSConfig [] ProtocolProteusTag [MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519] MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519
in withStatus FeatureStatusDisabled LockStatusUnlocked config FeatureTTLUnlimited
featureSingleton = FeatureSingletonMLSConfig
objectSchema = field "config" schema

----------------------------------------------------------------------
Expand All @@ -861,6 +897,7 @@ data ExposeInvitationURLsToTeamAdminConfig = ExposeInvitationURLsToTeamAdminConf
instance IsFeatureConfig ExposeInvitationURLsToTeamAdminConfig where
type FeatureSymbol ExposeInvitationURLsToTeamAdminConfig = "exposeInvitationURLsToTeamAdmin"
defFeatureStatus = withStatus FeatureStatusDisabled LockStatusLocked ExposeInvitationURLsToTeamAdminConfig FeatureTTLUnlimited
featureSingleton = FeatureSingletonExposeInvitationURLsToTeamAdminConfig
objectSchema = pure ExposeInvitationURLsToTeamAdminConfig

instance ToSchema ExposeInvitationURLsToTeamAdminConfig where
Expand All @@ -881,6 +918,7 @@ data OutlookCalIntegrationConfig = OutlookCalIntegrationConfig
instance IsFeatureConfig OutlookCalIntegrationConfig where
type FeatureSymbol OutlookCalIntegrationConfig = "outlookCalIntegration"
defFeatureStatus = withStatus FeatureStatusDisabled LockStatusLocked OutlookCalIntegrationConfig FeatureTTLUnlimited
featureSingleton = FeatureSingletonOutlookCalIntegrationConfig
objectSchema = pure OutlookCalIntegrationConfig

instance ToSchema OutlookCalIntegrationConfig where
Expand Down Expand Up @@ -938,6 +976,7 @@ instance IsFeatureConfig MlsE2EIdConfig where
defFeatureStatus = withStatus FeatureStatusDisabled LockStatusUnlocked defValue FeatureTTLUnlimited
where
defValue = MlsE2EIdConfig (fromIntegral @Int (60 * 60 * 24)) Nothing
featureSingleton = FeatureSingletonMlsE2EIdConfig
objectSchema = field "config" schema

----------------------------------------------------------------------
Expand Down
Loading