diff --git a/libs/api-client/src/Network/Wire/Client/API/Conversation.hs b/libs/api-client/src/Network/Wire/Client/API/Conversation.hs
index 8983b7f8c85..80345558b11 100644
--- a/libs/api-client/src/Network/Wire/Client/API/Conversation.hs
+++ b/libs/api-client/src/Network/Wire/Client/API/Conversation.hs
@@ -140,6 +140,6 @@ createConv users name = sessionRequest req rsc readBody
method POST
. path "conversations"
. acceptJson
- . json (NewConvUnmanaged (NewConv users name mempty Nothing Nothing Nothing Nothing roleNameWireAdmin))
+ . json (NewConvUnmanaged (NewConv users [] name mempty Nothing Nothing Nothing Nothing roleNameWireAdmin))
$ empty
rsc = status201 :| []
diff --git a/libs/wire-api/src/Wire/API/Conversation.hs b/libs/wire-api/src/Wire/API/Conversation.hs
index fd2e35dee60..fa9fc57bae4 100644
--- a/libs/wire-api/src/Wire/API/Conversation.hs
+++ b/libs/wire-api/src/Wire/API/Conversation.hs
@@ -384,6 +384,8 @@ modelNewConversation = Doc.defineModel "NewConversation" $ do
Doc.description "JSON object to create a new conversation"
Doc.property "users" (Doc.unique $ Doc.array Doc.bytes') $
Doc.description "List of user IDs (excluding the requestor) to be part of this conversation"
+ Doc.property "qualified_users" (Doc.unique . Doc.array $ Doc.bytes') $
+ Doc.description "List of qualified user IDs to be part of this conversation"
Doc.property "name" Doc.string' $ do
Doc.description "The conversation name"
Doc.optional
@@ -414,6 +416,9 @@ instance Arbitrary NewConvUnmanaged where
data NewConv = NewConv
{ newConvUsers :: [UserId],
+ -- | A list of qualified users, which can include some local qualified users
+ -- too.
+ newConvQualifiedUsers :: [Qualified UserId],
newConvName :: Maybe Text,
newConvAccess :: Set Access,
newConvAccessRole :: Maybe AccessRole,
@@ -437,6 +442,13 @@ newConvSchema =
"users"
(description ?~ usersDesc)
(array schema)
+ <*> newConvQualifiedUsers
+ .= ( fieldWithDocModifier
+ "qualified_users"
+ (description ?~ qualifiedUsersDesc)
+ (array schema)
+ <|> pure []
+ )
<*> newConvName .= opt (field "name" schema)
<*> (Set.toList . newConvAccess)
.= ( field "access" (Set.fromList <$> array schema)
@@ -465,7 +477,10 @@ newConvSchema =
where
usersDesc =
"List of user IDs (excluding the requestor) to be \
- \part of this conversation"
+ \part of this conversation (deprecated)"
+ qualifiedUsersDesc =
+ "List of qualified user IDs (excluding the requestor) \
+ \to be part of this conversation"
newConvIsManaged :: NewConv -> Bool
newConvIsManaged = maybe False cnvManaged . newConvTeam
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_1.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_1.json
index d0d5e76b057..6236cbb2ef1 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_1.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_1.json
@@ -8,5 +8,6 @@
"teamid": "00000001-0000-0001-0000-000200000000"
},
"receipt_mode": 4,
- "message_timer": 193643728192048
+ "message_timer": 193643728192048,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_10.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_10.json
index 0223225ebb3..c2daf4e3a7c 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_10.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_10.json
@@ -12,5 +12,6 @@
"teamid": "00000001-0000-0001-0000-000000000001"
},
"receipt_mode": 1,
- "message_timer": 8061252799624904
+ "message_timer": 8061252799624904,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_11.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_11.json
index 142a6d0d1f4..6c529a22ee9 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_11.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_11.json
@@ -11,5 +11,6 @@
"teamid": "00000001-0000-0000-0000-000200000001"
},
"receipt_mode": -2,
- "message_timer": 6292627004994884
+ "message_timer": 6292627004994884,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_12.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_12.json
index d2504f314a5..4fcadb414c4 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_12.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_12.json
@@ -14,5 +14,6 @@
"managed": true,
"teamid": "00000000-0000-0001-0000-000100000000"
},
- "message_timer": 7043412511612101
+ "message_timer": 7043412511612101,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_13.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_13.json
index ae4e7f50d05..c9ef6cba2b8 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_13.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_13.json
@@ -12,5 +12,6 @@
"managed": true,
"teamid": "00000000-0000-0001-0000-000100000001"
},
- "receipt_mode": 0
+ "receipt_mode": 0,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_14.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_14.json
index c4f0faee5f7..7ffb20118c5 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_14.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_14.json
@@ -20,5 +20,6 @@
"managed": true,
"teamid": "00000001-0000-0001-0000-000000000000"
},
- "message_timer": 8669416711689656
+ "message_timer": 8669416711689656,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_15.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_15.json
index a92993fe12b..4897835141b 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_15.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_15.json
@@ -17,5 +17,6 @@
"teamid": "00000001-0000-0001-0000-000000000000"
},
"receipt_mode": 2,
- "message_timer": 1166285470102499
+ "message_timer": 1166285470102499,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_16.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_16.json
index 1934d39888e..01aeef6c744 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_16.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_16.json
@@ -10,5 +10,6 @@
"managed": true,
"teamid": "00000002-0000-0001-0000-000000000001"
},
- "message_timer": 4425819976591162
+ "message_timer": 4425819976591162,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_17.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_17.json
index d73ce51661a..b8d1bb81cf9 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_17.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_17.json
@@ -17,5 +17,6 @@
"managed": true,
"teamid": "00000000-0000-0000-0000-000000000000"
},
- "message_timer": 5065871950676797
+ "message_timer": 5065871950676797,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_18.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_18.json
index 1120207cbce..862a990ee99 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_18.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_18.json
@@ -8,5 +8,6 @@
"managed": true,
"teamid": "00000001-0000-0000-0000-000100000001"
},
- "receipt_mode": -1
+ "receipt_mode": -1,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_19.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_19.json
index 46a4e152ffc..1f29a6a2939 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_19.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_19.json
@@ -12,5 +12,6 @@
"managed": true,
"teamid": "00000001-0000-0000-0000-000100000001"
},
- "message_timer": 8428756728484885
+ "message_timer": 8428756728484885,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_2.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_2.json
index d186ff4b00f..3944598bbc6 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_2.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_2.json
@@ -14,5 +14,11 @@
"managed": true,
"teamid": "00000002-0000-0002-0000-000200000002"
},
- "message_timer": 5509522199847054
+ "message_timer": 5509522199847054,
+ "qualified_users": [
+ {
+ "domain": "test.example.com",
+ "id": "00000000-0000-0000-0000-000100000001"
+ }
+ ]
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_20.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_20.json
index 7a67aa24955..7634af079d0 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_20.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_20.json
@@ -15,5 +15,6 @@
"managed": true,
"teamid": "00000000-0000-0000-0000-000000000001"
},
- "message_timer": 6168723896440273
+ "message_timer": 6168723896440273,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_3.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_3.json
index 4dea92bc2ea..07019eaaeab 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_3.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_3.json
@@ -14,5 +14,11 @@
"teamid": "00000001-0000-0001-0000-000000000000"
},
"receipt_mode": 2,
- "message_timer": 582808797322573
+ "message_timer": 582808797322573,
+ "qualified_users": [
+ {
+ "domain": "test.example.com",
+ "id": "00000000-0000-0000-0000-000100000001"
+ }
+ ]
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_4.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_4.json
index 1b1f6259c82..70d83c053d2 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_4.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_4.json
@@ -14,5 +14,6 @@
"team": {
"managed": true,
"teamid": "00000001-0000-0001-0000-000100000002"
- }
+ },
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_5.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_5.json
index 0bb397139b5..c54f6a917f6 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_5.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_5.json
@@ -13,5 +13,6 @@
"teamid": "00000001-0000-0000-0000-000100000000"
},
"receipt_mode": -1,
- "message_timer": 1570858821505994
+ "message_timer": 1570858821505994,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_6.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_6.json
index 1e64c83bd3b..9663fd804a0 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_6.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_6.json
@@ -15,5 +15,6 @@
"managed": true,
"teamid": "00000000-0000-0000-0000-000000000001"
},
- "message_timer": 6614365418177275
+ "message_timer": 6614365418177275,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_7.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_7.json
index 085917605a6..39582d207b7 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_7.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_7.json
@@ -12,5 +12,6 @@
"teamid": "00000001-0000-0001-0000-000100000000"
},
"receipt_mode": 0,
- "message_timer": 7417375067718994
+ "message_timer": 7417375067718994,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_8.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_8.json
index 5f7c0d496cc..ae8c6078685 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_8.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_8.json
@@ -11,5 +11,6 @@
"managed": true,
"teamid": "00000001-0000-0000-0000-000100000001"
},
- "receipt_mode": 2
+ "receipt_mode": 2,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvManaged_user_9.json b/libs/wire-api/test/golden/testObject_NewConvManaged_user_9.json
index cc918ca9b6c..9edd2c8c3d3 100644
--- a/libs/wire-api/test/golden/testObject_NewConvManaged_user_9.json
+++ b/libs/wire-api/test/golden/testObject_NewConvManaged_user_9.json
@@ -12,5 +12,6 @@
"teamid": "00000001-0000-0000-0000-000000000000"
},
"receipt_mode": 1,
- "message_timer": 2550845209410146
+ "message_timer": 2550845209410146,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_1.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_1.json
index bb91c95bdc9..edf0282f535 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_1.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_1.json
@@ -14,5 +14,6 @@
"teamid": "00000000-0000-0001-0000-000000000000"
},
"receipt_mode": 1,
- "message_timer": 3320987366258987
+ "message_timer": 3320987366258987,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_10.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_10.json
index 053072f59a0..e35128c1deb 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_10.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_10.json
@@ -11,5 +11,6 @@
"conversation_role": "30mnzwj79jo9ear300qs4k_x2262nyaqxt9qga1_zaqmto43q2935t4dzaan_qnlstgjix7efmqfljkpww2lz",
"name": "",
"receipt_mode": 2,
- "message_timer": 5041503034744095
+ "message_timer": 5041503034744095,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_11.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_11.json
index d8208e917eb..69680bdfa2e 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_11.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_11.json
@@ -10,5 +10,6 @@
"teamid": "00000000-0000-0000-0000-000000000000"
},
"receipt_mode": 1,
- "message_timer": 6019134025424754
+ "message_timer": 6019134025424754,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_12.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_12.json
index f4b4ae0d413..844cd30e634 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_12.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_12.json
@@ -3,5 +3,6 @@
"users": [],
"conversation_role": "wqhaeljk9zpp5nmspwl",
"name": ">+",
- "receipt_mode": 1
+ "receipt_mode": 1,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_13.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_13.json
index cb760bbf05d..04278d46724 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_13.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_13.json
@@ -13,5 +13,6 @@
"teamid": "00000000-0000-0000-0000-000000000001"
},
"receipt_mode": -2,
- "message_timer": 211460552735402
+ "message_timer": 211460552735402,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_14.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_14.json
index cbf228dbd47..6690d68083a 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_14.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_14.json
@@ -10,5 +10,6 @@
"conversation_role": "fga_hfm9uzn_5z883y6r_kumb",
"name": "",
"receipt_mode": -2,
- "message_timer": 854777662274030
+ "message_timer": 854777662274030,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_15.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_15.json
index 181966845c5..6fda451288c 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_15.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_15.json
@@ -14,5 +14,6 @@
"teamid": "00000001-0000-0001-0000-000200000002"
},
"receipt_mode": 1,
- "message_timer": 4005602882980532
+ "message_timer": 4005602882980532,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_16.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_16.json
index 1d351204ce8..4b11912e073 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_16.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_16.json
@@ -11,5 +11,6 @@
"managed": false,
"teamid": "00000000-0000-0001-0000-000100000000"
},
- "receipt_mode": 1
+ "receipt_mode": 1,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_17.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_17.json
index 45a12afa84f..cfab3503e9b 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_17.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_17.json
@@ -22,5 +22,6 @@
"teamid": "00000000-0000-0001-0000-000100000001"
},
"receipt_mode": 0,
- "message_timer": 880163555151907
+ "message_timer": 880163555151907,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_18.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_18.json
index c245ea066da..43f14dfd5af 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_18.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_18.json
@@ -12,5 +12,6 @@
"conversation_role": "ugehcdyu_ob9_woawlths95ez8cgtb6wjqypp7vbjaooiczerb5zpc6srxszgkrdu8l24ygz_",
"name": "sd\u0006",
"receipt_mode": -2,
- "message_timer": 3120553871655858
+ "message_timer": 3120553871655858,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_19.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_19.json
index f3d6cf50c57..d9086140b52 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_19.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_19.json
@@ -9,5 +9,6 @@
"conversation_role": "xik7vc3wp82gw4r934rad_bhmf2orany3qgu_tx9huwfrlxy8m0id71x20uddebps30zdahe_ffcxxhc",
"name": "Cu\u0011",
"receipt_mode": -1,
- "message_timer": 864918593306344
+ "message_timer": 864918593306344,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_2.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_2.json
index b5fe627bd56..eefa9c41791 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_2.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_2.json
@@ -9,5 +9,11 @@
"teamid": "00000000-0000-0001-0000-000000000001"
},
"receipt_mode": -1,
- "message_timer": 2406292360203739
+ "message_timer": 2406292360203739,
+ "qualified_users": [
+ {
+ "domain": "testdomain.example.com",
+ "id": "00000000-0000-0000-0000-000100000001"
+ }
+ ]
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_20.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_20.json
index 7974cdee0a4..f6acbbccc1d 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_20.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_20.json
@@ -6,5 +6,6 @@
"conversation_role": "udhi2sbf7tzyshrh",
"name": "\u000f",
"receipt_mode": -1,
- "message_timer": 3641984282941906
+ "message_timer": 3641984282941906,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_3.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_3.json
index 0448c8d6ae4..b695ab354d0 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_3.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_3.json
@@ -13,5 +13,6 @@
"teamid": "00000000-0000-0001-0000-000000000001"
},
"receipt_mode": 0,
- "message_timer": 6764297310186120
+ "message_timer": 6764297310186120,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_4.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_4.json
index 25f2a9d5f99..4eb17cc8734 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_4.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_4.json
@@ -9,5 +9,6 @@
"managed": false,
"teamid": "00000000-0000-0001-0000-000000000000"
},
- "receipt_mode": -2
+ "receipt_mode": -2,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_5.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_5.json
index 333b08ad340..8c3300d8268 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_5.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_5.json
@@ -13,5 +13,6 @@
"team": {
"managed": false,
"teamid": "00000001-0000-0001-0000-000100000000"
- }
+ },
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_6.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_6.json
index f416efa308e..9ad3210f5e9 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_6.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_6.json
@@ -7,5 +7,6 @@
"conversation_role": "5zlsxm_95e5j1lk04d6rka_1svnnk65pov7tqs",
"name": "`3",
"receipt_mode": 2,
- "message_timer": 3993332602038581
+ "message_timer": 3993332602038581,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_7.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_7.json
index ac18846f376..7864d68fd0e 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_7.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_7.json
@@ -11,5 +11,6 @@
"teamid": "00000001-0000-0002-0000-000200000000"
},
"receipt_mode": -3,
- "message_timer": 5300164242243961
+ "message_timer": 5300164242243961,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_8.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_8.json
index 1767aace79f..adcf1b3067a 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_8.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_8.json
@@ -13,5 +13,6 @@
"teamid": "00000000-0000-0001-0000-000100000001"
},
"receipt_mode": -1,
- "message_timer": 5317293791913533
+ "message_timer": 5317293791913533,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_9.json b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_9.json
index 0f13c872607..52bf3a61ab4 100644
--- a/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_9.json
+++ b/libs/wire-api/test/golden/testObject_NewConvUnmanaged_user_9.json
@@ -11,5 +11,6 @@
],
"conversation_role": "n8cjajmyhnw3hqv8sohb8674nwnpsv7g57i2hjhexg9tww",
"name": "L",
- "message_timer": 7179840365742041
+ "message_timer": 7179840365742041,
+ "qualified_users": []
}
\ No newline at end of file
diff --git a/libs/wire-api/test/unit/Test/Wire/API/Golden/Generated/NewConvManaged_user.hs b/libs/wire-api/test/unit/Test/Wire/API/Golden/Generated/NewConvManaged_user.hs
index ee0c0afee55..8711efb108f 100644
--- a/libs/wire-api/test/unit/Test/Wire/API/Golden/Generated/NewConvManaged_user.hs
+++ b/libs/wire-api/test/unit/Test/Wire/API/Golden/Generated/NewConvManaged_user.hs
@@ -18,8 +18,10 @@
-- with this program. If not, see .
module Test.Wire.API.Golden.Generated.NewConvManaged_user where
+import Data.Domain
import Data.Id (Id (Id))
import Data.Misc (Milliseconds (Ms, ms))
+import Data.Qualified
import qualified Data.Set as Set (fromList)
import qualified Data.UUID as UUID (fromString)
import Imports (Bool (True), Maybe (Just, Nothing), fromJust)
@@ -38,6 +40,7 @@ import Wire.API.Conversation
newConvAccessRole,
newConvMessageTimer,
newConvName,
+ newConvQualifiedUsers,
newConvReceiptMode,
newConvTeam,
newConvUsers,
@@ -48,11 +51,15 @@ import Wire.API.Conversation
)
import Wire.API.Conversation.Role (parseRoleName)
+testDomain :: Domain
+testDomain = Domain "test.example.com"
+
testObject_NewConvManaged_user_1 :: NewConvManaged
testObject_NewConvManaged_user_1 =
NewConvManaged
( NewConv
{ newConvUsers = [],
+ newConvQualifiedUsers = [],
newConvName = Nothing,
newConvAccess = Set.fromList [],
newConvAccessRole = Just ActivatedAccessRole,
@@ -74,6 +81,7 @@ testObject_NewConvManaged_user_2 =
NewConvManaged
( NewConv
{ newConvUsers = [(Id (fromJust (UUID.fromString "00000002-0000-0001-0000-000400000000")))],
+ newConvQualifiedUsers = [Qualified (Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000001"))) testDomain],
newConvName = Just "\995491\SUB5",
newConvAccess = Set.fromList [PrivateAccess, InviteAccess, LinkAccess],
newConvAccessRole = Just NonActivatedAccessRole,
@@ -98,6 +106,7 @@ testObject_NewConvManaged_user_3 =
[ (Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000000"))),
(Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000001")))
],
+ newConvQualifiedUsers = [Qualified (Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000001"))) testDomain],
newConvName = Just "NwK",
newConvAccess = Set.fromList [CodeAccess],
newConvAccessRole = Just TeamAccessRole,
@@ -128,6 +137,7 @@ testObject_NewConvManaged_user_4 =
(Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000001"))),
(Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000000")))
],
+ newConvQualifiedUsers = [],
newConvName = Just "k\61561-",
newConvAccess = Set.fromList [PrivateAccess, LinkAccess],
newConvAccessRole = Just TeamAccessRole,
@@ -159,6 +169,7 @@ testObject_NewConvManaged_user_5 =
(Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000001"))),
(Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000000")))
],
+ newConvQualifiedUsers = [],
newConvName = Just "v",
newConvAccess = Set.fromList [],
newConvAccessRole = Nothing,
@@ -184,6 +195,7 @@ testObject_NewConvManaged_user_6 =
(Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000"))),
(Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001")))
],
+ newConvQualifiedUsers = [],
newConvName = Just "P\1098873\r",
newConvAccess = Set.fromList [InviteAccess, CodeAccess],
newConvAccessRole = Just PrivateAccessRole,
@@ -213,6 +225,7 @@ testObject_NewConvManaged_user_7 =
[ (Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000000"))),
(Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000001")))
],
+ newConvQualifiedUsers = [],
newConvName = Just "\CAN",
newConvAccess = Set.fromList [],
newConvAccessRole = Just ActivatedAccessRole,
@@ -242,6 +255,7 @@ testObject_NewConvManaged_user_8 =
[ (Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000000"))),
(Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000000")))
],
+ newConvQualifiedUsers = [],
newConvName = Just "&",
newConvAccess = Set.fromList [],
newConvAccessRole = Just ActivatedAccessRole,
@@ -263,6 +277,7 @@ testObject_NewConvManaged_user_9 =
NewConvManaged
( NewConv
{ newConvUsers = [],
+ newConvQualifiedUsers = [],
newConvName = Nothing,
newConvAccess = Set.fromList [PrivateAccess, InviteAccess, LinkAccess],
newConvAccessRole = Just NonActivatedAccessRole,
@@ -284,6 +299,7 @@ testObject_NewConvManaged_user_10 =
NewConvManaged
( NewConv
{ newConvUsers = [(Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001")))],
+ newConvQualifiedUsers = [],
newConvName = Just "z\1112901",
newConvAccess = Set.fromList [LinkAccess],
newConvAccessRole = Nothing,
@@ -310,6 +326,7 @@ testObject_NewConvManaged_user_11 =
NewConvManaged
( NewConv
{ newConvUsers = [],
+ newConvQualifiedUsers = [],
newConvName = Just "r",
newConvAccess = Set.fromList [InviteAccess],
newConvAccessRole = Just NonActivatedAccessRole,
@@ -334,6 +351,7 @@ testObject_NewConvManaged_user_12 =
[ (Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001"))),
(Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000000")))
],
+ newConvQualifiedUsers = [],
newConvName = Just "",
newConvAccess = Set.fromList [PrivateAccess, CodeAccess],
newConvAccessRole = Just TeamAccessRole,
@@ -360,6 +378,7 @@ testObject_NewConvManaged_user_13 =
NewConvManaged
( NewConv
{ newConvUsers = [],
+ newConvQualifiedUsers = [],
newConvName = Just "\tB",
newConvAccess = Set.fromList [PrivateAccess, InviteAccess, LinkAccess],
newConvAccessRole = Just NonActivatedAccessRole,
@@ -397,6 +416,7 @@ testObject_NewConvManaged_user_14 =
(Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000000"))),
(Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000001")))
],
+ newConvQualifiedUsers = [],
newConvName = Just "",
newConvAccess = Set.fromList [CodeAccess],
newConvAccessRole = Nothing,
@@ -424,6 +444,7 @@ testObject_NewConvManaged_user_15 =
(Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000001"))),
(Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000")))
],
+ newConvQualifiedUsers = [],
newConvName = Nothing,
newConvAccess = Set.fromList [PrivateAccess, CodeAccess],
newConvAccessRole = Just NonActivatedAccessRole,
@@ -445,6 +466,7 @@ testObject_NewConvManaged_user_16 =
NewConvManaged
( NewConv
{ newConvUsers = [],
+ newConvQualifiedUsers = [],
newConvName = Just "",
newConvAccess = Set.fromList [InviteAccess, CodeAccess],
newConvAccessRole = Nothing,
@@ -478,6 +500,7 @@ testObject_NewConvManaged_user_17 =
(Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000000"))),
(Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000000")))
],
+ newConvQualifiedUsers = [],
newConvName = Just "",
newConvAccess = Set.fromList [LinkAccess],
newConvAccessRole = Just TeamAccessRole,
@@ -499,6 +522,7 @@ testObject_NewConvManaged_user_18 =
NewConvManaged
( NewConv
{ newConvUsers = [],
+ newConvQualifiedUsers = [],
newConvName = Just "\36412\tJ",
newConvAccess = Set.fromList [],
newConvAccessRole = Just ActivatedAccessRole,
@@ -520,6 +544,7 @@ testObject_NewConvManaged_user_19 =
NewConvManaged
( NewConv
{ newConvUsers = [(Id (fromJust (UUID.fromString "00000003-0000-0004-0000-000400000002")))],
+ newConvQualifiedUsers = [],
newConvName = Just "",
newConvAccess = Set.fromList [PrivateAccess],
newConvAccessRole = Just ActivatedAccessRole,
@@ -546,6 +571,7 @@ testObject_NewConvManaged_user_20 =
(Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001"))),
(Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000000")))
],
+ newConvQualifiedUsers = [],
newConvName = Just "\SOH?(",
newConvAccess = Set.fromList [PrivateAccess, InviteAccess],
newConvAccessRole = Just NonActivatedAccessRole,
diff --git a/libs/wire-api/test/unit/Test/Wire/API/Golden/Generated/NewConvUnmanaged_user.hs b/libs/wire-api/test/unit/Test/Wire/API/Golden/Generated/NewConvUnmanaged_user.hs
index a135ebb6385..b7ff8111f6f 100644
--- a/libs/wire-api/test/unit/Test/Wire/API/Golden/Generated/NewConvUnmanaged_user.hs
+++ b/libs/wire-api/test/unit/Test/Wire/API/Golden/Generated/NewConvUnmanaged_user.hs
@@ -18,8 +18,10 @@
-- with this program. If not, see .
module Test.Wire.API.Golden.Generated.NewConvUnmanaged_user where
+import Data.Domain (Domain (Domain))
import Data.Id (Id (Id))
import Data.Misc (Milliseconds (Ms, ms))
+import Data.Qualified (Qualified (Qualified))
import qualified Data.Set as Set (fromList)
import qualified Data.UUID as UUID (fromString)
import Imports (Bool (False), Maybe (Just, Nothing), fromJust)
@@ -38,6 +40,7 @@ import Wire.API.Conversation
newConvAccessRole,
newConvMessageTimer,
newConvName,
+ newConvQualifiedUsers,
newConvReceiptMode,
newConvTeam,
newConvUsers,
@@ -48,6 +51,9 @@ import Wire.API.Conversation
)
import Wire.API.Conversation.Role (parseRoleName)
+testDomain :: Domain
+testDomain = Domain "testdomain.example.com"
+
testObject_NewConvUnmanaged_user_1 :: NewConvUnmanaged
testObject_NewConvUnmanaged_user_1 =
NewConvUnmanaged
@@ -56,6 +62,7 @@ testObject_NewConvUnmanaged_user_1 =
[ (Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000000000001"))),
(Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000000")))
],
+ newConvQualifiedUsers = [],
newConvName = Nothing,
newConvAccess = Set.fromList [PrivateAccess, InviteAccess],
newConvAccessRole = Just ActivatedAccessRole,
@@ -77,6 +84,7 @@ testObject_NewConvUnmanaged_user_2 =
NewConvUnmanaged
( NewConv
{ newConvUsers = [],
+ newConvQualifiedUsers = [Qualified (Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000001"))) testDomain],
newConvName = Just "\128527\1061495",
newConvAccess = Set.fromList [],
newConvAccessRole = Just PrivateAccessRole,
@@ -103,6 +111,7 @@ testObject_NewConvUnmanaged_user_3 =
NewConvUnmanaged
( NewConv
{ newConvUsers = [],
+ newConvQualifiedUsers = [],
newConvName = Just "f",
newConvAccess = Set.fromList [InviteAccess, LinkAccess, CodeAccess],
newConvAccessRole = Just ActivatedAccessRole,
@@ -129,6 +138,7 @@ testObject_NewConvUnmanaged_user_4 =
NewConvUnmanaged
( NewConv
{ newConvUsers = [],
+ newConvQualifiedUsers = [],
newConvName = Just "\135359\70751z",
newConvAccess = Set.fromList [CodeAccess],
newConvAccessRole = Nothing,
@@ -159,6 +169,7 @@ testObject_NewConvUnmanaged_user_5 =
(Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001"))),
(Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000001")))
],
+ newConvQualifiedUsers = [],
newConvName = Just "X9",
newConvAccess = Set.fromList [InviteAccess, LinkAccess],
newConvAccessRole = Nothing,
@@ -185,6 +196,7 @@ testObject_NewConvUnmanaged_user_6 =
NewConvUnmanaged
( NewConv
{ newConvUsers = [],
+ newConvQualifiedUsers = [],
newConvName = Just "`3",
newConvAccess = Set.fromList [LinkAccess],
newConvAccessRole = Just TeamAccessRole,
@@ -200,6 +212,7 @@ testObject_NewConvUnmanaged_user_7 =
NewConvUnmanaged
( NewConv
{ newConvUsers = [(Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000400000004")))],
+ newConvQualifiedUsers = [],
newConvName = Just "\1038759\b\1057989'",
newConvAccess = Set.fromList [],
newConvAccessRole = Just ActivatedAccessRole,
@@ -221,6 +234,7 @@ testObject_NewConvUnmanaged_user_8 =
NewConvUnmanaged
( NewConv
{ newConvUsers = [(Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000000")))],
+ newConvQualifiedUsers = [],
newConvName = Just "",
newConvAccess = Set.fromList [InviteAccess],
newConvAccessRole = Just ActivatedAccessRole,
@@ -250,6 +264,7 @@ testObject_NewConvUnmanaged_user_9 =
[ (Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000001"))),
(Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000000")))
],
+ newConvQualifiedUsers = [],
newConvName = Just "L",
newConvAccess = Set.fromList [PrivateAccess, InviteAccess, LinkAccess],
newConvAccessRole = Just ActivatedAccessRole,
@@ -268,6 +283,7 @@ testObject_NewConvUnmanaged_user_10 =
[ (Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000001"))),
(Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000000")))
],
+ newConvQualifiedUsers = [],
newConvName = Just "",
newConvAccess = Set.fromList [PrivateAccess, CodeAccess],
newConvAccessRole = Just ActivatedAccessRole,
@@ -289,6 +305,7 @@ testObject_NewConvUnmanaged_user_11 =
[ (Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000000"))),
(Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000000")))
],
+ newConvQualifiedUsers = [],
newConvName = Nothing,
newConvAccess = Set.fromList [],
newConvAccessRole = Nothing,
@@ -310,6 +327,7 @@ testObject_NewConvUnmanaged_user_12 =
NewConvUnmanaged
( NewConv
{ newConvUsers = [],
+ newConvQualifiedUsers = [],
newConvName = Just ">+",
newConvAccess = Set.fromList [],
newConvAccessRole = Nothing,
@@ -330,6 +348,7 @@ testObject_NewConvUnmanaged_user_13 =
(Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000000000001"))),
(Id (fromJust (UUID.fromString "00000001-0000-0000-0000-000100000001")))
],
+ newConvQualifiedUsers = [],
newConvName = Just ".L'",
newConvAccess = Set.fromList [],
newConvAccessRole = Nothing,
@@ -359,6 +378,7 @@ testObject_NewConvUnmanaged_user_14 =
[ (Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000100000001"))),
(Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000000000000")))
],
+ newConvQualifiedUsers = [],
newConvName = Just "",
newConvAccess = Set.fromList [CodeAccess],
newConvAccessRole = Just NonActivatedAccessRole,
@@ -374,6 +394,7 @@ testObject_NewConvUnmanaged_user_15 =
NewConvUnmanaged
( NewConv
{ newConvUsers = [(Id (fromJust (UUID.fromString "00000002-0000-0003-0000-000300000003")))],
+ newConvQualifiedUsers = [],
newConvName = Just "b\1008988",
newConvAccess = Set.fromList [PrivateAccess, InviteAccess, CodeAccess],
newConvAccessRole = Nothing,
@@ -395,6 +416,7 @@ testObject_NewConvUnmanaged_user_16 =
NewConvUnmanaged
( NewConv
{ newConvUsers = [],
+ newConvQualifiedUsers = [],
newConvName = Just "!",
newConvAccess = Set.fromList [PrivateAccess, CodeAccess],
newConvAccessRole = Just PrivateAccessRole,
@@ -426,6 +448,7 @@ testObject_NewConvUnmanaged_user_17 =
(Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000000"))),
(Id (fromJust (UUID.fromString "00000000-0000-0000-0000-000100000000")))
],
+ newConvQualifiedUsers = [],
newConvName = Just "\ETXB\119338",
newConvAccess = Set.fromList [PrivateAccess, LinkAccess, CodeAccess],
newConvAccessRole = Nothing,
@@ -457,6 +480,7 @@ testObject_NewConvUnmanaged_user_18 =
(Id (fromJust (UUID.fromString "00000001-0000-0001-0000-000000000001"))),
(Id (fromJust (UUID.fromString "00000000-0000-0001-0000-000100000000")))
],
+ newConvQualifiedUsers = [],
newConvName = Just "sd\ACK",
newConvAccess = Set.fromList [PrivateAccess, CodeAccess],
newConvAccessRole = Nothing,
@@ -473,6 +497,7 @@ testObject_NewConvUnmanaged_user_19 =
NewConvUnmanaged
( NewConv
{ newConvUsers = [(Id (fromJust (UUID.fromString "00000002-0000-0001-0000-000000000002")))],
+ newConvQualifiedUsers = [],
newConvName = Just "Cu\DC1",
newConvAccess = Set.fromList [InviteAccess, LinkAccess],
newConvAccessRole = Nothing,
@@ -489,6 +514,7 @@ testObject_NewConvUnmanaged_user_20 =
NewConvUnmanaged
( NewConv
{ newConvUsers = [],
+ newConvQualifiedUsers = [],
newConvName = Just "\SI\1070774",
newConvAccess = Set.fromList [PrivateAccess],
newConvAccessRole = Nothing,
diff --git a/services/brig/test/integration/API/Provider.hs b/services/brig/test/integration/API/Provider.hs
index 7c73826f5ca..e5d8dde4a02 100644
--- a/services/brig/test/integration/API/Provider.hs
+++ b/services/brig/test/integration/API/Provider.hs
@@ -1252,7 +1252,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 Nothing Nothing Nothing Nothing roleNameWireAdmin
postMessage ::
Galley ->
diff --git a/services/brig/test/integration/API/Team/Util.hs b/services/brig/test/integration/API/Team/Util.hs
index 32b4b20b7a3..f2bea23d82a 100644
--- a/services/brig/test/integration/API/Team/Util.hs
+++ b/services/brig/test/integration/API/Team/Util.hs
@@ -206,7 +206,7 @@ createTeamConv g tid u us mtimer = do
let tinfo = Just $ ConvTeamInfo tid False
let conv =
NewConvUnmanaged $
- NewConv us Nothing (Set.fromList []) Nothing tinfo mtimer Nothing roleNameWireAdmin
+ NewConv us [] Nothing (Set.fromList []) Nothing tinfo mtimer Nothing roleNameWireAdmin
r <-
post
( g
@@ -228,7 +228,7 @@ createManagedConv g tid u us mtimer = do
let tinfo = Just $ ConvTeamInfo tid True
let conv =
NewConvManaged $
- NewConv us Nothing (Set.fromList []) Nothing tinfo mtimer Nothing roleNameWireAdmin
+ NewConv us [] Nothing (Set.fromList []) Nothing tinfo mtimer Nothing roleNameWireAdmin
r <-
post
( g
diff --git a/services/brig/test/integration/Federation/End2end.hs b/services/brig/test/integration/Federation/End2end.hs
index 44a284847ba..2ae3bf71b0a 100644
--- a/services/brig/test/integration/Federation/End2end.hs
+++ b/services/brig/test/integration/Federation/End2end.hs
@@ -212,7 +212,7 @@ testAddRemoteUsersToLocalConv brig1 galley1 brig2 = do
alice <- randomUser brig1
bob <- randomUser brig2
- let conv = NewConvUnmanaged $ NewConv [] (Just "gossip") mempty Nothing Nothing Nothing Nothing roleNameWireAdmin
+ let conv = NewConvUnmanaged $ NewConv [] [] (Just "gossip") mempty Nothing Nothing Nothing Nothing roleNameWireAdmin
convId <-
cnvId . responseJsonUnsafe
<$> post
diff --git a/services/galley/galley.cabal b/services/galley/galley.cabal
index 3b591fb7d51..8b2b0dabc1f 100644
--- a/services/galley/galley.cabal
+++ b/services/galley/galley.cabal
@@ -4,7 +4,7 @@ cabal-version: 1.12
--
-- see: https://github.com/sol/hpack
--
--- hash: c1d012009b1ef15dcf63843768bedfcf8ca4b2e86ac33d5f43ab680cb82e7450
+-- hash: 63f50e23b5853d8dd4b8b87b8588dc8499783ec5e7e72a181b0ccb399089a6ed
name: galley
version: 0.83.0
@@ -215,6 +215,7 @@ executable galley-integration
, brig-types
, bytestring
, bytestring-conversion
+ , case-insensitive
, cassandra-util
, cassava
, cereal
diff --git a/services/galley/package.yaml b/services/galley/package.yaml
index 1718f5d333e..b3b28541be1 100644
--- a/services/galley/package.yaml
+++ b/services/galley/package.yaml
@@ -153,6 +153,7 @@ executables:
- brig-types
- bytestring
- bytestring-conversion
+ - case-insensitive
- cassandra-util
- cassava
- cereal
diff --git a/services/galley/src/Galley/API/Create.hs b/services/galley/src/Galley/API/Create.hs
index 788602411fc..c85e175cedb 100644
--- a/services/galley/src/Galley/API/Create.hs
+++ b/services/galley/src/Galley/API/Create.hs
@@ -29,6 +29,7 @@ import Control.Lens hiding ((??))
import Control.Monad.Catch
import Data.Id
import Data.List1 (list1)
+import Data.Qualified (Qualified (..), partitionRemoteOrLocalIds')
import Data.Range
import qualified Data.Set as Set
import Data.Time
@@ -96,17 +97,23 @@ internalCreateManagedConversation zusr zcon (NewConvManaged body) = do
createRegularGroupConv :: UserId -> ConnId -> NewConvUnmanaged -> Galley ConversationResponse
createRegularGroupConv zusr zcon (NewConvUnmanaged body) = do
name <- rangeCheckedMaybe (newConvName body)
- _uids <- checkedConvSize (newConvUsers body) -- currently not needed, as we only consider local IDs
- let localUserIds = newConvUsers body
- ensureConnected zusr localUserIds
- localCheckedUsers <- checkedConvSize localUserIds
+ localDomain <- viewFederationDomain
+ let unqualifiedUserIds = newConvUsers body
+ qualifiedUserIds = newConvQualifiedUsers body
+ let allUsers = map (`Qualified` localDomain) unqualifiedUserIds <> qualifiedUserIds
+ checkedUsers <- checkedConvSize allUsers
+ let checkedPartitionedUsers = partitionRemoteOrLocalIds' localDomain <$> checkedUsers
+ let (remotes, locals) = fromConvSize checkedPartitionedUsers
+ ensureConnected zusr locals
+ checkRemoteUsersExist remotes
+ -- FUTUREWORK: Implement (2) and (3) as per comments for Update.addMembers. (also for createTeamGroupConv)
c <-
Data.createConversation
zusr
name
(access body)
(accessRole body)
- localCheckedUsers
+ checkedPartitionedUsers
(newConvTeam body)
(newConvMessageTimer body)
(newConvReceiptMode body)
@@ -118,22 +125,30 @@ createRegularGroupConv zusr zcon (NewConvUnmanaged body) = do
-- handlers above. Allows both unmanaged and managed conversations.
createTeamGroupConv :: UserId -> ConnId -> Public.ConvTeamInfo -> Public.NewConv -> Galley ConversationResponse
createTeamGroupConv zusr zcon tinfo body = do
- let localUserIds = newConvUsers body
name <- rangeCheckedMaybe (newConvName body)
+ localDomain <- viewFederationDomain
+ let unqualifiedUserIds = newConvUsers body
+ qualifiedUserIds = newConvQualifiedUsers body
+ allUserIds = map (`Qualified` localDomain) unqualifiedUserIds <> qualifiedUserIds
let convTeam = cnvTeamId tinfo
zusrMembership <- Data.teamMember convTeam zusr
+ void $ permissionCheck CreateConversation zusrMembership
+ checkedUsers <- checkedConvSize allUserIds
+ let checkedPartitionedUsers = partitionRemoteOrLocalIds' localDomain <$> checkedUsers
+ (remotes, localUserIds) = fromConvSize checkedPartitionedUsers
convMemberships <- mapM (Data.teamMember convTeam) localUserIds
ensureAccessRole (accessRole body) (zip localUserIds convMemberships)
- void $ permissionCheck CreateConversation zusrMembership
- otherConvMems <-
+ checkedPartitionedUsersManaged <-
if cnvManaged tinfo
then do
-- ConvMaxSize MUST be < than hardlimit so the conv size check is enough
maybeAllMembers <- Data.teamMembersForFanout convTeam
let otherConvMems = filter (/= zusr) $ map (view userId) $ (maybeAllMembers ^. teamMembers)
- checkedConvSize otherConvMems
+ checkedLocalUsers <- checkedConvSize otherConvMems
+ -- NOTE: Team members are local, therefore there are no remote users in
+ -- this case
+ pure (fmap ([],) checkedLocalUsers)
else do
- otherConvMems <- checkedConvSize localUserIds
-- In teams we don't have 1:1 conversations, only regular conversations. We want
-- users without the 'AddRemoveConvMember' permission to still be able to create
-- regular conversations, therefore we check for 'AddRemoveConvMember' only if
@@ -144,13 +159,15 @@ createTeamGroupConv zusr zcon tinfo body = do
-- Not sure at the moment how to best solve this but it is unlikely
-- we can ever get rid of the team permission model anyway - the only thing I can
-- think of is that 'partners' can create convs but not be admins...
- when (length (fromConvSize otherConvMems) > 1) $ do
+ when (length allUserIds > 1) $ do
void $ permissionCheck DoNotUseDeprecatedAddRemoveConvMember zusrMembership
-- Team members are always considered to be connected, so we only check
-- 'ensureConnected' for non-team-members.
- ensureConnectedToLocals zusr (notTeamMember (fromConvSize otherConvMems) (catMaybes convMemberships))
- pure otherConvMems
- conv <- Data.createConversation zusr name (access body) (accessRole body) otherConvMems (newConvTeam body) (newConvMessageTimer body) (newConvReceiptMode body) (newConvUsersRole body)
+ ensureConnectedToLocals zusr (notTeamMember localUserIds (catMaybes convMemberships))
+ pure checkedPartitionedUsers
+ checkRemoteUsersExist remotes
+ -- FUTUREWORK: Implement (2) and (3) as per comments for Update.addMembers.
+ conv <- Data.createConversation zusr name (access body) (accessRole body) checkedPartitionedUsersManaged (newConvTeam body) (newConvMessageTimer body) (newConvReceiptMode body) (newConvUsersRole body)
now <- liftIO getCurrentTime
-- NOTE: We only send (conversation) events to members of the conversation
notifyCreatedConversation (Just now) zusr (Just zcon) conv
diff --git a/services/galley/src/Galley/API/Update.hs b/services/galley/src/Galley/API/Update.hs
index 5d3ed694a98..89ac626cdc5 100644
--- a/services/galley/src/Galley/API/Update.hs
+++ b/services/galley/src/Galley/API/Update.hs
@@ -66,10 +66,8 @@ import qualified Brig.Types.User as User
import Control.Lens
import Control.Monad.Catch
import Control.Monad.State
-import Control.Monad.Trans.Except
import Data.ByteString.Conversion (toByteString')
import Data.Code
-import Data.Domain (Domain)
import Data.Id
import Data.LegalHold (UserLegalHoldStatus (UserLegalHoldNoConsent), defUserLegalHoldStatus)
import Data.List.Extra (nubOrdOn)
@@ -79,7 +77,6 @@ import Data.Misc (FutureWork (..))
import Data.Qualified
import Data.Range
import qualified Data.Set as Set
-import Data.Tagged (unTagged)
import Data.Time
import Galley.API.Error
import Galley.API.Mapping
@@ -116,9 +113,6 @@ import Wire.API.Conversation (InviteQualified (invQRoleName))
import qualified Wire.API.Conversation as Public
import qualified Wire.API.Conversation.Code as Public
import qualified Wire.API.Event.Conversation as Public
-import Wire.API.Federation.API.Brig as FederatedBrig
-import Wire.API.Federation.Client as FederatedBrig
-import Wire.API.Federation.Error
import qualified Wire.API.Message as Public
import qualified Wire.API.Message.Proto as Proto
import Wire.API.Routes.Public.Galley (UpdateResponses)
@@ -507,7 +501,7 @@ addMembers zusr zcon convId invite = do
ensureAccess conv InviteAccess
ensureConvRoleNotElevated self (invQRoleName invite)
checkLocals conv (Data.convTeam conv) newLocals
- checkRemotes newRemotes
+ checkRemoteUsersExist newRemotes
addToConversation mems (zusr, memConvRoleName self) zcon ((,invQRoleName invite) <$> newLocals) ((,invQRoleName invite) <$> newRemotes) conv
where
userIsMember u = (^. userId . to (== u))
@@ -525,26 +519,6 @@ addMembers zusr zcon convId invite = do
ensureAccessRole (Data.convAccessRole conv) (zip newUsers $ repeat Nothing)
ensureConnectedOrSameTeam zusr newUsers
- checkRemotes :: [Remote UserId] -> Galley ()
- checkRemotes =
- traverse_ (uncurry checkRemotesFor)
- . Map.assocs
- . partitionQualified
- . map unTagged
-
- checkRemotesFor :: Domain -> [UserId] -> Galley ()
- checkRemotesFor domain uids = do
- let rpc = FederatedBrig.getUsersByIds FederatedBrig.clientRoutes uids
- users <-
- runExceptT (executeFederated domain rpc)
- >>= either (throwM . federationErrorToWai) pure
- let uids' =
- map
- (qUnqualified . User.profileQualifiedId)
- (filter (not . User.profileDeleted) users)
- unless (Set.fromList uids == Set.fromList uids') $
- throwM unknownRemoteUser
-
updateSelfMemberH :: UserId ::: ConnId ::: ConvId ::: JsonRequest Public.MemberUpdate -> Galley Response
updateSelfMemberH (zusr ::: zcon ::: cid ::: req) = do
update <- fromJsonBody req
diff --git a/services/galley/src/Galley/API/Util.hs b/services/galley/src/Galley/API/Util.hs
index fcc3128a930..bb32dde8bff 100644
--- a/services/galley/src/Galley/API/Util.hs
+++ b/services/galley/src/Galley/API/Util.hs
@@ -21,12 +21,15 @@ import Brig.Types (Relation (..))
import Brig.Types.Intra (ReAuthUser (..))
import Control.Lens (view, (.~), (^.))
import Control.Monad.Catch
+import Control.Monad.Except (runExceptT)
import Data.ByteString.Conversion
import Data.Domain (Domain)
import Data.Id as Id
+import qualified Data.Map as Map
import Data.Misc (PlainTextPassword (..))
-import Data.Qualified (Remote)
+import Data.Qualified (Qualified (qUnqualified), Remote, partitionQualified)
import qualified Data.Set as Set
+import Data.Tagged (Tagged (unTagged))
import qualified Data.Text.Lazy as LT
import Data.Time
import Galley.API.Error
@@ -48,6 +51,10 @@ import Network.Wai
import Network.Wai.Predicate hiding (Error)
import Network.Wai.Utilities
import UnliftIO (concurrently)
+import qualified Wire.API.Federation.API.Brig as FederatedBrig
+import qualified Wire.API.Federation.Client as Federation
+import Wire.API.Federation.Error (federationErrorToWai)
+import qualified Wire.API.User as User
type JSON = Media "application" "json"
@@ -131,9 +138,9 @@ ensureConvRoleNotElevated origMember targetRole = do
(_, _) ->
throwM (badRequest "Custom roles not supported")
--- | If a team memeber is not given throw 'notATeamMember'; if the given team
+-- | If a team member is not given throw 'notATeamMember'; if the given team
-- member does not have the given permission, throw 'operationDenied'.
--- Otherwise, return unit.
+-- Otherwise, return the team member.
permissionCheck :: (IsPerm perm, Show perm) => perm -> Maybe TeamMember -> Galley TeamMember
permissionCheck p = \case
Just m -> do
@@ -299,3 +306,24 @@ pushConversationEvent e users bots = do
viewFederationDomain :: MonadReader Env m => m Domain
viewFederationDomain = view (options . optSettings . setFederationDomain)
+
+checkRemoteUsersExist :: [Remote UserId] -> Galley ()
+checkRemoteUsersExist =
+ -- FUTUREWORK: pooledForConcurrentlyN_ instead of sequential checks per domain
+ traverse_ (uncurry checkRemotesFor)
+ . Map.assocs
+ . partitionQualified
+ . map unTagged
+
+checkRemotesFor :: Domain -> [UserId] -> Galley ()
+checkRemotesFor domain uids = do
+ let rpc = FederatedBrig.getUsersByIds FederatedBrig.clientRoutes uids
+ users <-
+ runExceptT (Federation.executeFederated domain rpc)
+ >>= either (throwM . federationErrorToWai) pure
+ let uids' =
+ map
+ (qUnqualified . User.profileQualifiedId)
+ (filter (not . User.profileDeleted) users)
+ unless (Set.fromList uids == Set.fromList uids') $
+ throwM unknownRemoteUser
diff --git a/services/galley/src/Galley/Data.hs b/services/galley/src/Galley/Data.hs
index a1ab046806c..b0d88886fe5 100644
--- a/services/galley/src/Galley/Data.hs
+++ b/services/galley/src/Galley/Data.hs
@@ -574,7 +574,7 @@ createConversation ::
Maybe (Range 1 256 Text) ->
[Access] ->
AccessRole ->
- ConvSizeChecked [UserId] ->
+ ConvSizeChecked ([Remote UserId], [UserId]) ->
Maybe ConvTeamInfo ->
-- | Message timer
Maybe Milliseconds ->
@@ -592,10 +592,8 @@ createConversation usr name acc role others tinfo mtimer recpt othersConversatio
setConsistency Quorum
addPrepQuery Cql.insertConv (conv, RegularConv, usr, Set (toList acc), role, fromRange <$> name, Just (cnvTeamId ti), mtimer, recpt)
addPrepQuery Cql.insertTeamConv (cnvTeamId ti, conv, cnvManaged ti)
- -- FUTUREWORK: split users into list of remote and local users
- let remoteUsers :: [Remote UserId]
- remoteUsers = []
- (_, mems, rMems) <- addMembersUncheckedWithRole now conv (usr, roleNameWireAdmin) (toList $ list1 (usr, roleNameWireAdmin) ((,othersConversationRole) <$> fromConvSize others)) ((,othersConversationRole) <$> remoteUsers)
+ let (remoteUsers, localUsers) = fromConvSize others
+ (_, mems, rMems) <- addMembersUncheckedWithRole now conv (usr, roleNameWireAdmin) (toList $ list1 (usr, roleNameWireAdmin) ((,othersConversationRole) <$> localUsers)) ((,othersConversationRole) <$> remoteUsers)
return $ newConv conv RegularConv usr mems rMems acc role name (cnvTeamId <$> tinfo) mtimer recpt
createSelfConversation :: MonadClient m => UserId -> Maybe (Range 1 256 Text) -> m Conversation
diff --git a/services/galley/src/Galley/Validation.hs b/services/galley/src/Galley/Validation.hs
index 305be7f52b9..6473a52be4c 100644
--- a/services/galley/src/Galley/Validation.hs
+++ b/services/galley/src/Galley/Validation.hs
@@ -50,6 +50,7 @@ rangeCheckedMaybe (Just a) = Just <$> rangeChecked a
-- Between 0 and (setMaxConvSize - 1)
newtype ConvSizeChecked a = ConvSizeChecked {fromConvSize :: a}
+ deriving (Functor)
-- Between 1 and setMaxConvSize
data ConvMemberAddSizeChecked = ConvMemberAddSizeChecked {sizeCheckedLocals :: [(UserId, RoleName)], sizeCheckedRemotes :: [(Remote UserId, RoleName)]}
diff --git a/services/galley/test/integration/API.hs b/services/galley/test/integration/API.hs
index 99b8537ebe6..c138aaefd2c 100644
--- a/services/galley/test/integration/API.hs
+++ b/services/galley/test/integration/API.hs
@@ -98,8 +98,14 @@ tests s =
test s "fail to get >1000 conversation ids" getConvIdsFailMaxSize,
test s "page through conversations" getConvsPagingOk,
test s "fail to create conversation when not connected" postConvFailNotConnected,
+ test s "fail to create conversation with qualified users when not connected" postConvQualifiedFailNotConnected,
test s "M:N conversation creation must have view tsMaxConvSize
@@ -654,6 +670,16 @@ postConvFailNumMembers = do
const 400 === statusCode
const (Just "client-error") === fmap label . responseJsonUnsafe
+postConvQualifiedFailNumMembers :: TestM ()
+postConvQualifiedFailNumMembers = do
+ n <- fromIntegral <$> view tsMaxConvSize
+ alice <- randomUser
+ bob : others <- replicateM n randomQualifiedUser
+ connectLocalQualifiedUsers alice (list1 bob others)
+ postConvQualified alice (bob : others) Nothing [] Nothing Nothing !!! do
+ const 400 === statusCode
+ const (Just "client-error") === fmap label . responseJsonUnsafe
+
-- | If somebody has blocked a user, that user shouldn't be able to create a
-- group conversation which includes them.
postConvFailBlocked :: TestM ()
@@ -668,6 +694,67 @@ postConvFailBlocked = do
const 403 === statusCode
const (Just "not-connected") === fmap label . responseJsonUnsafe
+--- | If somebody has blocked a user, that user shouldn't be able to create a
+-- group conversation which includes them.
+postConvQualifiedFailBlocked :: TestM ()
+postConvQualifiedFailBlocked = do
+ alice <- randomUser
+ bob <- randomQualifiedUser
+ jane <- randomQualifiedUser
+ connectLocalQualifiedUsers alice (list1 bob [jane])
+ putConnectionQualified jane alice Blocked
+ !!! const 200 === statusCode
+ postConvQualified alice [bob, jane] Nothing [] Nothing Nothing !!! do
+ const 403 === statusCode
+ const (Just "not-connected") === fmap label . responseJsonUnsafe
+
+postConvQualifiedNonExistentDomain :: TestM ()
+postConvQualifiedNonExistentDomain = do
+ alice <- randomUser
+ bob <- flip Qualified (Domain "non-existent.example.com") <$> randomId
+ postConvQualified alice [bob] Nothing [] Nothing Nothing !!! do
+ const 422 === statusCode
+
+postConvQualifiedNonExistentUser :: TestM ()
+postConvQualifiedNonExistentUser = do
+ alice <- randomUser
+ bobId <- randomId
+ charlieId <- randomId
+ let remoteDomain = Domain "far-away.example.com"
+ bob = Qualified bobId remoteDomain
+ charlie = Qualified charlieId remoteDomain
+ opts <- view tsGConf
+ _g <- view tsGalley
+ (resp, _) <-
+ withTempMockFederator
+ opts
+ remoteDomain
+ (const [mkProfile charlie (Name "charlie")])
+ (postConvQualified alice [bob, charlie] (Just "remote gossip") [] Nothing Nothing)
+ liftIO $ do
+ statusCode resp @?= 400
+ let err = responseJsonUnsafe resp :: Object
+ (err ^. at "label") @?= Just "unknown-remote-user"
+
+postConvQualifiedFederationNotEnabled :: TestM ()
+postConvQualifiedFederationNotEnabled = do
+ g <- view tsGalley
+ alice <- randomUser
+ bob <- flip Qualified (Domain "some-remote-backend.example.com") <$> randomId
+ opts <- view tsGConf
+ let federatorNotConfigured :: Opts = opts & optFederator .~ Nothing
+ withSettingsOverrides federatorNotConfigured $
+ postConvHelper g alice [bob] !!! do
+ const 400 === statusCode
+ const (Just "federation-not-enabled") === fmap label . responseJsonUnsafe
+
+-- like postConvQualified
+-- FUTUREWORK: figure out how to use functions in the TestM monad inside withSettingsOverrides and remove this duplication
+postConvHelper :: (MonadIO m, MonadHttp m) => (Request -> Request) -> UserId -> [Qualified UserId] -> m ResponseLBS
+postConvHelper g zusr newUsers = do
+ let conv = NewConvUnmanaged $ NewConv [] newUsers (Just "gossip") (Set.fromList []) Nothing Nothing Nothing Nothing roleNameWireAdmin
+ post $ g . path "/conversations" . zUser zusr . zConn "conn" . zType "access" . json conv
+
postSelfConvOk :: TestM ()
postSelfConvOk = do
alice <- randomUser
@@ -692,7 +779,7 @@ postConvO2OFailWithSelf :: TestM ()
postConvO2OFailWithSelf = do
g <- view tsGalley
alice <- randomUser
- let inv = NewConvUnmanaged (NewConv [alice] Nothing mempty Nothing Nothing Nothing Nothing roleNameWireAdmin)
+ let inv = NewConvUnmanaged (NewConv [alice] [] Nothing mempty Nothing Nothing Nothing Nothing roleNameWireAdmin)
post (g . path "/conversations/one2one" . zUser alice . zConn "conn" . zType "access" . json inv) !!! do
const 403 === statusCode
const (Just "invalid-op") === fmap label . responseJsonUnsafe
@@ -853,6 +940,17 @@ getConvOk = do
getConv bob conv !!! const 200 === statusCode
getConv chuck conv !!! const 200 === statusCode
+getConvQualifiedOk :: TestM ()
+getConvQualifiedOk = do
+ alice <- randomUser
+ bob <- randomQualifiedUser
+ chuck <- randomQualifiedUser
+ connectLocalQualifiedUsers alice (list1 bob [chuck])
+ conv <- decodeConvId <$> postConvQualified alice [bob, chuck] (Just "gossip") [] Nothing Nothing
+ getConv alice conv !!! const 200 === statusCode
+ getConv (qUnqualified bob) conv !!! const 200 === statusCode
+ getConv (qUnqualified chuck) conv !!! const 200 === statusCode
+
accessConvMeta :: TestM ()
accessConvMeta = do
g <- view tsGalley
diff --git a/services/galley/test/integration/API/Teams.hs b/services/galley/test/integration/API/Teams.hs
index 8cbb2154641..fb72bb73b5f 100644
--- a/services/galley/test/integration/API/Teams.hs
+++ b/services/galley/test/integration/API/Teams.hs
@@ -880,7 +880,7 @@ testAddManagedConv = do
let tinfo = ConvTeamInfo tid True
let conv =
NewConvManaged $
- NewConv [owner] (Just "blah") (Set.fromList []) Nothing (Just tinfo) Nothing Nothing roleNameWireAdmin
+ NewConv [owner] [] (Just "blah") (Set.fromList []) Nothing (Just tinfo) Nothing Nothing roleNameWireAdmin
post
( g
. path "/conversations"
diff --git a/services/galley/test/integration/API/Teams/LegalHold.hs b/services/galley/test/integration/API/Teams/LegalHold.hs
index 6fe2929b925..a23c1fa1f64 100644
--- a/services/galley/test/integration/API/Teams/LegalHold.hs
+++ b/services/galley/test/integration/API/Teams/LegalHold.hs
@@ -29,6 +29,7 @@ import qualified API.SQS as SQS
import API.Util
import Bilge hiding (accept, head, timeout, trace)
import Bilge.Assert
+import qualified Bilge.TestSession as BilgeTest
import Brig.Types.Client
import Brig.Types.Intra (ConnectionStatus (ConnectionStatus), UserSet (..))
import Brig.Types.Provider
@@ -71,12 +72,10 @@ import Galley.Types.Teams
import Gundeck.Types.Notification (ntfPayload)
import Imports
import Network.HTTP.Types.Status (status200, status400, status404)
-import Network.Wai
import Network.Wai as Wai
import qualified Network.Wai.Handler.Warp as Warp
import qualified Network.Wai.Handler.Warp.Internal as Warp
import qualified Network.Wai.Handler.WarpTLS as Warp
-import qualified Network.Wai.Test as WaiTest
import qualified Network.Wai.Utilities.Error as Error
import qualified Network.Wai.Utilities.Response as Wai
import System.IO (hPutStrLn)
@@ -1350,7 +1349,7 @@ withDummyTestServiceForTeamNoService go = do
-- it's here for historical reason because we did this in galley.yaml
-- at some point in the past rather than in an internal end-point, and that required spawning
-- another galley 'Application' with 'withSettingsOverrides'.
-withLHWhitelist :: forall a. HasCallStack => TeamId -> WaiTest.Session a -> TestM a
+withLHWhitelist :: forall a. HasCallStack => TeamId -> BilgeTest.SessionT TestM a -> TestM a
withLHWhitelist tid action = do
void $ putLHWhitelistTeam tid
opts <- view tsGConf
diff --git a/services/galley/test/integration/API/Util.hs b/services/galley/test/integration/API/Util.hs
index b4836c8206b..fa9828dd2a1 100644
--- a/services/galley/test/integration/API/Util.hs
+++ b/services/galley/test/integration/API/Util.hs
@@ -28,7 +28,8 @@ import Brig.Types.Intra (ConnectionStatus (ConnectionStatus), UserAccount (..),
import Brig.Types.Team.Invitation
import Brig.Types.User.Auth (CookieLabel (..))
import Control.Lens hiding (from, to, (#), (.=))
-import Control.Monad.Catch (MonadCatch, finally)
+import Control.Monad.Catch (MonadCatch, MonadMask)
+import qualified Control.Monad.Catch as Catch
import Control.Monad.Except (ExceptT, runExceptT)
import Control.Retry (constantDelay, exponentialBackoff, limitRetries, retrying)
import Data.Aeson hiding (json)
@@ -47,6 +48,7 @@ import Data.Json.Util (UTCTimeMillis)
import Data.LegalHold (defUserLegalHoldStatus)
import Data.List.NonEmpty (NonEmpty)
import Data.List1 as List1
+import qualified Data.Map as LMap
import qualified Data.Map.Strict as Map
import Data.Misc
import Data.ProtocolBuffers (encodeMessage)
@@ -79,12 +81,12 @@ import Gundeck.Types.Notification
queuedTime,
)
import Imports
-import qualified Network.Wai.Test as WaiTest
import System.Random
import qualified Test.QuickCheck as Q
import Test.Tasty.Cannon (TimeoutUnit (..), (#))
import qualified Test.Tasty.Cannon as WS
import Test.Tasty.HUnit
+import TestHelpers (viewFederationDomain)
import TestSetup
import UnliftIO.Timeout
import Util.Options
@@ -118,7 +120,7 @@ createBindingTeam :: HasCallStack => TestM (UserId, TeamId)
createBindingTeam = do
ownerid <- randomTeamCreator
teams <- getTeams ownerid
- let [team] = view (teamListTeams) teams
+ let [team] = view teamListTeams teams
let tid = view teamId team
SQS.assertQueue "create team" SQS.tActivate
refreshIndex
@@ -131,7 +133,7 @@ createBindingTeamWithMembers numUsers = do
mem <- addUserToTeam owner tid
SQS.assertQueue "add member" $ SQS.tUpdate (fromIntegral n) [owner]
refreshIndex
- return $ view Galley.Types.Teams.userId $ mem
+ return $ view Galley.Types.Teams.userId mem
return (tid, owner, members)
@@ -428,13 +430,13 @@ getInvitationCode t ref = do
. queryItem "invitation_id" (toByteString' ref)
)
let lbs = fromMaybe "" $ responseBody r
- return $ fromByteString . Text.encodeUtf8 =<< (lbs ^? key "code" . _String)
+ return $ fromByteString . Text.encodeUtf8 =<< lbs ^? key "code" . _String
fromMaybe (error "No code?")
<$> retrying
(constantDelay 800000 <> limitRetries 3)
(\_ -> pure . isNothing)
- (\_ -> getm)
+ (const getm)
-- Note that here we don't make use of the datatype because NewConv has a default
-- and therefore cannot be unset. However, given that this is to test the legacy
@@ -477,7 +479,7 @@ createTeamConvAccessRaw u tid us name acc role mtimer convRole = do
let tinfo = ConvTeamInfo tid False
let conv =
NewConvUnmanaged $
- NewConv us name (fromMaybe (Set.fromList []) acc) role (Just tinfo) mtimer Nothing (fromMaybe roleNameWireAdmin convRole)
+ NewConv us [] name (fromMaybe (Set.fromList []) acc) role (Just tinfo) mtimer Nothing (fromMaybe roleNameWireAdmin convRole)
post
( g
. path "/conversations"
@@ -506,7 +508,7 @@ createManagedConv u tid us name acc mtimer = do
let tinfo = ConvTeamInfo tid True
let conv =
NewConvManaged $
- NewConv us name (fromMaybe (Set.fromList []) acc) Nothing (Just tinfo) mtimer Nothing roleNameWireAdmin
+ NewConv us [] name (fromMaybe (Set.fromList []) acc) Nothing (Just tinfo) mtimer Nothing roleNameWireAdmin
r <-
post
( g
@@ -524,28 +526,34 @@ createOne2OneTeamConv u1 u2 n tid = do
g <- view tsGalley
let conv =
NewConvUnmanaged $
- NewConv [u2] n mempty Nothing (Just $ ConvTeamInfo tid False) Nothing Nothing roleNameWireAdmin
+ NewConv [u2] [] n mempty Nothing (Just $ ConvTeamInfo tid False) Nothing Nothing roleNameWireAdmin
post $ g . path "/conversations/one2one" . zUser u1 . zConn "conn" . zType "access" . json conv
postConv :: UserId -> [UserId] -> Maybe Text -> [Access] -> Maybe AccessRole -> Maybe Milliseconds -> TestM ResponseLBS
postConv u us name a r mtimer = postConvWithRole u us name a r mtimer roleNameWireAdmin
+postConvQualified :: (HasGalley m, MonadIO m, MonadMask m, MonadHttp m) => UserId -> [Qualified UserId] -> Maybe Text -> [Access] -> Maybe AccessRole -> Maybe Milliseconds -> m ResponseLBS
+postConvQualified u us name a r mtimer = postConvWithRoleQualified us u [] name a r mtimer roleNameWireAdmin
+
postTeamConv :: TeamId -> UserId -> [UserId] -> Maybe Text -> [Access] -> Maybe AccessRole -> Maybe Milliseconds -> TestM ResponseLBS
postTeamConv tid u us name a r mtimer = do
g <- view tsGalley
- let conv = NewConvUnmanaged $ NewConv us name (Set.fromList a) r (Just (ConvTeamInfo tid False)) mtimer Nothing roleNameWireAdmin
+ let conv = NewConvUnmanaged $ NewConv us [] name (Set.fromList a) r (Just (ConvTeamInfo tid False)) mtimer Nothing roleNameWireAdmin
post $ g . path "/conversations" . zUser u . zConn "conn" . zType "access" . json conv
postConvWithRole :: UserId -> [UserId] -> Maybe Text -> [Access] -> Maybe AccessRole -> Maybe Milliseconds -> RoleName -> TestM ResponseLBS
-postConvWithRole u us name a r mtimer role = do
- g <- view tsGalley
- let conv = NewConvUnmanaged $ NewConv us name (Set.fromList a) r Nothing mtimer Nothing role
+postConvWithRole = postConvWithRoleQualified []
+
+postConvWithRoleQualified :: (HasGalley m, MonadIO m, MonadMask m, MonadHttp m) => [Qualified UserId] -> UserId -> [UserId] -> Maybe Text -> [Access] -> Maybe AccessRole -> Maybe Milliseconds -> RoleName -> m ResponseLBS
+postConvWithRoleQualified qualifiedUsers u unqualifiedUsers name a r mtimer role = do
+ g <- viewGalley
+ let conv = NewConvUnmanaged $ NewConv unqualifiedUsers qualifiedUsers name (Set.fromList a) r Nothing mtimer Nothing role
post $ g . path "/conversations" . zUser u . zConn "conn" . zType "access" . json conv
postConvWithReceipt :: UserId -> [UserId] -> Maybe Text -> [Access] -> Maybe AccessRole -> Maybe Milliseconds -> ReceiptMode -> TestM ResponseLBS
postConvWithReceipt u us name a r mtimer rcpt = do
g <- view tsGalley
- let conv = NewConvUnmanaged $ NewConv us name (Set.fromList a) r Nothing mtimer (Just rcpt) roleNameWireAdmin
+ let conv = NewConvUnmanaged $ NewConv us [] name (Set.fromList a) r Nothing mtimer (Just rcpt) roleNameWireAdmin
post $ g . path "/conversations" . zUser u . zConn "conn" . zType "access" . json conv
postSelfConv :: UserId -> TestM ResponseLBS
@@ -556,7 +564,7 @@ postSelfConv u = do
postO2OConv :: UserId -> UserId -> Maybe Text -> TestM ResponseLBS
postO2OConv u1 u2 n = do
g <- view tsGalley
- let conv = NewConvUnmanaged $ NewConv [u2] n mempty Nothing Nothing Nothing Nothing roleNameWireAdmin
+ let conv = NewConvUnmanaged $ NewConv [u2] [] n mempty Nothing Nothing Nothing Nothing roleNameWireAdmin
post $ g . path "/conversations/one2one" . zUser u1 . zConn "conn" . zType "access" . json conv
postConnectConv :: UserId -> UserId -> Text -> Text -> Maybe Text -> TestM ResponseLBS
@@ -616,7 +624,7 @@ postOtrBroadcastMessage req usrs clt rcps = do
-- | 'postOtrBroadcastMessage' with @"report_missing"@ in body.
postOtrBroadcastMessage' :: (Monad m, MonadCatch m, MonadIO m, MonadHttp m, MonadFail m, HasCallStack) => (Request -> Request) -> Maybe [UserId] -> (Request -> Request) -> UserId -> ClientId -> [(UserId, ClientId, Text)] -> m ResponseLBS
-postOtrBroadcastMessage' g reportMissingBody f u d rec = do
+postOtrBroadcastMessage' g reportMissingBody f u d rec =
post $
g
. f
@@ -935,7 +943,7 @@ deleteUser u = do
delete (g . path "/i/user" . zUser u) !!! const 200 === statusCode
getTeamQueue :: HasCallStack => UserId -> Maybe NotificationId -> Maybe (Int, Bool) -> Bool -> TestM [(NotificationId, UserId)]
-getTeamQueue zusr msince msize onlyLast = do
+getTeamQueue zusr msince msize onlyLast =
parseEventList . responseJsonUnsafe
<$> ( getTeamQueue' zusr msince (fst <$> msize) onlyLast
[(NotificationId, UserId)]
parseEventList qnl
- | isJust msize && qnl ^. queuedHasMore /= (snd $ fromJust msize) =
+ | isJust msize && qnl ^. queuedHasMore /= snd (fromJust msize) =
error $ "expected has_more: " <> show (snd $ fromJust msize) <> "; but found: " <> show (qnl ^. queuedHasMore)
- | qnl ^. queuedTime /= Nothing =
+ | isJust (qnl ^. queuedTime) =
error $ "expected time: Nothing; but found: " <> show (qnl ^. queuedTime)
| otherwise =
fmap (_2 %~ parseEvt) . mconcat . fmap parseEvts . view queuedNotifications $ qnl
@@ -1049,7 +1057,7 @@ assertConvWithRole r t c s us n mt role = do
assertEqual "self" (Just s) (memId <$> _self)
assertEqual "others" (Just . Set.fromList $ us) (Set.fromList . map (qUnqualified . omQualifiedId) . toList <$> others)
assertEqual "creator is always and admin" (Just roleNameWireAdmin) (memConvRoleName <$> _self)
- assertBool "others role" (all (\x -> x == role) $ fromMaybe (error "Cannot be null") ((map omConvRoleName . toList <$> others)))
+ assertBool "others role" (all (== role) $ maybe (error "Cannot be null") (map omConvRoleName . toList) others)
assertBool "otr muted not false" (Just False == (memOtrMuted <$> _self))
assertBool "otr muted ref not empty" (isNothing (memOtrMutedRef =<< _self))
assertBool "otr archived not false" (Just False == (memOtrArchived <$> _self))
@@ -1075,7 +1083,7 @@ wsAssertOtr' evData conv usr from to txt n = do
-- | This assumes the default role name
wsAssertMemberJoin :: ConvId -> UserId -> [UserId] -> Notification -> IO ()
-wsAssertMemberJoin conv usr new n = wsAssertMemberJoinWithRole conv usr new roleNameWireAdmin n
+wsAssertMemberJoin conv usr new = wsAssertMemberJoinWithRole conv usr new roleNameWireAdmin
wsAssertMemberJoinWithRole :: ConvId -> UserId -> [UserId] -> RoleName -> Notification -> IO ()
wsAssertMemberJoinWithRole conv usr new role n = do
@@ -1084,7 +1092,7 @@ wsAssertMemberJoinWithRole conv usr new role n = do
evtConv e @?= conv
evtType e @?= MemberJoin
evtFrom e @?= usr
- evtData e @?= EdMembersJoin (SimpleMembers (fmap (\x -> SimpleMember x role) new))
+ evtData e @?= EdMembersJoin (SimpleMembers (fmap (`SimpleMember` role) new))
wsAssertMemberUpdateWithRole :: ConvId -> UserId -> UserId -> RoleName -> Notification -> IO ()
wsAssertMemberUpdateWithRole conv usr target role n = do
@@ -1195,6 +1203,20 @@ zType = header "Z-Type"
connectUsers :: UserId -> List1 UserId -> TestM ()
connectUsers u us = void $ connectUsersWith expect2xx u us
+-- TODO: it'd be nicer to just take a list here and handle the cases with 0
+-- users differently
+connectLocalQualifiedUsers :: UserId -> List1 (Qualified UserId) -> TestM ()
+connectLocalQualifiedUsers u us = do
+ localDomain <- viewFederationDomain
+ let partitionMap = partitionQualified . toList . toNonEmpty $ us
+ -- FUTUREWORK: connect all users, not just those on the same domain as 'u'
+ case LMap.lookup localDomain partitionMap of
+ Nothing -> err
+ Just [] -> err
+ Just (x : xs) -> void $ connectUsersWith expect2xx u (list1 x xs)
+ where
+ err = liftIO . assertFailure $ "No user on the domain with " ++ show u
+
connectUsersUnchecked ::
UserId ->
List1 UserId ->
@@ -1206,7 +1228,7 @@ connectUsersWith ::
UserId ->
List1 UserId ->
TestM (List1 (Response (Maybe Lazy.ByteString), Response (Maybe Lazy.ByteString)))
-connectUsersWith fn u us = mapM connectTo us
+connectUsersWith fn u = mapM connectTo
where
connectTo v = do
b <- view tsBrig
@@ -1260,6 +1282,27 @@ putConnection from to r = do
where
payload = RequestBodyLBS . encode $ object ["status" .= r]
+-- | A slightly modified copy of 'putConnection' from above.
+putConnectionQualified :: Qualified UserId -> UserId -> Relation -> TestM ResponseLBS
+putConnectionQualified fromQualified to r = do
+ localDomain <- viewFederationDomain
+ let (Qualified from qualifiedDomain) = fromQualified
+ liftIO $
+ assertEqual
+ "The qualified user's domain is not local"
+ localDomain
+ qualifiedDomain
+ brig <- view tsBrig
+ put $
+ brig
+ . paths ["/connections", toByteString' to]
+ . contentJson
+ . body payload
+ . zUser from
+ . zConn "conn"
+ where
+ payload = RequestBodyLBS . encode $ object ["status" .= r]
+
-- | A copy of `assertConnections from Brig integration tests.
assertConnections :: HasCallStack => UserId -> [ConnectionStatus] -> TestM ()
assertConnections u cstat = do
@@ -1267,7 +1310,7 @@ assertConnections u cstat = do
resp <- listConnections brig u show cstat <> " is not a subset of " <> show cstat'
where
status c = ConnectionStatus (ucFrom c) (ucTo c) (ucStatus c)
@@ -1294,7 +1337,7 @@ randomUser' isCreator hasPassword hasEmail = do
["name" .= fromEmail e]
<> ["password" .= defPassword | hasPassword]
<> ["email" .= fromEmail e | hasEmail]
- <> ["team" .= (Team.BindingNewTeam $ Team.newNewTeam (unsafeRange "teamName") (unsafeRange "defaultIcon")) | isCreator]
+ <> ["team" .= Team.BindingNewTeam (Team.newNewTeam (unsafeRange "teamName") (unsafeRange "defaultIcon")) | isCreator]
selfProfile <- responseJsonUnsafe <$> (post (b . path "/i/users" . json p) error $ "getStatus: failed to parse response: " ++ show r
Just j -> do
- let st = maybeFromJSON =<< (j ^? key "status")
+ let st = maybeFromJSON =<< j ^? key "status"
let decoded = fromMaybe (error $ "getStatus: failed to decode status" ++ show j) st
return $ decoded == Deleted
where
@@ -1567,11 +1610,11 @@ defCookieLabel = CookieLabel "auth"
-- | This allows you to run requests against a galley instantiated using the given options.
-- Note that ONLY 'galley' calls should occur within the provided action, calls to other
-- services will fail.
-withSettingsOverrides :: MonadIO m => Opts.Opts -> WaiTest.Session a -> m a
-withSettingsOverrides opts action = liftIO $ do
- (galleyApp, _, finalizer) <- Run.mkApp opts
- WaiTest.runSession action galleyApp
- `finally` liftIO finalizer
+withSettingsOverrides :: (HasGalley m, MonadIO m, MonadMask m) => Opts.Opts -> SessionT m a -> m a
+withSettingsOverrides opts action = do
+ (galleyApp, _, finalizer) <- liftIO $ Run.mkApp opts
+ runSessionT action galleyApp
+ `Catch.finally` liftIO finalizer
waitForMemberDeletion :: UserId -> TeamId -> UserId -> TestM ()
waitForMemberDeletion zusr tid uid = do
@@ -1710,13 +1753,13 @@ mkProfile quid name =
-- federator response (of an arbitrary JSON-serialisable type a) for every
-- expected request.
withTempMockFederator ::
- (MonadIO m, ToJSON a) =>
+ (MonadIO m, ToJSON a, HasGalley m, MonadMask m) =>
Opts.Opts ->
Domain ->
(FederatedRequest -> a) ->
- WaiTest.Session b ->
+ SessionT m b ->
m (b, Mock.ReceivedRequests)
-withTempMockFederator opts targetDomain resp action = liftIO . assertRightT
+withTempMockFederator opts targetDomain resp action = assertRightT
. Mock.withTempMockFederator st0 (pure . oresp)
$ \st -> lift $ do
let opts' =
diff --git a/services/galley/test/integration/API/Util/TeamFeature.hs b/services/galley/test/integration/API/Util/TeamFeature.hs
index a16be31d0d4..78edbf72342 100644
--- a/services/galley/test/integration/API/Util/TeamFeature.hs
+++ b/services/galley/test/integration/API/Util/TeamFeature.hs
@@ -20,6 +20,7 @@ module API.Util.TeamFeature where
import API.Util (zUser)
import qualified API.Util as Util
import Bilge
+import qualified Bilge.TestSession as BilgeTest
import Control.Lens (view, (.~))
import Data.Aeson (ToJSON)
import Data.ByteString.Conversion (toByteString')
@@ -27,11 +28,10 @@ import Data.Id (TeamId, UserId)
import Galley.Options (optSettings, setFeatureFlags)
import Galley.Types.Teams
import Imports
-import qualified Network.Wai.Test as WaiTest
import TestSetup
import qualified Wire.API.Team.Feature as Public
-withCustomSearchFeature :: FeatureTeamSearchVisibility -> WaiTest.Session () -> TestM ()
+withCustomSearchFeature :: FeatureTeamSearchVisibility -> BilgeTest.SessionT TestM () -> TestM ()
withCustomSearchFeature flag action = do
opts <- view tsGConf
let opts' = opts & optSettings . setFeatureFlags . flagTeamSearchVisibility .~ flag