Skip to content

Commit 27effc4

Browse files
authored
feat: Add Permissions API support (#578)
1 parent e66855a commit 27effc4

12 files changed

+1677
-0
lines changed

.editorconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[*.cs]
2+
3+
# IDE1006: Naming Styles
4+
dotnet_diagnostic.IDE1006.severity = none

SendGrid.sln

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SendGrid.Extensions.Depende
2323
EndProject
2424
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CADBDC30-FD3E-4FBA-B8F0-D3B6A1874FB9}"
2525
ProjectSection(SolutionItems) = preProject
26+
.editorconfig = .editorconfig
2627
.env_sample = .env_sample
2728
.gitignore = .gitignore
2829
.travis.yml = .travis.yml

USE_CASES.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ This document provides examples for specific use cases. Please [open an issue](h
2525
- [How to transform HTML into plain text](#how-to-transform-html-into-plain-text)
2626
- [Send an Email With Twilio Email (Pilot)](#send-an-email-with-twilio-email-pilot)
2727
- [Send an SMS Message](#send-an-sms-message)
28+
- [Working With Permissions](#working-with-permissions)
2829

2930
<a name="attachments"></a>
3031
# Attachments
@@ -1000,3 +1001,90 @@ namespace TwilioTest
10001001
}
10011002
}
10021003
```
1004+
1005+
<a name="working-with-permissions" ></a>
1006+
# Working with permissions
1007+
1008+
The permissions builder is a convenient way to manipulate API key permissions when creating new API keys or managing existing API keys.
1009+
1010+
You can use the enums named according to the various [permissions](https://sendgrid.api-docs.io/v3.0/api-key-permissions) to add the scopes required for those permissions.
1011+
1012+
By default, all scopes for a given permission are added; however, You can filter out certain scopes by passing a ScopeOptions parameter or adding some filtering functions.
1013+
1014+
For example, to create an API key for all *Alerts* scopes and read only *Marketing Campaigns*:
1015+
1016+
```
1017+
var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY");
1018+
var client = new SendGridClient(apiKey);
1019+
var builder = new SendGridPermissionsBuilder();
1020+
builder.AddPermissionsFor(SendGridPermission.Alerts);
1021+
builder.AddPermissionsFor(SendGridPermission.MarketingCampaigns, ScopeOptions.ReadOnly);
1022+
1023+
/*
1024+
The above builder will emit the following scopes:
1025+
1026+
alerts.create
1027+
alerts.delete
1028+
alerts.read
1029+
alerts.update
1030+
marketing_campaigns.read
1031+
*/
1032+
1033+
// now use the provided extension method to create an API key
1034+
1035+
await client.CreateApiKey(builder, "Alerts & Read-Only Marketing Campaigns API Key");
1036+
```
1037+
1038+
There are also some methods to easily create API keys for various common use cases.
1039+
1040+
For example, to create a Mail Send API key scoped for sending email:
1041+
1042+
```
1043+
var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY");
1044+
var client = new SendGridClient(apiKey);
1045+
var builder = new SendGridPermissionsBuilder();
1046+
builder.AddPermissionsFor(SendGridPermission.Mail);
1047+
1048+
/*
1049+
The above builder will emit the following scope:
1050+
1051+
mail.batch.create
1052+
mail.batch.delete
1053+
mail.batch.read
1054+
mail.batch.update
1055+
mail.send
1056+
*/
1057+
1058+
await client.CreateApiKey(builder, "Mail Send API Key");
1059+
```
1060+
1061+
The builder filters out duplicate scopes by default but you can also add filters to the builder so that your application will never create keys with certain scopes.
1062+
1063+
For example, you may want to allow an API key to do just about anything EXCEPT create more API keys.
1064+
1065+
```
1066+
var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY");
1067+
var client = new SendGridClient(apiKey);
1068+
var builder = new SendGridPermissionsBuilder();
1069+
builder.Exclude(scope => scope.StartsWith("api_keys"));
1070+
builder.AddPermissionsFor(SendGridPermission.Admin);
1071+
1072+
await client.CreateApiKey(builder, "Admin API Key that cannot manage other API keys");
1073+
```
1074+
1075+
The builder can also include individual scopes without having to use the AddPermissionsFor method.
1076+
```
1077+
var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY");
1078+
var client = new SendGridClient(apiKey);
1079+
var builder = new SendGridPermissionsBuilder();
1080+
/// use the method overload that accepts an IEnumerable<string>
1081+
var myScopes = new []{
1082+
"mail.send", "alerts.read"
1083+
}
1084+
builder.Include(myScopes);
1085+
1086+
/// or use the method overload that accepts a params string[]
1087+
builder.Include("newsletter.read");
1088+
1089+
await client.CreateApiKey(builder, "Mail send, Alerts & Newletter read");
1090+
```
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace SendGrid.Permissions
2+
{
3+
/// <summary>
4+
/// Represents a set of possible scope options
5+
/// </summary>
6+
/// <seealso cref="string" />
7+
public enum ScopeOptions
8+
{
9+
/// <summary>
10+
/// All scopes. When filtering scopes no scopes will be exluded
11+
/// </summary>
12+
All,
13+
14+
/// <summary>
15+
/// Read-only scopes. When fitlering scopes this will include only those that end with ".read"
16+
/// </summary>
17+
ReadOnly
18+
}
19+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System.Linq;
2+
using System.Threading.Tasks;
3+
using Newtonsoft.Json;
4+
using Newtonsoft.Json.Linq;
5+
6+
namespace SendGrid.Permissions
7+
{
8+
/// <summary>
9+
/// Utility extension methods that bridge the gap between the <see cref="ISendGridClient"/> and the <see cref="SendGridPermissionsBuilder"/>.
10+
/// </summary>
11+
public static class SendGridClientExtensions
12+
{
13+
/// <summary>
14+
/// Create a permissions builder instance that masks the emitted scopes to exclude any scopes not
15+
/// contained in the list of scopes already granted for the given API Key the <paramref name="client"/> was initialized with.
16+
/// </summary>
17+
/// <param name="client">The SendGrid client.</param>
18+
/// <returns>A <see cref="SendGridPermissionsBuilder"/> instance.</returns>
19+
public static async Task<SendGridPermissionsBuilder> CreateMaskedPermissionsBuilderForClient(this ISendGridClient client)
20+
{
21+
var response = await client.RequestAsync(method: SendGridClient.Method.GET, urlPath: "scopes");
22+
var body = await response.DeserializeResponseBodyAsync(response.Body);
23+
var userScopesJArray = (body["scopes"] as JArray);
24+
var includedScopes = userScopesJArray.Values<string>().ToArray();
25+
var builder = new SendGridPermissionsBuilder();
26+
builder.Exclude(scope => !includedScopes.Contains(scope));
27+
return builder;
28+
}
29+
30+
/// <summary>
31+
/// Create a new API key for the scopes contained in the <paramref name="permissions"/>.
32+
/// </summary>
33+
/// <param name="client">The SendGrid client.</param>
34+
/// <param name="permissions">The permissions builder.</param>
35+
/// <param name="name">The API key name.</param>
36+
/// <returns>The <see cref="Response"/> from the SendGrid API call.</returns>
37+
public static async Task<Response> CreateApiKey(this ISendGridClient client, SendGridPermissionsBuilder permissions, string name)
38+
{
39+
var scopes = permissions.Build();
40+
var payload = new
41+
{
42+
name,
43+
scopes
44+
};
45+
var data = JsonConvert.SerializeObject(payload);
46+
var response = await client.RequestAsync(method: SendGridClient.Method.POST, urlPath: "api_keys", requestBody: data);
47+
return response;
48+
}
49+
}
50+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace SendGrid.Permissions
6+
{
7+
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
8+
public enum SendGridPermission
9+
10+
{
11+
Admin,
12+
Alerts,
13+
ApiKeys,
14+
ASMGroups,
15+
Billing,
16+
Categories,
17+
Clients,
18+
Credentials,
19+
DomainAuthentication,
20+
IPs,
21+
Mail,
22+
MailSettings,
23+
MarketingCampaigns,
24+
Newsletter,
25+
PartnerSettings,
26+
ReverseDNS,
27+
ScheduledSends,
28+
Stats,
29+
Subusers,
30+
Suppressions,
31+
Teammates,
32+
Templates,
33+
Tracking,
34+
UserSettings,
35+
Webhook
36+
}
37+
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
38+
}

0 commit comments

Comments
 (0)