diff --git a/libs/cassandra-util/src/Cassandra/Options.hs b/libs/cassandra-util/src/Cassandra/Options.hs index e8aca6a7de..7171c56866 100644 --- a/libs/cassandra-util/src/Cassandra/Options.hs +++ b/libs/cassandra-util/src/Cassandra/Options.hs @@ -12,7 +12,7 @@ data Endpoint = Endpoint { host :: !Text, port :: !Word16 } - deriving (Show, Generic) + deriving (Show, Eq, Generic) deriveFromJSON defaultOptions ''Endpoint @@ -27,6 +27,6 @@ data CassandraOpts = CassandraOpts filterNodesByDatacentre :: !(Maybe Text), tlsCa :: Maybe FilePath } - deriving (Show, Generic) + deriving (Show, Eq, Generic) deriveFromJSON defaultOptions ''CassandraOpts diff --git a/libs/extended/default.nix b/libs/extended/default.nix index 61f4643c17..0ef8ec1c23 100644 --- a/libs/extended/default.nix +++ b/libs/extended/default.nix @@ -19,6 +19,7 @@ , hspec-discover , http-client , http-client-tls +, http-media , http-types , imports , lib @@ -26,6 +27,7 @@ , monad-control , resourcet , retry +, schema-profunctor , servant , servant-client , servant-client-core @@ -40,6 +42,7 @@ , transformers , unliftio , wai +, yaml }: mkDerivation { pname = "extended"; @@ -59,12 +62,14 @@ mkDerivation { exceptions http-client http-client-tls + http-media http-types imports metrics-wai monad-control resourcet retry + schema-profunctor servant servant-client servant-client-core @@ -77,6 +82,7 @@ mkDerivation { transformers unliftio wai + yaml ]; testHaskellDepends = [ aeson diff --git a/libs/extended/extended.cabal b/libs/extended/extended.cabal index 65ad786401..d5792638b0 100644 --- a/libs/extended/extended.cabal +++ b/libs/extended/extended.cabal @@ -91,12 +91,14 @@ library , exceptions , http-client , http-client-tls + , http-media , http-types , imports , metrics-wai , monad-control , resourcet , retry + , schema-profunctor , servant , servant-client , servant-client-core @@ -109,6 +111,7 @@ library , transformers , unliftio , wai + , yaml default-language: GHC2021 diff --git a/libs/extended/src/Network/AMQP/Extended.hs b/libs/extended/src/Network/AMQP/Extended.hs index 955e54c0a3..0cc5870d6c 100644 --- a/libs/extended/src/Network/AMQP/Extended.hs +++ b/libs/extended/src/Network/AMQP/Extended.hs @@ -55,7 +55,7 @@ data RabbitMqTlsOpts = RabbitMqTlsOpts { caCert :: !(Maybe FilePath), insecureSkipVerifyTls :: Bool } - deriving (Show) + deriving (Show, Eq) parseTlsJson :: Object -> Parser (Maybe RabbitMqTlsOpts) parseTlsJson v = do @@ -111,7 +111,7 @@ data AmqpEndpoint = AmqpEndpoint vHost :: !Text, tls :: !(Maybe RabbitMqTlsOpts) } - deriving (Show) + deriving (Show, Eq) instance FromJSON AmqpEndpoint where parseJSON = withObject "AmqpEndpoint" $ \v -> diff --git a/libs/extended/src/Servant/API/Extended.hs b/libs/extended/src/Servant/API/Extended.hs index 959249ac48..17260f2395 100644 --- a/libs/extended/src/Servant/API/Extended.hs +++ b/libs/extended/src/Servant/API/Extended.hs @@ -19,14 +19,18 @@ -- errors instead of plaintext. module Servant.API.Extended where +import Data.Bifunctor import Data.ByteString import Data.ByteString.Lazy qualified as BL import Data.EitherR (fmapL) import Data.Kind +import Data.List.NonEmpty qualified as NE import Data.Metrics.Servant import Data.Typeable +import Data.Yaml as Y import GHC.TypeLits import Imports +import Network.HTTP.Media qualified as M import Network.HTTP.Types hiding (Header, ResponseHeaders) import Network.Wai import Servant.API @@ -116,3 +120,18 @@ instance instance (RoutesToPaths rest) => RoutesToPaths (ReqBodyCustomError' mods list tag a :> rest) where getRoutes = getRoutes @rest + +data YAML + +instance Accept YAML where + contentTypes _ = + "application" + M.// "yaml" + M./: ("charset", "utf-8") + NE.:| ["application" M.// "yaml"] + +instance {-# OVERLAPPABLE #-} (ToJSON a) => MimeRender YAML a where + mimeRender _ = fromStrict . Y.encode + +instance {-# OVERLAPPABLE #-} (FromJSON a) => MimeUnrender YAML a where + mimeUnrender _ = first show . Y.decodeEither' . toStrict diff --git a/libs/extended/src/System/Logger/Extended.hs b/libs/extended/src/System/Logger/Extended.hs index 2b45c3f746..e072917731 100644 --- a/libs/extended/src/System/Logger/Extended.hs +++ b/libs/extended/src/System/Logger/Extended.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# OPTIONS_GHC -Wno-orphans #-} @@ -41,6 +40,7 @@ import Data.ByteString (toStrict) import Data.ByteString.Builder qualified as B import Data.ByteString.Lazy.Char8 qualified as L import Data.Map.Lazy qualified as Map +import Data.Schema qualified as S import Data.Text.Encoding import Data.Text.Encoding.Error import GHC.Generics @@ -50,14 +50,36 @@ import System.Logger.Class qualified as LC deriving instance Generic LC.Level -instance FromJSON LC.Level +deriving via (S.Schema LC.Level) instance Aeson.FromJSON LC.Level -instance ToJSON LC.Level +deriving via (S.Schema LC.Level) instance Aeson.ToJSON LC.Level + +instance S.ToSchema LC.Level where + schema = + S.enum @Text "Level" $ + mconcat + [ S.element "Trace" Trace, + S.element "Debug" Debug, + S.element "Info" Info, + S.element "Warn" Warn, + S.element "Error" LC.Error, + S.element "Fatal" Fatal + ] -- | The log formats supported data LogFormat = JSON | Plain | Netstring | StructuredJSON - deriving stock (Eq, Show, Generic) - deriving anyclass (ToJSON, FromJSON) + deriving stock (Eq, Show, Bounded, Enum, Generic) + deriving (ToJSON, FromJSON) via (S.Schema LogFormat) + +instance S.ToSchema LogFormat where + schema = + S.enum @Text "LogFormat" $ + mconcat + [ S.element "JSON" JSON, + S.element "Plain" Plain, + S.element "Netstring" Netstring, + S.element "StructuredJSON" StructuredJSON + ] -- | We use this as an intermediate structure to ease the implementation of the -- ToJSON instance but we could just inline everything. I think this has diff --git a/libs/extended/test/Test/System/Logger/ExtendedSpec.hs b/libs/extended/test/Test/System/Logger/ExtendedSpec.hs index 753ba59ada..4e97ffc75f 100644 --- a/libs/extended/test/Test/System/Logger/ExtendedSpec.hs +++ b/libs/extended/test/Test/System/Logger/ExtendedSpec.hs @@ -28,6 +28,8 @@ import Test.Hspec (Spec, describe, it, shouldBe) spec :: Spec spec = describe "System.Loggger.Extended" $ do + it "instance {To,From}JSON LogFormat" $ do + Aeson.eitherDecode' "[\"JSON\", \"Plain\", \"Netstring\", \"StructuredJSON\"]" `shouldBe` Right [minBound @LogFormat ..] describe "LogFormat: StructuredJSON" $ do it "should encode logs as new line separated structured JSON with log level, messages and fields" $ do withSystemTempFile "structured-json" $ \f h -> do diff --git a/libs/types-common/src/Data/Json/Util.hs b/libs/types-common/src/Data/Json/Util.hs index c152fc6539..9a9c95b415 100644 --- a/libs/types-common/src/Data/Json/Util.hs +++ b/libs/types-common/src/Data/Json/Util.hs @@ -28,6 +28,9 @@ module Data.Json.Util toJSONFieldName, (#), ToJSONObject (..), + JsonObject, + mkJsonObject, + unJsonObject, -- * UTCTimeMillis UTCTimeMillis, @@ -53,6 +56,7 @@ import Cassandra qualified as CQL import Control.Lens hiding ((#), (.=)) import Data.Aeson (FromJSON (..), ToJSON (..)) import Data.Aeson qualified as A +import Data.Aeson.KeyMap qualified as A import Data.Aeson.Types qualified as A import Data.Attoparsec.Text qualified as Atto import Data.Attoparsec.Time qualified as Atto @@ -63,8 +67,8 @@ import Data.ByteString.Conversion qualified as BS import Data.ByteString.Lazy qualified as L import Data.ByteString.UTF8 qualified as UTF8 import Data.Fixed -import Data.OpenApi qualified as S -import Data.Schema +import Data.OpenApi qualified as O +import Data.Schema as S import Data.Text qualified as Text import Data.Text.Encoding qualified as Text import Data.Text.Encoding.Error qualified as Text @@ -99,24 +103,24 @@ infixr 5 # -- Unlike with 'UTCTime', 'Show' renders ISO string. newtype UTCTimeMillis = UTCTimeMillis {fromUTCTimeMillis :: UTCTime} deriving (Eq, Ord, Generic) - deriving (FromJSON, ToJSON, S.ToSchema) via Schema UTCTimeMillis + deriving (FromJSON, ToJSON, O.ToSchema) via Schema UTCTimeMillis instance ToSchema UTCTimeMillis where schema = UTCTimeMillis <$> showUTCTimeMillis .= ( utcTimeTextSchema "UTCTimeMillis" - & doc . S.schema - %~ (S.format ?~ "yyyy-mm-ddThh:MM:ss.qqqZ") - . (S.example ?~ "2021-05-12T10:52:02.671Z") + & doc . O.schema + %~ (O.format ?~ "yyyy-mm-ddThh:MM:ss.qqqZ") + . (O.example ?~ "2021-05-12T10:52:02.671Z") ) utcTimeTextSchema :: Text -> ValueSchemaP NamedSwaggerDoc Text UTCTime utcTimeTextSchema name = parsedText name (Atto.parseOnly (Atto.utcTime <* Atto.endOfInput)) - & doc . S.schema - %~ (S.format ?~ "yyyy-mm-ddThh:MM:ssZ") - . (S.example ?~ "2021-05-12T10:52:02Z") + & doc . O.schema + %~ (O.format ?~ "yyyy-mm-ddThh:MM:ssZ") + . (O.example ?~ "2021-05-12T10:52:02Z") utcTimeSchema :: ValueSchema NamedSwaggerDoc UTCTime utcTimeSchema = showUTCTime .= utcTimeTextSchema "UTCTime" @@ -164,17 +168,33 @@ class ToJSONObject a where instance ToJSONObject A.Object where toJSONObject = id +instance ToJSONObject [A.Pair] where + toJSONObject = A.fromList + ----------------------------------------------------------------------------- -- Aeson Object -instance S.ToParamSchema A.Object where - toParamSchema _ = - mempty & S.type_ ?~ S.OpenApiString +-- | Arbitrary aeson object value with helpful {to,from}json instances and schema. +newtype JsonObject = JsonObject {unJsonObject :: A.Object} + deriving newtype (Eq, Ord, Show) + deriving (O.ToSchema) via (Schema JsonObject) -instance ToSchema A.Object where - schema = - named "Object" $ - id .= jsonObject +mkJsonObject :: (ToJSONObject a) => a -> JsonObject +mkJsonObject = JsonObject . toJSONObject + +instance A.FromJSON JsonObject where + parseJSON = A.withObject "Object" (pure . JsonObject) + +instance A.ToJSON JsonObject where + toJSON (JsonObject obj) = A.Object obj + +instance S.ToSchema JsonObject where + schema = named "Object" $ unJsonObject .= (JsonObject <$> S.jsonObject) + +-- | This instance is currently still used for 'Push' (in a `List1`). Instead we could +-- introduce a type `JsonObjectList1` that works analogously to `JsonObject`. +instance S.ToSchema A.Object where + schema = named "Object" $ id .= S.jsonObject ----------------------------------------------------------------------------- -- toJSONFieldName @@ -204,7 +224,7 @@ toJSONFieldName = A.defaultOptions {A.fieldLabelModifier = A.camelTo2 '_'} -- Some related discussion: . newtype Base64ByteString = Base64ByteString {fromBase64ByteString :: ByteString} deriving stock (Eq, Ord, Show) - deriving (FromJSON, ToJSON, S.ToSchema) via Schema Base64ByteString + deriving (FromJSON, ToJSON, O.ToSchema) via Schema Base64ByteString deriving newtype (Arbitrary, IsString) instance ToSchema Base64ByteString where @@ -216,14 +236,14 @@ instance FromHttpApiData Base64ByteString where instance ToHttpApiData Base64ByteString where toUrlPiece = Text.decodeUtf8With Text.lenientDecode . B64U.encodeUnpadded . fromBase64ByteString -instance S.ToParamSchema Base64ByteString where - toParamSchema _ = mempty & S.type_ ?~ S.OpenApiString +instance O.ToParamSchema Base64ByteString where + toParamSchema _ = mempty & O.type_ ?~ O.OpenApiString -- base64("example") ~> "ZXhhbXBsZQo=" base64SchemaN :: ValueSchema NamedSwaggerDoc ByteString base64SchemaN = (toBase64Text .= parsedText "Base64ByteString" fromBase64Text) - & doc %~ fmap (S.schema . S.example ?~ A.String "ZXhhbXBsZQo=") + & doc %~ fmap (O.schema . O.example ?~ A.String "ZXhhbXBsZQo=") base64Schema :: ValueSchema SwaggerDoc ByteString base64Schema = unnamed base64SchemaN @@ -233,7 +253,7 @@ base64URLSchemaN = ( (Text.decodeUtf8 . B64U.encodeUnpadded) .= parsedText "Base64URLByteString" (B64U.decodeUnpadded . Text.encodeUtf8) ) - & doc %~ fmap (S.schema . S.example ?~ A.String "ZXhhbXBsZQo=") + & doc %~ fmap (O.schema . O.example ?~ A.String "ZXhhbXBsZQo=") base64URLSchema :: ValueSchema SwaggerDoc ByteString base64URLSchema = unnamed base64URLSchemaN @@ -262,8 +282,8 @@ instance FromHttpApiData Base64ByteStringL where instance ToHttpApiData Base64ByteStringL where toUrlPiece = toUrlPiece . base64ToStrict -instance S.ToParamSchema Base64ByteStringL where - toParamSchema _ = mempty & S.type_ ?~ S.OpenApiString +instance O.ToParamSchema Base64ByteStringL where + toParamSchema _ = mempty & O.type_ ?~ O.OpenApiString base64SchemaLN :: ValueSchema NamedSwaggerDoc LByteString base64SchemaLN = L.toStrict .= fmap L.fromStrict base64SchemaN diff --git a/libs/types-common/src/Util/Options.hs b/libs/types-common/src/Util/Options.hs index 9fa6117aed..509fb3b47c 100644 --- a/libs/types-common/src/Util/Options.hs +++ b/libs/types-common/src/Util/Options.hs @@ -30,8 +30,12 @@ where import Cassandra.Options import Control.Lens +import Data.Aeson qualified as A import Data.ByteString.Char8 qualified as BS import Data.ByteString.Conversion +import Data.OpenApi qualified as O +import Data.Schema qualified as S +import Data.Text qualified as T import Data.Text.Encoding (encodeUtf8) import Data.Yaml hiding (Parser) import Imports @@ -78,8 +82,12 @@ urlPort u = do makeLenses ''AWSEndpoint -newtype FilePathSecrets = FilePathSecrets FilePath - deriving (Eq, Show, FromJSON, IsString) +newtype FilePathSecrets = FilePathSecrets {unFilePathSecrets :: FilePath} + deriving (Eq, Show, IsString, Generic) + deriving (A.FromJSON, A.ToJSON, O.ToSchema) via (S.Schema FilePathSecrets) + +instance S.ToSchema FilePathSecrets where + schema = (T.pack . unFilePathSecrets) S..= (FilePathSecrets . T.unpack <$> S.text "FilePathSecrets") initCredentials :: (MonadIO m, FromJSON a) => FilePathSecrets -> m a initCredentials secretFile = do @@ -151,14 +159,14 @@ parseAWSEndpoint = readerAsk >>= maybe (error "Could not parse AWS endpoint") pu data PasswordHashingOptions = PasswordHashingArgon2id Argon2idOptions | PasswordHashingScrypt - deriving (Show, Generic) + deriving (Show, Eq, Generic) data Argon2idOptions = Argon2idOptions { iterations :: !Word32, memory :: !Word32, parallelism :: !Word32 } - deriving (Show, Generic) + deriving (Show, Eq, Generic) instance FromJSON PasswordHashingOptions where parseJSON = diff --git a/libs/wire-api/src/Wire/API/Allowlists.hs b/libs/wire-api/src/Wire/API/Allowlists.hs index ef986a2d5a..ea716d52e7 100644 --- a/libs/wire-api/src/Wire/API/Allowlists.hs +++ b/libs/wire-api/src/Wire/API/Allowlists.hs @@ -31,7 +31,7 @@ import Wire.API.User.Identity -- | A service providing a whitelist of allowed email addresses and phone numbers data AllowlistEmailDomains = AllowlistEmailDomains [Text] - deriving (Show, Generic) + deriving (Show, Eq, Generic) instance FromJSON AllowlistEmailDomains diff --git a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs index 8af642848d..c7653fa35c 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs @@ -27,6 +27,7 @@ import Data.CommaSeparatedList (CommaSeparatedList) import Data.Domain import Data.Handle import Data.Id as Id +import Data.Json.Util import Data.Nonce (Nonce) import Data.OpenApi hiding (Contact, Header, Schema, ToSchema) import Data.OpenApi qualified as S @@ -39,6 +40,7 @@ import Imports hiding (head) import Network.Wai.Utilities import Servant (JSON) import Servant hiding (Handler, JSON, addHeader, respond) +import Servant.API.Extended import Servant.OpenApi.Internal.Orphans () import Wire.API.Call.Config (RTCConfiguration) import Wire.API.Connection hiding (MissingLegalholdConsent) @@ -80,6 +82,21 @@ import Wire.API.User.RichInfo (RichInfoAssocList) import Wire.API.User.Search (Contact, PagingState, RoleFilter, SearchResult, TeamContact, TeamUserSearchSortBy, TeamUserSearchSortOrder) import Wire.API.UserMap +---------------------------------------------------------------------- + +type ServerOptionsDocsAPI = + Named + "server-config-options" + ( Summary "JSON schema of the server config yaml file(s)." + :> Description + "returns a JSON (or YAML) object with one JSON schema for each \ + \backend service (brig, gundeck, ...)." + :> "server-config-options" + :> Get '[JSON, YAML] JsonObject + ) + +---------------------------------------------------------------------- + type BrigAPI = UserAPI :<|> SelfAPI diff --git a/libs/wire-subsystems/default.nix b/libs/wire-subsystems/default.nix index 768fcdc5ca..bb6f8b9b9b 100644 --- a/libs/wire-subsystems/default.nix +++ b/libs/wire-subsystems/default.nix @@ -24,6 +24,8 @@ , currency-codes , data-default , data-timeout +, dns +, email-validate , errors , exceptions , extended @@ -47,6 +49,7 @@ , mime-mail , network , network-conduit-tls +, openapi3 , pipes , polysemy , polysemy-plugin @@ -86,6 +89,7 @@ , wire-api-federation , wire-otel , witherable +, yaml }: mkDerivation { pname = "wire-subsystems"; @@ -113,6 +117,7 @@ mkDerivation { currency-codes data-default data-timeout + dns errors exceptions extended @@ -133,6 +138,7 @@ mkDerivation { mime-mail network network-conduit-tls + openapi3 polysemy polysemy-plugin polysemy-time @@ -169,13 +175,17 @@ mkDerivation { testHaskellDepends = [ aeson async + attoparsec base bilge + bloodhound bytestring cassandra-util containers crypton data-default + dns + email-validate errors extended hspec @@ -204,6 +214,7 @@ mkDerivation { types-common wire-api wire-api-federation + yaml ]; testToolDepends = [ hspec-discover ]; license = lib.licenses.agpl3Only; diff --git a/services/brig/src/Brig/Options.hs b/libs/wire-subsystems/src/Wire/ServerOptions/Brig.hs similarity index 92% rename from services/brig/src/Brig/Options.hs rename to libs/wire-subsystems/src/Wire/ServerOptions/Brig.hs index 04da370766..44ba92be19 100644 --- a/services/brig/src/Brig/Options.hs +++ b/libs/wire-subsystems/src/Wire/ServerOptions/Brig.hs @@ -3,7 +3,7 @@ {-# LANGUAGE TemplateHaskell #-} {-# OPTIONS_GHC -Wno-ambiguous-fields #-} -- Disabling to stop errors on Getters -{-# OPTIONS_GHC -Wno-redundant-constraints #-} +{-# OPTIONS_GHC -Wno-redundant-constraints -Wno-orphans #-} -- This file is part of the Wire Server implementation. -- @@ -22,13 +22,10 @@ -- You should have received a copy of the GNU Affero General Public License along -- with this program. If not, see . -module Brig.Options where +module Wire.ServerOptions.Brig where -import Brig.Queue.Types (QueueOpts (..)) -import Brig.User.Auth.Cookie.Limit -import Brig.ZAuth qualified as ZAuth import Control.Applicative -import Control.Lens hiding (Level, element, enum) +import Control.Lens (lensField, lensRules, makeLensesWith, (.~)) import Data.Aeson import Data.Aeson.Types qualified as A import Data.Char qualified as Char @@ -39,13 +36,15 @@ import Data.Id import Data.LanguageCodes (ISO639_1 (EN)) import Data.Misc (HttpsUrl) import Data.Nonce +import Data.OpenApi qualified as O import Data.Range import Data.Schema +import Data.Schema qualified as S import Data.Text qualified as Text import Data.Text.Encoding qualified as Text import Database.Bloodhound.Types qualified as ES import Imports -import Network.AMQP.Extended +import Network.AMQP.Extended qualified as AMQP import Network.DNS qualified as DNS import System.Logger.Extended (Level, LogFormat) import Util.Options @@ -57,6 +56,9 @@ import Wire.API.Routes.Version import Wire.API.Team.Feature import Wire.API.User import Wire.EmailSending.SMTP (SMTPConnType (..)) +import Wire.ServerOptions.Brig.CookieLimit +import Wire.ServerOptions.Brig.Queue (QueueOpts (..)) +import Wire.ServerOptions.Brig.ZAuth qualified as ZAuth data ElasticSearchOpts = ElasticSearchOpts { -- | ElasticSearch URL @@ -86,9 +88,29 @@ data ElasticSearchOpts = ElasticSearchOpts additionalInsecureSkipVerifyTls :: Bool, additionalCaCert :: Maybe FilePath } - deriving (Show, Generic) + deriving (Show, Eq, Generic) + deriving (ToJSON, FromJSON, O.ToSchema) via (Schema ElasticSearchOpts) + +instance ToSchema ES.Server where + schema = (Text.pack . show) S..= (ES.Server <$> text "ElasticSearch.Server") -instance FromJSON ElasticSearchOpts +instance ToSchema ES.IndexName where + schema = (Text.pack . show) S..= (ES.IndexName <$> S.text "ElasticSearch.IndexName") + +instance S.ToSchema ElasticSearchOpts where + schema = + S.object "ElasticSearchOpts" $ + ElasticSearchOpts + <$> url S..= S.field "url" S.schema + <*> index S..= S.field "index" S.schema + <*> additionalWriteIndex S..= maybe_ (S.optField "additionalWriteIndex" S.schema) + <*> additionalWriteIndexUrl S..= maybe_ (S.optField "additionalWriteIndexUrl" S.schema) + <*> credentials S..= maybe_ (S.optField "credentials" S.schema) + <*> additionalCredentials S..= maybe_ (S.optField "additionalCredentials" S.schema) + <*> insecureSkipVerifyTls S..= S.field "insecureSkipVerifyTls" S.schema + <*> caCert S..= maybe_ (S.optField "caCert" S.schema) + <*> additionalInsecureSkipVerifyTls S..= S.field "additionalInsecureSkipVerifyTls" S.schema + <*> additionalCaCert S..= maybe_ (S.optField "additionalCaCert" S.schema) data AWSOpts = AWSOpts { -- | Event journal queue for user events @@ -101,7 +123,7 @@ data AWSOpts = AWSOpts -- | DynamoDB endpoint dynamoDBEndpoint :: !(Maybe AWSEndpoint) } - deriving (Show, Generic) + deriving (Show, Eq, Generic) instance FromJSON AWSOpts @@ -112,7 +134,7 @@ data EmailAWSOpts = EmailAWSOpts -- | AWS SES endpoint sesEndpoint :: !AWSEndpoint } - deriving (Show, Generic) + deriving (Show, Eq, Generic) instance FromJSON EmailAWSOpts @@ -124,7 +146,7 @@ data EmailSMTPCredentials = EmailSMTPCredentials -- authenticate against the SMTP server smtpPassword :: !FilePathSecrets } - deriving (Show, Generic) + deriving (Show, Eq, Generic) instance FromJSON EmailSMTPCredentials @@ -136,7 +158,7 @@ data EmailSMTPOpts = EmailSMTPOpts -- against the SMTP server {tls,ssl,plain} smtpConnType :: !SMTPConnType } - deriving (Show, Generic) + deriving (Show, Eq, Generic) instance FromJSON EmailSMTPOpts @@ -145,12 +167,12 @@ data StompOpts = StompOpts port :: !Int, tls :: !Bool } - deriving (Show, Generic) + deriving (Show, Eq, Generic) data InternalEventsOpts = InternalEventsOpts { internalEventsQueue :: !QueueOpts } - deriving (Show) + deriving (Show, Eq, Generic) instance FromJSON InternalEventsOpts where parseJSON = withObject "InternalEventsOpts" $ \o -> @@ -169,7 +191,7 @@ data EmailSMSGeneralOpts = EmailSMSGeneralOpts -- emails/sms/calls templateBranding :: !BrandingOpts } - deriving (Show, Generic) + deriving (Show, Eq, Generic) instance FromJSON EmailSMSGeneralOpts @@ -185,7 +207,7 @@ data BrandingOpts = BrandingOpts forgot :: !Text, support :: !Text } - deriving (Show, Generic) + deriving (Show, Eq, Generic) instance FromJSON BrandingOpts @@ -199,7 +221,7 @@ data EmailUserOpts = EmailUserOpts -- | Deletion URL template deletionUrl :: !Text } - deriving (Show, Generic) + deriving (Show, Eq, Generic) instance FromJSON EmailUserOpts @@ -216,7 +238,7 @@ data ProviderOpts = ProviderOpts -- | Password reset URL template providerPwResetUrl :: !Text } - deriving (Show, Generic) + deriving (Show, Eq, Generic) instance FromJSON ProviderOpts @@ -232,14 +254,14 @@ data TeamOpts = TeamOpts -- | Team Member Welcome URL tMemberWelcomeUrl :: !Text } - deriving (Show, Generic) + deriving (Show, Eq, Generic) instance FromJSON TeamOpts data EmailOpts = EmailAWS EmailAWSOpts | EmailSMTP EmailSMTPOpts - deriving (Show, Generic) + deriving (Show, Eq, Generic) instance FromJSON EmailOpts where parseJSON o = @@ -253,7 +275,7 @@ data EmailSMSOpts = EmailSMSOpts provider :: !ProviderOpts, team :: !TeamOpts } - deriving (Show, Generic) + deriving (Show, Eq, Generic) instance FromJSON EmailSMSOpts @@ -292,7 +314,7 @@ data ZAuthOpts = ZAuthOpts -- | Other settings authSettings :: !ZAuth.Settings } - deriving (Show, Generic) + deriving (Show, Eq, Generic) instance FromJSON ZAuthOpts @@ -309,7 +331,7 @@ data TurnOpts = TurnOpts -- should be fetched, in seconds configTTL :: !Word32 } - deriving (Show) + deriving (Show, Eq, Generic) instance FromJSON TurnOpts where parseJSON = withObject "TurnOpts" $ \o -> do @@ -327,13 +349,13 @@ instance FromJSON TurnOpts where data TurnServersSource = TurnSourceDNS TurnDnsOpts | TurnSourceFiles TurnServersFiles - deriving (Show) + deriving (Show, Eq, Generic) data TurnServersFiles = TurnServersFiles { tsfServers :: !FilePath, tsfServersV2 :: !FilePath } - deriving (Show) + deriving (Show, Eq, Generic) instance FromJSON TurnServersFiles where parseJSON = withObject "TurnServersFiles" $ \o -> @@ -345,7 +367,7 @@ data TurnDnsOpts = TurnDnsOpts { tdoBaseDomain :: DNS.Domain, tdoDiscoveryIntervalSeconds :: !(Maybe DiffTime) } - deriving (Show) + deriving (Show, Eq, Generic) instance FromJSON TurnDnsOpts where parseJSON = withObject "TurnDnsOpts" $ \o -> @@ -356,7 +378,7 @@ instance FromJSON TurnDnsOpts where data ListAllSFTServers = ListAllSFTServers | HideAllSFTServers - deriving (Show, Eq, Ord) + deriving (Show, Eq, Ord, Generic) deriving (FromJSON) via Schema ListAllSFTServers instance ToSchema ListAllSFTServers where @@ -389,7 +411,7 @@ data Opts = Opts -- | SFT Federation multiSFT :: !(Maybe Bool), -- | RabbitMQ settings, required when federation is enabled. - rabbitmq :: !(Maybe AmqpEndpoint), + rabbitmq :: !(Maybe AMQP.AmqpEndpoint), -- | AWS settings aws :: !AWSOpts, -- | Enable Random Prekey Strategy @@ -429,7 +451,7 @@ data Opts = Opts -- | Runtime settings settings :: !Settings } - deriving (Show, Generic) + deriving (Show, Eq, Generic) -- | Options that persist as runtime settings. data Settings = Settings @@ -588,7 +610,7 @@ data Settings = Settings -- | Options to override the default Argon2id settings for specific operators. passwordHashingOptions :: !(PasswordHashingOptions) } - deriving (Show, Generic) + deriving (Show, Eq, Generic) newtype ImplicitNoFederationRestriction = ImplicitNoFederationRestriction {federationDomainConfig :: FederationDomainConfig} @@ -679,7 +701,7 @@ oAuthMaxActiveRefreshTokens = fromMaybe defaultOAuthMaxActiveRefreshTokens . oAu data UserFeatureFlags = UserFeatureFlags { conferenceCalling :: UserFeature ConferenceCallingConfig } - deriving (Eq, Ord, Show) + deriving (Eq, Ord, Show, Generic) instance FromJSON UserFeatureFlags where parseJSON = withObject "UserFeatureFlags" $ \obj -> do @@ -694,7 +716,7 @@ data instance UserFeature ConferenceCallingConfig = ConferenceCallingUserStatus -- | How an unset status for this feature should be interpreted. forNull :: FeatureStatus } - deriving (Eq, Ord, Show) + deriving (Eq, Ord, Show, Generic) instance Default (UserFeature ConferenceCallingConfig) where def = ConferenceCallingUserStatus Nothing FeatureStatusEnabled @@ -747,11 +769,11 @@ data CustomerExtensions = CustomerExtensions -- least @domainsBlockedForRegistration = []@. :) domainsBlockedForRegistration :: DomainsBlockedForRegistration } - deriving (Show, FromJSON, Generic) + deriving (Show, Eq, FromJSON, Generic) -- | See also: "Galley.API.CustomBackend", `galley.custom_backend`. newtype DomainsBlockedForRegistration = DomainsBlockedForRegistration [Domain] - deriving newtype (Show, FromJSON, Generic) + deriving newtype (Show, Eq, FromJSON, Generic) data SFTOptions = SFTOptions { sftBaseDomain :: !DNS.Domain, @@ -760,7 +782,7 @@ data SFTOptions = SFTOptions sftListLength :: !(Maybe (Range 1 100 Int)), -- defaults to defSftListLength sftTokenOptions :: !(Maybe SFTTokenOptions) } - deriving (Show, Generic) + deriving (Show, Eq, Generic) instance FromJSON SFTOptions where parseJSON = withObject "SFTOptions" $ \o -> @@ -775,7 +797,7 @@ data SFTTokenOptions = SFTTokenOptions { sttTTL :: !Word32, sttSecret :: !FilePath } - deriving (Show, Generic) + deriving (Show, Eq, Generic) instance FromJSON SFTTokenOptions where parseJSON = withObject "SFTTokenOptions" $ \o -> diff --git a/libs/wire-subsystems/src/Wire/ServerOptions/Brig/CookieLimit.hs b/libs/wire-subsystems/src/Wire/ServerOptions/Brig/CookieLimit.hs new file mode 100644 index 0000000000..323eb1ce6b --- /dev/null +++ b/libs/wire-subsystems/src/Wire/ServerOptions/Brig/CookieLimit.hs @@ -0,0 +1,43 @@ +-- This file is part of the Wire Server implementation. +-- +-- Copyright (C) 2022 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 Wire.ServerOptions.Brig.CookieLimit where + +import Data.Aeson +import Data.RetryAfter +import Imports + +-- | The fields are: +-- +-- * Min. standard deviation cookie creation +-- * Wait time when the min deviation is violated +-- +-- Both fields are in seconds. +data CookieThrottle + = StdDevThrottle StdDev RetryAfter + deriving (Eq, Show) + +newtype StdDev = StdDev Double + deriving (Eq, Ord, Show, Num, Generic) + +instance FromJSON StdDev + +instance FromJSON CookieThrottle where + parseJSON = withObject "User.Auth.Cookie.Limit.CookieThrottle" $ \o -> + StdDevThrottle + <$> o .: "stdDev" + <*> (RetryAfter <$> o .: "retryAfter") diff --git a/services/brig/src/Brig/Queue/Types.hs b/libs/wire-subsystems/src/Wire/ServerOptions/Brig/Queue.hs similarity index 95% rename from services/brig/src/Brig/Queue/Types.hs rename to libs/wire-subsystems/src/Wire/ServerOptions/Brig/Queue.hs index e7784b8b8f..003e396016 100644 --- a/services/brig/src/Brig/Queue/Types.hs +++ b/libs/wire-subsystems/src/Wire/ServerOptions/Brig/Queue.hs @@ -15,10 +15,7 @@ -- You should have received a copy of the GNU Affero General Public License along -- with this program. If not, see . -module Brig.Queue.Types - ( QueueOpts (..), - ) -where +module Wire.ServerOptions.Brig.Queue where import Data.Aeson import Imports diff --git a/libs/wire-subsystems/src/Wire/ServerOptions/Brig/ZAuth.hs b/libs/wire-subsystems/src/Wire/ServerOptions/Brig/ZAuth.hs new file mode 100644 index 0000000000..1e1bbf4aa9 --- /dev/null +++ b/libs/wire-subsystems/src/Wire/ServerOptions/Brig/ZAuth.hs @@ -0,0 +1,132 @@ +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE TemplateHaskell #-} + +-- This file is part of the Wire Server implementation. +-- +-- Copyright (C) 2022 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 Wire.ServerOptions.Brig.ZAuth + ( Settings (..), + keyIndex, + userTokenTimeout, + sessionTokenTimeout, + accessTokenTimeout, + providerTokenTimeout, + legalHoldUserTokenTimeout, + legalHoldAccessTokenTimeout, + defSettings, + UserTokenTimeout (..), + userTokenTimeoutSeconds, + SessionTokenTimeout (..), + AccessTokenTimeout (..), + accessTokenTimeoutSeconds, + ProviderTokenTimeout (..), + LegalHoldUserTokenTimeout (..), + legalHoldUserTokenTimeoutSeconds, + LegalHoldAccessTokenTimeout (..), + legalHoldAccessTokenTimeoutSeconds, + ) +where + +import Control.Lens (makeLenses) +import Data.Aeson +import Imports + +data Settings = Settings + { -- | Secret key index to use + -- for token creation + _keyIndex :: !Int, + -- | User token validity timeout + _userTokenTimeout :: !UserTokenTimeout, + -- | Session token validity timeout + _sessionTokenTimeout :: !SessionTokenTimeout, + -- | Access token validity timeout + _accessTokenTimeout :: !AccessTokenTimeout, + -- | Proider token validity timeout + _providerTokenTimeout :: !ProviderTokenTimeout, + -- | Legal Hold User token validity timeout + _legalHoldUserTokenTimeout :: !LegalHoldUserTokenTimeout, + -- | Legal Hold Access token validity timeout + _legalHoldAccessTokenTimeout :: !LegalHoldAccessTokenTimeout + } + deriving (Show, Eq, Generic) + +defSettings :: Settings +defSettings = + Settings + 1 + (UserTokenTimeout (60 * 60 * 24 * 28)) -- 28 days + (SessionTokenTimeout (60 * 60 * 24)) -- 1 day + (AccessTokenTimeout 900) -- 15 minutes + (ProviderTokenTimeout (60 * 60 * 24 * 7)) -- 7 days + (LegalHoldUserTokenTimeout (60 * 60 * 24 * 56)) -- 56 days + (LegalHoldAccessTokenTimeout (60 * 15)) -- 15 minutes + +newtype UserTokenTimeout = UserTokenTimeout + {_userTokenTimeoutSeconds :: Integer} + deriving (Show, Num, Eq, Generic) + +newtype SessionTokenTimeout = SessionTokenTimeout + {sessionTokenTimeoutSeconds :: Integer} + deriving (Show, Num, Eq, Generic) + +newtype AccessTokenTimeout = AccessTokenTimeout + {_accessTokenTimeoutSeconds :: Integer} + deriving (Show, Num, Eq, Generic) + +newtype ProviderTokenTimeout = ProviderTokenTimeout + {providerTokenTimeoutSeconds :: Integer} + deriving (Show, Num, Eq, Generic) + +newtype LegalHoldUserTokenTimeout = LegalHoldUserTokenTimeout + {_legalHoldUserTokenTimeoutSeconds :: Integer} + deriving (Show, Num, Eq, Generic) + +newtype LegalHoldAccessTokenTimeout = LegalHoldAccessTokenTimeout + {_legalHoldAccessTokenTimeoutSeconds :: Integer} + deriving (Show, Num, Eq, Generic) + +instance FromJSON UserTokenTimeout + +instance FromJSON SessionTokenTimeout + +instance FromJSON AccessTokenTimeout + +instance FromJSON ProviderTokenTimeout + +instance FromJSON LegalHoldAccessTokenTimeout + +instance FromJSON LegalHoldUserTokenTimeout + +instance FromJSON Settings where + parseJSON = withObject "ZAuth.Settings" $ \o -> + Settings + <$> o .: "keyIndex" + <*> (UserTokenTimeout <$> o .: "userTokenTimeout") + <*> (SessionTokenTimeout <$> o .: "sessionTokenTimeout") + <*> (AccessTokenTimeout <$> o .: "accessTokenTimeout") + <*> (ProviderTokenTimeout <$> o .: "providerTokenTimeout") + <*> (LegalHoldUserTokenTimeout <$> o .: "legalHoldUserTokenTimeout") + <*> (LegalHoldAccessTokenTimeout <$> o .: "legalHoldAccessTokenTimeout") + +makeLenses ''LegalHoldAccessTokenTimeout +makeLenses ''AccessTokenTimeout + +makeLenses ''UserTokenTimeout + +makeLenses ''LegalHoldUserTokenTimeout + +makeLenses ''Settings diff --git a/services/cannon/src/Cannon/Options.hs b/libs/wire-subsystems/src/Wire/ServerOptions/Cannon.hs similarity index 58% rename from services/cannon/src/Cannon/Options.hs rename to libs/wire-subsystems/src/Wire/ServerOptions/Cannon.hs index ae301862e1..d25fb678b7 100644 --- a/services/cannon/src/Cannon/Options.hs +++ b/libs/wire-subsystems/src/Wire/ServerOptions/Cannon.hs @@ -19,7 +19,7 @@ -- You should have received a copy of the GNU Affero General Public License along -- with this program. If not, see . -module Cannon.Options +module Wire.ServerOptions.Cannon ( host, port, cannon, @@ -40,7 +40,10 @@ module Cannon.Options where import Control.Lens (makeFields) -import Data.Aeson.APIFieldJsonTH +import Data.Aeson qualified as A +import Data.OpenApi qualified as O +import Data.Schema +import Data.Set qualified as Set import Imports import System.Logger.Extended (Level, LogFormat) import Wire.API.Routes.Version @@ -52,20 +55,34 @@ data Cannon = Cannon _cannonExternalHostFile :: !(Maybe FilePath) } deriving (Eq, Show, Generic) + deriving (A.ToJSON, A.FromJSON, O.ToSchema) via (Schema Cannon) -makeFields ''Cannon +instance ToSchema Cannon where + schema = + object "Cannon.Options.Cannon" $ + Cannon + <$> _cannonHost .= field "host" schema + <*> _cannonPort .= field "port" schema + <*> _cannonExternalHost .= maybe_ (optField "externalHost" schema) + <*> _cannonExternalHostFile .= maybe_ (optField "externalHostFile" schema) -deriveApiFieldJSON ''Cannon +makeFields ''Cannon data Gundeck = Gundeck { _gundeckHost :: !Text, _gundeckPort :: !Word16 } deriving (Eq, Show, Generic) + deriving (A.ToJSON, A.FromJSON, O.ToSchema) via (Schema Gundeck) -makeFields ''Gundeck +instance ToSchema Gundeck where + schema = + object "Cannon.Options.Gundeck" $ + Gundeck + <$> _gundeckHost .= field "host" schema + <*> _gundeckPort .= field "port" schema -deriveApiFieldJSON ''Gundeck +makeFields ''Gundeck data DrainOpts = DrainOpts { -- | Maximum amount of time draining should take. Must not be set to 0. @@ -79,10 +96,17 @@ data DrainOpts = DrainOpts _drainOptsMinBatchSize :: Word64 } deriving (Eq, Show, Generic) + deriving (A.ToJSON, A.FromJSON, O.ToSchema) via (Schema DrainOpts) -makeFields ''DrainOpts +instance ToSchema DrainOpts where + schema = + object "Cannon.Options.DrainOpts" $ + DrainOpts + <$> _drainOptsGracePeriodSeconds .= field "gracePeriodSeconds" schema + <*> _drainOptsMillisecondsBetweenBatches .= field "millisecondsBetweenBatches" schema + <*> _drainOptsMinBatchSize .= field "minBatchSize" schema -deriveApiFieldJSON ''DrainOpts +makeFields ''DrainOpts data Opts = Opts { _optsCannon :: !Cannon, @@ -94,7 +118,18 @@ data Opts = Opts _optsDisabledAPIVersions :: !(Set VersionExp) } deriving (Eq, Show, Generic) + deriving (A.ToJSON, A.FromJSON, O.ToSchema) via (Schema Opts) -makeFields ''Opts +instance ToSchema Opts where + schema = + object "Cannon.Options.Opts" $ + Opts + <$> _optsCannon .= field "cannon" schema + <*> _optsGundeck .= field "gundeck" schema + <*> _optsLogLevel .= field "logLevel" schema + <*> (fmap getLast . _optsLogNetStrings) .= maybe_ (optField "logNetStrings" (Last <$> schema)) + <*> (fmap getLast . _optsLogFormat) .= maybe_ (optField "logFormat" (Last <$> schema)) + <*> _optsDrainOpts .= field "drainOpts" schema + <*> (Set.toList . _optsDisabledAPIVersions) .= field "disabledAPIVersions" (Set.fromList <$> array schema) -deriveApiFieldJSON ''Opts +makeFields ''Opts diff --git a/services/gundeck/src/Gundeck/Options.hs b/libs/wire-subsystems/src/Wire/ServerOptions/Gundeck.hs similarity index 94% rename from services/gundeck/src/Gundeck/Options.hs rename to libs/wire-subsystems/src/Wire/ServerOptions/Gundeck.hs index 5f67081e17..d3678ea3a9 100644 --- a/services/gundeck/src/Gundeck/Options.hs +++ b/libs/wire-subsystems/src/Wire/ServerOptions/Gundeck.hs @@ -18,14 +18,15 @@ -- You should have received a copy of the GNU Affero General Public License along -- with this program. If not, see . -module Gundeck.Options where +module Wire.ServerOptions.Gundeck where +import Amazonka (Region) import Control.Lens hiding (Level) import Data.Aeson.TH import Data.Yaml (FromJSON) -import Gundeck.Aws.Arn import Imports import System.Logger.Extended (Level, LogFormat) +import Text.Shakespeare.Text (ToText (..)) import Util.Options import Util.Options.Common import Wire.API.Routes.Version @@ -34,6 +35,12 @@ newtype NotificationTTL = NotificationTTL {notificationTTLSeconds :: Word32} deriving (Eq, Ord, Show, Generic, FromJSON) +newtype ArnEnv = ArnEnv {arnEnvText :: Text} + deriving (Show, ToText, FromJSON) + +newtype Account = Account {fromAccount :: Text} + deriving (Eq, Ord, Show, ToText, FromJSON) + data AWSOpts = AWSOpts { -- | AWS account _account :: !Account, diff --git a/services/spar/src/Spar/Options.hs b/libs/wire-subsystems/src/Wire/ServerOptions/Spar.hs similarity index 99% rename from services/spar/src/Spar/Options.hs rename to libs/wire-subsystems/src/Wire/ServerOptions/Spar.hs index 32c11360b1..9ebd1c896d 100644 --- a/services/spar/src/Spar/Options.hs +++ b/libs/wire-subsystems/src/Wire/ServerOptions/Spar.hs @@ -19,7 +19,7 @@ -- with this program. If not, see . -- | Reading the Spar config. -module Spar.Options +module Wire.ServerOptions.Spar ( Opts' (..), Opts, DerivedOpts (..), diff --git a/libs/wire-subsystems/test/unit/Wire/ServerOptionsSpec.hs b/libs/wire-subsystems/test/unit/Wire/ServerOptionsSpec.hs new file mode 100644 index 0000000000..ff4cc2ff1a --- /dev/null +++ b/libs/wire-subsystems/test/unit/Wire/ServerOptionsSpec.hs @@ -0,0 +1,428 @@ +{-# OPTIONS_GHC -Wno-incomplete-patterns #-} + +module Wire.ServerOptionsSpec (spec) where + +import Cassandra.Options +import Data.Bifunctor +import Data.Code qualified as Code +import Data.Domain +import Data.Nonce +import Data.RetryAfter +import Data.Set +import Data.Yaml +import Database.Bloodhound.Types qualified as ES +import Imports +import Network.AMQP.Extended +import System.Logger +import Test.Hspec +import Text.Email.Parser +import Util.Options +import Wire.API.Locale +import Wire.API.Routes.FederationDomainConfig +import Wire.API.Team.Feature +import Wire.API.User +import Wire.API.User.Search +import Wire.ServerOptions.Brig qualified as B +import Wire.ServerOptions.Brig.CookieLimit qualified as CookieLimit +import Wire.ServerOptions.Brig.Queue qualified as Queue +import Wire.ServerOptions.Brig.ZAuth qualified as ZAuth + +spec :: Spec +spec = do + describe "Wire.ServerOptions.CookieLimit" $ do + it "CookieThrottle" $ do + let i = + "stdDev: 5\n\ + \retryAfter: 3" + o = CookieLimit.StdDevThrottle 5 3 + (prettyPrintParseException `first` decodeEither' i) `shouldBe` Right o + + describe "Wire.ServerOptions.Brig.Queue" $ do + it "QueueOpts (sqs)" $ do + let i = + "queueType: sqs\n\ + \queueName: test" + o = Queue.SqsQueueOpts "test" + (prettyPrintParseException `first` decodeEither' i) `shouldBe` Right o + + it "QueueOpts (stomp)" $ do + let i = + "queueType: stomp\n\ + \queueName: test" + o = Queue.StompQueueOpts "test" + (prettyPrintParseException `first` decodeEither' i) `shouldBe` Right o + + describe "Wire.ServerOptions.Brig.ZAuth" $ do + it "Settings" $ do + let i = + "keyIndex: 1\n\ + \userTokenTimeout: 120\n\ + \sessionTokenTimeout: 20\n\ + \accessTokenTimeout: 30\n\ + \providerTokenTimeout: 60\n\ + \legalHoldUserTokenTimeout: 120\n\ + \legalHoldAccessTokenTimeout: 30" + o = ZAuth.Settings 1 120 20 30 60 120 30 + (prettyPrintParseException `first` decodeEither' i) `shouldBe` Right o + + describe "Wire.ServerOptions.Brig" $ do + it "Settings" $ do + let i = + "brig:\n\ + \ host: 0.0.0.0\n\ + \ port: 8082\n\ + \cassandra:\n\ + \ endpoint:\n\ + \ host: 127.0.0.1\n\ + \ port: 9042\n\ + \ keyspace: brig_test\n\ + \elasticsearch:\n\ + \ url: https://localhost:9200\n\ + \ index: directory_test\n\ + \ credentials: test/resources/elasticsearch-credentials.yaml\n\ + \ caCert: test/resources/elasticsearch-ca.pem\n\ + \ insecureSkipVerifyTls: false\n\ + \ additionalCredentials: test/resources/elasticsearch-credentials.yaml\n\ + \ additionalCaCert: test/resources/elasticsearch-ca.pem\n\ + \ additionalInsecureSkipVerifyTls: false\n\ + \rabbitmq:\n\ + \ host: 127.0.0.1\n\ + \ port: 5671\n\ + \ vHost: /\n\ + \ enableTls: true\n\ + \ caCert: test/resources/rabbitmq-ca.pem\n\ + \ insecureSkipVerifyTls: false\n\ + \cargohold:\n\ + \ host: 127.0.0.1\n\ + \ port: 8084\n\ + \galley:\n\ + \ host: 127.0.0.1\n\ + \ port: 8085\n\ + \gundeck:\n\ + \ host: 127.0.0.1\n\ + \ port: 8086\n\ + \federatorInternal:\n\ + \ host: 127.0.0.1\n\ + \ port: 8097\n\ + \multiSFT: false\n\ + \aws:\n\ + \ userJournalQueue: integration-user-events.fifo\n\ + \ prekeyTable: integration-brig-prekeys\n\ + \ sqsEndpoint: http://localhost:4568\n\ + \randomPrekeys: true\n\ + \internalEvents:\n\ + \ queueType: sqs\n\ + \ queueName: integration-brig-events-internal\n\ + \emailSMS:\n\ + \ email:\n\ + \ sesQueue: integration-brig-events\n\ + \ sesEndpoint: http://localhost:4569\n\ + \ general:\n\ + \ templateDir: deb/opt/brig/templates\n\ + \ emailSender: backend-integration@wire.com\n\ + \ smsSender: \"+123456789\"\n\ + \ templateBranding:\n\ + \ brand: Wire\n\ + \ brandUrl: https://wire.com\n\ + \ brandLabelUrl: wire.com\n\ + \ brandLogoUrl: https://wire.com/p/img/email/logo-email-black.png\n\ + \ brandService: Wire Service Provider\n\ + \ copyright: WIRE SWISS GmbH\n\ + \ misuse: misuse@wire.com\n\ + \ legal: https://wire.com/legal/\n\ + \ forgot: https://wire.com/forgot/\n\ + \ support: https://support.wire.com/\n\ + \ user:\n\ + \ activationUrl: http://127.0.0.1:8080/activate?key=${key}&code=${code}\n\ + \ smsActivationUrl: http://127.0.0.1:8080/v/${code}\n\ + \ passwordResetUrl: http://127.0.0.1:8080/password-reset/${key}?code=${code}\n\ + \ invitationUrl: http://127.0.0.1:8080/register?invitation_code=${code}\n\ + \ deletionUrl: http://127.0.0.1:8080/users/delete?key=${key}&code=${code}\n\ + \ provider:\n\ + \ homeUrl: https://provider.localhost/\n\ + \ providerActivationUrl: http://127.0.0.1:8080/provider/activate?key=${key}&code=${code}\n\ + \ approvalUrl: http://127.0.0.1:8080/provider/approve?key=${key}&code=${code}\n\ + \ approvalTo: success@simulator.amazonses.com\n\ + \ providerPwResetUrl: http://127.0.0.1:8080/provider/password-reset?key=${key}&code=${code}\n\ + \ team:\n\ + \ tInvitationUrl: http://127.0.0.1:8080/register?team=${team}&team_code=${code}\n\ + \ tExistingUserInvitationUrl: http://127.0.0.1:8080/accept-invitation?team-code=${code}\n\ + \ tActivationUrl: http://127.0.0.1:8080/register?team=${team}&team_code=${code}\n\ + \ tCreatorWelcomeUrl: http://127.0.0.1:8080/creator-welcome-website\n\ + \ tMemberWelcomeUrl: http://127.0.0.1:8080/member-welcome-website\n\ + \zauth:\n\ + \ privateKeys: test/resources/zauth/privkeys.txt\n\ + \ publicKeys: test/resources/zauth/pubkeys.txt\n\ + \ authSettings:\n\ + \ keyIndex: 1\n\ + \ userTokenTimeout: 120\n\ + \ sessionTokenTimeout: 20\n\ + \ accessTokenTimeout: 30\n\ + \ providerTokenTimeout: 60\n\ + \ legalHoldUserTokenTimeout: 120\n\ + \ legalHoldAccessTokenTimeout: 30\n\ + \turn:\n\ + \ serversSource: files\n\ + \ servers: test/resources/turn/servers.txt\n\ + \ serversV2: test/resources/turn/servers-v2.txt\n\ + \ secret: test/resources/turn/secret.txt\n\ + \ configTTL: 3600\n\ + \ tokenTTL: 21600\n\ + \optSettings:\n\ + \ setActivationTimeout: 4\n\ + \ setVerificationTimeout: 4\n\ + \ setTeamInvitationTimeout: 4\n\ + \ setExpiredUserCleanupTimeout: 1\n\ + \ setUserMaxConnections: 16\n\ + \ setCookieInsecure: true\n\ + \ setUserCookieRenewAge: 2\n\ + \ setUserCookieLimit: 5\n\ + \ setUserCookieThrottle:\n\ + \ stdDev: 5\n\ + \ retryAfter: 3\n\ + \ setLimitFailedLogins:\n\ + \ timeout: 5\n\ + \ retryLimit: 5\n\ + \ setSuspendInactiveUsers:\n\ + \ suspendTimeout: 10\n\ + \ setRichInfoLimit: 5000\n\ + \ setDefaultUserLocale: en\n\ + \ setMaxTeamSize: 32\n\ + \ setMaxConvSize: 16\n\ + \ setEmailVisibility: visible_to_self\n\ + \ setPropertyMaxKeyLen: 1024\n\ + \ setPropertyMaxValueLen: 4096\n\ + \ setDeleteThrottleMillis: 0\n\ + \ setSqsThrottleMillis: 1000\n\ + \ setRestrictUserCreation: false\n\ + \ setFederationDomain: example.com\n\ + \ setFeatureFlags:\n\ + \ conferenceCalling:\n\ + \ defaultForNew:\n\ + \ status: disabled\n\ + \ defaultForNull:\n\ + \ status: disabled\n\ + \ setFederationDomainConfigsUpdateFreq: 1\n\ + \ setFederationStrategy: allowAll\n\ + \ setFederationDomainConfigs:\n\ + \ - domain: example.com\n\ + \ search_policy: full_search\n\ + \ setDisabledAPIVersions: []\n\ + \ set2FACodeGenerationDelaySecs: 5\n\ + \ setNonceTtlSecs: 5\n\ + \ setDpopMaxSkewSecs: 1\n\ + \ setDpopTokenExpirationTimeSecs: 300\n\ + \ setPublicKeyBundle: test/resources/jwt/ecdsa_secp256r1_sha256_key.pem\n\ + \ setEnableMLS: true\n\ + \ setOAuthJwkKeyPair: test/resources/oauth/ed25519.jwk\n\ + \ setOAuthAuthCodeExpirationTimeSecs: 3\n\ + \ setOAuthAccessTokenExpirationTimeSecs: 3\n\ + \ setOAuthEnabled: true\n\ + \ setOAuthRefreshTokenExpirationTimeSecs: 14515200\n\ + \ setOAuthMaxActiveRefreshTokens: 10\n\ + \ setPasswordHashingOptions:\n\ + \ algorithm: argon2id\n\ + \ iterations: 1\n\ + \ memory: 128\n\ + \ parallelism: 1\n\ + \logLevel: Warn\n\ + \logNetStrings: false\n" + + o = + B.Opts + { brig = Endpoint {host = "0.0.0.0", port = 8082}, + cargohold = Endpoint {host = "127.0.0.1", port = 8084}, + galley = Endpoint {host = "127.0.0.1", port = 8085}, + gundeck = Endpoint {host = "127.0.0.1", port = 8086}, + federatorInternal = Just (Endpoint {host = "127.0.0.1", port = 8097}), + cassandra = + CassandraOpts + { endpoint = Endpoint {host = "127.0.0.1", port = 9042}, + keyspace = "brig_test", + filterNodesByDatacentre = Nothing, + tlsCa = Nothing + }, + elasticsearch = + B.ElasticSearchOpts + { url = ES.Server "https://localhost:9200", + index = ES.IndexName "directory_test", + additionalWriteIndex = Nothing, + additionalWriteIndexUrl = Nothing, + credentials = Just (FilePathSecrets "test/resources/elasticsearch-credentials.yaml"), + additionalCredentials = Just (FilePathSecrets "test/resources/elasticsearch-credentials.yaml"), + insecureSkipVerifyTls = False, + caCert = Just "test/resources/elasticsearch-ca.pem", + additionalInsecureSkipVerifyTls = False, + additionalCaCert = Just "test/resources/elasticsearch-ca.pem" + }, + multiSFT = Just False, + rabbitmq = + Just + ( AmqpEndpoint + { host = "127.0.0.1", + port = 5671, + vHost = "/", + tls = Just (RabbitMqTlsOpts {caCert = Just "test/resources/rabbitmq-ca.pem", insecureSkipVerifyTls = False}) + } + ), + aws = + B.AWSOpts + { userJournalQueue = Just "integration-user-events.fifo", + prekeyTable = "integration-brig-prekeys", + sqsEndpoint = AWSEndpoint {_awsHost = "localhost", _awsSecure = False, _awsPort = 4568}, + dynamoDBEndpoint = Nothing + }, + randomPrekeys = Just True, + stompOptions = Nothing, + emailSMS = + B.EmailSMSOpts + { email = + B.EmailAWS + ( B.EmailAWSOpts + { sesQueue = "integration-brig-events", + sesEndpoint = AWSEndpoint {_awsHost = "localhost", _awsSecure = False, _awsPort = 4569} + } + ), + general = + B.EmailSMSGeneralOpts + { templateDir = "deb/opt/brig/templates", + emailSender = unsafeEmailAddress "backend-integration" "wire.com", + smsSender = "+123456789", + templateBranding = + B.BrandingOpts + { brand = "Wire", + brandUrl = "https://wire.com", + brandLabelUrl = "wire.com", + brandLogoUrl = "https://wire.com/p/img/email/logo-email-black.png", + brandService = "Wire Service Provider", + copyright = "WIRE SWISS GmbH", + misuse = "misuse@wire.com", + legal = "https://wire.com/legal/", + forgot = "https://wire.com/forgot/", + support = "https://support.wire.com/" + } + }, + user = + B.EmailUserOpts + { activationUrl = "http://127.0.0.1:8080/activate?key=${key}&code=${code}", + smsActivationUrl = "http://127.0.0.1:8080/v/${code}", + passwordResetUrl = "http://127.0.0.1:8080/password-reset/${key}?code=${code}", + deletionUrl = "http://127.0.0.1:8080/users/delete?key=${key}&code=${code}" + }, + provider = + B.ProviderOpts + { homeUrl = "https://provider.localhost/", + providerActivationUrl = "http://127.0.0.1:8080/provider/activate?key=${key}&code=${code}", + approvalUrl = "http://127.0.0.1:8080/provider/approve?key=${key}&code=${code}", + approvalTo = unsafeEmailAddress "success" "simulator.amazonses.com", + providerPwResetUrl = "http://127.0.0.1:8080/provider/password-reset?key=${key}&code=${code}" + }, + team = + B.TeamOpts + { tInvitationUrl = "http://127.0.0.1:8080/register?team=${team}&team_code=${code}", + tExistingUserInvitationUrl = "http://127.0.0.1:8080/accept-invitation?team-code=${code}", + tActivationUrl = "http://127.0.0.1:8080/register?team=${team}&team_code=${code}", + tCreatorWelcomeUrl = "http://127.0.0.1:8080/creator-welcome-website", + tMemberWelcomeUrl = "http://127.0.0.1:8080/member-welcome-website" + } + }, + zauth = + B.ZAuthOpts + { privateKeys = "test/resources/zauth/privkeys.txt", + publicKeys = "test/resources/zauth/pubkeys.txt", + authSettings = ZAuth.Settings 1 120 20 30 60 120 30 + }, + discoUrl = Nothing, + internalEvents = B.InternalEventsOpts {internalEventsQueue = Queue.SqsQueueOpts "integration-brig-events-internal"}, + logLevel = Warn, + logNetStrings = Just (Last {getLast = False}), + logFormat = Nothing, + turn = + B.TurnOpts + { serversSource = + B.TurnSourceFiles + ( B.TurnServersFiles + { tsfServers = "test/resources/turn/servers.txt", + tsfServersV2 = "test/resources/turn/servers-v2.txt" + } + ), + secret = "test/resources/turn/secret.txt", + tokenTTL = 21600, + configTTL = 3600 + }, + sft = Nothing, + settings = + B.Settings + { activationTimeout = 4, + verificationCodeTimeoutInternal = Just (Code.Timeout {Code.timeoutDiffTime = 4}), + teamInvitationTimeout = 4, + expiredUserCleanupTimeout = Just 1, + stomp = Nothing, + allowlistEmailDomains = Nothing, + userMaxConnections = 16, + userMaxPermClients = Nothing, + cookieInsecure = True, + userCookieRenewAge = 2, + userCookieLimit = 5, + userCookieThrottle = CookieLimit.StdDevThrottle (CookieLimit.StdDev 5.0) (RetryAfter {retryAfterSeconds = 3}), + limitFailedLogins = Just (B.LimitFailedLogins {timeout = 5, retryLimit = 5}), + suspendInactiveUsers = Just (B.SuspendInactiveUsers {suspendTimeout = 10}), + richInfoLimit = 5000, + defaultTemplateLocaleInternal = Nothing, + defaultUserLocaleInternal = (Just . fromJust) (parseLocale "en"), + maxTeamSize = 32, + maxConvSize = 16, + providerSearchFilter = Nothing, + emailVisibility = EmailVisibleToSelf, + propertyMaxKeyLen = Just 1024, + propertyMaxValueLen = Just 4096, + deleteThrottleMillis = Just 0, + searchSameTeamOnly = Nothing, + federationDomain = Domain {_domainText = "example.com"}, + federationStrategy = Just AllowAll, + federationDomainConfigs = + Just + [ B.ImplicitNoFederationRestriction + { federationDomainConfig = + FederationDomainConfig + { domain = Domain {_domainText = "example.com"}, + searchPolicy = FullSearch, + restriction = FederationRestrictionAllowAll + } + } + ], + federationDomainConfigsUpdateFreq = Just 1, + sqsThrottleMillis = Just 1000, + restrictUserCreation = Just False, + featureFlags = + Just + ( B.UserFeatureFlags + { conferenceCalling = + B.ConferenceCallingUserStatus + { forNew = Just FeatureStatusDisabled, + forNull = FeatureStatusDisabled + } + } + ), + customerExtensions = Nothing, + sftStaticUrl = Nothing, + sftListAllServers = Nothing, + enableMLS = Just True, + keyPackageMaximumLifetime = Nothing, + disabledAPIVersions = fromList [], + twoFACodeGenerationDelaySecsInternal = Just 5, + nonceTtlSecsInternal = Just (NonceTtlSecs {unNonceTtlSecs = 5}), + dpopMaxSkewSecsInternal = Just 1, + dpopTokenExpirationTimeSecsInternal = Just 300, + publicKeyBundle = Just "test/resources/jwt/ecdsa_secp256r1_sha256_key.pem", + oAuthJwkKeyPair = Just "test/resources/oauth/ed25519.jwk", + oAuthAccessTokenExpirationTimeSecsInternal = Just 3, + oAuthAuthorizationCodeExpirationTimeSecsInternal = Nothing, + oAuthEnabledInternal = Just True, + oAuthRefreshTokenExpirationTimeSecsInternal = Just 14515200, + oAuthMaxActiveRefreshTokensInternal = Just 10, + passwordHashingOptions = PasswordHashingArgon2id (Argon2idOptions {iterations = 1, memory = 128, parallelism = 1}) + } + } + + (prettyPrintParseException `first` decodeEither' i) `shouldBe` Right o diff --git a/libs/wire-subsystems/wire-subsystems.cabal b/libs/wire-subsystems/wire-subsystems.cabal index 2e591f788d..a8fe67ba1a 100644 --- a/libs/wire-subsystems/wire-subsystems.cabal +++ b/libs/wire-subsystems/wire-subsystems.cabal @@ -116,6 +116,13 @@ library Wire.PropertySubsystem Wire.PropertySubsystem.Interpreter Wire.Rpc + Wire.ServerOptions.Brig + Wire.ServerOptions.Brig.CookieLimit + Wire.ServerOptions.Brig.Queue + Wire.ServerOptions.Brig.ZAuth + Wire.ServerOptions.Cannon + Wire.ServerOptions.Gundeck + Wire.ServerOptions.Spar Wire.SessionStore Wire.SessionStore.Cassandra Wire.StoredUser @@ -166,6 +173,7 @@ library , currency-codes , data-default , data-timeout + , dns , errors , exceptions , extended @@ -186,6 +194,8 @@ library , mime-mail , network , network-conduit-tls + , openapi3 + , optparse-applicative , polysemy , polysemy-plugin , polysemy-time @@ -199,10 +209,12 @@ library , schema-profunctor , servant , servant-client-core + , shakespeare , stomp-queue , template , text , text-icu-translit + , text-latin1 , time , time-out , time-units @@ -218,6 +230,7 @@ library , wire-api-federation , wire-otel , witherable + , yaml default-language: GHC2021 @@ -257,6 +270,7 @@ test-suite wire-subsystems-tests Wire.MockInterpreters.VerificationCodeStore Wire.NotificationSubsystem.InterpreterSpec Wire.PropertySubsystem.InterpreterSpec + Wire.ServerOptionsSpec Wire.UserSearch.TypesSpec Wire.UserStoreSpec Wire.UserSubsystem.InterpreterSpec @@ -266,13 +280,17 @@ test-suite wire-subsystems-tests build-depends: , aeson , async + , attoparsec , base , bilge + , bloodhound , bytestring , cassandra-util , containers , crypton , data-default + , dns + , email-validate , errors , extended , hspec @@ -302,3 +320,4 @@ test-suite wire-subsystems-tests , wire-api , wire-api-federation , wire-subsystems + , yaml diff --git a/services/brig/brig.cabal b/services/brig/brig.cabal index 29cc881005..2ae612d8ba 100644 --- a/services/brig/brig.cabal +++ b/services/brig/brig.cabal @@ -128,7 +128,6 @@ library Brig.IO.Intra Brig.IO.Journal Brig.IO.Logging - Brig.Options Brig.Provider.API Brig.Provider.DB Brig.Provider.Email @@ -136,7 +135,6 @@ library Brig.Provider.Template Brig.Queue Brig.Queue.Stomp - Brig.Queue.Types Brig.RPC Brig.Run Brig.Schema.Run @@ -257,7 +255,6 @@ library , imports , insert-ordered-containers , iproute >=1.5 - , iso639 >=0.1 , jose , jwt-tools , lens >=3.8 diff --git a/services/brig/default.nix b/services/brig/default.nix index ed77acac6e..f1c547b5fe 100644 --- a/services/brig/default.nix +++ b/services/brig/default.nix @@ -65,7 +65,6 @@ , imports , insert-ordered-containers , iproute -, iso639 , jose , jwt-tools , lens @@ -214,7 +213,6 @@ mkDerivation { imports insert-ordered-containers iproute - iso639 jose jwt-tools lens diff --git a/services/brig/src/Brig/API/Auth.hs b/services/brig/src/Brig/API/Auth.hs index 3821d6b453..25fb262321 100644 --- a/services/brig/src/Brig/API/Auth.hs +++ b/services/brig/src/Brig/API/Auth.hs @@ -21,7 +21,6 @@ import Brig.API.Error import Brig.API.Handler import Brig.API.Types import Brig.App -import Brig.Options import Brig.User.Auth qualified as Auth import Brig.ZAuth hiding (Env, settings) import Control.Monad.Trans.Except @@ -55,6 +54,7 @@ import Wire.BlockListStore import Wire.EmailSubsystem (EmailSubsystem) import Wire.Events (Events) import Wire.GalleyAPIAccess +import Wire.ServerOptions.Brig import Wire.UserKeyStore import Wire.UserStore import Wire.UserSubsystem (UpdateOriginType (..), UserSubsystem) diff --git a/services/brig/src/Brig/API/Client.hs b/services/brig/src/Brig/API/Client.hs index 9a94f88065..30bb11ab7c 100644 --- a/services/brig/src/Brig/API/Client.hs +++ b/services/brig/src/Brig/API/Client.hs @@ -61,7 +61,6 @@ import Brig.Federation.Client (getUserClients) import Brig.Federation.Client qualified as Federation import Brig.IO.Intra (guardLegalhold) import Brig.IO.Intra qualified as Intra -import Brig.Options qualified as Opt import Brig.Types.Intra import Brig.Types.Team.LegalHold (LegalHoldClientRequest (..)) import Brig.User.Auth qualified as UserAuth @@ -114,6 +113,7 @@ import Wire.NotificationSubsystem import Wire.Sem.Concurrency import Wire.Sem.FromUTC (FromUTC (fromUTCTime)) import Wire.Sem.Now as Now +import Wire.ServerOptions.Brig qualified as Opt import Wire.UserSubsystem (UserSubsystem) import Wire.UserSubsystem qualified as User import Wire.VerificationCodeSubsystem (VerificationCodeSubsystem) diff --git a/services/brig/src/Brig/API/Connection.hs b/services/brig/src/Brig/API/Connection.hs index 7dbbc0b86a..08317a91c5 100644 --- a/services/brig/src/Brig/API/Connection.hs +++ b/services/brig/src/Brig/API/Connection.hs @@ -43,7 +43,6 @@ import Brig.Data.Types (resultHasMore, resultList) import Brig.Data.User qualified as Data import Brig.IO.Intra qualified as Intra import Brig.IO.Logging -import Brig.Options import Brig.Types.Connection import Control.Error import Control.Monad.Catch (throwM) @@ -70,6 +69,7 @@ import Wire.FederationConfigStore import Wire.GalleyAPIAccess import Wire.GalleyAPIAccess qualified as GalleyAPIAccess import Wire.NotificationSubsystem +import Wire.ServerOptions.Brig import Wire.UserStore import Wire.UserSubsystem diff --git a/services/brig/src/Brig/API/Connection/Remote.hs b/services/brig/src/Brig/API/Connection/Remote.hs index 0bf4c398d5..b568b82579 100644 --- a/services/brig/src/Brig/API/Connection/Remote.hs +++ b/services/brig/src/Brig/API/Connection/Remote.hs @@ -30,7 +30,6 @@ import Brig.Data.Connection qualified as Data import Brig.Data.User qualified as Data import Brig.Federation.Client as Federation import Brig.IO.Intra qualified as Intra -import Brig.Options import Control.Comonad import Control.Error.Util ((??)) import Control.Monad.Trans.Except @@ -52,6 +51,7 @@ import Wire.API.UserEvent import Wire.FederationConfigStore import Wire.GalleyAPIAccess import Wire.NotificationSubsystem +import Wire.ServerOptions.Brig import Wire.UserStore data LocalConnectionAction diff --git a/services/brig/src/Brig/API/Connection/Util.hs b/services/brig/src/Brig/API/Connection/Util.hs index e256ff373f..970b6e48bd 100644 --- a/services/brig/src/Brig/API/Connection/Util.hs +++ b/services/brig/src/Brig/API/Connection/Util.hs @@ -26,7 +26,6 @@ where import Brig.API.Types import Brig.App import Brig.Data.Connection qualified as Data -import Brig.Options (Settings (userMaxConnections)) import Control.Error (MaybeT, noteT) import Control.Monad.Trans.Except import Data.Id (UserId) @@ -34,6 +33,7 @@ import Data.Qualified import Imports import Polysemy import Wire.API.Connection (Relation (..)) +import Wire.ServerOptions.Brig (Settings (userMaxConnections)) import Wire.UserStore type ConnectionM r = ExceptT ConnectionError (AppT r) diff --git a/services/brig/src/Brig/API/Federation.hs b/services/brig/src/Brig/API/Federation.hs index 02e1c04031..bda0178c30 100644 --- a/services/brig/src/Brig/API/Federation.hs +++ b/services/brig/src/Brig/API/Federation.hs @@ -32,7 +32,6 @@ import Brig.App import Brig.Data.Connection qualified as Data import Brig.Data.User qualified as Data import Brig.IO.Intra (notify) -import Brig.Options import Brig.User.API.Handle import Brig.User.Search.SearchIndex qualified as Q import Control.Error.Util @@ -74,6 +73,7 @@ import Wire.FederationConfigStore qualified as E import Wire.GalleyAPIAccess (GalleyAPIAccess) import Wire.NotificationSubsystem import Wire.Sem.Concurrency +import Wire.ServerOptions.Brig import Wire.UserStore import Wire.UserSubsystem (UserSubsystem) import Wire.UserSubsystem qualified as UserSubsystem diff --git a/services/brig/src/Brig/API/Handler.hs b/services/brig/src/Brig/API/Handler.hs index c664cd3f0e..cb7a5e2ff7 100644 --- a/services/brig/src/Brig/API/Handler.hs +++ b/services/brig/src/Brig/API/Handler.hs @@ -33,7 +33,6 @@ import Brig.API.Error import Brig.AWS qualified as AWS import Brig.App import Brig.CanonicalInterpreter (BrigCanonicalEffects, runBrigToIO) -import Brig.Options (allowlistEmailDomains) import Control.Error import Control.Exception (throwIO) import Control.Monad.Catch (catches, throwM) @@ -55,6 +54,7 @@ import Wire.API.Error import Wire.API.Error.Brig import Wire.API.User import Wire.Error +import Wire.ServerOptions.Brig (allowlistEmailDomains) ------------------------------------------------------------------------------- -- HTTP Handler Monad diff --git a/services/brig/src/Brig/API/Internal.hs b/services/brig/src/Brig/API/Internal.hs index 75a80dde93..466cd1460c 100644 --- a/services/brig/src/Brig/API/Internal.hs +++ b/services/brig/src/Brig/API/Internal.hs @@ -38,7 +38,6 @@ import Brig.Data.Connection qualified as Data import Brig.Data.MLS.KeyPackage qualified as Data import Brig.Data.User qualified as Data import Brig.Effects.UserPendingActivationStore (UserPendingActivationStore) -import Brig.Options hiding (internalEvents) import Brig.Provider.API qualified as Provider import Brig.Team.API qualified as Team import Brig.Types.Connection @@ -111,6 +110,7 @@ import Wire.PasswordResetCodeStore (PasswordResetCodeStore) import Wire.PropertySubsystem import Wire.Rpc import Wire.Sem.Concurrency +import Wire.ServerOptions.Brig hiding (internalEvents) import Wire.TeamInvitationSubsystem import Wire.UserKeyStore import Wire.UserStore as UserStore diff --git a/services/brig/src/Brig/API/MLS/KeyPackages/Validation.hs b/services/brig/src/Brig/API/MLS/KeyPackages/Validation.hs index 6a2d428748..f317a330dd 100644 --- a/services/brig/src/Brig/API/MLS/KeyPackages/Validation.hs +++ b/services/brig/src/Brig/API/MLS/KeyPackages/Validation.hs @@ -27,7 +27,6 @@ import Brig.API.Error import Brig.API.Handler import Brig.App import Brig.Data.Client qualified as Data -import Brig.Options import Control.Applicative import Data.ByteString qualified as LBS import Data.Qualified @@ -42,6 +41,7 @@ import Wire.API.MLS.KeyPackage import Wire.API.MLS.Lifetime import Wire.API.MLS.Serialisation import Wire.API.MLS.Validation +import Wire.ServerOptions.Brig validateUploadedKeyPackage :: ClientIdentity -> diff --git a/services/brig/src/Brig/API/MLS/Util.hs b/services/brig/src/Brig/API/MLS/Util.hs index b23308d55b..38de570e9c 100644 --- a/services/brig/src/Brig/API/MLS/Util.hs +++ b/services/brig/src/Brig/API/MLS/Util.hs @@ -21,9 +21,9 @@ import Brig.API.Error import Brig.API.Handler import Brig.App import Brig.Data.Client -import Brig.Options import Control.Error import Imports +import Wire.ServerOptions.Brig isMLSEnabled :: Handler r Bool isMLSEnabled = fromMaybe False <$> asks (.settings.enableMLS) diff --git a/services/brig/src/Brig/API/OAuth.hs b/services/brig/src/Brig/API/OAuth.hs index 9176f14553..96d59c3e3d 100644 --- a/services/brig/src/Brig/API/OAuth.hs +++ b/services/brig/src/Brig/API/OAuth.hs @@ -26,7 +26,6 @@ where import Brig.API.Error (throwStd) import Brig.API.Handler (Handler) import Brig.App -import Brig.Options qualified as Opt import Cassandra hiding (Set) import Cassandra qualified as C import Control.Error @@ -64,6 +63,7 @@ import Wire.Sem.Jwk import Wire.Sem.Jwk qualified as Jwk import Wire.Sem.Now (Now) import Wire.Sem.Now qualified as Now +import Wire.ServerOptions.Brig qualified as Opt -------------------------------------------------------------------------------- -- API Internal diff --git a/services/brig/src/Brig/API/Public.hs b/services/brig/src/Brig/API/Public.hs index 8b3b484e23..4dc8df26f5 100644 --- a/services/brig/src/Brig/API/Public.hs +++ b/services/brig/src/Brig/API/Public.hs @@ -20,8 +20,8 @@ module Brig.API.Public ( servantSitemap, - docsAPI, - DocsAPI, + docsAndOptionsAPI, + DocsAndOptionsAPI, ) where @@ -46,7 +46,6 @@ import Brig.Effects.JwtTools (JwtTools) import Brig.Effects.PublicKeyBundle (PublicKeyBundle) import Brig.Effects.SFT import Brig.Effects.UserPendingActivationStore (UserPendingActivationStore) -import Brig.Options hiding (internalEvents) import Brig.Provider.API import Brig.Team.API qualified as Team import Brig.Team.Email qualified as Team @@ -61,6 +60,7 @@ import Control.Lens ((.~), (?~)) import Control.Monad.Catch (throwM) import Control.Monad.Except import Data.Aeson hiding (json) +import Data.Aeson.Types qualified as A import Data.ByteString (fromStrict, toStrict) import Data.ByteString.Lazy.Char8 qualified as LBS import Data.ByteString.UTF8 qualified as UTF8 @@ -74,10 +74,12 @@ import Data.Handle qualified as Handle import Data.HavePendingInvitations import Data.Id import Data.Id qualified as Id +import Data.Json.Util import Data.List.NonEmpty (nonEmpty) import Data.Map.Strict qualified as Map import Data.Nonce (Nonce, randomNonce) import Data.OpenApi qualified as S +import Data.OpenApi.Declare qualified as S import Data.Qualified import Data.Range import Data.Schema () @@ -168,6 +170,8 @@ import Wire.Sem.Concurrency import Wire.Sem.Jwk (Jwk) import Wire.Sem.Now (Now) import Wire.Sem.Paging.Cassandra +import Wire.ServerOptions.Brig hiding (internalEvents) +import Wire.ServerOptions.Cannon qualified import Wire.TeamInvitationSubsystem import Wire.UserKeyStore import Wire.UserSearch.Types @@ -183,6 +187,33 @@ import Wire.VerificationCodeSubsystem -- User API ----------------------------------------------------------- +type DocsAndOptionsAPI = DocsAPI :<|> ServerOptionsDocsAPI + +docsAndOptionsAPI :: Servant.Server DocsAndOptionsAPI +docsAndOptionsAPI = docsAPI :<|> serverOptionsDocsAPI + +-- TODO: write a test for this end-point! +serverOptionsDocsAPI :: Servant.Server ServerOptionsDocsAPI +serverOptionsDocsAPI = Named @"server-config-options" $ pure allOptsSchema + where + allOptsSchema = + mkJsonObject + ( [ "brig" .= ("comping up!" :: Text), -- TODO: use schema-profunctor, then connect here. + "galley" .= ("comping up!" :: Text), -- TODO: move to wire-subsystems. + "spar" .= ("comping up!" :: Text), -- TODO: use schema-profunctor, then connect here. + "gundeck" .= ("comping up!" :: Text), -- TODO: get it to compile. + "cannon" .= describeOpts (Proxy @Wire.ServerOptions.Cannon.Opts), + "cargohold" .= ("comping up!" :: Text), -- TODO + "federator" .= ("comping up!" :: Text), -- TODO + "proxy" .= ("comping up!" :: Text), -- TODO + "background-worker" .= ("comping up!" :: Text) -- TODO + ] :: + [A.Pair] + ) + + describeOpts :: (S.ToSchema a) => Proxy a -> A.Value + describeOpts prx = toJSON $ S.runDeclare (S.declareSchema prx) mempty + docsAPI :: Servant.Server DocsAPI docsAPI = versionedSwaggerDocsAPI diff --git a/services/brig/src/Brig/API/User.hs b/services/brig/src/Brig/API/User.hs index 8c6a2e6fb6..f0322527ef 100644 --- a/services/brig/src/Brig/API/User.hs +++ b/services/brig/src/Brig/API/User.hs @@ -79,7 +79,6 @@ import Brig.Effects.ConnectionStore import Brig.Effects.UserPendingActivationStore (UserPendingActivation (..), UserPendingActivationStore) import Brig.Effects.UserPendingActivationStore qualified as UserPendingActivationStore import Brig.IO.Intra qualified as Intra -import Brig.Options hiding (internalEvents) import Brig.Team.Email import Brig.Types.Activation (ActivationPair) import Brig.Types.Intra @@ -145,6 +144,7 @@ import Wire.PasswordStore (PasswordStore, lookupHashedPassword, upsertHashedPass import Wire.PropertySubsystem as PropertySubsystem import Wire.Sem.Concurrency import Wire.Sem.Paging.Cassandra +import Wire.ServerOptions.Brig hiding (internalEvents) import Wire.UserKeyStore import Wire.UserStore import Wire.UserSubsystem as User diff --git a/services/brig/src/Brig/AWS.hs b/services/brig/src/Brig/AWS.hs index 1d86abdc0f..0111f70401 100644 --- a/services/brig/src/Brig/AWS.hs +++ b/services/brig/src/Brig/AWS.hs @@ -48,7 +48,6 @@ import Amazonka.DynamoDB qualified as DDB import Amazonka.SES qualified as SES import Amazonka.SQS qualified as SQS import Amazonka.SQS.Lens qualified as SQS -import Brig.Options qualified as Opt import Control.Lens hiding ((.=)) import Control.Monad.Catch import Control.Monad.Trans.Resource @@ -68,6 +67,7 @@ import UnliftIO.Async import UnliftIO.Exception import Util.Options import Wire.AWS +import Wire.ServerOptions.Brig qualified as Opt data Env = Env { _logger :: !Logger, diff --git a/services/brig/src/Brig/App.hs b/services/brig/src/Brig/App.hs index eb7b06457e..7bfd8421b5 100644 --- a/services/brig/src/Brig/App.hs +++ b/services/brig/src/Brig/App.hs @@ -98,11 +98,8 @@ import Bilge.RPC (HasRequestId (..)) import Brig.AWS qualified as AWS import Brig.Calling qualified as Calling import Brig.DeleteQueue.Interpreter -import Brig.Options (ElasticSearchOpts, Opts, Settings (..)) -import Brig.Options qualified as Opt import Brig.Provider.Template import Brig.Queue.Stomp qualified as Stomp -import Brig.Queue.Types import Brig.Schema.Run qualified as Migrations import Brig.Team.Template import Brig.Template (Localised, genTemplateBranding) @@ -157,6 +154,9 @@ import Wire.API.Routes.Version import Wire.API.User.Identity import Wire.EmailSending.SMTP qualified as SMTP import Wire.EmailSubsystem.Template (TemplateBranding, forLocale) +import Wire.ServerOptions.Brig (ElasticSearchOpts, Opts, Settings (..)) +import Wire.ServerOptions.Brig qualified as Opt +import Wire.ServerOptions.Brig.Queue import Wire.SessionStore import Wire.SessionStore.Cassandra import Wire.UserKeyStore diff --git a/services/brig/src/Brig/Calling.hs b/services/brig/src/Brig/Calling.hs index 8c1c2749d3..3cfa765863 100644 --- a/services/brig/src/Brig/Calling.hs +++ b/services/brig/src/Brig/Calling.hs @@ -48,8 +48,6 @@ module Brig.Calling ) where -import Brig.Options (SFTOptions (..), defSftListLength, defSftServiceName, defSrvDiscoveryIntervalSeconds) -import Brig.Options qualified as Opts import Control.Exception.Enclosed (handleAny) import Control.Lens import Control.Monad.Random.Class (MonadRandom) @@ -81,6 +79,8 @@ import Wire.Network.DNS.Effect import Wire.Network.DNS.SRV import Wire.Sem.Delay import Wire.Sem.Logger.TinyLog +import Wire.ServerOptions.Brig (SFTOptions (..), defSftListLength, defSftServiceName, defSrvDiscoveryIntervalSeconds) +import Wire.ServerOptions.Brig qualified as Opts -- | NOTE SFTServers: -- Retrieving SFTServers should give a 1) randomized and 2) limited list of servers. diff --git a/services/brig/src/Brig/Calling/API.hs b/services/brig/src/Brig/Calling/API.hs index bc5ae8d601..7c3339f49a 100644 --- a/services/brig/src/Brig/Calling/API.hs +++ b/services/brig/src/Brig/Calling/API.hs @@ -37,8 +37,6 @@ import Brig.Calling import Brig.Calling qualified as Calling import Brig.Calling.Internal import Brig.Effects.SFT -import Brig.Options (ListAllSFTServers (..)) -import Brig.Options qualified as Opt import Control.Error (hush, throwE) import Control.Lens import Crypto.Hash qualified as Crypto @@ -64,6 +62,8 @@ import Wire.API.Team.Feature import Wire.Error import Wire.GalleyAPIAccess (GalleyAPIAccess, getAllTeamFeaturesForUser) import Wire.Network.DNS.SRV (srvTarget) +import Wire.ServerOptions.Brig (ListAllSFTServers (..)) +import Wire.ServerOptions.Brig qualified as Opt -- | ('UserId', 'ConnId' are required as args here to make sure this is an authenticated end-point.) getCallsConfigV2 :: diff --git a/services/brig/src/Brig/CanonicalInterpreter.hs b/services/brig/src/Brig/CanonicalInterpreter.hs index 18e53608df..6a221618fa 100644 --- a/services/brig/src/Brig/CanonicalInterpreter.hs +++ b/services/brig/src/Brig/CanonicalInterpreter.hs @@ -11,8 +11,6 @@ import Brig.Effects.SFT (SFT, interpretSFT) import Brig.Effects.UserPendingActivationStore (UserPendingActivationStore) import Brig.Effects.UserPendingActivationStore.Cassandra (userPendingActivationStoreToCassandra) import Brig.IO.Intra (runEvents) -import Brig.Options (federationDomainConfigs, federationStrategy) -import Brig.Options qualified as Opt import Brig.Team.Template (TeamTemplates) import Brig.User.Search.Index (IndexEnv (..)) import Cassandra qualified as Cas @@ -83,6 +81,8 @@ import Wire.Sem.Now.IO (nowToIOAction) import Wire.Sem.Paging.Cassandra (InternalPaging) import Wire.Sem.Random import Wire.Sem.Random.IO +import Wire.ServerOptions.Brig (federationDomainConfigs, federationStrategy) +import Wire.ServerOptions.Brig qualified as Opt import Wire.SessionStore import Wire.SessionStore.Cassandra (interpretSessionStoreCassandra) import Wire.TeamInvitationSubsystem diff --git a/services/brig/src/Brig/Data/MLS/KeyPackage.hs b/services/brig/src/Brig/Data/MLS/KeyPackage.hs index 20f95a40af..1544ef06f2 100644 --- a/services/brig/src/Brig/Data/MLS/KeyPackage.hs +++ b/services/brig/src/Brig/Data/MLS/KeyPackage.hs @@ -26,7 +26,6 @@ where import Brig.API.MLS.KeyPackages.Validation import Brig.App -import Brig.Options import Cassandra import Control.Arrow import Control.Error @@ -42,6 +41,7 @@ import Wire.API.MLS.CipherSuite import Wire.API.MLS.KeyPackage import Wire.API.MLS.LeafNode import Wire.API.MLS.Serialisation +import Wire.ServerOptions.Brig insertKeyPackages :: (MonadClient m) => diff --git a/services/brig/src/Brig/Data/User.hs b/services/brig/src/Brig/Data/User.hs index 326ef1cb78..be39c880de 100644 --- a/services/brig/src/Brig/Data/User.hs +++ b/services/brig/src/Brig/Data/User.hs @@ -51,7 +51,6 @@ module Brig.Data.User where import Brig.App -import Brig.Options import Brig.Types.Intra import Brig.ZAuth qualified as ZAuth import Cassandra hiding (Set) @@ -75,6 +74,7 @@ import Wire.API.Team.Feature import Wire.API.User import Wire.API.User.RichInfo import Wire.HashPassword +import Wire.ServerOptions.Brig -- | Preconditions: -- diff --git a/services/brig/src/Brig/Index/Eval.hs b/services/brig/src/Brig/Index/Eval.hs index 64dd9ebca5..6225c7045e 100644 --- a/services/brig/src/Brig/Index/Eval.hs +++ b/services/brig/src/Brig/Index/Eval.hs @@ -22,7 +22,6 @@ where import Brig.App (initHttpManagerWithTLSConfig, mkIndexEnv) import Brig.Index.Options -import Brig.Options import Brig.User.Search.Index import Cassandra (Client, runClient) import Cassandra.Options @@ -70,6 +69,7 @@ import Wire.Sem.Concurrency.IO import Wire.Sem.Logger.TinyLog import Wire.Sem.Metrics import Wire.Sem.Metrics.IO +import Wire.ServerOptions.Brig import Wire.UserKeyStore (UserKeyStore) import Wire.UserKeyStore.Cassandra import Wire.UserSearch.Migration (MigrationException) diff --git a/services/brig/src/Brig/InternalEvent/Process.hs b/services/brig/src/Brig/InternalEvent/Process.hs index d9c6f32abd..a4354f04d4 100644 --- a/services/brig/src/Brig/InternalEvent/Process.hs +++ b/services/brig/src/Brig/InternalEvent/Process.hs @@ -22,7 +22,6 @@ import Brig.App import Brig.IO.Intra (rmClient) import Brig.IO.Intra qualified as Intra import Brig.InternalEvent.Types -import Brig.Options (defDeleteThrottleMillis, deleteThrottleMillis) import Brig.Provider.API qualified as API import Control.Monad.Catch import Data.ByteString.Conversion @@ -39,6 +38,7 @@ import Wire.Events (Events) import Wire.NotificationSubsystem import Wire.PropertySubsystem import Wire.Sem.Delay +import Wire.ServerOptions.Brig (defDeleteThrottleMillis, deleteThrottleMillis) import Wire.UserKeyStore import Wire.UserStore (UserStore) import Wire.UserSubsystem diff --git a/services/brig/src/Brig/Provider/API.hs b/services/brig/src/Brig/Provider/API.hs index 162a110906..a9edac8db2 100644 --- a/services/brig/src/Brig/Provider/API.hs +++ b/services/brig/src/Brig/Provider/API.hs @@ -36,8 +36,6 @@ import Brig.API.Types (PasswordResetError (..)) import Brig.App import Brig.Data.Client qualified as User import Brig.Data.User qualified as User -import Brig.Options (Settings (..)) -import Brig.Options qualified as Opt import Brig.Provider.DB (ServiceConn (..)) import Brig.Provider.DB qualified as DB import Brig.Provider.Email @@ -130,6 +128,8 @@ import Wire.GalleyAPIAccess qualified as GalleyAPIAccess import Wire.HashPassword (HashPassword) import Wire.HashPassword qualified as HashPassword import Wire.Sem.Concurrency (Concurrency, ConcurrencySafety (Unsafe)) +import Wire.ServerOptions.Brig (Settings (..)) +import Wire.ServerOptions.Brig qualified as Opt import Wire.UserKeyStore (mkEmailKey) import Wire.UserSubsystem import Wire.UserSubsystem.Error diff --git a/services/brig/src/Brig/Provider/Template.hs b/services/brig/src/Brig/Provider/Template.hs index 2c50f22fcd..1e8defc783 100644 --- a/services/brig/src/Brig/Provider/Template.hs +++ b/services/brig/src/Brig/Provider/Template.hs @@ -29,7 +29,6 @@ module Brig.Provider.Template ) where -import Brig.Options import Brig.Template import Data.ByteString.Conversion (fromByteString) import Data.Misc (HttpsUrl) @@ -37,6 +36,7 @@ import Data.Text.Encoding (encodeUtf8) import Imports import Wire.API.User.Identity import Wire.EmailSubsystem.Template +import Wire.ServerOptions.Brig data ProviderTemplates = ProviderTemplates { activationEmail :: !ActivationEmailTemplate, diff --git a/services/brig/src/Brig/Queue.hs b/services/brig/src/Brig/Queue.hs index 3772b57fc0..dbfcc2faee 100644 --- a/services/brig/src/Brig/Queue.hs +++ b/services/brig/src/Brig/Queue.hs @@ -17,7 +17,7 @@ -- | Working with remote queues (like Amazon SQS). module Brig.Queue - ( module Brig.Queue.Types, + ( module Wire.ServerOptions.Brig.Queue, listen, ) where @@ -25,11 +25,11 @@ where import Brig.AWS qualified as AWS import Brig.DeleteQueue.Interpreter (QueueEnv (..)) import Brig.Queue.Stomp qualified as Stomp -import Brig.Queue.Types import Control.Monad.Catch import Data.Aeson import Imports import System.Logger.Class as Log hiding (settings) +import Wire.ServerOptions.Brig.Queue -- | Forever listen to messages coming from a queue and execute a callback -- for each incoming message. diff --git a/services/brig/src/Brig/Queue/Stomp.hs b/services/brig/src/Brig/Queue/Stomp.hs index 631f790013..c55c8222bb 100644 --- a/services/brig/src/Brig/Queue/Stomp.hs +++ b/services/brig/src/Brig/Queue/Stomp.hs @@ -27,7 +27,6 @@ module Brig.Queue.Stomp where import BasePrelude hiding (Handler, throwIO) -import Brig.Options qualified as Opts import Codec.MIME.Type qualified as MIME import Control.Monad.Catch (Handler (..), MonadMask) import Control.Retry hiding (retryPolicy) @@ -39,6 +38,7 @@ import Data.Text.Encoding import Network.Mom.Stompl.Client.Queue hiding (try) import System.Logger.Class as Log import UnliftIO (MonadUnliftIO, throwIO, withRunInIO) +import Wire.ServerOptions.Brig qualified as Opts data Env = Env { -- | STOMP broker that we're using diff --git a/services/brig/src/Brig/Run.hs b/services/brig/src/Brig/Run.hs index 2bd43d585e..ce50832814 100644 --- a/services/brig/src/Brig/Run.hs +++ b/services/brig/src/Brig/Run.hs @@ -31,7 +31,6 @@ import Brig.CanonicalInterpreter import Brig.Effects.UserPendingActivationStore (UserPendingActivation (UserPendingActivation), UserPendingActivationStore) import Brig.Effects.UserPendingActivationStore qualified as UsersPendingActivationStore import Brig.InternalEvent.Process qualified as Internal -import Brig.Options hiding (internalEvents, sesQueue) import Brig.Queue qualified as Queue import Brig.Version import Control.Concurrent.Async qualified as Async @@ -72,6 +71,7 @@ import Wire.API.User (AccountStatus (PendingInvitation)) import Wire.DeleteQueue import Wire.OpenTelemetry (withTracer) import Wire.Sem.Paging qualified as P +import Wire.ServerOptions.Brig hiding (internalEvents, sesQueue) import Wire.UserStore -- FUTUREWORK: If any of these async threads die, we will have no clue about it @@ -134,7 +134,7 @@ mkApp opts = do Servant.serveWithContext (Proxy @ServantCombinedAPI) (customFormatters :. localDomain :. Servant.EmptyContext) - ( docsAPI + ( docsAndOptionsAPI :<|> hoistServerWithDomain @BrigAPI (toServantHandler env) servantSitemap :<|> hoistServerWithDomain @IAPI.API (toServantHandler env) IAPI.servantSitemap :<|> hoistServerWithDomain @FederationAPI (toServantHandler env) federationSitemap @@ -159,7 +159,7 @@ internalHandleCompatibilityMiddleware app req k = k type ServantCombinedAPI = - ( DocsAPI + ( DocsAndOptionsAPI :<|> BrigAPI :<|> IAPI.API :<|> FederationAPI diff --git a/services/brig/src/Brig/Team/Template.hs b/services/brig/src/Brig/Team/Template.hs index 86c409e9f6..2f97ce1ca3 100644 --- a/services/brig/src/Brig/Team/Template.hs +++ b/services/brig/src/Brig/Team/Template.hs @@ -27,10 +27,10 @@ module Brig.Team.Template ) where -import Brig.Options import Brig.Template import Imports import Wire.EmailSubsystem.Template +import Wire.ServerOptions.Brig loadTeamTemplates :: Opts -> IO (Localised TeamTemplates) loadTeamTemplates o = readLocalesDir defLocale (templateDir gOptions) "team" $ \fp -> diff --git a/services/brig/src/Brig/Template.hs b/services/brig/src/Brig/Template.hs index 906f395d8e..54ccba25db 100644 --- a/services/brig/src/Brig/Template.hs +++ b/services/brig/src/Brig/Template.hs @@ -34,7 +34,6 @@ module Brig.Template ) where -import Brig.Options import Control.Exception (catchJust) import Data.ByteString qualified as BS import Data.Map.Strict qualified as Map @@ -45,6 +44,7 @@ import Imports hiding (readFile) import System.IO.Error (isDoesNotExistError) import Wire.API.User import Wire.EmailSubsystem.Template (Localised (Localised)) +import Wire.ServerOptions.Brig -- | See 'genTemplateBranding'. type TemplateBranding = Text -> Text diff --git a/services/brig/src/Brig/User/API/Handle.hs b/services/brig/src/Brig/User/API/Handle.hs index 0b97637255..5d9b034cbf 100644 --- a/services/brig/src/Brig/User/API/Handle.hs +++ b/services/brig/src/Brig/User/API/Handle.hs @@ -29,7 +29,6 @@ import Brig.API.User qualified as API import Brig.App import Brig.Data.User qualified as Data import Brig.Federation.Client qualified as Federation -import Brig.Options (searchSameTeamOnly) import Data.Handle (Handle, fromHandle) import Data.Id (UserId) import Data.Qualified @@ -41,6 +40,7 @@ import Wire.API.User import Wire.API.User qualified as Public import Wire.API.User.Search import Wire.API.User.Search qualified as Public +import Wire.ServerOptions.Brig (searchSameTeamOnly) import Wire.UserStore (UserStore) import Wire.UserSubsystem diff --git a/services/brig/src/Brig/User/Auth.hs b/services/brig/src/Brig/User/Auth.hs index b8e6556f4a..590e099940 100644 --- a/services/brig/src/Brig/User/Auth.hs +++ b/services/brig/src/Brig/User/Auth.hs @@ -39,7 +39,6 @@ import Brig.API.User (changeSingleAccountStatus) import Brig.App import Brig.Budget import Brig.Data.Client -import Brig.Options qualified as Opt import Brig.Types.Intra import Brig.User.Auth.Cookie import Brig.ZAuth qualified as ZAuth @@ -77,6 +76,7 @@ import Wire.AuthenticationSubsystem qualified as Authentication import Wire.Events (Events) import Wire.GalleyAPIAccess (GalleyAPIAccess) import Wire.GalleyAPIAccess qualified as GalleyAPIAccess +import Wire.ServerOptions.Brig qualified as Opt import Wire.UserKeyStore import Wire.UserStore import Wire.UserSubsystem (UserSubsystem) diff --git a/services/brig/src/Brig/User/Auth/Cookie.hs b/services/brig/src/Brig/User/Auth/Cookie.hs index 081d23c1d3..5a313bcdc6 100644 --- a/services/brig/src/Brig/User/Auth/Cookie.hs +++ b/services/brig/src/Brig/User/Auth/Cookie.hs @@ -40,7 +40,6 @@ module Brig.User.Auth.Cookie where import Brig.App -import Brig.Options hiding (user) import Brig.User.Auth.Cookie.Limit import Brig.ZAuth qualified as ZAuth import Cassandra @@ -60,6 +59,7 @@ import System.Logger.Class qualified as Log import Util.Timeout import Web.Cookie qualified as WebCookie import Wire.API.User.Auth +import Wire.ServerOptions.Brig hiding (user) import Wire.SessionStore qualified as Store -------------------------------------------------------------------------------- diff --git a/services/brig/src/Brig/User/Auth/Cookie/Limit.hs b/services/brig/src/Brig/User/Auth/Cookie/Limit.hs index 034f3ced85..d9ed7c3ccf 100644 --- a/services/brig/src/Brig/User/Auth/Cookie/Limit.hs +++ b/services/brig/src/Brig/User/Auth/Cookie/Limit.hs @@ -17,7 +17,6 @@ module Brig.User.Auth.Cookie.Limit where -import Data.Aeson import Data.RetryAfter import Data.Time.Clock import Data.Time.Clock.POSIX @@ -25,6 +24,7 @@ import Data.Vector qualified as Vector import Imports import Statistics.Sample qualified as Stats import Wire.API.User.Auth +import Wire.ServerOptions.Brig.CookieLimit -------------------------------------------------------------------------------- -- Quantitive Limiting @@ -59,27 +59,6 @@ limitCookies lim now cs -------------------------------------------------------------------------------- -- Temporal Throttling --- | The fields are: --- --- * Min. standard deviation cookie creation --- * Wait time when the min deviation is violated --- --- Both fields are in seconds. -data CookieThrottle - = StdDevThrottle StdDev RetryAfter - deriving (Show) - -newtype StdDev = StdDev Double - deriving (Eq, Ord, Show, Generic) - -instance FromJSON StdDev - -instance FromJSON CookieThrottle where - parseJSON = withObject "User.Auth.Cookie.Limit.CookieThrottle" $ \o -> - StdDevThrottle - <$> o .: "stdDev" - <*> (RetryAfter <$> o .: "retryAfter") - -- | Check that the standard deviation of cookie creation dates is /higher/ -- than the specified minimum. If the standard deviation is below the -- minimum, check if the specified wait time (i.e. penalty) is over to diff --git a/services/brig/src/Brig/User/Template.hs b/services/brig/src/Brig/User/Template.hs index 110d979bc8..2d70dfed46 100644 --- a/services/brig/src/Brig/User/Template.hs +++ b/services/brig/src/Brig/User/Template.hs @@ -37,10 +37,10 @@ module Brig.User.Template ) where -import Brig.Options qualified as Opt import Brig.Template import Imports import Wire.EmailSubsystem.Template +import Wire.ServerOptions.Brig qualified as Opt loadUserTemplates :: Opt.Opts -> IO (Localised UserTemplates) loadUserTemplates o = readLocalesDir defLocale templateDir "user" $ \fp -> diff --git a/services/brig/src/Brig/ZAuth.hs b/services/brig/src/Brig/ZAuth.hs index 512e1251b9..9a6e028249 100644 --- a/services/brig/src/Brig/ZAuth.hs +++ b/services/brig/src/Brig/ZAuth.hs @@ -31,17 +31,8 @@ module Brig.ZAuth Env, mkEnv, readKeys, - - -- * Settings settings, - Settings (..), - defSettings, localSettings, - keyIndex, - SessionTokenTimeout (..), - sessionTokenTimeout, - ProviderTokenTimeout (..), - providerTokenTimeout, -- * timeout settings for access and legalholdaccess settingsTTL, @@ -80,6 +71,7 @@ module Brig.ZAuth zauthType, -- * Re-exports + module Wire.ServerOptions.Brig.ZAuth, SecretKey, PublicKey, ) @@ -87,7 +79,6 @@ where import Control.Lens (Lens', makeLenses, over, (.~), (^.)) import Control.Monad.Catch -import Data.Aeson import Data.Bits import Data.ByteString qualified as BS import Data.ByteString.Conversion @@ -105,6 +96,7 @@ import Imports import OpenSSL.Random import Sodium.Crypto.Sign import Wire.API.User.Auth qualified as Auth +import Wire.ServerOptions.Brig.ZAuth newtype ZAuth a = ZAuth {unZAuth :: ReaderT Env IO a} deriving (Functor, Applicative, Monad, MonadIO, MonadReader Env) @@ -118,99 +110,12 @@ instance MonadZAuth ZAuth where runZAuth :: (MonadIO m) => Env -> ZAuth a -> m a runZAuth e za = liftIO $ runReaderT (unZAuth za) e -data Settings = Settings - { -- | Secret key index to use - -- for token creation - _keyIndex :: !Int, - -- | User token validity timeout - _userTokenTimeout :: !UserTokenTimeout, - -- | Session token validity timeout - _sessionTokenTimeout :: !SessionTokenTimeout, - -- | Access token validity timeout - _accessTokenTimeout :: !AccessTokenTimeout, - -- | Proider token validity timeout - _providerTokenTimeout :: !ProviderTokenTimeout, - -- | Legal Hold User token validity timeout - _legalHoldUserTokenTimeout :: !LegalHoldUserTokenTimeout, - -- | Legal Hold Access token validity timeout - _legalHoldAccessTokenTimeout :: !LegalHoldAccessTokenTimeout - } - deriving (Show, Generic) - -defSettings :: Settings -defSettings = - Settings - 1 - (UserTokenTimeout (60 * 60 * 24 * 28)) -- 28 days - (SessionTokenTimeout (60 * 60 * 24)) -- 1 day - (AccessTokenTimeout 900) -- 15 minutes - (ProviderTokenTimeout (60 * 60 * 24 * 7)) -- 7 days - (LegalHoldUserTokenTimeout (60 * 60 * 24 * 56)) -- 56 days - (LegalHoldAccessTokenTimeout (60 * 15)) -- 15 minutes - data Env = Env { _private :: !ZC.Env, _public :: !ZV.Env, _settings :: !Settings } -newtype UserTokenTimeout = UserTokenTimeout - {_userTokenTimeoutSeconds :: Integer} - deriving (Show, Generic) - -newtype SessionTokenTimeout = SessionTokenTimeout - {sessionTokenTimeoutSeconds :: Integer} - deriving (Show, Generic) - -newtype AccessTokenTimeout = AccessTokenTimeout - {_accessTokenTimeoutSeconds :: Integer} - deriving (Show, Generic) - -newtype ProviderTokenTimeout = ProviderTokenTimeout - {providerTokenTimeoutSeconds :: Integer} - deriving (Show, Generic) - -newtype LegalHoldUserTokenTimeout = LegalHoldUserTokenTimeout - {_legalHoldUserTokenTimeoutSeconds :: Integer} - deriving (Show, Generic) - -newtype LegalHoldAccessTokenTimeout = LegalHoldAccessTokenTimeout - {_legalHoldAccessTokenTimeoutSeconds :: Integer} - deriving (Show, Generic) - -instance FromJSON UserTokenTimeout - -instance FromJSON SessionTokenTimeout - -instance FromJSON AccessTokenTimeout - -instance FromJSON ProviderTokenTimeout - -instance FromJSON LegalHoldAccessTokenTimeout - -instance FromJSON LegalHoldUserTokenTimeout - -instance FromJSON Settings where - parseJSON = withObject "ZAuth.Settings" $ \o -> - Settings - <$> o .: "keyIndex" - <*> (UserTokenTimeout <$> o .: "userTokenTimeout") - <*> (SessionTokenTimeout <$> o .: "sessionTokenTimeout") - <*> (AccessTokenTimeout <$> o .: "accessTokenTimeout") - <*> (ProviderTokenTimeout <$> o .: "providerTokenTimeout") - <*> (LegalHoldUserTokenTimeout <$> o .: "legalHoldUserTokenTimeout") - <*> (LegalHoldAccessTokenTimeout <$> o .: "legalHoldAccessTokenTimeout") - -makeLenses ''LegalHoldAccessTokenTimeout - -makeLenses ''AccessTokenTimeout - -makeLenses ''UserTokenTimeout - -makeLenses ''LegalHoldUserTokenTimeout - -makeLenses ''Settings - makeLenses ''Env localSettings :: (Settings -> Settings) -> ZAuth a -> ZAuth a diff --git a/services/brig/test/integration/API/Calling.hs b/services/brig/test/integration/API/Calling.hs index ce9b2bebbf..212aaec452 100644 --- a/services/brig/test/integration/API/Calling.hs +++ b/services/brig/test/integration/API/Calling.hs @@ -22,7 +22,6 @@ module API.Calling where import Bilge import Bilge.Assert -import Brig.Options qualified as Opts import Control.Lens (view, (.~), (?~), (^.)) import Control.Monad.Catch (MonadCatch) import Data.Bifunctor (Bifunctor (first)) @@ -44,6 +43,7 @@ import UnliftIO.Temporary qualified as Temp import Util import Wire.API.Call.Config import Wire.API.User +import Wire.ServerOptions.Brig qualified as Opts tests :: Manager -> Brig -> Opts.Opts -> FilePath -> FilePath -> IO TestTree tests m b opts turn turnV2 = do diff --git a/services/brig/test/integration/API/Federation.hs b/services/brig/test/integration/API/Federation.hs index b25a380291..861873c4bf 100644 --- a/services/brig/test/integration/API/Federation.hs +++ b/services/brig/test/integration/API/Federation.hs @@ -21,7 +21,6 @@ module API.Federation where import API.Search.Util (refreshIndex) import Bilge hiding (head) import Bilge.Assert -import Brig.Options qualified as Opt import Control.Arrow (Arrow (first), (&&&)) import Control.Lens ((?~)) import Data.Aeson @@ -49,6 +48,7 @@ import Wire.API.User.Client import Wire.API.User.Client.Prekey import Wire.API.User.Search import Wire.API.UserMap (UserMap (UserMap)) +import Wire.ServerOptions.Brig qualified as Opt -- Note: POST /federation/send-connection-action is implicitly tested in API.User.Connection tests :: Manager -> Opt.Opts -> Brig -> FedClient 'Brig -> IO TestTree diff --git a/services/brig/test/integration/API/Internal.hs b/services/brig/test/integration/API/Internal.hs index 55a713d321..eab18a78a4 100644 --- a/services/brig/test/integration/API/Internal.hs +++ b/services/brig/test/integration/API/Internal.hs @@ -27,7 +27,6 @@ import API.MLS.Util import Bilge import Bilge.Assert import Brig.Data.User -import Brig.Options qualified as Opt import Cassandra qualified as C import Cassandra qualified as Cass import Cassandra.Util @@ -44,6 +43,7 @@ import Util import Util.Options (Endpoint) import Wire.API.User import Wire.API.User.Client +import Wire.ServerOptions.Brig qualified as Opt type TestConstraints m = (MonadFail m, MonadCatch m, MonadIO m, MonadHttp m) diff --git a/services/brig/test/integration/API/Metrics.hs b/services/brig/test/integration/API/Metrics.hs index cc93b37cca..7afef5a8fa 100644 --- a/services/brig/test/integration/API/Metrics.hs +++ b/services/brig/test/integration/API/Metrics.hs @@ -26,7 +26,6 @@ where import Bilge import Bilge.Assert -import Brig.Options qualified as Opt import Data.Attoparsec.Text import Data.ByteString.Conversion import Imports @@ -34,6 +33,7 @@ import Test.Tasty import Test.Tasty.HUnit import Util import Wire.API.User +import Wire.ServerOptions.Brig qualified as Opt tests :: Manager -> Opt.Opts -> Brig -> IO TestTree tests manager opts brig = do diff --git a/services/brig/test/integration/API/OAuth.hs b/services/brig/test/integration/API/OAuth.hs index dc54cd254d..51d44d0d31 100644 --- a/services/brig/test/integration/API/OAuth.hs +++ b/services/brig/test/integration/API/OAuth.hs @@ -22,8 +22,6 @@ import API.Team.Util qualified as Team import Bilge import Bilge.Assert import Brig.API.OAuth hiding (verifyRefreshToken) -import Brig.Options -import Brig.Options qualified as Opt import Cassandra qualified as C import Control.Lens import Control.Monad.Catch (MonadCatch) @@ -62,6 +60,8 @@ import Wire.API.Routes.Bearer (Bearer (Bearer, unBearer)) import Wire.API.User as User import Wire.API.User.Auth (CookieType (PersistentCookie)) import Wire.Sem.Jwk (readJwk) +import Wire.ServerOptions.Brig +import Wire.ServerOptions.Brig qualified as Opt tests :: Manager -> C.ClientState -> Brig -> Nginz -> Opts -> TestTree tests m db b n o = do diff --git a/services/brig/test/integration/API/Search.hs b/services/brig/test/integration/API/Search.hs index 14832d5e37..b40da72ad5 100644 --- a/services/brig/test/integration/API/Search.hs +++ b/services/brig/test/integration/API/Search.hs @@ -33,8 +33,6 @@ import API.User.Util import Bilge import Bilge.Assert import Brig.App (initHttpManagerWithTLSConfig) -import Brig.Options qualified as Opt -import Brig.Options qualified as Opts import Control.Lens ((.~), (?~), (^.)) import Control.Monad.Catch (MonadCatch, MonadThrow) import Control.Retry @@ -71,6 +69,8 @@ import Wire.API.Team.SearchVisibility import Wire.API.User as User import Wire.API.User.Search import Wire.API.User.Search qualified as Search +import Wire.ServerOptions.Brig qualified as Opt +import Wire.ServerOptions.Brig qualified as Opts tests :: Opt.Opts -> Manager -> Galley -> Brig -> IO TestTree tests opts mgr galley brig = do diff --git a/services/brig/test/integration/API/Settings.hs b/services/brig/test/integration/API/Settings.hs index 3647a4463b..7ac03e5e5b 100644 --- a/services/brig/test/integration/API/Settings.hs +++ b/services/brig/test/integration/API/Settings.hs @@ -20,8 +20,6 @@ module API.Settings (tests) where import API.Team.Util import Bilge hiding (accept, timeout) import Bilge.Assert -import Brig.Options (Opts) -import Brig.Options qualified as Opt import Control.Arrow ((&&&)) import Control.Lens import Data.Aeson @@ -38,6 +36,8 @@ import Wire.API.Team.Member (rolePermissions) import Wire.API.Team.Permission import Wire.API.Team.Role import Wire.API.User +import Wire.ServerOptions.Brig (Opts) +import Wire.ServerOptions.Brig qualified as Opt allEmailVisibilities :: [EmailVisibilityConfig] allEmailVisibilities = [EmailVisibleIfOnTeam, EmailVisibleIfOnSameTeam (), EmailVisibleToSelf] diff --git a/services/brig/test/integration/API/SystemSettings.hs b/services/brig/test/integration/API/SystemSettings.hs index 265d2d43dd..e0fbe25830 100644 --- a/services/brig/test/integration/API/SystemSettings.hs +++ b/services/brig/test/integration/API/SystemSettings.hs @@ -19,7 +19,6 @@ module API.SystemSettings (tests) where import Bilge import Bilge.Assert -import Brig.Options import Control.Lens import Data.ByteString.Char8 qualified as BS import Data.ByteString.Conversion (toByteString') @@ -32,6 +31,7 @@ import Test.Tasty.HUnit import Util import Wire.API.Routes.Version import Wire.API.SystemSettings +import Wire.ServerOptions.Brig tests :: Opts -> Manager -> IO TestTree tests opts m = pure $ do diff --git a/services/brig/test/integration/API/Team.hs b/services/brig/test/integration/API/Team.hs index d4599cc0fc..341dc916b7 100644 --- a/services/brig/test/integration/API/Team.hs +++ b/services/brig/test/integration/API/Team.hs @@ -28,7 +28,6 @@ import API.User.Util as Util import Bilge hiding (accept, head, timeout) import Bilge qualified import Bilge.Assert -import Brig.Options qualified as Opt import Control.Arrow ((&&&)) import Control.Lens hiding ((.=)) import Control.Monad.Catch (MonadCatch) @@ -76,6 +75,7 @@ import Wire.API.Team.Size import Wire.API.User import Wire.API.User.Auth import Wire.API.User.Client (ClientType (PermanentClientType)) +import Wire.ServerOptions.Brig qualified as Opt newtype TeamSizeLimit = TeamSizeLimit Word32 diff --git a/services/brig/test/integration/API/TeamUserSearch.hs b/services/brig/test/integration/API/TeamUserSearch.hs index 0301b8eaa4..38d7fd77a0 100644 --- a/services/brig/test/integration/API/TeamUserSearch.hs +++ b/services/brig/test/integration/API/TeamUserSearch.hs @@ -21,7 +21,6 @@ import API.Search.Util (executeTeamUserSearch, executeTeamUserSearchWithMaybeSta import API.Team.Util (createPopulatedBindingTeamWithNamesAndHandles) import API.User.Util (activateEmail, initiateEmailUpdateNoSend) import Bilge (Manager, MonadHttp) -import Brig.Options qualified as Opt import Control.Monad.Catch (MonadCatch) import Control.Retry () import Data.ByteString.Conversion (toByteString) @@ -37,6 +36,7 @@ import Util (Brig, Galley, randomEmail, test, withSettingsOverrides) import Wire.API.User (User (..), userEmail, userId) import Wire.API.User.Identity hiding (toByteString) import Wire.API.User.Search +import Wire.ServerOptions.Brig qualified as Opt type TestConstraints m = (MonadFail m, MonadCatch m, MonadIO m, MonadHttp m) diff --git a/services/brig/test/integration/API/User.hs b/services/brig/test/integration/API/User.hs index 95e26d13ef..df9555cb5b 100644 --- a/services/brig/test/integration/API/User.hs +++ b/services/brig/test/integration/API/User.hs @@ -30,7 +30,6 @@ import API.User.RichInfo qualified import API.User.Util import Bilge hiding (accept, timeout) import Brig.AWS qualified as AWS -import Brig.Options qualified as Opt import Brig.ZAuth qualified as ZAuth import Cassandra qualified as DB import Data.List.NonEmpty (NonEmpty ((:|))) @@ -40,6 +39,7 @@ import Util import Util.AWS (UserJournalWatcher) import Util.Options.Common import Wire.API.Federation.Component +import Wire.ServerOptions.Brig qualified as Opt tests :: Opt.Opts -> diff --git a/services/brig/test/integration/API/User/Account.hs b/services/brig/test/integration/API/User/Account.hs index e1757ba6a6..bbfd0a80c2 100644 --- a/services/brig/test/integration/API/User/Account.hs +++ b/services/brig/test/integration/API/User/Account.hs @@ -29,7 +29,6 @@ import Bilge hiding (accept, timeout) import Bilge.Assert import Brig.AWS qualified as AWS import Brig.AWS.Types -import Brig.Options qualified as Opt import Brig.Types.Activation import Brig.Types.Intra import Control.Arrow ((&&&)) @@ -93,6 +92,7 @@ import Wire.API.User.Activation import Wire.API.User.Auth import Wire.API.User.Auth qualified as Auth import Wire.API.User.Client +import Wire.ServerOptions.Brig qualified as Opt tests :: ConnectionLimit -> Timeout -> Opt.Opts -> Manager -> Brig -> Cannon -> CargoHold -> Galley -> AWS.Env -> UserJournalWatcher -> TestTree tests _ at opts p b c ch g aws userJournalWatcher = diff --git a/services/brig/test/integration/API/User/Auth.hs b/services/brig/test/integration/API/User/Auth.hs index a93fa99317..2cd05e56c3 100644 --- a/services/brig/test/integration/API/User/Auth.hs +++ b/services/brig/test/integration/API/User/Auth.hs @@ -28,7 +28,6 @@ import API.Team.Util import Bilge hiding (body) import Bilge qualified as Http import Bilge.Assert hiding (assert) -import Brig.Options qualified as Opts import Brig.ZAuth (ZAuth, runZAuth) import Brig.ZAuth qualified as ZAuth import Cassandra hiding (Value) @@ -71,6 +70,7 @@ import Wire.API.User.Auth.ReAuth import Wire.API.User.Auth.Sso import Wire.API.User.Client import Wire.HashPassword +import Wire.ServerOptions.Brig qualified as Opts -- | FUTUREWORK: Implement this function. This wrapper should make sure that -- wrapped tests run only when the feature flag 'legalhold' is set to diff --git a/services/brig/test/integration/API/User/Client.hs b/services/brig/test/integration/API/User/Client.hs index c73e81861f..32145b9594 100644 --- a/services/brig/test/integration/API/User/Client.hs +++ b/services/brig/test/integration/API/User/Client.hs @@ -30,7 +30,6 @@ import API.User.Util import API.User.Util qualified as Util import Bilge hiding (accept, head, timeout) import Bilge.Assert -import Brig.Options as Opt import Cassandra qualified as DB import Control.Lens hiding (Wrapped, (#)) import Crypto.JWT hiding (Ed25519, header, params) @@ -82,6 +81,7 @@ import Wire.API.User.Client.DPoPAccessToken import Wire.API.User.Client.Prekey import Wire.API.UserMap (QualifiedUserMap (..), UserMap (..), WrappedQualifiedUserMap) import Wire.API.Wrapped (Wrapped (..)) +import Wire.ServerOptions.Brig as Opt import Wire.VerificationCode qualified as Code import Wire.VerificationCodeGen diff --git a/services/brig/test/integration/API/User/Handles.hs b/services/brig/test/integration/API/User/Handles.hs index c505e9b824..67bb378145 100644 --- a/services/brig/test/integration/API/User/Handles.hs +++ b/services/brig/test/integration/API/User/Handles.hs @@ -26,7 +26,6 @@ import API.Team.Util import API.User.Util import Bilge hiding (accept, timeout) import Bilge.Assert -import Brig.Options qualified as Opt import Control.Lens hiding (from, (#)) import Control.Monad.Catch (MonadCatch) import Data.Aeson @@ -52,6 +51,7 @@ import Wire.API.Team.Feature (FeatureStatus (..)) import Wire.API.Team.SearchVisibility import Wire.API.User import Wire.API.User.Handle +import Wire.ServerOptions.Brig qualified as Opt tests :: ConnectionLimit -> Timeout -> Opt.Opts -> Manager -> Brig -> Cannon -> Galley -> TestTree tests _cl _at conf p b c g = diff --git a/services/brig/test/integration/API/User/RichInfo.hs b/services/brig/test/integration/API/User/RichInfo.hs index 453ba3394d..459a0038a9 100644 --- a/services/brig/test/integration/API/User/RichInfo.hs +++ b/services/brig/test/integration/API/User/RichInfo.hs @@ -25,8 +25,6 @@ import API.Team.Util (createTeamMember, createUserWithTeam) import API.User.Util import Bilge hiding (accept, timeout) import Bilge.Assert -import Brig.Options -import Brig.Options qualified as Opt import Data.CaseInsensitive qualified as CI import Data.List1 qualified as List1 import Data.Text qualified as Text @@ -38,6 +36,8 @@ import Util.Timeout import Wire.API.Team.Permission import Wire.API.User import Wire.API.User.RichInfo +import Wire.ServerOptions.Brig +import Wire.ServerOptions.Brig qualified as Opt tests :: ConnectionLimit -> Timeout -> Opt.Opts -> Manager -> Brig -> Cannon -> Galley -> TestTree tests _cl _at conf p b _c g = diff --git a/services/brig/test/integration/API/UserPendingActivation.hs b/services/brig/test/integration/API/UserPendingActivation.hs index b82eb25195..c549beaff0 100644 --- a/services/brig/test/integration/API/UserPendingActivation.hs +++ b/services/brig/test/integration/API/UserPendingActivation.hs @@ -24,7 +24,6 @@ module API.UserPendingActivation where import API.Team.Util (getTeam) import Bilge hiding (query) import Bilge.Assert (( Manager -> ClientState -> Brig -> Galley -> Spar -> IO TestTree tests opts m db brig galley spar = do diff --git a/services/brig/test/integration/Federation/End2end.hs b/services/brig/test/integration/Federation/End2end.hs index a19f1bc328..645fa71fa7 100644 --- a/services/brig/test/integration/Federation/End2end.hs +++ b/services/brig/test/integration/Federation/End2end.hs @@ -22,7 +22,6 @@ import API.User.Util import Bilge import Bilge.Assert ((!!!), ( Request diff --git a/services/brig/test/unit/Test/Brig/Calling.hs b/services/brig/test/unit/Test/Brig/Calling.hs index 0dcf489a12..c32c530431 100644 --- a/services/brig/test/unit/Test/Brig/Calling.hs +++ b/services/brig/test/unit/Test/Brig/Calling.hs @@ -24,7 +24,6 @@ import Brig.Calling import Brig.Calling.API import Brig.Calling.Internal import Brig.Effects.SFT -import Brig.Options import Control.Concurrent.Timeout qualified as System import Control.Lens ((^.)) import Control.Monad.Catch @@ -54,6 +53,7 @@ import Wire.Network.DNS.Effect import Wire.Network.DNS.SRV import Wire.Sem.Logger.Level import Wire.Sem.Logger.TinyLog +import Wire.ServerOptions.Brig data FakeDNSEnv = FakeDNSEnv { fakeLookupSrv :: Domain -> SrvResponse, diff --git a/services/cannon/cannon.cabal b/services/cannon/cannon.cabal index 1eb1b4cdd2..f0638023ca 100644 --- a/services/cannon/cannon.cabal +++ b/services/cannon/cannon.cabal @@ -22,7 +22,6 @@ library Cannon.API.Public Cannon.App Cannon.Dict - Cannon.Options Cannon.Run Cannon.Types Cannon.WS @@ -79,7 +78,6 @@ library build-depends: aeson >=2.0.1.0 - , api-field-json-th >=0.1.0.2 , async >=2.0 , base >=4.6 && <5 , bilge >=0.12 @@ -118,6 +116,7 @@ library , websockets >=0.11.2 , wire-api , wire-otel + , wire-subsystems default-language: GHC2021 diff --git a/services/cannon/default.nix b/services/cannon/default.nix index c0e94ff02f..3cfa4b0816 100644 --- a/services/cannon/default.nix +++ b/services/cannon/default.nix @@ -4,7 +4,6 @@ # dependencies are added or removed. { mkDerivation , aeson -, api-field-json-th , async , base , bilge @@ -52,6 +51,7 @@ , websockets , wire-api , wire-otel +, wire-subsystems }: mkDerivation { pname = "cannon"; @@ -61,7 +61,6 @@ mkDerivation { isExecutable = true; libraryHaskellDepends = [ aeson - api-field-json-th async base bilge @@ -100,6 +99,7 @@ mkDerivation { websockets wire-api wire-otel + wire-subsystems ]; executableHaskellDepends = [ base imports types-common ]; testHaskellDepends = [ diff --git a/services/cannon/src/Cannon/Run.hs b/services/cannon/src/Cannon/Run.hs index eefd22f4af..f648f0018b 100644 --- a/services/cannon/src/Cannon/Run.hs +++ b/services/cannon/src/Cannon/Run.hs @@ -26,7 +26,6 @@ import Cannon.API.Internal import Cannon.API.Public import Cannon.App (maxPingInterval) import Cannon.Dict qualified as D -import Cannon.Options import Cannon.Types (Cannon, applog, clients, env, mkEnv, runCannon, runCannonToServant) import Cannon.WS hiding (env) import Control.Concurrent @@ -61,6 +60,7 @@ import Wire.API.Routes.Public.Cannon import Wire.API.Routes.Version import Wire.API.Routes.Version.Wai import Wire.OpenTelemetry (withTracer) +import Wire.ServerOptions.Cannon type CombinedAPI = CannonAPI :<|> Internal.API diff --git a/services/cannon/src/Cannon/Types.hs b/services/cannon/src/Cannon/Types.hs index 6fa37b78a6..09af9ec0d8 100644 --- a/services/cannon/src/Cannon/Types.hs +++ b/services/cannon/src/Cannon/Types.hs @@ -36,7 +36,6 @@ where import Bilge (Manager) import Bilge.RPC (HasRequestId (..)) import Cannon.Dict (Dict) -import Cannon.Options import Cannon.WS (Clock, Key, Websocket) import Cannon.WS qualified as WS import Control.Concurrent.Async (mapConcurrently) @@ -50,6 +49,7 @@ import Servant qualified import System.Logger qualified as Logger import System.Logger.Class hiding (info) import System.Random.MWC (GenIO) +import Wire.ServerOptions.Cannon ----------------------------------------------------------------------------- -- Cannon monad diff --git a/services/cannon/src/Cannon/WS.hs b/services/cannon/src/Cannon/WS.hs index ea106f4cf0..5db5adea31 100644 --- a/services/cannon/src/Cannon/WS.hs +++ b/services/cannon/src/Cannon/WS.hs @@ -51,7 +51,6 @@ import Bilge.RPC import Bilge.Retry import Cannon.Dict (Dict) import Cannon.Dict qualified as D -import Cannon.Options (DrainOpts, gracePeriodSeconds, millisecondsBetweenBatches, minBatchSize) import Conduit import Control.Concurrent.Timeout import Control.Lens ((^.)) @@ -76,6 +75,7 @@ import System.Logger.Class hiding (Error, Settings, close, (.=)) import System.Random.MWC (GenIO, uniform) import UnliftIO.Async (async, cancel, pooledMapConcurrentlyN_) import Wire.API.Presence +import Wire.ServerOptions.Cannon (DrainOpts, gracePeriodSeconds, millisecondsBetweenBatches, minBatchSize) ----------------------------------------------------------------------------- -- Key diff --git a/services/gundeck/gundeck.cabal b/services/gundeck/gundeck.cabal index 19ce66fb3e..f7e9903ac7 100644 --- a/services/gundeck/gundeck.cabal +++ b/services/gundeck/gundeck.cabal @@ -29,7 +29,6 @@ library Gundeck.Monad Gundeck.Notification Gundeck.Notification.Data - Gundeck.Options Gundeck.Presence Gundeck.Presence.Data Gundeck.Push @@ -167,7 +166,7 @@ library , wai-utilities >=0.16 , wire-api , wire-otel - , yaml >=0.8 + , wire-subsystems default-language: GHC2021 diff --git a/services/gundeck/src/Gundeck/Aws/Arn.hs b/services/gundeck/src/Gundeck/Aws/Arn.hs index 6723ba223a..c7b08245ad 100644 --- a/services/gundeck/src/Gundeck/Aws/Arn.hs +++ b/services/gundeck/src/Gundeck/Aws/Arn.hs @@ -59,10 +59,7 @@ import Data.Attoparsec.Text import Data.Text qualified as Text import Imports import Wire.API.Push.V2 (AppName (..), Transport (..)) - -newtype ArnEnv = ArnEnv {arnEnvText :: Text} deriving (Show, ToText, FromJSON) - -newtype Account = Account {fromAccount :: Text} deriving (Eq, Ord, Show, ToText, FromJSON) +import Wire.ServerOptions.Gundeck newtype EndpointId = EndpointId Text deriving (Eq, Ord, Show, ToText) diff --git a/services/gundeck/src/Gundeck/ThreadBudget/Internal.hs b/services/gundeck/src/Gundeck/ThreadBudget/Internal.hs index 89595b9d51..43993d8aa7 100644 --- a/services/gundeck/src/Gundeck/ThreadBudget/Internal.hs +++ b/services/gundeck/src/Gundeck/ThreadBudget/Internal.hs @@ -29,13 +29,13 @@ import Data.Set qualified as Set import Data.Time import Data.UUID (UUID, toText) import Data.UUID.V4 (nextRandom) -import Gundeck.Options import Imports import Prometheus (MonadMonitor) import Prometheus qualified as Prom import System.Logger.Class qualified as LC import UnliftIO.Async import UnliftIO.Exception (finally) +import Wire.ServerOptions.Gundeck data ThreadBudgetState = ThreadBudgetState { threadBudgetLimits :: MaxConcurrentNativePushes, diff --git a/services/spar/exec/Main.hs b/services/spar/exec/Main.hs index 8eb5cf9a42..6539e6d29e 100644 --- a/services/spar/exec/Main.hs +++ b/services/spar/exec/Main.hs @@ -18,8 +18,8 @@ module Main where import Imports -import Spar.Options import Spar.Run +import Wire.ServerOptions.Spar main :: IO () main = runServer =<< getOpts diff --git a/services/spar/spar.cabal b/services/spar/spar.cabal index a9b452682e..794cc8e9be 100644 --- a/services/spar/spar.cabal +++ b/services/spar/spar.cabal @@ -25,7 +25,6 @@ library Spar.Intra.Brig Spar.Intra.BrigApp Spar.Intra.Galley - Spar.Options Spar.Orphans Spar.Run Spar.Schema.Run @@ -173,7 +172,6 @@ library , metrics-wai , mtl , network-uri - , optparse-applicative , polysemy , polysemy-check >=0.9 , polysemy-plugin @@ -185,7 +183,6 @@ library , servant-multipart , servant-server , text - , text-latin1 , these , time , tinylog @@ -200,7 +197,6 @@ library , warp , wire-api , wire-subsystems - , yaml default-language: Haskell2010 @@ -261,6 +257,7 @@ executable spar base , imports , spar + , wire-subsystems default-language: Haskell2010 @@ -397,6 +394,7 @@ executable spar-integration , wai-extra , wai-utilities , wire-api + , wire-subsystems , xml-conduit , yaml , zauth diff --git a/services/spar/src/Spar/API.hs b/services/spar/src/Spar/API.hs index cbf91970c4..98dbc200ff 100644 --- a/services/spar/src/Spar/API.hs +++ b/services/spar/src/Spar/API.hs @@ -71,7 +71,6 @@ import Spar.App import Spar.CanonicalInterpreter import Spar.Error import qualified Spar.Intra.BrigApp as Brig -import Spar.Options import Spar.Orphans () import Spar.Scim hiding (handle) import Spar.Sem.AReqIDStore (AReqIDStore) @@ -114,6 +113,7 @@ import qualified Wire.Sem.Logger as Logger import Wire.Sem.Now (Now) import Wire.Sem.Random (Random) import qualified Wire.Sem.Random as Random +import Wire.ServerOptions.Spar app :: Env -> Application app ctx0 req cont = do diff --git a/services/spar/src/Spar/App.hs b/services/spar/src/Spar/App.hs index 562776433b..eac936cd63 100644 --- a/services/spar/src/Spar/App.hs +++ b/services/spar/src/Spar/App.hs @@ -72,7 +72,6 @@ import Servant import qualified Servant.Multipart as Multipart import Spar.Error hiding (sparToServerErrorWithLogging) import qualified Spar.Intra.BrigApp as Intra -import Spar.Options import Spar.Orphans () import Spar.Sem.AReqIDStore (AReqIDStore) import Spar.Sem.BrigAccess (BrigAccess, getAccount) @@ -102,6 +101,7 @@ import Wire.Sem.Logger (Logger) import qualified Wire.Sem.Logger as Logger import Wire.Sem.Random (Random) import qualified Wire.Sem.Random as Random +import Wire.ServerOptions.Spar throwSparSem :: (Member (Error SparError) r) => SparCustomError -> Sem r a throwSparSem = throw . SAML.CustomError diff --git a/services/spar/src/Spar/CanonicalInterpreter.hs b/services/spar/src/Spar/CanonicalInterpreter.hs index 75170b8e2d..fdaad4cccc 100644 --- a/services/spar/src/Spar/CanonicalInterpreter.hs +++ b/services/spar/src/Spar/CanonicalInterpreter.hs @@ -33,7 +33,6 @@ import Polysemy.Input (Input, runInputConst) import Servant import Spar.App hiding (sparToServerErrorWithLogging) import Spar.Error -import Spar.Options import Spar.Orphans () import Spar.Sem.AReqIDStore (AReqIDStore) import Spar.Sem.AReqIDStore.Cassandra (aReqIDStoreToCassandra) @@ -74,6 +73,7 @@ import Wire.Sem.Now (Now) import Wire.Sem.Now.IO (nowToIO) import Wire.Sem.Random (Random) import Wire.Sem.Random.IO (randomToIO) +import Wire.ServerOptions.Spar type CanonicalEffs = '[ SAML2, diff --git a/services/spar/src/Spar/Data.hs b/services/spar/src/Spar/Data.hs index 919d1ddce4..f3ef628920 100644 --- a/services/spar/src/Spar/Data.hs +++ b/services/spar/src/Spar/Data.hs @@ -42,9 +42,9 @@ import Imports import SAML2.Util (renderURI) import qualified SAML2.WebSSO as SAML import qualified SAML2.WebSSO.Types.Email as SAMLEmail -import Spar.Options import qualified Spar.Schema.Run as Migrations import Wire.API.User.Saml +import Wire.ServerOptions.Spar -- | A lower bound: @schemaVersion <= whatWeFoundOnCassandra@, not @==@. schemaVersion :: Int32 diff --git a/services/spar/src/Spar/Run.hs b/services/spar/src/Spar/Run.hs index 170721df48..3bded78571 100644 --- a/services/spar/src/Spar/Run.hs +++ b/services/spar/src/Spar/Run.hs @@ -48,7 +48,6 @@ import Spar.API (SparAPI, app) import Spar.App import qualified Spar.Data as Data import Spar.Data.Instances () -import Spar.Options as Opt import Spar.Orphans () import System.Logger (Logger) import qualified System.Logger as Log @@ -57,6 +56,7 @@ import Util.Options import Wire.API.Routes.Version (expandVersionExp) import Wire.API.Routes.Version.Wai import Wire.Sem.Logger.TinyLog +import Wire.ServerOptions.Spar as Opt ---------------------------------------------------------------------- -- cassandra diff --git a/services/spar/src/Spar/Scim.hs b/services/spar/src/Spar/Scim.hs index 0d66908bbe..66ebeba671 100644 --- a/services/spar/src/Spar/Scim.hs +++ b/services/spar/src/Spar/Scim.hs @@ -78,7 +78,6 @@ import Spar.Error ( SparCustomError (SparScimError), SparError, ) -import Spar.Options import Spar.Scim.Auth import Spar.Scim.User import Spar.Sem.BrigAccess (BrigAccess) @@ -102,6 +101,7 @@ import Wire.API.User.Scim import Wire.Sem.Logger (Logger) import Wire.Sem.Now (Now) import Wire.Sem.Random (Random) +import Wire.ServerOptions.Spar -- | SCIM config for our server. -- diff --git a/services/spar/src/Spar/Scim/Auth.hs b/services/spar/src/Spar/Scim/Auth.hs index 5bad582605..d4890108b3 100644 --- a/services/spar/src/Spar/Scim/Auth.hs +++ b/services/spar/src/Spar/Scim/Auth.hs @@ -49,7 +49,6 @@ import Servant (NoContent (NoContent), ServerT, (:<|>) ((:<|>))) import Spar.App (throwSparSem) import qualified Spar.Error as E import qualified Spar.Intra.BrigApp as Intra.Brig -import Spar.Options import Spar.Sem.BrigAccess (BrigAccess) import qualified Spar.Sem.BrigAccess as BrigAccess import Spar.Sem.GalleyAccess (GalleyAccess) @@ -68,6 +67,7 @@ import Wire.Sem.Now (Now) import qualified Wire.Sem.Now as Now import Wire.Sem.Random (Random) import qualified Wire.Sem.Random as Random +import Wire.ServerOptions.Spar -- | An instance that tells @hscim@ how authentication should be done for SCIM routes. instance (Member ScimTokenStore r) => Scim.Class.Auth.AuthDB SparTag (Sem r) where diff --git a/services/spar/src/Spar/Scim/User.hs b/services/spar/src/Spar/Scim/User.hs index 019c20902a..c55f5ea501 100644 --- a/services/spar/src/Spar/Scim/User.hs +++ b/services/spar/src/Spar/Scim/User.hs @@ -76,7 +76,6 @@ import Spar.App (getUserByUrefUnsafe, getUserByUrefViaOldIssuerUnsafe, getUserId import qualified Spar.App import Spar.Intra.BrigApp as Intra import qualified Spar.Intra.BrigApp as Brig -import Spar.Options import Spar.Scim.Auth () import Spar.Scim.Types import qualified Spar.Scim.Types as ST @@ -120,6 +119,7 @@ import Wire.Sem.Now (Now) import qualified Wire.Sem.Now as Now import Wire.Sem.Random (Random) import qualified Wire.Sem.Random as Random +import Wire.ServerOptions.Spar ---------------------------------------------------------------------------- -- UserDB instance diff --git a/services/spar/src/Spar/Sem/AReqIDStore/Cassandra.hs b/services/spar/src/Spar/Sem/AReqIDStore/Cassandra.hs index 87a2ef9e55..845e3b8e2a 100644 --- a/services/spar/src/Spar/Sem/AReqIDStore/Cassandra.hs +++ b/services/spar/src/Spar/Sem/AReqIDStore/Cassandra.hs @@ -33,11 +33,11 @@ import Polysemy.Input (Input, input) import qualified SAML2.WebSSO as SAML import qualified Spar.Data as Data import Spar.Data.Instances () -import Spar.Options import Spar.Sem.AReqIDStore import Wire.API.User.Saml import Wire.Sem.Now (Now) import qualified Wire.Sem.Now as Now +import Wire.ServerOptions.Spar aReqIDStoreToCassandra :: forall m r a. diff --git a/services/spar/src/Spar/Sem/AssIDStore/Cassandra.hs b/services/spar/src/Spar/Sem/AssIDStore/Cassandra.hs index 877b2b3b6f..e75ab0da7c 100644 --- a/services/spar/src/Spar/Sem/AssIDStore/Cassandra.hs +++ b/services/spar/src/Spar/Sem/AssIDStore/Cassandra.hs @@ -33,11 +33,11 @@ import Polysemy.Input import qualified SAML2.WebSSO as SAML import qualified Spar.Data as Data import Spar.Data.Instances () -import Spar.Options import Spar.Sem.AssIDStore import Wire.API.User.Saml import Wire.Sem.Now (Now) import qualified Wire.Sem.Now as Now +import Wire.ServerOptions.Spar assIDStoreToCassandra :: forall m r a. diff --git a/services/spar/src/Spar/Sem/SAML2/Library.hs b/services/spar/src/Spar/Sem/SAML2/Library.hs index e728fe6d0b..fe9a62d799 100644 --- a/services/spar/src/Spar/Sem/SAML2/Library.hs +++ b/services/spar/src/Spar/Sem/SAML2/Library.hs @@ -34,7 +34,6 @@ import Polysemy.Internal.Tactics import SAML2.WebSSO hiding (Error) import qualified SAML2.WebSSO as SAML hiding (Error) import Spar.Error (SparCustomError (..), SparError) -import Spar.Options import Spar.Sem.AReqIDStore (AReqIDStore) import qualified Spar.Sem.AReqIDStore as AReqIDStore import Spar.Sem.AssIDStore (AssIDStore) @@ -45,6 +44,7 @@ import Spar.Sem.SAML2 import Wire.API.User.IdentityProvider (WireIdP) import Wire.Sem.Logger (Logger) import qualified Wire.Sem.Logger as Logger +import Wire.ServerOptions.Spar wrapMonadClientSPImpl :: ( Member (Error SparError) r, diff --git a/services/spar/test-integration/Test/Spar/APISpec.hs b/services/spar/test-integration/Test/Spar/APISpec.hs index 9f9b0773d1..65f50869e5 100644 --- a/services/spar/test-integration/Test/Spar/APISpec.hs +++ b/services/spar/test-integration/Test/Spar/APISpec.hs @@ -71,7 +71,6 @@ import SAML2.WebSSO.Test.Lenses import SAML2.WebSSO.Test.MockResponse import SAML2.WebSSO.Test.Util import qualified Spar.Intra.BrigApp as Intra -import Spar.Options import qualified Spar.Sem.AReqIDStore as AReqIDStore import qualified Spar.Sem.BrigAccess as BrigAccess import qualified Spar.Sem.IdPConfigStore as IdPEffect @@ -96,6 +95,7 @@ import Wire.API.User.Client import Wire.API.User.Client.Prekey import Wire.API.User.IdentityProvider import Wire.API.User.Scim hiding (handle) +import Wire.ServerOptions.Spar spec :: SpecWith TestEnv spec = do diff --git a/services/spar/test-integration/Test/Spar/DataSpec.hs b/services/spar/test-integration/Test/Spar/DataSpec.hs index f310a26539..7ec3e2195a 100644 --- a/services/spar/test-integration/Test/Spar/DataSpec.hs +++ b/services/spar/test-integration/Test/Spar/DataSpec.hs @@ -32,7 +32,6 @@ import SAML2.WebSSO as SAML import Spar.App as App import Spar.Error (IdpDbError (IdpNotFound), SparCustomError (IdpDbError)) import Spar.Intra.BrigApp (veidFromUserSSOId) -import Spar.Options import qualified Spar.Sem.AReqIDStore as AReqIDStore import qualified Spar.Sem.AssIDStore as AssIDStore import qualified Spar.Sem.IdPConfigStore as IdPEffect @@ -48,6 +47,7 @@ import Web.Scim.Schema.Common as Scim.Common import Web.Scim.Schema.Meta as Scim.Meta import Wire.API.User.IdentityProvider import Wire.API.User.Saml +import Wire.ServerOptions.Spar spec :: SpecWith TestEnv spec = do diff --git a/services/spar/test-integration/Test/Spar/Scim/UserSpec.hs b/services/spar/test-integration/Test/Spar/Scim/UserSpec.hs index 71a8eaee3f..fb2a94b336 100644 --- a/services/spar/test-integration/Test/Spar/Scim/UserSpec.hs +++ b/services/spar/test-integration/Test/Spar/Scim/UserSpec.hs @@ -63,7 +63,6 @@ import qualified SAML2.WebSSO.Test.MockResponse as SAML import SAML2.WebSSO.Test.Util.TestSP (makeSampleIdPMetadata) import qualified SAML2.WebSSO.Test.Util.Types as SAML import qualified Spar.Intra.BrigApp as Intra -import Spar.Options import Spar.Scim import Spar.Scim.Types (normalizeLikeStored) import qualified Spar.Scim.User as SU @@ -95,6 +94,7 @@ import qualified Wire.API.User.IdentityProvider as User import Wire.API.User.RichInfo import qualified Wire.API.User.Scim as Spar.Types import qualified Wire.API.User.Search as Search +import Wire.ServerOptions.Spar -- | Tests for @\/scim\/v2\/Users@. spec :: SpecWith TestEnv diff --git a/services/spar/test-integration/Util/Core.hs b/services/spar/test-integration/Util/Core.hs index 6d92d56e0d..143514733b 100644 --- a/services/spar/test-integration/Util/Core.hs +++ b/services/spar/test-integration/Util/Core.hs @@ -182,7 +182,6 @@ import qualified Spar.App as Spar import Spar.CanonicalInterpreter import Spar.Error (SparError) import qualified Spar.Intra.BrigApp as Intra -import Spar.Options import Spar.Run import Spar.Sem.BrigAccess (getAccount) import qualified Spar.Sem.IdPConfigStore as IdPConfigStore @@ -218,6 +217,7 @@ import Wire.API.User.Auth hiding (Cookie) import Wire.API.User.IdentityProvider import Wire.API.User.Scim import Wire.Sem.Logger.TinyLog +import Wire.ServerOptions.Spar -- | Call 'mkEnv' with options from config files. mkEnvFromOptions :: IO TestEnv @@ -225,7 +225,7 @@ mkEnvFromOptions = do let desc = "Spar - SSO Service Integration Test Suite" (integrationCfgFilePath, cfgFilePath) <- OPA.execParser (OPA.info (OPA.helper <*> cliOptsParser) (OPA.header desc <> OPA.fullDesc)) integrationOpts :: IntegrationConfig <- Yaml.decodeFileEither integrationCfgFilePath >>= either (error . show) pure - serviceOpts :: Opts <- Yaml.decodeFileEither cfgFilePath >>= either (throwIO . ErrorCall . show) Spar.Options.deriveOpts + serviceOpts :: Opts <- Yaml.decodeFileEither cfgFilePath >>= either (throwIO . ErrorCall . show) Wire.ServerOptions.Spar.deriveOpts mkEnv integrationOpts serviceOpts -- | Accept config file locations as cli options. diff --git a/services/spar/test-integration/Util/Types.hs b/services/spar/test-integration/Util/Types.hs index 553ed09674..c8f8e4a6e3 100644 --- a/services/spar/test-integration/Util/Types.hs +++ b/services/spar/test-integration/Util/Types.hs @@ -51,10 +51,10 @@ import Data.Aeson.TH import Imports import Spar.API () import qualified Spar.App as Spar -import Spar.Options import Test.Hspec (pendingWith) import Util.Options import Wire.API.User.IdentityProvider (WireIdPAPIVersion) +import Wire.ServerOptions.Spar type BrigReq = Request -> Request