Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ jobs:
with:
dotnet-version: 8.0.x

- name: Setup .NET
uses: actions/[email protected]
with:
dotnet-version: 8.0.x

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ jobs:
shell: bash
run: |
mkdir -p artifacts/bin
mv out/windows/Installer.Windows/bin/Release/net472/win-x86 artifacts/bin/
cp out/windows/Installer.Windows/bin/Release/net472/win-x86.sym/* artifacts/bin/win-x86/
mv out/windows/Installer.Windows/bin/Release/net472/gcm*.exe artifacts/
mv out/windows/Installer.Windows/bin/Release/net8.0/win-x86 artifacts/bin/
cp out/windows/Installer.Windows/bin/Release/net8.0/win-x86.sym/* artifacts/bin/win-x86/
mv out/windows/Installer.Windows/bin/Release/net8.0/gcm*.exe artifacts/

- name: Upload artifacts
uses: actions/upload-artifact@v5
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ jobs:
/p:PayloadPath=$env:GITHUB_WORKSPACE\payload /p:NoLayout=true `
--configuration=WindowsRelease
mkdir installers
Move-Item -Path .\out\windows\Installer.Windows\bin\Release\net472\*.exe `
Move-Item -Path .\out\windows\Installer.Windows\bin\Release\net8.0\*.exe `
-Destination $env:GITHUB_WORKSPACE\installers

- name: Sign installers with Azure Code Signing
Expand Down
6 changes: 0 additions & 6 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,4 @@
<GenerateWindowsAppManifest Condition="'$(GenerateWindowsAppManifest)' == '' AND '$(OSPlatform)' == 'windows' AND '$(_IsExeProject)' == 'true'">true</GenerateWindowsAppManifest>
</PropertyGroup>

<ItemGroup Condition = "'$(TargetFramework)' == 'net472'">
<PackageReference Include="System.Text.Json">
<Version>8.0.5</Version>
</PackageReference>
</ItemGroup>

</Project>
5 changes: 5 additions & 0 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,9 @@
</ItemGroup>
</Target>

<PropertyGroup>
<!-- Ignore platform API compatibilty checks in test projects -->
<NoWarn Condition="'$(IsTestProject)'=='true'">$(NoWarn);CA1416</NoWarn>
</PropertyGroup>

</Project>
4 changes: 2 additions & 2 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ To build from the command line, run:
dotnet build -c WindowsDebug
```

You can find a copy of the installer .exe file in `out\windows\Installer.Windows\bin\Debug\net472`.
You can find a copy of the installer .exe file in `out\windows\Installer.Windows\bin\Debug\net8.0`.

The flat binaries can also be found in `out\windows\Payload.Windows\bin\Debug\net472\win-x86`.
The flat binaries can also be found in `out\windows\Payload.Windows\bin\Debug\net8.0\win-x86`.

### Linux

Expand Down
2 changes: 0 additions & 2 deletions src/linux/Packaging.Linux/layout.sh
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,13 @@ if [ -z "$RUNTIME" ]; then
--configuration="$CONFIGURATION" \
--framework="$FRAMEWORK" \
--self-contained \
-p:PublishSingleFile=true \
--output="$(make_absolute "$PAYLOAD")" || exit 1
else
$DOTNET_ROOT/dotnet publish "$GCM_SRC" \
--configuration="$CONFIGURATION" \
--framework="$FRAMEWORK" \
--runtime="$RUNTIME" \
--self-contained \
-p:PublishSingleFile=true \
--output="$(make_absolute "$PAYLOAD")" || exit 1
fi

Expand Down
1 change: 0 additions & 1 deletion src/osx/Installer.Mac/layout.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ SRC="$ROOT/src"
OUT="$ROOT/out"
INSTALLER_SRC="$SRC/osx/Installer.Mac"
GCM_SRC="$SRC/shared/Git-Credential-Manager"
GCM_UI_SRC="$SRC/shared/Git-Credential-Manager.UI.Avalonia"

# Build parameters
FRAMEWORK=net8.0
Expand Down
7 changes: 1 addition & 6 deletions src/shared/Atlassian.Bitbucket/Atlassian.Bitbucket.csproj
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net8.0</TargetFrameworks>
<TargetFrameworks Condition="'$(OSPlatform)'=='windows'">net8.0;net472</TargetFrameworks>
<TargetFramework>net8.0</TargetFramework>
<AssemblyName>Atlassian.Bitbucket</AssemblyName>
<RootNamespace>Atlassian.Bitbucket</RootNamespace>
<IsTestProject>false</IsTestProject>
Expand All @@ -13,10 +12,6 @@
<ProjectReference Include="..\Core\Core.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net472'">
<Reference Include="System.Net.Http" />
</ItemGroup>

<ItemGroup>
<AvaloniaResource Include="UI\Assets\atlassian-logo.png" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.Text.Json.Serialization;

namespace Atlassian.Bitbucket;

[JsonSourceGenerationOptions(
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNameCaseInsensitive = true
)]
[JsonSerializable(typeof(BitbucketTokenEndpointResponseJson))]
[JsonSerializable(typeof(Cloud.UserInfo), TypeInfoPropertyName = "Cloud_UserInfo")]
[JsonSerializable(typeof(DataCenter.UserInfo), TypeInfoPropertyName = "DataCenter_UserInfo")]
[JsonSerializable(typeof(DataCenter.LoginOptions))]
internal partial class BitbucketJsonSerializerContext : JsonSerializerContext
{
}
3 changes: 2 additions & 1 deletion src/shared/Atlassian.Bitbucket/BitbucketOAuth2Client.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using GitCredentialManager;
Expand Down Expand Up @@ -42,7 +43,7 @@ protected override bool TryCreateTokenEndpointResult(string json, out OAuth2Toke
// We override the token endpoint response parsing because the Bitbucket authority returns
// the non-standard 'scopes' property for the list of scopes, rather than the (optional)
// 'scope' (note the singular vs plural) property as outlined in the standard.
if (TryDeserializeJson(json, out BitbucketTokenEndpointResponseJson jsonObj))
if (TryDeserializeJson(json, BitbucketJsonSerializerContext.Default, out BitbucketTokenEndpointResponseJson jsonObj))
{
result = jsonObj.ToResult();
return true;
Expand Down
6 changes: 1 addition & 5 deletions src/shared/Atlassian.Bitbucket/Cloud/BitbucketRestApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,7 @@ public async Task<RestApiResult<IUserInfo>> GetUserInformationAsync(string userN

if (response.IsSuccessStatusCode)
{
var obj = JsonSerializer.Deserialize<UserInfo>(json,
new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
});
UserInfo obj = JsonSerializer.Deserialize(json, BitbucketJsonSerializerContext.Default.Cloud_UserInfo);

return new RestApiResult<IUserInfo>(response.StatusCode, obj);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,7 @@ public async Task<List<AuthenticationMethod>> GetAuthenticationMethodsAsync()

if (response.IsSuccessStatusCode)
{
var loginOptions = JsonSerializer.Deserialize<LoginOptions>(json,
new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
});
LoginOptions loginOptions = JsonSerializer.Deserialize(json, BitbucketJsonSerializerContext.Default.LoginOptions);

if (loginOptions.Results.Any(r => "LOGIN_FORM".Equals(r.Type)))
{
Expand Down Expand Up @@ -151,4 +146,4 @@ private Uri ApiUri
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
xmlns:vm="clr-namespace:Atlassian.Bitbucket.UI.ViewModels;assembly=Atlassian.Bitbucket"
xmlns:converters="clr-namespace:GitCredentialManager.UI.Converters;assembly=gcmcore"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:DataType="vm:CredentialsViewModel"
x:CompileBindings="True"
x:Class="Atlassian.Bitbucket.UI.Views.CredentialsView">
<Design.DataContext>
<vm:CredentialsViewModel/>
Expand Down
4 changes: 0 additions & 4 deletions src/shared/Core/Authentication/AuthenticationBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,7 @@ protected internal virtual async Task<IDictionary<string, string>> InvokeHelperA
// Write the standard input to the process if we have any to write
if (standardInput is not null)
{
#if NETFRAMEWORK
await standardInput.BaseStream.CopyToAsync(process.StandardInput.BaseStream);
#else
await standardInput.BaseStream.CopyToAsync(process.StandardInput.BaseStream, ct);
#endif
process.StandardInput.Close();
}

Expand Down
29 changes: 8 additions & 21 deletions src/shared/Core/Authentication/MicrosoftAuthentication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@
using GitCredentialManager.UI.ViewModels;
using GitCredentialManager.UI.Views;
using Microsoft.Identity.Client.AppConfig;

#if NETFRAMEWORK
using Microsoft.Identity.Client.Broker;
#endif

namespace GitCredentialManager.Authentication
{
Expand Down Expand Up @@ -508,15 +505,13 @@ private async Task<IPublicClientApplication> CreatePublicClientApplicationAsync(
// to save on the distribution size of the .NET builds (no need for MSALRuntime bits).
if (enableBroker)
{
#if NETFRAMEWORK
appBuilder.WithBroker(
new BrokerOptions(BrokerOptions.OperatingSystems.Windows)
{
Title = "Git Credential Manager",
MsaPassthrough = msaPt,
}
);
#endif
}

IPublicClientApplication app = appBuilder.Build();
Expand Down Expand Up @@ -808,7 +803,6 @@ public HttpClient GetHttpClient()

public bool CanUseBroker()
{
#if NETFRAMEWORK
// We only support the broker on Windows 10+ and in an interactive session
if (!Context.SessionManager.IsDesktopSession || !PlatformUtils.IsWindowsBrokerSupported())
{
Expand All @@ -827,34 +821,27 @@ public bool CanUseBroker()
}

return defaultValue;
#else
// OS broker requires .NET Framework right now until we migrate to .NET 5.0 (net5.0-windows10.x.y.z)
return false;
#endif
}

private bool CanUseEmbeddedWebView()
{
// If we're in an interactive session and on .NET Framework then MSAL can show the WinForms-based embedded UI
#if NETFRAMEWORK
return Context.SessionManager.IsDesktopSession;
#else
return false;
#endif
// If we're in an interactive session and on Windows then MSAL can show the WinForms-based embedded UI
return PlatformUtils.IsWindows() && Context.SessionManager.IsDesktopSession;
}

private void EnsureCanUseEmbeddedWebView()
{
#if NETFRAMEWORK
if (!Context.SessionManager.IsDesktopSession)
{
throw new Trace2InvalidOperationException(Context.Trace2,
"Embedded web view is not available without a desktop session.");
}
#else
throw new Trace2InvalidOperationException(Context.Trace2,
"Embedded web view is not available on .NET Core.");
#endif

if (!PlatformUtils.IsWindows())
{
throw new Trace2InvalidOperationException(Context.Trace2,
"Embedded web view is only available on Windows.");
}
}

private bool CanUseSystemWebView(IPublicClientApplication app, Uri redirectUri)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Text.Json.Serialization;

namespace GitCredentialManager.Authentication.OAuth.Json;

[JsonSourceGenerationOptions(
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNameCaseInsensitive = true
)]
[JsonSerializable(typeof(DeviceAuthorizationEndpointResponseJson))]
[JsonSerializable(typeof(ErrorResponseJson))]
[JsonSerializable(typeof(TokenEndpointResponseJson))]
public partial class OAuthJsonSerializerContext : JsonSerializerContext
{
}
23 changes: 11 additions & 12 deletions src/shared/Core/Authentication/OAuth/OAuth2Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Threading.Tasks;
using GitCredentialManager.Authentication.OAuth.Json;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace GitCredentialManager.Authentication.OAuth
{
Expand Down Expand Up @@ -213,7 +214,8 @@ public async Task<OAuth2DeviceCodeResult> GetDeviceCodeAsync(IEnumerable<string>
{
string json = await response.Content.ReadAsStringAsync();

if (response.IsSuccessStatusCode && TryDeserializeJson(json, out DeviceAuthorizationEndpointResponseJson jsonObj))
if (response.IsSuccessStatusCode && TryDeserializeJson(json, OAuthJsonSerializerContext.Default,
out DeviceAuthorizationEndpointResponseJson jsonObj))
{
return jsonObj.ToResult();
}
Expand Down Expand Up @@ -321,12 +323,9 @@ public async Task<OAuth2TokenResult> GetTokenByDeviceCodeAsync(OAuth2DeviceCodeR
return result;
}

var error = JsonSerializer.Deserialize<ErrorResponseJson>(json, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
TryDeserializeJson(json, OAuthJsonSerializerContext.Default, out ErrorResponseJson error);

switch (error.Error)
switch (error?.Error)
{
case OAuth2Constants.DeviceAuthorization.Errors.AuthorizationPending:
// Retry with the current polling interval value
Expand Down Expand Up @@ -358,7 +357,7 @@ public async Task<OAuth2TokenResult> GetTokenByDeviceCodeAsync(OAuth2DeviceCodeR

protected virtual bool TryCreateTokenEndpointResult(string json, out OAuth2TokenResult result)
{
if (TryDeserializeJson(json, out TokenEndpointResponseJson jsonObj))
if (TryDeserializeJson(json, OAuthJsonSerializerContext.Default, out TokenEndpointResponseJson jsonObj))
{
result = jsonObj.ToResult();
return true;
Expand All @@ -368,9 +367,9 @@ protected virtual bool TryCreateTokenEndpointResult(string json, out OAuth2Token
return false;
}

protected virtual bool TryCreateExceptionFromResponse(string json, out OAuth2Exception exception)
private static bool TryCreateExceptionFromResponse(string json, out OAuth2Exception exception)
{
if (TryDeserializeJson(json, out ErrorResponseJson obj))
if (TryDeserializeJson(json, OAuthJsonSerializerContext.Default, out ErrorResponseJson obj))
{
exception = obj.ToException();
return true;
Expand All @@ -397,7 +396,7 @@ private HttpRequestMessage CreateRequestMessage(HttpMethod method, Uri requestUr
return request;
}

protected Exception CreateExceptionFromResponse(string json)
private Exception CreateExceptionFromResponse(string json)
{
if (TryCreateExceptionFromResponse(json, out OAuth2Exception exception))
{
Expand All @@ -410,11 +409,11 @@ protected Exception CreateExceptionFromResponse(string json)
return new Trace2OAuth2Exception(_trace2, message, format);
}

protected static bool TryDeserializeJson<T>(string json, out T obj)
protected static bool TryDeserializeJson<T>(string json, JsonSerializerContext context, out T obj)
{
try
{
obj = JsonSerializer.Deserialize<T>(json);
obj = (T)JsonSerializer.Deserialize(json, typeof(T), context);
return true;
}
catch
Expand Down
5 changes: 5 additions & 0 deletions src/shared/Core/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ public static class Constants
public const string GcmDataDirectoryName = ".gcm";

public const string MacOSBundleId = "git-credential-manager";

public const string WindowsPlatformName = "windows";
public const string LinuxPlatformName = "linux";
public const string MacOSPlatformName = "osx";

public static readonly Guid DevBoxPartnerId = new("e3171dd9-9a5f-e5be-b36c-cc7c4f3f3bcf");

/// <summary>
Expand Down
Loading