Skip to content

Commit 23be802

Browse files
committed
Update user entry when user joins a project
1 parent 29a4455 commit 23be802

File tree

2 files changed

+137
-7
lines changed

2 files changed

+137
-7
lines changed

src/SIL.XForge.Scripture/Services/SFProjectService.cs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public class SFProjectService : ProjectService<SFProject, SFProjectSecret>, ISFP
4949
private readonly ITransceleratorService _transceleratorService;
5050
private readonly IEventMetricService _eventMetricService;
5151
private readonly ISFProjectRights _projectRights;
52+
private readonly IGuidService _guidService;
5253

5354
public SFProjectService(
5455
IRealtimeService realtimeService,
@@ -68,7 +69,8 @@ public SFProjectService(
6869
ITransceleratorService transceleratorService,
6970
IBackgroundJobClient backgroundJobClient,
7071
IEventMetricService eventMetricService,
71-
ISFProjectRights projectRights
72+
ISFProjectRights projectRights,
73+
IGuidService guidService
7274
)
7375
: base(realtimeService, siteOptions, audioService, projectSecrets, fileSystemService)
7476
{
@@ -86,6 +88,7 @@ ISFProjectRights projectRights
8688
_eventMetricService = eventMetricService;
8789
_backgroundJobClient = backgroundJobClient;
8890
_projectRights = projectRights;
91+
_guidService = guidService;
8992
}
9093

9194
protected override string ProjectAdminRole => SFProjectRole.Administrator;
@@ -1322,6 +1325,31 @@ await conn.CreateAsync(
13221325
}
13231326
// Listeners can now assume the ProjectUserConfig is ready when the user is added.
13241327
await base.AddUserToProjectAsync(conn, projectDoc, userDoc, projectRole, shareKey);
1328+
if (SFProjectRole.IsParatextRole(projectRole))
1329+
{
1330+
int index = projectDoc.Data.ParatextUsers.FindIndex(u => u.Username == userDoc.Data.Name);
1331+
if (index > -1)
1332+
await projectDoc.SubmitJson0OpAsync(op =>
1333+
{
1334+
op.Set(p => p.ParatextUsers[index].SFUserId, userDoc.Id);
1335+
op.Set(p => p.ParatextUsers[index].Role, projectRole);
1336+
});
1337+
else
1338+
{
1339+
await projectDoc.SubmitJson0OpAsync(op =>
1340+
op.Add(
1341+
p => p.ParatextUsers,
1342+
new ParatextUserProfile
1343+
{
1344+
SFUserId = userDoc.Id,
1345+
Username = userDoc.Data.Name,
1346+
Role = projectRole,
1347+
OpaqueUserId = _guidService.NewObjectId(),
1348+
}
1349+
)
1350+
);
1351+
}
1352+
}
13251353

13261354
// Update book and chapter permissions on SF project/resource, but only if user
13271355
// has a role on the PT project or permissions to the DBL resource. These permissions are needed
@@ -1372,7 +1400,13 @@ projectDoc.Data.UserRoles[curUserId] is not (SFProjectRole.Administrator or SFPr
13721400
&& ptRole is SFProjectRole.Administrator or SFProjectRole.Translator;
13731401
if (projectDoc.Data.UserRoles[curUserId] != ptRole)
13741402
{
1375-
await projectDoc.SubmitJson0OpAsync(op => op.Set(p => p.UserRoles[curUserId], ptRole));
1403+
await projectDoc.SubmitJson0OpAsync(op =>
1404+
{
1405+
op.Set(p => p.UserRoles[curUserId], ptRole);
1406+
int index = projectDoc.Data.ParatextUsers.FindIndex(u => u.SFUserId == curUserId);
1407+
if (index > -1)
1408+
op.Set(p => p.ParatextUsers[index].Role, ptRole);
1409+
});
13761410
}
13771411

13781412
// If the user can now write text, we should sync to see if there are new permissions for them.

test/SIL.XForge.Scripture.Tests/Services/SFProjectServiceTests.cs

Lines changed: 101 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,6 +1712,34 @@ public void UninviteUser_SystemAdmin_NoSpecialAccess()
17121712
);
17131713
}
17141714

1715+
[Test]
1716+
public async Task AddUserAsync_AddsRoleAndIdToParatextUsers()
1717+
{
1718+
var env = new TestEnvironment();
1719+
SFProject project = env.GetProject(Project02);
1720+
1721+
Assert.That(project.UserRoles.ContainsKey(User01), Is.False, "setup");
1722+
Assert.That(project.ParatextUsers.Exists(u => u.Username == "User 01"), Is.True, "setup");
1723+
Assert.That(project.ParatextUsers.Exists(u => u.SFUserId == User01), Is.False, "setup");
1724+
env.ParatextService.TryGetProjectRoleAsync(
1725+
Arg.Any<UserSecret>(),
1726+
Arg.Any<string>(),
1727+
Arg.Any<CancellationToken>()
1728+
)
1729+
.Returns(Task.FromResult(Attempt.Success(SFProjectRole.Administrator)));
1730+
1731+
await env.Service.AddUserAsync(User01, Project02, null);
1732+
project = env.GetProject(Project02);
1733+
1734+
Assert.That(project.UserRoles.ContainsKey(User01), Is.True, "User should have been added to project");
1735+
Assert.That(
1736+
project.ParatextUsers.Exists(u =>
1737+
u.SFUserId == User01 && u.Username == "User 01" && u.Role == SFProjectRole.Administrator
1738+
),
1739+
Is.True
1740+
);
1741+
}
1742+
17151743
[Test]
17161744
public async Task AddUserAsync_ShareKeyExists_AddsUserAndRemovesKey()
17171745
{
@@ -1732,6 +1760,7 @@ public async Task AddUserAsync_ShareKeyExists_AddsUserAndRemovesKey()
17321760
project = env.GetProject(Project03);
17331761

17341762
Assert.That(project.UserRoles.ContainsKey(User03), Is.True, "User should have been added to project");
1763+
Assert.That(project.ParatextUsers.Exists(u => u.SFUserId == User03 && u.Username == "User 03"), Is.True);
17351764
}
17361765

17371766
[Test]
@@ -1743,6 +1772,7 @@ public void AddUserAsync_SourceProjectUnavailable_SkipProject()
17431772
Assert.DoesNotThrowAsync(() => env.Service.AddUserAsync(User03, Project04, SFProjectRole.Translator));
17441773
var project = env.GetProject(Project04);
17451774
Assert.That(project.UserRoles[User03], Is.EqualTo(SFProjectRole.Translator));
1775+
Assert.That(project.ParatextUsers.Exists(u => u.SFUserId == User03 && u.Username == "User 03"), Is.True);
17461776
}
17471777

17481778
[Test]
@@ -1909,8 +1939,9 @@ public async Task AddUserAsync_HasSourceProjectRole_AddedToSourceProject()
19091939
await env.Service.AddUserAsync(User03, Project03, SFProjectRole.Translator);
19101940
project03 = env.GetProject(Project03);
19111941
source = env.GetProject(SourceOnly);
1912-
Assert.That(project03.UserRoles.ContainsKey(User03));
1913-
Assert.That(source.UserRoles.ContainsKey(User03));
1942+
Assert.That(project03.UserRoles.ContainsKey(User03), Is.True);
1943+
Assert.That(project03.ParatextUsers.Exists(u => u.SFUserId == User03 && u.Username == "User 03"), Is.True);
1944+
Assert.That(source.UserRoles.ContainsKey(User03), Is.True);
19141945
user = env.GetUser(User03);
19151946
Assert.That(user.Sites[SiteId].Projects, Is.EquivalentTo(new[] { Project01, Project03, SourceOnly }));
19161947
}
@@ -4622,13 +4653,20 @@ public async Task SyncUserRoleAsync_DowngradesRole()
46224653
var env = new TestEnvironment();
46234654
var user = env.GetProject(Project01).UserRoles[User01];
46244655
Assert.AreEqual(SFProjectRole.Administrator, user);
4656+
SFProject project = env.GetProject(Project01);
4657+
Assert.IsFalse(
4658+
project.ParatextUsers.Exists(u => u.Username == "User 01" && u.Role == SFProjectRole.Translator),
4659+
"setup"
4660+
);
46254661

46264662
// SUT
46274663
env.ParatextService.TryGetProjectRoleAsync(Arg.Any<UserSecret>(), Arg.Any<string>(), CancellationToken.None)
46284664
.Returns(Task.FromResult(Attempt.Success(SFProjectRole.Translator)));
46294665
await env.Service.SyncUserRoleAsync(User01, Project01);
4630-
user = env.GetProject(Project01).UserRoles[User01];
4666+
project = env.GetProject(Project01);
4667+
user = project.UserRoles[User01];
46314668
Assert.AreEqual(SFProjectRole.Translator, user);
4669+
Assert.IsTrue(project.ParatextUsers.Exists(u => u.Username == "User 01" && u.Role == SFProjectRole.Translator));
46324670
await env.SyncService.DidNotReceive().SyncAsync(Arg.Any<SyncConfig>());
46334671
}
46344672

@@ -4651,13 +4689,20 @@ public async Task SyncUserRoleAsync_UpgradesRole()
46514689
var env = new TestEnvironment();
46524690
var user = env.GetProject(Project01).UserRoles[User03];
46534691
Assert.AreEqual(SFProjectRole.Consultant, user);
4692+
SFProject project = env.GetProject(Project01);
4693+
Assert.IsFalse(
4694+
project.ParatextUsers.Exists(u => u.Username == "User 03" && u.Role == SFProjectRole.Translator),
4695+
"setup"
4696+
);
46544697

46554698
// SUT
46564699
env.ParatextService.TryGetProjectRoleAsync(Arg.Any<UserSecret>(), Arg.Any<string>(), CancellationToken.None)
46574700
.Returns(Task.FromResult(Attempt.Success(SFProjectRole.Translator)));
46584701
await env.Service.SyncUserRoleAsync(User03, Project01);
4659-
user = env.GetProject(Project01).UserRoles[User03];
4702+
project = env.GetProject(Project01);
4703+
user = project.UserRoles[User03];
46604704
Assert.AreEqual(SFProjectRole.Translator, user);
4705+
Assert.IsTrue(project.ParatextUsers.Exists(u => u.Username == "User 03" && u.Role == SFProjectRole.Translator));
46614706
await env.SyncService.Received().SyncAsync(Arg.Any<SyncConfig>());
46624707
}
46634708

@@ -4678,6 +4723,7 @@ public TestEnvironment()
46784723
Id = User01,
46794724
Email = "[email protected]",
46804725
ParatextId = "pt-user01",
4726+
Name = "User 01",
46814727
Roles = [SystemRole.User],
46824728
Sites = new Dictionary<string, Site>
46834729
{
@@ -4692,6 +4738,7 @@ public TestEnvironment()
46924738
Id = User02,
46934739
Email = "[email protected]",
46944740
ParatextId = "pt-user02",
4741+
Name = "User 02",
46954742
Roles = [SystemRole.User],
46964743
Sites = new Dictionary<string, Site>
46974744
{
@@ -4706,6 +4753,7 @@ public TestEnvironment()
47064753
Id = User03,
47074754
Email = "[email protected]",
47084755
ParatextId = "pt-user03",
4756+
Name = "User 03",
47094757
Roles = [SystemRole.User],
47104758
Sites = new Dictionary<string, Site>
47114759
{
@@ -4720,6 +4768,7 @@ public TestEnvironment()
47204768
Id = User04,
47214769
Email = "[email protected]",
47224770
Roles = [SystemRole.SystemAdmin],
4771+
Name = "User 04",
47234772
Sites = new Dictionary<string, Site> { { SiteId, new Site() } },
47244773
},
47254774
new User
@@ -4734,6 +4783,7 @@ public TestEnvironment()
47344783
Id = User05,
47354784
Email = "[email protected]",
47364785
ParatextId = "pt-user05",
4786+
Name = "User 05",
47374787
Roles = [SystemRole.User],
47384788
Sites = new Dictionary<string, Site>
47394789
{
@@ -4748,6 +4798,7 @@ public TestEnvironment()
47484798
Id = User06,
47494799
Email = "[email protected]",
47504800
Roles = [SystemRole.User],
4801+
Name = "User 06",
47514802
Sites = new Dictionary<string, Site>
47524803
{
47534804
{
@@ -4761,6 +4812,7 @@ public TestEnvironment()
47614812
Id = User07,
47624813
Email = "[email protected]",
47634814
Roles = [SystemRole.SystemAdmin],
4815+
Name = "User 07",
47644816
Sites = new Dictionary<string, Site>
47654817
{
47664818
{
@@ -4869,6 +4921,30 @@ public TestEnvironment()
48694921
},
48704922
},
48714923
WritingSystem = new WritingSystem { Tag = "qaa" },
4924+
ParatextUsers =
4925+
{
4926+
new ParatextUserProfile
4927+
{
4928+
SFUserId = User01,
4929+
Username = "User 01",
4930+
Role = SFProjectRole.Administrator,
4931+
OpaqueUserId = "syncuser01",
4932+
},
4933+
new ParatextUserProfile
4934+
{
4935+
SFUserId = User03,
4936+
Username = "User 03",
4937+
OpaqueUserId = "syncuser03",
4938+
Role = SFProjectRole.Consultant,
4939+
},
4940+
new ParatextUserProfile
4941+
{
4942+
SFUserId = User05,
4943+
Username = "User 05",
4944+
OpaqueUserId = "syncuser05",
4945+
Role = SFProjectRole.Translator,
4946+
},
4947+
},
48724948
},
48734949
new SFProject
48744950
{
@@ -4889,6 +4965,22 @@ public TestEnvironment()
48894965
{ User02, SFProjectRole.Administrator },
48904966
{ User04, SFProjectRole.CommunityChecker },
48914967
},
4968+
ParatextUsers =
4969+
{
4970+
new ParatextUserProfile
4971+
{
4972+
SFUserId = User02,
4973+
Username = "User 02",
4974+
Role = SFProjectRole.Administrator,
4975+
OpaqueUserId = "syncuser02",
4976+
},
4977+
new ParatextUserProfile
4978+
{
4979+
SFUserId = string.Empty,
4980+
Username = "User 01",
4981+
OpaqueUserId = "syncuser01",
4982+
},
4983+
},
48924984
},
48934985
new SFProject
48944986
{
@@ -5440,6 +5532,8 @@ public TestEnvironment()
54405532
TransceleratorService = Substitute.For<ITransceleratorService>();
54415533
EventMetricService = Substitute.For<IEventMetricService>();
54425534
BackgroundJobClient = Substitute.For<IBackgroundJobClient>();
5535+
GuidService = Substitute.For<IGuidService>();
5536+
GuidService.NewObjectId().Returns($"syncuser");
54435537

54445538
// These project rights correspond to the permissions in the projects above
54455539
ProjectRights = Substitute.For<ISFProjectRights>();
@@ -5566,7 +5660,8 @@ public TestEnvironment()
55665660
TransceleratorService,
55675661
BackgroundJobClient,
55685662
EventMetricService,
5569-
ProjectRights
5663+
ProjectRights,
5664+
GuidService
55705665
);
55715666
}
55725667

@@ -5586,6 +5681,7 @@ public TestEnvironment()
55865681
public ITransceleratorService TransceleratorService { get; set; }
55875682
public IBackgroundJobClient BackgroundJobClient { get; }
55885683
public ISFProjectRights ProjectRights { get; }
5684+
public IGuidService GuidService { get; }
55895685

55905686
public SFProject GetProject(string id) => RealtimeService.GetRepository<SFProject>().Get(id);
55915687

0 commit comments

Comments
 (0)