I have just finished coding a permission system for my game server but one method in the class is seeming to be very complicated, and maybe some people on this site can help me improve the method?
Let me walk you through the permission system, which will give you a better understanding of the question, and how you can review my code.
The screenshot clearly explains a lot more just by looking at it.
PermissionManager.cs:
namespace MyApp.Permissions
{
using System;
using System.Collections.Generic;
using System.Linq;
using Players.Players;
using Utilities;
internal sealed class PermissionManager : IManager
{
private readonly Dictionary<int, Permission> _permissions;
public PermissionManager()
{
_permissions = new Dictionary<int, Permission>();
}
public void Initialize()
{
using (var databaseConnection = Hariak.HariakServer.Database.NewDatabaseConnection)
{
databaseConnection.SetQuery("SELECT * FROM `game_permissions`");
using (var reader = databaseConnection.ExecuteReader())
{
while (reader.Read())
{
_permissions.Add(reader.GetInt32("id"), new Permission(
reader.GetString("permission_name"),
reader.GetString("ranks_allowed"),
reader.GetString("usernames_allowed"),
reader.GetInt32("minimum_rank"),
reader.GetInt32("maximum_rank"),
reader.GetString("user_ids_allowed"),
reader.GetString("custom_column_set")));
}
}
}
}
public bool CheckPermission(PlayerConnection playerConnection, string permissionName)
{
try
{
foreach (var permission in _permissions.Values.Where(permission => permission.PermissionName == permissionName))
{
if (permission.RanksAllowedString.Contains(","))
{
var ranksAllowed = permission.RanksAllowedString.Contains(",") ? permission.RanksAllowedString.Split(',').Select(int.Parse).ToList() : new List<int>();
if (ranksAllowed.Any(rankAllowed => playerConnection.SelectColumnInt("rank") == rankAllowed))
{
return true;
}
}
else if (HelperUtilities.IsInteger(permission.RanksAllowedString) && playerConnection.SelectColumnInt("rank") == int.Parse(permission.RanksAllowedString))
{
return true;
}
if (permission.UsernamesAllowedString.Contains(","))
{
var usernamesAllowed = permission.UsernamesAllowedString.Contains(",") ? permission.UsernamesAllowedString.Split(',').ToList() : new List<string>();
if (usernamesAllowed.Any(usernameAllowed => usernameAllowed.StartsWith("\"") && usernameAllowed.EndsWith("\"") && usernameAllowed.Trim('"') == playerConnection.SelectColumn("username")))
{
return true;
}
}
else if (permission.UsernamesAllowedString.StartsWith("\"") && permission.UsernamesAllowedString.EndsWith("\"") && permission.UsernamesAllowedString.Trim('"') == playerConnection.SelectColumn("username"))
{
return true;
}
if (permission.MinimumRank >= 1 && playerConnection.SelectColumnInt("rank") >= permission.MinimumRank && (permission.MaximumRank == 0 || playerConnection.SelectColumnInt("rank") < permission.MaximumRank + 1))
{
return true;
}
if (permission.MinimumRank < 1 && permission.MaximumRank > 1 && playerConnection.SelectColumnInt("rank") < permission.MaximumRank + 1)
{
return true;
}
if (permission.UserIdsAllowedString.Contains(","))
{
var idsAllowed = permission.UserIdsAllowedString.Contains(",") ? permission.UserIdsAllowedString.Split(',').Select(int.Parse).ToList() : new List<int>();
if (idsAllowed.Any(idAllowed => playerConnection.SelectColumnInt("id") == idAllowed))
{
return true;
}
}
else if (HelperUtilities.IsInteger(permission.UserIdsAllowedString) && playerConnection.SelectColumnInt("id") == int.Parse(permission.UserIdsAllowedString))
{
return true;
}
if (!permission.CustomColumnSet.Contains("}{"))
{
continue;
}
foreach (var customColumnString in permission.CustomColumnSet.Split('}'))
{
if (!customColumnString.StartsWith("{"))
{
continue;
}
var cleanString = customColumnString.Substring(1);
var requestKey = cleanString.Split('=')[0];
requestKey = requestKey.Substring(1, requestKey.Length - 2);
var requestValue = cleanString.Split('=')[1];
requestValue = requestValue.Substring(1, requestValue.Length - 2);
if (requestKey.Trim('\'').Contains("."))
{
var tableAsking = requestKey.Split('.')[0];
var columnAsking = requestKey.Split('.')[1];
try
{
using (var databaseConnection = Hariak.HariakServer.Database.NewDatabaseConnection)
{
databaseConnection.SetQuery("SELECT `" + columnAsking + "` FROM `" + tableAsking + "` WHERE `id` = @userId");
databaseConnection.AppendParameter("userId", playerConnection.SelectColumnInt("id"));
if (databaseConnection.ExecuteSingleString() == requestValue)
{
return true;
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
else if (playerConnection.SelectColumn(requestKey) == requestValue)
{
return true;
}
}
}
return false;
}
catch (Exception)
{
return false;
}
}
}
}
Permission.cs:
namespace MyApp.Permissions
{
internal sealed class Permission
{
public Permission(string permissionName, string ranksAllowedString, string usernamesAllowString, int minimumRank, int maximumRank, string userIdsAllowedString, string customColumnSet)
{
PermissionName = permissionName;
RanksAllowedString = ranksAllowedString;
UsernamesAllowedString = usernamesAllowString;
MinimumRank = minimumRank;
MaximumRank = maximumRank;
UserIdsAllowedString = userIdsAllowedString;
CustomColumnSet = customColumnSet;
}
internal string PermissionName { get; }
internal string RanksAllowedString { get; }
internal string UsernamesAllowedString { get; }
internal int MinimumRank { get; }
internal int MaximumRank { get; }
internal string UserIdsAllowedString { get; }
internal string CustomColumnSet { get; }
}
}
In my opinion, most of the code is clean. The main thing I am looking for help with is the CheckPermission method. It's very large (compared to other methods in my Solution) and I feel like it could be improved a lot.
What does SelectColumnInt do? Simply selected a column from the 'users' table with the player's id.
I haven't checked for just one rule in the custom_column_set column because I am under the impression the foreach will handle it even if it doesn't contain a, (multiple {}'s? If I am wrong, please correct me).
