feat: don't hide information from own system when directly requested
in lists, pk;m <ref> <prop>, etc
This commit is contained in:
		| @@ -133,6 +133,12 @@ public class Context | ||||
|             await Reply($"{Emojis.Warn} This command is deprecated and will be removed soon. In the future, please use `pk;{commandDef.Key}`."); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Same as LookupContextFor, but skips flags / config checks. | ||||
|     /// </summary> | ||||
|     public LookupContext DirectLookupContextFor(SystemId systemId) | ||||
|         => System?.Id == systemId ? LookupContext.ByOwner : LookupContext.ByNonOwner; | ||||
|  | ||||
|     public LookupContext LookupContextFor(SystemId systemId) | ||||
|     { | ||||
|         var hasPrivateOverride = this.MatchFlag("private", "priv"); | ||||
|   | ||||
| @@ -21,10 +21,10 @@ public static class ContextChecksExt | ||||
|         throw new PKError("This command must be run in a DM."); | ||||
|     } | ||||
|  | ||||
|     public static Context CheckSystemPrivacy(this Context ctx, PKSystem target, PrivacyLevel level) | ||||
|     public static Context CheckSystemPrivacy(this Context ctx, SystemId target, PrivacyLevel level) | ||||
|     { | ||||
|         if (level.CanAccess(ctx.LookupContextFor(target.Id))) return ctx; | ||||
|         throw target.Id == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; | ||||
|         if (level.CanAccess(ctx.DirectLookupContextFor(target))) return ctx; | ||||
|         throw Errors.LookupNotAllowed; | ||||
|     } | ||||
|  | ||||
|     public static Context CheckOwnSystem(this Context ctx, PKSystem system) | ||||
|   | ||||
| @@ -129,10 +129,12 @@ public class GroupMember | ||||
|  | ||||
|     public async Task ListGroupMembers(Context ctx, PKGroup target) | ||||
|     { | ||||
|         var targetSystem = await GetGroupSystem(ctx, target); | ||||
|         ctx.CheckSystemPrivacy(targetSystem, target.ListPrivacy); | ||||
|         // see global system list for explanation of how privacy settings are used here | ||||
|  | ||||
|         var opts = ctx.ParseMemberListOptions(ctx.LookupContextFor(target.System)); | ||||
|         var targetSystem = await GetGroupSystem(ctx, target); | ||||
|         ctx.CheckSystemPrivacy(targetSystem.Id, target.ListPrivacy); | ||||
|  | ||||
|         var opts = ctx.ParseMemberListOptions(ctx.DirectLookupContextFor(target.System)); | ||||
|         opts.GroupFilter = target.Id; | ||||
|  | ||||
|         var title = new StringBuilder($"Members of {target.DisplayName ?? target.Name} (`{target.Hid}`) in "); | ||||
|   | ||||
| @@ -189,8 +189,7 @@ public class Groups | ||||
|  | ||||
|     public async Task GroupDescription(Context ctx, PKGroup target) | ||||
|     { | ||||
|         if (!target.DescriptionPrivacy.CanAccess(ctx.LookupContextFor(target.System))) | ||||
|             throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; | ||||
|         ctx.CheckSystemPrivacy(target.System, target.DescriptionPrivacy); | ||||
|  | ||||
|         var noDescriptionSetMessage = "This group does not have a description set."; | ||||
|         if (ctx.System?.Id == target.System) | ||||
| @@ -281,8 +280,7 @@ public class Groups | ||||
|  | ||||
|         async Task ShowIcon() | ||||
|         { | ||||
|             if (!target.IconPrivacy.CanAccess(ctx.LookupContextFor(target.System))) | ||||
|                 throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; | ||||
|             ctx.CheckSystemPrivacy(target.System, target.IconPrivacy); | ||||
|  | ||||
|             if ((target.Icon?.Trim() ?? "").Length > 0) | ||||
|             { | ||||
| @@ -346,8 +344,7 @@ public class Groups | ||||
|  | ||||
|         async Task ShowBannerImage() | ||||
|         { | ||||
|             if (!target.DescriptionPrivacy.CanAccess(ctx.LookupContextFor(target.System))) | ||||
|                 throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; | ||||
|             ctx.CheckSystemPrivacy(target.System, target.DescriptionPrivacy); | ||||
|  | ||||
|             if ((target.BannerImage?.Trim() ?? "").Length > 0) | ||||
|             { | ||||
| @@ -432,7 +429,7 @@ public class Groups | ||||
|             system = ctx.System; | ||||
|         } | ||||
|  | ||||
|         ctx.CheckSystemPrivacy(system, system.GroupListPrivacy); | ||||
|         ctx.CheckSystemPrivacy(system.Id, system.GroupListPrivacy); | ||||
|  | ||||
|         // TODO: integrate with the normal "search" system | ||||
|  | ||||
| @@ -442,7 +439,7 @@ public class Groups | ||||
|             if (system.Id == ctx.System.Id) | ||||
|                 pctx = LookupContext.ByOwner; | ||||
|             else | ||||
|                 throw system.Id == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; | ||||
|                 throw Errors.LookupNotAllowed; | ||||
|         } | ||||
|  | ||||
|         var groups = (await _db.Execute(conn => conn.QueryGroupList(system.Id))) | ||||
| @@ -577,7 +574,7 @@ public class Groups | ||||
|     public async Task GroupFrontPercent(Context ctx, PKGroup target) | ||||
|     { | ||||
|         var targetSystem = await GetGroupSystem(ctx, target); | ||||
|         ctx.CheckSystemPrivacy(targetSystem, targetSystem.FrontHistoryPrivacy); | ||||
|         ctx.CheckSystemPrivacy(targetSystem.Id, targetSystem.FrontHistoryPrivacy); | ||||
|  | ||||
|         var totalSwitches = await _repo.GetSwitchCount(targetSystem.Id); | ||||
|         if (totalSwitches == 0) throw Errors.NoRegisteredSwitches; | ||||
|   | ||||
| @@ -41,9 +41,12 @@ public class MemberAvatar | ||||
|     private async Task AvatarShow(AvatarLocation location, Context ctx, PKMember target, | ||||
|                                   MemberGuildSettings? guildData) | ||||
|     { | ||||
|         // todo: this privacy code is really confusing | ||||
|         // for now, we skip privacy flag/config parsing for this, but it would be good to fix that at some point | ||||
|  | ||||
|         var currentValue = location == AvatarLocation.Member ? target.AvatarUrl : guildData?.AvatarUrl; | ||||
|         var canAccess = location != AvatarLocation.Member || | ||||
|                         target.AvatarPrivacy.CanAccess(ctx.LookupContextFor(target.System)); | ||||
|                         target.AvatarPrivacy.CanAccess(ctx.DirectLookupContextFor(target.System)); | ||||
|         if (string.IsNullOrEmpty(currentValue) || !canAccess) | ||||
|         { | ||||
|             if (location == AvatarLocation.Member) | ||||
|   | ||||
| @@ -63,14 +63,13 @@ public class MemberEdit | ||||
|  | ||||
|     public async Task Description(Context ctx, PKMember target) | ||||
|     { | ||||
|         ctx.CheckSystemPrivacy(target.System, target.DescriptionPrivacy); | ||||
|  | ||||
|         var noDescriptionSetMessage = "This member does not have a description set."; | ||||
|         if (ctx.System?.Id == target.System) | ||||
|             noDescriptionSetMessage += | ||||
|                 $" To set one, type `pk;member {target.Reference()} description <description>`."; | ||||
|  | ||||
|         if (!target.DescriptionPrivacy.CanAccess(ctx.LookupContextFor(target.System))) | ||||
|             throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; | ||||
|  | ||||
|         if (ctx.MatchRaw()) | ||||
|         { | ||||
|             if (target.Description == null) | ||||
| @@ -124,8 +123,7 @@ public class MemberEdit | ||||
|         if (ctx.System?.Id == target.System) | ||||
|             noPronounsSetMessage += $"To set some, type `pk;member {target.Reference()} pronouns <pronouns>`."; | ||||
|  | ||||
|         if (!target.PronounPrivacy.CanAccess(ctx.LookupContextFor(target.System))) | ||||
|             throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; | ||||
|         ctx.CheckSystemPrivacy(target.System, target.PronounPrivacy); | ||||
|  | ||||
|         if (ctx.MatchRaw()) | ||||
|         { | ||||
| @@ -292,8 +290,7 @@ public class MemberEdit | ||||
|         } | ||||
|         else if (!ctx.HasNext()) | ||||
|         { | ||||
|             if (!target.BirthdayPrivacy.CanAccess(ctx.LookupContextFor(target.System))) | ||||
|                 throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; | ||||
|             ctx.CheckSystemPrivacy(target.System, target.BirthdayPrivacy); | ||||
|  | ||||
|             if (target.Birthday == null) | ||||
|                 await ctx.Reply("This member does not have a birthdate set." | ||||
|   | ||||
| @@ -55,7 +55,7 @@ public class Random | ||||
|  | ||||
|     public async Task GroupMember(Context ctx, PKGroup group) | ||||
|     { | ||||
|         var opts = ctx.ParseMemberListOptions(ctx.LookupContextFor(group.System)); | ||||
|         var opts = ctx.ParseMemberListOptions(ctx.DirectLookupContextFor(group.System)); | ||||
|         opts.GroupFilter = group.Id; | ||||
|  | ||||
|         await using var conn = await _db.Obtain(); | ||||
|   | ||||
| @@ -22,7 +22,7 @@ public class SystemFront | ||||
|     public async Task SystemFronter(Context ctx, PKSystem system) | ||||
|     { | ||||
|         if (system == null) throw Errors.NoSystemError; | ||||
|         ctx.CheckSystemPrivacy(system, system.FrontPrivacy); | ||||
|         ctx.CheckSystemPrivacy(system.Id, system.FrontPrivacy); | ||||
|  | ||||
|         var sw = await _repo.GetLatestSwitch(system.Id); | ||||
|         if (sw == null) throw Errors.NoRegisteredSwitches; | ||||
| @@ -33,7 +33,7 @@ public class SystemFront | ||||
|     public async Task SystemFrontHistory(Context ctx, PKSystem system) | ||||
|     { | ||||
|         if (system == null) throw Errors.NoSystemError; | ||||
|         ctx.CheckSystemPrivacy(system, system.FrontHistoryPrivacy); | ||||
|         ctx.CheckSystemPrivacy(system.Id, system.FrontHistoryPrivacy); | ||||
|  | ||||
|         var totalSwitches = await _repo.GetSwitchCount(system.Id); | ||||
|         if (totalSwitches == 0) throw Errors.NoRegisteredSwitches; | ||||
| @@ -98,7 +98,7 @@ public class SystemFront | ||||
|     public async Task SystemFrontPercent(Context ctx, PKSystem system) | ||||
|     { | ||||
|         if (system == null) throw Errors.NoSystemError; | ||||
|         ctx.CheckSystemPrivacy(system, system.FrontHistoryPrivacy); | ||||
|         ctx.CheckSystemPrivacy(system.Id, system.FrontHistoryPrivacy); | ||||
|  | ||||
|         var totalSwitches = await _repo.GetSwitchCount(system.Id); | ||||
|         if (totalSwitches == 0) throw Errors.NoRegisteredSwitches; | ||||
|   | ||||
| @@ -9,9 +9,13 @@ public class SystemList | ||||
|     public async Task MemberList(Context ctx, PKSystem target) | ||||
|     { | ||||
|         if (target == null) throw Errors.NoSystemError; | ||||
|         ctx.CheckSystemPrivacy(target, target.MemberListPrivacy); | ||||
|         ctx.CheckSystemPrivacy(target.Id, target.MemberListPrivacy); | ||||
|  | ||||
|         var opts = ctx.ParseMemberListOptions(ctx.LookupContextFor(target.Id)); | ||||
|         // explanation of privacy lookup here: | ||||
|         // - ParseMemberListOptions checks list access privacy and sets the privacy filter (which members show up in list) | ||||
|         // - RenderMemberList checks the indivual privacy for each member (NameFor, etc) | ||||
|         // the own system is always allowed to look up their list | ||||
|         var opts = ctx.ParseMemberListOptions(ctx.DirectLookupContextFor(target.Id)); | ||||
|         await ctx.RenderMemberList( | ||||
|             ctx.LookupContextFor(target.Id), | ||||
|             target.Id, | ||||
|   | ||||
| @@ -90,8 +90,6 @@ public static class Errors | ||||
|         new("Cannot get the front percent between now and a time in the future."); | ||||
|  | ||||
|     public static PKError LookupNotAllowed => new("You do not have permission to access this information."); | ||||
|     public static PKError LookupHidden => | ||||
|         new("This information is private and you have chosen to hide private information by default. Add the `-private` flag to this command to show it."); | ||||
|  | ||||
|     public static PKError StringTooLongError(string name, int length, int maxLength) => | ||||
|         new($"{name} too long ({length}/{maxLength} characters)."); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user