This commit is contained in:
Sina Blattmann 2023-03-31 08:55:04 +02:00
commit 156eee6c9c
8 changed files with 113 additions and 59 deletions

View File

@ -27,7 +27,7 @@ public class Controller : ControllerBase
return Unauthorized(); return Unauthorized();
} }
var session = new Session(user); var session = new Session(user.HidePassword().HideParentIfUserHasNoAccessToParent(user));
//TODO The Frontend should check for the MustResetPassword Flag //TODO The Frontend should check for the MustResetPassword Flag
@ -60,8 +60,7 @@ public class Controller : ControllerBase
if (user is null || !session.HasAccessTo(user)) if (user is null || !session.HasAccessTo(user))
return Unauthorized(); return Unauthorized();
user.Password = ""; return user.HidePassword().HideParentIfUserHasNoAccessToParent(session);
return user;
} }
@ -77,7 +76,7 @@ public class Controller : ControllerBase
if (installation is null || !user.HasAccessTo(installation)) if (installation is null || !user.HasAccessTo(installation))
return Unauthorized(); return Unauthorized();
return installation; return installation.FillOrderNumbers().HideParentIfUserHasNoAccessToParent(user);
} }
[HttpGet(nameof(GetUsersWithDirectAccessToInstallation))] [HttpGet(nameof(GetUsersWithDirectAccessToInstallation))]
@ -95,6 +94,7 @@ public class Controller : ControllerBase
return installation return installation
.UsersWithDirectAccess() .UsersWithDirectAccess()
.Where(u => u.IsDescendantOf(user)) .Where(u => u.IsDescendantOf(user))
.Select(u => u.HidePassword())
.ToList(); .ToList();
} }
@ -133,6 +133,7 @@ public class Controller : ControllerBase
return folder return folder
.UsersWithDirectAccess() .UsersWithDirectAccess()
.Where(u => u.IsDescendantOf(user)) .Where(u => u.IsDescendantOf(user))
.Select(u => u.HidePassword())
.ToList(); .ToList();
} }
@ -167,8 +168,8 @@ public class Controller : ControllerBase
if (folder is null || !user.HasAccessTo(folder)) if (folder is null || !user.HasAccessTo(folder))
return Unauthorized(); return Unauthorized();
return folder; return folder.HideParentIfUserHasNoAccessToParent(user);
} }
[HttpGet(nameof(GetAllDirectChildUsers))] [HttpGet(nameof(GetAllDirectChildUsers))]
@ -178,7 +179,7 @@ public class Controller : ControllerBase
if (user == null) if (user == null)
return Unauthorized(); return Unauthorized();
return user.ChildUsers().ToList(); return user.ChildUsers().Select(u => u.HidePassword()).ToList();
} }
[HttpGet(nameof(GetAllChildUsers))] [HttpGet(nameof(GetAllChildUsers))]
@ -188,7 +189,7 @@ public class Controller : ControllerBase
if (user == null) if (user == null)
return Unauthorized(); return Unauthorized();
return user.DescendantUsers().ToList(); return user.DescendantUsers().Select(u => u.HidePassword()).ToList();
} }
@ -199,10 +200,8 @@ public class Controller : ControllerBase
if (user is null) if (user is null)
return Unauthorized(); return Unauthorized();
user.AccessibleInstallations().ForEach(i => i.FillOrderNumbers()); return user.AccessibleInstallations().Select(i => i.FillOrderNumbers().HideParentIfUserHasNoAccessToParent(user)).ToList();
return user.AccessibleInstallations().ToList();
} }
@ -215,7 +214,7 @@ public class Controller : ControllerBase
if (user is null) if (user is null)
return Unauthorized(); return Unauthorized();
return new(user.AccessibleFolders()); return new(user.AccessibleFolders().HideParentIfUserHasNoAccessToParent(user));
} }
@ -228,9 +227,11 @@ public class Controller : ControllerBase
return Unauthorized(); return Unauthorized();
var foldersAndInstallations = user var foldersAndInstallations = user
.AccessibleFoldersAndInstallations() .AccessibleFoldersAndInstallations()
.OfType<Object>(); // Important! JSON serializer must see Objects otherwise .Do(o => o.FillOrderNumbers())
// it will just serialize the members of TreeNode %&@#!!! .Select(o => o.HideParentIfUserHasNoAccessToParent(user))
.OfType<Object>(); // Important! JSON serializer must see Objects otherwise
// it will just serialize the members of TreeNode %&@#!!!
return new (foldersAndInstallations); return new (foldersAndInstallations);
} }
@ -240,17 +241,19 @@ public class Controller : ControllerBase
public ActionResult<User> CreateUser(User newUser, Token authToken) public ActionResult<User> CreateUser(User newUser, Token authToken)
{ {
return Db.GetSession(authToken).Create(newUser) return Db.GetSession(authToken).Create(newUser)
? newUser ? newUser.HidePassword()
: Unauthorized() ; : Unauthorized() ;
} }
[HttpPost(nameof(CreateInstallation))] [HttpPost(nameof(CreateInstallation))]
public async Task<ActionResult<Installation>> CreateInstallation(Installation installation, Token authToken) public async Task<ActionResult<Installation>> CreateInstallation(Installation installation, Token authToken)
{ {
if (!await Db.GetSession(authToken).Create(installation)) var session = Db.GetSession(authToken);
if (! await session.Create(installation))
return Unauthorized(); return Unauthorized();
return installation; return installation.FillOrderNumbers().HideParentIfUserHasNoAccessToParent(session!.User);
} }
[HttpPost(nameof(CreateFolder))] [HttpPost(nameof(CreateFolder))]
@ -261,7 +264,7 @@ public class Controller : ControllerBase
if (!session.Create(folder)) if (!session.Create(folder))
return Unauthorized(); return Unauthorized();
return folder; return folder.HideParentIfUserHasNoAccessToParent(session!.User);
} }
[HttpPost(nameof(GrantUserAccessToFolder))] [HttpPost(nameof(GrantUserAccessToFolder))]
@ -332,7 +335,7 @@ public class Controller : ControllerBase
if (!session.Update(updatedUser)) if (!session.Update(updatedUser))
return Unauthorized(); return Unauthorized();
return updatedUser; return updatedUser.HidePassword();
} }
@ -356,7 +359,7 @@ public class Controller : ControllerBase
if (!session.Update(installation)) if (!session.Update(installation))
return Unauthorized(); return Unauthorized();
return installation; return installation.FillOrderNumbers().HideParentIfUserHasNoAccessToParent(session!.User);
} }
@ -368,7 +371,7 @@ public class Controller : ControllerBase
if (!session.Update(folder)) if (!session.Update(folder))
return Unauthorized(); return Unauthorized();
return folder; return folder.HideParentIfUserHasNoAccessToParent(session!.User);
} }
[HttpPut(nameof(MoveInstallation))] [HttpPut(nameof(MoveInstallation))]

View File

@ -175,6 +175,7 @@ public static class SessionMethods
&& sessionUser.HasAccessTo(editedUser) && sessionUser.HasAccessTo(editedUser)
&& editedUser && editedUser
.WithParentOf(originalUser) // prevent moving .WithParentOf(originalUser) // prevent moving
.WithNameOf(originalUser)
.WithPasswordOf(originalUser) .WithPasswordOf(originalUser)
.Apply(Db.Update); .Apply(Db.Update);
} }

View File

@ -1,3 +1,5 @@
using InnovEnergy.App.Backend.Database;
namespace InnovEnergy.App.Backend.DataTypes.Methods; namespace InnovEnergy.App.Backend.DataTypes.Methods;
public static class TreeNodeMethods public static class TreeNodeMethods
@ -9,16 +11,38 @@ public static class TreeNodeMethods
return treeNode; return treeNode;
} }
public static T WithNameOf<T>(this T treeNode, T other) where T: TreeNode
{
treeNode.Name = other.Name;
return treeNode;
}
public static T WithParent<T>(this T treeNode, T other) where T: TreeNode public static T WithParent<T>(this T treeNode, T other) where T: TreeNode
{ {
treeNode.ParentId = other.Id; treeNode.ParentId = other.Id;
return treeNode; return treeNode;
} }
public static T HideParent<T>(this T treeNode) where T: TreeNode public static T HideParentIfUserHasNoAccessToParent<T>(this T node, User? accessingUser)
{ {
treeNode.ParentId = 0; if (accessingUser is not null && node is TreeNode treeNode && !accessingUser.HasAccessToParentOf(treeNode))
{
treeNode.ParentId = 0;
}
return node;
}
public static TreeNode FillOrderNumbers(this TreeNode treeNode)
{
if (treeNode is Installation installation)
{
installation.FillOrderNumbers();
}
return treeNode; return treeNode;
} }
} }

View File

@ -35,7 +35,7 @@ public static class UserMethods
{ {
var folders = user.AccessibleFolders() as IEnumerable<TreeNode>; var folders = user.AccessibleFolders() as IEnumerable<TreeNode>;
user.AccessibleInstallations().ForEach(i => i.FillOrderNumbers()); // user.AccessibleInstallations().ForEach(i => i.FillOrderNumbers());
var installations = user.AccessibleInstallations(); var installations = user.AccessibleInstallations();
return folders.Concat(installations); return folders.Concat(installations);
@ -49,7 +49,7 @@ public static class UserMethods
.Select(r => r.InstallationId) .Select(r => r.InstallationId)
.Select(i => Db.GetInstallationById(i)) .Select(i => Db.GetInstallationById(i))
.NotNull() .NotNull()
.Do(i => i.HideParent()); // hide inaccessible parents from calling user .Do(i => i.HideParentIfUserHasNoAccessToParent(user)); // hide inaccessible parents from calling user
} }
public static IEnumerable<Folder> DirectlyAccessibleFolders(this User user) public static IEnumerable<Folder> DirectlyAccessibleFolders(this User user)
@ -60,7 +60,7 @@ public static class UserMethods
.Select(r => r.FolderId) .Select(r => r.FolderId)
.Select(i => Db.GetFolderById(i)) .Select(i => Db.GetFolderById(i))
.NotNull() .NotNull()
.Do(f => f.HideParent()); // hide inaccessible parents from calling user; .Do(f => f.HideParentIfUserHasNoAccessToParent(user)); // hide inaccessible parents from calling user;
} }
public static IEnumerable<User> ChildUsers(this User parent) public static IEnumerable<User> ChildUsers(this User parent)
@ -93,7 +93,7 @@ public static class UserMethods
public static Boolean VerifyPassword(this User user, String password) public static Boolean VerifyPassword(this User user, String password)
{ {
return Db.GetUserWithPasswordByName(user.Name)?.Password == user.SaltAndHashPassword(password); return Db.GetUserByName(user.Name)?.Password == user.SaltAndHashPassword(password);
} }
@ -166,8 +166,32 @@ public static class UserMethods
.Ancestors() .Ancestors()
.Contains(user); .Contains(user);
} }
public static Boolean HasAccessTo(this User user, TreeNode? other)
{
return other?.Type switch
{
"installation" => user.HasAccessTo((Installation)other),
"user" => user.HasAccessTo((User)other),
"folder" => user.HasAccessTo((Folder)other),
_ => false
};
}
public static String Salt(this User user) public static Boolean HasAccessToParentOf(this User user, TreeNode? other)
{
return other?.Type switch
{
"installation" => user.HasAccessTo(Db.GetInstallationById(other.ParentId)),
"user" => user.HasAccessTo(Db.GetUserById(other.ParentId)),
"folder" => user.HasAccessTo(Db.GetFolderById(other.ParentId)),
_ => false
};
}
private static String Salt(this User user)
{ {
// + id => salt unique per user // + id => salt unique per user
// + InnovEnergy => globally unique // + InnovEnergy => globally unique
@ -192,11 +216,10 @@ public static class UserMethods
return deletedUser; return deletedUser;
} }
public static User? HidePassword(this User? user) public static User HidePassword(this User user)
{ {
if(user is not null) user.Password = "";
user.Password = "";
return user; return user;
} }
} }

View File

@ -1,7 +1,6 @@
using InnovEnergy.App.Backend.DataTypes; using InnovEnergy.App.Backend.DataTypes;
using InnovEnergy.App.Backend.DataTypes.Methods; using InnovEnergy.App.Backend.DataTypes.Methods;
using InnovEnergy.App.Backend.Relations; using InnovEnergy.App.Backend.Relations;
using InnovEnergy.Lib.Utils;
namespace InnovEnergy.App.Backend.Database; namespace InnovEnergy.App.Backend.Database;
@ -18,25 +17,16 @@ public static partial class Db
public static Installation? GetInstallationById(Int64? id) public static Installation? GetInstallationById(Int64? id)
{ {
return Installations return Installations
.FirstOrDefault(i => i.Id == id) .FirstOrDefault(i => i.Id == id);
.FillOrderNumbers();
} }
public static User? GetUserById(Int64? id) public static User? GetUserById(Int64? id)
{ {
return Users return Users
.FirstOrDefault(u => u.Id == id) .FirstOrDefault(u => u.Id == id);
.HidePassword();
} }
public static User? GetUserByName(String userName) public static User? GetUserByName(String userName)
{
return Users
.FirstOrDefault(u => u.Name == userName)
.HidePassword();
}
public static User? GetUserWithPasswordByName(String userName)
{ {
return Users return Users
.FirstOrDefault(u => u.Name == userName); .FirstOrDefault(u => u.Name == userName);

View File

@ -1,17 +1,17 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
#pragma warning disable CS8618
namespace InnovEnergy.App.OpenVpnCertificatesServer; namespace InnovEnergy.App.OpenVpnCertificatesServer;
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
[SuppressMessage("ReSharper", "InconsistentNaming")] [SuppressMessage("ReSharper", "InconsistentNaming")]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
internal class AccToken internal class AccToken
{ {
public String token { get; init; } public String bearer { get; init; } = "";
public String bearer { get; init; }
public UInt64 idUser { get; init; } public UInt64 idUser { get; init; }
public String verification_mode { get; init; } public String verification_mode { get; init; } = "password";
public String idAccessToken { get; init; } public Boolean verification_sent { get; init; } = false;
public Boolean verification_sent { get; init; } public Boolean success { get; init; } = false;
public Boolean success { get; init; } public String token { get; init; } = "";
public String idAccessToken { get; init; } = "";
} }

View File

@ -19,4 +19,8 @@
</None> </None>
</ItemGroup> </ItemGroup>
<PropertyGroup>
<PublishTrimmed>false</PublishTrimmed>
</PropertyGroup>
</Project> </Project>

View File

@ -36,10 +36,11 @@ public static class Program
private const String CertsDir = VpnDir + "/certs"; private const String CertsDir = VpnDir + "/certs";
private const String Endpoint = "http://localhost:4000/"; private const String Endpoint = "http://localhost:4000/";
private static AccToken ReadAccessToken() private static AccToken? ReadAccessToken()
{ {
var content = File.ReadAllText("./token.json"); var content = File.ReadAllText("./token.json");
return JsonSerializer.Deserialize<AccToken>(content)!;
return JsonSerializer.Deserialize<AccToken>(content);
} }
@ -146,9 +147,14 @@ public static class Program
//var installationName = await LookupInstallationNameByUniqueId(ccdName); //var installationName = await LookupInstallationNameByUniqueId(ccdName);
var token = ReadAccessToken(); var token = ReadAccessToken();
using var vrm = VrmAccount.Token(token.idUser, token.token);
var installations = await vrm.GetInstallations();
var vrm = VrmAccount.Token(token.idUser, token.token);
var installations = await vrm.GetInstallations();
var installationName = installations var installationName = installations
.Where(i => i.UniqueId == uniqueId) .Where(i => i.UniqueId == uniqueId)
.Select(i => i.Name) .Select(i => i.Name)
@ -163,7 +169,9 @@ public static class Program
{ {
Console.WriteLine($"looking up {ccdName} on VRM"); Console.WriteLine($"looking up {ccdName} on VRM");
var token = ReadAccessToken(); var token = ReadAccessToken();
using var vrm = VrmAccount.Token(token.idUser, token.token); using var vrm = VrmAccount.Token(token.idUser, token.token);
var installations = await vrm.GetInstallations(); var installations = await vrm.GetInstallations();
foreach (var installation in installations) foreach (var installation in installations)
@ -176,6 +184,7 @@ public static class Program
return (ccdName, installation.Name); return (ccdName, installation.Name);
} }
Console.WriteLine($"not found");
return null; return null;
} }