-
-
Notifications
You must be signed in to change notification settings - Fork 348
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge #2266 User interfaces for auth tokens
- Loading branch information
Showing
15 changed files
with
665 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using CommandLine; | ||
using CommandLine.Text; | ||
using log4net; | ||
|
||
namespace CKAN.CmdLine | ||
{ | ||
/// <summary> | ||
/// Subcommand for managing authentication tokens | ||
/// </summary> | ||
public class AuthToken : ISubCommand | ||
{ | ||
/// <summary> | ||
/// Initialize the subcommand | ||
/// </summary> | ||
public AuthToken() { } | ||
|
||
/// <summary> | ||
/// Run the subcommand | ||
/// </summary> | ||
/// <param name="unparsed">Command line parameters not yet handled by parser</param> | ||
/// <returns> | ||
/// Exit code | ||
/// </returns> | ||
public int RunSubCommand(SubCommandOptions unparsed) | ||
{ | ||
string[] args = unparsed.options.ToArray(); | ||
int exitCode = Exit.OK; | ||
|
||
Parser.Default.ParseArgumentsStrict(args, new AuthTokenSubOptions(), (string option, object suboptions) => | ||
{ | ||
if (!string.IsNullOrEmpty(option) && suboptions != null) | ||
{ | ||
CommonOptions options = (CommonOptions)suboptions; | ||
user = new ConsoleUser(options.Headless); | ||
manager = new KSPManager(user); | ||
exitCode = options.Handle(manager, user); | ||
if (exitCode == Exit.OK) | ||
{ | ||
switch (option) | ||
{ | ||
case "list": | ||
exitCode = listAuthTokens(options); | ||
break; | ||
case "add": | ||
exitCode = addAuthToken((AddAuthTokenOptions)options); | ||
break; | ||
case "remove": | ||
exitCode = removeAuthToken((RemoveAuthTokenOptions)options); | ||
break; | ||
} | ||
} | ||
} | ||
}, () => { exitCode = MainClass.AfterHelp(); }); | ||
return exitCode; | ||
} | ||
|
||
private int listAuthTokens(CommonOptions opts) | ||
{ | ||
List<string> hosts = new List<string>(Win32Registry.GetAuthTokenHosts()); | ||
if (hosts.Count > 0) | ||
{ | ||
int longestHostLen = hostHeader.Length; | ||
int longestTokenLen = tokenHeader.Length; | ||
foreach (string host in hosts) | ||
{ | ||
longestHostLen = Math.Max(longestHostLen, host.Length); | ||
string token; | ||
if (Win32Registry.TryGetAuthToken(host, out token)) | ||
{ | ||
longestTokenLen = Math.Max(longestTokenLen, token.Length); | ||
} | ||
} | ||
// Create format string: {0,-longestHostLen} {1,-longestTokenLen} | ||
string fmt = string.Format("{0}0,-{2}{1} {0}1,-{3}{1}", | ||
"{", "}", longestHostLen, longestTokenLen); | ||
user.RaiseMessage(fmt, hostHeader, tokenHeader); | ||
user.RaiseMessage(fmt, | ||
new string('-', longestHostLen), | ||
new string('-', longestTokenLen) | ||
); | ||
foreach (string host in hosts) | ||
{ | ||
string token; | ||
if (Win32Registry.TryGetAuthToken(host, out token)) | ||
{ | ||
user.RaiseMessage(fmt, host, token); | ||
} | ||
} | ||
} | ||
return Exit.OK; | ||
} | ||
|
||
private int addAuthToken(AddAuthTokenOptions opts) | ||
{ | ||
if (Uri.CheckHostName(opts.host) != UriHostNameType.Unknown) | ||
{ | ||
Win32Registry.SetAuthToken(opts.host, opts.token); | ||
} | ||
else | ||
{ | ||
user.RaiseError("Invalid host name: {0}", opts.host); | ||
} | ||
return Exit.OK; | ||
} | ||
|
||
private int removeAuthToken(RemoveAuthTokenOptions opts) | ||
{ | ||
Win32Registry.SetAuthToken(opts.host, null); | ||
return Exit.OK; | ||
} | ||
|
||
private const string hostHeader = "Host"; | ||
private const string tokenHeader = "Token"; | ||
|
||
private IUser user; | ||
private KSPManager manager; | ||
private static readonly ILog log = LogManager.GetLogger(typeof(AuthToken)); | ||
} | ||
|
||
internal class AuthTokenSubOptions : VerbCommandOptions | ||
{ | ||
[VerbOption("list", HelpText = "List auth tokens")] | ||
public CommonOptions ListOptions { get; set; } | ||
|
||
[VerbOption("add", HelpText = "Add an auth token")] | ||
public AddAuthTokenOptions AddOptions { get; set; } | ||
|
||
[VerbOption("remove", HelpText = "Delete an auth token")] | ||
public RemoveAuthTokenOptions RemoveOptions { get; set; } | ||
|
||
[HelpVerbOption] | ||
public string GetUsage(string verb) | ||
{ | ||
HelpText ht = HelpText.AutoBuild(this, verb); | ||
// Add a usage prefix line | ||
ht.AddPreOptionsLine(" "); | ||
if (string.IsNullOrEmpty(verb)) | ||
{ | ||
ht.AddPreOptionsLine("ckan authtoken - Manage authentication tokens"); | ||
ht.AddPreOptionsLine($"Usage: ckan authtoken <command> [options]"); | ||
} | ||
else | ||
{ | ||
ht.AddPreOptionsLine("authtoken " + verb + " - " + GetDescription(verb)); | ||
switch (verb) | ||
{ | ||
case "add": | ||
ht.AddPreOptionsLine($"Usage: ckan authtoken {verb} [options] host token"); | ||
break; | ||
case "remove": | ||
ht.AddPreOptionsLine($"Usage: ckan authtoken {verb} [options] host"); | ||
break; | ||
case "list": | ||
ht.AddPreOptionsLine($"Usage: ckan authtoken {verb} [options]"); | ||
break; | ||
} | ||
} | ||
return ht; | ||
} | ||
} | ||
|
||
internal class AddAuthTokenOptions : CommonOptions | ||
{ | ||
[ValueOption(0)] public string host { get; set; } | ||
[ValueOption(1)] public string token { get; set; } | ||
} | ||
|
||
internal class RemoveAuthTokenOptions : CommonOptions | ||
{ | ||
[ValueOption(0)] public string host { get; set; } | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
using System; | ||
using CKAN.ConsoleUI.Toolkit; | ||
|
||
namespace CKAN.ConsoleUI { | ||
|
||
/// <summary> | ||
/// Popup for adding a new authentication token. | ||
/// </summary> | ||
public class AuthTokenAddDialog : ConsoleDialog { | ||
|
||
/// <summary> | ||
/// Initialize the popup. | ||
/// </summary> | ||
public AuthTokenAddDialog() : base() | ||
{ | ||
CenterHeader = () => "Create Authentication Key"; | ||
|
||
int top = (Console.WindowHeight - height) / 2; | ||
SetDimensions(6, top, -6, top + height - 1); | ||
|
||
int l = GetLeft(), | ||
r = GetRight(), | ||
t = GetTop(), | ||
b = GetBottom(); | ||
|
||
AddObject(new ConsoleLabel( | ||
l + 2, t + 2, l + 2 + labelW, | ||
() => "Host:", | ||
() => ConsoleTheme.Current.PopupBg, | ||
() => ConsoleTheme.Current.PopupFg | ||
)); | ||
|
||
hostEntry = new ConsoleField( | ||
l + 2 + labelW + wPad, t + 2, r - 3 | ||
) { | ||
GhostText = () => "<Enter a host name>" | ||
}; | ||
AddObject(hostEntry); | ||
|
||
AddObject(new ConsoleLabel( | ||
l + 2, t + 4, l + 2 + labelW, | ||
() => "Token:", | ||
() => ConsoleTheme.Current.PopupBg, | ||
() => ConsoleTheme.Current.PopupFg | ||
)); | ||
|
||
tokenEntry = new ConsoleField( | ||
l + 2 + labelW + wPad, t + 4, r - 3 | ||
) { | ||
GhostText = () => "<Enter an authentication token>" | ||
}; | ||
AddObject(tokenEntry); | ||
|
||
AddTip("Esc", "Cancel"); | ||
AddBinding(Keys.Escape, (object sender) => false); | ||
|
||
AddTip("Enter", "Accept", validKey); | ||
AddBinding(Keys.Enter, (object sender) => { | ||
if (validKey()) { | ||
Win32Registry.SetAuthToken(hostEntry.Value, tokenEntry.Value); | ||
return false; | ||
} else { | ||
// Don't close window on Enter unless adding a key | ||
return true; | ||
} | ||
}); | ||
} | ||
|
||
private bool validKey() | ||
{ | ||
string token; | ||
return hostEntry.Value.Length > 0 | ||
&& tokenEntry.Value.Length > 0 | ||
&& Uri.CheckHostName(hostEntry.Value) != UriHostNameType.Unknown | ||
&& !Win32Registry.TryGetAuthToken(hostEntry.Value, out token); | ||
} | ||
|
||
private ConsoleField hostEntry; | ||
private ConsoleField tokenEntry; | ||
|
||
private const int wPad = 2; | ||
private const int labelW = 6; | ||
private const int height = 7; | ||
} | ||
|
||
} |
Oops, something went wrong.