Skip to content

Commit d322402

Browse files
committed
gitlab: add shared UI project
Add shared UI project for GitLab. Project contains the shared view models and commands for the main auth prompt.
1 parent 569d10b commit d322402

File tree

7 files changed

+330
-0
lines changed

7 files changed

+330
-0
lines changed

Git-Credential-Manager.sln

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitLab", "src\shared\GitLab
6363
EndProject
6464
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitLab.Tests", "src\shared\GitLab.Tests\GitLab.Tests.csproj", "{1AF9F7C5-FA2E-48F1-B216-4D5E9A27F393}"
6565
EndProject
66+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitLab.UI", "src\shared\GitLab.UI\GitLab.UI.csproj", "{9AFD88E2-7E2C-46DA-9D38-4342086426D3}"
67+
EndProject
6668
Global
6769
GlobalSection(SolutionConfigurationPlatforms) = preSolution
6870
Debug|Any CPU = Debug|Any CPU
@@ -433,6 +435,22 @@ Global
433435
{1AF9F7C5-FA2E-48F1-B216-4D5E9A27F393}.MacRelease|Any CPU.Build.0 = Release|Any CPU
434436
{1AF9F7C5-FA2E-48F1-B216-4D5E9A27F393}.WindowsRelease|Any CPU.ActiveCfg = Release|Any CPU
435437
{1AF9F7C5-FA2E-48F1-B216-4D5E9A27F393}.WindowsRelease|Any CPU.Build.0 = Release|Any CPU
438+
{9AFD88E2-7E2C-46DA-9D38-4342086426D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
439+
{9AFD88E2-7E2C-46DA-9D38-4342086426D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
440+
{9AFD88E2-7E2C-46DA-9D38-4342086426D3}.MacDebug|Any CPU.ActiveCfg = Debug|Any CPU
441+
{9AFD88E2-7E2C-46DA-9D38-4342086426D3}.MacDebug|Any CPU.Build.0 = Debug|Any CPU
442+
{9AFD88E2-7E2C-46DA-9D38-4342086426D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
443+
{9AFD88E2-7E2C-46DA-9D38-4342086426D3}.Release|Any CPU.Build.0 = Release|Any CPU
444+
{9AFD88E2-7E2C-46DA-9D38-4342086426D3}.WindowsDebug|Any CPU.ActiveCfg = Debug|Any CPU
445+
{9AFD88E2-7E2C-46DA-9D38-4342086426D3}.WindowsDebug|Any CPU.Build.0 = Debug|Any CPU
446+
{9AFD88E2-7E2C-46DA-9D38-4342086426D3}.LinuxDebug|Any CPU.ActiveCfg = Debug|Any CPU
447+
{9AFD88E2-7E2C-46DA-9D38-4342086426D3}.LinuxDebug|Any CPU.Build.0 = Debug|Any CPU
448+
{9AFD88E2-7E2C-46DA-9D38-4342086426D3}.LinuxRelease|Any CPU.ActiveCfg = Release|Any CPU
449+
{9AFD88E2-7E2C-46DA-9D38-4342086426D3}.LinuxRelease|Any CPU.Build.0 = Release|Any CPU
450+
{9AFD88E2-7E2C-46DA-9D38-4342086426D3}.MacRelease|Any CPU.ActiveCfg = Release|Any CPU
451+
{9AFD88E2-7E2C-46DA-9D38-4342086426D3}.MacRelease|Any CPU.Build.0 = Release|Any CPU
452+
{9AFD88E2-7E2C-46DA-9D38-4342086426D3}.WindowsRelease|Any CPU.ActiveCfg = Release|Any CPU
453+
{9AFD88E2-7E2C-46DA-9D38-4342086426D3}.WindowsRelease|Any CPU.Build.0 = Release|Any CPU
436454
EndGlobalSection
437455
GlobalSection(SolutionProperties) = preSolution
438456
HideSolutionNode = FALSE
@@ -467,6 +485,7 @@ Global
467485
{3F015046-DAF2-4D2A-96EC-F9782F169E45} = {66722747-1B61-40E4-A89B-1AC8E6D62EA9}
468486
{570897DC-A85C-4598-B793-9A00CF710119} = {D5277A0E-997E-453A-8CB9-4EFCC8B16A29}
469487
{1AF9F7C5-FA2E-48F1-B216-4D5E9A27F393} = {D5277A0E-997E-453A-8CB9-4EFCC8B16A29}
488+
{9AFD88E2-7E2C-46DA-9D38-4342086426D3} = {D5277A0E-997E-453A-8CB9-4EFCC8B16A29}
470489
EndGlobalSection
471490
GlobalSection(ExtensibilityGlobals) = postSolution
472491
SolutionGuid = {0EF9FC65-E6BA-45D4-A455-262A9EA4366B}

src/osx/SignFiles.Mac/SignFiles.Mac.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
$(OutDir)\GitHub.UI.dll;
2929
$(OutDir)\GitHub.UI.Shared.dll;
3030
$(OutDir)\GitLab.dll;
31+
$(OutDir)\GitLab.UI.Shared.dll;
3132
$(OutDir)\Microsoft.AzureRepos.dll;
3233
$(OutDir)\gcmcore.dll;">
3334
<Authenticode>Microsoft400</Authenticode>
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.CommandLine;
4+
using System.CommandLine.Invocation;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using GitLab.UI.ViewModels;
8+
using GitCredentialManager;
9+
using GitCredentialManager.UI;
10+
11+
namespace GitLab.UI.Commands
12+
{
13+
public abstract class CredentialsCommand : HelperCommand
14+
{
15+
protected CredentialsCommand(ICommandContext context)
16+
: base(context, "prompt", "Show authentication prompt.")
17+
{
18+
AddOption(
19+
new Option<string>("--url", "GitLab instance URL.")
20+
);
21+
22+
AddOption(
23+
new Option<string>("--username", "Username or email.")
24+
);
25+
26+
AddOption(
27+
new Option("--basic", "Enable username/password (basic) authentication.")
28+
);
29+
30+
AddOption(
31+
new Option("--browser", "Enable browser-based OAuth authentication.")
32+
);
33+
34+
AddOption(
35+
new Option("--pat", "Enable personal access token authentication.")
36+
);
37+
38+
AddOption(
39+
new Option("--all", "Enable all available authentication options.")
40+
);
41+
42+
Handler = CommandHandler.Create<CommandOptions>(ExecuteAsync);
43+
}
44+
45+
private class CommandOptions
46+
{
47+
public string UserName { get; set; }
48+
public string Url { get; set; }
49+
public bool Basic { get; set; }
50+
public bool Browser { get; set; }
51+
public bool Pat { get; set; }
52+
public bool All { get; set; }
53+
}
54+
55+
private async Task<int> ExecuteAsync(CommandOptions options)
56+
{
57+
var viewModel = new CredentialsViewModel(Context.Environment)
58+
{
59+
ShowBrowserLogin = options.All || options.Browser,
60+
ShowTokenLogin = options.All || options.Pat,
61+
ShowBasicLogin = options.All || options.Basic,
62+
};
63+
64+
if (Uri.TryCreate(options.Url, UriKind.Absolute, out Uri uri) && !GitLabConstants.IsGitLabDotCom(uri))
65+
{
66+
viewModel.Url = options.Url;
67+
}
68+
69+
if (!string.IsNullOrWhiteSpace(options.UserName))
70+
{
71+
viewModel.UserName = options.UserName;
72+
viewModel.TokenUserName = options.UserName;
73+
}
74+
75+
await ShowAsync(viewModel, CancellationToken.None);
76+
77+
if (!viewModel.WindowResult)
78+
{
79+
throw new Exception("User cancelled dialog.");
80+
}
81+
82+
var result = new Dictionary<string, string>();
83+
84+
switch (viewModel.SelectedMode)
85+
{
86+
case AuthenticationModes.Basic:
87+
result["mode"] = "basic";
88+
result["username"] = viewModel.UserName;
89+
result["password"] = viewModel.Password;
90+
break;
91+
92+
case AuthenticationModes.Browser:
93+
result["mode"] = "browser";
94+
break;
95+
96+
case AuthenticationModes.Pat:
97+
result["mode"] = "pat";
98+
result["pat"] = viewModel.Token;
99+
result["username"] = viewModel.TokenUserName;
100+
break;
101+
102+
default:
103+
throw new ArgumentOutOfRangeException();
104+
}
105+
106+
WriteResult(result);
107+
return 0;
108+
}
109+
110+
protected abstract Task ShowAsync(CredentialsViewModel viewModel, CancellationToken ct);
111+
}
112+
}

src/shared/GitLab.UI/GitLab.UI.csproj

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.0</TargetFramework>
5+
<RootNamespace>GitLab.UI</RootNamespace>
6+
<AssemblyName>GitLab.UI.Shared</AssemblyName>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<ProjectReference Include="..\GitLab\GitLab.csproj" />
11+
<ProjectReference Include="..\Core.UI\Core.UI.csproj" />
12+
</ItemGroup>
13+
14+
</Project>
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
using System.ComponentModel;
2+
using System.Windows.Input;
3+
using GitCredentialManager;
4+
using GitCredentialManager.UI;
5+
using GitCredentialManager.UI.ViewModels;
6+
7+
namespace GitLab.UI.ViewModels
8+
{
9+
public class CredentialsViewModel : WindowViewModel
10+
{
11+
private readonly IEnvironment _environment;
12+
13+
private string _url;
14+
private string _token;
15+
private string _tokenUserName;
16+
private string _userName;
17+
private string _password;
18+
private bool _showBrowserLogin;
19+
private bool _showTokenLogin;
20+
private bool _showBasicLogin;
21+
private ICommand _signUpCommand;
22+
private ICommand _signInBrowserCommand;
23+
private RelayCommand _signInBasicCommand;
24+
private RelayCommand _signInTokenCommand;
25+
26+
public CredentialsViewModel()
27+
{
28+
// Constructor the XAML designer
29+
}
30+
31+
public CredentialsViewModel(IEnvironment environment)
32+
{
33+
EnsureArgument.NotNull(environment, nameof(environment));
34+
35+
_environment = environment;
36+
37+
Title = "Connect to GitLab";
38+
SignUpCommand = new RelayCommand(SignUp);
39+
SignInBrowserCommand = new RelayCommand(SignInBrowser);
40+
SignInTokenCommand = new RelayCommand(SignInToken, CanSignInToken);
41+
SignInBasicCommand = new RelayCommand(SignInBasic, CanSignInBasic);
42+
43+
PropertyChanged += OnPropertyChanged;
44+
}
45+
46+
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
47+
{
48+
switch (e.PropertyName)
49+
{
50+
case nameof(UserName):
51+
case nameof(Password):
52+
SignInBasicCommand.RaiseCanExecuteChanged();
53+
break;
54+
55+
case nameof(Token):
56+
SignInTokenCommand.RaiseCanExecuteChanged();
57+
break;
58+
}
59+
}
60+
61+
private void SignUp()
62+
{
63+
BrowserUtils.OpenDefaultBrowser(_environment, "https://about.gitlab.com/");
64+
}
65+
66+
private void SignInBrowser()
67+
{
68+
SelectedMode = AuthenticationModes.Browser;
69+
Accept();
70+
}
71+
72+
private bool CanSignInToken()
73+
{
74+
return !string.IsNullOrWhiteSpace(Token);
75+
}
76+
77+
private void SignInToken()
78+
{
79+
SelectedMode = AuthenticationModes.Pat;
80+
Accept();
81+
}
82+
83+
private bool CanSignInBasic()
84+
{
85+
return !string.IsNullOrWhiteSpace(UserName) && !string.IsNullOrEmpty(Password);
86+
}
87+
88+
private void SignInBasic()
89+
{
90+
SelectedMode = AuthenticationModes.Basic;
91+
Accept();
92+
}
93+
94+
public string Token
95+
{
96+
get => _token;
97+
set => SetAndRaisePropertyChanged(ref _token, value);
98+
}
99+
100+
public string TokenUserName
101+
{
102+
get => _tokenUserName;
103+
set => SetAndRaisePropertyChanged(ref _tokenUserName, value);
104+
}
105+
106+
public string UserName
107+
{
108+
get => _userName;
109+
set => SetAndRaisePropertyChanged(ref _userName, value);
110+
}
111+
112+
public string Password
113+
{
114+
get => _password;
115+
set => SetAndRaisePropertyChanged(ref _password, value);
116+
}
117+
118+
public string Url
119+
{
120+
get => _url;
121+
set => SetAndRaisePropertyChanged(ref _url, value);
122+
}
123+
124+
public string OAuthModeTitle
125+
{
126+
get
127+
{
128+
if (ShowBrowserLogin) return "Browser";
129+
return "OAuth";
130+
}
131+
}
132+
133+
public bool ShowBrowserLogin
134+
{
135+
get => _showBrowserLogin;
136+
set
137+
{
138+
SetAndRaisePropertyChanged(ref _showBrowserLogin, value);
139+
RaisePropertyChanged(OAuthModeTitle);
140+
}
141+
}
142+
143+
public bool ShowTokenLogin
144+
{
145+
get => _showTokenLogin;
146+
set => SetAndRaisePropertyChanged(ref _showTokenLogin, value);
147+
}
148+
149+
public bool ShowBasicLogin
150+
{
151+
get => _showBasicLogin;
152+
set => SetAndRaisePropertyChanged(ref _showBasicLogin, value);
153+
}
154+
155+
public ICommand SignUpCommand
156+
{
157+
get => _signUpCommand;
158+
set => SetAndRaisePropertyChanged(ref _signUpCommand, value);
159+
}
160+
161+
public ICommand SignInBrowserCommand
162+
{
163+
get => _signInBrowserCommand;
164+
set => SetAndRaisePropertyChanged(ref _signInBrowserCommand, value);
165+
}
166+
167+
public RelayCommand SignInTokenCommand
168+
{
169+
get => _signInTokenCommand;
170+
set => SetAndRaisePropertyChanged(ref _signInTokenCommand, value);
171+
}
172+
173+
public RelayCommand SignInBasicCommand
174+
{
175+
get => _signInBasicCommand;
176+
set => SetAndRaisePropertyChanged(ref _signInBasicCommand, value);
177+
}
178+
179+
public AuthenticationModes SelectedMode { get; private set; }
180+
}
181+
}

src/windows/Installer.Windows/Setup.iss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ Source: "{#PayloadDir}\GitHub.UI.exe"; DestDir:
113113
Source: "{#PayloadDir}\GitHub.UI.exe.config"; DestDir: "{app}"; Flags: ignoreversion
114114
Source: "{#PayloadDir}\GitHub.UI.Shared.dll"; DestDir: "{app}"; Flags: ignoreversion
115115
Source: "{#PayloadDir}\GitLab.dll"; DestDir: "{app}"; Flags: ignoreversion
116+
Source: "{#PayloadDir}\GitLab.UI.Shared.dll"; DestDir: "{app}"; Flags: ignoreversion
116117
Source: "{#PayloadDir}\Microsoft.AzureRepos.dll"; DestDir: "{app}"; Flags: ignoreversion
117118
Source: "{#PayloadDir}\gcmcore.dll"; DestDir: "{app}"; Flags: ignoreversion
118119
Source: "{#PayloadDir}\gcmcoreui.dll"; DestDir: "{app}"; Flags: ignoreversion

src/windows/Payload.Windows/Payload.Windows.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
$(OutDir)git-credential-manager-core.exe;
2828
$(OutDir)GitHub.dll;
2929
$(OutDir)GitHub.UI.exe;
30+
$(OutDir)GitHub.UI.Shared.dll;
3031
$(OutDir)GitLab.dll;
32+
$(OutDir)GitLab.UI.Shared.dll;
3133
$(OutDir)Microsoft.AzureRepos.dll;
3234
$(OutDir)gcmcore.dll;
3335
$(OutDir)gcmcoreui.dll;

0 commit comments

Comments
 (0)