-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathSignInViewModel.cs
136 lines (114 loc) · 3.88 KB
/
SignInViewModel.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using System;
using System.Threading;
using System.Threading.Tasks;
using Coder.Desktop.App.Services;
using Coder.Desktop.App.Views;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.UI.Xaml;
namespace Coder.Desktop.App.ViewModels;
/// <summary>
/// The View Model backing the sign in window and all its associated pages.
/// </summary>
public partial class SignInViewModel : ObservableObject
{
private readonly ICredentialManager _credentialManager;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(CoderUrlError))]
[NotifyPropertyChangedFor(nameof(GenTokenUrl))]
public partial string CoderUrl { get; set; } = string.Empty;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(CoderUrlError))]
public partial bool CoderUrlTouched { get; set; } = false;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(ApiTokenError))]
public partial string ApiToken { get; set; } = string.Empty;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(ApiTokenError))]
public partial bool ApiTokenTouched { get; set; } = false;
[ObservableProperty] public partial string? SignInError { get; set; } = null;
[ObservableProperty] public partial bool SignInLoading { get; set; } = false;
public string? CoderUrlError => CoderUrlTouched ? _coderUrlError : null;
private string? _coderUrlError
{
get
{
if (!Uri.TryCreate(CoderUrl, UriKind.Absolute, out var uri))
return "Invalid URL";
if (uri.Scheme is not "http" and not "https")
return "Must be a HTTP or HTTPS URL";
if (uri.PathAndQuery != "/")
return "Must be a root URL with no path or query";
return null;
}
}
public string? ApiTokenError => ApiTokenTouched ? _apiTokenError : null;
private string? _apiTokenError => string.IsNullOrWhiteSpace(ApiToken) ? "Invalid token" : null;
public Uri GenTokenUrl
{
get
{
// In case somehow the URL is invalid, just default to coder.com.
// The HyperlinkButton will crash the entire app if the URL is
// invalid.
try
{
var baseUri = new Uri(CoderUrl.Trim());
var cliAuthUri = new Uri(baseUri, "/cli-auth");
return cliAuthUri;
}
catch
{
return new Uri("https://coder.com");
}
}
}
public SignInViewModel(ICredentialManager credentialManager)
{
_credentialManager = credentialManager;
}
public void CoderUrl_FocusLost(object sender, RoutedEventArgs e)
{
CoderUrlTouched = true;
}
public void ApiToken_FocusLost(object sender, RoutedEventArgs e)
{
ApiTokenTouched = true;
}
[RelayCommand]
public void UrlPage_Next(SignInWindow signInWindow)
{
CoderUrlTouched = true;
if (_coderUrlError != null) return;
signInWindow.NavigateToTokenPage();
}
[RelayCommand]
public void TokenPage_Back(SignInWindow signInWindow)
{
ApiToken = "";
signInWindow.NavigateToUrlPage();
}
[RelayCommand]
public async Task TokenPage_SignIn(SignInWindow signInWindow)
{
CoderUrlTouched = true;
ApiTokenTouched = true;
if (_coderUrlError != null || _apiTokenError != null) return;
try
{
SignInLoading = true;
SignInError = null;
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(15));
await _credentialManager.SetCredentials(CoderUrl.Trim(), ApiToken.Trim(), cts.Token);
signInWindow.Close();
}
catch (Exception e)
{
SignInError = $"Failed to sign in: {e}";
}
finally
{
SignInLoading = false;
}
}
}