Compare commits

...

2 Commits

Author SHA1 Message Date
88ca468708 get rid of feature permissions
Some checks failed
gitea/vassago/pipeline/head There was a failure building this commit
2024-04-06 00:01:31 -04:00
464b6a90e4 channel permissions are just part of channel 2024-04-05 23:59:39 -04:00
7 changed files with 55 additions and 201 deletions

View File

@ -5,6 +5,7 @@ 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
@ -13,7 +14,6 @@ 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,6 +21,14 @@ 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;
@ -32,33 +40,29 @@ public class Channel
{ {
get get
{ {
ChannelPermissions toReturn = Permissions ?? new ChannelPermissions(); var path = new Stack<Channel>(); //omg i actually get to use a data structure from university
return GetEffectivePermissions(ref toReturn).Definite(); var walker = this;
} path.Push(this);
} while(walker.ParentChannel != null)
private ChannelPermissions GetEffectivePermissions(ref ChannelPermissions settings) {
{ walker = walker.ParentChannel;
if(settings == null) throw new ArgumentNullException(); path.Push(walker);
settings.LewdnessFilterLevel = settings.LewdnessFilterLevel ?? Permissions?.LewdnessFilterLevel; }
settings.MeannessFilterLevel = settings.MeannessFilterLevel ?? Permissions?.MeannessFilterLevel; DefinitePermissionSettings toReturn = new DefinitePermissionSettings();
settings.LinksAllowed = settings.LinksAllowed ?? Permissions?.LinksAllowed; walker = path.Pop();
settings.MaxAttachmentBytes = settings.MaxAttachmentBytes ?? Permissions?.MaxAttachmentBytes; while(walker != null)
settings.MaxTextChars = settings.MaxTextChars ?? Permissions?.MaxTextChars; {
settings.ReactionsPossible = settings.ReactionsPossible ?? Permissions?.ReactionsPossible; toReturn.LewdnessFilterLevel = LewdnessFilterLevel ?? toReturn.LewdnessFilterLevel;
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;
if(this.ParentChannel != null && walker = path.Pop();
(settings.LewdnessFilterLevel == null || }
settings.MeannessFilterLevel == null ||
settings.LinksAllowed == null || return toReturn;
settings.MaxAttachmentBytes == null ||
settings.MaxTextChars == null ||
settings.ReactionsPossible == null))
{
return this.ParentChannel.GetEffectivePermissions(ref settings);
}
else
{
return settings;
} }
} }
public string LineageSummary public string LineageSummary
@ -75,4 +79,14 @@ 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

@ -1,38 +0,0 @@
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,8 +9,6 @@ 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; }

View File

@ -1,109 +0,0 @@
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,15 +58,12 @@ public class DiscordInterface
protocolAsChannel = new Channel() protocolAsChannel = new Channel()
{ {
DisplayName = "discord (itself)", DisplayName = "discord (itself)",
Permissions = new Models.ChannelPermissions() MeannessFilterLevel = Enumerations.MeannessFilterLevel.Strict,
{ LewdnessFilterLevel = Enumerations.LewdnessFilterLevel.Moderate,
MeannessFilterLevel = Enumerations.MeannessFilterLevel.Strict, MaxTextChars = 2000,
LewdnessFilterLevel = Enumerations.LewdnessFilterLevel.Moderate, MaxAttachmentBytes = 25 * 1024 * 1024, //allegedly it's 25, but I worry it's not actually.
MaxTextChars = 2000, LinksAllowed = true,
MaxAttachmentBytes = 25 * 1024 * 1024, //allegedly it's 25, but I worry it's not actually. ReactionsPossible = true,
LinksAllowed = true,
ReactionsPossible = true
},
ExternalId = null, ExternalId = null,
Protocol = PROTOCOL, Protocol = PROTOCOL,
SubChannels = new List<Channel>() SubChannels = new List<Channel>()
@ -298,8 +295,7 @@ 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.Permissions = c.Permissions ?? new Models.ChannelPermissions(); c.MaxAttachmentBytes = channel.MaxUploadLimit;
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,15 +39,12 @@ public class TwitchInterface
protocolAsChannel = new Channel() protocolAsChannel = new Channel()
{ {
DisplayName = "twitch (itself)", DisplayName = "twitch (itself)",
Permissions = new ChannelPermissions() MeannessFilterLevel = Enumerations.MeannessFilterLevel.Medium,
{ LewdnessFilterLevel = Enumerations.LewdnessFilterLevel.G,
MeannessFilterLevel = Enumerations.MeannessFilterLevel.Medium, MaxTextChars = 500,
LewdnessFilterLevel = Enumerations.LewdnessFilterLevel.G, MaxAttachmentBytes = 0,
MaxTextChars = 500, LinksAllowed = false,
MaxAttachmentBytes = 0, ReactionsPossible = false,
LinksAllowed = false,
ReactionsPossible = false
},
ExternalId = null, ExternalId = null,
Protocol = PROTOCOL, Protocol = PROTOCOL,
SubChannels = new List<Channel>() SubChannels = new List<Channel>()

View File

@ -21,11 +21,7 @@ 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". 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.
### 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