Skip to content

Commit c33ff2a

Browse files
committed
Better error handling, AuthToken API version, Edit user password
1 parent 16ed464 commit c33ff2a

Some content is hidden

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

63 files changed

+338
-788
lines changed

UiPath.PowerShell.Tests/Util/PowershellFactory.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ public static Cmdlet CreateCmdlet(Runspace rss)
2828
return cmdlet;
2929
}
3030

31-
public static void AuthenticateSession(Runspace rss, string url, string tenantName, string userName, string password)
31+
public static void AuthenticateSession(Runspace rss, string url, string tenantName, string userName, string password, TestContext testContext)
3232
{
3333
using (var cmdlet = CreateCmdlet(rss))
3434
{
35+
TestClassBase.HookCmdlet(cmdlet, testContext);
3536
cmdlet.AddCommand(UiPathStrings.GetUiPathAuthToken)
3637
.AddParameter(UiPathStrings.URL, url)
3738
.AddParameter(UiPathStrings.Username, userName)
@@ -54,7 +55,7 @@ public static Runspace CreateAuthenticatedSession(TestContext testContext)
5455
try
5556
{
5657
runspace.Open();
57-
AuthenticateSession(runspace, testSettings.URL, testSettings.TenantName, testSettings.UserName, testSettings.Password);
58+
AuthenticateSession(runspace, testSettings.URL, testSettings.TenantName, testSettings.UserName, testSettings.Password, testContext);
5859
}
5960
catch
6061
{

UiPath.PowerShell.Tests/Util/TestClassBase.cs

+8-8
Original file line numberDiff line numberDiff line change
@@ -16,38 +16,38 @@ public class TestClassBase
1616

1717
public Collection<T> Invoke<T>(Cmdlet cmdlet)
1818
{
19-
HookCmdlet(cmdlet);
19+
HookCmdlet(cmdlet, TestContext);
2020
return cmdlet.Invoke<T>();
2121
}
2222

2323
public Collection<PSObject> Invoke(Cmdlet cmdlet)
2424
{
25-
HookCmdlet(cmdlet);
25+
HookCmdlet(cmdlet, TestContext);
2626
return cmdlet.Invoke();
2727
}
2828

29-
public void HookCmdlet(Cmdlet cmdlet)
29+
public static void HookCmdlet(Cmdlet cmdlet, TestContext testContext)
3030
{
3131
var streams = cmdlet.Streams;
3232
streams.Debug.DataAdded += (sender, e) =>
3333
{
34-
TestContext.WriteLine("DEBUG: {0}", streams.Debug[e.Index].Message);
34+
testContext.WriteLine("DEBUG: {0}", streams.Debug[e.Index].Message);
3535
};
3636
streams.Error.DataAdded += (sender, e) =>
3737
{
38-
TestContext.WriteLine("ERROR: {0}:{1} {2}", streams.Error[e.Index].Exception?.GetType().Name, streams.Error[e.Index].Exception?.Message, streams.Error[e.Index].FullyQualifiedErrorId);
38+
testContext.WriteLine("ERROR: {0}:{1} {2}", streams.Error[e.Index].Exception?.GetType().Name, streams.Error[e.Index].Exception?.Message, streams.Error[e.Index].FullyQualifiedErrorId);
3939
};
4040
streams.Information.DataAdded += (sender, e) =>
4141
{
42-
TestContext.WriteLine("INFO: {0}", streams.Information[e.Index].MessageData);
42+
testContext.WriteLine("INFO: {0}", streams.Information[e.Index].MessageData);
4343
};
4444
streams.Warning.DataAdded += (sender, e) =>
4545
{
46-
TestContext.WriteLine("WARN: {0} {1}", streams.Warning[e.Index].Message, streams.Warning[e.Index].FullyQualifiedWarningId);
46+
testContext.WriteLine("WARN: {0} {1}", streams.Warning[e.Index].Message, streams.Warning[e.Index].FullyQualifiedWarningId);
4747
};
4848
streams.Verbose.DataAdded += (sender, e) =>
4949
{
50-
TestContext.WriteLine("VERBOSE: {0}", streams.Verbose[e.Index].Message);
50+
testContext.WriteLine("VERBOSE: {0}", streams.Verbose[e.Index].Message);
5151
};
5252
}
5353
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.Management.Automation;
2+
using UiPath.PowerShell.Util;
3+
4+
namespace UiPath.PowerShell.Cmdlets
5+
{
6+
/// <summary>
7+
/// <para name="synopsis">Clears the Orchestrator authentication token from the Powershell session.</para>
8+
/// </summary>
9+
[Cmdlet(VerbsCommon.Clear, Nouns.AuthToken)]
10+
public class ClearAuthToken: UiPathCmdlet
11+
{
12+
protected override void ProcessRecord()
13+
{
14+
AuthenticatedCmdlet.SetAuthToken(null);
15+
}
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
using Newtonsoft.Json.Linq;
2+
using System;
3+
using System.Management.Automation;
4+
using System.Net.Http;
5+
using UiPath.PowerShell.Models;
6+
using UiPath.PowerShell.Util;
7+
using UiPath.Web.Client;
8+
using UiPath.Web.Client.Models;
9+
10+
namespace UiPath.PowerShell.Cmdlets
11+
{
12+
[Cmdlet(VerbsData.Edit, Nouns.UserPassword)]
13+
public class EditUserPassword : AuthenticatedCmdlet
14+
{
15+
16+
[Parameter(Mandatory = true, ParameterSetName = "Id")]
17+
public long Id { get; set; }
18+
19+
[Parameter(Mandatory = true, Position = 0, ValueFromPipeline = true, ParameterSetName = "User")]
20+
public User User { get; set; }
21+
22+
[Parameter(Mandatory = true)]
23+
public string CurrentPassword { get; set; }
24+
25+
[Parameter(Mandatory = true)]
26+
public string NewPassword { get; set; }
27+
28+
protected override void ProcessRecord()
29+
{
30+
if (InternalAuthToken.Authenticated)
31+
{
32+
ChangeAuthenticatedUser();
33+
}
34+
else
35+
{
36+
ChangeUnauthenticatedUser();
37+
}
38+
}
39+
40+
private void ChangeAuthenticatedUser()
41+
{
42+
HandleHttpOperationException(() => Api.Users.ChangePasswordById(User?.Id ?? Id, new ChangePasswordDto
43+
{
44+
CurrentPassword = CurrentPassword,
45+
NewPassword = NewPassword
46+
}));
47+
}
48+
49+
/// <summary>
50+
/// This is the method to update the initial password of a new deployment (admin must change password at first login)
51+
/// </summary>
52+
private void ChangeUnauthenticatedUser()
53+
{
54+
55+
var dto = new ChangePasswordAccountDto
56+
{
57+
UserId = User?.Id ?? Id,
58+
CurrentPassword = CurrentPassword,
59+
NewPassword = NewPassword
60+
};
61+
62+
string responseContent = null;
63+
64+
HandleHttpOperationException(() => Api.MakeHttpRequest(HttpMethod.Post, "/account/changepassword", dto, out responseContent, out var headers));
65+
66+
// On success Orchestrator returns 200 OK and no payload
67+
// On error it returns 200 OK and payload with the error...
68+
// {"result":null,"targetUrl":null,"success":false,"error":{"code":400,"message":"Incorrect password.","details":null,"validationErrors":null},"unAuthorizedRequest":false,"__abp":true}
69+
if (!String.IsNullOrWhiteSpace(responseContent))
70+
{
71+
var jo = JObject.Parse(responseContent);
72+
var errorCode = jo["error"]?["code"].Value<int>();
73+
var errorMessage = jo["error"]?["message"].Value<string>();
74+
WriteError(errorCode, errorMessage);
75+
}
76+
}
77+
}
78+
}

UiPath.PowerShell/Cmdlets/GetAuthToken.cs

+54-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using Microsoft.Rest;
22
using System;
3+
using System.Linq;
34
using System.Management.Automation;
5+
using System.Net.Http;
46
using UiPath.PowerShell.Models;
57
using UiPath.PowerShell.Util;
68
using UiPath.Web.Client;
@@ -29,6 +31,7 @@ public class GetAuthToken: UiPathCmdlet
2931
{
3032
private const string UserPasswordSet = "UserPassword";
3133
private const string WindowsCredentialsSet = "WindowsCredentials";
34+
private const string UnauthenticatedSet = "Unauthenticated";
3235

3336
[Parameter(Mandatory = true, Position = 0)]
3437
public string URL { get; set; }
@@ -45,34 +48,74 @@ public class GetAuthToken: UiPathCmdlet
4548
[Parameter(Mandatory = true, ParameterSetName = WindowsCredentialsSet)]
4649
public SwitchParameter WindowsCredentials { get; set; }
4750

51+
[Parameter(Mandatory = true, ParameterSetName = UnauthenticatedSet)]
52+
public SwitchParameter Unauthenticated { get; set; }
53+
4854
[Parameter]
4955
public SwitchParameter Session { get; set; }
5056

5157
protected override void ProcessRecord()
5258
{
53-
AuthToken authToken = null;
54-
if (ParameterSetName == UserPasswordSet)
59+
try
5560
{
56-
authToken = GetUserToken();
61+
AuthToken authToken = null;
62+
if (ParameterSetName == UserPasswordSet)
63+
{
64+
authToken = GetUserToken();
65+
}
66+
else if (ParameterSetName == WindowsCredentialsSet)
67+
{
68+
authToken = GetWindowsToken();
69+
}
70+
else if (ParameterSetName == UnauthenticatedSet)
71+
{
72+
authToken = GetUnauthenticatedToken();
73+
}
74+
75+
GetServerVersion(authToken);
76+
77+
if (Session.IsPresent)
78+
{
79+
AuthenticatedCmdlet.SetAuthToken(authToken);
80+
}
81+
82+
WriteObject(authToken);
5783
}
58-
else if (ParameterSetName == WindowsCredentialsSet)
84+
catch(Exception e)
5985
{
60-
authToken = GetWindowsToken();
86+
WriteVerbose(e.ToString());
6187
}
62-
if (Session.IsPresent)
88+
}
89+
90+
private void GetServerVersion(AuthToken authToken)
91+
{
92+
using (var api = AuthenticatedCmdlet.MakeApi(authToken))
6393
{
64-
AuthenticatedCmdlet.SetAuthToken(authToken);
94+
api.MakeHttpRequest(HttpMethod.Get, "/odata/$metadata", null, out var response, out var headers);
95+
if (headers.TryGetValues("api-supported-versions", out var values))
96+
{
97+
authToken.ApiVersion = values.First();
98+
}
6599
}
100+
}
66101

67-
WriteObject(authToken);
102+
private AuthToken GetUnauthenticatedToken()
103+
{
104+
return new AuthToken
105+
{
106+
URL = URL,
107+
WindowsCredentials = false,
108+
Authenticated = false
109+
};
68110
}
69111

70112
private AuthToken GetWindowsToken()
71113
{
72114
return new AuthToken
73115
{
74116
URL = URL,
75-
WindowsCredentials = true
117+
WindowsCredentials = true,
118+
Authenticated = true
76119
};
77120
}
78121

@@ -97,7 +140,8 @@ private AuthToken GetUserToken()
97140
{
98141
Token = token,
99142
URL = URL,
100-
WindowsCredentials = false
143+
WindowsCredentials = false,
144+
Authenticated = true
101145
};
102146

103147
}

UiPath.PowerShell/Cmdlets/Nouns.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ internal static class Nouns
55
internal const string UiPath = "UiPath";
66

77
internal const string Asset = UiPath + "Asset";
8-
internal const string Authentication = UiPath + "Authentication";
98
internal const string AuthToken = UiPath + "AuthToken";
109
internal const string Environment = UiPath + "Environment";
1110
internal const string EnvironmentRobot = UiPath + "EnvironmentRobot";
@@ -24,5 +23,6 @@ internal static class Nouns
2423
internal const string Tenant = UiPath + "Tenant";
2524
internal const string TimeZones = UiPath + "TimeZones";
2625
internal const string User = UiPath + "User";
26+
internal const string UserPassword = UiPath + "UserPassword";
2727
}
2828
}

UiPath.PowerShell/Cmdlets/SetAuthentication.cs renamed to UiPath.PowerShell/Cmdlets/SetAuthToken.cs

+6-8
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Management.Automation;
5-
using System.Text;
6-
using System.Threading.Tasks;
1+
using System.Management.Automation;
72
using UiPath.PowerShell.Models;
83
using UiPath.PowerShell.Util;
94

105
namespace UiPath.PowerShell.Cmdlets
116
{
12-
[Cmdlet(VerbsCommon.Set, Nouns.Authentication)]
13-
public class SetAuthentication: UiPathCmdlet
7+
/// <summary>
8+
/// <para name="synopsis">Sets the Powershell session Orchestrator authentication token.</para>
9+
/// </summary>
10+
[Cmdlet(VerbsCommon.Set, Nouns.AuthToken)]
11+
public class SetAuthToken: UiPathCmdlet
1412
{
1513
[Parameter(Mandatory = true, ParameterSetName = "AuthToken", Position = 0, ValueFromPipeline = true)]
1614
public AuthToken AuthToken { get; set; }

UiPath.PowerShell/Models/AuthToken.cs

+2
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@ public class AuthToken
1010
public string Token { get; internal set; }
1111

1212
public bool WindowsCredentials { get; internal set; }
13+
public bool Authenticated { get; internal set; }
14+
public string ApiVersion { get; internal set; }
1315
}
1416
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace UiPath.PowerShell.Models
2+
{
3+
internal class ChangePasswordAccountDto
4+
{
5+
public long UserId { get; set; }
6+
7+
public string CurrentPassword { get; set; }
8+
9+
public string NewPassword { get; set; }
10+
}
11+
}

UiPath.PowerShell/UiPath.PowerShell.csproj

+5-1
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,13 @@
7373
<Compile Include="Cmdlets\AddProcess.cs" />
7474
<Compile Include="Cmdlets\AddRobot.cs" />
7575
<Compile Include="Cmdlets\AddRole.cs" />
76+
<Compile Include="Cmdlets\ClearAuthToken.cs" />
7677
<Compile Include="Cmdlets\EditRoleUser.cs" />
7778
<Compile Include="Cmdlets\AddTenant.cs" />
7879
<Compile Include="Cmdlets\AddUser.cs" />
7980
<Compile Include="Cmdlets\EditQueueDefinition.cs" />
8081
<Compile Include="Cmdlets\EditRobot.cs" />
82+
<Compile Include="Cmdlets\EditUserPassword.cs" />
8183
<Compile Include="Cmdlets\GetPermission.cs" />
8284
<Compile Include="Cmdlets\GetRole.cs" />
8385
<Compile Include="Cmdlets\GetProcessSchedule.cs" />
@@ -108,9 +110,10 @@
108110
<Compile Include="Cmdlets\RemoveRole.cs" />
109111
<Compile Include="Cmdlets\RemoveTenant.cs" />
110112
<Compile Include="Cmdlets\RemoveUser.cs" />
111-
<Compile Include="Cmdlets\SetAuthentication.cs" />
113+
<Compile Include="Cmdlets\SetAuthToken.cs" />
112114
<Compile Include="Cmdlets\StartJob.cs" />
113115
<Compile Include="Cmdlets\StopJob.cs" />
116+
<Compile Include="Models\ChangePasswordAccountDto.cs" />
114117
<Compile Include="Models\Job.cs" />
115118
<Compile Include="Models\Permission.cs" />
116119
<Compile Include="Models\Role.cs" />
@@ -140,6 +143,7 @@
140143
<Link>Properties\GlobalAssemblyInfo.cs</Link>
141144
</Compile>
142145
<Compile Include="Util\SpecificItemDtoConverter.cs" />
146+
<Compile Include="Util\UiPathWebApiExtenssions.cs" />
143147
<Compile Include="Util\ValidateEnumAttribute.cs" />
144148
</ItemGroup>
145149
<ItemGroup>

0 commit comments

Comments
 (0)