67
67
import qualified Cassandra.CQL as Cass
68
68
import Control.Lens (makeLenses , (?~) )
69
69
import qualified Data.Aeson as A
70
+ import qualified Data.Aeson.Types as A
70
71
import qualified Data.Attoparsec.ByteString as Parser
71
72
import Data.ByteString.Conversion
72
73
import qualified Data.ByteString.UTF8 as UTF8
@@ -75,6 +76,7 @@ import Data.Either.Extra (maybeToEither)
75
76
import Data.Id
76
77
import Data.Proxy
77
78
import Data.Schema
79
+ import Data.Scientific (toBoundedInteger )
78
80
import Data.String.Conversions (cs )
79
81
import qualified Data.Swagger as S
80
82
import qualified Data.Swagger.Build.Api as Doc
@@ -162,13 +164,14 @@ featureNameBS = UTF8.fromString $ symbolVal (Proxy @(FeatureSymbol cfg))
162
164
data WithStatus (cfg :: * ) = WithStatus
163
165
{ wsStatus :: FeatureStatus ,
164
166
wsLockStatus :: LockStatus ,
165
- wsConfig :: cfg
167
+ wsConfig :: cfg ,
168
+ wsTTL :: FeatureTTL
166
169
}
167
170
deriving stock (Eq , Show , Generic , Typeable , Functor )
168
171
deriving (ToJSON , FromJSON , S.ToSchema ) via (Schema (WithStatus cfg ))
169
172
170
173
instance Arbitrary cfg => Arbitrary (WithStatus cfg ) where
171
- arbitrary = WithStatus <$> arbitrary <*> arbitrary <*> arbitrary
174
+ arbitrary = WithStatus <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
172
175
173
176
instance (ToSchema cfg , IsFeatureConfig cfg ) => ToSchema (WithStatus cfg ) where
174
177
schema =
@@ -177,6 +180,7 @@ instance (ToSchema cfg, IsFeatureConfig cfg) => ToSchema (WithStatus cfg) where
177
180
<$> wsStatus .= field " status" schema
178
181
<*> wsLockStatus .= field " lockStatus" schema
179
182
<*> wsConfig .= objectSchema @ cfg
183
+ <*> wsTTL .= field " ttl" schema
180
184
where
181
185
inner = schema @ cfg
182
186
name = fromMaybe " " (getName (schemaDoc inner)) <> " .WithStatus"
@@ -200,19 +204,20 @@ withStatusModel =
200
204
201
205
data WithStatusNoLock (cfg :: * ) = WithStatusNoLock
202
206
{ wssStatus :: FeatureStatus ,
203
- wssConfig :: cfg
207
+ wssConfig :: cfg ,
208
+ wssTTL :: FeatureTTL
204
209
}
205
210
deriving stock (Eq , Show , Generic , Typeable , Functor )
206
211
deriving (ToJSON , FromJSON , S.ToSchema ) via (Schema (WithStatusNoLock cfg ))
207
212
208
213
instance Arbitrary cfg => Arbitrary (WithStatusNoLock cfg ) where
209
- arbitrary = WithStatusNoLock <$> arbitrary <*> arbitrary
214
+ arbitrary = WithStatusNoLock <$> arbitrary <*> arbitrary <*> arbitrary
210
215
211
216
forgetLock :: WithStatus a -> WithStatusNoLock a
212
- forgetLock WithStatus {.. } = WithStatusNoLock wsStatus wsConfig
217
+ forgetLock WithStatus {.. } = WithStatusNoLock wsStatus wsConfig wsTTL
213
218
214
219
withLockStatus :: LockStatus -> WithStatusNoLock a -> WithStatus a
215
- withLockStatus ls (WithStatusNoLock s c) = WithStatus s ls c
220
+ withLockStatus ls (WithStatusNoLock s c ttl ) = WithStatus s ls c ttl
216
221
217
222
withUnlocked :: WithStatusNoLock a -> WithStatus a
218
223
withUnlocked = withLockStatus LockStatusUnlocked
@@ -226,6 +231,7 @@ instance (ToSchema cfg, IsFeatureConfig cfg) => ToSchema (WithStatusNoLock cfg)
226
231
WithStatusNoLock
227
232
<$> wssStatus .= field " status" schema
228
233
<*> wssConfig .= objectSchema @ cfg
234
+ <*> wssTTL .= field " ttl" schema
229
235
where
230
236
inner = schema @ cfg
231
237
name = fromMaybe " " (getName (schemaDoc inner)) <> " .WithStatusNoLock"
@@ -255,6 +261,35 @@ data FeatureTTL
255
261
deriving stock (Eq , Show , Generic )
256
262
deriving (Arbitrary ) via (GenericUniform FeatureTTL )
257
263
264
+ instance ToSchema FeatureTTL where
265
+ schema = mkSchema ttlDoc toTTL fromTTL
266
+ where
267
+ ttlDoc :: NamedSwaggerDoc
268
+ ttlDoc = swaggerDoc @ Word & S. schema . S. example ?~ " unlimited"
269
+
270
+ toTTL :: A. Value -> A. Parser FeatureTTL
271
+ toTTL v = parseUnlimited v <|> parseSeconds v
272
+
273
+ parseUnlimited :: A. Value -> A. Parser FeatureTTL
274
+ parseUnlimited =
275
+ A. withText " FeatureTTL" $
276
+ \ t ->
277
+ if t == " unlimited" || t == " 0"
278
+ then pure FeatureTTLUnlimited
279
+ else A. parseFail " Expected ''unlimited' or '0'."
280
+
281
+ parseSeconds :: A. Value -> A. Parser FeatureTTL
282
+ parseSeconds = A. withScientific " FeatureTTL" $
283
+ \ s -> case toBoundedInteger s of
284
+ Just 0 -> pure FeatureTTLUnlimited
285
+ Just i -> pure . FeatureTTLSeconds $ i
286
+ Nothing -> A. parseFail " Expected an integer."
287
+
288
+ fromTTL :: FeatureTTL -> Maybe A. Value
289
+ fromTTL FeatureTTLUnlimited = Just " unlimited"
290
+ fromTTL (FeatureTTLSeconds 0 ) = Just " unlimited"
291
+ fromTTL (FeatureTTLSeconds s) = A. decode . toByteString $ s
292
+
258
293
instance ToHttpApiData FeatureTTL where
259
294
toQueryParam = T. decodeUtf8 . toByteString'
260
295
@@ -441,7 +476,7 @@ instance ToSchema GuestLinksConfig where
441
476
442
477
instance IsFeatureConfig GuestLinksConfig where
443
478
type FeatureSymbol GuestLinksConfig = " conversationGuestLinks"
444
- defFeatureStatus = WithStatus FeatureStatusEnabled LockStatusUnlocked GuestLinksConfig
479
+ defFeatureStatus = WithStatus FeatureStatusEnabled LockStatusUnlocked GuestLinksConfig FeatureTTLUnlimited
445
480
objectSchema = pure GuestLinksConfig
446
481
447
482
instance FeatureTrivialConfig GuestLinksConfig where
@@ -456,7 +491,7 @@ data LegalholdConfig = LegalholdConfig
456
491
457
492
instance IsFeatureConfig LegalholdConfig where
458
493
type FeatureSymbol LegalholdConfig = " legalhold"
459
- defFeatureStatus = WithStatus FeatureStatusDisabled LockStatusUnlocked LegalholdConfig
494
+ defFeatureStatus = WithStatus FeatureStatusDisabled LockStatusUnlocked LegalholdConfig FeatureTTLUnlimited
460
495
objectSchema = pure LegalholdConfig
461
496
462
497
instance ToSchema LegalholdConfig where
@@ -474,7 +509,7 @@ data SSOConfig = SSOConfig
474
509
475
510
instance IsFeatureConfig SSOConfig where
476
511
type FeatureSymbol SSOConfig = " sso"
477
- defFeatureStatus = WithStatus FeatureStatusDisabled LockStatusUnlocked SSOConfig
512
+ defFeatureStatus = WithStatus FeatureStatusDisabled LockStatusUnlocked SSOConfig FeatureTTLUnlimited
478
513
objectSchema = pure SSOConfig
479
514
480
515
instance ToSchema SSOConfig where
@@ -494,7 +529,7 @@ data SearchVisibilityAvailableConfig = SearchVisibilityAvailableConfig
494
529
495
530
instance IsFeatureConfig SearchVisibilityAvailableConfig where
496
531
type FeatureSymbol SearchVisibilityAvailableConfig = " searchVisibility"
497
- defFeatureStatus = WithStatus FeatureStatusDisabled LockStatusUnlocked SearchVisibilityAvailableConfig
532
+ defFeatureStatus = WithStatus FeatureStatusDisabled LockStatusUnlocked SearchVisibilityAvailableConfig FeatureTTLUnlimited
498
533
objectSchema = pure SearchVisibilityAvailableConfig
499
534
500
535
instance ToSchema SearchVisibilityAvailableConfig where
@@ -518,7 +553,7 @@ instance ToSchema ValidateSAMLEmailsConfig where
518
553
519
554
instance IsFeatureConfig ValidateSAMLEmailsConfig where
520
555
type FeatureSymbol ValidateSAMLEmailsConfig = " validateSAMLemails"
521
- defFeatureStatus = WithStatus FeatureStatusEnabled LockStatusUnlocked ValidateSAMLEmailsConfig
556
+ defFeatureStatus = WithStatus FeatureStatusEnabled LockStatusUnlocked ValidateSAMLEmailsConfig FeatureTTLUnlimited
522
557
objectSchema = pure ValidateSAMLEmailsConfig
523
558
524
559
instance HasDeprecatedFeatureName ValidateSAMLEmailsConfig where
@@ -536,7 +571,7 @@ data DigitalSignaturesConfig = DigitalSignaturesConfig
536
571
537
572
instance IsFeatureConfig DigitalSignaturesConfig where
538
573
type FeatureSymbol DigitalSignaturesConfig = " digitalSignatures"
539
- defFeatureStatus = WithStatus FeatureStatusDisabled LockStatusUnlocked DigitalSignaturesConfig
574
+ defFeatureStatus = WithStatus FeatureStatusDisabled LockStatusUnlocked DigitalSignaturesConfig FeatureTTLUnlimited
540
575
objectSchema = pure DigitalSignaturesConfig
541
576
542
577
instance HasDeprecatedFeatureName DigitalSignaturesConfig where
@@ -557,7 +592,7 @@ data ConferenceCallingConfig = ConferenceCallingConfig
557
592
558
593
instance IsFeatureConfig ConferenceCallingConfig where
559
594
type FeatureSymbol ConferenceCallingConfig = " conferenceCalling"
560
- defFeatureStatus = WithStatus FeatureStatusEnabled LockStatusUnlocked ConferenceCallingConfig
595
+ defFeatureStatus = WithStatus FeatureStatusEnabled LockStatusUnlocked ConferenceCallingConfig FeatureTTLUnlimited
561
596
objectSchema = pure ConferenceCallingConfig
562
597
563
598
instance ToSchema ConferenceCallingConfig where
@@ -578,7 +613,7 @@ instance ToSchema SndFactorPasswordChallengeConfig where
578
613
579
614
instance IsFeatureConfig SndFactorPasswordChallengeConfig where
580
615
type FeatureSymbol SndFactorPasswordChallengeConfig = " sndFactorPasswordChallenge"
581
- defFeatureStatus = WithStatus FeatureStatusDisabled LockStatusLocked SndFactorPasswordChallengeConfig
616
+ defFeatureStatus = WithStatus FeatureStatusDisabled LockStatusLocked SndFactorPasswordChallengeConfig FeatureTTLUnlimited
582
617
objectSchema = pure SndFactorPasswordChallengeConfig
583
618
584
619
instance FeatureTrivialConfig SndFactorPasswordChallengeConfig where
@@ -593,7 +628,7 @@ data SearchVisibilityInboundConfig = SearchVisibilityInboundConfig
593
628
594
629
instance IsFeatureConfig SearchVisibilityInboundConfig where
595
630
type FeatureSymbol SearchVisibilityInboundConfig = " searchVisibilityInbound"
596
- defFeatureStatus = WithStatus FeatureStatusDisabled LockStatusUnlocked SearchVisibilityInboundConfig
631
+ defFeatureStatus = WithStatus FeatureStatusDisabled LockStatusUnlocked SearchVisibilityInboundConfig FeatureTTLUnlimited
597
632
objectSchema = pure SearchVisibilityInboundConfig
598
633
599
634
instance ToSchema SearchVisibilityInboundConfig where
@@ -626,6 +661,7 @@ instance IsFeatureConfig ClassifiedDomainsConfig where
626
661
FeatureStatusDisabled
627
662
LockStatusUnlocked
628
663
(ClassifiedDomainsConfig [] )
664
+ FeatureTTLUnlimited
629
665
configModel = Just $
630
666
Doc. defineModel " ClassifiedDomainsConfig" $ do
631
667
Doc. property " domains" (Doc. array Doc. string') $ Doc. description " domains"
@@ -656,6 +692,7 @@ instance IsFeatureConfig AppLockConfig where
656
692
FeatureStatusEnabled
657
693
LockStatusUnlocked
658
694
(AppLockConfig (EnforceAppLock False ) 60 )
695
+ FeatureTTLUnlimited
659
696
configModel = Just $
660
697
Doc. defineModel " AppLockConfig" $ do
661
698
Doc. property " enforceAppLock" Doc. bool' $ Doc. description " enforceAppLock"
@@ -679,7 +716,7 @@ data FileSharingConfig = FileSharingConfig
679
716
680
717
instance IsFeatureConfig FileSharingConfig where
681
718
type FeatureSymbol FileSharingConfig = " fileSharing"
682
- defFeatureStatus = WithStatus FeatureStatusEnabled LockStatusUnlocked FileSharingConfig
719
+ defFeatureStatus = WithStatus FeatureStatusEnabled LockStatusUnlocked FileSharingConfig FeatureTTLUnlimited
683
720
objectSchema = pure FileSharingConfig
684
721
685
722
instance ToSchema FileSharingConfig where
@@ -711,6 +748,7 @@ instance IsFeatureConfig SelfDeletingMessagesConfig where
711
748
FeatureStatusEnabled
712
749
LockStatusUnlocked
713
750
(SelfDeletingMessagesConfig 0 )
751
+ FeatureTTLUnlimited
714
752
configModel = Just $
715
753
Doc. defineModel " SelfDeletingMessagesConfig" $ do
716
754
Doc. property " enforcedTimeoutSeconds" Doc. int32' $ Doc. description " optional; default: `0` (no enforcement)"
@@ -741,7 +779,7 @@ instance IsFeatureConfig MLSConfig where
741
779
type FeatureSymbol MLSConfig = " mls"
742
780
defFeatureStatus =
743
781
let config = MLSConfig [] ProtocolProteusTag [MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 ] MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519
744
- in WithStatus FeatureStatusDisabled LockStatusUnlocked config
782
+ in WithStatus FeatureStatusDisabled LockStatusUnlocked config FeatureTTLUnlimited
745
783
objectSchema = field " config" schema
746
784
configModel = Just $
747
785
Doc. defineModel " MLSConfig" $ do
0 commit comments