Permission Storage

● When permissions are applied, it will be done recursively. This will help speed up the code for general permission checks.

● This new layout also makes it faster to get the members who have access to a given channel.

● This push also removed a pointless role override.
This commit is contained in:
JacobTech 2023-05-21 21:38:55 -04:00
parent 5e3dca5ce2
commit 612ad59547
4 changed files with 103 additions and 71 deletions

View File

@ -3,6 +3,7 @@ using System.Text.Json;
using System.Text.Json.Serialization.Metadata; using System.Text.Json.Serialization.Metadata;
using LuskiServer.Classes.TableDef; using LuskiServer.Classes.TableDef;
using LuskiServer.Enums; using LuskiServer.Enums;
using Npgsql;
using ServerDatabase; using ServerDatabase;
namespace LuskiServer.Classes; namespace LuskiServer.Classes;
@ -65,68 +66,112 @@ public static class Luski
public static AppConfig Config = null!; public static AppConfig Config = null!;
public static long[] GetChannelBroadcastMembers(long Channel)
{
List<long> Members = new();
long[] ChanUserOverides = Tables.Channels.Read(Channels.UserOverides, Channels.ID.CreateParameter(Channel));
long[] ChanRoleOverides = Tables.Channels.Read(Channels.RoleOverides, Channels.ID.CreateParameter(Channel));
Dictionary<long, long> ChanRoleIDOverides = new();
foreach (long cro in ChanRoleOverides)
{
ChanRoleIDOverides.Add(Tables.ServerRoleOverides.Read(ServerRoleOverides.RoleID, ServerRoleOverides.ID.CreateParameter(cro)), cro);
}
Dictionary<long, long> ChanUserIDOverides = new();
foreach (long cro in ChanUserOverides)
{
ChanUserIDOverides.Add(Tables.UserRoleOverides.Read(UserRoleOverides.UserID, UserRoleOverides.ID.CreateParameter(cro)), cro);
}
ServerPermissions[] pp = new[]
{ ServerPermissions.ViewChannels, ServerPermissions.ViewCategories, ServerPermissions.ReadMessageHistory };
using NpgsqlConnection dbConnection = Luski.Database.CreateConnection();
dbConnection.Open();
using NpgsqlCommand cmd = new();
cmd.Connection = dbConnection;
cmd.CommandText = $"SELECT {Roles.ID.Name} FROM {Tables.Roles.Name};";
NpgsqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
long rol = reader.GetInt64(0);
List<ServerPermissions> GoodPerms = new();
if (ChanRoleIDOverides.ContainsKey(rol))
{
string[] overides = Tables.ServerRoleOverides.Read(ServerRoleOverides.Overides,
ServerRoleOverides.ID.CreateParameter(ChanRoleIDOverides[rol]));
foreach (string o in overides)
{
foreach (ServerPermissions p in pp)
{
if (GoodPerms.Contains(p)) continue;
if (o.StartsWith($"{p.GetNumberString()}:"))
{
if (o.EndsWith("1")) GoodPerms.Add(p);
}
}
}
if (GoodPerms.Count == pp.Length)
{
foreach (long m in Tables.Roles.Read(Roles.MembersList, Roles.ID.CreateParameter(rol)))
{
if (!Members.Contains(m)) Members.Add(m);
}
}
}
else
{
ServerPermissions[] pppp = Tables.Roles.Read(Roles.ServerPermissions, Roles.ID.CreateParameter(rol));
foreach (ServerPermissions p in pp)
{
if (GoodPerms.Contains(p)) continue;
if (pppp.Contains(p)) GoodPerms.Add(p);
}
if (GoodPerms.Count == pp.Length)
{
foreach (long m in Tables.Roles.Read(Roles.MembersList, Roles.ID.CreateParameter(rol)))
{
if (!Members.Contains(m)) Members.Add(m);
}
}
}
}
foreach (long o in ChanUserOverides)
{
List<ServerPermissions> GoodPerms = new();
long u = Tables.UserRoleOverides.Read(UserRoleOverides.UserID, UserRoleOverides.ID.CreateParameter(o));
string[] x = Tables.UserRoleOverides.Read(UserRoleOverides.Overides, UserRoleOverides.ID.CreateParameter(o));
foreach (string oo in x)
{
foreach (ServerPermissions p in pp)
{
if (GoodPerms.Contains(p)) continue;
if (oo.StartsWith($"{p.GetNumberString()}:"))
{
if (oo.EndsWith("1")) GoodPerms.Add(p);
}
}
}
if (GoodPerms.Count == pp.Length)
{
if (!Members.Contains(u)) Members.Add(u);
}
else
{
if (Members.Contains(u)) Members.Remove(u);
}
}
dbConnection.Close();
return Members.ToArray();
}
public static bool HasAccessToChannel(long User, long Channel, params ServerPermissions[] RequiredPerms) public static bool HasAccessToChannel(long User, long Channel, params ServerPermissions[] RequiredPerms)
{ {
long[] UserRoleIDList = Tables.Users.Read(Users.Roles, Users.ID.CreateParameter(User)); long[] UserRoleIDList = Tables.Users.Read(Users.Roles, Users.ID.CreateParameter(User));
List<ServerPermissions> pp = RequiredPerms.ToList(); List<ServerPermissions> pp = RequiredPerms.ToList();
if (!pp.Contains(ServerPermissions.ViewChannels)) pp.Add(ServerPermissions.ViewChannels); if (!pp.Contains(ServerPermissions.ViewChannels)) pp.Add(ServerPermissions.ViewChannels);
if (!pp.Contains(ServerPermissions.ViewCategories)) pp.Add(ServerPermissions.ViewCategories);
List<ServerPermissions> GoodPerms = new(); List<ServerPermissions> GoodPerms = new();
bool more = false;
bool CheckCatPerm(long Cat, List<ServerPermissions> NeededPerms, bool more2 = false)
{
more = more2;
if (more2 && pp.Contains(ServerPermissions.ViewCategories)) pp.Add(ServerPermissions.ViewCategories);
long Parent = Tables.Categories.Read(Categories.Parent, Categories.ID.CreateParameter(Channel));
if (Parent != -1 && !CheckCatPerm(Parent, pp, true)) return false;
long[] CatUserOverides = Tables.Categories.Read(Categories.UserOverides, Categories.ID.CreateParameter(Cat));
foreach (long CatUserOveride in CatUserOverides)
{
if (Tables.UserRoleOverides.Read(UserRoleOverides.UserID, UserRoleOverides.ID.CreateParameter(CatUserOveride)) != User) continue;
string[] overrids = Tables.UserRoleOverides.Read(UserRoleOverides.Overides,
UserRoleOverides.ID.CreateParameter(CatUserOveride));
foreach (string o in overrids)
{
foreach (ServerPermissions p in NeededPerms)
{
if (o.StartsWith($"{p.GetNumberString()}:"))
{
if (o.EndsWith("0")) return false;
else GoodPerms.Add(p);
}
}
}
}
long[] CatRoleOverides = Tables.Categories.Read(Categories.RoleOverides, Categories.ID.CreateParameter(Cat));
foreach (long CatRoleOveride in CatRoleOverides)
{
if (!UserRoleIDList.Contains(Tables.ServerRoleOverides.Read(ServerRoleOverides.RoleID, ServerRoleOverides.ID.CreateParameter(CatRoleOveride)))) continue;
string[] overrids = Tables.UserRoleOverides.Read(ServerRoleOverides.Overides,
ServerRoleOverides.ID.CreateParameter(CatRoleOveride));
foreach (string o in overrids)
{
foreach (ServerPermissions p in NeededPerms)
{
if (o.StartsWith($"{p.GetNumberString()}:"))
{
if (o.EndsWith("0")) return false;
else GoodPerms.Add(p);
}
}
}
}
if (GoodPerms.Count == NeededPerms.Count) return true;
return false;
}
if (!CheckCatPerm(Tables.Channels.Read(Channels.Parent, Channels.ID.CreateParameter(Channel)), pp)) return false;
if (more && !GoodPerms.Contains(ServerPermissions.ViewCategories)) return false;
foreach (ServerPermissions v in GoodPerms)
{
pp.Remove(v);
}
GoodPerms.Clear();
long[] ChanUserOverides = Tables.Channels.Read(Channels.UserOverides, Channels.ID.CreateParameter(Channel)); long[] ChanUserOverides = Tables.Channels.Read(Channels.UserOverides, Channels.ID.CreateParameter(Channel));
foreach (long ChanUserOveride in ChanUserOverides) foreach (long ChanUserOveride in ChanUserOverides)
{ {

View File

@ -10,4 +10,5 @@ public static class Roles
public static TableColumn<string> Color { get; } = new("color"); public static TableColumn<string> Color { get; } = new("color");
public static TableColumn<string> Description { get; } = new("description"); public static TableColumn<string> Description { get; } = new("description");
public static TableColumn<ServerPermissions[]> ServerPermissions { get; } = new("server_perms"); public static TableColumn<ServerPermissions[]> ServerPermissions { get; } = new("server_perms");
public static TableColumn<long[]> MembersList { get; } = new("members_list") {DefaultValue = Array.Empty<long>()};
} }

View File

@ -42,12 +42,11 @@ public class SocketMessageController : ControllerBase
Messages.Files.CreateParameter(data.Files), Messages.Files.CreateParameter(data.Files),
Messages.EncoderType.CreateParameter(data.Encoding), Messages.EncoderType.CreateParameter(data.Encoding),
Messages.EncryptionType.CreateParameter(data.Encryption)); Messages.EncryptionType.CreateParameter(data.Encryption));
//TODO Get all ID for members to send to
WSS.SendData(SendType.ID_Group, new ServerEvent() WSS.SendData(SendType.ID_Group, new ServerEvent()
{ {
Type = DataType.MessageCreate, Type = DataType.MessageCreate,
Data = MessageEvent Data = MessageEvent
}, Array.Empty<long>()); }, Luski.GetChannelBroadcastMembers(data.ChannelID));
Response.StatusCode = 201; Response.StatusCode = 201;
return null!; return null!;
} }

View File

@ -75,19 +75,6 @@ if (!Tables.Roles.TryRead(Roles.ID, out _, Roles.ID.CreateParameter(0)))
); );
} }
if (!Tables.ServerRoleOverides.TryRead(ServerRoleOverides.ID, out _, Categories.ID.CreateParameter(0)))
{
Tables.ServerRoleOverides.Insert(
ServerRoleOverides.ID.CreateParameter(0),
ServerRoleOverides.RoleID.CreateParameter(0),
ServerRoleOverides.Overides.CreateParameter(new string[]
{
$"{ServerPermissions.ViewCategories.GetNumberString()}:1",
$"{ServerPermissions.ViewChannels.GetNumberString()}:1",
})
);
}
if (!Tables.Categories.TryRead(Categories.ID, out _, Categories.ID.CreateParameter(0))) if (!Tables.Categories.TryRead(Categories.ID, out _, Categories.ID.CreateParameter(0)))
{ {
Tables.Categories.Insert( Tables.Categories.Insert(