From dd684b70cabb7b20cdc8f33a0d0079fb389b21b5 Mon Sep 17 00:00:00 2001 From: Guillaume Lacasa Date: Sat, 22 Apr 2023 14:03:36 +0200 Subject: [PATCH] Replace Scopes with GranularScopes #107 --- Mastonet/AuthenticationClient.cs | 62 +++++++++++++++++++++------- Mastonet/Entities/AppRegistration.cs | 2 +- Mastonet/Enums/Scope.cs | 55 +++++++++++++++++++++++- Mastonet/IAuthenticationClient.cs | 4 ++ 4 files changed, 106 insertions(+), 17 deletions(-) diff --git a/Mastonet/AuthenticationClient.cs b/Mastonet/AuthenticationClient.cs index 9cacd96..bc97ac6 100644 --- a/Mastonet/AuthenticationClient.cs +++ b/Mastonet/AuthenticationClient.cs @@ -1,6 +1,7 @@ using Mastonet.Entities; using System; using System.Collections.Generic; +using System.Linq; using System.Net; using System.Net.Http; using System.Text; @@ -36,11 +37,43 @@ public AuthenticationClient(AppRegistration app, HttpClient client) : base(clien /// The rights needed by your application /// URL to the homepage of your app /// - public async Task CreateApp(string appName, Scope scope, string? website = null, string? redirectUri = null) + [Obsolete("Use GranularScopes instead of deprecated Scope")] + public Task CreateApp(string appName, Scope scope, string? website = null, string? redirectUri = null) { + var scopes = new List(); + if (scope.HasFlag(Scope.Read)) + { + scopes.Add(GranularScope.Read); + } + + if (scope.HasFlag(Scope.Write)) + { + scopes.Add(GranularScope.Write); + } + + if (scope.HasFlag(Scope.Follow)) + { + scopes.AddRange(new GranularScope[] { + GranularScope.Read__Blocks, GranularScope.Write__Blocks, + GranularScope.Read__Follows, GranularScope.Write__Follows, + GranularScope.Read__Mutes, GranularScope.Write__Mutes + }); + } + + return CreateApp(appName, website, redirectUri, scopes); + } + + public Task CreateApp(string appName, string? website = null, string? redirectUri = null, params GranularScope[] scope) + { + return CreateApp(appName, website, redirectUri, scope.AsEnumerable()); + } + + public async Task CreateApp(string appName, string? website = null, string? redirectUri = null, IEnumerable? scope = null) + { + var scopeString = GetScopeParam(scope); var data = new List>() { new KeyValuePair("client_name", appName), - new KeyValuePair("scopes", GetScopeParam(scope)), + new KeyValuePair("scopes", scopeString), new KeyValuePair("redirect_uris", redirectUri?? "urn:ietf:wg:oauth:2.0:oob") }; @@ -52,7 +85,7 @@ public async Task CreateApp(string appName, Scope scope, string var appRegistration = await Post("/api/v1/apps", data); appRegistration.Instance = Instance; - appRegistration.Scope = scope; + appRegistration.Scope = scopeString; this.AppRegistration = appRegistration; return appRegistration; @@ -62,7 +95,7 @@ public async Task CreateApp(string appName, Scope scope, string #region Auth - public Task ConnectWithPassword(string email, string password) + public Task ConnectWithPassword(string email, string password) { if (AppRegistration == null) { @@ -76,13 +109,13 @@ public Task ConnectWithPassword(string email, string password) new KeyValuePair("grant_type", "password"), new KeyValuePair("username", email), new KeyValuePair("password", password), - new KeyValuePair("scope", GetScopeParam(AppRegistration.Scope)), + new KeyValuePair("scope", AppRegistration.Scope), }; return Post("/oauth/token", data); } - public Task ConnectWithCode(string code, string? redirect_uri = null) + public Task ConnectWithCode(string code, string? redirect_uri = null) { if (AppRegistration == null) { @@ -117,7 +150,7 @@ public string OAuthUrl(string? redirectUri = null) redirectUri = "urn:ietf:wg:oauth:2.0:oob"; } - return $"https://{this.Instance}/oauth/authorize?response_type=code&client_id={AppRegistration.ClientId}&scope={GetScopeParam(AppRegistration.Scope).Replace(" ", "%20")}&redirect_uri={redirectUri ?? "urn:ietf:wg:oauth:2.0:oob"}"; + return $"https://{this.Instance}/oauth/authorize?response_type=code&client_id={AppRegistration.ClientId}&scope={AppRegistration.Scope.Replace(" ", "%20")}&redirect_uri={redirectUri ?? "urn:ietf:wg:oauth:2.0:oob"}"; } /// @@ -142,20 +175,19 @@ public Task Revoke(string token) return Post("/oauth/revoke", data); } - private static string GetScopeParam(Scope scope) + private static string GetScopeParam(IEnumerable? scopes) { - var scopeParam = ""; - if ((scope & Scope.Read) == Scope.Read) scopeParam += " read"; - if ((scope & Scope.Write) == Scope.Write) scopeParam += " write"; - if ((scope & Scope.Follow) == Scope.Follow) scopeParam += " follow"; + if (scopes == null) + { + return ""; + } - return scopeParam.Trim(); + return String.Join(" ", scopes.Select(s => s.ToString().ToLowerInvariant().Replace("__", ":"))); } #endregion - + protected override void OnResponseReceived(HttpResponseMessage response) { } - } diff --git a/Mastonet/Entities/AppRegistration.cs b/Mastonet/Entities/AppRegistration.cs index 8789f5f..d3651ca 100644 --- a/Mastonet/Entities/AppRegistration.cs +++ b/Mastonet/Entities/AppRegistration.cs @@ -22,5 +22,5 @@ public class AppRegistration public string Instance { get; set; } = string.Empty; [JsonProperty("scope")] - public Scope Scope { get; set; } + public string Scope { get; set; } = string.Empty; } diff --git a/Mastonet/Enums/Scope.cs b/Mastonet/Enums/Scope.cs index 9c32895..54e88af 100644 --- a/Mastonet/Enums/Scope.cs +++ b/Mastonet/Enums/Scope.cs @@ -5,9 +5,62 @@ namespace Mastonet; [Flags] +[Obsolete("Use Granular Scopes")] public enum Scope { Read = 1, Write = 2, - Follow = 4, + Follow = 4 } + +public enum GranularScope +{ + Read, + Read__Accounts, + Read__Blocks, + Read__Bookmarks, + Read__Favourites, + Read__Filters, + Read__Follows, + Read__Lists, + Read__Mutes, + Read__Notifications, + Read__Search, + Read__Statuses, + + Write, + Write__Accounts, + Write__Blocks, + Write__Bookmarks, + Write__Conversations, + Write__Favourites, + Write__Filters, + Write__Follows, + Write__Lists, + Write__Media, + Write__Mutes, + Write__Notifications, + Write__Reports, + Write__Statuses, + + Push, + + Admin__Read, + Admin__Read__Accounts, + Admin__Read__Reports, + Admin__Read__Domain_Allows, + Admin__Read__Domain_Blocks, + Admin__Read__Ip_Blocks, + Admin__Read__Email_Domain_Blocks, + Admin__Read__Canonical_Email_Blocks, + + Admin__Write, + Admin__Write__Accounts, + Admin__Write__Reports, + Admin__Write__Domain_Allows, + Admin__Write__Domain_Blocks, + Admin__Write__Ip_Blocks, + Admin__Write__Email_Domain_Blocks, + Admin__Write__Canonical_Email_Blocks, + +} \ No newline at end of file diff --git a/Mastonet/IAuthenticationClient.cs b/Mastonet/IAuthenticationClient.cs index cbb9291..ed33b6e 100644 --- a/Mastonet/IAuthenticationClient.cs +++ b/Mastonet/IAuthenticationClient.cs @@ -18,8 +18,12 @@ public interface IAuthenticationClient /// The rights needed by your application /// URL to the homepage of your app /// + [Obsolete("Use GranularScopes instead of deprecated Scope")] Task CreateApp(string appName, Scope scope, string? website = null, string? redirectUri = null); + Task CreateApp(string appName, string? website = null, string? redirectUri = null, params GranularScope[] scope); + Task CreateApp(string appName, string? website = null, string? redirectUri = null, IEnumerable? scope = null); + Task ConnectWithPassword(string email, string password); Task ConnectWithCode(string code, string? redirect_uri = null);