Browse Source

Added user login, switching users/tokens, and token validation

tags/1.0-rc
RogueException 9 years ago
parent
commit
96efc97fc1
7 changed files with 110 additions and 45 deletions
  1. +37
    -20
      src/Discord.Net/API/DiscordRawClient.cs
  2. +12
    -0
      src/Discord.Net/API/Rest/LoginParams.cs
  3. +10
    -0
      src/Discord.Net/API/Rest/LoginResponse.cs
  4. +2
    -0
      src/Discord.Net/Discord.Net.csproj
  5. +2
    -1
      src/Discord.Net/IDiscordClient.cs
  6. +46
    -20
      src/Discord.Net/Rest/DiscordClient.cs
  7. +1
    -4
      src/Discord.Net/Rest/Entities/Users/GuildUser.cs

+ 37
- 20
src/Discord.Net/API/DiscordRawClient.cs View File

@@ -29,29 +29,13 @@ namespace Discord.API
public TokenType AuthTokenType { get; private set; }
public IRestClient RestClient { get; private set; }
public IRequestQueue RequestQueue { get; private set; }
internal DiscordRawClient(RestClientProvider restClientProvider, CancellationToken cancelToken, TokenType authTokenType, string authToken)
internal DiscordRawClient(RestClientProvider restClientProvider, CancellationToken cancelToken)
{
_cancelToken = cancelToken;
AuthTokenType = authTokenType;

switch (authTokenType)
{
case TokenType.Bot:
authToken = $"Bot {authToken}";
break;
case TokenType.Bearer:
authToken = $"Bearer {authToken}";
break;
case TokenType.User:
break;
default:
throw new ArgumentException("Unknown oauth token type", nameof(authTokenType));
}

_restClient = restClientProvider(DiscordConfig.ClientAPIUrl, cancelToken);
_restClient.SetHeader("accept", "*/*");
_restClient.SetHeader("authorization", authToken);
_restClient.SetHeader("user-agent", DiscordConfig.UserAgent);
_requestQueue = new RequestQueue(_restClient);

@@ -69,6 +53,27 @@ namespace Discord.API
_serializer.ContractResolver = new OptionalContractResolver();
}

public void SetToken(TokenType tokenType, string token)
{
AuthTokenType = tokenType;

switch (tokenType)
{
case TokenType.Bot:
token = $"Bot {token}";
break;
case TokenType.Bearer:
token = $"Bearer {token}";
break;
case TokenType.User:
break;
default:
throw new ArgumentException("Unknown oauth token type", nameof(tokenType));
}

_restClient.SetHeader("authorization", token);
}

//Core
public Task Send(string method, string endpoint, GlobalBucket bucket = GlobalBucket.General)
=> SendInternal(method, endpoint, null, true, bucket);
@@ -122,7 +127,7 @@ namespace Discord.API
stopwatch.Stop();

double milliseconds = ToMilliseconds(stopwatch);
SentRequest(this, new SentRequestEventArgs(method, endpoint, bytes, milliseconds));
SentRequest?.Invoke(this, new SentRequestEventArgs(method, endpoint, bytes, milliseconds));

return responseStream;
}
@@ -134,11 +139,23 @@ namespace Discord.API
stopwatch.Stop();

double milliseconds = ToMilliseconds(stopwatch);
SentRequest(this, new SentRequestEventArgs(method, endpoint, bytes, milliseconds));
SentRequest?.Invoke(this, new SentRequestEventArgs(method, endpoint, bytes, milliseconds));

return responseStream;
}


//Auth
public async Task Login(LoginParams args)
{
var response = await Send<LoginResponse>("POST", "auth/login", args).ConfigureAwait(false);
SetToken(TokenType.User, response.Token);
}
public async Task ValidateToken()
{
await Send("GET", "auth/login").ConfigureAwait(false);
}

//Gateway
public async Task<GetGatewayResponse> GetGateway()
{


+ 12
- 0
src/Discord.Net/API/Rest/LoginParams.cs View File

@@ -0,0 +1,12 @@
using Newtonsoft.Json;

namespace Discord.API.Rest
{
public class LoginParams
{
[JsonProperty("email")]
public string Email { get; set; }
[JsonProperty("password")]
public string Password { get; set; }
}
}

+ 10
- 0
src/Discord.Net/API/Rest/LoginResponse.cs View File

@@ -0,0 +1,10 @@
using Newtonsoft.Json;

namespace Discord.API.Rest
{
public class LoginResponse
{
[JsonProperty("token")]
public string Token { get; set; }
}
}

+ 2
- 0
src/Discord.Net/Discord.Net.csproj View File

@@ -70,6 +70,8 @@
<Compile Include="API\Optional.cs" />
<Compile Include="API\Rest\DeleteMessagesParam.cs" />
<Compile Include="API\Rest\GetGuildMembersParams.cs" />
<Compile Include="API\Rest\LoginParams.cs" />
<Compile Include="API\Rest\LoginResponse.cs" />
<Compile Include="API\Rest\ModifyCurrentUserNickParams.cs" />
<Compile Include="API\Rest\UploadFileParams.cs" />
<Compile Include="API\Rest\GuildPruneParams.cs" />


+ 2
- 1
src/Discord.Net/IDiscordClient.cs View File

@@ -14,7 +14,8 @@ namespace Discord
IRestClient RestClient { get; }
IRequestQueue RequestQueue { get; }

Task Login(TokenType tokenType, string token);
Task Login(string email, string password);
Task Login(TokenType tokenType, string token, bool validateToken = true);
Task Logout();

Task<IChannel> GetChannel(ulong id);


+ 46
- 20
src/Discord.Net/Rest/DiscordClient.cs View File

@@ -47,43 +47,64 @@ namespace Discord.Rest
_log.Message += (s,e) => Log.Raise(this, e);
}

public async Task Login(TokenType tokenType, string token)
public async Task Login(string email, string password)
{
await _connectionLock.WaitAsync().ConfigureAwait(false);
try
{
await LoginInternal(tokenType, token).ConfigureAwait(false);
await LoginInternal(email, password).ConfigureAwait(false);
}
finally { _connectionLock.Release(); }
}
private async Task LoginInternal(TokenType tokenType, string token)
public async Task Login(TokenType tokenType, string token, bool validateToken = true)
{
await _connectionLock.WaitAsync().ConfigureAwait(false);
try
{
await LoginInternal(tokenType, token, validateToken).ConfigureAwait(false);
}
finally { _connectionLock.Release(); }
}
private async Task LoginInternal(string email, string password)
{
if (IsLoggedIn)
LogoutInternal();

try
{
var cancelTokenSource = new CancellationTokenSource();
BaseClient = new API.DiscordRawClient(_restClientProvider, cancelTokenSource.Token, tokenType, token);
BaseClient.SentRequest += (s, e) => _log.Verbose("Rest", $"{e.Method} {e.Endpoint}: {e.Milliseconds} ms");
BaseClient = new API.DiscordRawClient(_restClientProvider, cancelTokenSource.Token);

//MessageQueue = new MessageQueue(RestClient, _restLogger);
//await MessageQueue.Start(_cancelTokenSource.Token).ConfigureAwait(false);
var args = new LoginParams { Email = email, Password = password };
await BaseClient.Login(args).ConfigureAwait(false);
await CompleteLogin(cancelTokenSource, false).ConfigureAwait(false);
}
catch { LogoutInternal(); throw; }
}
private async Task LoginInternal(TokenType tokenType, string token, bool validateToken)
{
if (IsLoggedIn)
LogoutInternal();
try
{
var cancelTokenSource = new CancellationTokenSource();
BaseClient = new API.DiscordRawClient(_restClientProvider, cancelTokenSource.Token);

try
{
var currentUser = await BaseClient.GetCurrentUser().ConfigureAwait(false);
_currentUser = new SelfUser(this, currentUser);
}
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.Unauthorized && tokenType == TokenType.Bearer) { } //Ignore 401 if Bearer doesnt have identity
_cancelTokenSource = cancelTokenSource;
IsLoggedIn = true;
LoggedIn.Raise(this);
BaseClient.SetToken(tokenType, token);
await CompleteLogin(cancelTokenSource, validateToken).ConfigureAwait(false);
}
catch { LogoutInternal(); throw; }
}
private async Task CompleteLogin(CancellationTokenSource cancelTokenSource, bool validateToken)
{
BaseClient.SentRequest += (s, e) => _log.Verbose("Rest", $"{e.Method} {e.Endpoint}: {e.Milliseconds} ms");

if (validateToken)
await BaseClient.ValidateToken().ConfigureAwait(false);

_cancelTokenSource = cancelTokenSource;
IsLoggedIn = true;
LoggedIn.Raise(this);
}

public async Task Logout()
{
@@ -99,9 +120,14 @@ namespace Discord.Rest
{
bool wasLoggedIn = IsLoggedIn;

try { _cancelTokenSource.Cancel(false); } catch { }
if (_cancelTokenSource != null)
{
try { _cancelTokenSource.Cancel(false); }
catch { }
}

BaseClient = null;
_currentUser = null;

if (wasLoggedIn)
{


+ 1
- 4
src/Discord.Net/Rest/Entities/Users/GuildUser.cs View File

@@ -87,10 +87,7 @@ namespace Discord.Rest
bool isCurrentUser = (await Discord.GetCurrentUser().ConfigureAwait(false)).Id == Id;
if (isCurrentUser && args.Nickname.IsSpecified)
{
var nickArgs = new ModifyCurrentUserNickParams
{
Nickname = args.Nickname.Value
};
var nickArgs = new ModifyCurrentUserNickParams { Nickname = args.Nickname.Value };
await Discord.BaseClient.ModifyCurrentUserNick(Guild.Id, nickArgs).ConfigureAwait(false);
args.Nickname = new API.Optional<string>(); //Remove
}


Loading…
Cancel
Save