Skip to content
This repository was archived by the owner on Dec 5, 2024. It is now read-only.

Commit b30fc38

Browse files
committedOct 12, 2018
Initial support for GitHub Enterprise
1 parent 1c53148 commit b30fc38

38 files changed

+1264
-403
lines changed
 

Diff for: ‎octorun/bin/octorun-meta

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env node
2+
3+
require('../src/bin/app-meta.js');

Diff for: ‎octorun/src/api.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
var config = require("./configuration");
22
var octokitWrapper = require("./octokit");
33

4-
function ApiWrapper() {
4+
function ApiWrapper(host) {
55
if (!config.appName) {
66
throw "appName missing";
77
}
@@ -10,7 +10,7 @@ function ApiWrapper() {
1010
throw "token missing";
1111
}
1212

13-
this.octokit = octokitWrapper.createOctokit(config.appName);
13+
this.octokit = octokitWrapper.createOctokit(config.appName, host);
1414

1515
this.octokit.authenticate({
1616
type: "oauth",

Diff for: ‎octorun/src/authentication.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ var twoFactorRegex = new RegExp("must specify two-factor authentication otp code
55

66
var scopes = ["user", "repo"];
77

8-
var handleAuthentication = function (username, password, onSuccess, onFailure, twoFactor) {
8+
var handleAuthentication = function (username, password, onSuccess, onFailure, twoFactor, host) {
99
if (!config.clientId || !config.clientSecret) {
1010
throw "clientId and/or clientSecret missing";
1111
}
@@ -14,7 +14,7 @@ var handleAuthentication = function (username, password, onSuccess, onFailure, t
1414
throw "appName missing";
1515
}
1616

17-
var octokit = octokitWrapper.createOctokit(config.appName);
17+
var octokit = octokitWrapper.createOctokit(config.appName, host);
1818

1919
octokit.authenticate({
2020
type: "basic",

Diff for: ‎octorun/src/bin/app-login.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ var output = require('../output');
66
commander
77
.version(package.version)
88
.option('-t, --twoFactor')
9+
.option('-h, --host <host>')
910
.parse(process.argv);
1011

1112
var handleAuthentication = function (username, password, twoFactor) {
@@ -18,7 +19,7 @@ var handleAuthentication = function (username, password, twoFactor) {
1819
}
1920
}, function (error) {
2021
output.error(error);
21-
}, twoFactor);
22+
}, twoFactor, commander.host);
2223
}
2324

2425
var encoding = 'utf-8';

Diff for: ‎octorun/src/bin/app-meta.js

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
var commander = require('commander');
2+
var package = require('../../package.json');
3+
var output = require('../output');
4+
5+
commander
6+
.version(package.version)
7+
.option('-h, --host <host>')
8+
.parse(process.argv);
9+
10+
var host = commander.host;
11+
var port = 443;
12+
var scheme = 'https';
13+
14+
if (host) {
15+
var https = require(scheme);
16+
var options = {
17+
protocol: scheme + ':',
18+
hostname: host,
19+
port: port,
20+
path: '/api/v3/meta',
21+
method: 'GET',
22+
headers: {
23+
'Content-Type': 'application/json'
24+
}
25+
};
26+
27+
var req = https.request(options, function (res) {
28+
var success = res.statusCode == 200;
29+
30+
if(!success) {
31+
output.error(res.statusCode);
32+
} else {
33+
res.on('data', function (d) {
34+
output.custom("success", d, true);
35+
});
36+
37+
res.on('end', function (d) {
38+
process.exit();
39+
});
40+
}
41+
});
42+
43+
req.on('error', function (error) {
44+
output.error(error);
45+
});
46+
47+
req.end();
48+
}
49+
else {
50+
commander.help();
51+
process.exit(-1);
52+
}

Diff for: ‎octorun/src/bin/app-organizations.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ var output = require('../output');
55

66
commander
77
.version(package.version)
8+
.option('-h, --host <host>')
89
.parse(process.argv);
910

1011
try {
11-
12-
var apiWrapper = new ApiWrapper();
12+
var apiWrapper = new ApiWrapper(commander.host);
1313
apiWrapper.getOrgs(function (error, result) {
1414
if (error) {
1515
output.error(error);

Diff for: ‎octorun/src/bin/app-publish.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ commander
99
.option('-d, --description <description>')
1010
.option('-o, --organization <organization>')
1111
.option('-p, --private')
12+
.option('-h, --host <host>')
1213
.parse(process.argv);
1314

1415
if(!commander.repository)
@@ -23,7 +24,7 @@ if (commander.private) {
2324
}
2425

2526
try {
26-
var apiWrapper = new ApiWrapper();
27+
var apiWrapper = new ApiWrapper(commander.host);
2728

2829
apiWrapper.publish(commander.repository, commander.description, private, commander.organization,
2930
function (error, result) {

Diff for: ‎octorun/src/bin/app-validate.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ var output = require('../output');
55

66
commander
77
.version(package.version)
8+
.option('-h, --host <host>')
89
.parse(process.argv);
910

1011
try {
11-
var apiWrapper = new ApiWrapper();
12+
var apiWrapper = new ApiWrapper(commander.host);
1213

1314
apiWrapper.verifyUser(function (error, result) {
1415
if (error) {

Diff for: ‎octorun/src/bin/app.js

+1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ commander
99
.command('organizations', 'Get Organizations')
1010
.command('publish', 'Publish')
1111
.command('usage', 'Usage')
12+
.command('meta', 'Get Server Meta Data')
1213
.parse(process.argv);

Diff for: ‎octorun/src/octokit.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
var Octokit = require('octokit-rest-for-node-v0.12');
22

3-
var createOctokit = function (appName) {
4-
return Octokit({
3+
var createOctokit = function (appName, host) {
4+
var octokitConfiguration = {
55
timeout: 0,
66
requestMedia: 'application/vnd.github.v3+json',
77
headers: {
88
'user-agent': appName
99
}
10-
});
10+
};
11+
12+
if(host) {
13+
octokitConfiguration.baseUrl = "https://" + host;
14+
}
15+
16+
return Octokit(octokitConfiguration);
1117
};
1218

1319
module.exports = { createOctokit: createOctokit };

Diff for: ‎octorun/version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
902910f4
1+
902910f45

Diff for: ‎script

Diff for: ‎src/GitHub.Api/Application/ApiClient.cs

+109-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Net;
45
using GitHub.Logging;
56
using System.Runtime.Serialization;
67
using System.Text;
8+
using System.Text.RegularExpressions;
9+
using GitHub.Unity.Json;
710

811
namespace GitHub.Unity
912
{
1013
class ApiClient : IApiClient
1114
{
1215
private static readonly ILogging logger = LogHelper.GetLogger<ApiClient>();
16+
private static readonly Regex httpStatusErrorRegex = new Regex("(?<=[a-z])([A-Z])", RegexOptions.Compiled);
17+
1318
public HostAddress HostAddress { get; }
1419
public UriString OriginalUrl { get; }
1520

@@ -30,6 +35,9 @@ public ApiClient(UriString hostUrl, IKeychain keychain, IProcessManager processM
3035

3136
HostAddress = HostAddress.Create(host);
3237
OriginalUrl = host;
38+
39+
logger.Trace("OriginalUrl: {1}", HostAddress.ToString(), OriginalUrl.ToString());
40+
3341
this.keychain = keychain;
3442
this.processManager = processManager;
3543
this.taskManager = taskManager;
@@ -52,7 +60,10 @@ public void CreateRepository(string name, string description, bool isPrivate,
5260
// this validates the user, again
5361
GetCurrentUser();
5462

55-
var command = new StringBuilder("publish -r \"");
63+
var command = new StringBuilder("publish -h ");
64+
command.Append(OriginalUrl.Host);
65+
66+
command.Append(" -r \"");
5667
command.Append(name);
5768
command.Append("\"");
5869

@@ -75,7 +86,13 @@ public void CreateRepository(string name, string description, bool isPrivate,
7586
command.Append(" -p");
7687
}
7788

78-
var octorunTask = new OctorunTask(taskManager.Token, keychain, environment, command.ToString())
89+
var adapter = keychain.Connect(OriginalUrl);
90+
if (adapter.Credential == null)
91+
{
92+
throw new ApiClientException("No Credentials found");
93+
}
94+
95+
var octorunTask = new OctorunTask(taskManager.Token, environment, command.ToString(), adapter.Credential.Token)
7996
.Configure(processManager);
8097

8198
var ret = octorunTask.RunSynchronously();
@@ -103,13 +120,88 @@ public void CreateRepository(string name, string description, bool isPrivate,
103120
.Start();
104121
}
105122

123+
public void GetServerMeta(Action<GitHubHostMeta> onSuccess, Action<Exception> onError = null)
124+
{
125+
Guard.ArgumentNotNull(onSuccess, nameof(onSuccess));
126+
new FuncTask<GitHubHostMeta>(taskManager.Token, () =>
127+
{
128+
var octorunTask = new OctorunTask(taskManager.Token, environment, "meta -h " + OriginalUrl.Host)
129+
.Configure(processManager);
130+
131+
var ret = octorunTask.RunSynchronously();
132+
if (ret.IsSuccess)
133+
{
134+
var deserializeObject = SimpleJson.DeserializeObject<Dictionary<string, object>>(ret.Output[0]);
135+
136+
return new GitHubHostMeta()
137+
{
138+
InstalledVersion = (string)deserializeObject["installed_version"],
139+
GithubServicesSha = (string)deserializeObject["github_services_sha"],
140+
VerifiablePasswordAuthentication = (bool)deserializeObject["verifiable_password_authentication"]
141+
};
142+
}
143+
144+
var message = ret.GetApiErrorMessage();
145+
146+
logger.Trace("Message: {0}", message);
147+
148+
if (message != null)
149+
{
150+
if (message.Contains("ETIMEDOUT", StringComparison.InvariantCulture))
151+
{
152+
message = "Connection timed out.";
153+
}
154+
else if (message.Contains("ECONNREFUSED", StringComparison.InvariantCulture))
155+
{
156+
message = "Connection refused.";
157+
}
158+
else if (message.Contains("ENOTFOUND", StringComparison.InvariantCulture))
159+
{
160+
message = "Address not found.";
161+
}
162+
else
163+
{
164+
int httpStatusCode;
165+
if (int.TryParse(message, out httpStatusCode))
166+
{
167+
var httpStatus = ((HttpStatusCode)httpStatusCode).ToString();
168+
message = httpStatusErrorRegex.Replace(httpStatus, " $1");
169+
}
170+
}
171+
}
172+
else
173+
{
174+
message = "Error getting server meta";
175+
}
176+
177+
throw new ApiClientException(message);
178+
})
179+
.FinallyInUI((success, ex, meta) =>
180+
{
181+
if (success)
182+
onSuccess(meta);
183+
else
184+
{
185+
logger.Error(ex, "Error getting server meta");
186+
onError?.Invoke(ex);
187+
}
188+
})
189+
.Start();
190+
}
191+
106192
public void GetOrganizations(Action<Organization[]> onSuccess, Action<Exception> onError = null)
107193
{
108194
Guard.ArgumentNotNull(onSuccess, nameof(onSuccess));
109195
new FuncTask<Organization[]>(taskManager.Token, () =>
110196
{
111-
var octorunTask = new OctorunTask(taskManager.Token, keychain, environment,
112-
"organizations")
197+
var adapter = keychain.Connect(OriginalUrl);
198+
if (adapter.Credential == null)
199+
{
200+
throw new ApiClientException("No Credentials found");
201+
}
202+
203+
var octorunTask = new OctorunTask(taskManager.Token, environment,
204+
"organizations -h " + OriginalUrl.Host, adapter.Credential.Token)
113205
.Configure(processManager);
114206

115207
var ret = octorunTask.RunSynchronously();
@@ -247,7 +339,12 @@ private GitHubUser GetValidatedGitHubUser(Connection keychainConnection, IKeycha
247339
{
248340
try
249341
{
250-
var octorunTask = new OctorunTask(taskManager.Token, keychain, environment, "validate")
342+
if (keychainAdapter.Credential == null)
343+
{
344+
throw new ApiClientException("No Credentials found");
345+
}
346+
347+
var octorunTask = new OctorunTask(taskManager.Token, environment, "validate -h " + OriginalUrl.Host, keychainAdapter.Credential.Token)
251348
.Configure(processManager);
252349

253350
var ret = octorunTask.RunSynchronously();
@@ -283,6 +380,13 @@ private GitHubUser GetValidatedGitHubUser(Connection keychainConnection, IKeycha
283380
}
284381
}
285382

383+
class GitHubHostMeta
384+
{
385+
public bool VerifiablePasswordAuthentication { get; set; }
386+
public string GithubServicesSha { get; set; }
387+
public string InstalledVersion { get; set; }
388+
}
389+
286390
class GitHubUser
287391
{
288392
public string Name { get; set; }

Diff for: ‎src/GitHub.Api/Application/IApiClient.cs

+1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ void CreateRepository(string name, string description, bool isPrivate,
1313
void ContinueLogin(LoginResult loginResult, string code);
1414
ITask Logout(UriString host);
1515
void GetCurrentUser(Action<GitHubUser> onSuccess, Action<Exception> onError = null);
16+
void GetServerMeta(Action<GitHubHostMeta> onSuccess, Action<Exception> onError = null);
1617
}
1718
}

Diff for: ‎src/GitHub.Api/Authentication/ILoginManager.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace GitHub.Unity
88
interface ILoginManager
99
{
1010
/// <summary>
11-
/// Attempts to log into a GitHub server.
11+
/// Attempts to log into a GitHub server with a username and password.
1212
/// </summary>
1313
/// <param name="host"></param>
1414
/// <param name="username">The username.</param>
@@ -18,6 +18,7 @@ interface ILoginManager
1818
/// The login authorization failed.
1919
/// </exception>
2020
LoginResultData Login(UriString host, string username, string password);
21+
2122
LoginResultData ContinueLogin(LoginResultData loginResultData, string twofacode);
2223

2324
/// <summary>

Diff for: ‎src/GitHub.Api/Authentication/LoginManager.cs

+7-7
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public LoginResultData Login(
7373

7474
if (loginResultData.Code == LoginResultCodes.Success)
7575
{
76-
username = RetrieveUsername(loginResultData, username);
76+
username = RetrieveUsername(loginResultData.Token, username, host);
7777
keychainAdapter.Update(loginResultData.Token, username);
7878
keychain.SaveToSystem(host);
7979
}
@@ -113,7 +113,7 @@ public LoginResultData ContinueLogin(LoginResultData loginResultData, string two
113113
}
114114

115115
keychainAdapter.Update(loginResultData.Token, username);
116-
username = RetrieveUsername(loginResultData, username);
116+
username = RetrieveUsername(loginResultData.Token, username, host);
117117
keychainAdapter.Update(loginResultData.Token, username);
118118
keychain.SaveToSystem(host);
119119

@@ -147,9 +147,9 @@ private LoginResultData TryLogin(
147147
{
148148
var hasTwoFactorCode = code != null;
149149

150-
var arguments = hasTwoFactorCode ? "login --twoFactor" : "login";
151-
var loginTask = new OctorunTask(taskManager.Token, keychain, environment,
152-
arguments);
150+
var arguments = (hasTwoFactorCode ? "login --twoFactor -h " : "login -h ") + host.Host;
151+
152+
var loginTask = new OctorunTask(taskManager.Token, environment, arguments);
153153
loginTask.Configure(processManager, withInput: true);
154154
loginTask.OnStartProcess += proc =>
155155
{
@@ -180,14 +180,14 @@ private LoginResultData TryLogin(
180180
return new LoginResultData(LoginResultCodes.Failed, ret.GetApiErrorMessage() ?? "Failed.", host);
181181
}
182182

183-
private string RetrieveUsername(LoginResultData loginResultData, string username)
183+
private string RetrieveUsername(string token, string username, UriString host)
184184
{
185185
if (!username.Contains("@"))
186186
{
187187
return username;
188188
}
189189

190-
var octorunTask = new OctorunTask(taskManager.Token, keychain, environment, "validate")
190+
var octorunTask = new OctorunTask(taskManager.Token, environment, "validate -h " + host.Host, token)
191191
.Configure(processManager);
192192

193193
var validateResult = octorunTask.RunSynchronously();

Diff for: ‎src/GitHub.Api/Installer/CopyHelper.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ public static void Copy(NPath fromPath, NPath toPath)
1414
{
1515
try
1616
{
17-
1817
CopyFolder(fromPath, toPath);
1918
}
2019
catch (Exception ex1)
@@ -39,7 +38,7 @@ public static void Copy(NPath fromPath, NPath toPath)
3938
public static void CopyFolder(NPath fromPath, NPath toPath)
4039
{
4140
Logger.Trace("CopyFolder fromPath: {0} toPath:{1}", fromPath.ToString(), toPath.ToString());
42-
41+
toPath.DeleteIfExists();
4342
toPath.EnsureParentDirectoryExists();
4443
fromPath.Move(toPath);
4544
}

Diff for: ‎src/GitHub.Api/Installer/OctorunInstaller.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public class OctorunInstallDetails
8686
public const string DefaultZipMd5Url = "http://github-vs.s3.amazonaws.com/unity/octorun/octorun.zip.md5";
8787
public const string DefaultZipUrl = "http://github-vs.s3.amazonaws.com/unity/octorun/octorun.zip";
8888

89-
public const string PackageVersion = "902910f4";
89+
public const string PackageVersion = "902910f45";
9090
private const string PackageName = "octorun";
9191
private const string zipFile = "octorun.zip";
9292

Diff for: ‎src/GitHub.Api/Resources/octorun.zip

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
version https://git-lfs.github.com/spec/v1
2-
oid sha256:3550059c5aceda73bc5ad30889c3fa7ba4e0abafeb17022721a777a3fa16dcf4
3-
size 212152
2+
oid sha256:ffc11593937b7a03f3ef5450ec07699a0ae2f23d0785eb11fb827c1eccc82b20
3+
size 220342

Diff for: ‎src/GitHub.Api/Resources/octorun.zip.md5

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
e20177a919ff49abab5d00f83080c622
1+
0e2d411bfe82bc5b579703f5604ceed0

Diff for: ‎src/GitHub.Api/Tasks/OctorunTask.cs

+22-19
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ class OctorunTask : ProcessTask<OctorunResult>
6060
private readonly NPath pathToOctorunJs;
6161
private readonly string arguments;
6262

63-
public OctorunTask(CancellationToken token, IKeychain keychain, IEnvironment environment,
63+
public OctorunTask(CancellationToken token, IEnvironment environment,
6464
string arguments,
65+
string userToken = null,
6566
IOutputProcessor<OctorunResult> processor = null)
6667
: base(token, processor ?? new OctorunResultOutputProcessor())
6768
{
@@ -71,24 +72,26 @@ public OctorunTask(CancellationToken token, IKeychain keychain, IEnvironment env
7172
this.pathToOctorunJs = environment.OctorunScriptPath;
7273
this.arguments = $"\"{pathToOctorunJs}\" {arguments}";
7374

74-
var cloneUrl = environment.Repository?.CloneUrl;
75-
var host = String.IsNullOrEmpty(cloneUrl)
76-
? UriString.ToUriString(HostAddress.GitHubDotComHostAddress.WebUri)
77-
: new UriString(cloneUrl.ToRepositoryUri()
78-
.GetComponents(UriComponents.SchemeAndServer, UriFormat.SafeUnescaped));
79-
80-
var adapter = keychain.Connect(host);
81-
if (adapter.Credential?.Token != null)
82-
{
83-
userToken = adapter.Credential.Token;
84-
}
85-
else
86-
{
87-
// use a cached adapter if there is one filled out
88-
adapter = keychain.LoadFromSystem(host);
89-
if (adapter != null)
90-
userToken = adapter.Credential.Token;
91-
}
75+
this.userToken = userToken;
76+
77+
// var cloneUrl = environment.Repository?.CloneUrl;
78+
// var host = String.IsNullOrEmpty(cloneUrl)
79+
// ? UriString.ToUriString(HostAddress.GitHubDotComHostAddress.WebUri)
80+
// : new UriString(cloneUrl.ToRepositoryUri()
81+
// .GetComponents(UriComponents.SchemeAndServer, UriFormat.SafeUnescaped));
82+
//
83+
// var adapter = keychain.Connect(host);
84+
// if (adapter.Credential?.Token != null)
85+
// {
86+
// userToken = adapter.Credential.Token;
87+
// }
88+
// else
89+
// {
90+
// // use a cached adapter if there is one filled out
91+
// adapter = keychain.LoadFromSystem(host);
92+
// if (adapter != null)
93+
// userToken = adapter.Credential.Token;
94+
// }
9295
}
9396

9497
public override void Configure(ProcessStartInfo psi)

Diff for: ‎src/UnityExtension/Assets/Editor/GitHub.Unity/GitHub.Unity.45.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@
8686
<Compile Include="Properties\AssemblyInfo.cs" />
8787
<Compile Include="Logging\UnityLogAdapter.cs" />
8888
<Compile Include="EntryPoint.cs" />
89+
<Compile Include="UI\GitHubEnterpriseAuthenticationView.cs" />
90+
<Compile Include="UI\GitHubAuthenticationView.cs" />
8991
<Compile Include="UpdateCheck.cs" />
9092
<Compile Include="Misc\Installer.cs" />
9193
<Compile Include="UI\BaseWindow.cs" />

Diff for: ‎src/UnityExtension/Assets/Editor/GitHub.Unity/GitHub.Unity.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@
7777
<Compile Include="Properties\AssemblyInfo.cs" />
7878
<Compile Include="Logging\UnityLogAdapter.cs" />
7979
<Compile Include="EntryPoint.cs" />
80+
<Compile Include="UI\GitHubAuthenticationView.cs" />
81+
<Compile Include="UI\GitHubEnterpriseAuthenticationView.cs" />
8082
<Compile Include="UpdateCheck.cs" />
8183
<Compile Include="Misc\Installer.cs" />
8284
<Compile Include="UI\BaseWindow.cs" />

Diff for: ‎src/UnityExtension/Assets/Editor/GitHub.Unity/Services/AuthenticationService.cs

+19-1
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ IEnvironment environment
1616
client = new ApiClient(host, keychain, processManager, taskManager, environment);
1717
}
1818

19+
public HostAddress HostAddress { get { return client.HostAddress; } }
20+
1921
public void Login(string username, string password, Action<string> twofaRequired, Action<bool, string> authResult)
2022
{
21-
2223
loginResultData = null;
2324
client.Login(username, password, r =>
2425
{
@@ -27,11 +28,28 @@ public void Login(string username, string password, Action<string> twofaRequired
2728
}, authResult);
2829
}
2930

31+
public void LoginWithToken(string token, Action<string> twofaRequired, Action<bool, string> authResult)
32+
{
33+
Login("[token]", token, twofaRequired, authResult);
34+
}
35+
36+
3037
public void LoginWith2fa(string code)
3138
{
3239
if (loginResultData == null)
3340
throw new InvalidOperationException("Call Login() first");
3441
client.ContinueLogin(loginResultData, code);
3542
}
43+
44+
public void GetServerMeta(Action<GitHubHostMeta> serverMeta, Action<string> error)
45+
{
46+
loginResultData = null;
47+
client.GetServerMeta(data =>
48+
{
49+
serverMeta(data);
50+
}, exception => {
51+
error(exception.Message);
52+
});
53+
}
3654
}
3755
}

Diff for: ‎src/UnityExtension/Assets/Editor/GitHub.Unity/UI/AuthenticationView.cs

+57-197
Original file line numberDiff line numberDiff line change
@@ -10,253 +10,113 @@ class AuthenticationView : Subview
1010
{
1111
private static readonly Vector2 viewSize = new Vector2(290, 290);
1212

13-
private const string CredentialsNeedRefreshMessage = "We've detected that your stored credentials are out of sync with your current user. This can happen if you have signed in to git outside of Unity. Sign in again to refresh your credentials.";
14-
private const string NeedAuthenticationMessage = "We need you to authenticate first";
1513
private const string WindowTitle = "Authenticate";
16-
private const string UsernameLabel = "Username";
17-
private const string PasswordLabel = "Password";
18-
private const string TwofaLabel = "2FA Code";
19-
private const string LoginButton = "Sign in";
20-
private const string BackButton = "Back";
21-
private const string AuthTitle = "Sign in to GitHub";
22-
private const string TwofaTitle = "Two-Factor Authentication";
23-
private const string TwofaDescription = "Open the two-factor authentication app on your device to view your 2FA code and verify your identity.";
24-
private const string TwofaButton = "Verify";
25-
26-
[SerializeField] private Vector2 scroll;
27-
[SerializeField] private string username = string.Empty;
28-
[SerializeField] private string two2fa = string.Empty;
29-
[SerializeField] private string message;
30-
[SerializeField] private string errorMessage;
31-
[SerializeField] private bool need2fa;
3214

3315
[NonSerialized] private bool isBusy;
34-
[NonSerialized] private bool enterPressed;
35-
[NonSerialized] private string password = string.Empty;
36-
[NonSerialized] private AuthenticationService authenticationService;
3716

17+
[SerializeField] private SubTab changeTab = SubTab.GitHub;
18+
[SerializeField] private SubTab activeTab = SubTab.GitHub;
19+
20+
[SerializeField] private GitHubAuthenticationView gitHubAuthenticationView;
21+
[SerializeField] private GitHubEnterpriseAuthenticationView gitHubEnterpriseAuthenticationView;
3822

3923
public override void InitializeView(IView parent)
4024
{
4125
base.InitializeView(parent);
42-
need2fa = isBusy = false;
43-
message = errorMessage = null;
4426
Title = WindowTitle;
4527
Size = viewSize;
28+
29+
gitHubAuthenticationView = gitHubAuthenticationView ?? new GitHubAuthenticationView();
30+
gitHubEnterpriseAuthenticationView = gitHubEnterpriseAuthenticationView ?? new GitHubEnterpriseAuthenticationView();
31+
32+
gitHubAuthenticationView.InitializeView(parent);
33+
gitHubEnterpriseAuthenticationView.InitializeView(parent);
4634
}
4735

4836
public void Initialize(Exception exception)
4937
{
50-
var usernameMismatchException = exception as TokenUsernameMismatchException;
51-
if (usernameMismatchException != null)
52-
{
53-
message = CredentialsNeedRefreshMessage;
54-
username = usernameMismatchException.CachedUsername;
55-
}
56-
57-
var keychainEmptyException = exception as KeychainEmptyException;
58-
if (keychainEmptyException != null)
59-
{
60-
message = NeedAuthenticationMessage;
61-
}
62-
63-
if (usernameMismatchException == null && keychainEmptyException == null)
64-
{
65-
message = exception.Message;
66-
}
38+
6739
}
6840

6941
public override void OnGUI()
7042
{
71-
HandleEnterPressed();
72-
73-
EditorGUIUtility.labelWidth = 90f;
74-
75-
scroll = GUILayout.BeginScrollView(scroll);
76-
{
77-
GUILayout.BeginHorizontal(Styles.AuthHeaderBoxStyle);
78-
{
79-
GUILayout.Label(AuthTitle, Styles.HeaderRepoLabelStyle);
80-
}
81-
GUILayout.EndHorizontal();
82-
83-
GUILayout.BeginVertical();
84-
{
85-
if (!need2fa)
86-
{
87-
OnGUILogin();
88-
}
89-
else
90-
{
91-
OnGUI2FA();
92-
}
93-
}
94-
95-
GUILayout.EndVertical();
96-
}
97-
GUILayout.EndScrollView();
43+
DoToolbarGUI();
44+
ActiveView.OnGUI();
9845
}
9946

100-
private void HandleEnterPressed()
47+
public override bool IsBusy
10148
{
102-
if (Event.current.type != EventType.KeyDown)
103-
return;
104-
105-
enterPressed = Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.KeypadEnter;
106-
if (enterPressed)
107-
Event.current.Use();
49+
get { return isBusy; }
10850
}
10951

110-
private void OnGUILogin()
52+
private static SubTab TabButton(SubTab tab, string title, SubTab currentTab)
11153
{
112-
EditorGUI.BeginDisabledGroup(isBusy);
113-
{
114-
ShowMessage();
54+
return GUILayout.Toggle(currentTab == tab, title, EditorStyles.toolbarButton) ? tab : currentTab;
55+
}
11556

116-
EditorGUILayout.Space();
57+
private enum SubTab
58+
{
59+
None,
60+
GitHub,
61+
GitHubEnterprise
62+
}
11763

118-
GUILayout.BeginHorizontal();
64+
private void DoToolbarGUI()
65+
{
66+
GUILayout.BeginHorizontal(EditorStyles.toolbar);
67+
{
68+
EditorGUI.BeginChangeCheck();
11969
{
120-
username = EditorGUILayout.TextField(UsernameLabel ,username, Styles.TextFieldStyle);
70+
changeTab = TabButton(SubTab.GitHub, "GitHub", changeTab);
71+
changeTab = TabButton(SubTab.GitHubEnterprise, "GitHub Enterprise", changeTab);
12172
}
122-
GUILayout.EndHorizontal();
12373

124-
EditorGUILayout.Space();
125-
126-
GUILayout.BeginHorizontal();
74+
if (EditorGUI.EndChangeCheck())
12775
{
128-
password = EditorGUILayout.PasswordField(PasswordLabel, password, Styles.TextFieldStyle);
76+
UpdateActiveTab();
12977
}
130-
GUILayout.EndHorizontal();
131-
132-
EditorGUILayout.Space();
13378

134-
ShowErrorMessage();
135-
136-
GUILayout.Space(Styles.BaseSpacing + 3);
137-
GUILayout.BeginHorizontal();
138-
{
139-
GUILayout.FlexibleSpace();
140-
if (GUILayout.Button(LoginButton) || (!isBusy && enterPressed))
141-
{
142-
GUI.FocusControl(null);
143-
isBusy = true;
144-
AuthenticationService.Login(username, password, DoRequire2fa, DoResult);
145-
}
146-
}
147-
GUILayout.EndHorizontal();
79+
GUILayout.FlexibleSpace();
14880
}
149-
EditorGUI.EndDisabledGroup();
81+
EditorGUILayout.EndHorizontal();
15082
}
15183

152-
private void OnGUI2FA()
84+
private void UpdateActiveTab()
15385
{
154-
GUILayout.BeginVertical();
86+
if (changeTab != activeTab)
15587
{
156-
GUILayout.Label(TwofaTitle, EditorStyles.boldLabel);
157-
GUILayout.Label(TwofaDescription, EditorStyles.wordWrappedLabel);
158-
159-
EditorGUI.BeginDisabledGroup(isBusy);
160-
{
161-
EditorGUILayout.Space();
162-
two2fa = EditorGUILayout.TextField(TwofaLabel, two2fa, Styles.TextFieldStyle);
163-
EditorGUILayout.Space();
164-
ShowErrorMessage();
165-
166-
GUILayout.BeginHorizontal();
167-
{
168-
GUILayout.FlexibleSpace();
169-
if (GUILayout.Button(BackButton))
170-
{
171-
GUI.FocusControl(null);
172-
Clear();
173-
}
174-
175-
if (GUILayout.Button(TwofaButton) || (!isBusy && enterPressed))
176-
{
177-
GUI.FocusControl(null);
178-
isBusy = true;
179-
AuthenticationService.LoginWith2fa(two2fa);
180-
}
181-
}
182-
GUILayout.EndHorizontal();
183-
184-
EditorGUILayout.Space();
185-
}
186-
EditorGUI.EndDisabledGroup();
88+
var fromView = ActiveView;
89+
activeTab = changeTab;
90+
var toView = ActiveView;
91+
SwitchView(fromView, toView);
18792
}
188-
GUILayout.EndVertical();
18993
}
190-
191-
private void DoRequire2fa(string msg)
94+
private void SwitchView(Subview fromView, Subview toView)
19295
{
193-
need2fa = true;
194-
errorMessage = msg;
195-
isBusy = false;
196-
Redraw();
197-
}
198-
199-
private void Clear()
200-
{
201-
need2fa = false;
202-
errorMessage = null;
203-
isBusy = false;
204-
Redraw();
205-
}
206-
207-
private void DoResult(bool success, string msg)
208-
{
209-
isBusy = false;
210-
if (success)
211-
{
212-
UsageTracker.IncrementAuthenticationViewButtonAuthentication();
213-
214-
Clear();
215-
Finish(true);
216-
}
217-
else
218-
{
219-
errorMessage = msg;
220-
Redraw();
221-
}
222-
}
96+
GUI.FocusControl(null);
22397

224-
private void ShowMessage()
225-
{
226-
if (message != null)
227-
{
228-
EditorGUILayout.HelpBox(message, MessageType.Warning);
229-
}
230-
}
98+
if (fromView != null)
99+
fromView.OnDisable();
100+
toView.OnEnable();
231101

232-
private void ShowErrorMessage()
233-
{
234-
if (errorMessage != null)
235-
{
236-
EditorGUILayout.HelpBox(errorMessage, MessageType.Error);
237-
}
102+
// this triggers a repaint
103+
Parent.Redraw();
238104
}
239105

240-
private AuthenticationService AuthenticationService
106+
private Subview ActiveView
241107
{
242108
get
243109
{
244-
if (authenticationService == null)
110+
switch (activeTab)
245111
{
246-
UriString host = Repository != null ? Repository.CloneUrl : null;
247-
AuthenticationService = new AuthenticationService(host, Platform.Keychain, Manager.ProcessManager, Manager.TaskManager, Environment);
112+
case SubTab.GitHub:
113+
return gitHubAuthenticationView;
114+
case SubTab.GitHubEnterprise:
115+
return gitHubEnterpriseAuthenticationView;
116+
default:
117+
throw new NotImplementedException();
248118
}
249-
return authenticationService;
250-
}
251-
set
252-
{
253-
authenticationService = value;
254119
}
255120
}
256-
257-
public override bool IsBusy
258-
{
259-
get { return isBusy; }
260-
}
261121
}
262122
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
using System;
2+
using System.Threading;
3+
using UnityEngine;
4+
using UnityEditor;
5+
6+
namespace GitHub.Unity
7+
{
8+
[Serializable]
9+
class GitHubAuthenticationView : Subview
10+
{
11+
private static readonly Vector2 viewSize = new Vector2(290, 290);
12+
13+
private const string CredentialsNeedRefreshMessage = "We've detected that your stored credentials are out of sync with your current user. This can happen if you have signed in to git outside of Unity. Sign in again to refresh your credentials.";
14+
private const string NeedAuthenticationMessage = "We need you to authenticate first";
15+
private const string WindowTitle = "Authenticate";
16+
private const string UsernameLabel = "Username";
17+
private const string PasswordLabel = "Password";
18+
private const string TwofaLabel = "2FA Code";
19+
private const string LoginButton = "Sign in";
20+
private const string BackButton = "Back";
21+
private const string AuthTitle = "Sign in to GitHub";
22+
private const string TwofaTitle = "Two-Factor Authentication";
23+
private const string TwofaDescription = "Open the two-factor authentication app on your device to view your 2FA code and verify your identity.";
24+
private const string TwofaButton = "Verify";
25+
26+
[SerializeField] private Vector2 scroll;
27+
[SerializeField] private string username = string.Empty;
28+
[SerializeField] private string two2fa = string.Empty;
29+
[SerializeField] private string message;
30+
[SerializeField] private string errorMessage;
31+
[SerializeField] private bool need2fa;
32+
33+
[NonSerialized] private bool isBusy;
34+
[NonSerialized] private bool enterPressed;
35+
[NonSerialized] private string password = string.Empty;
36+
[NonSerialized] private AuthenticationService authenticationService;
37+
38+
39+
public override void InitializeView(IView parent)
40+
{
41+
base.InitializeView(parent);
42+
need2fa = isBusy = false;
43+
message = errorMessage = null;
44+
Title = WindowTitle;
45+
Size = viewSize;
46+
}
47+
48+
public void Initialize(Exception exception)
49+
{
50+
var usernameMismatchException = exception as TokenUsernameMismatchException;
51+
if (usernameMismatchException != null)
52+
{
53+
message = CredentialsNeedRefreshMessage;
54+
username = usernameMismatchException.CachedUsername;
55+
}
56+
57+
var keychainEmptyException = exception as KeychainEmptyException;
58+
if (keychainEmptyException != null)
59+
{
60+
message = NeedAuthenticationMessage;
61+
}
62+
63+
if (usernameMismatchException == null && keychainEmptyException == null)
64+
{
65+
message = exception.Message;
66+
}
67+
}
68+
69+
public override void OnGUI()
70+
{
71+
HandleEnterPressed();
72+
73+
EditorGUIUtility.labelWidth = 90f;
74+
75+
scroll = GUILayout.BeginScrollView(scroll);
76+
{
77+
GUILayout.BeginHorizontal(Styles.AuthHeaderBoxStyle);
78+
{
79+
GUILayout.Label(AuthTitle, Styles.HeaderRepoLabelStyle);
80+
}
81+
GUILayout.EndHorizontal();
82+
83+
GUILayout.BeginVertical();
84+
{
85+
if (!need2fa)
86+
{
87+
OnGUILogin();
88+
}
89+
else
90+
{
91+
OnGUI2FA();
92+
}
93+
}
94+
95+
GUILayout.EndVertical();
96+
}
97+
GUILayout.EndScrollView();
98+
}
99+
100+
private void HandleEnterPressed()
101+
{
102+
if (Event.current.type != EventType.KeyDown)
103+
return;
104+
105+
enterPressed = Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.KeypadEnter;
106+
if (enterPressed)
107+
Event.current.Use();
108+
}
109+
110+
private void OnGUILogin()
111+
{
112+
EditorGUI.BeginDisabledGroup(isBusy);
113+
{
114+
ShowMessage();
115+
116+
EditorGUILayout.Space();
117+
118+
GUILayout.BeginHorizontal();
119+
{
120+
username = EditorGUILayout.TextField(UsernameLabel ,username, Styles.TextFieldStyle);
121+
}
122+
GUILayout.EndHorizontal();
123+
124+
EditorGUILayout.Space();
125+
126+
GUILayout.BeginHorizontal();
127+
{
128+
password = EditorGUILayout.PasswordField(PasswordLabel, password, Styles.TextFieldStyle);
129+
}
130+
GUILayout.EndHorizontal();
131+
132+
EditorGUILayout.Space();
133+
134+
ShowErrorMessage();
135+
136+
GUILayout.Space(Styles.BaseSpacing + 3);
137+
GUILayout.BeginHorizontal();
138+
{
139+
GUILayout.FlexibleSpace();
140+
if (GUILayout.Button(LoginButton) || (!isBusy && enterPressed))
141+
{
142+
GUI.FocusControl(null);
143+
isBusy = true;
144+
AuthenticationService.Login(username, password, DoRequire2fa, DoResult);
145+
}
146+
}
147+
GUILayout.EndHorizontal();
148+
}
149+
EditorGUI.EndDisabledGroup();
150+
}
151+
152+
private void OnGUI2FA()
153+
{
154+
GUILayout.BeginVertical();
155+
{
156+
GUILayout.Label(TwofaTitle, EditorStyles.boldLabel);
157+
GUILayout.Label(TwofaDescription, EditorStyles.wordWrappedLabel);
158+
159+
EditorGUI.BeginDisabledGroup(isBusy);
160+
{
161+
EditorGUILayout.Space();
162+
two2fa = EditorGUILayout.TextField(TwofaLabel, two2fa, Styles.TextFieldStyle);
163+
EditorGUILayout.Space();
164+
ShowErrorMessage();
165+
166+
GUILayout.BeginHorizontal();
167+
{
168+
GUILayout.FlexibleSpace();
169+
if (GUILayout.Button(BackButton))
170+
{
171+
GUI.FocusControl(null);
172+
Clear();
173+
}
174+
175+
if (GUILayout.Button(TwofaButton) || (!isBusy && enterPressed))
176+
{
177+
GUI.FocusControl(null);
178+
isBusy = true;
179+
AuthenticationService.LoginWith2fa(two2fa);
180+
}
181+
}
182+
GUILayout.EndHorizontal();
183+
184+
EditorGUILayout.Space();
185+
}
186+
EditorGUI.EndDisabledGroup();
187+
}
188+
GUILayout.EndVertical();
189+
}
190+
191+
private void DoRequire2fa(string msg)
192+
{
193+
need2fa = true;
194+
errorMessage = msg;
195+
isBusy = false;
196+
Redraw();
197+
}
198+
199+
private void Clear()
200+
{
201+
need2fa = false;
202+
errorMessage = null;
203+
isBusy = false;
204+
Redraw();
205+
}
206+
207+
private void DoResult(bool success, string msg)
208+
{
209+
isBusy = false;
210+
if (success)
211+
{
212+
UsageTracker.IncrementAuthenticationViewButtonAuthentication();
213+
214+
Clear();
215+
Finish(true);
216+
}
217+
else
218+
{
219+
errorMessage = msg;
220+
Redraw();
221+
}
222+
}
223+
224+
private void ShowMessage()
225+
{
226+
if (message != null)
227+
{
228+
EditorGUILayout.HelpBox(message, MessageType.Warning);
229+
}
230+
}
231+
232+
private void ShowErrorMessage()
233+
{
234+
if (errorMessage != null)
235+
{
236+
EditorGUILayout.HelpBox(errorMessage, MessageType.Error);
237+
}
238+
}
239+
240+
private AuthenticationService AuthenticationService
241+
{
242+
get
243+
{
244+
if (authenticationService == null)
245+
{
246+
UriString host = Repository != null ? Repository.CloneUrl : null;
247+
AuthenticationService = new AuthenticationService(host, Platform.Keychain, Manager.ProcessManager, Manager.TaskManager, Environment);
248+
}
249+
return authenticationService;
250+
}
251+
set
252+
{
253+
authenticationService = value;
254+
}
255+
}
256+
257+
public override bool IsBusy
258+
{
259+
get { return isBusy; }
260+
}
261+
}
262+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,388 @@
1+
using System;
2+
using System.Threading;
3+
using UnityEngine;
4+
using UnityEditor;
5+
6+
namespace GitHub.Unity
7+
{
8+
[Serializable]
9+
class GitHubEnterpriseAuthenticationView : Subview
10+
{
11+
private static readonly Vector2 viewSize = new Vector2(290, 290);
12+
13+
private const string CredentialsNeedRefreshMessage = "We've detected that your stored credentials are out of sync with your current user. This can happen if you have signed in to git outside of Unity. Sign in again to refresh your credentials.";
14+
private const string NeedAuthenticationMessage = "We need you to authenticate first";
15+
private const string WindowTitle = "Authenticate";
16+
private const string ServerAddressLabel = "Server Address";
17+
private const string TokenLabel = "Token";
18+
private const string UsernameLabel = "Username";
19+
private const string PasswordLabel = "Password";
20+
private const string TwofaLabel = "2FA Code";
21+
private const string LoginButton = "Sign in";
22+
private const string BackButton = "Back";
23+
private const string AuthTitle = "Sign in to GitHub Enterprise";
24+
private const string TwofaTitle = "Two-Factor Authentication";
25+
private const string TwofaDescription = "Open the two-factor authentication app on your device to view your 2FA code and verify your identity.";
26+
private const string TwofaButton = "Verify";
27+
28+
[SerializeField] private Vector2 scroll;
29+
[SerializeField] private string serverAddress = string.Empty;
30+
[SerializeField] private string username = string.Empty;
31+
[SerializeField] private string two2fa = string.Empty;
32+
[SerializeField] private string message;
33+
[SerializeField] private string errorMessage;
34+
[SerializeField] private bool need2fa;
35+
[SerializeField] private bool hasServerMeta;
36+
[SerializeField] private bool verifiablePasswordAuthentication;
37+
38+
[NonSerialized] private bool isBusy;
39+
[NonSerialized] private bool enterPressed;
40+
[NonSerialized] private string password = string.Empty;
41+
[NonSerialized] private string token = string.Empty;
42+
[NonSerialized] private AuthenticationService authenticationService;
43+
44+
public override void InitializeView(IView parent)
45+
{
46+
base.InitializeView(parent);
47+
need2fa = isBusy = false;
48+
message = errorMessage = null;
49+
Title = WindowTitle;
50+
Size = viewSize;
51+
}
52+
53+
public void Initialize(Exception exception)
54+
{
55+
var usernameMismatchException = exception as TokenUsernameMismatchException;
56+
if (usernameMismatchException != null)
57+
{
58+
message = CredentialsNeedRefreshMessage;
59+
username = usernameMismatchException.CachedUsername;
60+
}
61+
62+
var keychainEmptyException = exception as KeychainEmptyException;
63+
if (keychainEmptyException != null)
64+
{
65+
message = NeedAuthenticationMessage;
66+
}
67+
68+
if (usernameMismatchException == null && keychainEmptyException == null)
69+
{
70+
message = exception.Message;
71+
}
72+
}
73+
74+
public override void OnGUI()
75+
{
76+
HandleEnterPressed();
77+
78+
EditorGUIUtility.labelWidth = 90f;
79+
80+
scroll = GUILayout.BeginScrollView(scroll);
81+
{
82+
GUILayout.BeginHorizontal(Styles.AuthHeaderBoxStyle);
83+
{
84+
GUILayout.Label(AuthTitle, Styles.HeaderRepoLabelStyle);
85+
}
86+
GUILayout.EndHorizontal();
87+
88+
GUILayout.BeginVertical();
89+
{
90+
if (!hasServerMeta)
91+
{
92+
OnGUIHost();
93+
}
94+
else
95+
{
96+
EditorGUILayout.Space();
97+
98+
EditorGUI.BeginDisabledGroup(true);
99+
{
100+
GUILayout.BeginHorizontal();
101+
{
102+
serverAddress = EditorGUILayout.TextField(ServerAddressLabel, serverAddress, Styles.TextFieldStyle);
103+
}
104+
GUILayout.EndHorizontal();
105+
}
106+
EditorGUI.EndDisabledGroup();
107+
108+
if (!need2fa)
109+
{
110+
if (verifiablePasswordAuthentication)
111+
{
112+
OnGUIUserPasswordLogin();
113+
}
114+
else
115+
{
116+
OnGUITokenLogin();
117+
}
118+
}
119+
else
120+
{
121+
OnGUI2FA();
122+
}
123+
}
124+
}
125+
126+
GUILayout.EndVertical();
127+
}
128+
GUILayout.EndScrollView();
129+
}
130+
131+
private void HandleEnterPressed()
132+
{
133+
if (Event.current.type != EventType.KeyDown)
134+
return;
135+
136+
enterPressed = Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.KeypadEnter;
137+
if (enterPressed)
138+
Event.current.Use();
139+
}
140+
141+
private void OnGUIHost()
142+
{
143+
EditorGUI.BeginDisabledGroup(isBusy);
144+
{
145+
ShowMessage();
146+
147+
EditorGUILayout.Space();
148+
149+
GUILayout.BeginHorizontal();
150+
{
151+
serverAddress = EditorGUILayout.TextField(ServerAddressLabel, serverAddress, Styles.TextFieldStyle);
152+
}
153+
GUILayout.EndHorizontal();
154+
155+
ShowErrorMessage();
156+
157+
GUILayout.Space(Styles.BaseSpacing + 3);
158+
GUILayout.BeginHorizontal();
159+
{
160+
GUILayout.FlexibleSpace();
161+
if (GUILayout.Button(LoginButton) || (!isBusy && enterPressed))
162+
{
163+
GUI.FocusControl(null);
164+
errorMessage = null;
165+
isBusy = true;
166+
167+
GetAuthenticationService(serverAddress)
168+
.GetServerMeta(DoServerMetaResult, DoServerMetaError);
169+
170+
Redraw();
171+
}
172+
}
173+
GUILayout.EndHorizontal();
174+
}
175+
EditorGUI.EndDisabledGroup();
176+
}
177+
178+
private void OnGUIUserPasswordLogin()
179+
{
180+
EditorGUI.BeginDisabledGroup(isBusy);
181+
{
182+
ShowMessage();
183+
184+
EditorGUILayout.Space();
185+
186+
GUILayout.BeginHorizontal();
187+
{
188+
username = EditorGUILayout.TextField(UsernameLabel ,username, Styles.TextFieldStyle);
189+
}
190+
GUILayout.EndHorizontal();
191+
192+
EditorGUILayout.Space();
193+
194+
GUILayout.BeginHorizontal();
195+
{
196+
password = EditorGUILayout.PasswordField(PasswordLabel, password, Styles.TextFieldStyle);
197+
}
198+
GUILayout.EndHorizontal();
199+
200+
ShowErrorMessage();
201+
202+
GUILayout.Space(Styles.BaseSpacing + 3);
203+
GUILayout.BeginHorizontal();
204+
{
205+
GUILayout.FlexibleSpace();
206+
if (GUILayout.Button(LoginButton) || (!isBusy && enterPressed))
207+
{
208+
GUI.FocusControl(null);
209+
isBusy = true;
210+
GetAuthenticationService(serverAddress)
211+
.Login(username, password, DoRequire2fa, DoResult);
212+
}
213+
}
214+
GUILayout.EndHorizontal();
215+
}
216+
EditorGUI.EndDisabledGroup();
217+
}
218+
219+
private void OnGUITokenLogin()
220+
{
221+
EditorGUI.BeginDisabledGroup(isBusy);
222+
{
223+
ShowMessage();
224+
225+
EditorGUILayout.Space();
226+
227+
GUILayout.BeginHorizontal();
228+
{
229+
token = EditorGUILayout.TextField(TokenLabel, token, Styles.TextFieldStyle);
230+
}
231+
GUILayout.EndHorizontal();
232+
233+
ShowErrorMessage();
234+
235+
GUILayout.Space(Styles.BaseSpacing + 3);
236+
GUILayout.BeginHorizontal();
237+
{
238+
GUILayout.FlexibleSpace();
239+
if (GUILayout.Button("Back"))
240+
{
241+
GUI.FocusControl(null);
242+
243+
hasServerMeta = false;
244+
Redraw();
245+
}
246+
247+
if (GUILayout.Button(LoginButton) || (!isBusy && enterPressed))
248+
{
249+
GUI.FocusControl(null);
250+
isBusy = true;
251+
GetAuthenticationService(serverAddress)
252+
.LoginWithToken(token, DoRequire2fa, DoResult);
253+
}
254+
}
255+
GUILayout.EndHorizontal();
256+
}
257+
EditorGUI.EndDisabledGroup();
258+
}
259+
260+
private void OnGUI2FA()
261+
{
262+
GUILayout.BeginVertical();
263+
{
264+
GUILayout.Label(TwofaTitle, EditorStyles.boldLabel);
265+
GUILayout.Label(TwofaDescription, EditorStyles.wordWrappedLabel);
266+
267+
EditorGUI.BeginDisabledGroup(isBusy);
268+
{
269+
EditorGUILayout.Space();
270+
two2fa = EditorGUILayout.TextField(TwofaLabel, two2fa, Styles.TextFieldStyle);
271+
272+
ShowErrorMessage();
273+
274+
GUILayout.BeginHorizontal();
275+
{
276+
GUILayout.FlexibleSpace();
277+
if (GUILayout.Button(BackButton))
278+
{
279+
GUI.FocusControl(null);
280+
Clear();
281+
}
282+
283+
if (GUILayout.Button(TwofaButton) || (!isBusy && enterPressed))
284+
{
285+
GUI.FocusControl(null);
286+
isBusy = true;
287+
GetAuthenticationService(serverAddress)
288+
.LoginWith2fa(two2fa);
289+
}
290+
}
291+
GUILayout.EndHorizontal();
292+
293+
EditorGUILayout.Space();
294+
}
295+
EditorGUI.EndDisabledGroup();
296+
}
297+
GUILayout.EndVertical();
298+
}
299+
300+
private void DoServerMetaResult(GitHubHostMeta gitHubHostMeta)
301+
{
302+
hasServerMeta = true;
303+
verifiablePasswordAuthentication = gitHubHostMeta.VerifiablePasswordAuthentication;
304+
isBusy = false;
305+
Redraw();
306+
}
307+
308+
private void DoServerMetaError(string message)
309+
{
310+
errorMessage = message;
311+
hasServerMeta = false;
312+
isBusy = false;
313+
Redraw();
314+
}
315+
316+
private void DoRequire2fa(string msg)
317+
{
318+
need2fa = true;
319+
errorMessage = msg;
320+
isBusy = false;
321+
Redraw();
322+
}
323+
324+
private void Clear()
325+
{
326+
need2fa = false;
327+
errorMessage = null;
328+
isBusy = false;
329+
Redraw();
330+
}
331+
332+
private void DoResult(bool success, string msg)
333+
{
334+
isBusy = false;
335+
if (success)
336+
{
337+
UsageTracker.IncrementAuthenticationViewButtonAuthentication();
338+
339+
Clear();
340+
Finish(true);
341+
}
342+
else
343+
{
344+
errorMessage = msg;
345+
Redraw();
346+
}
347+
}
348+
349+
private void ShowMessage()
350+
{
351+
if (message != null)
352+
{
353+
EditorGUILayout.HelpBox(message, MessageType.Warning);
354+
}
355+
}
356+
357+
private void ShowErrorMessage()
358+
{
359+
if (errorMessage != null)
360+
{
361+
EditorGUILayout.Space();
362+
363+
EditorGUILayout.HelpBox(errorMessage, MessageType.Error);
364+
}
365+
}
366+
367+
private AuthenticationService GetAuthenticationService(string host)
368+
{
369+
if (authenticationService == null || authenticationService.HostAddress.WebUri.Host != host)
370+
{
371+
authenticationService
372+
= new AuthenticationService(
373+
host,
374+
Platform.Keychain,
375+
Manager.ProcessManager,
376+
Manager.TaskManager,
377+
Environment);
378+
}
379+
380+
return authenticationService;
381+
}
382+
383+
public override bool IsBusy
384+
{
385+
get { return isBusy; }
386+
}
387+
}
388+
}

Diff for: ‎unity/PackageProject/Assets/Plugins/GitHub/Editor/AsyncBridge.Net35.dll.meta

+22-24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: ‎unity/PackageProject/Assets/Plugins/GitHub/Editor/GitHub.Api.dll.meta

+22-24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: ‎unity/PackageProject/Assets/Plugins/GitHub/Editor/GitHub.Unity.dll.meta

+22-24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: ‎unity/PackageProject/Assets/Plugins/GitHub/Editor/ReadOnlyCollectionsInterfaces.dll.meta

+22-24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: ‎unity/PackageProject/Assets/Plugins/GitHub/Editor/System.Threading.dll.meta

+22-24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: ‎unity/PackageProject/ProjectSettings/DynamicsManager.asset

+2
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ PhysicsManager:
1616
m_EnableAdaptiveForce: 0
1717
m_EnablePCM: 1
1818
m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
19+
m_AutoSimulation: 1
20+
m_AutoSyncTransforms: 1

Diff for: ‎unity/PackageProject/ProjectSettings/Physics2DSettings.asset

+5-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
--- !u!19 &1
44
Physics2DSettings:
55
m_ObjectHideFlags: 0
6-
serializedVersion: 2
6+
serializedVersion: 3
77
m_Gravity: {x: 0, y: -9.81}
88
m_DefaultMaterial: {fileID: 0}
99
m_VelocityIterations: 8
@@ -13,15 +13,18 @@ Physics2DSettings:
1313
m_MaxAngularCorrection: 8
1414
m_MaxTranslationSpeed: 100
1515
m_MaxRotationSpeed: 360
16-
m_MinPenetrationForPenalty: 0.01
1716
m_BaumgarteScale: 0.2
1817
m_BaumgarteTimeOfImpactScale: 0.75
1918
m_TimeToSleep: 0.5
2019
m_LinearSleepTolerance: 0.01
2120
m_AngularSleepTolerance: 2
21+
m_DefaultContactOffset: 0.01
22+
m_AutoSimulation: 1
2223
m_QueriesHitTriggers: 1
2324
m_QueriesStartInColliders: 1
2425
m_ChangeStopsCallbacks: 0
26+
m_CallbacksOnDisable: 1
27+
m_AutoSyncTransforms: 1
2528
m_AlwaysShowColliders: 0
2629
m_ShowColliderSleep: 1
2730
m_ShowColliderContacts: 0

Diff for: ‎unity/TestProject/ProjectSettings/DynamicsManager.asset

+2
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ PhysicsManager:
1616
m_EnableAdaptiveForce: 0
1717
m_EnablePCM: 1
1818
m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
19+
m_AutoSimulation: 1
20+
m_AutoSyncTransforms: 1

Diff for: ‎unity/TestProject/ProjectSettings/Physics2DSettings.asset

+5-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
--- !u!19 &1
44
Physics2DSettings:
55
m_ObjectHideFlags: 0
6-
serializedVersion: 2
6+
serializedVersion: 3
77
m_Gravity: {x: 0, y: -9.81}
88
m_DefaultMaterial: {fileID: 0}
99
m_VelocityIterations: 8
@@ -13,15 +13,18 @@ Physics2DSettings:
1313
m_MaxAngularCorrection: 8
1414
m_MaxTranslationSpeed: 100
1515
m_MaxRotationSpeed: 360
16-
m_MinPenetrationForPenalty: 0.01
1716
m_BaumgarteScale: 0.2
1817
m_BaumgarteTimeOfImpactScale: 0.75
1918
m_TimeToSleep: 0.5
2019
m_LinearSleepTolerance: 0.01
2120
m_AngularSleepTolerance: 2
21+
m_DefaultContactOffset: 0.01
22+
m_AutoSimulation: 1
2223
m_QueriesHitTriggers: 1
2324
m_QueriesStartInColliders: 1
2425
m_ChangeStopsCallbacks: 0
26+
m_CallbacksOnDisable: 1
27+
m_AutoSyncTransforms: 1
2528
m_AlwaysShowColliders: 0
2629
m_ShowColliderSleep: 1
2730
m_ShowColliderContacts: 0

Diff for: ‎unity/TestProject/ProjectSettings/ProjectSettings.asset

+184-28
Large diffs are not rendered by default.

Diff for: ‎unity/TestProject/ProjectSettings/ProjectVersion.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
m_EditorVersion: 5.5.0f3
1+
m_EditorVersion: 2017.2.0f3

0 commit comments

Comments
 (0)
This repository has been archived.