Skip to content

Commit

Permalink
Various improvements around LH policy conflict detection. (#3773)
Browse files Browse the repository at this point in the history
* Move integration tests from galley/lh to /integration

* Improve test coverage

* Remove optimization for corner case of self messages

* Resolve trivial FUTUREWORK
  • Loading branch information
fisx committed Jan 17, 2024
1 parent a0b61c1 commit 973951a
Show file tree
Hide file tree
Showing 28 changed files with 824 additions and 278 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Various improvements around LH policy conflict detection:
* Fix LH policy conflict detection logic when posting messages
* Better policy conflict error messages (distinguish between old clients and missing consent)
* Add first LH scaffolding and tests to `/integration`
* Annotate some API functions in `/integration` with links to openapi3 docs
2 changes: 2 additions & 0 deletions integration/integration.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ library
Test.FeatureFlags
Test.Federation
Test.Federator
Test.LegalHold
Test.MessageTimer
Test.MLS
Test.MLS.KeyPackage
Expand All @@ -142,6 +143,7 @@ library
Testlib.HTTP
Testlib.JSON
Testlib.Mock
Testlib.MockIntegrationService
Testlib.ModService
Testlib.One2One
Testlib.Options
Expand Down
36 changes: 32 additions & 4 deletions integration/test/API/Brig.hs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ data AddClient = AddClient
model :: String,
prekeys :: Maybe [Value],
lastPrekey :: Maybe Value,
password :: String
password :: String,
acapabilities :: Maybe [String]
}

instance Default AddClient where
Expand All @@ -172,9 +173,11 @@ instance Default AddClient where
model = "Test Model",
prekeys = Nothing,
lastPrekey = Nothing,
password = defPassword
password = defPassword,
acapabilities = Just ["legalhold-implicit-consent"]
}

-- | https://staging-nginz-https.zinfra.io/api-internal/swagger-ui/brig/#/brig/post_i_clients__uid_
addClient ::
(HasCallStack, MakesValue user) =>
user ->
Expand All @@ -193,14 +196,15 @@ addClient user args = do
"type" .= args.ctype,
"label" .= args.clabel,
"model" .= args.model,
"password" .= args.password
"password" .= args.password,
"capabilities" .= args.acapabilities
]

data UpdateClient = UpdateClient
{ prekeys :: [Value],
lastPrekey :: Maybe Value,
label :: Maybe String,
capabilities :: Maybe [Value],
capabilities :: Maybe [String],
mlsPublicKeys :: Maybe Value
}

Expand Down Expand Up @@ -245,6 +249,7 @@ deleteClient user client = do
[ "password" .= defPassword
]

-- | https://staging-nginz-https.zinfra.io/v5/api/swagger-ui/#/default/get_users__uid_domain___uid__clients
getClientsQualified ::
( HasCallStack,
MakesValue user,
Expand All @@ -267,6 +272,7 @@ getClientsQualified user domain otherUser = do
<> "/clients"
submit "GET" req

-- | https://staging-nginz-https.zinfra.io/v5/api/swagger-ui/#/default/post_users_list_clients
listUsersClients :: (HasCallStack, MakesValue user, MakesValue qualifiedUserIds) => user -> [qualifiedUserIds] -> App Response
listUsersClients usr qualifiedUserIds = do
qUsers <- mapM objQidObject qualifiedUserIds
Expand Down Expand Up @@ -588,3 +594,25 @@ updateService dom providerId serviceId mAcceptHeader newName = do
. addHdrs
. addJSONObject ["name" .= n | n <- maybeToList newName]
$ req

-- | https://staging-nginz-https.zinfra.io/v5/api/swagger-ui/#/default/get_users__uid_domain___uid__prekeys__client_
getUsersPrekeysClient :: (HasCallStack, MakesValue caller, MakesValue targetUser) => caller -> targetUser -> String -> App Response
getUsersPrekeysClient caller targetUser targetClient = do
dom <- asString $ targetUser %. "domain"
uid <- asString $ targetUser %. "id"
req <- baseRequest caller Brig Versioned $ joinHttpPath ["users", dom, uid, "prekeys", targetClient]
submit "GET" req

-- | https://staging-nginz-https.zinfra.io/v5/api/swagger-ui/#/default/get_users__uid_domain___uid__prekeys
getUsersPrekeyBundle :: (HasCallStack, MakesValue caller, MakesValue targetUser) => caller -> targetUser -> App Response
getUsersPrekeyBundle caller targetUser = do
dom <- asString $ targetUser %. "domain"
uid <- asString $ targetUser %. "id"
req <- baseRequest caller Brig Versioned $ joinHttpPath ["users", dom, uid, "prekeys"]
submit "GET" req

-- | https://staging-nginz-https.zinfra.io/v5/api/swagger-ui/#/default/post_users_list_prekeys
getMultiUserPrekeyBundle :: (HasCallStack, MakesValue caller, ToJSON userClients) => caller -> userClients -> App Response
getMultiUserPrekeyBundle caller userClients = do
req <- baseRequest caller Brig Versioned $ joinHttpPath ["users", "list-prekeys"]
submit "POST" (addJSON userClients req)
53 changes: 53 additions & 0 deletions integration/test/API/Galley.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module API.Galley where
import API.Common
import Control.Lens hiding ((.=))
import Control.Monad.Reader
import Control.Retry
import qualified Data.Aeson as Aeson
import qualified Data.Aeson.Types as Aeson
import qualified Data.ByteString.Base64 as B64
Expand Down Expand Up @@ -513,3 +514,55 @@ getTeamMembers user tid = do
tidStr <- asString tid
req <- baseRequest user Galley Versioned (joinHttpPath ["teams", tidStr, "members"])
submit "GET" req

-- | https://staging-nginz-https.zinfra.io/v5/api/swagger-ui/#/default/post_teams__tid__legalhold_settings
enableLegalHold :: (HasCallStack, MakesValue tid, MakesValue ownerid) => tid -> ownerid -> App Response
enableLegalHold tid ownerid = do
tidStr <- asString tid
req <- baseRequest ownerid Galley Versioned (joinHttpPath ["teams", tidStr, "features", "legalhold"])
submit "PUT" (addJSONObject ["status" .= "enabled", "ttl" .= "unlimited"] req)

-- | https://staging-nginz-https.zinfra.io/v5/api/swagger-ui/#/default/post_teams__tid__legalhold_settings
postLegalHoldSettings :: (HasCallStack, MakesValue owner, MakesValue tid, MakesValue newService) => owner -> tid -> newService -> App Response
postLegalHoldSettings owner tid newSettings = retrying policy only412 $ \_ -> do
tidStr <- asString tid
req <- baseRequest owner Galley Versioned (joinHttpPath ["teams", tidStr, "legalhold", "settings"])
newSettingsObj <- make newSettings
submit "POST" (addJSON newSettingsObj req)
where
policy :: RetryPolicy
policy = limitRetriesByCumulativeDelay 5_000_000 $ exponentialBackoff 50

only412 :: RetryStatus -> Response -> App Bool
only412 _ resp = pure $ resp.status == 412

-- | https://staging-nginz-https.zinfra.io/v5/api/swagger-ui/#/default/post_teams__tid__legalhold__uid_
requestLegalHoldDevice :: (HasCallStack, MakesValue tid, MakesValue ownerid, MakesValue uid) => tid -> ownerid -> uid -> App Response
requestLegalHoldDevice tid ownerid uid = do
tidStr <- asString tid
uidStr <- objId uid
req <- baseRequest ownerid Galley Versioned (joinHttpPath ["teams", tidStr, "legalhold", uidStr])
submit "POST" req

-- | https://staging-nginz-https.zinfra.io/v5/api/swagger-ui/#/default/put_teams__tid__legalhold__uid__approve
approveLegalHoldDevice :: (HasCallStack, MakesValue tid, MakesValue uid) => tid -> uid -> String -> App Response
approveLegalHoldDevice tid uid pwd = do
tidStr <- asString tid
uidStr <- asString $ uid %. "id"
req <- baseRequest uid Galley Versioned (joinHttpPath ["teams", tidStr, "legalhold", uidStr, "approve"])
submit "PUT" (addJSONObject ["password" .= pwd] req)

-- | https://staging-nginz-https.zinfra.io/v5/api/swagger-ui/#/default/post_teams__tid__legalhold_consent
consentToLegalHold :: (HasCallStack, MakesValue tid, MakesValue zusr) => tid -> zusr -> String -> App Response
consentToLegalHold tid zusr pwd = do
tidStr <- asString tid
req <- baseRequest zusr Galley Versioned (joinHttpPath ["teams", tidStr, "legalhold", "consent"])
submit "POST" (addJSONObject ["password" .= pwd] req)

-- | https://staging-nginz-https.zinfra.io/v5/api/swagger-ui/#/default/get_teams__tid__legalhold__uid_
getLegalHoldStatus :: (HasCallStack, MakesValue tid, MakesValue zusr) => tid -> zusr -> App Response
getLegalHoldStatus tid zusr = do
tidStr <- asString tid
uidStr <- asString $ zusr %. "id"
req <- baseRequest zusr Galley Versioned (joinHttpPath ["teams", tidStr, "legalhold", uidStr])
submit "GET" req
12 changes: 12 additions & 0 deletions integration/test/API/GalleyInternal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,15 @@ getFederationStatus user domains =
submit
"GET"
$ req & addJSONObject ["domains" .= domainList]

legalholdWhitelistTeam :: (HasCallStack, MakesValue uid, MakesValue tid) => uid -> tid -> App Response
legalholdWhitelistTeam uid tid = do
tidStr <- asString tid
req <- baseRequest uid Galley Unversioned $ joinHttpPath ["i", "legalhold", "whitelisted-teams", tidStr]
submit "PUT" req

legalholdIsTeamInWhitelist :: (HasCallStack, MakesValue uid, MakesValue tid) => uid -> tid -> App Response
legalholdIsTeamInWhitelist uid tid = do
tidStr <- asString tid
req <- baseRequest uid Galley Unversioned $ joinHttpPath ["i", "legalhold", "whitelisted-teams", tidStr]
submit "GET" req
Loading

0 comments on commit 973951a

Please sign in to comment.