Compare commits

..

No commits in common. "88ca4687080a1a1ee4c76eb42366de5c7c1a031e" and "581fddf6f90936cb08c0da229a13b3b57d843085" have entirely different histories.

7 changed files with 201 additions and 55 deletions

View File

@ -5,7 +5,6 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Web;
using static vassago.Models.Enumerations; using static vassago.Models.Enumerations;
public class Channel public class Channel
@ -14,6 +13,7 @@ public class Channel
public Guid Id { get; set; } public Guid Id { get; set; }
public string ExternalId { get; set; } public string ExternalId { get; set; }
public string DisplayName { get; set; } public string DisplayName { get; set; }
public ChannelPermissions Permissions { get; set; }
public List<Channel> SubChannels { get; set; } public List<Channel> SubChannels { get; set; }
public Channel ParentChannel { get; set; } public Channel ParentChannel { get; set; }
public string Protocol { get; set; } public string Protocol { get; set; }
@ -21,14 +21,6 @@ public class Channel
public List<Account> Users { get; set; } public List<Account> Users { get; set; }
public ChannelType ChannelType {get; set; } public ChannelType ChannelType {get; set; }
//Permissions
public ulong? MaxAttachmentBytes { get; set; }
public uint? MaxTextChars { get; set; }
public bool? LinksAllowed { get; set; }
public bool? ReactionsPossible { get; set; }
public Enumerations.LewdnessFilterLevel? LewdnessFilterLevel { get; set; }
public Enumerations.MeannessFilterLevel? MeannessFilterLevel { get; set; }
[NonSerialized] [NonSerialized]
public Func<string, string, Task> SendFile; public Func<string, string, Task> SendFile;
@ -40,29 +32,33 @@ public class Channel
{ {
get get
{ {
var path = new Stack<Channel>(); //omg i actually get to use a data structure from university ChannelPermissions toReturn = Permissions ?? new ChannelPermissions();
var walker = this; return GetEffectivePermissions(ref toReturn).Definite();
path.Push(this); }
while(walker.ParentChannel != null) }
{ private ChannelPermissions GetEffectivePermissions(ref ChannelPermissions settings)
walker = walker.ParentChannel; {
path.Push(walker); if(settings == null) throw new ArgumentNullException();
} settings.LewdnessFilterLevel = settings.LewdnessFilterLevel ?? Permissions?.LewdnessFilterLevel;
DefinitePermissionSettings toReturn = new DefinitePermissionSettings(); settings.MeannessFilterLevel = settings.MeannessFilterLevel ?? Permissions?.MeannessFilterLevel;
walker = path.Pop(); settings.LinksAllowed = settings.LinksAllowed ?? Permissions?.LinksAllowed;
while(walker != null) settings.MaxAttachmentBytes = settings.MaxAttachmentBytes ?? Permissions?.MaxAttachmentBytes;
{ settings.MaxTextChars = settings.MaxTextChars ?? Permissions?.MaxTextChars;
toReturn.LewdnessFilterLevel = LewdnessFilterLevel ?? toReturn.LewdnessFilterLevel; settings.ReactionsPossible = settings.ReactionsPossible ?? Permissions?.ReactionsPossible;
toReturn.MeannessFilterLevel = MeannessFilterLevel ?? toReturn.MeannessFilterLevel;
toReturn.LinksAllowed = LinksAllowed ?? toReturn.LinksAllowed;
toReturn.MaxAttachmentBytes = MaxAttachmentBytes ?? toReturn.MaxAttachmentBytes;
toReturn.MaxTextChars = MaxTextChars ?? toReturn.MaxTextChars;
toReturn.ReactionsPossible = ReactionsPossible ?? toReturn.ReactionsPossible;
walker = path.Pop(); if(this.ParentChannel != null &&
} (settings.LewdnessFilterLevel == null ||
settings.MeannessFilterLevel == null ||
return toReturn; settings.LinksAllowed == null ||
settings.MaxAttachmentBytes == null ||
settings.MaxTextChars == null ||
settings.ReactionsPossible == null))
{
return this.ParentChannel.GetEffectivePermissions(ref settings);
}
else
{
return settings;
} }
} }
public string LineageSummary public string LineageSummary
@ -79,14 +75,4 @@ public class Channel
} }
} }
} }
}
public class DefinitePermissionSettings
{
public ulong MaxAttachmentBytes { get; set; }
public uint MaxTextChars { get; set; }
public bool LinksAllowed { get; set; }
public bool ReactionsPossible { get; set; }
public Enumerations.LewdnessFilterLevel LewdnessFilterLevel { get; set; }
public Enumerations.MeannessFilterLevel MeannessFilterLevel { get; set; }
} }

View File

@ -0,0 +1,38 @@
namespace vassago.Models;
using System;
using System.ComponentModel.DataAnnotations.Schema;
public class ChannelPermissions
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public ulong? MaxAttachmentBytes { get; set; }
public uint? MaxTextChars { get; set; }
public bool? LinksAllowed { get; set; }
public bool? ReactionsPossible { get; set; }
public Enumerations.LewdnessFilterLevel? LewdnessFilterLevel { get; set; }
public Enumerations.MeannessFilterLevel? MeannessFilterLevel { get; set; }
internal DefinitePermissionSettings Definite()
{
return new DefinitePermissionSettings()
{
MaxAttachmentBytes = this.MaxAttachmentBytes ?? 0,
MaxTextChars = this.MaxTextChars ?? 0,
LinksAllowed = this.LinksAllowed ?? false,
LewdnessFilterLevel = this.LewdnessFilterLevel ?? Enumerations.LewdnessFilterLevel.G,
MeannessFilterLevel = this.MeannessFilterLevel ?? Enumerations.MeannessFilterLevel.Strict,
ReactionsPossible = this.ReactionsPossible ?? false
};
}
}
public class DefinitePermissionSettings
{
public ulong MaxAttachmentBytes { get; set; }
public uint MaxTextChars { get; set; }
public bool LinksAllowed { get; set; }
public bool ReactionsPossible { get; set; }
public Enumerations.LewdnessFilterLevel LewdnessFilterLevel { get; set; }
public Enumerations.MeannessFilterLevel MeannessFilterLevel { get; set; }
}

View File

@ -9,6 +9,8 @@ public class ChattingContext : DbContext
public DbSet<Channel> Channels { get; set; } public DbSet<Channel> Channels { get; set; }
//public DbSet<Emoji> Emoji {get;set;} //public DbSet<Emoji> Emoji {get;set;}
public DbSet<Message> Messages { get; set; } public DbSet<Message> Messages { get; set; }
public DbSet<ChannelPermissions> ChannelPermissions{get;set;}
public DbSet<FeaturePermission> FeaturePermissions{get;set;}
public DbSet<Account> Accounts { get; set; } public DbSet<Account> Accounts { get; set; }
public DbSet<User> Users { get; set; } public DbSet<User> Users { get; set; }

109
Models/FeaturePermission.cs Normal file
View File

@ -0,0 +1,109 @@
namespace vassago.Models;
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Reflection;
using System.Threading.Tasks;
using Discord.WebSocket;
using static vassago.Models.Enumerations;
public enum WellknownPermissions
{
Administrator,
TwitchSummon,
}
public class FeaturePermission
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
public string InternalName { get; set; }
public WellknownPermissions? InternalTag { get; set; }
//a permissions-needing-feature can determine how to use these, but a default "matches" is provided
//for a message to "match", it must match in every category for which there are candidates.
//e.g., Administrator is going to be restricted to Users only, and that'll be me
//e.g., my future Torrent feature would be restricted to accounts and channels.
//hmmm, what would be inheritable and what wouldn't?
public IEnumerable<User> RestrictedToUsers { get; set; }
public IEnumerable<Account> RestrictedToAccounts { get; set; }
public IEnumerable<Channel> RestrictedToChannels { get; set; }
public bool Inheritable { get; set; } = true;
public bool Matches(Message message)
{
if(RestrictedToUsers?.Count() > 0)
{
if(RestrictedToUsers.FirstOrDefault(u => u.Id == message.Author.IsUser.Id) == null)
{
return false;
}
}
if(RestrictedToChannels?.Count() > 0)
{
if(Inheritable)
{
var found = false;
var walker = message.Channel;
if (RestrictedToChannels.FirstOrDefault(c => c.Id == walker.Id) != null)
{
found = true;
}
else
{
while (walker.ParentChannel != null)
{
walker = walker.ParentChannel;
if(walker.Users.FirstOrDefault(a => a.ExternalId == message.Author.ExternalId) == null)
{
//the chain is broken; I don't exist in this channel
break;
}
if (RestrictedToChannels.FirstOrDefault(c => c.Id == walker.Id) != null)
{
found = true;
break;
}
}
}
if (found)
{
if(RestrictedToAccounts?.Count() > 0)
{
//walker is the "actual" restricted-to channel, but we're inheriting
if(walker.Users.FirstOrDefault(a => a.Id == message.Author.Id) == null)
{
return false;
}
}
}
else
{
return false;
}
}
else
{
if(RestrictedToChannels.FirstOrDefault(c => c.Id == message.Channel.Id) == null)
{
return false;
}
}
}
if(RestrictedToAccounts?.Count() > 0)
{
if(RestrictedToAccounts.FirstOrDefault(a => a.Id == message.Author.Id) == null)
{
return false;
}
}
//if I got all the way down here, I must be good
return true;
}
}

View File

@ -58,12 +58,15 @@ public class DiscordInterface
protocolAsChannel = new Channel() protocolAsChannel = new Channel()
{ {
DisplayName = "discord (itself)", DisplayName = "discord (itself)",
MeannessFilterLevel = Enumerations.MeannessFilterLevel.Strict, Permissions = new Models.ChannelPermissions()
LewdnessFilterLevel = Enumerations.LewdnessFilterLevel.Moderate, {
MaxTextChars = 2000, MeannessFilterLevel = Enumerations.MeannessFilterLevel.Strict,
MaxAttachmentBytes = 25 * 1024 * 1024, //allegedly it's 25, but I worry it's not actually. LewdnessFilterLevel = Enumerations.LewdnessFilterLevel.Moderate,
LinksAllowed = true, MaxTextChars = 2000,
ReactionsPossible = true, MaxAttachmentBytes = 25 * 1024 * 1024, //allegedly it's 25, but I worry it's not actually.
LinksAllowed = true,
ReactionsPossible = true
},
ExternalId = null, ExternalId = null,
Protocol = PROTOCOL, Protocol = PROTOCOL,
SubChannels = new List<Channel>() SubChannels = new List<Channel>()
@ -295,7 +298,8 @@ public class DiscordInterface
c.Protocol = protocolAsChannel.Protocol; c.Protocol = protocolAsChannel.Protocol;
c.ParentChannel = protocolAsChannel; c.ParentChannel = protocolAsChannel;
c.SubChannels = c.SubChannels ?? new List<Channel>(); c.SubChannels = c.SubChannels ?? new List<Channel>();
c.MaxAttachmentBytes = channel.MaxUploadLimit; c.Permissions = c.Permissions ?? new Models.ChannelPermissions();
c.Permissions.MaxAttachmentBytes = channel.MaxUploadLimit;
c.SendMessage = (t) => { throw new InvalidOperationException($"channel {channel.Name} is guild; cannot accept text"); }; c.SendMessage = (t) => { throw new InvalidOperationException($"channel {channel.Name} is guild; cannot accept text"); };
c.SendFile = (f, t) => { throw new InvalidOperationException($"channel {channel.Name} is guild; send file"); }; c.SendFile = (f, t) => { throw new InvalidOperationException($"channel {channel.Name} is guild; send file"); };

View File

@ -39,12 +39,15 @@ public class TwitchInterface
protocolAsChannel = new Channel() protocolAsChannel = new Channel()
{ {
DisplayName = "twitch (itself)", DisplayName = "twitch (itself)",
MeannessFilterLevel = Enumerations.MeannessFilterLevel.Medium, Permissions = new ChannelPermissions()
LewdnessFilterLevel = Enumerations.LewdnessFilterLevel.G, {
MaxTextChars = 500, MeannessFilterLevel = Enumerations.MeannessFilterLevel.Medium,
MaxAttachmentBytes = 0, LewdnessFilterLevel = Enumerations.LewdnessFilterLevel.G,
LinksAllowed = false, MaxTextChars = 500,
ReactionsPossible = false, MaxAttachmentBytes = 0,
LinksAllowed = false,
ReactionsPossible = false
},
ExternalId = null, ExternalId = null,
Protocol = PROTOCOL, Protocol = PROTOCOL,
SubChannels = new List<Channel>() SubChannels = new List<Channel>()

View File

@ -21,7 +21,11 @@ debating whether to save a copy of every single attachment. Discord allows 25MB
### Channel ### Channel
a place where communication can happen. any level of these can have any number of children. In matrix, everything is a "room" - even spaces and threads. Seems like a fine idea. So for vassago, a discord "channel" is a channel. a "thread" is a child of that channel. a "category" is a parent of that channel. A "server" (formerly "guild") is a parent of that channel. and fuck it, Discord itself is a "channel". Includes permissions vassago has for a channel; MaxAttachmentBytes, etc. go down the hierarchy until you find an override. a place where communication can happen. any level of these can have any number of children. In matrix, everything is a "room" - even spaces and threads. Seems like a fine idea. So for vassago, a discord "channel" is a channel. a "thread" is a child of that channel. a "category" is a parent of that channel. A "server" (formerly "guild") is a parent of that channel. and fuck it, Discord itself is a "channel".
### ChannelPermissions
the permissions Vassago has for a channel. MaxAttachmentBytes, etc. (...shouldn't this be just part of Channel? You're *always* going down the hierarchy until you find an override. permissions should always inherit, right?)
### FeaturePermission ### FeaturePermission