Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Gitee.com's OAuth and Logo with chinese #1452

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from
Draft
1,098 changes: 554 additions & 544 deletions Git-Credential-Manager.sln

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/linux/Packaging.Linux/Packaging.Linux.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<ProjectReference Include="../../shared/Atlassian.Bitbucket.UI.Avalonia/Atlassian.Bitbucket.UI.Avalonia.csproj" ReferenceOutputAssembly="false" />
<ProjectReference Include="../../shared/GitHub.UI.Avalonia/GitHub.UI.Avalonia.csproj" ReferenceOutputAssembly="false" />
<ProjectReference Include="../../shared/GitLab.UI.Avalonia/GitLab.UI.Avalonia.csproj" ReferenceOutputAssembly="false" />
<ProjectReference Include="../../shared/Gitee.UI.Avalonia/Gitee.UI.Avalonia.csproj" ReferenceOutputAssembly="false" />
<ProjectReference Include="../../shared/Core.UI.Avalonia/Core.UI.Avalonia.csproj" ReferenceOutputAssembly="false" />
</ItemGroup>

Expand Down
10 changes: 10 additions & 0 deletions src/linux/Packaging.Linux/layout.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ GCM_UI_SRC="$SRC/shared/Git-Credential-Manager.UI.Avalonia"
BITBUCKET_UI_SRC="$SRC/shared/Atlassian.Bitbucket.UI.Avalonia"
GITHUB_UI_SRC="$SRC/shared/GitHub.UI.Avalonia"
GITLAB_UI_SRC="$SRC/shared/GitLab.UI.Avalonia"
GITEE_UI_SRC="$SRC/shared/Gitee.UI.Avalonia"
PROJ_OUT="$OUT/linux/Packaging.Linux"

# Build parameters
Expand Down Expand Up @@ -117,6 +118,15 @@ $DOTNET_ROOT/dotnet publish "$GITLAB_UI_SRC" \
-p:PublishSingleFile=true \
--output="$(make_absolute "$PAYLOAD")" || exit 1

echo "Publishing Gitee UI helper..."
$DOTNET_ROOT/dotnet publish "$GITEE_UI_SRC" \
--configuration="$CONFIGURATION" \
--framework="$FRAMEWORK" \
--runtime="$RUNTIME" \
--self-contained=true \
-p:PublishSingleFile=true \
--output="$(make_absolute "$PAYLOAD")" || exit 1

# Collect symbols
echo "Collecting managed symbols..."
mv "$PAYLOAD"/*.pdb "$SYMBOLOUT" || exit 1
Expand Down
1 change: 1 addition & 0 deletions src/osx/Installer.Mac/Installer.Mac.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<ProjectReference Include="../../shared/Atlassian.Bitbucket.UI.Avalonia/Atlassian.Bitbucket.UI.Avalonia.csproj" ReferenceOutputAssembly="false" />
<ProjectReference Include="../../shared/GitHub.UI.Avalonia/GitHub.UI.Avalonia.csproj" ReferenceOutputAssembly="false" />
<ProjectReference Include="../../shared/GitLab.UI.Avalonia/GitLab.UI.Avalonia.csproj" ReferenceOutputAssembly="false" />
<ProjectReference Include="../../shared/Gitee.UI.Avalonia/Gitee.UI.Avalonia.csproj" ReferenceOutputAssembly="false" />
<ProjectReference Include="../../shared/Core.UI.Avalonia/Core.UI.Avalonia.csproj" ReferenceOutputAssembly="false" />
</ItemGroup>

Expand Down
9 changes: 9 additions & 0 deletions src/osx/Installer.Mac/layout.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ GCM_UI_SRC="$SRC/shared/Git-Credential-Manager.UI.Avalonia"
BITBUCKET_UI_SRC="$SRC/shared/Atlassian.Bitbucket.UI.Avalonia"
GITHUB_UI_SRC="$SRC/shared/GitHub.UI.Avalonia"
GITLAB_UI_SRC="$SRC/shared/GitLab.UI.Avalonia"
GITEE_UI_SRC="$SRC/shared/Gitee.UI.Avalonia"

# Build parameters
FRAMEWORK=net6.0
Expand Down Expand Up @@ -135,6 +136,14 @@ dotnet publish "$GITLAB_UI_SRC" \
--self-contained \
--output="$(make_absolute "$PAYLOAD")" || exit 1

echo "Publishing Gitee UI helper..."
dotnet publish "$GITEE_UI_SRC" \
--configuration="$CONFIGURATION" \
--framework="$FRAMEWORK" \
--runtime="$RUNTIME" \
--self-contained \
--output="$(make_absolute "$PAYLOAD")" || exit 1

# Collect symbols
echo "Collecting managed symbols..."
mv "$PAYLOAD"/*.pdb "$SYMBOLOUT" || exit 1
Expand Down
8 changes: 8 additions & 0 deletions src/shared/DotnetTool/layout.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ GCM_UI_SRC="$SRC/shared/Git-Credential-Manager.UI.Avalonia"
BITBUCKET_UI_SRC="$SRC/shared/Atlassian.Bitbucket.UI.Avalonia"
GITHUB_UI_SRC="$SRC/shared/GitHub.UI.Avalonia"
GITLAB_UI_SRC="$SRC/shared/GitLab.UI.Avalonia"
GITEE_UI_SRC="$SRC/shared/Gitee.UI.Avalonia"
DOTNET_TOOL="shared/DotnetTool"
PROJ_OUT="$OUT/$DOTNET_TOOL"

Expand Down Expand Up @@ -100,6 +101,13 @@ $DOTNET_ROOT/dotnet publish "$GITLAB_UI_SRC" \
--output="$(make_absolute "$PAYLOAD")" \
-p:UseAppHost=false || exit 1

echo "Publishing Gitee UI helper..."
$DOTNET_ROOT/dotnet publish "$GITEE_UI_SRC" \
--configuration="$CONFIGURATION" \
--framework="$FRAMEWORK" \
--output="$(make_absolute "$PAYLOAD")" \
-p:UseAppHost=false || exit 1

# Collect symbols
echo "Collecting managed symbols..."
mv "$PAYLOAD"/*.pdb "$SYMBOLOUT" || exit 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<ProjectReference Include="..\Atlassian.Bitbucket\Atlassian.Bitbucket.csproj" />
<ProjectReference Include="..\GitHub\GitHub.csproj" />
<ProjectReference Include="..\GitLab\GitLab.csproj" />
<ProjectReference Include="..\Gitee\Gitee.csproj" />
<ProjectReference Include="..\Microsoft.AzureRepos\Microsoft.AzureRepos.csproj" />
<ProjectReference Include="..\Core\Core.csproj" />
</ItemGroup>
Expand Down
2 changes: 2 additions & 0 deletions src/shared/Git-Credential-Manager/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Atlassian.Bitbucket;
using GitHub;
using GitLab;
using Gitee;
using Microsoft.AzureRepos;
using GitCredentialManager.Authentication;

Expand Down Expand Up @@ -68,6 +69,7 @@ public static void Main(string[] args)
app.RegisterProvider(new BitbucketHostProvider(context), HostProviderPriority.Normal);
app.RegisterProvider(new GitHubHostProvider(context), HostProviderPriority.Normal);
app.RegisterProvider(new GitLabHostProvider(context), HostProviderPriority.Normal);
app.RegisterProvider(new GiteeHostProvider(context), HostProviderPriority.Normal);
app.RegisterProvider(new GenericHostProvider(context), HostProviderPriority.Low);

int exitCode = app.RunAsync(args)
Expand Down
26 changes: 26 additions & 0 deletions src/shared/Gitee.Tests/Gitee.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<LangVersion>latest</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="3.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="ReportGenerator" Version="5.1.9" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Gitee\Gitee.csproj" />
<ProjectReference Include="..\TestInfrastructure\TestInfrastructure.csproj" />
</ItemGroup>

</Project>
96 changes: 96 additions & 0 deletions src/shared/Gitee.Tests/GiteeAuthenticationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using System;
using System.Threading.Tasks;
using GitCredentialManager.Tests.Objects;
using Xunit;

namespace Gitee.Tests
{
public class GiteeAuthenticationTests
{
[Fact]
public async Task GiteeAuthentication_GetAuthenticationAsync_AuthenticationModesNone_ThrowsException()
{
var context = new TestCommandContext();
var auth = new GiteeAuthentication(context);
await Assert.ThrowsAsync<ArgumentException>("modes",
() => auth.GetAuthenticationAsync(null, null, AuthenticationModes.None)
);
}

[Theory]
[InlineData(AuthenticationModes.Browser)]
public async Task GiteeAuthentication_GetAuthenticationAsync_SingleChoice_TerminalAndInteractionNotRequired(Gitee.AuthenticationModes modes)
{
var context = new TestCommandContext();
context.Settings.IsTerminalPromptsEnabled = false;
context.Settings.IsInteractionAllowed = false;
context.SessionManager.IsDesktopSession = true; // necessary for browser
var auth = new GiteeAuthentication(context);
var result = await auth.GetAuthenticationAsync(null, null, modes);
Assert.Equal(modes, result.AuthenticationMode);
}

[Fact]
public async Task GiteeAuthentication_GetAuthenticationAsync_TerminalPromptsDisabled_Throws()
{
var context = new TestCommandContext();
context.Settings.IsTerminalPromptsEnabled = false;
var auth = new GiteeAuthentication(context);
var exception = await Assert.ThrowsAsync<InvalidOperationException>(
() => auth.GetAuthenticationAsync(null, null, AuthenticationModes.All)
);
Assert.Equal("Cannot prompt because terminal prompts have been disabled.", exception.Message);
}

[Fact]
public async Task GiteeAuthentication_GetAuthenticationAsync_Terminal()
{
var context = new TestCommandContext();
var auth = new GiteeAuthentication(context);
context.SessionManager.IsDesktopSession = true;
context.Terminal.Prompts["option (enter for default)"] = "";
var result = await auth.GetAuthenticationAsync(null, null, AuthenticationModes.All);
Assert.Equal(AuthenticationModes.Browser, result.AuthenticationMode);
}

[Fact]
public async Task GiteeAuthentication_GetAuthenticationAsync_ChoosePat()
{
var context = new TestCommandContext();
var auth = new GiteeAuthentication(context);
context.Terminal.Prompts["option (enter for default)"] = "";
context.Terminal.Prompts["Username"] = "username";
context.Terminal.SecretPrompts["Personal access token"] = "token";
var result = await auth.GetAuthenticationAsync(null, null, AuthenticationModes.All);
Assert.Equal(AuthenticationModes.Pat, result.AuthenticationMode);
Assert.Equal("username", result.Credential.Account);
Assert.Equal("token", result.Credential.Password);
}

[Fact]
public async Task GiteeAuthentication_GetAuthenticationAsync_ChooseBasic()
{
var context = new TestCommandContext();
var auth = new GiteeAuthentication(context);
context.Terminal.Prompts["option (enter for default)"] = "2";
context.Terminal.Prompts["Username"] = "username";
context.Terminal.SecretPrompts["Password"] = "password";
var result = await auth.GetAuthenticationAsync(null, null, AuthenticationModes.All);
Assert.Equal(AuthenticationModes.Basic, result.AuthenticationMode);
Assert.Equal("username", result.Credential.Account);
Assert.Equal("password", result.Credential.Password);
}

[Fact]
public async Task GiteeAuthentication_GetAuthenticationAsync_AuthenticationModesAll_RequiresInteraction()
{
var context = new TestCommandContext();
context.Settings.IsInteractionAllowed = false;
var auth = new GiteeAuthentication(context);
var exception = await Assert.ThrowsAsync<InvalidOperationException>(
() => auth.GetAuthenticationAsync(new Uri("https://gitee.com"), null, AuthenticationModes.All)
);
Assert.Equal("Cannot prompt because user interactivity has been disabled.", exception.Message);
}
}
}
73 changes: 73 additions & 0 deletions src/shared/Gitee.Tests/GiteeHostProviderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using GitCredentialManager;
using GitCredentialManager.Tests.Objects;
using Xunit;

namespace Gitee.Tests
{
public class GiteeHostProviderTests
{
[Theory]
[InlineData("https", "gitee.com", true)]
[InlineData("http", "gitee.com", true)]
[InlineData("https", "gitee.example.com", true)]
[InlineData("https", "github.com", false)]
[InlineData("https", "github.example.com", false)]
public void GiteeHostProvider_IsSupported(string protocol, string host, bool expected)
{
var input = new InputArguments(new Dictionary<string, string>
{
["protocol"] = protocol,
["host"] = host,
});

var provider = new GiteeHostProvider(new TestCommandContext());
Assert.Equal(expected, provider.IsSupported(input));
}

[Fact]
public void GiteeHostProvider_GetSupportedAuthenticationModes_DotCom_ReturnsDotComModes()
{
Uri targetUri = GiteeConstants.GiteeDotCom;
AuthenticationModes expected = GiteeConstants.DotComAuthenticationModes;

var context = new TestCommandContext();
var provider = new GiteeHostProvider(context);
AuthenticationModes actual = provider.GetSupportedAuthenticationModes(targetUri);

Assert.Equal(expected, actual);
}

[Fact]
public void GiteeHostProvider_GetSupportedAuthenticationModes_Custom_NoOAuthConfig_ReturnsBasicPat()
{
var targetUri = new Uri("https://gitee.example.com");
var expected = AuthenticationModes.Basic
| AuthenticationModes.Pat;

var context = new TestCommandContext();
var provider = new GiteeHostProvider(context);
AuthenticationModes actual = provider.GetSupportedAuthenticationModes(targetUri);

Assert.Equal(expected, actual);
}

[Fact]
public void GiteeHostProvider_GetSupportedAuthenticationModes_Custom_WithOAuthConfig_ReturnsBasicPatBrowser()
{
var targetUri = new Uri("https://gitee.example.com");
var expected = AuthenticationModes.Basic
| AuthenticationModes.Pat
| AuthenticationModes.Browser;

var context = new TestCommandContext();
context.Environment.Variables[GiteeConstants.EnvironmentVariables.DevOAuthClientId] = "abcdefg1234567";

var provider = new GiteeHostProvider(context);
AuthenticationModes actual = provider.GetSupportedAuthenticationModes(targetUri);

Assert.Equal(expected, actual);
}
}
}
19 changes: 19 additions & 0 deletions src/shared/Gitee.UI.Avalonia/Commands/CredentialsCommandImpl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Threading;
using System.Threading.Tasks;
using Gitee.UI.ViewModels;
using Gitee.UI.Views;
using GitCredentialManager;
using GitCredentialManager.UI;

namespace Gitee.UI.Commands
{
public class CredentialsCommandImpl : CredentialsCommand
{
public CredentialsCommandImpl(ICommandContext context) : base(context) { }

protected override Task ShowAsync(CredentialsViewModel viewModel, CancellationToken ct)
{
return AvaloniaUi.ShowViewAsync<CredentialsView>(viewModel, GetParentHandle(), ct);
}
}
}
49 changes: 49 additions & 0 deletions src/shared/Gitee.UI.Avalonia/Controls/TesterWindow.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Gitee.UI.Controls.TesterWindow"
CanResize="False" Width="550" SizeToContent="Height"
Title="Gitee Authentication Dialog Tester">
<TabControl Margin="5,10">
<TabControl.Styles>
<Style Selector="TabItem">
<Setter Property="MinHeight" Value="30" />
<Setter Property="FontSize" Value="12"/>
</Style>
<Style Selector="TabItem > StackPanel">
<Setter Property="Margin" Value="0,10,0,0"/>
</Style>
<Style Selector="TabItem > StackPanel > Grid > Label">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="0,0,10,0"/>
</Style>
<Style Selector="TabItem > StackPanel > Button">
<Setter Property="Margin" Value="0,10,0,0" />
<Setter Property="Padding" Value="14,10" />
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
</TabControl.Styles>
<TabItem Header="Credentials">
<StackPanel>
<Grid RowDefinitions="Auto,Auto,Auto" ColumnDefinitions="Auto,*">
<Label Grid.Row="0" Grid.Column="0"
Content="Auth Modes" />
<StackPanel Grid.Row="0" Grid.Column="1"
Orientation="Horizontal" VerticalAlignment="Center">
<CheckBox Content="Browser" x:Name="useBrowser" MinWidth="90" IsChecked="True" />
<CheckBox Content="PAT" x:Name="usePat" MinWidth="80" IsChecked="True" />
<CheckBox Content="Basic" x:Name="useBasic" MinWidth="80" />
</StackPanel>
<Label Grid.Row="1" Grid.Column="0"
Content="Instance URL" />
<TextBox Grid.Row="1" Grid.Column="1"
x:Name="instanceUrl" />
<Label Grid.Row="2" Grid.Column="0"
Content="Username" />
<TextBox Grid.Row="2" Grid.Column="1"
x:Name="username" />
</Grid>
<Button Classes="accent" Content="Show" Click="ShowCredentials" />
</StackPanel>
</TabItem>
</TabControl>
</Window>
Loading