Skip to content

Commit 355ac2f

Browse files
committed
Version 1.0.2.2
1 parent b958498 commit 355ac2f

File tree

55 files changed

+339
-187
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+339
-187
lines changed

Docs/Configuration.md

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ The Example project on Github has extended the configuration and will therefore
1818
### CodeEditor
1919
The path to your favorite code editor, that you could start with the ConfigCommand, this command is shipping with the creation of new PowerCommand Visual Studio solution.
2020

21+
### Command design overrides
22+
You can override some of the values that are set in the **PowerCommandsDesignAttribute**, read more about this [here](OverrideDesignAttribute.md)
23+
2124
### Components
2225
Here you declare those dll components that the Core framework will use to find all available Commands.
2326

@@ -45,10 +48,21 @@ Enable or disable the display of diagnostic output.
4548
version: 1.0
4649
configuration:
4750
showDiagnosticInformation: false
48-
defaultCommand: commands
51+
defaultCommand: commands
4952
codeEditor: C:\Users\%USERNAME%\AppData\Local\Programs\Microsoft VS Code\Code.exe
5053
repository: https://github.com/PowerCommands/PowerCommands2022
51-
backupPath: ..\..\..\..\Core\PainKiller.PowerCommands.Core\
54+
backupPath: ..\..\..\..\..\
55+
defaultGitRepositoryPath: C:\repos\github\PowerCommands2022
56+
commandDesignOverrides:
57+
- name: demo
58+
description: "Demo command just to try out how you could use the input, do not forget the MANDATORY option, will trigger a validation error otherwise! ;-)\n That is because the option name is typed with UPPERCASE letters, useful when you want a mandatory option\n The pause option on the other hand starts with a ! symbol meaning that if you add the --pause option you must also give it a value, an integer in this case."
59+
arguments: "!<url>"
60+
quotes: "!<local file path>"
61+
options: "!MANDATORY|!pause"
62+
examples: "//Must provide the MANDATORY option, will trigger a validation error otherwise|demo MANDATORY|//Test the pause service|demo --pause 5 MANDATORY"
63+
suggestions: ""
64+
useAsync: true
65+
showElapsedTime: false
5266
metadata:
5367
name: Test
5468
description: En exempelbeskrivning
@@ -60,24 +74,22 @@ configuration:
6074
component: PainKiller.SerilogExtensions.dll
6175
checksum: 13b9944b55efe60362720a679f17a22c
6276
name: Serialog
63-
components:
77+
components:
78+
- component: PainKiller.PowerCommands.MyExampleCommands.dll
79+
checksum: a2df61ea89e4f9ec265d921bfad87193
80+
name: My Example Command
6481
- component: PainKiller.PowerCommands.Core.dll
6582
checksum: 4f04313db8e67b2bc4b059c478a900af
6683
name: PainKiller Core
67-
- component: PainKiller.PowerCommands.MyExampleCommands.dll
68-
checksum: a2df61ea89e4f9ec265d921bfad87193
69-
name: My Example Command
70-
secret:
71-
secrets:
72-
- name: localDB
73-
options:
74-
target: User
84+
bookmark:
85+
bookmarks:
86+
- name: Program
87+
path: C:\Program Files
88+
index: 0
7589
environment:
7690
variables:
77-
- name: VAULT_NAME
78-
environmentVariableTarget: User
79-
- name: CLIENT_ID
80-
environmentVariableTarget: User
91+
- name: OS
92+
environmentVariableTarget: Machine
8193
```
8294

8395
Next step could be to [Extend your configuration](ExtendYourConfiguration.md)
@@ -86,6 +98,8 @@ Read more about:
8698

8799
[Design your Command](Design_command.md)
88100

101+
[Override Design attribute](OverrideDesignAttribute.md)
102+
89103
[Documentation index](DocumentationIndexDB.md)
90104

91105
[Back to start](https://github.com/PowerCommands/PowerCommands2022/blob/main/Docs/README.md)

Docs/OverrideDesignAttribute.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Override PowerCommandsDesign Attribute
2+
## Edit PowerCommandsConfiguration.yaml file
3+
In some cases you may want to override the **PowerCommandsDesignAttribute** a typical use case could be that you want a different kind of suggestions or add suggestions to a certain command in your implementation but you do not want to change the source code and recompile it.
4+
Then this feature to override it in configuration comes in handy.
5+
6+
![Alt text](images/override_design_attribute.png?raw=true "Attribute")
7+
8+
The image above illustrates how it could look like, the table below shows those properties of the design attribute you can override.
9+
### PLEASE NOTE
10+
In the configuration file you just add those properties you want to override, the **name** property is not a property of the design attribute, it is the name of the command that you are overriding the design attribute for.
11+
12+
| Property Name | Data Type |
13+
|------------------|-----------|
14+
| **name** | string |
15+
| description | string |
16+
| arguments | string |
17+
| quotes | string |
18+
| options | string |
19+
| examples | string |
20+
| suggestions | string |
21+
| useAsync | boolean |
22+
| showElapsedTime | boolean |
23+
24+
### Read more about:
25+
26+
[PowerCommandDesign Attribute](PowerCommandDesignAttribute.md)
27+
28+
[Design your Command](Design_command.md)
29+
30+
[Input](Input.md)
31+
32+
[options](options.md)
33+
34+
[Back to start](https://github.com/PowerCommands/PowerCommands2022/blob/main/Docs/README.md)
250 KB
Loading

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ https://github.com/PowerCommands/PowerCommands2022/assets/102176789/d8ad92f0-93a
2929

3030
[Power Commands Design attribute](Docs/PowerCommandDesignAttribute.md)
3131

32+
[Override Design attribute in config file](Docs/OverrideDesignAttribute.md)
33+
3234
[Patterns to use the Toolbar with dynamic content](Docs/PowerCommandToolbarAttribute.md)
3335

3436
[Command base class](Docs/CommandBase.md)

Templates/PowerCommands.zip

8.89 KB
Binary file not shown.

Templates/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ I recommend you to use the option ```Place solution in the same directory``` som
1414

1515

1616
# What is new?
17+
## Version 1.0.2.2
18+
**Released 2023-09-09**
19+
- Some of the values set with ```PowerCommandsDesignAttribute``` is now possible to override in the **PowerCommandsConfiguration.yaml** file, look at the example that comes with the VS template or read the documentation on GitHub.
20+
- Removed checksum control at startup as it achieves no really security purpose.
21+
- Minor fixes in core dialogs.
22+
1723
## Version 1.0.2.1
1824
**Released 2023-07-24**
1925
- ```ReadLineService``` now has two static events by the ```OpenShortCutPressed``` Occurs when user press [`Ctrl + O`], ```SaveShortCutPressed``` Occurs when user press [`Ctrl + S`].

Templates/src/Core/PainKiller.PowerCommands.Core/BASECLASSES/CommandBase.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public virtual bool InitializeAndValidateInput(ICommandLineInput input, PowerCom
2929
if (IPowerCommandServices.DefaultInstance!.DefaultConsoleService.GetType().Name != _console.GetType().Name) _console = IPowerCommandServices.DefaultInstance.DefaultConsoleService;
3030
Input = input;
3131
DesignAttribute = designAttribute;
32-
IPowerCommandServices.DefaultInstance.Diagnostic.ShowElapsedTime = DesignAttribute.ShowElapsedTime;
32+
IPowerCommandServices.DefaultInstance.Diagnostic.ShowElapsedTime = DesignAttribute.ShowElapsedTime.GetValueOrDefault();
3333
var validationManager = new InputValidationManager(this, input, WriteError);
3434
var result = validationManager.ValidateAndInitialize();
3535
if (result.Options.Count > 0) Options.AddRange(result.Options);
@@ -70,8 +70,10 @@ public virtual void RunCompleted()
7070
#endregion
7171

7272
#region RunResult
73-
protected RunResult Ok() => new(this, Input, _ouput.ToString(), RunResultStatus.Ok);
74-
protected RunResult Quit() => new(this, Input, _ouput.ToString(), RunResultStatus.Quit);
73+
protected RunResult Ok(string message) => new(this, Input, $"{message} {_ouput}", RunResultStatus.Ok);
74+
protected RunResult Ok() => Ok(_ouput.ToString());
75+
protected RunResult Quit() => Quit(_ouput.ToString());
76+
protected RunResult Quit(string message) => new(this, Input, $"{message} {_ouput}", RunResultStatus.Ok);
7577
protected RunResult BadParameterError(string output) => new(this, Input, output, RunResultStatus.ArgumentError);
7678
protected RunResult ExceptionError(string output) => new(this, Input, output, RunResultStatus.ExceptionThrown);
7779
protected RunResult ContinueWith(string rawInput) => new(this, Input, _ouput.ToString(), RunResultStatus.ExceptionThrown, rawInput);

Templates/src/Core/PainKiller.PowerCommands.Core/COMMANDS/SecretCommand.cs

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
using PainKiller.PowerCommands.Security.Services;
22

33
namespace $safeprojectname$.Commands;
4+
45
[PowerCommandDesign(description: "Get, creates, removes or view secrets, first you need to configure your encryption key with initialize argument",
5-
options: "initialize|configuration|create|get|remove|salt",
6-
disableProxyOutput: true,
7-
example: "//View all declared secrets|secret|//Get the decrypted value of named secret|secret --get \"mycommand-pass\"|secret --create \"mycommand-pass\"|secret --remove \"mycommand-pass\"|//Initialize your machine with a new encryption key (stops if this is already done)|secret --initialize")]
6+
options: "create|initialize|configuration|remove|salt",
7+
disableProxyOutput: true,
8+
example: "//View all declared secrets|secret|secret --create \"mycommand-pass\"|secret --remove \"mycommand-pass\"|//Initialize your machine with a new encryption key (stops if this is already done)|secret --initialize")]
89
public class SecretCommand : CommandBase<CommandsConfiguration>
910
{
1011
public SecretCommand(string identifier, CommandsConfiguration configuration) : base(identifier, configuration) { }
@@ -13,7 +14,6 @@ public override RunResult Run()
1314
if (Input.HasOption("initialize")) return Init();
1415
if (Input.HasOption("")) return CheckEncryptConfiguration();
1516
if (Input.HasOption("salt")) return Salt();
16-
if (Input.HasOption("get")) return Get();
1717
if (Input.HasOption("create")) return Create();
1818
if (Input.HasOption("remove")) return Remove();
1919
if ((Input.Arguments.Length + Input.Quotes.Length < 2) && Input.Arguments.Length > 0) throw new MissingFieldException("Two parameters must be provided");
@@ -45,8 +45,8 @@ private RunResult Salt()
4545

4646
private RunResult Init()
4747
{
48-
var firstHalf = IEncryptionService.GetRandomSalt();;
49-
var secondHalf = IEncryptionService.GetRandomSalt();;
48+
var firstHalf = IEncryptionService.GetRandomSalt();
49+
var secondHalf = IEncryptionService.GetRandomSalt();
5050
Environment.SetEnvironmentVariable("_encryptionManager", firstHalf, EnvironmentVariableTarget.User);
5151
var securityConfig = new SecurityConfiguration { Encryption = new EncryptionConfiguration { SharedSecretEnvironmentKey = "_encryptionManager", SharedSecretSalt = secondHalf } };
5252
var fileName = Path.Combine(ConfigurationGlobals.ApplicationDataFolder, ConfigurationGlobals.SecurityFileName);
@@ -57,31 +57,18 @@ private RunResult Init()
5757

5858
private RunResult List()
5959
{
60-
if (Configuration.Secret.Secrets == null) return Ok();
6160
foreach (var secret in Configuration.Secret.Secrets) ConsoleService.Service.WriteObjectDescription($"{GetType().Name}", secret.Name, $"{string.Join(',', secret.Options.Keys)}");
6261
return Ok();
6362
}
64-
private RunResult Get()
65-
{
66-
var name = Input.SingleQuote;
67-
var secret = Configuration.Secret.Secrets.FirstOrDefault(s => s.Name.ToLower() == name.ToLower());
68-
if (secret == null) return BadParameterError($"No secret with name \"{name}\" found.");
69-
70-
var val = SecretService.Service.GetSecret(name, secret.Options, EncryptionService.Service.DecryptString);
71-
ConsoleService.Service.WriteObjectDescription($"{GetType().Name}", name, val);
72-
73-
return Ok();
74-
}
7563
private RunResult Create()
7664
{
7765
var name = Input.SingleQuote;
7866
var password = DialogService.SecretPromptDialog("Enter secret:");
7967
if (string.IsNullOrEmpty(password)) return BadParameterError("Passwords do not match");
80-
68+
8169
var secret = new SecretItemConfiguration { Name = name };
8270
var val = SecretService.Service.SetSecret(name, password, secret.Options, EncryptionService.Service.EncryptString);
83-
84-
Configuration.Secret ??= new();
71+
8572
Configuration.Secret.Secrets ??= new();
8673
Configuration.Secret.Secrets.Add(secret);
8774
ConfigurationService.Service.SaveChanges(Configuration);

Templates/src/Core/PainKiller.PowerCommands.Core/EXTENSIONS/ReflectionExtensions.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,12 @@ public static List<PropertyInfo> GetProperties(this Type instanceType)
4343
public static PowerCommandDesignAttribute GetPowerCommandAttribute(this IConsoleCommand command)
4444
{
4545
var attributes = command.GetType().GetCustomAttributes(typeof(PowerCommandDesignAttribute), inherit: false);
46-
return attributes.Length == 0 ? new PowerCommandDesignAttribute(description:"Command have no description attribute") : (PowerCommandDesignAttribute)attributes.First();
46+
var retVal = attributes.Length == 0 ? new PowerCommandDesignAttribute(description:"Command have no description attribute") : (PowerCommandDesignAttribute)attributes.First();
47+
var cfgAttr = ReflectionService.CommandDesignOverrides.FirstOrDefault(c => c.Name == command.Identifier);
48+
if (cfgAttr == null) return retVal;
49+
//Not all values must be set in config so we have to create a new merged cfgDesign where does values that are not set is taken from the runtime attribute values
50+
var cfgDesignMerged = new PowerCommandDesignConfiguration(cfgAttr, retVal);
51+
return new PowerCommandDesignAttribute(description: cfgDesignMerged.Description, overrideHelpOption: retVal.OverrideHelpOption, arguments: cfgDesignMerged.Arguments, quotes: cfgDesignMerged.Quotes, example: cfgDesignMerged.Examples, options: cfgDesignMerged.Options, secrets: retVal.Secrets, suggestions: cfgDesignMerged.Suggestions, useAsync: cfgDesignMerged.UseAsync.GetValueOrDefault(), disableProxyOutput: retVal.DisableProxyOutput, showElapsedTime: cfgDesignMerged.ShowElapsedTime.GetValueOrDefault());
4752
}
4853
public static PowerCommandsToolbarAttribute? GetToolbarAttribute(this IConsoleCommand command)
4954
{

Templates/src/Core/PainKiller.PowerCommands.Core/MANAGERS/ComponentManager.cs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,6 @@ public ComponentManager(TConfiguration configuration, IDiagnosticManager diagnos
88
_configuration = configuration;
99
_diagnostic = diagnostic;
1010
}
11-
public bool ValidateConfigurationWithComponents()
12-
{
13-
var retVal = true;
14-
var components = typeof(TConfiguration).GetPropertiesOfT<BaseComponentConfiguration>().Select(c => c.GetValue(_configuration) as BaseComponentConfiguration).ToList();
15-
if(_configuration.Components.Count > 0) components.AddRange(_configuration.Components);
16-
_diagnostic.Header("\nChecksum validations:");
17-
foreach (var component in components)
18-
{
19-
if(component is null) continue;
20-
var fileCheckSum = new FileChecksum(component.Component);
21-
var validateCheckSum = fileCheckSum.CompareFileChecksum(component.Checksum) ? "Valid" : "Not valid";
22-
if(validateCheckSum == "Not valid") retVal = false;
23-
_diagnostic.Message($"{component.Name} Checksum {fileCheckSum.Mde5Hash} {validateCheckSum}");
24-
}
25-
return retVal;
26-
}
2711
public List<BaseComponentConfiguration> AutofixConfigurationComponents<T>(T configuration) where T : CommandsConfiguration, new()
2812
{
2913
var retVal = new List<BaseComponentConfiguration>();

0 commit comments

Comments
 (0)