Skip to content

Commit

Permalink
Support project permissions in mock (#455)
Browse files Browse the repository at this point in the history
* Support project permissions in mock

* Update global.json

* Add some tests
  • Loading branch information
jairbubbles authored Jun 1, 2023
1 parent 502fce5 commit 421f97b
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 34 deletions.
56 changes: 54 additions & 2 deletions NGitLab.Mock.Tests/ProjectsMockTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System.Globalization;
using System.IO;
using FluentAssertions;
using NGitLab.Mock.Config;
using NGitLab.Models;
using NUnit.Framework;

namespace NGitLab.Mock.Tests
Expand Down Expand Up @@ -76,10 +78,60 @@ public void Test_empty_repo()
var user = server.Users.AddNew();
var project = user.Namespace.Projects.AddNew();

Assert.IsTrue(project.ToClientProject().EmptyRepo);
Assert.IsTrue(project.ToClientProject(user).EmptyRepo);

project.Repository.Commit(user, "dummy");
Assert.IsFalse(project.ToClientProject().EmptyRepo);
Assert.IsFalse(project.ToClientProject(user).EmptyRepo);
}

[Test]
public void Test_project_permissions_maintainer_with_project_access()
{
using var server = new GitLabConfig()
.WithUser("Test", isDefault: true)
.WithProject("Test", @namespace: "testgroup", addDefaultUserAsMaintainer: true)
.BuildServer();

var client = server.CreateClient();
var project = client.Projects["testgroup/Test"];

project.Should().NotBeNull();
project.Permissions.GroupAccess.Should().BeNull();
project.Permissions.ProjectAccess.AccessLevel.Should().Be(AccessLevel.Maintainer);
}

[Test]
public void Test_project_permissions_with_no_access()
{
using var server = new GitLabConfig()
.WithUser("Test", isDefault: true)
.WithProject("Test", @namespace: "testgroup")
.BuildServer();

var client = server.CreateClient();
var project = client.Projects["testgroup/Test"];

project.Should().NotBeNull();
project.Permissions.GroupAccess.Should().BeNull();
project.Permissions.ProjectAccess.Should().BeNull();
}

[Test]
public void Test_project_permissions_with_group_access()
{
using var server = new GitLabConfig()
.WithUser("Test", isDefault: true)
.WithGroup("testgroup", addDefaultUserAsMaintainer: true)
.WithProject("Test", @namespace: "testgroup")
.BuildServer();

var client = server.CreateClient();
var project = client.Projects["testgroup/Test"];

project.Should().NotBeNull();
project.Permissions.ProjectAccess.Should().BeNull();
project.Permissions.GroupAccess.AccessLevel.Should().Be(AccessLevel.Maintainer);
}

}
}
20 changes: 10 additions & 10 deletions NGitLab.Mock/Clients/GroupClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public Models.Group this[int id]
if (group == null || !group.CanUserViewGroup(Context.User))
throw new GitLabNotFoundException();

return group.ToClientGroup();
return group.ToClientGroup(Context.User);
}
}
}
Expand All @@ -41,7 +41,7 @@ public Models.Group this[string fullPath]
if (group == null || !group.CanUserViewGroup(Context.User))
throw new GitLabNotFoundException();

return group.ToClientGroup();
return group.ToClientGroup(Context.User);
}
}
}
Expand All @@ -52,7 +52,7 @@ public IEnumerable<Models.Group> Accessible
{
using (Context.BeginOperationScope())
{
return Server.AllGroups.Where(group => group.CanUserViewGroup(Context.User)).Select(group => group.ToClientGroup()).ToList();
return Server.AllGroups.Where(group => group.CanUserViewGroup(Context.User)).Select(group => group.ToClientGroup(Context.User)).ToList();
}
}
}
Expand Down Expand Up @@ -92,7 +92,7 @@ public Models.Group Create(GroupCreate group)
Server.Groups.Add(newGroup);
}

return newGroup.ToClientGroup();
return newGroup.ToClientGroup(Context.User);
}
}

Expand All @@ -114,7 +114,7 @@ public void Delete(int id)
if (!group.CanUserDeleteGroup(Context.User))
throw new GitLabForbiddenException();

group.ToClientGroup();
group.ToClientGroup(Context.User);
}
}

Expand Down Expand Up @@ -151,7 +151,7 @@ public async Task DeleteAsync(int id, CancellationToken cancellationToken = defa
throw new NotImplementedException();
}

return groups.Select(g => g.ToClientGroup()).ToArray();
return groups.Select(g => g.ToClientGroup(Context.User)).ToArray();
}
}

Expand Down Expand Up @@ -227,7 +227,7 @@ public void Restore(int id)
}

projects = projects.Where(project => project.CanUserViewProject(Context.User));
return GitLabCollectionResponse.Create(projects.Select(project => project.ToClientProject()).ToArray());
return GitLabCollectionResponse.Create(projects.Select(project => project.ToClientProject(Context.User)).ToArray());
}
}

Expand Down Expand Up @@ -282,7 +282,7 @@ public Models.Group Update(int id, GroupUpdate groupUpdate)
group.Visibility = groupUpdate.Visibility.Value;
}

return group.ToClientGroup();
return group.ToClientGroup(Context.User);
}
}

Expand Down Expand Up @@ -320,7 +320,7 @@ public Models.Group Update(int id, GroupUpdate groupUpdate)
throw new NotImplementedException();
}

var clientGroups = groups.Select(g => g.ToClientGroup());
var clientGroups = groups.Select(g => g.ToClientGroup(Context.User));

return GitLabCollectionResponse.Create(clientGroups.Where(g => g.ParentId == parentGroup.Id));
}
Expand Down Expand Up @@ -353,7 +353,7 @@ public Models.Group Update(int id, GroupUpdate groupUpdate)
throw new NotImplementedException();
}

var clientGroups = groups.Select(g => g.ToClientGroup());
var clientGroups = groups.Select(g => g.ToClientGroup(Context.User));

return GitLabCollectionResponse.Create(clientGroups.Where(g => g.ParentId == parentGroup.Id));
}
Expand Down
22 changes: 11 additions & 11 deletions NGitLab.Mock/Clients/ProjectClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public Models.Project this[int id]
if (project == null || !project.CanUserViewProject(Context.User))
throw new GitLabNotFoundException();

return project.ToClientProject();
return project.ToClientProject(Context.User);
}
}
}
Expand All @@ -39,7 +39,7 @@ public Models.Project this[string fullName]
using (Context.BeginOperationScope())
{
var project = GetProject(fullName, ProjectPermission.View);
return project.ToClientProject();
return project.ToClientProject(Context.User);
}
}
}
Expand All @@ -50,7 +50,7 @@ public IEnumerable<Models.Project> Accessible
{
using (Context.BeginOperationScope())
{
return Server.AllProjects.Where(project => project.IsUserMember(Context.User)).Select(project => project.ToClientProject()).ToList();
return Server.AllProjects.Where(project => project.IsUserMember(Context.User)).Select(project => project.ToClientProject(Context.User)).ToList();
}
}
}
Expand All @@ -61,7 +61,7 @@ public IEnumerable<Models.Project> Owned
{
using (Context.BeginOperationScope())
{
return Server.AllProjects.Where(project => project.IsUserOwner(Context.User)).Select(project => project.ToClientProject()).ToList();
return Server.AllProjects.Where(project => project.IsUserOwner(Context.User)).Select(project => project.ToClientProject(Context.User)).ToList();
}
}
}
Expand All @@ -72,7 +72,7 @@ public IEnumerable<Models.Project> Visible
{
using (Context.BeginOperationScope())
{
return Server.AllProjects.Where(project => project.CanUserViewProject(Context.User)).Select(project => project.ToClientProject()).ToList();
return Server.AllProjects.Where(project => project.CanUserViewProject(Context.User)).Select(project => project.ToClientProject(Context.User)).ToList();
}
}
}
Expand All @@ -94,7 +94,7 @@ public Models.Project Create(ProjectCreate project)
};

parentGroup.Projects.Add(newProject);
return newProject.ToClientProject();
return newProject.ToClientProject(Context.User);
}
}

Expand Down Expand Up @@ -151,7 +151,7 @@ public Models.Project Fork(string id, ForkProject forkProject)
var project = GetProject(id, ProjectPermission.View);
var group = forkProject.Namespace != null ? GetParentGroup(forkProject.Namespace) : Context.User.Namespace;
var newProject = project.Fork(group, Context.User, forkProject.Name);
return newProject.ToClientProject();
return newProject.ToClientProject(Context.User);
}
}

Expand Down Expand Up @@ -220,15 +220,15 @@ public Models.Project Fork(string id, ForkProject forkProject)
throw new NotImplementedException();
}

return projects.Select(project => project.ToClientProject()).ToList();
return projects.Select(project => project.ToClientProject(Context.User)).ToList();
}
}

public Models.Project GetById(int id, SingleProjectQuery query)
{
using (Context.BeginOperationScope())
{
return GetProject(id, ProjectPermission.View).ToClientProject();
return GetProject(id, ProjectPermission.View).ToClientProject(Context.User);
}
}

Expand Down Expand Up @@ -265,7 +265,7 @@ public Models.Project GetById(int id, SingleProjectQuery query)
var matches = Server.AllProjects.Where(project => project.ForkedFrom?.Id == upstream.Id);
matches = matches.Where(project => query.Owned == null || query.Owned == project.IsUserOwner(Context.User));

return matches.Select(project => project.ToClientProject()).ToList();
return matches.Select(project => project.ToClientProject(Context.User)).ToList();
}
}

Expand Down Expand Up @@ -352,7 +352,7 @@ public Models.Project Update(string id, ProjectUpdate projectUpdate)
project.Topics = projectUpdate.Topics.Where(t => !string.IsNullOrEmpty(t)).Distinct(StringComparer.Ordinal).ToArray();
}

return project.ToClientProject();
return project.ToClientProject(Context.User);
}
}

Expand Down
15 changes: 12 additions & 3 deletions NGitLab.Mock/Clients/RunnerClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,16 @@ namespace NGitLab.Mock.Clients
{
internal sealed class RunnerClient : ClientBase, IRunnerClient
{
public IEnumerable<Models.Runner> Accessible => GetOwnedRunners().Select(r => r.ToClientRunner());
public IEnumerable<Models.Runner> Accessible
{
get
{
using (Context.BeginOperationScope())
{
return GetOwnedRunners().Select(r => r.ToClientRunner(Context.User));
}
}
}

public IEnumerable<Models.Runner> All
{
Expand All @@ -25,7 +34,7 @@ public IEnumerable<Models.Runner> All
using (Context.BeginOperationScope())
{
var runners = Server.AllProjects.SelectMany(p => p.RegisteredRunners);
var clientRunners = runners.Select(r => r.ToClientRunner()).ToList();
var clientRunners = runners.Select(r => r.ToClientRunner(Context.User)).ToList();
return clientRunners;
}
}
Expand Down Expand Up @@ -125,7 +134,7 @@ public Models.Runner EnableRunner(int projectId, RunnerId runnerId)
}

project.EnabledRunners.Add(runnerReference);
return runner.ToClientRunner();
return runner.ToClientRunner(Context.User);
}
}

Expand Down
4 changes: 2 additions & 2 deletions NGitLab.Mock/Group.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,15 +235,15 @@ public bool CanUserAddProject(User user)
return accessLevel.HasValue && accessLevel.Value >= AccessLevel.Developer;
}

public Models.Group ToClientGroup()
public Models.Group ToClientGroup(User currentUser)
{
return new Models.Group
{
Id = Id,
Name = Name,
Visibility = Visibility,
ParentId = Parent?.Id,
Projects = Projects.Select(p => p.ToClientProject()).ToArray(),
Projects = Projects.Select(p => p.ToClientProject(currentUser)).ToArray(),
FullName = FullName,
FullPath = PathWithNameSpace,
Path = Path,
Expand Down
21 changes: 19 additions & 2 deletions NGitLab.Mock/Project.cs
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ public Project Fork(Group group, User user, string projectName)
return newProject;
}

public Models.Project ToClientProject()
public Models.Project ToClientProject(User currentUser)
{
var kind = Group.IsUserNamespace ? "user" : "group";

Expand All @@ -412,7 +412,7 @@ public Models.Project ToClientProject()
EmptyRepo = Repository.IsEmpty,
Path = Path,
PathWithNamespace = PathWithNamespace,
ForkedFromProject = ForkedFrom?.ToClientProject(),
ForkedFromProject = ForkedFrom?.ToClientProject(currentUser),
ForkingAccessLevel = ForkingAccessLevel,
ImportStatus = ImportStatus,
HttpUrl = HttpUrl,
Expand All @@ -435,8 +435,25 @@ public Models.Project ToClientProject()
MirrorTriggerBuilds = MirrorTriggerBuilds,
OnlyMirrorProtectedBranch = OnlyMirrorProtectedBranch,
MirrorOverwritesDivergedBranches = MirrorOverwritesDivergedBranches,
Permissions = GetProjectPermissions(currentUser),
};
#pragma warning restore CS0618 // Type or member is obsolete
}

private ProjectPermissions GetProjectPermissions(User user)
{
var projectPermissions = new ProjectPermissions();
if (Permissions.FirstOrDefault(x => x.User == user)?.AccessLevel is { } accessLevel)
{
projectPermissions.ProjectAccess = new ProjectPermission { AccessLevel = accessLevel };
}

if (Group.GetEffectivePermissions().GetAccessLevel(user) is { } groupAccessLevel)
{
projectPermissions.GroupAccess = new ProjectPermission { AccessLevel = groupAccessLevel };
}

return projectPermissions;
}
}
}
4 changes: 2 additions & 2 deletions NGitLab.Mock/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ NGitLab.Mock.Group.RequestAccessEnabled.get -> bool
NGitLab.Mock.Group.RequestAccessEnabled.set -> void
NGitLab.Mock.Group.SharedRunnersLimit.get -> System.TimeSpan
NGitLab.Mock.Group.SharedRunnersLimit.set -> void
NGitLab.Mock.Group.ToClientGroup() -> NGitLab.Models.Group
NGitLab.Mock.Group.ToClientGroup(NGitLab.Mock.User currentUser) -> NGitLab.Models.Group
NGitLab.Mock.Group.Visibility.get -> NGitLab.Models.VisibilityLevel
NGitLab.Mock.Group.Visibility.set -> void
NGitLab.Mock.GroupCollection
Expand Down Expand Up @@ -849,7 +849,7 @@ NGitLab.Mock.Project.Statistics.get -> NGitLab.Models.ProjectStatistics
NGitLab.Mock.Project.Statistics.set -> void
NGitLab.Mock.Project.Tags.get -> string[]
NGitLab.Mock.Project.Tags.set -> void
NGitLab.Mock.Project.ToClientProject() -> NGitLab.Models.Project
NGitLab.Mock.Project.ToClientProject(NGitLab.Mock.User currentUser) -> NGitLab.Models.Project
NGitLab.Mock.Project.Topics.get -> string[]
NGitLab.Mock.Project.Topics.set -> void
NGitLab.Mock.Project.Visibility.get -> NGitLab.Models.VisibilityLevel
Expand Down
4 changes: 2 additions & 2 deletions NGitLab.Mock/Runner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public sealed class Runner : GitLabObject

public bool RunUntagged { get; set; }

internal Models.Runner ToClientRunner()
internal Models.Runner ToClientRunner(User currentUser)
{
return new Models.Runner
{
Expand All @@ -46,7 +46,7 @@ internal Models.Runner ToClientRunner()
Status = Status,
Description = Description,
IsShared = IsShared,
Projects = Parent.Server.AllProjects.Where(p => p.EnabledRunners.Any(r => r.Id == Id)).Select(p => p.ToClientProject()).ToArray(),
Projects = Parent.Server.AllProjects.Where(p => p.EnabledRunners.Any(r => r.Id == Id)).Select(p => p.ToClientProject(currentUser)).ToArray(),
ContactedAt = ContactedAt,
Token = Token,
TagList = TagList,
Expand Down

0 comments on commit 421f97b

Please sign in to comment.