@@ -147,6 +147,76 @@ void main() {
147
147
});
148
148
});
149
149
150
+ group ('package uploader invite' , () {
151
+ setupTestsWithAdminTokenIssues ((client) => client.adminInvokeAction (
152
+ 'package-invite-uploader' ,
153
+ AdminInvokeActionArguments (
154
+ arguments: {'package' : 'oxygen' , 'email' : 'member@example.com' })));
155
+
156
+ testWithProfile ('invite + accept' , fn: () async {
157
+ final adminClient = createPubApiClient (authToken: siteAdminToken);
158
+ final adminOutput = await adminClient.adminInvokeAction (
159
+ 'package-invite-uploader' ,
160
+ AdminInvokeActionArguments (
161
+ arguments: {'package' : 'oxygen' , 'email' : 'newmember@pub.dev' }));
162
+
163
+ expect (adminOutput.output, {
164
+ 'message' : 'Invited user' ,
165
+ 'package' : 'oxygen' ,
166
+ 'emailSent' : true ,
167
+ 'email' : 'newmember@pub.dev' ,
168
+ });
169
+
170
+ final email = fakeEmailSender.sentMessages.first;
171
+ expect (email.subject, 'You have a new invitation to confirm on pub.dev' );
172
+
173
+ final page = await auditBackend.listRecordsForPackage ('oxygen' );
174
+ final r = page.records
175
+ .firstWhere ((e) => e.kind == AuditLogRecordKind .uploaderInvited);
176
+ expect (r.summary,
177
+ '`support@pub.dev` invited `newmember@pub.dev` to be an uploader for package `oxygen`.' );
178
+
179
+ late String consentId;
180
+ await withFakeAuthRequestContext (
181
+ 'newmember@pub.dev' ,
182
+ () async {
183
+ final authenticatedUser = await requireAuthenticatedWebUser ();
184
+ final user = authenticatedUser.user;
185
+ final consentRow = await dbService.query <Consent >().run ().single;
186
+ final consent =
187
+ await consentBackend.getConsent (consentRow.consentId, user);
188
+ expect (consent.descriptionHtml, contains ('/packages/oxygen' ));
189
+ expect (consent.descriptionHtml,
190
+ contains ('perform administrative actions' ));
191
+ consentId = consentRow.consentId;
192
+ },
193
+ );
194
+
195
+ final acceptingClient =
196
+ await createFakeAuthPubApiClient (email: 'newmember@pub.dev' );
197
+ final rs = await acceptingClient.resolveConsent (
198
+ consentId, account_api.ConsentResult (granted: true ));
199
+ expect (rs.granted, true );
200
+
201
+ final page2 = await auditBackend.listRecordsForPackage ('oxygen' );
202
+ final r2 = page2.records.firstWhere (
203
+ (e) => e.kind == AuditLogRecordKind .uploaderInviteAccepted);
204
+ expect (r2.summary,
205
+ '`newmember@pub.dev` accepted uploader invite for package `oxygen`.' );
206
+
207
+ final uploaders =
208
+ (await packageBackend.lookupPackage ('oxygen' ))! .uploaders;
209
+ expect (uploaders! , hasLength (2 ));
210
+ expect (
211
+ await Future .wait (uploaders.map ((uploader) async =>
212
+ (await accountBackend.lookupUserById (uploader))! .email)),
213
+ {
214
+ 'admin@pub.dev' ,
215
+ 'newmember@pub.dev' ,
216
+ });
217
+ });
218
+ });
219
+
150
220
group ('create and delete publisher' , () {
151
221
testWithProfile ('publisher has packages' , fn: () async {
152
222
final p1 = await publisherBackend.lookupPublisher ('example.com' );
0 commit comments