Skip to content

Commit 40dc261

Browse files
Merge pull request #82 from SocksM/model-generator/feature/ClientCredentialsLoginFlow
Model Generator: Client Credentials Login Flow
2 parents 5a3c8ea + 7761054 commit 40dc261

File tree

5 files changed

+98
-13
lines changed

5 files changed

+98
-13
lines changed

src/NetCoreForce.Client/Models/AuthInfo.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,19 @@ public class AuthInfo
3131
[JsonProperty(PropertyName = "password")]
3232
public string Password { get; set; }
3333

34+
/// <summary>
35+
/// Current supported auth methods
36+
/// </summary>
37+
public enum AuthMethodType {
38+
UsernamePassword = 1,
39+
ClientCredentials = 2,
40+
}
41+
/// <summary>
42+
/// Auth type
43+
/// </summary>
44+
[JsonProperty(PropertyName = "authMethod")]
45+
public AuthMethodType? AuthMethod { get; set; }
46+
3447
/// <summary>
3548
/// Salesforce API version
3649
/// </summary>

src/NetCoreForce.ModelGenerator/GenConfig.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Collections.Generic;
22
using NetCoreForce.Client.Models;
3+
using Newtonsoft.Json;
34

45
namespace NetCoreForce.ModelGenerator
56
{
@@ -15,10 +16,13 @@ public class GenConfig
1516
public bool IncludeCustom { get; set; }
1617
public bool IncludeReferences { get; set; }
1718

19+
[JsonIgnore]
20+
public const string DefaultTokenRequestEndpoint = "https://login.salesforce.com/services/oauth2/token";
21+
1822
public GenConfig()
1923
{
2024
this.AuthInfo = new AuthInfo(){
21-
TokenRequestEndpoint = "https://login.salesforce.com/services/oauth2/token",
25+
TokenRequestEndpoint = DefaultTokenRequestEndpoint,
2226
ApiVersion = "v64.0"
2327
};
2428
}

src/NetCoreForce.ModelGenerator/Program.cs

Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Diagnostics;
4-
using System.Dynamic;
53
using System.Reflection;
64
using System.IO;
75
using System.Linq;
@@ -17,6 +15,15 @@ namespace NetCoreForce.ModelGenerator
1715
{
1816
class Program
1917
{
18+
/// <summary>
19+
/// Gets a human-readable string for which value maps to which auth method type
20+
/// </summary>
21+
/// <returns>
22+
/// For example: <c>1 = UsernamePassword, 2 = ClientCredentials</c>
23+
/// </returns>>
24+
private static string ValidAuthTypesInputString =>
25+
string.Join(", ", Enum.GetValues(typeof(AuthInfo.AuthMethodType)).Cast<AuthInfo.AuthMethodType>().Select(v => $"{(int)v} = {v}"));
26+
2027
const string defaultConfigFilename = "modelgenerator_config.json";
2128

2229
static void Main(string[] args)
@@ -45,7 +52,7 @@ static void Main(string[] args)
4552
"You can supply the API credentials either in the config file, the command parameters, or wait to be prompted for that information." + Environment.NewLine +
4653
"If you choose to save the config file, be careful with it as it may contain your API credentials.";
4754

48-
//Authentication
55+
//Authentication options
4956
var clientIdOption = command.Option("--client-id",
5057
"API Client ID, a.k.a. Consumer Key",
5158
CommandOptionType.SingleValue);
@@ -62,6 +69,15 @@ static void Main(string[] args)
6269
"API Password",
6370
CommandOptionType.SingleValue);
6471

72+
var authMethodOption = command.Option("--auth-method",
73+
$"Auth Method, Valid inputs: {ValidAuthTypesInputString}",
74+
CommandOptionType.SingleValue);
75+
76+
var tokenRequestEndpointOption = command.Option("--token-request-endpoint",
77+
$"Token Request endpoint default: {GenConfig.DefaultTokenRequestEndpoint}",
78+
CommandOptionType.SingleValue);
79+
80+
//Config options
6581
var configFileOption = command.Option("--config-file",
6682
"Config file path",
6783
CommandOptionType.SingleValue);
@@ -130,6 +146,22 @@ static void Main(string[] args)
130146
config.AuthInfo.Password = passwordOption.Value();
131147
}
132148

149+
if (authMethodOption.HasValue())
150+
{
151+
if (Enum.TryParse(authMethodOption.Value(), ignoreCase: true, out AuthInfo.AuthMethodType authMethod))
152+
config.AuthInfo.AuthMethod = authMethod;
153+
else
154+
{
155+
Console.WriteLine($"Invalid auth method input, valid inputs: {ValidAuthTypesInputString}");
156+
return -1;
157+
}
158+
}
159+
160+
if (tokenRequestEndpointOption.HasValue())
161+
{
162+
config.AuthInfo.TokenRequestEndpoint = tokenRequestEndpointOption.Value();
163+
}
164+
133165
if (customOption.HasValue())
134166
{
135167
config.IncludeCustom = customOption.HasValue();
@@ -209,6 +241,30 @@ static void Main(string[] args)
209241
private static GenConfig CheckOptions(GenConfig config)
210242
{
211243
//check required auth options
244+
while (config.AuthInfo.AuthMethod == null)
245+
{
246+
Console.WriteLine("Enter Auth Method:");
247+
string consoleReadLine = Console.ReadLine();
248+
249+
if (Enum.TryParse(consoleReadLine, ignoreCase: true, out AuthInfo.AuthMethodType authMethod))
250+
config.AuthInfo.AuthMethod = authMethod;
251+
else
252+
Console.WriteLine($"Invalid input, valid inputs: {ValidAuthTypesInputString}");
253+
254+
Console.WriteLine();
255+
}
256+
257+
while ((
258+
string.IsNullOrEmpty(config.AuthInfo.TokenRequestEndpoint) ||
259+
config.AuthInfo.TokenRequestEndpoint == GenConfig.DefaultTokenRequestEndpoint
260+
) &&
261+
config.AuthInfo.AuthMethod == AuthInfo.AuthMethodType.ClientCredentials)
262+
{
263+
Console.WriteLine("Enter Token Request Endpoint:");
264+
config.AuthInfo.TokenRequestEndpoint = Console.ReadLine();
265+
Console.WriteLine();
266+
}
267+
212268
while (string.IsNullOrEmpty(config.AuthInfo.ClientId))
213269
{
214270
Console.WriteLine("Enter API Client ID:");
@@ -223,14 +279,14 @@ private static GenConfig CheckOptions(GenConfig config)
223279
Console.WriteLine();
224280
}
225281

226-
while (string.IsNullOrEmpty(config.AuthInfo.Username))
282+
while (string.IsNullOrEmpty(config.AuthInfo.Username) && config.AuthInfo.AuthMethod == AuthInfo.AuthMethodType.UsernamePassword)
227283
{
228284
Console.WriteLine("Enter API username:");
229285
config.AuthInfo.Username = Console.ReadLine();
230286
Console.WriteLine();
231287
}
232288

233-
while (string.IsNullOrEmpty(config.AuthInfo.Password))
289+
while (string.IsNullOrEmpty(config.AuthInfo.Password) && config.AuthInfo.AuthMethod == AuthInfo.AuthMethodType.UsernamePassword)
234290
{
235291
Console.WriteLine("Enter API password:");
236292
config.AuthInfo.Password = Console.ReadLine();
@@ -338,8 +394,19 @@ private static async Task<ForceClient> Login(GenConfig config)
338394
AuthenticationClient auth = new AuthenticationClient(config.AuthInfo.ApiVersion);
339395
try
340396
{
341-
await auth.UsernamePasswordAsync(config.AuthInfo.ClientId, config.AuthInfo.ClientSecret,
342-
config.AuthInfo.Username, config.AuthInfo.Password, config.AuthInfo.TokenRequestEndpoint);
397+
switch (config.AuthInfo.AuthMethod)
398+
{
399+
case AuthInfo.AuthMethodType.UsernamePassword:
400+
await auth.UsernamePasswordAsync(config.AuthInfo.ClientId, config.AuthInfo.ClientSecret,
401+
config.AuthInfo.Username, config.AuthInfo.Password, config.AuthInfo.TokenRequestEndpoint);
402+
break;
403+
case AuthInfo.AuthMethodType.ClientCredentials:
404+
await auth.ClientCredentialsAsync(config.AuthInfo.ClientId, config.AuthInfo.ClientSecret,
405+
config.AuthInfo.TokenRequestEndpoint);
406+
break;
407+
default:
408+
throw new ArgumentOutOfRangeException(nameof(config.AuthInfo.AuthMethod), $"authMethodInt is out of range, value: {(int)config.AuthInfo.AuthMethod}");
409+
}
343410

344411
Console.WriteLine("Connected to Salesforce");
345412
}
@@ -499,7 +566,7 @@ public static async Task<string> GenClass(ForceClient client, string objectName,
499566
if (field.Custom && !config.IncludeCustom)
500567
{
501568
continue;
502-
}
569+
}
503570

504571
gen.AppendLine("\t\t///<summary>");
505572
gen.AppendLine("\t\t/// " + WebUtility.HtmlEncode(field.Label));

src/NetCoreForce.ModelGenerator/README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# NetCoreForce.ModelGenerator
22

3-
Generates model classes according to your enviroment, optionally including any custom objects or fields. One file per class, named [ClassName].cs
3+
Generates model classes according to your environment, optionally including any custom objects or fields. One file per class, named [ClassName].cs
44

55
This is packaged as a custom .NET CLI tool. You can add it via
66
```
@@ -69,15 +69,16 @@ However, if you choose to save the config file, be careful with it as it does co
6969
```json
7070
{
7171
"comment": "Example config file - Make a copy of this file named modegenerator_config.json with your login info",
72-
"AuthInfo": {
72+
"AuthInfo": {
7373
"clientId": "your_client_id",
7474
"clientSecret": "your_client_secret",
7575
"username": "username",
7676
"password": "password",
77-
"apiVersion": "v57.0",
77+
"apiVersion": "v64.0",
7878
"authorizationEndpoint": "https://login.salesforce.com/services/oauth2/authorize",
7979
"tokenRequestEndpoint": "https://login.salesforce.com/services/oauth2/token",
80-
"tokenRevocationEndpoint": "https://login.salesforce.com/services/oauth2/revoke"
80+
"tokenRevocationEndpoint": "https://login.salesforce.com/services/oauth2/revoke",
81+
"authMethod": 1
8182
},
8283
"OutputDirectory": null,
8384
"Objects": [
42 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)