Archived
1
0

Added authorization mechanism

This commit is contained in:
Michael Gordeev
2019-12-05 00:58:09 +03:00
parent 903c0c563d
commit e2b2a7cc8d
9 changed files with 148 additions and 40 deletions
+6 -8
View File
@@ -136,7 +136,7 @@
<Compile Include="Helpers\Metrics.cs" /> <Compile Include="Helpers\Metrics.cs" />
<Compile Include="Helpers\Settings.cs" /> <Compile Include="Helpers\Settings.cs" />
<Compile Include="Helpers\StoreInterop.cs" /> <Compile Include="Helpers\StoreInterop.cs" />
<Compile Include="Helpers\UserControl.cs" /> <Compile Include="Helpers\UsersControl.cs" />
<Compile Include="Helpers\Utils.cs" /> <Compile Include="Helpers\Utils.cs" />
<Compile Include="Models\Inbox\Changelog.cs" /> <Compile Include="Models\Inbox\Changelog.cs" />
<Compile Include="Models\Inbox\DeveloperMessage.cs" /> <Compile Include="Models\Inbox\DeveloperMessage.cs" />
@@ -153,6 +153,9 @@
<PackageReference Include="AngleSharp"> <PackageReference Include="AngleSharp">
<Version>0.13.0</Version> <Version>0.13.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="ExtendedYouTubeAPI">
<Version>1.0.1</Version>
</PackageReference>
<PackageReference Include="Google.Apis.Auth"> <PackageReference Include="Google.Apis.Auth">
<Version>1.42.0</Version> <Version>1.42.0</Version>
</PackageReference> </PackageReference>
@@ -163,10 +166,10 @@
<Version>1.42.0.1758</Version> <Version>1.42.0.1758</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.AppCenter.Analytics"> <PackageReference Include="Microsoft.AppCenter.Analytics">
<Version>2.6.1</Version> <Version>2.6.2</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.AppCenter.Crashes"> <PackageReference Include="Microsoft.AppCenter.Crashes">
<Version>2.6.1</Version> <Version>2.6.2</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform"> <PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
<Version>6.2.9</Version> <Version>6.2.9</Version>
@@ -186,11 +189,6 @@
<Name>Visual C++ 2015 Runtime for Universal Windows Platform Apps</Name> <Name>Visual C++ 2015 Runtime for Universal Windows Platform Apps</Name>
</SDKReference> </SDKReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Reference Include="YouTube.API">
<HintPath>..\Src\YouTube.API.dll</HintPath>
</Reference>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' "> <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion> <VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup> </PropertyGroup>
@@ -2,21 +2,26 @@
using Google.Apis.Oauth2.v2; using Google.Apis.Oauth2.v2;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Windows.Security.Authentication.Web; using Windows.Security.Authentication.Web;
using YouTube.Authorization; using YouTube.Authorization;
using YouTube;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Windows.Security.Credentials; using Windows.Security.Credentials;
using FoxTube.Core.Models; using FoxTube.Core.Models;
using YouTube;
using System.Threading; using System.Threading;
using Google.Apis.YouTube.v3; using Google.Apis.YouTube.v3;
namespace FoxTube namespace FoxTube
{ {
public static class UserControl public static class UsersControl
{ {
static ExtendedYouTubeService _defaultService = new ExtendedYouTubeService(new Google.Apis.Services.BaseClientService.Initializer
{
ApplicationName = "FoxTube",
ApiKey = "AIzaSyD7tpbuvmYDv9h4udo9L_g3r0sLPFAnN00"
});
static string[] Scopes { get; } = new string[] static string[] Scopes { get; } = new string[]
{ {
Oauth2Service.Scope.UserinfoProfile, Oauth2Service.Scope.UserinfoProfile,
@@ -32,6 +37,7 @@ namespace FoxTube
public static User CurrentUser { get; set; } public static User CurrentUser { get; set; }
public static bool Authorized => CurrentUser != null; public static bool Authorized => CurrentUser != null;
public static ExtendedYouTubeService Service => CurrentUser?.Service ?? _defaultService;
public static async Task<bool> AddUser() public static async Task<bool> AddUser()
{ {
@@ -42,8 +48,10 @@ namespace FoxTube
switch(result.ResponseStatus) switch(result.ResponseStatus)
{ {
case WebAuthenticationStatus.Success: case WebAuthenticationStatus.Success:
UserCredential credential = await AuthorizationHelpers.ExchangeToken(ClientSecrets, new Regex(@"(?<=code=).?\w+").Match(result.ResponseData).Value); // TODO: Add credential assignment UserCredential credential = await AuthorizationHelpers.ExchangeToken(ClientSecrets, new Regex(@"(?<=code=).?\w+").Match(result.ResponseData).Value);
CurrentUser = new User(credential); CurrentUser = new User(credential);
PasswordVault passwordVault = new PasswordVault();
passwordVault.Add(new PasswordCredential("foxtube", CurrentUser.UserInfo.Id, credential.Token.RefreshToken));
return true; return true;
case WebAuthenticationStatus.UserCancel: case WebAuthenticationStatus.UserCancel:
break; break;
@@ -57,7 +65,8 @@ namespace FoxTube
public static async Task Initialize() public static async Task Initialize()
{ {
PasswordVault passwordVault = new PasswordVault(); PasswordVault passwordVault = new PasswordVault();
List<PasswordCredential> credentials = passwordVault.FindAllByResource("foxtube").ToList(); IReadOnlyList<PasswordCredential> credentials;
credentials = passwordVault.RetrieveAll();
if (credentials.Count == 0) if (credentials.Count == 0)
return; return;
@@ -67,7 +76,12 @@ namespace FoxTube
CurrentUser = new User(credential); CurrentUser = new User(credential);
} }
public static async Task Logout() => public static async Task Logout()
{
PasswordVault passwordVault = new PasswordVault();
PasswordCredential credential = passwordVault.Retrieve("foxtube", CurrentUser.UserInfo.Id);
passwordVault.Remove(credential);
await CurrentUser.Credential.RevokeTokenAsync(CancellationToken.None); await CurrentUser.Credential.RevokeTokenAsync(CancellationToken.None);
} }
} }
}
+43 -9
View File
@@ -1,24 +1,58 @@
using Google.Apis.Auth.OAuth2; using Google.Apis.Auth.OAuth2;
using Google.Apis.Oauth2.v2;
using Google.Apis.Oauth2.v2.Data;
using Google.Apis.Services;
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data; using Google.Apis.YouTube.v3.Data;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using YouTube;
using System.Text;
using System.Threading.Tasks;
namespace FoxTube.Core.Models namespace FoxTube.Core.Models
{ {
public class User public class User
{ {
public string Name { get; set; } public Userinfoplus UserInfo { get; }
public string Email { get; set; } public UserCredential Credential { get; }
internal string RefreshToken { get; set; } public Channel Channel { get; private set; }
public UserCredential Credential { get; set; } public List<Subscription> Subscriptions { get; } = new List<Subscription>();
public Channel Channel { get; set; } public ExtendedYouTubeService Service { get; }
public User(UserCredential credential) public User(UserCredential credential)
{ {
Credential = credential;
BaseClientService.Initializer initializer = new BaseClientService.Initializer
{
ApplicationName = "FoxTube",
HttpClientInitializer = Credential
};
Service = new ExtendedYouTubeService(initializer);
UserInfo = new Oauth2Service(initializer).Userinfo.Get().Execute();
// TODO: Retrieve history and WL
SubscriptionsResource.ListRequest subRequest = Service.Subscriptions.List("snippet");
subRequest.Mine = true;
subRequest.MaxResults = 50;
subRequest.Order = SubscriptionsResource.ListRequest.OrderEnum.Relevance;
SubscriptionListResponse subResponse;
string nextToken = null;
Subscriptions.Clear();
do
{
subRequest.PageToken = nextToken;
subResponse = subRequest.Execute();
foreach (Subscription s in subResponse.Items)
Subscriptions.Add(s);
nextToken = subResponse.NextPageToken;
} while (!string.IsNullOrWhiteSpace(nextToken));
var request = Service.Channels.List("snippet,contentDetails");
request.Mine = true;
Channel = request.Execute().Items[0];
} }
} }
} }
+1 -1
View File
@@ -19,7 +19,7 @@ namespace FoxTube
protected override async void OnLaunched(LaunchActivatedEventArgs e) protected override async void OnLaunched(LaunchActivatedEventArgs e)
{ {
await UserControl.Initialize(); await UsersControl.Initialize();
await StoreInterop.UpdateStoreState(); await StoreInterop.UpdateStoreState();
if (Settings.LastReviewedVersion != Metrics.CurrentVersion) if (Settings.LastReviewedVersion != Metrics.CurrentVersion)
Inbox.PushChangelog(); Inbox.PushChangelog();
+3 -2
View File
@@ -5,10 +5,11 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" mc:Ignorable="d"
Label="Michael 'XFox' Gordeev" Label="Sign in"
xmlns:ui="using:Microsoft.UI.Xaml.Controls" xmlns:ui="using:Microsoft.UI.Xaml.Controls"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls" xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
Style="{StaticResource AppBarButtonRevealStyle}"> Style="{StaticResource AppBarButtonRevealStyle}"
Loaded="AppBarButton_Loaded">
<AppBarButton.Icon> <AppBarButton.Icon>
<FontIcon Glyph="&#xE1E2;"/> <FontIcon Glyph="&#xE1E2;"/>
+23 -7
View File
@@ -10,18 +10,34 @@ namespace FoxTube.Controls
async void Flyout_Opening(object sender, object e) async void Flyout_Opening(object sender, object e)
{ {
if (UserControl.Authorized) if (UsersControl.Authorized)
return; return;
(sender as Flyout).Hide(); (sender as Flyout).Hide();
if(await UserControl.AddUser()) if (await UsersControl.AddUser())
UpdateData();
}
void AppBarButton_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{ {
banner.Source = new BitmapImage(UserControl.CurrentUser.Channel.BrandingSettings.Image.BannerMobileLowImageUrl.ToUri()) { DecodePixelWidth = 300, DecodePixelHeight = 60 }; if (UsersControl.Authorized)
avatar.ProfilePicture = new BitmapImage(UserControl.CurrentUser.Channel.Snippet.Thumbnails.Default__.Url.ToUri()) { DecodePixelHeight = 40, DecodePixelWidth = 40 }; UpdateData();
name.Text = UserControl.CurrentUser.Name; else
email.Text = UserControl.CurrentUser.Email; MainPage.Current.Update();
} }
void UpdateData()
{
Label = UsersControl.CurrentUser.UserInfo.Name;
Icon = new SymbolIcon(Symbol.Contact);
banner.Source = new BitmapImage(UsersControl.CurrentUser.Channel.BrandingSettings.Image.BannerMobileLowImageUrl.ToUri()) { DecodePixelWidth = 300, DecodePixelHeight = 60 };
avatar.ProfilePicture = new BitmapImage(UsersControl.CurrentUser.Channel.Snippet.Thumbnails.Default__.Url.ToUri()) { DecodePixelHeight = 40, DecodePixelWidth = 40 };
name.Text = UsersControl.CurrentUser.UserInfo.Name;
email.Text = UsersControl.CurrentUser.UserInfo.Email;
MainPage.Current.Update();
} }
} }
} }
+1 -1
View File
@@ -292,7 +292,7 @@
<Version>6.0.0</Version> <Version>6.0.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.UI.Xaml"> <PackageReference Include="Microsoft.UI.Xaml">
<Version>2.2.190917002</Version> <Version>2.3.191129002</Version>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
+18 -4
View File
@@ -8,7 +8,8 @@
xmlns:ui="using:Microsoft.UI.Xaml.Controls" xmlns:ui="using:Microsoft.UI.Xaml.Controls"
xmlns:controls="using:FoxTube.Controls" xmlns:controls="using:FoxTube.Controls"
xmlns:toolkit="using:Microsoft.Toolkit.Uwp.UI.Controls" xmlns:toolkit="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:models="using:FoxTube.Core.Models"> xmlns:models="using:FoxTube.Core.Models"
xmlns:data="using:Google.Apis.YouTube.v3.Data">
<Page.Background> <Page.Background>
<AcrylicBrush BackgroundSource="HostBackdrop" TintColor="{ThemeResource SystemAltHighColor}" FallbackColor="{ThemeResource SystemAltHighColor}" TintOpacity=".5"/> <AcrylicBrush BackgroundSource="HostBackdrop" TintColor="{ThemeResource SystemAltHighColor}" FallbackColor="{ThemeResource SystemAltHighColor}" TintOpacity=".5"/>
</Page.Background> </Page.Background>
@@ -59,6 +60,19 @@
</ui:NavigationViewList> </ui:NavigationViewList>
</ui:NavigationView.PaneFooter> </ui:NavigationView.PaneFooter>
<ui:NavigationView.MenuItemTemplate>
<DataTemplate x:DataType="data:Subscription">
<StackPanel Orientation="Horizontal" Padding="5" Margin="-5,0,0,0" Tag="{Binding Snippet.ResourceId.ChannelId}">
<PersonPicture Height="20" Margin="-5,0,15,0">
<PersonPicture.ProfilePicture>
<BitmapImage UriSource="{Binding Snippet.Thumbnails.Medium.Url}" DecodePixelHeight="20" DecodePixelWidth="20"/>
</PersonPicture.ProfilePicture>
</PersonPicture>
<TextBlock FontSize="14" Text="{Binding Snippet.Title}"/>
</StackPanel>
</DataTemplate>
</ui:NavigationView.MenuItemTemplate>
<ui:NavigationView.MenuItems> <ui:NavigationView.MenuItems>
<ui:NavigationViewItem Icon="Home" Content="Home" Name="home"/> <ui:NavigationViewItem Icon="Home" Content="Home" Name="home"/>
<ui:NavigationViewItem Content="Subscriptions" Name="subscriptions"> <ui:NavigationViewItem Content="Subscriptions" Name="subscriptions">
@@ -67,7 +81,7 @@
</ui:NavigationViewItem.Icon> </ui:NavigationViewItem.Icon>
</ui:NavigationViewItem> </ui:NavigationViewItem>
<ui:NavigationViewItemHeader Content="Library"/> <ui:NavigationViewItemHeader Content="Library" Name="libraryHeader"/>
<ui:NavigationViewItem Content="History" Name="history"> <ui:NavigationViewItem Content="History" Name="history">
<ui:NavigationViewItem.Icon> <ui:NavigationViewItem.Icon>
@@ -82,11 +96,11 @@
<ui:NavigationViewItem Icon="Clock" Content="Watch later" Name="wl"/> <ui:NavigationViewItem Icon="Clock" Content="Watch later" Name="wl"/>
<ui:NavigationViewItem Icon="Download" Content="Downloads" Name="download"/> <ui:NavigationViewItem Icon="Download" Content="Downloads" Name="download"/>
<ui:NavigationViewItemHeader Content="Subscriptions"/> <ui:NavigationViewItemHeader Content="Subscriptions" Name="subscriptionsHeader"/>
<ui:NavigationViewItemHeader Content="Best of YouTube"/> <ui:NavigationViewItemHeader Content="Best of YouTube" Name="categoriesHeader"/>
<ui:NavigationViewItem Content="Music" Name="music"> <ui:NavigationViewItem Content="Music" Name="music">
<ui:NavigationViewItem.Icon> <ui:NavigationViewItem.Icon>
<FontIcon Glyph="&#xE189;"/> <FontIcon Glyph="&#xE189;"/>
+31
View File
@@ -1,5 +1,6 @@
using FoxTube.Core.Helpers; using FoxTube.Core.Helpers;
using FoxTube.Core.Models; using FoxTube.Core.Models;
using Google.Apis.YouTube.v3.Data;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -235,5 +236,35 @@ namespace FoxTube
break; break;
} }
} }
public void Update()
{
if(UsersControl.Authorized)
{
for (int i = NavigationViewControl.MenuItems.IndexOf(subscriptions); i < NavigationViewControl.MenuItems.IndexOf(categoriesHeader); i++)
(NavigationViewControl.MenuItems[i] as FrameworkElement).Visibility = Visibility.Visible;
for (int i = NavigationViewControl.MenuItems.IndexOf(categoriesHeader); i < NavigationViewControl.MenuItems.Count; i++)
(NavigationViewControl.MenuItems[i] as FrameworkElement).Visibility = Visibility.Collapsed;
foreach (Subscription i in UsersControl.CurrentUser.Subscriptions)
NavigationViewControl.MenuItems.Insert(NavigationViewControl.MenuItems.IndexOf(categoriesHeader), i);
}
else
{
IEnumerable<object> subs = from i in NavigationViewControl.MenuItems
where string.IsNullOrWhiteSpace((i as FrameworkElement).Name)
select i;
foreach (object i in subs)
NavigationViewControl.MenuItems.Remove(i);
for (int i = NavigationViewControl.MenuItems.IndexOf(subscriptions); i < NavigationViewControl.MenuItems.IndexOf(categoriesHeader); i++)
(NavigationViewControl.MenuItems[i] as FrameworkElement).Visibility = Visibility.Collapsed;
for (int i = NavigationViewControl.MenuItems.IndexOf(categoriesHeader); i < NavigationViewControl.MenuItems.Count; i++)
(NavigationViewControl.MenuItems[i] as FrameworkElement).Visibility = Visibility.Visible;
}
}
} }
} }