@page "/Rooms/{RoomId}/Policies2" @using LibMatrix @using ArcaneLibs.Extensions @using LibMatrix.EventTypes.Spec.State @using LibMatrix.EventTypes.Spec.State.Policy @using System.Diagnostics @using LibMatrix.RoomTypes @using System.Collections.Frozen @using System.Reflection @using ArcaneLibs.Attributes @using LibMatrix.EventTypes @using MatrixUtils.Web.Shared.PolicyEditorComponents

Policy list editor - Editing @RoomId


@* *@ Create new policy @if (Loading) {

Loading...

} else if (PolicyEventsByType is not { Count: > 0 }) {

No policies yet

} else { var renderSw = Stopwatch.StartNew(); var renderTotalSw = Stopwatch.StartNew(); @foreach (var (type, value) in PolicyEventsByType) {

@(GetValidPolicyEventsByType(type).Count) active, @(GetInvalidPolicyEventsByType(type).Count) invalid (@value.Count total) @(GetPolicyTypeName(type).ToLower())

} Console.WriteLine($"Rendered hearder in {renderSw.GetElapsedAndRestart()}"); @foreach (var type in KnownPolicyTypes.OrderByDescending(t => GetPolicyEventsByType(t).Count)) {
@($"{GetPolicyTypeName(type)}: {GetPolicyEventsByType(type).Count} policies")
@{ var policies = GetValidPolicyEventsByType(type); var invalidPolicies = GetInvalidPolicyEventsByType(type); // enumerate all properties with friendly name var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(x => (x.GetFriendlyNameOrNull() ?? x.GetJsonPropertyNameOrNull()) is not null) .Where(x => x.GetCustomAttribute() is null) .ToFrozenSet(); var propNames = props.Select(x => x.GetFriendlyNameOrNull() ?? x.GetJsonPropertyName()!).ToFrozenSet(); var proxySafeProps = type.GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(x => props.Any(y => y.Name == x.Name)) .ToFrozenSet(); Console.WriteLine($"{proxySafeProps?.Count} proxy safe props found in {policies.FirstOrDefault()?.TypedContent?.GetType()}"); } @foreach (var policy in policies.OrderBy(x => x.RawContent?["entity"]?.GetValue())) {
@{ var typedContent = policy.TypedContent!; } @foreach (var prop in proxySafeProps ?? Enumerable.Empty()) { @prop.GetGetMethod()?.Invoke(typedContent, null) }
@if (PowerLevels.UserHasStatePermission(Homeserver.WhoAmI.UserId, policy.Type)) { Edit Remove @if (policy.IsLegacyType) { Update policy type } }
}
@("Invalid " + GetPolicyTypeName(type).ToLower()) @foreach (var policy in invalidPolicies) { }
State key Json contents
@policy.StateKey
@policy.RawContent.ToJson(true, false)
} Console.WriteLine($"Rendered policies in {renderSw.GetElapsedAndRestart()}"); Console.WriteLine($"Rendered in {renderTotalSw.Elapsed}"); } @if (CurrentlyEditingEvent is not null) { } @code { #if DEBUG private const bool Debug = true; #else private const bool Debug = false; #endif private bool Loading { get; set; } = true; [Parameter] public string RoomId { get; set; } = null!; private bool _enableAvatars; private StateEventResponse? _currentlyEditingEvent; private Dictionary> PolicyEventsByType { get; set; } = new(); private StateEventResponse? CurrentlyEditingEvent { get => _currentlyEditingEvent; set { _currentlyEditingEvent = value; StateHasChanged(); } } private AuthenticatedHomeserverGeneric Homeserver { get; set; } private GenericRoom Room { get; set; } private RoomPowerLevelEventContent PowerLevels { get; set; } protected override async Task OnInitializedAsync() { var sw = Stopwatch.StartNew(); await base.OnInitializedAsync(); Homeserver = (await RMUStorage.GetCurrentSessionOrNavigate())!; if (Homeserver is null) return; Room = Homeserver.GetRoom(RoomId!); PowerLevels = (await Room.GetPowerLevelsAsync())!; await LoadStatesAsync(); Console.WriteLine($"Policy list editor initialized in {sw.Elapsed}!"); } private async Task LoadStatesAsync() { Loading = true; var states = Room.GetFullStateAsync(); PolicyEventsByType.Clear(); await foreach (var state in states) { if (state is null) continue; if (!state.MappedType.IsAssignableTo(typeof(PolicyRuleEventContent))) continue; if (!PolicyEventsByType.ContainsKey(state.MappedType)) PolicyEventsByType.Add(state.MappedType, new()); PolicyEventsByType[state.MappedType].Add(state); } Loading = false; StateHasChanged(); } private List GetPolicyEventsByType(Type type) => PolicyEventsByType.ContainsKey(type) ? PolicyEventsByType[type] : []; private List GetValidPolicyEventsByType(Type type) => GetPolicyEventsByType(type) .Where(x => !string.IsNullOrWhiteSpace(x.RawContent?["recommendation"]?.GetValue())).ToList(); private List GetInvalidPolicyEventsByType(Type type) => GetPolicyEventsByType(type) .Where(x => string.IsNullOrWhiteSpace(x.RawContent?["recommendation"]?.GetValue())).ToList(); private string? GetPolicyTypeNameOrNull(Type type) => type.GetFriendlyNamePluralOrNull() ?? type.GetCustomAttributes() .FirstOrDefault(x => !string.IsNullOrWhiteSpace(x.EventName))?.EventName; private string GetPolicyTypeName(Type type) => GetPolicyTypeNameOrNull(type) ?? type.Name; private async Task RemovePolicyAsync(StateEventResponse policyEvent) { await Room.SendStateEventAsync(policyEvent.Type, policyEvent.StateKey.UrlEncode(), new { }); PolicyEventsByType[policyEvent.MappedType].Remove(policyEvent); await LoadStatesAsync(); } private async Task UpdatePolicyAsync(StateEventResponse policyEvent) { await Room.SendStateEventAsync(policyEvent.Type, policyEvent.StateKey.UrlEncode(), policyEvent.RawContent); CurrentlyEditingEvent = null; await LoadStatesAsync(); } private async Task UpgradePolicyAsync(StateEventResponse policyEvent) { policyEvent.RawContent["upgraded_from_type"] = policyEvent.Type; await LoadStatesAsync(); } private static FrozenSet KnownPolicyTypes = StateEvent.KnownStateEventTypes.Where(x => x.IsAssignableTo(typeof(PolicyRuleEventContent))).ToFrozenSet(); // event types, unnamed private static Dictionary PolicyTypes = KnownPolicyTypes .ToDictionary(x => x.GetCustomAttributes().First(y => !string.IsNullOrWhiteSpace(y.EventName)).EventName, x => x); }