add openhack files

This commit is contained in:
Ryan Peters
2022-11-03 16:41:13 -04:00
commit b2c9f7e29f
920 changed files with 118861 additions and 0 deletions

View File

@ -0,0 +1,198 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for details.
using System;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net;
using Microsoft.WindowsAzure.MobileServices;
using System.Threading;
using MyDriving.Utils;
using System.Text;
using MyDriving.Utils.Interfaces;
using MyDriving.Utils.Helpers;
using Newtonsoft.Json.Linq;
namespace MyDriving.AzureClient
{
class AuthHandler : DelegatingHandler
{
private static readonly SemaphoreSlim semaphore = new SemaphoreSlim(1);
private static bool isReauthenticating = false;
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
//Clone the request in case we need to send it again
var clonedRequest = await CloneRequest(request);
var response = await base.SendAsync(clonedRequest, cancellationToken);
//If the token is expired or is invalid, then we need to either refresh the token or prompt the user to log back in
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
if (isReauthenticating)
return response;
var client = ServiceLocator.Instance.Resolve<IAzureClient>()?.Client as MobileServiceClient;
if (client == null)
{
throw new InvalidOperationException(
"Make sure to set the ServiceLocator has an instance of IAzureClient");
}
string authToken = client.CurrentUser.MobileServiceAuthenticationToken;
await semaphore.WaitAsync();
//In case two threads enter this method at the same time, only one should do the refresh (or re-login), the other should just resend the request with an updated header.
if (authToken != client.CurrentUser.MobileServiceAuthenticationToken) // token was already renewed
{
semaphore.Release();
return await ResendRequest(client, request, cancellationToken);
}
isReauthenticating = true;
bool gotNewToken = false;
try
{
//For MSA, attempt to refresh the token if we haven't already so that user doesn't have to log back in again
//This isn't needed for Facebook since the token doesn't expire for 60 days; similarly, for Twitter, the token never expires
if (Settings.Current.LoginAccount == LoginAccount.Microsoft)
{
gotNewToken = await RefreshToken(client);
}
//Otherwise if refreshing the token failed or Facebook\Twitter is being used, prompt the user to log back in via the login screen
if (!gotNewToken)
{
//First, make sure there isn't a progress dialog being displayed since this will block the main ui thread
ProgressDialogManager.HideProgressDialog();
gotNewToken = await Login(client);
//Redisplay the progress dialog if needed
ProgressDialogManager.ShowProgressDialog();
}
}
catch (System.Exception e)
{
Logger.Instance.Report(e);
}
finally
{
isReauthenticating = false;
semaphore.Release();
}
if (gotNewToken)
{
if (!request.RequestUri.OriginalString.Contains("/.auth/me")) //do not resend in this case since we're not using the return value of auth/me
{
//Resend the request since the user has successfully logged in and return the response
return await ResendRequest(client, request, cancellationToken);
}
}
}
return response;
}
private MobileServiceAuthenticationProvider GetProviderType()
{
var accountType = MobileServiceAuthenticationProvider.MicrosoftAccount;
switch (Settings.Current.LoginAccount)
{
case LoginAccount.Facebook:
accountType = MobileServiceAuthenticationProvider.Facebook;
break;
case LoginAccount.Twitter:
accountType = MobileServiceAuthenticationProvider.Twitter;
break;
}
return accountType;
}
private async Task<HttpResponseMessage> ResendRequest(IMobileServiceClient client, HttpRequestMessage request, CancellationToken cancellationToken)
{
// Clone the request
var clonedRequest = await CloneRequest(request);
// Set the authentication header
clonedRequest.Headers.Remove("X-ZUMO-AUTH");
clonedRequest.Headers.Add("X-ZUMO-AUTH", client.CurrentUser.MobileServiceAuthenticationToken);
// Resend the request
return await base.SendAsync(clonedRequest, cancellationToken);
}
private async Task<bool> RefreshToken(IMobileServiceClient client)
{
try
{
JObject refreshJson = (JObject)await client.InvokeApiAsync("/.auth/refresh", HttpMethod.Get, null);
if (refreshJson != null)
{
string newToken = refreshJson["authenticationToken"].Value<string>();
client.CurrentUser.MobileServiceAuthenticationToken = newToken;
Settings.Current.AuthToken = newToken;
return true;
}
}
catch (System.Exception e)
{
Logger.Instance.Report(e);
}
return false;
}
private async Task<bool> Login(IMobileServiceClient client)
{
var authentication = ServiceLocator.Instance.Resolve<IAuthentication>();
if (authentication == null)
{
throw new InvalidOperationException("Make sure the ServiceLocator has an instance of IAuthentication");
}
var accountType = GetProviderType();
try
{
var user = await authentication.LoginAsync(client, accountType);
if (user != null)
return true;
}
catch (System.Exception e)
{
Logger.Instance.Report(e);
}
return false;
}
private async Task<HttpRequestMessage> CloneRequest(HttpRequestMessage request)
{
var result = new HttpRequestMessage(request.Method, request.RequestUri);
foreach (var header in request.Headers)
{
result.Headers.Add(header.Key, header.Value);
}
if (request.Content != null && request.Content.Headers.ContentType != null)
{
var requestBody = await request.Content.ReadAsStringAsync();
var mediaType = request.Content.Headers.ContentType.MediaType;
result.Content = new StringContent(requestBody, Encoding.UTF8, mediaType);
foreach (var header in request.Content.Headers)
{
if (!header.Key.Equals("Content-Type", StringComparison.OrdinalIgnoreCase))
{
result.Content.Headers.Add(header.Key, header.Value);
}
}
}
return result;
}
}
}

View File

@ -0,0 +1,48 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for details.
using Microsoft.WindowsAzure.MobileServices;
using System.Net.Http;
using System.Threading.Tasks;
using MyDriving.Utils;
using Newtonsoft.Json.Linq;
using System;
using PCLAppConfig;
namespace MyDriving.AzureClient
{
public class AzureClient : IAzureClient
{
//ConfigurationManager config = new ConfigurationManager(PCLAppConfig.FileSystemStream.PortableStream.Current);
//ConfigurationManager.Initialise(PCLAppConfig.FileSystemStream.PortableStream.Current);
const string DefaultMobileServiceUrl = "https://mydriving-or76fh5yqpqg2.azurewebsites.net";
static IMobileServiceClient client;
public IMobileServiceClient Client => client ?? (client = CreateClient());
IMobileServiceClient CreateClient()
{
client = new MobileServiceClient(DefaultMobileServiceUrl, new AuthHandler())
{
SerializerSettings = new MobileServiceJsonSerializerSettings()
{
ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore,
CamelCasePropertyNames = true
}
};
return client;
}
public static async Task CheckIsAuthTokenValid()
{
//Check if the access token is valid by sending a general request to mobile service
var client = ServiceLocator.Instance.Resolve<IAzureClient>()?.Client;
try
{
await client.InvokeApiAsync("/.auth/me", HttpMethod.Get, null);
}
catch { } //Eat any exceptions
}
}
}

View File

@ -0,0 +1,125 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for details.
using Microsoft.WindowsAzure.MobileServices;
using MyDriving.Utils;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Plugin.DeviceInfo;
using System.Text;
namespace MyDriving.AzureClient
{
public class DeviceProvisionHandler
{
private const string DefaultHostName = "mydriving-or76fh5yqpqg2.azure-devices.net";
private static DeviceProvisionHandler _handler;
private DeviceProvisionHandler()
{
try
{
DeviceId = Settings.Current.DeviceId;
HostName = Settings.Current.HostName;
}
catch (Exception e)
{
//Occassionally, a System.IO.FileLoadException can occur
Logger.Instance.Track("Unable to get device id and/or host name from user settings: " + e.Message);
}
if (String.IsNullOrEmpty(DeviceId))
{
//generate device ID
DeviceId = GenerateDeviceId();
Settings.Current.DeviceId = DeviceId;
}
if (String.IsNullOrEmpty(HostName))
{
HostName = DefaultHostName;
Settings.Current.HostName = HostName;
}
}
private string GenerateDeviceId()
{
string id = CrossDeviceInfo.Current.Id;
if (id == null)
return id;
int limit = 128;
//remove unaccepted characters - see https://azure.microsoft.com/en-us/documentation/articles/iot-hub-devguide/#device-identity-registry
//Note due to bug in Microsoft.Azure.Devices.Client.PCL some characters such as '+' in DeviceID still cause trouble
StringBuilder sb = new StringBuilder(id.Length);
foreach (char c in id)
{
if (Char.IsLetterOrDigit(c))
sb.Append(c);
if (sb.Length >= limit)
break;
}
return sb.ToString();
}
public string DeviceId { get; private set; }
public string HostName { get; private set; }
public string AccessKey { get; private set; }
public string DeviceConnectionString
{
get
{
string connectionStr = String.Empty;
if (!String.IsNullOrEmpty(AccessKey) && !String.IsNullOrEmpty(HostName) && !String.IsNullOrEmpty(DeviceId))
{
connectionStr = $"HostName={HostName};DeviceId={DeviceId};SharedAccessKey={AccessKey}";
}
return connectionStr;
}
}
public static DeviceProvisionHandler GetHandler()
{
return _handler ?? (_handler = new DeviceProvisionHandler());
}
public async Task<string> ProvisionDevice()
{
if (!string.IsNullOrEmpty(Settings.Current.DeviceConnectionString))
{
return Settings.Current.DeviceConnectionString;
}
else
{
Dictionary<string, string> myParms = new Dictionary<string, string>();
myParms.Add("userId", Settings.Current.UserUID);
myParms.Add("deviceName", DeviceId);
var client = ServiceLocator.Instance.Resolve<IAzureClient>()?.Client as MobileServiceClient;
try
{
var response = await client.InvokeApiAsync("provision", null, HttpMethod.Post, myParms);
AccessKey = response.Value<string>();
}
catch (Exception e)
{
Logger.Instance.Track("Unable to provision device with IOT Hub: " + e.Message);
}
Settings.Current.DeviceConnectionString = DeviceConnectionString;
return Settings.Current.DeviceConnectionString;
}
}
}
}

View File

@ -0,0 +1,43 @@
// Helpers/Settings.cs
using Plugin.Settings;
using Plugin.Settings.Abstractions;
namespace MyDriving.AzureClient.Helpers
{
/// <summary>
/// This is the Settings static class that can be used in your Core solution or in any
/// of your client applications. All settings are laid out the same exact way with getters
/// and setters.
/// </summary>
public static class Settings
{
private static ISettings AppSettings
{
get
{
return CrossSettings.Current;
}
}
#region Setting Constants
private const string SettingsKey = "settings_key";
private static readonly string SettingsDefault = string.Empty;
#endregion
public static string GeneralSettings
{
get
{
return AppSettings.GetValueOrDefault<string>(SettingsKey, SettingsDefault);
}
set
{
AppSettings.AddOrUpdateValue<string>(SettingsKey, value);
}
}
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for details.
using Microsoft.WindowsAzure.MobileServices;
namespace MyDriving.AzureClient
{
public interface IAzureClient
{
IMobileServiceClient Client { get; }
}
}

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{29B6B823-6639-4942-9723-0075BBEF7C69}</ProjectGuid>
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<RootNamespace>MyDriving.AzureClient</RootNamespace>
<AssemblyName>MyDriving.AzureClient</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<NoStdLib>false</NoStdLib>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<NoStdLib>false</NoStdLib>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'XTC|AnyCPU'">
<OutputPath>bin\XTC\</OutputPath>
<Optimize>true</Optimize>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Compile Include="DeviceProvisionHandler.cs" />
<Compile Include="Helpers\Settings.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="IAzureClient.cs" />
<Compile Include="AzureClient.cs" />
<Compile Include="AuthHandler.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.8.0.3\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="PCLAppConfig, Version=0.3.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\PCLAppConfig.0.3.4\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\PCLAppConfig.dll</HintPath>
</Reference>
<Reference Include="PCLAppConfig.FileSystemStream, Version=0.3.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\PCLAppConfig.0.3.4\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\PCLAppConfig.FileSystemStream.dll</HintPath>
</Reference>
<Reference Include="PCLAppConfig.FileSystemStream.Abstractions, Version=0.3.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\PCLAppConfig.0.3.4\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\PCLAppConfig.FileSystemStream.Abstractions.dll</HintPath>
</Reference>
<Reference Include="PCLStorage, Version=1.0.2.0, Culture=neutral, PublicKeyToken=286fe515a2c35b64, processorArchitecture=MSIL">
<HintPath>..\..\packages\PCLStorage.1.0.2\lib\portable-net45+wp8+wpa81+win8+monoandroid+monotouch+Xamarin.iOS+Xamarin.Mac\PCLStorage.dll</HintPath>
</Reference>
<Reference Include="PCLStorage.Abstractions, Version=1.0.2.0, Culture=neutral, PublicKeyToken=286fe515a2c35b64, processorArchitecture=MSIL">
<HintPath>..\..\packages\PCLStorage.1.0.2\lib\portable-net45+wp8+wpa81+win8+monoandroid+monotouch+Xamarin.iOS+Xamarin.Mac\PCLStorage.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Plugin.DeviceInfo, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Xam.Plugin.DeviceInfo.2.0.2\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10+UAP10\Plugin.DeviceInfo.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Plugin.DeviceInfo.Abstractions, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Xam.Plugin.DeviceInfo.2.0.2\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10+UAP10\Plugin.DeviceInfo.Abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Plugin.Settings, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Xam.Plugins.Settings.2.1.0\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10+UAP10\Plugin.Settings.dll</HintPath>
</Reference>
<Reference Include="Plugin.Settings.Abstractions, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Xam.Plugins.Settings.2.1.0\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10+UAP10\Plugin.Settings.Abstractions.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Primitives">
<HintPath>..\..\packages\Microsoft.Net.Http.2.2.29\lib\portable-net45+win8\System.Net.Http.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Extensions">
<HintPath>..\..\packages\Microsoft.Net.Http.2.2.29\lib\portable-net45+win8\System.Net.Http.Extensions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAzure.Mobile">
<HintPath>..\..\packages\Microsoft.Azure.Mobile.Client.2.0.1\lib\portable-win+net45+wp8+wpa81+monotouch+monoandroid\Microsoft.WindowsAzure.Mobile.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MyDriving.Utils\MyDriving.Utils.csproj">
<Project>{CEF8CB82-B2BF-42D0-998C-8C50A4CA7AE6}</Project>
<Name>MyDriving.Utils</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<Import Project="..\..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
</Project>

View File

@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for details.
using System.Reflection;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("MyDriving.AzureClient")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("jamesmontemagno")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.29.0" newVersion="4.2.29.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<appSettings>
<add key="DefaultMobileServiceUrl" value="https://mydriving-or76fh5yqpqg2.azurewebsites.net" />
</appSettings>
</configuration>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Azure.Mobile.Client" version="2.0.1" targetFramework="portable-net45+win+MonoTouch10+MonoAndroid10+xamarinmac20+xamarintvos10+xamarinwatchos10+xamarinios10" />
<package id="Microsoft.Bcl" version="1.1.10" targetFramework="portable-net45+win+MonoTouch10+MonoAndroid10+xamarinmac20+xamarintvos10+xamarinwatchos10+xamarinios10" />
<package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="portable-net45+win+MonoTouch10+MonoAndroid10+xamarinmac20+xamarintvos10+xamarinwatchos10+xamarinios10" />
<package id="Microsoft.Net.Http" version="2.2.29" targetFramework="portable-net45+win+MonoTouch10+MonoAndroid10+xamarinmac20+xamarintvos10+xamarinwatchos10+xamarinios10" />
<package id="Newtonsoft.Json" version="8.0.2" targetFramework="portable-net45+win+MonoTouch10+MonoAndroid10+xamarinmac20+xamarintvos10+xamarinwatchos10+xamarinios10" />
<package id="PCLAppConfig" version="0.3.4" targetFramework="portable45-net45+win8" />
<package id="PCLStorage" version="1.0.2" targetFramework="portable45-net45+win8" />
<package id="Xam.Plugin.DeviceInfo" version="2.0.2" targetFramework="portable45-net45+win8" />
<package id="Xam.Plugins.Settings" version="2.1.0" targetFramework="portable45-net45+win8" />
</packages>