Alexander Shabarshov 2a7a24c9e7 Initial contribution
2025-11-03 14:43:26 +00:00

257 lines
9.4 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* dbMango
*
* Copyright 2025 Deutsche Bank AG
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using MongoDB.Bson;
using Newtonsoft.Json;
namespace Rms.Risk.Mango.Pivot.Core.Models;
public class RolesInfoModel
{
public List<RoleInfoModel> Roles { get; set; } = [];
public static RolesInfoModel FromBson(BsonDocument bsonDocument)
{
var model = new RolesInfoModel();
var rolesArray = bsonDocument["roles"].AsBsonArray;
foreach (var roleElement in rolesArray)
{
var roleDoc = roleElement.AsBsonDocument;
var role = new RoleInfoModel
{
RoleName = roleDoc.Contains("role") ? roleDoc["role"].AsString : string.Empty,
Db = roleDoc.Contains("db") ? roleDoc["db"].AsString : string.Empty,
IsBuiltin = roleDoc.Contains("isBuiltin") && roleDoc["isBuiltin"].AsBoolean,
Roles = roleDoc.Contains("roles") && roleDoc["roles"].IsBsonArray
? roleDoc["roles"].AsBsonArray.Select(r =>
{
var roleInDbDoc = r.AsBsonDocument;
return new RoleInDbModel
{
Role = roleInDbDoc.Contains("role") ? roleInDbDoc["role"].AsString : string.Empty,
Db = roleInDbDoc.Contains("db") ? roleInDbDoc["db"].AsString : string.Empty
};
}).ToList()
: [],
InheritedRoles = roleDoc.Contains("inheritedRoles") && roleDoc["inheritedRoles"].IsBsonArray
? roleDoc["inheritedRoles"].AsBsonArray.Select(r => r.ToString()!).ToList()
: [],
Privileges = roleDoc.Contains("privileges") && roleDoc["privileges"].IsBsonArray
? ParsePrivileges(roleDoc["privileges"].AsBsonArray)
: [],
InheritedPrivileges = roleDoc.Contains("inheritedPrivileges") && roleDoc["inheritedPrivileges"].IsBsonArray
? ParsePrivileges(roleDoc["inheritedPrivileges"].AsBsonArray)
: []
};
model.Roles.Add(role);
}
return model;
}
private static List<PrivilegeModel> ParsePrivileges(BsonArray privilegesArray)
{
var privileges = new List<PrivilegeModel>();
foreach (var privilegeElement in privilegesArray)
{
var privilegeDoc = privilegeElement.AsBsonDocument;
var resourceDoc = privilegeDoc["resource"].AsBsonDocument;
var privilege = new PrivilegeModel
{
Resource = new()
{
AnyResource= resourceDoc.Contains("anyResource") && resourceDoc["anyResource"].AsBoolean,
Db = resourceDoc.Contains("db") ? resourceDoc["db"].AsString : string.Empty,
Collection = resourceDoc.Contains("collection") ? resourceDoc["collection"].AsString : string.Empty,
Cluster = resourceDoc.Contains("cluster") && resourceDoc["cluster"].AsBoolean,
Buckets = resourceDoc.Contains("system_buckets") ? resourceDoc["system_buckets"].AsString : null,
},
Actions = privilegeDoc.Contains("actions") && privilegeDoc["actions"].IsBsonArray
? privilegeDoc["actions"].AsBsonArray.Select(a => a.AsString).ToList()
: []
};
privileges.Add(privilege);
}
return privileges;
}
}
public class RoleInfoModel
{
public override string ToString() => $"{RoleName} ({Db})";
public string RoleName { get; set; } = string.Empty;
public string Db { get; set; } = string.Empty;
public bool IsBuiltin { get; set; }
public List<RoleInDbModel> Roles { get; set; } = [];
public List<PrivilegeModel> Privileges { get; set; } = [];
[JsonIgnore]
public List<string> InheritedRoles { get; set; } = [];
[JsonIgnore]
public List<PrivilegeModel> InheritedPrivileges { get; set; } = [];
public void CopyFrom(RoleInfoModel other)
{
RoleName = other.RoleName;
Db = other.Db;
IsBuiltin = other.IsBuiltin;
Roles = new(other.Roles);
InheritedRoles = new(other.InheritedRoles);
Privileges = other.Privileges.Select(p => new PrivilegeModel
{
Resource = new()
{
AnyResource = p.Resource.AnyResource,
Db = p.Resource.Db,
Collection = p.Resource.Collection,
Cluster = p.Resource.Cluster,
Buckets = p.Resource.Buckets
},
Actions = [..p.Actions]
}).ToList();
InheritedPrivileges = other.InheritedPrivileges.Select(p => new PrivilegeModel
{
Resource = new()
{
AnyResource = p.Resource.AnyResource,
Db = p.Resource.Db,
Collection = p.Resource.Collection,
Cluster = p.Resource.Cluster,
Buckets = p.Resource.Buckets
},
Actions = [..p.Actions]
}).ToList();
}
public RoleInfoModel Clone()
{
var clone = new RoleInfoModel();
clone.CopyFrom(this);
return clone;
}
public BsonDocument CreateUpdateRoleCommand(bool add)
{
var command = new BsonDocument
{
{ add ? "createRole" : "updateRole", RoleName },
{ "privileges", new BsonArray(
Privileges.Select(p => new BsonDocument
{
{ "resource", ToBsonDocument(p.Resource) },
{ "actions", new BsonArray(p.Actions) }
})
) },
{ "roles", new BsonArray(
Roles.Select(x =>
string.IsNullOrWhiteSpace(x.Db)
? BsonValue.Create(x.Role)
: new BsonDocument
{
{ "role", x.Role },
{ "db", x.Db }
}
)
)
},
// { "authenticationRestrictions", new BsonArray(
// role.AuthenticationRestrictions.Select(ar => new BsonDocument
// {
// { "clientSource", new BsonArray(ar.ClientSource) },
// { "serverAddress", new BsonArray(ar.ServerAddress) }
// })
// ) },
{ "writeConcern", new BsonDocument { { "w", "majority" } } }
};
return command;
}
private static BsonDocument ToBsonDocument(ResourceModel resource)
{
var resourceDoc = new BsonDocument();
if (resource.Cluster)
{
resourceDoc.Add("cluster", true);
}
else if (resource.AnyResource)
{
resourceDoc.Add("anyResource", true);
}
else if ( string.IsNullOrWhiteSpace(resource.Buckets) )
{
resourceDoc.Add("db", resource.Db);
resourceDoc.Add("collection", resource.Collection);
}
else
{
resourceDoc.Add("system_buckets", resource.Buckets);
}
return resourceDoc;
}
}
public class RoleInDbModel
{
public string Db { get; set; } = string.Empty;
public string Role { get; set; } = string.Empty;
public override string ToString() => $"{Role}, {Db}";
public override bool Equals(object? obj)
{
if (obj is not RoleInDbModel other)
return false;
return Db == other.Db && Role == other.Role;
}
public override int GetHashCode()
{
return HashCode.Combine(Db, Role);
}
}
public class PrivilegeModel
{
public override string ToString() => $"{Resource} => {string.Join(", ", Actions)}";
public ResourceModel Resource { get; set; } = new();
public List<string> Actions { get; set; } = [];
}
public class ResourceModel
{
public override string ToString() => $"Db={Db}, Collection={Collection}, Any={AnyResource}, Cluster={Cluster} {Buckets}";
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public bool AnyResource { get; set; }
public string Db { get; set; } = string.Empty;
public string Collection { get; set; } = string.Empty;
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public bool Cluster { get; set;}
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public string? Buckets { get; set; }
}