Skip to content

Commit

Permalink
Merge pull request #2083 from wireapp/release_2022_01_28
Browse files Browse the repository at this point in the history
  • Loading branch information
fisx authored Jan 28, 2022
2 parents 13a6a83 + 2f344f7 commit 1b37f06
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 24 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
<!-- if you're not the release manager, do your edits to changelog under CHANGELOG.d/ -->

# [2022-01-28]

## Release notes

* Bump the webapp version. (#2082)

## Internal changes

* Additional integration testing for conversation access control. (#2057)


# [2022-01-27]

## Release notes
Expand Down
2 changes: 1 addition & 1 deletion charts/webapp/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ resources:
cpu: "1"
image:
repository: quay.io/wire/webapp
tag: "2021-12-02-federation-M1-spillover"
tag: "2022-01-27-production.0-v0.28.29-0-42c9a1e"
service:
https:
externalPort: 443
Expand Down
1 change: 1 addition & 0 deletions libs/wire-api/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ library:
- proto-lens
- QuickCheck >=2.14
- quickcheck-instances >=0.3.16
- random >=1.2.0
- resourcet
- servant-client
- servant-client-core
Expand Down
18 changes: 17 additions & 1 deletion libs/wire-api/src/Wire/API/Conversation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ module Wire.API.Conversation
-- * Conversation properties
Access (..),
AccessRoleV2 (..),
genAccessRolesV2,
AccessRoleLegacy (..),
ConvType (..),
ReceiptMode (..),
Expand Down Expand Up @@ -95,6 +96,7 @@ import Control.Lens (at, (?~))
import Data.Aeson (FromJSON (..), ToJSON (..))
import qualified Data.Aeson as A
import Data.Id
import Data.List.Extra (disjointOrd)
import Data.List.NonEmpty (NonEmpty)
import Data.List1
import Data.Misc
Expand All @@ -107,6 +109,7 @@ import Data.String.Conversions (cs)
import qualified Data.Swagger as S
import qualified Data.Swagger.Build.Api as Doc
import Imports
import System.Random (randomRIO)
import qualified Test.QuickCheck as QC
import Wire.API.Arbitrary (Arbitrary (arbitrary), GenericUniform (..))
import Wire.API.Conversation.Member
Expand Down Expand Up @@ -476,10 +479,23 @@ data AccessRoleV2
| NonTeamMemberAccessRole
| GuestAccessRole
| ServiceAccessRole
deriving stock (Eq, Ord, Show, Generic)
deriving stock (Eq, Ord, Show, Generic, Bounded, Enum)
deriving (Arbitrary) via (GenericUniform AccessRoleV2)
deriving (ToJSON, FromJSON, S.ToSchema) via Schema AccessRoleV2

genAccessRolesV2 :: [AccessRoleV2] -> [AccessRoleV2] -> IO (Either String (Set AccessRoleV2))
genAccessRolesV2 = genEnumSet

genEnumSet :: forall a. (Bounded a, Enum a, Ord a, Eq a, Show a) => [a] -> [a] -> IO (Either String (Set a))
genEnumSet with without =
if disjointOrd with without
then do
let xs = Set.toList . Set.powerSet . Set.fromList $ [minBound ..]
x <- (xs !!) <$> randomRIO (0, length xs - 1)
pure . Right . Set.fromList $ (Set.toList x <> with) \\ without
else do
pure $ Left ("overlapping arguments: " <> show (with, without))

toAccessRoleLegacy :: Set AccessRoleV2 -> AccessRoleLegacy
toAccessRoleLegacy accessRoles = do
fromMaybe NonActivatedAccessRole $ find (allMember accessRoles . fromAccessRoleLegacy) [minBound ..]
Expand Down
1 change: 1 addition & 0 deletions libs/wire-api/wire-api.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ library
, proto-lens
, protobuf >=0.2
, quickcheck-instances >=0.3.16
, random >=1.2.0
, resourcet
, saml2-web-sso
, schema-profunctor
Expand Down
46 changes: 36 additions & 10 deletions services/brig/test/integration/API/Provider.hs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ tests dom conf p db b c g = do
"bot"
[ test p "add-remove" $ testAddRemoveBot conf db b g c,
test p "message" $ testMessageBot conf db b g c,
test p "bad fingerprint" $ testBadFingerprint conf db b g c
test p "bad fingerprint" $ testBadFingerprint conf db b g c,
test p "add bot forbidden" $ testAddBotForbidden conf db b g
],
testGroup
"bot-teams"
Expand Down Expand Up @@ -520,24 +521,41 @@ testDeleteService config db brig galley cannon = withTestService config db brig

testAddRemoveBot :: Config -> DB.ClientState -> Brig -> Galley -> Cannon -> Http ()
testAddRemoveBot config db brig galley cannon = withTestService config db brig defServiceApp $ \sref buf -> do
(pid, sid, u1, u2, h) <- prepareUsers sref brig
let uid1 = userId u1
quid1 = userQualifiedId u1
localDomain = qDomain quid1
uid2 = userId u2
-- Create conversation
_rs <- createConv galley uid1 [uid2] <!! const 201 === statusCode
let Just cnv = responseJsonMaybe _rs
let cid = qUnqualified . cnvQualifiedId $ cnv
testAddRemoveBotUtil localDomain pid sid cid u1 u2 h sref buf brig galley cannon

testAddBotForbidden :: Config -> DB.ClientState -> Brig -> Galley -> Http ()
testAddBotForbidden config db brig galley = withTestService config db brig defServiceApp $ \sref _ -> do
(pid, sid, userId -> uid1, userId -> uid2, _) <- prepareUsers sref brig
-- Create conversation without the service access role
let accessRoles = Set.fromList [TeamMemberAccessRole, NonTeamMemberAccessRole, GuestAccessRole]
_rs <- createConvWithAccessRoles (Just accessRoles) galley uid1 [uid2] <!! const 201 === statusCode
let Just cnv = responseJsonMaybe _rs
let cid = qUnqualified . cnvQualifiedId $ cnv
addBot brig uid1 pid sid cid !!! const 403 === statusCode

prepareUsers :: ServiceRef -> Brig -> Http (ProviderId, ServiceId, User, User, Text)
prepareUsers sref brig = do
let pid = sref ^. serviceRefProvider
let sid = sref ^. serviceRefId
-- Prepare users
u1 <- createUser "Ernie" brig
u2 <- createUser "Bert" brig
let uid1 = userId u1
quid1 = userQualifiedId u1
localDomain = qDomain quid1
uid2 = userId u2
h <- randomHandle
putHandle brig uid1 h !!! const 200 === statusCode
postConnection brig uid1 uid2 !!! const 201 === statusCode
putConnection brig uid2 uid1 Accepted !!! const 200 === statusCode
-- Create conversation
_rs <- createConv galley uid1 [uid2] <!! const 201 === statusCode
let Just cnv = responseJsonMaybe _rs
let cid = qUnqualified . cnvQualifiedId $ cnv
testAddRemoveBotUtil localDomain pid sid cid u1 u2 h sref buf brig galley cannon
pure (pid, sid, u1, u2, h)

testMessageBot :: Config -> DB.ClientState -> Brig -> Galley -> Cannon -> Http ()
testMessageBot config db brig galley cannon = withTestService config db brig defServiceApp $ \sref buf -> do
Expand Down Expand Up @@ -1257,7 +1275,15 @@ createConv ::
UserId ->
[UserId] ->
Http ResponseLBS
createConv g u us =
createConv = createConvWithAccessRoles Nothing

createConvWithAccessRoles ::
Maybe (Set AccessRoleV2) ->
Galley ->
UserId ->
[UserId] ->
Http ResponseLBS
createConvWithAccessRoles ars g u us =
post $
g
. path "/conversations"
Expand All @@ -1267,7 +1293,7 @@ createConv g u us =
. contentJson
. body (RequestBodyLBS (encode (NewConvUnmanaged conv)))
where
conv = NewConv us [] Nothing Set.empty Nothing Nothing Nothing Nothing roleNameWireAdmin
conv = NewConv us [] Nothing Set.empty ars Nothing Nothing Nothing roleNameWireAdmin

postMessage ::
Galley ->
Expand Down
34 changes: 22 additions & 12 deletions services/galley/test/integration/API.hs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ tests s =
where
mainTests =
testGroup
"Main API"
"Main Conversations API"
[ test s "status" status,
test s "metrics" metrics,
test s "create conversation" postConvOk,
Expand Down Expand Up @@ -1190,9 +1190,9 @@ postJoinConvOk = do
testJoinCodeConv :: TestM ()
testJoinCodeConv = do
let convName = "gossip"

Right noGuestsAccess <- liftIO $ genAccessRolesV2 [NonTeamMemberAccessRole] [GuestAccessRole]
alice <- randomUser
convId <- decodeConvId <$> postConv alice [] (Just convName) [CodeAccess] (Just (Set.fromList [TeamMemberAccessRole, NonTeamMemberAccessRole])) Nothing
convId <- decodeConvId <$> postConv alice [] (Just convName) [CodeAccess] (Just noGuestsAccess) Nothing
cCode <- decodeConvCodeEvent <$> postConvCode alice convId

qbob <- randomQualifiedUser
Expand All @@ -1209,8 +1209,9 @@ testGetCodeRejectedIfGuestLinksDisabled :: TestM ()
testGetCodeRejectedIfGuestLinksDisabled = do
galley <- view tsGalley
(owner, teamId, []) <- Util.createBindingTeamWithNMembers 0
Right accessRoles <- liftIO $ genAccessRolesV2 [TeamMemberAccessRole] [GuestAccessRole]
let createConvWithGuestLink = do
convId <- decodeConvId <$> postTeamConv teamId owner [] (Just "testConversation") [CodeAccess] (Just (Set.fromList [TeamMemberAccessRole, NonTeamMemberAccessRole])) Nothing
convId <- decodeConvId <$> postTeamConv teamId owner [] (Just "testConversation") [CodeAccess] (Just accessRoles) Nothing
void $ decodeConvCodeEvent <$> postConvCode owner convId
pure convId
convId <- createConvWithGuestLink
Expand All @@ -1229,7 +1230,8 @@ testPostCodeRejectedIfGuestLinksDisabled :: TestM ()
testPostCodeRejectedIfGuestLinksDisabled = do
galley <- view tsGalley
(owner, teamId, []) <- Util.createBindingTeamWithNMembers 0
convId <- decodeConvId <$> postTeamConv teamId owner [] (Just "testConversation") [CodeAccess] (Just (Set.fromList [TeamMemberAccessRole, NonTeamMemberAccessRole])) Nothing
Right noGuestsAccess <- liftIO $ genAccessRolesV2 [NonTeamMemberAccessRole] [GuestAccessRole]
convId <- decodeConvId <$> postTeamConv teamId owner [] (Just "testConversation") [CodeAccess] (Just noGuestsAccess) Nothing
let checkPostCode expectedStatus = postConvCode owner convId !!! statusCode === const expectedStatus
let setStatus tfStatus =
TeamFeatures.putTeamFeatureFlagWithGalley @'Public.TeamFeatureGuestLinks galley owner teamId (Public.TeamFeatureStatusNoConfig tfStatus) !!! do
Expand All @@ -1247,7 +1249,8 @@ testJoinTeamConvGuestLinksDisabled = do
let convName = "testConversation"
(owner, teamId, []) <- Util.createBindingTeamWithNMembers 0
userNotInTeam <- randomUser
convId <- decodeConvId <$> postTeamConv teamId owner [] (Just convName) [CodeAccess] (Just (Set.fromList [TeamMemberAccessRole, NonTeamMemberAccessRole])) Nothing
Right accessRoles <- liftIO $ genAccessRolesV2 [TeamMemberAccessRole, NonTeamMemberAccessRole] [GuestAccessRole]
convId <- decodeConvId <$> postTeamConv teamId owner [] (Just convName) [CodeAccess] (Just accessRoles) Nothing
cCode <- decodeConvCodeEvent <$> postConvCode owner convId

-- works by default
Expand Down Expand Up @@ -1278,7 +1281,8 @@ testJoinNonTeamConvGuestLinksDisabled = do
let convName = "testConversation"
(owner, teamId, []) <- Util.createBindingTeamWithNMembers 0
userNotInTeam <- randomUser
convId <- decodeConvId <$> postConv owner [] (Just convName) [CodeAccess] (Just (Set.fromList [TeamMemberAccessRole, NonTeamMemberAccessRole])) Nothing
Right accessRoles <- liftIO $ genAccessRolesV2 [NonTeamMemberAccessRole] [GuestAccessRole]
convId <- decodeConvId <$> postConv owner [] (Just convName) [CodeAccess] (Just accessRoles) Nothing
cCode <- decodeConvCodeEvent <$> postConvCode owner convId

-- works by default
Expand All @@ -1303,7 +1307,8 @@ postJoinCodeConvOk = do
let bob = qUnqualified qbob
eve <- ephemeralUser
dave <- ephemeralUser
conv <- decodeConvId <$> postConv alice [] (Just "gossip") [CodeAccess] (Just (Set.fromList [TeamMemberAccessRole, NonTeamMemberAccessRole])) Nothing
Right accessRoles <- liftIO $ genAccessRolesV2 [TeamMemberAccessRole, NonTeamMemberAccessRole] [GuestAccessRole]
conv <- decodeConvId <$> postConv alice [] (Just "gossip") [CodeAccess] (Just accessRoles) Nothing
let qconv = Qualified conv (qDomain qbob)
cCode <- decodeConvCodeEvent <$> postConvCode alice conv
-- currently ConversationCode is used both as return type for POST ../code and as body for ../join
Expand All @@ -1326,11 +1331,12 @@ postJoinCodeConvOk = do
WS.assertMatchN (5 # Second) [wsA, wsB] $
wsAssertMemberJoinWithRole qconv qbob [qbob] roleNameWireMember
-- changing access to non-activated should give eve access
let nonActivatedAccess = ConversationAccessData (Set.singleton CodeAccess) (Set.fromList [TeamMemberAccessRole, NonTeamMemberAccessRole, GuestAccessRole, ServiceAccessRole])
Right accessRolesWithGuests <- liftIO $ genAccessRolesV2 [TeamMemberAccessRole, NonTeamMemberAccessRole, GuestAccessRole] []
let nonActivatedAccess = ConversationAccessData (Set.singleton CodeAccess) accessRolesWithGuests
putAccessUpdate alice conv nonActivatedAccess !!! const 200 === statusCode
postJoinCodeConv eve payload !!! const 200 === statusCode
-- after removing CodeAccess, no further people can join
let noCodeAccess = ConversationAccessData (Set.singleton InviteAccess) (Set.fromList [TeamMemberAccessRole, NonTeamMemberAccessRole, GuestAccessRole, ServiceAccessRole])
let noCodeAccess = ConversationAccessData (Set.singleton InviteAccess) accessRoles
putAccessUpdate alice conv noCodeAccess !!! const 200 === statusCode
postJoinCodeConv dave payload !!! const 404 === statusCode

Expand Down Expand Up @@ -1373,7 +1379,10 @@ postConvertCodeConv = do
getConvCode alice conv !!! const 404 === statusCode
-- create a new code; then revoking CodeAccess should make existing codes invalid
void $ postConvCode alice conv
let noCodeAccess = ConversationAccessData (Set.singleton InviteAccess) (Set.fromList [TeamMemberAccessRole, NonTeamMemberAccessRole, GuestAccessRole, ServiceAccessRole])
let noCodeAccess =
ConversationAccessData
(Set.singleton InviteAccess)
(Set.fromList [TeamMemberAccessRole, NonTeamMemberAccessRole, GuestAccessRole, ServiceAccessRole])
putAccessUpdate alice conv noCodeAccess !!! const 200 === statusCode
getConvCode alice conv !!! const 403 === statusCode

Expand All @@ -1397,8 +1406,9 @@ postConvertTeamConv = do
-- creating a team-only conversation containing eve should fail
createTeamConvAccessRaw alice tid [bob, eve] (Just "blaa") acc (Just (Set.fromList [TeamMemberAccessRole])) Nothing Nothing
!!! const 403 === statusCode
Right accessRoles <- liftIO $ genAccessRolesV2 [TeamMemberAccessRole, NonTeamMemberAccessRole, GuestAccessRole] []
-- create conversation allowing any type of guest
conv <- createTeamConvAccess alice tid [bob, eve] (Just "blaa") acc (Just (Set.fromList [TeamMemberAccessRole, NonTeamMemberAccessRole, GuestAccessRole, ServiceAccessRole])) Nothing Nothing
conv <- createTeamConvAccess alice tid [bob, eve] (Just "blaa") acc (Just accessRoles) Nothing Nothing
-- mallory joins by herself
mallory <- ephemeralUser
let qmallory = Qualified mallory localDomain
Expand Down

0 comments on commit 1b37f06

Please sign in to comment.