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}`."); |             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) |     public LookupContext LookupContextFor(SystemId systemId) | ||||||
|     { |     { | ||||||
|         var hasPrivateOverride = this.MatchFlag("private", "priv"); |         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."); |         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; |         if (level.CanAccess(ctx.DirectLookupContextFor(target))) return ctx; | ||||||
|         throw target.Id == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; |         throw Errors.LookupNotAllowed; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static Context CheckOwnSystem(this Context ctx, PKSystem system) |     public static Context CheckOwnSystem(this Context ctx, PKSystem system) | ||||||
|   | |||||||
| @@ -129,10 +129,12 @@ public class GroupMember | |||||||
|  |  | ||||||
|     public async Task ListGroupMembers(Context ctx, PKGroup target) |     public async Task ListGroupMembers(Context ctx, PKGroup target) | ||||||
|     { |     { | ||||||
|         var targetSystem = await GetGroupSystem(ctx, target); |         // see global system list for explanation of how privacy settings are used here | ||||||
|         ctx.CheckSystemPrivacy(targetSystem, target.ListPrivacy); |  | ||||||
|  |  | ||||||
|         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; |         opts.GroupFilter = target.Id; | ||||||
|  |  | ||||||
|         var title = new StringBuilder($"Members of {target.DisplayName ?? target.Name} (`{target.Hid}`) in "); |         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) |     public async Task GroupDescription(Context ctx, PKGroup target) | ||||||
|     { |     { | ||||||
|         if (!target.DescriptionPrivacy.CanAccess(ctx.LookupContextFor(target.System))) |         ctx.CheckSystemPrivacy(target.System, target.DescriptionPrivacy); | ||||||
|             throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; |  | ||||||
|  |  | ||||||
|         var noDescriptionSetMessage = "This group does not have a description set."; |         var noDescriptionSetMessage = "This group does not have a description set."; | ||||||
|         if (ctx.System?.Id == target.System) |         if (ctx.System?.Id == target.System) | ||||||
| @@ -281,8 +280,7 @@ public class Groups | |||||||
|  |  | ||||||
|         async Task ShowIcon() |         async Task ShowIcon() | ||||||
|         { |         { | ||||||
|             if (!target.IconPrivacy.CanAccess(ctx.LookupContextFor(target.System))) |             ctx.CheckSystemPrivacy(target.System, target.IconPrivacy); | ||||||
|                 throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; |  | ||||||
|  |  | ||||||
|             if ((target.Icon?.Trim() ?? "").Length > 0) |             if ((target.Icon?.Trim() ?? "").Length > 0) | ||||||
|             { |             { | ||||||
| @@ -346,8 +344,7 @@ public class Groups | |||||||
|  |  | ||||||
|         async Task ShowBannerImage() |         async Task ShowBannerImage() | ||||||
|         { |         { | ||||||
|             if (!target.DescriptionPrivacy.CanAccess(ctx.LookupContextFor(target.System))) |             ctx.CheckSystemPrivacy(target.System, target.DescriptionPrivacy); | ||||||
|                 throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; |  | ||||||
|  |  | ||||||
|             if ((target.BannerImage?.Trim() ?? "").Length > 0) |             if ((target.BannerImage?.Trim() ?? "").Length > 0) | ||||||
|             { |             { | ||||||
| @@ -432,7 +429,7 @@ public class Groups | |||||||
|             system = ctx.System; |             system = ctx.System; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         ctx.CheckSystemPrivacy(system, system.GroupListPrivacy); |         ctx.CheckSystemPrivacy(system.Id, system.GroupListPrivacy); | ||||||
|  |  | ||||||
|         // TODO: integrate with the normal "search" system |         // TODO: integrate with the normal "search" system | ||||||
|  |  | ||||||
| @@ -442,7 +439,7 @@ public class Groups | |||||||
|             if (system.Id == ctx.System.Id) |             if (system.Id == ctx.System.Id) | ||||||
|                 pctx = LookupContext.ByOwner; |                 pctx = LookupContext.ByOwner; | ||||||
|             else |             else | ||||||
|                 throw system.Id == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; |                 throw Errors.LookupNotAllowed; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         var groups = (await _db.Execute(conn => conn.QueryGroupList(system.Id))) |         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) |     public async Task GroupFrontPercent(Context ctx, PKGroup target) | ||||||
|     { |     { | ||||||
|         var targetSystem = await GetGroupSystem(ctx, 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); |         var totalSwitches = await _repo.GetSwitchCount(targetSystem.Id); | ||||||
|         if (totalSwitches == 0) throw Errors.NoRegisteredSwitches; |         if (totalSwitches == 0) throw Errors.NoRegisteredSwitches; | ||||||
|   | |||||||
| @@ -41,9 +41,12 @@ public class MemberAvatar | |||||||
|     private async Task AvatarShow(AvatarLocation location, Context ctx, PKMember target, |     private async Task AvatarShow(AvatarLocation location, Context ctx, PKMember target, | ||||||
|                                   MemberGuildSettings? guildData) |                                   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 currentValue = location == AvatarLocation.Member ? target.AvatarUrl : guildData?.AvatarUrl; | ||||||
|         var canAccess = location != AvatarLocation.Member || |         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 (string.IsNullOrEmpty(currentValue) || !canAccess) | ||||||
|         { |         { | ||||||
|             if (location == AvatarLocation.Member) |             if (location == AvatarLocation.Member) | ||||||
|   | |||||||
| @@ -63,14 +63,13 @@ public class MemberEdit | |||||||
|  |  | ||||||
|     public async Task Description(Context ctx, PKMember target) |     public async Task Description(Context ctx, PKMember target) | ||||||
|     { |     { | ||||||
|  |         ctx.CheckSystemPrivacy(target.System, target.DescriptionPrivacy); | ||||||
|  |  | ||||||
|         var noDescriptionSetMessage = "This member does not have a description set."; |         var noDescriptionSetMessage = "This member does not have a description set."; | ||||||
|         if (ctx.System?.Id == target.System) |         if (ctx.System?.Id == target.System) | ||||||
|             noDescriptionSetMessage += |             noDescriptionSetMessage += | ||||||
|                 $" To set one, type `pk;member {target.Reference()} description <description>`."; |                 $" 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 (ctx.MatchRaw()) | ||||||
|         { |         { | ||||||
|             if (target.Description == null) |             if (target.Description == null) | ||||||
| @@ -124,8 +123,7 @@ public class MemberEdit | |||||||
|         if (ctx.System?.Id == target.System) |         if (ctx.System?.Id == target.System) | ||||||
|             noPronounsSetMessage += $"To set some, type `pk;member {target.Reference()} pronouns <pronouns>`."; |             noPronounsSetMessage += $"To set some, type `pk;member {target.Reference()} pronouns <pronouns>`."; | ||||||
|  |  | ||||||
|         if (!target.PronounPrivacy.CanAccess(ctx.LookupContextFor(target.System))) |         ctx.CheckSystemPrivacy(target.System, target.PronounPrivacy); | ||||||
|             throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; |  | ||||||
|  |  | ||||||
|         if (ctx.MatchRaw()) |         if (ctx.MatchRaw()) | ||||||
|         { |         { | ||||||
| @@ -292,8 +290,7 @@ public class MemberEdit | |||||||
|         } |         } | ||||||
|         else if (!ctx.HasNext()) |         else if (!ctx.HasNext()) | ||||||
|         { |         { | ||||||
|             if (!target.BirthdayPrivacy.CanAccess(ctx.LookupContextFor(target.System))) |             ctx.CheckSystemPrivacy(target.System, target.BirthdayPrivacy); | ||||||
|                 throw target.System == ctx.System?.Id ? Errors.LookupHidden : Errors.LookupNotAllowed; |  | ||||||
|  |  | ||||||
|             if (target.Birthday == null) |             if (target.Birthday == null) | ||||||
|                 await ctx.Reply("This member does not have a birthdate set." |                 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) |     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; |         opts.GroupFilter = group.Id; | ||||||
|  |  | ||||||
|         await using var conn = await _db.Obtain(); |         await using var conn = await _db.Obtain(); | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ public class SystemFront | |||||||
|     public async Task SystemFronter(Context ctx, PKSystem system) |     public async Task SystemFronter(Context ctx, PKSystem system) | ||||||
|     { |     { | ||||||
|         if (system == null) throw Errors.NoSystemError; |         if (system == null) throw Errors.NoSystemError; | ||||||
|         ctx.CheckSystemPrivacy(system, system.FrontPrivacy); |         ctx.CheckSystemPrivacy(system.Id, system.FrontPrivacy); | ||||||
|  |  | ||||||
|         var sw = await _repo.GetLatestSwitch(system.Id); |         var sw = await _repo.GetLatestSwitch(system.Id); | ||||||
|         if (sw == null) throw Errors.NoRegisteredSwitches; |         if (sw == null) throw Errors.NoRegisteredSwitches; | ||||||
| @@ -33,7 +33,7 @@ public class SystemFront | |||||||
|     public async Task SystemFrontHistory(Context ctx, PKSystem system) |     public async Task SystemFrontHistory(Context ctx, PKSystem system) | ||||||
|     { |     { | ||||||
|         if (system == null) throw Errors.NoSystemError; |         if (system == null) throw Errors.NoSystemError; | ||||||
|         ctx.CheckSystemPrivacy(system, system.FrontHistoryPrivacy); |         ctx.CheckSystemPrivacy(system.Id, system.FrontHistoryPrivacy); | ||||||
|  |  | ||||||
|         var totalSwitches = await _repo.GetSwitchCount(system.Id); |         var totalSwitches = await _repo.GetSwitchCount(system.Id); | ||||||
|         if (totalSwitches == 0) throw Errors.NoRegisteredSwitches; |         if (totalSwitches == 0) throw Errors.NoRegisteredSwitches; | ||||||
| @@ -98,7 +98,7 @@ public class SystemFront | |||||||
|     public async Task SystemFrontPercent(Context ctx, PKSystem system) |     public async Task SystemFrontPercent(Context ctx, PKSystem system) | ||||||
|     { |     { | ||||||
|         if (system == null) throw Errors.NoSystemError; |         if (system == null) throw Errors.NoSystemError; | ||||||
|         ctx.CheckSystemPrivacy(system, system.FrontHistoryPrivacy); |         ctx.CheckSystemPrivacy(system.Id, system.FrontHistoryPrivacy); | ||||||
|  |  | ||||||
|         var totalSwitches = await _repo.GetSwitchCount(system.Id); |         var totalSwitches = await _repo.GetSwitchCount(system.Id); | ||||||
|         if (totalSwitches == 0) throw Errors.NoRegisteredSwitches; |         if (totalSwitches == 0) throw Errors.NoRegisteredSwitches; | ||||||
|   | |||||||
| @@ -9,9 +9,13 @@ public class SystemList | |||||||
|     public async Task MemberList(Context ctx, PKSystem target) |     public async Task MemberList(Context ctx, PKSystem target) | ||||||
|     { |     { | ||||||
|         if (target == null) throw Errors.NoSystemError; |         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( |         await ctx.RenderMemberList( | ||||||
|             ctx.LookupContextFor(target.Id), |             ctx.LookupContextFor(target.Id), | ||||||
|             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."); |         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 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) => |     public static PKError StringTooLongError(string name, int length, int maxLength) => | ||||||
|         new($"{name} too long ({length}/{maxLength} characters)."); |         new($"{name} too long ({length}/{maxLength} characters)."); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user