diff --git a/changelog.d/5-internal/WPB-663 b/changelog.d/5-internal/WPB-663 deleted file mode 100644 index 303cf529f7b..00000000000 --- a/changelog.d/5-internal/WPB-663 +++ /dev/null @@ -1,14 +0,0 @@ -Migrating the following routes to the Servant API form. - -POST /provider/services -GET /provider/services -GET /provider/services/:sid -PUT /provider/services/:sid -PUT /provider/services/:sid/connection -DELETE /provider/services/:sid -GET /providers/:pid/services -GET /providers/:pid/services/:sid -GET /services -GET /services/tags -GET /teams/:tid/services/whitelisted -POST /teams/:tid/services/whitelist \ No newline at end of file diff --git a/libs/types-common/src/Data/Range.hs b/libs/types-common/src/Data/Range.hs index 8b3d3a9cb11..e4c5be14781 100644 --- a/libs/types-common/src/Data/Range.hs +++ b/libs/types-common/src/Data/Range.hs @@ -152,9 +152,6 @@ numRangedSchemaDocModifier n m = S.schema %~ ((S.minimum_ ?~ fromIntegral n) . ( instance S.HasSchema d S.Schema => HasRangedSchemaDocModifier d [a] where rangedSchemaDocModifier _ = listRangedSchemaDocModifier --- Sets are effectively lists, so we can reuse that code. -instance S.HasSchema d S.Schema => HasRangedSchemaDocModifier d (Set a) where rangedSchemaDocModifier _ = listRangedSchemaDocModifier - instance S.HasSchema d S.Schema => HasRangedSchemaDocModifier d Text where rangedSchemaDocModifier _ = stringRangedSchemaDocModifier instance S.HasSchema d S.Schema => HasRangedSchemaDocModifier d String where rangedSchemaDocModifier _ = stringRangedSchemaDocModifier diff --git a/libs/wire-api/src/Wire/API/Provider/Service.hs b/libs/wire-api/src/Wire/API/Provider/Service.hs index 9b59decbcec..28a1e5609a1 100644 --- a/libs/wire-api/src/Wire/API/Provider/Service.hs +++ b/libs/wire-api/src/Wire/API/Provider/Service.hs @@ -47,7 +47,6 @@ module Wire.API.Provider.Service -- * UpdateServiceWhitelist UpdateServiceWhitelist (..), - UpdateServiceWhitelistResp (..), ) where @@ -64,8 +63,7 @@ import Data.List1 (List1) import Data.Misc (HttpsUrl (..), PlainTextPassword6) import Data.PEM (PEM, pemParseBS, pemWriteLBS) import Data.Proxy -import Data.Range (Range, fromRange, rangedSchema) -import Data.SOP +import Data.Range (Range) import Data.Schema import Data.Swagger qualified as S import Data.Text qualified as Text @@ -73,7 +71,6 @@ import Data.Text.Ascii import Data.Text.Encoding qualified as Text import Imports import Wire.API.Provider.Service.Tag (ServiceTag (..)) -import Wire.API.Routes.MultiVerb import Wire.API.User.Profile (Asset, Name) import Wire.Arbitrary (Arbitrary (arbitrary), GenericUniform (..)) @@ -208,22 +205,6 @@ data Service = Service } deriving stock (Eq, Show, Generic) deriving (Arbitrary) via (GenericUniform Service) - deriving (S.ToSchema) via (Schema Service) - -instance ToSchema Service where - schema = - object "Service" $ - Service - <$> serviceId .= field "id" schema - <*> serviceName .= field "name" schema - <*> serviceSummary .= field "summary" schema - <*> serviceDescr .= field "description" schema - <*> serviceUrl .= field "base_url" schema - <*> serviceTokens .= field "auth_tokens" schema - <*> serviceKeys .= field "public_keys" schema - <*> serviceAssets .= field "assets" (array schema) - <*> serviceTags .= field "tags" (set schema) - <*> serviceEnabled .= field "enabled" schema instance ToJSON Service where toJSON s = @@ -284,7 +265,6 @@ data ServiceProfile = ServiceProfile } deriving stock (Eq, Show, Generic) deriving (Arbitrary) via (GenericUniform ServiceProfile) - deriving (S.ToSchema) via (Schema ServiceProfile) instance ToJSON ServiceProfile where toJSON s = @@ -311,19 +291,6 @@ instance FromJSON ServiceProfile where <*> o A..: "tags" <*> o A..: "enabled" -instance ToSchema ServiceProfile where - schema = - object "ServiceProfile" $ - ServiceProfile - <$> serviceProfileId .= field "id" schema - <*> serviceProfileProvider .= field "provider" schema - <*> serviceProfileName .= field "name" schema - <*> serviceProfileSummary .= field "summary" schema - <*> serviceProfileDescr .= field "description" schema - <*> serviceProfileAssets .= field "assets" (array schema) - <*> serviceProfileTags .= field "tags" (set schema) - <*> serviceProfileEnabled .= field "enabled" schema - -------------------------------------------------------------------------------- -- ServiceProfilePage @@ -333,7 +300,6 @@ data ServiceProfilePage = ServiceProfilePage } deriving stock (Eq, Show, Generic) deriving (Arbitrary) via (GenericUniform ServiceProfilePage) - deriving (S.ToSchema) via (Schema ServiceProfilePage) instance ToJSON ServiceProfilePage where toJSON p = @@ -348,13 +314,6 @@ instance FromJSON ServiceProfilePage where <$> o A..: "has_more" <*> o A..: "services" -instance ToSchema ServiceProfilePage where - schema = - object "ServiceProfile" $ - ServiceProfilePage - <$> serviceProfilePageHasMore .= field "has_more" schema - <*> serviceProfilePageResults .= field "services" (array schema) - -------------------------------------------------------------------------------- -- NewService @@ -371,20 +330,6 @@ data NewService = NewService } deriving stock (Eq, Show, Generic) deriving (Arbitrary) via (GenericUniform NewService) - deriving (S.ToSchema) via (Schema NewService) - -instance ToSchema NewService where - schema = - object "NewService" $ - NewService - <$> newServiceName .= field "name" schema - <*> newServiceSummary .= field "summary" schema - <*> newServiceDescr .= field "description" schema - <*> newServiceUrl .= field "base_url" schema - <*> newServiceKey .= field "public_key" schema - <*> newServiceToken .= maybe_ (optField "auth_token" schema) - <*> newServiceAssets .= field "assets" (array schema) - <*> newServiceTags .= field "tags" (fromRange .= rangedSchema (set schema)) instance ToJSON NewService where toJSON s = @@ -421,14 +366,6 @@ data NewServiceResponse = NewServiceResponse } deriving stock (Eq, Show, Generic) deriving (Arbitrary) via (GenericUniform NewServiceResponse) - deriving (S.ToSchema) via (Schema NewServiceResponse) - -instance ToSchema NewServiceResponse where - schema = - object "NewServiceResponse" $ - NewServiceResponse - <$> rsNewServiceId .= field "id" schema - <*> rsNewServiceToken .= maybe_ (optField "auth_token" schema) instance ToJSON NewServiceResponse where toJSON r = @@ -456,17 +393,6 @@ data UpdateService = UpdateService } deriving stock (Eq, Show, Generic) deriving (Arbitrary) via (GenericUniform UpdateService) - deriving (S.ToSchema) via (Schema UpdateService) - -instance ToSchema UpdateService where - schema = - object "UpdateService" $ - UpdateService - <$> updateServiceName .= maybe_ (optField "name" schema) - <*> updateServiceSummary .= maybe_ (optField "summary" schema) - <*> updateServiceDescr .= maybe_ (optField "description" schema) - <*> updateServiceAssets .= maybe_ (optField "assets" $ array schema) - <*> updateServiceTags .= maybe_ (optField "tags" (fromRange .= rangedSchema (set schema))) instance ToJSON UpdateService where toJSON u = @@ -501,17 +427,6 @@ data UpdateServiceConn = UpdateServiceConn } deriving stock (Eq, Show, Generic) deriving (Arbitrary) via (GenericUniform UpdateServiceConn) - deriving (S.ToSchema) via (Schema UpdateServiceConn) - -instance ToSchema UpdateServiceConn where - schema = - object "UpdateServiceConn" $ - UpdateServiceConn - <$> updateServiceConnPassword .= field "password" schema - <*> updateServiceConnUrl .= maybe_ (optField "base_url" schema) - <*> updateServiceConnKeys .= maybe_ (optField "public_keys" (fromRange .= rangedSchema (array schema))) - <*> updateServiceConnTokens .= maybe_ (optField "auth_tokens" (fromRange .= rangedSchema (array schema))) - <*> updateServiceConnEnabled .= maybe_ (optField "enabled" schema) mkUpdateServiceConn :: PlainTextPassword6 -> UpdateServiceConn mkUpdateServiceConn pw = UpdateServiceConn pw Nothing Nothing Nothing Nothing @@ -543,13 +458,6 @@ newtype DeleteService = DeleteService {deleteServicePassword :: PlainTextPassword6} deriving stock (Eq, Show) deriving newtype (Arbitrary) - deriving (S.ToSchema) via (Schema DeleteService) - -instance ToSchema DeleteService where - schema = - object "DeleteService" $ - DeleteService - <$> deleteServicePassword .= field "password" schema instance ToJSON DeleteService where toJSON d = @@ -571,15 +479,6 @@ data UpdateServiceWhitelist = UpdateServiceWhitelist } deriving stock (Eq, Show, Generic) deriving (Arbitrary) via (GenericUniform UpdateServiceWhitelist) - deriving (S.ToSchema) via (Schema UpdateServiceWhitelist) - -instance ToSchema UpdateServiceWhitelist where - schema = - object "UpdateServiceWhitelist" $ - UpdateServiceWhitelist - <$> updateServiceWhitelistProvider .= field "provider" schema - <*> updateServiceWhitelistService .= field "id" schema - <*> updateServiceWhitelistStatus .= field "whitelisted" schema instance ToJSON UpdateServiceWhitelist where toJSON u = @@ -595,15 +494,3 @@ instance FromJSON UpdateServiceWhitelist where <$> o A..: "provider" <*> o A..: "id" <*> o A..: "whitelisted" - -data UpdateServiceWhitelistResp - = UpdateServiceWhitelistRespChanged - | UpdateServiceWhitelistRespUnchanged - --- basically the same as the instance for CheckBlacklistResponse -instance AsUnion '[RespondEmpty 200 "UpdateServiceWhitelistRespChanged", RespondEmpty 204 "UpdateServiceWhitelistRespUnchanged"] UpdateServiceWhitelistResp where - toUnion UpdateServiceWhitelistRespChanged = Z (I ()) - toUnion UpdateServiceWhitelistRespUnchanged = S (Z (I ())) - fromUnion (Z (I ())) = UpdateServiceWhitelistRespChanged - fromUnion (S (Z (I ()))) = UpdateServiceWhitelistRespUnchanged - fromUnion (S (S x)) = case x of {} diff --git a/libs/wire-api/src/Wire/API/Provider/Service/Tag.hs b/libs/wire-api/src/Wire/API/Provider/Service/Tag.hs index 55a804d4cb0..522c519ff87 100644 --- a/libs/wire-api/src/Wire/API/Provider/Service/Tag.hs +++ b/libs/wire-api/src/Wire/API/Provider/Service/Tag.hs @@ -1,5 +1,4 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} -{-# OPTIONS_GHC -Wno-orphans #-} -- This file is part of the Wire Server implementation. -- @@ -40,30 +39,18 @@ module Wire.API.Provider.Service.Tag ) where -import Control.Lens (Prism', prism) import Data.Aeson (FromJSON (parseJSON), ToJSON (toJSON)) -import Data.Aeson qualified as A import Data.Aeson qualified as JSON -import Data.Attoparsec.ByteString (IResult (..), parse) -import Data.ByteString (toStrict) import Data.ByteString.Builder qualified as BB import Data.ByteString.Char8 qualified as C8 import Data.ByteString.Conversion -import Data.Range (Range, fromRange, rangedSchema) +import Data.Range (Range, fromRange) import Data.Range qualified as Range -import Data.Schema import Data.Set qualified as Set -import Data.Swagger (ParamSchema (_paramSchemaEnum, _paramSchemaType), SwaggerType (SwaggerString), ToParamSchema (toParamSchema)) -import Data.Swagger qualified as S -import Data.Text qualified as T -import Data.Text.Encoding (decodeUtf8) -import Data.Text.Encoding qualified as T import Data.Text.Encoding qualified as Text import Data.Type.Ord import GHC.TypeLits (KnownNat, Nat) import Imports -import Web.HttpApiData (FromHttpApiData (parseUrlPiece), ToHttpApiData, toQueryParam) -import Web.Internal.HttpApiData (toUrlPiece) import Wire.Arbitrary (Arbitrary (..), GenericUniform (..)) -------------------------------------------------------------------------------- @@ -72,13 +59,6 @@ import Wire.Arbitrary (Arbitrary (..), GenericUniform (..)) newtype ServiceTagList = ServiceTagList [ServiceTag] deriving stock (Eq, Ord, Show) deriving newtype (FromJSON, ToJSON, Arbitrary) - deriving (S.ToSchema) via (Schema ServiceTagList) - -_ServiceTagList :: Prism' ServiceTagList [ServiceTag] -_ServiceTagList = prism ServiceTagList (\(ServiceTagList l) -> pure l) - -instance ToSchema ServiceTagList where - schema = named "ServiceTagList" $ tag _ServiceTagList $ array schema -- | A fixed enumeration of tags for services. data ServiceTag @@ -115,7 +95,6 @@ data ServiceTag | WeatherTag deriving stock (Eq, Show, Ord, Enum, Bounded, Generic) deriving (Arbitrary) via (GenericUniform ServiceTag) - deriving (S.ToSchema) via (Schema ServiceTag) instance FromByteString ServiceTag where parser = @@ -194,12 +173,6 @@ instance FromJSON ServiceTag where JSON.withText "ServiceTag" $ either fail pure . runParser parser . Text.encodeUtf8 -instance ToSchema ServiceTag where - schema = enum @Text "" . mconcat $ (\a -> element (decodeUtf8 $ toStrict $ toByteString a) a) <$> [minBound ..] - -instance ToHttpApiData ServiceTag where - toUrlPiece = cs . toByteString' - -------------------------------------------------------------------------------- -- Bounded ServiceTag Queries @@ -208,19 +181,6 @@ newtype QueryAnyTags (m :: Nat) (n :: Nat) = QueryAnyTags {queryAnyTagsRange :: Range m n (Set (QueryAllTags m n))} deriving stock (Eq, Show, Ord) -instance (m <= n) => ToParamSchema (QueryAnyTags m n) where - toParamSchema _ = - mempty - { _paramSchemaType = Just SwaggerString, - _paramSchemaEnum = Just (A.String . toQueryParam <$> [(minBound :: ServiceTag) ..]) - } - -instance (KnownNat n, KnownNat m, m <= n) => ToSchema (QueryAnyTags m n) where - schema = - let sch :: ValueSchema NamedSwaggerDoc (Range m n (Set (QueryAllTags m n))) - sch = fromRange .= rangedSchema (named "QueryAnyTags" $ set schema) - in queryAnyTagsRange .= (QueryAnyTags <$> sch) - instance (KnownNat m, KnownNat n, m <= n) => Arbitrary (QueryAnyTags m n) where arbitrary = QueryAnyTags <$> arbitrary @@ -247,31 +207,11 @@ instance (KnownNat n, KnownNat m, m <= n) => FromByteString (QueryAnyTags m n) w rs <- either fail pure (Range.checkedEither (Set.fromList ts)) pure $! QueryAnyTags rs -runPartial :: IsString i => Bool -> IResult i b -> Either Text b -runPartial alreadyRun result = case result of - Fail _ _ e -> Left $ T.pack e - Partial f -> - if alreadyRun - then Left "A partial parse returned another partial parse." - else runPartial True $ f "" - Done _ r -> pure r - -instance (KnownNat n, KnownNat m, m <= n) => FromHttpApiData (QueryAnyTags m n) where - parseUrlPiece t = do - txt <- parseUrlPiece t - runPartial False $ parse parser $ T.encodeUtf8 txt - -- | Bounded logical conjunction of 'm' to 'n' 'ServiceTag's to match. newtype QueryAllTags (m :: Nat) (n :: Nat) = QueryAllTags {queryAllTagsRange :: Range m n (Set ServiceTag)} deriving stock (Eq, Show, Ord) -instance (KnownNat n, KnownNat m, m <= n) => ToSchema (QueryAllTags m n) where - schema = - let sch :: ValueSchema NamedSwaggerDoc (Range m n (Set ServiceTag)) - sch = fromRange .= rangedSchema (named "QueryAllTags" $ set schema) - in queryAllTagsRange .= (QueryAllTags <$> sch) - instance (KnownNat m, KnownNat n, m <= n) => Arbitrary (QueryAllTags m n) where arbitrary = QueryAllTags <$> arbitrary @@ -296,11 +236,6 @@ instance (KnownNat m, KnownNat n, m <= n) => FromByteString (QueryAllTags m n) w rs <- either fail pure (Range.checkedEither (Set.fromList ts)) pure $! QueryAllTags rs -instance (KnownNat n, KnownNat m, m <= n) => FromHttpApiData (QueryAllTags m n) where - parseUrlPiece t = do - txt <- parseUrlPiece t - runPartial False $ parse parser $ T.encodeUtf8 txt - -------------------------------------------------------------------------------- -- ServiceTag Matchers 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 592fc7a8f5f..d83004bb54b 100644 --- a/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs +++ b/libs/wire-api/src/Wire/API/Routes/Public/Brig.hs @@ -1,6 +1,4 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} --- Required for `instance MimeRender PlainText ()` -{-# OPTIONS_GHC -Wno-orphans #-} -- This file is part of the Wire Server implementation. -- @@ -52,12 +50,6 @@ import Wire.API.MLS.Servant import Wire.API.MakesFederatedCall import Wire.API.OAuth import Wire.API.Properties - ( PropertyKey, - PropertyKeysAndValues, - RawPropertyValue, - ) -import Wire.API.Provider.Service qualified as Public -import Wire.API.Provider.Service.Tag qualified as Public import Wire.API.Routes.API import Wire.API.Routes.Bearer import Wire.API.Routes.Cookies @@ -102,8 +94,6 @@ type BrigAPI = :<|> SystemSettingsAPI :<|> OAuthAPI :<|> BotAPI - :<|> ProviderAPI - :<|> ServicesAPI data BrigAPITag @@ -296,112 +286,6 @@ type UserAPI = (Respond 200 "Protocols supported by the user" (Set BaseProtocolTag)) ) -type ProviderAPI = - Named - "post-provider-services" - ( Summary "" - :> Description "" - :> ZProvider - :> "provider" - :> "services" - :> ReqBody '[JSON] Public.NewService - :> MultiVerb1 'POST '[JSON] (Respond 201 "" Public.NewServiceResponse) - ) - :<|> Named - "get-provider-services" - ( Summary "" - :> Description "" - :> ZProvider - :> "provider" - :> "services" - :> Get '[JSON] [Public.Service] - ) - :<|> Named - "get-provider-services-by-service-id" - ( Summary "" - :> Description "" - :> ZProvider - :> "provider" - :> "services" - :> Capture "service-id" ServiceId - :> Get '[JSON] Public.Service - ) - :<|> Named - "put-provider-services-by-service-id" - ( Summary "" - :> Description "" - :> ZProvider - :> "provider" - :> "services" - :> Capture "service-id" ServiceId - :> ReqBody '[JSON] Public.UpdateService - :> Put '[PlainText] () - ) - :<|> Named - "put-provider-services-connection-by-service-id" - ( Summary "" - :> Description "" - :> ZProvider - :> "provider" - :> "services" - :> Capture "service-id" ServiceId - :> "connection" - :> ReqBody '[JSON] Public.UpdateServiceConn - :> Put '[PlainText] () - ) - :<|> Named - "delete-provider-services-by-service-id" - ( Summary "" - :> Description "" - :> ZProvider - :> "provider" - :> "services" - :> Capture "service-id" ServiceId - :> ReqBody '[JSON] Public.DeleteService - :> MultiVerb1 'DELETE '[PlainText] (RespondEmpty 202 "") - ) - :<|> Named - "get-provider-services-by-provider-id" - ( Summary "" - :> Description "" - :> ZAccess - :> "providers" - :> Capture "provider-id" ProviderId - :> "services" - :> Get '[JSON] [Public.ServiceProfile] - ) - :<|> Named - "get-provider-services-by-provider-id-and-service-id" - ( Summary "" - :> Description "" - :> ZAccess - :> "providers" - :> Capture "provider-id" ProviderId - :> "services" - :> Capture "service-id" ServiceId - :> Get '[JSON] Public.ServiceProfile - ) - -type ServicesAPI = - Named - "get-services" - ( Summary "" - :> Description "" - :> ZAccess - :> "services" - :> QueryParam "tags" (Public.QueryAnyTags 1 3) - :> QueryParam "start" Text - :> QueryParam "size" (Range 10 100 Int32) -- Default to 20 - :> Get '[JSON] Public.ServiceProfilePage - ) - :<|> Named - "get-services-tags" - ( Summary "" - :> Description "" - :> ZAccess - :> Get '[JSON] Public.ServiceTagList - ) - type SelfAPI = Named "get-self" @@ -1642,39 +1526,6 @@ type TeamsAPI = '[JSON] (Respond 200 "Number of team members" TeamSize) ) - :<|> Named - "get-whitelisted-services-by-team-id" - ( Summary "" - :> Description "" - :> ZAccess - :> "teams" - :> Capture "team-id" TeamId - :> "services" - :> "whitelisted" - :> QueryParam "prefix" (Range 1 128 Text) - -- Default to True - :> QueryParam "filter_disabled" Bool - -- Default to 20 - :> QueryParam "size" (Range 10 100 Int32) - :> Get '[JSON] Public.ServiceProfilePage - ) - :<|> Named - "post-team-whitelist-by-team-id" - ( Summary "" - :> Description "" - :> ZAccess - :> ZConn - :> "teams" - :> Capture "team-id" TeamId - :> "services" - :> "whitelist" - :> ReqBody '[JSON] Public.UpdateServiceWhitelist - :> MultiVerb 'POST '[PlainText] '[RespondEmpty 200 "UpdateServiceWhitelistRespChanged", RespondEmpty 204 "UpdateServiceWhitelistRespUnchanged"] Public.UpdateServiceWhitelistResp - ) - --- Plaintext doesn't ship a renderer for (), so we have an orphan for it -instance MimeRender PlainText () where - mimeRender _ () = "" type SystemSettingsAPI = Named diff --git a/services/brig/src/Brig/API/Public.hs b/services/brig/src/Brig/API/Public.hs index fedbc25d5d3..46665c7122f 100644 --- a/services/brig/src/Brig/API/Public.hs +++ b/services/brig/src/Brig/API/Public.hs @@ -90,7 +90,6 @@ import Data.Misc (IpAddr (..)) import Data.Nonce (Nonce, randomNonce) import Data.Qualified import Data.Range -import Data.Schema () import Data.Swagger qualified as S import Data.Text qualified as Text import Data.Text.Ascii qualified as Ascii @@ -115,8 +114,6 @@ import Wire.API.Error.Brig qualified as E import Wire.API.Federation.API import Wire.API.Federation.Error import Wire.API.Properties qualified as Public -import Wire.API.Provider.Service qualified as Public -import Wire.API.Provider.Service.Tag qualified as Public import Wire.API.Routes.API import Wire.API.Routes.Internal.Brig qualified as BrigInternalAPI import Wire.API.Routes.Internal.Cannon qualified as CannonInternalAPI @@ -291,23 +288,7 @@ servantSitemap = :<|> systemSettingsAPI :<|> oauthAPI :<|> botAPI - :<|> providerAPI - :<|> servicesAPI where - providerAPI :: ServerT ProviderAPI (Handler r) - providerAPI = - Named @"post-provider-services" addServiceH - :<|> Named @"get-provider-services" listServicesH - :<|> Named @"get-provider-services-by-service-id" getServiceH - :<|> Named @"put-provider-services-by-service-id" updateServiceH - :<|> Named @"put-provider-services-connection-by-service-id" updateServiceConnH - :<|> Named @"delete-provider-services-by-service-id" deleteServiceH - :<|> Named @"get-provider-services-by-provider-id" listServiceProfilesH - :<|> Named @"get-provider-services-by-provider-id-and-service-id" getServiceProfileH - servicesAPI :: ServerT ServicesAPI (Handler r) - servicesAPI = - Named @"get-services" searchServiceProfilesH - :<|> Named @"get-services-tags" getServiceTagListH userAPI :: ServerT UserAPI (Handler r) userAPI = Named @"get-user-unqualified" (callsFed (exposeAnnotations getUserUnqualifiedH)) @@ -1140,75 +1121,6 @@ updateUserEmail zuserId emailOwnerId (Public.EmailUpdate email) = do teamMember <- MaybeT $ lift $ liftSem $ GalleyProvider.getTeamMember zuserId teamId pure $ teamMember `hasPermission` ChangeTeamMemberProfiles --- ProviderAPI -addServiceH :: - Member GalleyProvider r => - ProviderId -> - Public.NewService -> - (Handler r) Public.NewServiceResponse -addServiceH pid req = do - Provider.guardSecondFactorDisabled Nothing - Provider.addService pid req - -listServicesH :: Member GalleyProvider r => ProviderId -> (Handler r) [Public.Service] -listServicesH pid = do - Provider.guardSecondFactorDisabled Nothing - Provider.listServices pid - -getServiceH :: Member GalleyProvider r => ProviderId -> ServiceId -> (Handler r) Public.Service -getServiceH pid sid = do - Provider.guardSecondFactorDisabled Nothing - Provider.getService pid sid - -updateServiceH :: Member GalleyProvider r => ProviderId -> ServiceId -> Public.UpdateService -> (Handler r) () -updateServiceH pid sid req = do - Provider.guardSecondFactorDisabled Nothing - void $ Provider.updateService pid sid req - -updateServiceConnH :: Member GalleyProvider r => ProviderId -> ServiceId -> Public.UpdateServiceConn -> (Handler r) () -updateServiceConnH pid sid req = do - Provider.guardSecondFactorDisabled Nothing - void $ Provider.updateServiceConn pid sid req - --- TODO: Send informational email to provider. - --- | Member GalleyProvider r => The endpoint that is called to delete a service. --- --- Since deleting a service can be costly, it just marks the service as --- disabled and then creates an event that will, when processed, actually --- delete the service. See 'finishDeleteService'. -deleteServiceH :: Member GalleyProvider r => ProviderId -> ServiceId -> Public.DeleteService -> (Handler r) () -deleteServiceH pid sid req = do - Provider.guardSecondFactorDisabled Nothing - void $ Provider.deleteService pid sid req - -listServiceProfilesH :: Member GalleyProvider r => UserId -> ProviderId -> (Handler r) [Public.ServiceProfile] -listServiceProfilesH _ pid = do - Provider.guardSecondFactorDisabled Nothing - Provider.listServiceProfiles pid - -getServiceProfileH :: Member GalleyProvider r => UserId -> ProviderId -> ServiceId -> (Handler r) Public.ServiceProfile -getServiceProfileH _ pid sid = do - Provider.guardSecondFactorDisabled Nothing - Provider.getServiceProfile pid sid - --- ServicesAPI -searchServiceProfilesH :: - Member GalleyProvider r => - UserId -> - Maybe (Public.QueryAnyTags 1 3) -> - Maybe Text -> - Maybe (Range 10 100 Int32) -> -- Default to 20 - (Handler r) Public.ServiceProfilePage -searchServiceProfilesH _ qt start size = do - Provider.guardSecondFactorDisabled Nothing - Provider.searchServiceProfiles qt start $ fromMaybe (unsafeRange 20) size - -getServiceTagListH :: Member GalleyProvider r => UserId -> (Handler r) Public.ServiceTagList -getServiceTagListH _ = do - Provider.guardSecondFactorDisabled Nothing - Provider.getServiceTagList () - -- activation activate :: diff --git a/services/brig/src/Brig/Provider/API.hs b/services/brig/src/Brig/Provider/API.hs index 46cc9b38045..a836861f8f5 100644 --- a/services/brig/src/Brig/Provider/API.hs +++ b/services/brig/src/Brig/Provider/API.hs @@ -23,23 +23,6 @@ module Brig.Provider.API -- * Event handlers finishDeleteService, - - -- * Extras - guardSecondFactorDisabled, - addService, - listServices, - getService, - updateService, - updateServiceConn, - deleteService, - listServiceProfiles, - getServiceProfile, - searchServiceProfilesH, - searchServiceProfiles, - getServiceTagList, - searchTeamServiceProfiles, - updateServiceWhitelist, - UpdateServiceWhitelistResp (..), ) where @@ -98,7 +81,7 @@ import GHC.TypeNats import Imports import Network.HTTP.Types.Status import Network.Wai (Response) -import Network.Wai.Predicate (accept, query) +import Network.Wai.Predicate (accept, def, opt, query) import Network.Wai.Routing import Network.Wai.Utilities.Error ((!>>)) import Network.Wai.Utilities.Error qualified as Wai @@ -223,11 +206,46 @@ routesPublic = do .&> zauth ZAuthProvider .&> zauthProviderId + post "/provider/services" (continue addServiceH) $ + accept "application" "json" + .&> zauth ZAuthProvider + .&> zauthProviderId + .&. jsonRequest @Public.NewService + + get "/provider/services" (continue listServicesH) $ + accept "application" "json" + .&> zauth ZAuthProvider + .&> zauthProviderId + + get "/provider/services/:sid" (continue getServiceH) $ + accept "application" "json" + .&> zauth ZAuthProvider + .&> zauthProviderId + .&. capture "sid" + + put "/provider/services/:sid" (continue updateServiceH) $ + zauth ZAuthProvider + .&> zauthProviderId + .&. capture "sid" + .&. jsonRequest @Public.UpdateService + + put "/provider/services/:sid/connection" (continue updateServiceConnH) $ + zauth ZAuthProvider + .&> zauthProviderId + .&. capture "sid" + .&. jsonRequest @Public.UpdateServiceConn + -- TODO -- post "/provider/services/:sid/token" (continue genServiceTokenH) $ -- accept "application" "json" -- .&. zauthProvider + delete "/provider/services/:sid" (continue deleteServiceH) $ + zauth ZAuthProvider + .&> zauthProviderId + .&. capture "sid" + .&. jsonRequest @Public.DeleteService + -- User API ---------------------------------------------------------------- get "/providers/:pid" (continue getProviderProfileH) $ @@ -235,6 +253,44 @@ routesPublic = do .&> zauth ZAuthAccess .&> capture "pid" + get "/providers/:pid/services" (continue listServiceProfilesH) $ + accept "application" "json" + .&> zauth ZAuthAccess + .&> capture "pid" + + get "/providers/:pid/services/:sid" (continue getServiceProfileH) $ + accept "application" "json" + .&> zauth ZAuthAccess + .&> capture "pid" + .&. capture "sid" + + get "/services" (continue searchServiceProfilesH) $ + accept "application" "json" + .&> zauth ZAuthAccess + .&> opt (query "tags") + .&. opt (query "start") + .&. def (unsafeRange 20) (query "size") + + get "/services/tags" (continue getServiceTagListH) $ + accept "application" "json" + .&> zauth ZAuthAccess + + get "/teams/:tid/services/whitelisted" (continue searchTeamServiceProfilesH) $ + accept "application" "json" + .&> zauthUserId + .&. capture "tid" + .&. opt (query "prefix") + .&. def True (query "filter_disabled") + .&. def (unsafeRange 20) (query "size") + + post "/teams/:tid/services/whitelist" (continue updateServiceWhitelistH) $ + accept "application" "json" + .&> zauth ZAuthAccess + .&> zauthUserId + .&. zauthConnId + .&. capture "tid" + .&. jsonRequest @Public.UpdateServiceWhitelist + routesInternal :: Member GalleyProvider r => Routes a (Handler r) () routesInternal = do get "/i/provider/activation-code" (continue getActivationCodeH) $ @@ -463,6 +519,11 @@ updateAccountPassword pid upd = do throwStd newPasswordMustDiffer wrapClientE $ DB.updateAccountPassword pid (newPassword upd) +addServiceH :: Member GalleyProvider r => ProviderId ::: JsonRequest Public.NewService -> (Handler r) Response +addServiceH (pid ::: req) = do + guardSecondFactorDisabled Nothing + setStatus status201 . json <$> (addService pid =<< parseJsonBody req) + addService :: ProviderId -> Public.NewService -> (Handler r) Public.NewServiceResponse addService pid new = do _ <- wrapClientE (DB.lookupAccount pid) >>= maybeInvalidProvider @@ -479,13 +540,28 @@ addService pid new = do let rstoken = maybe (Just token) (const Nothing) (newServiceToken new) pure $ Public.NewServiceResponse sid rstoken +listServicesH :: Member GalleyProvider r => ProviderId -> (Handler r) Response +listServicesH pid = do + guardSecondFactorDisabled Nothing + json <$> listServices pid + listServices :: ProviderId -> (Handler r) [Public.Service] listServices = wrapClientE . DB.listServices +getServiceH :: Member GalleyProvider r => ProviderId ::: ServiceId -> (Handler r) Response +getServiceH (pid ::: sid) = do + guardSecondFactorDisabled Nothing + json <$> getService pid sid + getService :: ProviderId -> ServiceId -> (Handler r) Public.Service getService pid sid = wrapClientE (DB.lookupService pid sid) >>= maybeServiceNotFound +updateServiceH :: Member GalleyProvider r => ProviderId ::: ServiceId ::: JsonRequest Public.UpdateService -> (Handler r) Response +updateServiceH (pid ::: sid ::: req) = do + guardSecondFactorDisabled Nothing + empty <$ (updateService pid sid =<< parseJsonBody req) + updateService :: ProviderId -> ServiceId -> Public.UpdateService -> (Handler r) () updateService pid sid upd = do _ <- wrapClientE (DB.lookupAccount pid) >>= maybeInvalidProvider @@ -514,6 +590,11 @@ updateService pid sid upd = do tagsChange (serviceEnabled svc) +updateServiceConnH :: Member GalleyProvider r => ProviderId ::: ServiceId ::: JsonRequest Public.UpdateServiceConn -> (Handler r) Response +updateServiceConnH (pid ::: sid ::: req) = do + guardSecondFactorDisabled Nothing + empty <$ (updateServiceConn pid sid =<< parseJsonBody req) + updateServiceConn :: ProviderId -> ServiceId -> Public.UpdateServiceConn -> (Handler r) () updateServiceConn pid sid upd = do pass <- wrapClientE (DB.lookupPassword pid) >>= maybeBadCredentials @@ -548,6 +629,18 @@ updateServiceConn pid sid upd = do then DB.deleteServiceIndexes pid sid name tags else DB.insertServiceIndexes pid sid name tags +-- TODO: Send informational email to provider. + +-- | Member GalleyProvider r => The endpoint that is called to delete a service. +-- +-- Since deleting a service can be costly, it just marks the service as +-- disabled and then creates an event that will, when processed, actually +-- delete the service. See 'finishDeleteService'. +deleteServiceH :: Member GalleyProvider r => ProviderId ::: ServiceId ::: JsonRequest Public.DeleteService -> (Handler r) Response +deleteServiceH (pid ::: sid ::: req) = do + guardSecondFactorDisabled Nothing + setStatus status202 empty <$ (deleteService pid sid =<< parseJsonBody req) + -- | The endpoint that is called to delete a service. -- -- Since deleting a service can be costly, it just marks the service as @@ -641,9 +734,19 @@ getProviderProfile :: ProviderId -> (Handler r) Public.ProviderProfile getProviderProfile pid = wrapClientE (DB.lookupAccountProfile pid) >>= maybeProviderNotFound +listServiceProfilesH :: Member GalleyProvider r => ProviderId -> (Handler r) Response +listServiceProfilesH pid = do + guardSecondFactorDisabled Nothing + json <$> listServiceProfiles pid + listServiceProfiles :: ProviderId -> (Handler r) [Public.ServiceProfile] listServiceProfiles = wrapClientE . DB.listServiceProfiles +getServiceProfileH :: Member GalleyProvider r => ProviderId ::: ServiceId -> (Handler r) Response +getServiceProfileH (pid ::: sid) = do + guardSecondFactorDisabled Nothing + json <$> getServiceProfile pid sid + getServiceProfile :: ProviderId -> ServiceId -> (Handler r) Public.ServiceProfile getServiceProfile pid sid = wrapClientE (DB.lookupServiceProfile pid sid) >>= maybeServiceNotFound @@ -666,6 +769,14 @@ searchServiceProfiles (Just tags) start size = do searchServiceProfiles Nothing Nothing _ = do throwStd $ badRequest "At least `tags` or `start` must be provided." +searchTeamServiceProfilesH :: + Member GalleyProvider r => + UserId ::: TeamId ::: Maybe (Range 1 128 Text) ::: Bool ::: Range 10 100 Int32 -> + (Handler r) Response +searchTeamServiceProfilesH (uid ::: tid ::: prefix ::: filterDisabled ::: size) = do + guardSecondFactorDisabled (Just uid) + json <$> searchTeamServiceProfiles uid tid prefix filterDisabled size + -- NB: unlike 'searchServiceProfiles', we don't filter by service provider here searchTeamServiceProfiles :: UserId -> @@ -684,11 +795,29 @@ searchTeamServiceProfiles uid tid prefix filterDisabled size = do -- Get search results wrapClientE $ DB.paginateServiceWhitelist tid prefix filterDisabled (fromRange size) +getServiceTagListH :: Member GalleyProvider r => () -> (Handler r) Response +getServiceTagListH () = do + guardSecondFactorDisabled Nothing + json <$> getServiceTagList () + getServiceTagList :: () -> Monad m => m Public.ServiceTagList getServiceTagList () = pure (Public.ServiceTagList allTags) where allTags = [(minBound :: Public.ServiceTag) ..] +updateServiceWhitelistH :: Member GalleyProvider r => UserId ::: ConnId ::: TeamId ::: JsonRequest Public.UpdateServiceWhitelist -> (Handler r) Response +updateServiceWhitelistH (uid ::: con ::: tid ::: req) = do + guardSecondFactorDisabled (Just uid) + resp <- updateServiceWhitelist uid con tid =<< parseJsonBody req + let status = case resp of + UpdateServiceWhitelistRespChanged -> status200 + UpdateServiceWhitelistRespUnchanged -> status204 + pure $ setStatus status empty + +data UpdateServiceWhitelistResp + = UpdateServiceWhitelistRespChanged + | UpdateServiceWhitelistRespUnchanged + updateServiceWhitelist :: Member GalleyProvider r => UserId -> ConnId -> TeamId -> Public.UpdateServiceWhitelist -> (Handler r) UpdateServiceWhitelistResp updateServiceWhitelist uid con tid upd = do let pid = updateServiceWhitelistProvider upd diff --git a/services/brig/src/Brig/Team/API.hs b/services/brig/src/Brig/Team/API.hs index bcfcb310958..18a60a9e797 100644 --- a/services/brig/src/Brig/Team/API.hs +++ b/services/brig/src/Brig/Team/API.hs @@ -37,7 +37,6 @@ import Brig.Effects.UserPendingActivationStore (UserPendingActivationStore) import Brig.Email qualified as Email import Brig.Options (setMaxTeamSize, setTeamInvitationTimeout) import Brig.Phone qualified as Phone -import Brig.Provider.API (guardSecondFactorDisabled, searchTeamServiceProfiles, updateServiceWhitelist) import Brig.Team.DB qualified as DB import Brig.Team.Email import Brig.Team.Types (ShowOrHideInvitationUrl (..)) @@ -65,7 +64,6 @@ import System.Logger.Class qualified as Log import Util.Logging (logFunction, logTeam) import Wire.API.Error import Wire.API.Error.Brig qualified as E -import Wire.API.Provider.Service (ServiceProfilePage, UpdateServiceWhitelist, UpdateServiceWhitelistResp (..)) import Wire.API.Routes.Internal.Galley.TeamsIntra qualified as Team import Wire.API.Routes.Named import Wire.API.Routes.Public.Brig @@ -93,8 +91,6 @@ servantAPI = :<|> Named @"get-team-invitation-info" getInvitationByCode :<|> Named @"head-team-invitations" headInvitationByEmail :<|> Named @"get-team-size" teamSizePublic - :<|> Named @"get-whitelisted-services-by-team-id" searchTeamServiceProfilesH - :<|> Named @"post-team-whitelist-by-team-id" updateServiceWhitelistH routesInternal :: ( Member BlacklistStore r, @@ -128,26 +124,6 @@ routesInternal = do accept "application" "json" .&. jsonRequest @NewUserScimInvitation -searchTeamServiceProfilesH :: - Member GalleyProvider r => - UserId -> - TeamId -> - Maybe (Range 1 128 Text) -> - Maybe Bool -> - Maybe (Range 10 100 Int32) -> - (Handler r) ServiceProfilePage -searchTeamServiceProfilesH uid tid prefix filterDisabled' size' = do - guardSecondFactorDisabled (Just uid) - searchTeamServiceProfiles uid tid prefix filterDisabled size - where - size = fromMaybe (unsafeRange 20) size' - filterDisabled = fromMaybe True filterDisabled' - -updateServiceWhitelistH :: Member GalleyProvider r => UserId -> ConnId -> TeamId -> UpdateServiceWhitelist -> (Handler r) UpdateServiceWhitelistResp -updateServiceWhitelistH uid con tid req = do - guardSecondFactorDisabled (Just uid) - updateServiceWhitelist uid con tid req - teamSizePublic :: Member GalleyProvider r => UserId -> TeamId -> (Handler r) TeamSize teamSizePublic uid tid = do ensurePermissions uid tid [AddTeamMember] -- limit this to team admins to reduce risk of involuntary DOS attacks