| @@ -0,0 +1,17 @@ | |||
| using ProtoBuf; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace GrpcShared.DTO.Db | |||
| { | |||
| [ProtoContract] | |||
| public class DbRequestMessage | |||
| { | |||
| [ProtoMember(1)] | |||
| public string Id { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,16 @@ | |||
| using ProtoBuf; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace GrpcShared.DTO.Db | |||
| { | |||
| [ProtoContract] | |||
| public class SaveTrackRequest : TrackResponse | |||
| { | |||
| [ProtoMember(1)] | |||
| public string UserId { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,25 @@ | |||
| using ProtoBuf; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace GrpcShared.DTO.Db | |||
| { | |||
| [ProtoContract] | |||
| [ProtoInclude(6, typeof(SaveTrackRequest))] | |||
| public class TrackResponse | |||
| { | |||
| [ProtoMember(1)] | |||
| public string Id { get; set; } | |||
| [ProtoMember(2)] | |||
| public string Title { get; set; } | |||
| [ProtoMember(3)] | |||
| public string Artist { get; set; } | |||
| [ProtoMember(4)] | |||
| public string Album { get; set; } | |||
| [ProtoMember(5)] | |||
| public string TrackId { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,20 @@ | |||
| using ProtoBuf; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace GrpcShared.DTO.Db | |||
| { | |||
| [ProtoContract] | |||
| public class UserResponse | |||
| { | |||
| [ProtoMember(1)] | |||
| public string Id { get; set; } | |||
| [ProtoMember(2)] | |||
| public string Token { get; set; } | |||
| [ProtoMember(3)] | |||
| public string RefreshToken{ get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| using ProtoBuf; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace GrpcShared.DTO | |||
| { | |||
| [ProtoContract] | |||
| public class VoidMessage | |||
| { | |||
| [ProtoMember(1)] | |||
| public string InsertedId { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,24 @@ | |||
| using GrpcShared.DTO; | |||
| using GrpcShared.DTO.Db; | |||
| using ProtoBuf.Grpc.Configuration; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace GrpcShared.Interfaces | |||
| { | |||
| [Service] | |||
| public interface IIdentityService | |||
| { | |||
| Task<UserResponse> GetTokenByIdAsync(DbRequestMessage id); | |||
| Task<List<UserResponse>> ListUsersAsync(VoidMessage msg); | |||
| Task<TrackResponse> GetTrackByUserAsync(DbRequestMessage id); | |||
| Task<VoidMessage> SaveTrackAsync(SaveTrackRequest track); | |||
| Task<VoidMessage> DeleteTrackAsync(DbRequestMessage id); | |||
| Task<VoidMessage> SaveUserAsync(UserResponse user); | |||
| Task<VoidMessage> DeleteUserAsync(DbRequestMessage user); | |||
| Task<VoidMessage> UpdateTokenAsync (UserResponse user); | |||
| } | |||
| } | |||
| @@ -10,6 +10,7 @@ | |||
| <PackageReference Include="Grpc.AspNetCore" Version="2.40.0" /> | |||
| <PackageReference Include="Grpc.AspNetCore.Web" Version="2.47.0" /> | |||
| <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="6.0.8" /> | |||
| <PackageReference Include="MongoDB.Driver" Version="2.17.1" /> | |||
| <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> | |||
| <PackageReference Include="protobuf-net.Grpc" Version="1.0.171" /> | |||
| <PackageReference Include="protobuf-net.Grpc.AspNetCore" Version="1.0.152" /> | |||
| @@ -24,8 +25,4 @@ | |||
| <ProjectReference Include="..\NemAnCore\NemAnBlazor.csproj" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <Folder Include="Services\" /> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -0,0 +1,10 @@ | |||
| namespace IdentityProvider.Models | |||
| { | |||
| public class SpotifyDbConfig | |||
| { | |||
| public string ConnectionString { get; set; } = null!; | |||
| public string DatabaseName { get; set; } = null!; | |||
| public string UserCollection { get; set; } = null!; | |||
| public string TracksCollection { get; set; } = null!; | |||
| } | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| using MongoDB.Bson; | |||
| using MongoDB.Bson.Serialization.Attributes; | |||
| namespace IdentityProvider.Models | |||
| { | |||
| public class TrackModel | |||
| { | |||
| [BsonId] | |||
| [BsonRepresentation(BsonType.ObjectId)] | |||
| public string Id { get; set; } | |||
| public string Title { get; set; } | |||
| public string Artist { get; set; } | |||
| public string Album { get; set; } | |||
| public string UserId { get; set; } | |||
| public string TrackId { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,14 @@ | |||
| using MongoDB.Bson; | |||
| using MongoDB.Bson.Serialization.Attributes; | |||
| namespace IdentityProvider.Models | |||
| { | |||
| public class UserModel | |||
| { | |||
| [BsonId] | |||
| [BsonRepresentation(BsonType.ObjectId)] | |||
| public string Id { get; set; } | |||
| public string Token { get; set; } | |||
| public string RefreshToken { get; set; } | |||
| } | |||
| } | |||
| @@ -5,6 +5,8 @@ using ProtoBuf.Grpc.Server; | |||
| using Microsoft.Extensions.Options; | |||
| using GrpcShared.DTO.Auth; | |||
| using Blazored.LocalStorage; | |||
| using IdentityProvider.Models; | |||
| using IdentityProvider.Services; | |||
| var builder = WebApplication.CreateBuilder(args); | |||
| #if DEBUG | |||
| @@ -25,6 +27,7 @@ builder.Services.AddHttpClient("HttpClient", c => | |||
| }); | |||
| builder.Services.AddOptions(); | |||
| builder.Services.AddSingleton<SpotifyDbConfig>(); | |||
| // Additional configuration is required to successfully run gRPC on macOS. | |||
| // For instructions on how to configure Kestrel and gRPC clients on macOS, visit https://go.microsoft.com/fwlink/?linkid=2099682 | |||
| builder.Services.AddControllersWithViews(); | |||
| @@ -38,7 +41,12 @@ builder.Services.AddCodeFirstGrpcReflection(); | |||
| builder.Services.AddBlazoredLocalStorage(); | |||
| //call spotify api | |||
| builder.Services.AddHttpClient(); | |||
| builder.Services.Configure<CodeRequest>(builder.Configuration.GetSection("AuthParams")); | |||
| builder.Services.Configure<CodeRequest>( | |||
| builder.Configuration.GetSection("AuthParams")); | |||
| builder.Services.Configure<SpotifyDbConfig>( | |||
| builder.Configuration.GetSection("SpotifyDb")); | |||
| var app = builder.Build(); | |||
| @@ -72,6 +80,7 @@ app.MapControllers(); | |||
| app.MapGrpcService<AuthService>().EnableGrpcWeb(); | |||
| app.MapGrpcService<TrackService>().EnableGrpcWeb(); | |||
| app.MapGrpcService<StatsService>().EnableGrpcWeb(); | |||
| app.MapGrpcService<IdentityService>().EnableGrpcWeb(); | |||
| app.MapCodeFirstGrpcReflectionService(); | |||
| @@ -1,4 +1,4 @@ | |||
| { | |||
| { | |||
| "iisSettings": { | |||
| "windowsAuthentication": false, | |||
| "anonymousAuthentication": true, | |||
| @@ -10,21 +10,20 @@ | |||
| "profiles": { | |||
| "IIS Express": { | |||
| "commandName": "IISExpress", | |||
| "launchBrowser": true, | |||
| "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", | |||
| "environmentVariables": { | |||
| "ASPNETCORE_ENVIRONMENT": "Development" | |||
| } | |||
| }, | |||
| "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}" | |||
| }, | |||
| "IdentityProvider": { | |||
| "commandName": "Project", | |||
| "dotnetRunMessages": "true", | |||
| "launchBrowser": true, | |||
| "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", | |||
| "applicationUrl": "https://localhost:5001;http://localhost:5000", | |||
| "environmentVariables": { | |||
| "ASPNETCORE_ENVIRONMENT": "Development" | |||
| } | |||
| }, | |||
| "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", | |||
| "applicationUrl": "https://localhost:5001;http://localhost:5000", | |||
| "dotnetRunMessages": "true" | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,131 @@ | |||
| using GrpcShared.DTO; | |||
| using GrpcShared.DTO.Db; | |||
| using GrpcShared.Interfaces; | |||
| using IdentityProvider.Models; | |||
| using Microsoft.Extensions.Options; | |||
| using MongoDB.Driver; | |||
| namespace IdentityProvider.Services | |||
| { | |||
| public class IdentityService : IIdentityService | |||
| { | |||
| private readonly IMongoCollection<UserModel> _userCollection; | |||
| private readonly IMongoCollection<TrackModel> _trackCollection; | |||
| public IdentityService(IOptions<SpotifyDbConfig> spotifyDbConfig) | |||
| { | |||
| var mongoClient = new MongoClient(spotifyDbConfig.Value.ConnectionString); | |||
| var mongoDbContext = mongoClient.GetDatabase(spotifyDbConfig.Value.DatabaseName); | |||
| _userCollection = mongoDbContext.GetCollection<UserModel>(spotifyDbConfig.Value.UserCollection); | |||
| _trackCollection = mongoDbContext.GetCollection<TrackModel>(spotifyDbConfig.Value.TracksCollection); | |||
| } | |||
| public async Task<List<UserResponse>> ListUsersAsync(VoidMessage msg) | |||
| { | |||
| List<UserModel> users = await _userCollection.Find(_ => true).ToListAsync(); | |||
| //map users to match the grpc response | |||
| var usersRes = users.Select(u => new UserResponse | |||
| { | |||
| Id = u.Id, | |||
| Token = u.Token | |||
| }).ToList(); | |||
| return usersRes; | |||
| } | |||
| public async Task<UserResponse> GetTokenByIdAsync(DbRequestMessage request) | |||
| { | |||
| UserModel user = await _userCollection.Find(u => u.Id == request.Id).FirstOrDefaultAsync(); | |||
| if (user != null) | |||
| return new UserResponse | |||
| { | |||
| Id = user.Id, | |||
| Token = user.Token | |||
| }; | |||
| else return new UserResponse(); | |||
| } | |||
| public async Task<TrackResponse> GetTrackByUserAsync(DbRequestMessage request) | |||
| { | |||
| TrackModel track = await _trackCollection.Find(t => t.UserId == request.Id).FirstOrDefaultAsync(); | |||
| return new TrackResponse | |||
| { | |||
| Id = track.Id, | |||
| Album = track.Album, | |||
| Artist = track.Artist, | |||
| Title = track.Title, | |||
| TrackId = track.TrackId | |||
| }; | |||
| } | |||
| public async Task<VoidMessage> SaveTrackAsync(SaveTrackRequest track) | |||
| { | |||
| TrackModel trackModel = new() | |||
| { | |||
| Id = track.Id, | |||
| Title = track.Title, | |||
| Album = track.Album, | |||
| Artist = track.Artist, | |||
| UserId = track.UserId, | |||
| TrackId = track.TrackId | |||
| }; | |||
| //first check if there's already a song in the db, if yes, update the row | |||
| bool song = await _trackCollection.Find(x => x.UserId == track.UserId).AnyAsync(); | |||
| if (song) await _trackCollection.DeleteOneAsync(s => s.UserId == track.UserId); | |||
| await _trackCollection.InsertOneAsync(trackModel); | |||
| return new VoidMessage() { InsertedId = trackModel.Id }; | |||
| } | |||
| public async Task<VoidMessage> SaveUserAsync(UserResponse userRequest) | |||
| { | |||
| bool user = await _userCollection.Find(x => x.Id == userRequest.Id).AnyAsync(); | |||
| UserModel tempUser = new() | |||
| { | |||
| Token = userRequest.Token, | |||
| RefreshToken = userRequest.RefreshToken | |||
| }; | |||
| if (!user) await _userCollection.InsertOneAsync(tempUser); | |||
| return new VoidMessage() { InsertedId = tempUser.Id }; | |||
| } | |||
| public async Task<VoidMessage> DeleteTrackAsync(DbRequestMessage request) | |||
| { | |||
| await _trackCollection.DeleteOneAsync(x => x.Id == request.Id); | |||
| return new VoidMessage(); | |||
| } | |||
| public async Task<VoidMessage> DeleteUserAsync(DbRequestMessage userRequest) | |||
| { | |||
| //check if user exists | |||
| bool user = await _userCollection.Find(x => x.Id == userRequest.Id).AnyAsync(); | |||
| //delete track related to him | |||
| if (user) | |||
| { | |||
| await _trackCollection.DeleteManyAsync(x => x.UserId == userRequest.Id); | |||
| //delete user | |||
| await _userCollection.DeleteOneAsync(x => x.Id == userRequest.Id); | |||
| } | |||
| return new VoidMessage(); | |||
| } | |||
| public async Task<VoidMessage> UpdateTokenAsync(UserResponse user) | |||
| { | |||
| UserModel dbUser = await _userCollection.Find(x => x.Id == user.Id).FirstOrDefaultAsync(); | |||
| if (dbUser.Id != null) | |||
| { | |||
| dbUser.Token = user.Token; | |||
| dbUser.RefreshToken = user.RefreshToken; | |||
| await _userCollection.ReplaceOneAsync(x => x.Id == user.Id, dbUser); | |||
| } | |||
| return new VoidMessage | |||
| { | |||
| InsertedId = dbUser.Id | |||
| }; | |||
| } | |||
| } | |||
| } | |||
| @@ -16,5 +16,11 @@ | |||
| "RedirectURI": "https://localhost:44342/callback", | |||
| "Scope": "user-read-currently-playing user-read-email user-library-modify user-top-read user-read-private", | |||
| "ClientSecret": "ea752433d0774fad87fab5c1ee788c8d" | |||
| }, | |||
| "SpotifyDb": { | |||
| "ConnectionString": "mongodb://127.0.0.1:27017", | |||
| "DatabaseName": "spotifyDb", | |||
| "UserCollection": "Users", | |||
| "TracksCollection": "Tracks" | |||
| } | |||
| } | |||
| @@ -1,8 +1,12 @@ | |||
| @page "/callback" | |||
| @using GrpcShared.DTO | |||
| @using GrpcShared.DTO.Db | |||
| @using NemAnBlazor.Services.Interfaces | |||
| @inject NavigationManager NavigationMgr | |||
| @inject IAuthClientService AuthService | |||
| @inject Blazored.LocalStorage.ILocalStorageService localStorage | |||
| @inject IIdentityClientService identityService | |||
| <PageTitle>Redirecting...</PageTitle> | |||
| @@ -24,9 +28,20 @@ | |||
| //if (response.access_token == null) NavigationMgr.NavigateTo("/"); | |||
| //store access token in local storage | |||
| await localStorage.SetItemAsync("token", response.AccessToken); | |||
| await localStorage.SetItemAsync("refresh_token", response.RefreshToken); | |||
| //await localStorage.SetItemAsync("token", response.AccessToken); | |||
| //await localStorage.SetItemAsync("refresh_token", response.RefreshToken); | |||
| //UserResponse user = new(); | |||
| //await identityService.SaveUserAsync(new GrpcShared.DTO.Db.UserResponse()); | |||
| string userId = await localStorage.GetItemAsync<string>("user_info"); | |||
| if(userId == null) | |||
| { | |||
| VoidMessage userRes = await identityService.SaveUserAsync(new GrpcShared.DTO.Db.UserResponse { RefreshToken = response.RefreshToken , Token = response.AccessToken}); | |||
| if (userRes.InsertedId != null) | |||
| await localStorage.SetItemAsync<string>("user_info", userRes.InsertedId); | |||
| } | |||
| //redirect to home | |||
| NavigationMgr.NavigateTo("/home"); | |||
| } | |||
| @@ -12,6 +12,7 @@ | |||
| @inject Blazored.LocalStorage.ILocalStorageService localStorage | |||
| @inject ITrackClientService SearchService | |||
| @inject IAuthClientService AuthService | |||
| @inject IIdentityClientService identityService | |||
| <PageTitle>Search</PageTitle> | |||
| @@ -35,12 +36,16 @@ | |||
| private async Task Click() | |||
| { | |||
| var token = await localStorage.GetItemAsync<string>("token"); | |||
| string refreshT = await localStorage.GetItemAsync<string>("refresh_token"); | |||
| var userInfo = await localStorage.GetItemAsync<string>("user_info"); | |||
| TokenMessage tokenM = new TokenMessage { Token = token, RefreshToken = refreshT }; | |||
| var user = await identityService.GetTokenByIdAsync(new GrpcShared.DTO.Db.DbRequestMessage | |||
| { | |||
| Id = userInfo | |||
| }); | |||
| TokenMessage tokenM = new TokenMessage { Token = user.Token, RefreshToken = user.RefreshToken }; | |||
| SearchRequest request = new() { Query = "aitch", Type = "track", Token = token }; | |||
| SearchRequest request = new() { Query = "aitch", Type = "track", Token = user.Token }; | |||
| try | |||
| { | |||
| @@ -48,8 +53,7 @@ | |||
| if (searchResponse.ResponseMsg == System.Net.HttpStatusCode.Unauthorized) | |||
| { | |||
| string? tempToken = await SpotifyHelper.TryRefreshToken(AuthService, tokenM, localStorage); | |||
| token = tempToken == null ? token : tempToken; | |||
| string? tempToken = await SpotifyHelper.TryRefreshToken(AuthService, tokenM, user, localStorage, identityService); | |||
| } | |||
| } | |||
| catch (RpcException e) | |||
| @@ -1,6 +1,7 @@ | |||
| @page "/home" | |||
| @using Grpc.Core | |||
| @using GrpcShared.DTO | |||
| @using GrpcShared.DTO.Db | |||
| @using GrpcShared.DTO.Track | |||
| @using NemAnBlazor.Services.Interfaces | |||
| @using System.Net | |||
| @@ -8,6 +9,8 @@ | |||
| @inject IStatsClientService spotifyService | |||
| @inject ITrackClientService trackService | |||
| @inject IAuthClientService AuthService | |||
| @inject NavigationManager NavigationMgr | |||
| @inject IIdentityClientService identityService | |||
| <h3>Home</h3> | |||
| @@ -16,21 +19,38 @@ | |||
| @code { | |||
| protected override async Task OnInitializedAsync() | |||
| { | |||
| CurrentTrackResponse track; | |||
| string tokenS = "", refreshT = ""; | |||
| string userId = await localStorage.GetItemAsync<string>("user_info"); | |||
| string tokenS = await localStorage.GetItemAsync<string>("token"); | |||
| string refreshT = await localStorage.GetItemAsync<string>("refresh_token"); | |||
| if (userId != null) | |||
| { | |||
| //get token from identity | |||
| var userResponse = await identityService.GetTokenByIdAsync(new GrpcShared.DTO.Db.DbRequestMessage { Id = userId }); | |||
| //tokenS = "BQBMgFm6jnFNWWeZEMGIRP_f-ENPid7Kw8JubAyuWAe4JK0S1DPFGlaAdZ_Fey6ePkCnz8-cqC0oyRmrciWUy5ISUTQKDe8PTQn4iBRMYCgM0n4GnS1xAErHJcm4Vpu2TAngk-4vQUOfTQRcedNTfCaHKP4uFJgTlTI7JHGrtB-_EZLnFcZ2OQe31oFQIJ1wM3ZtvwnN"; | |||
| TokenMessage token = new TokenMessage { Token = tokenS, RefreshToken = refreshT }; | |||
| if (userResponse != null) | |||
| { | |||
| tokenS = userResponse.Token; | |||
| refreshT = userResponse.RefreshToken; | |||
| } | |||
| else { | |||
| await localStorage.RemoveItemAsync("user_info"); | |||
| NavigationMgr.NavigateTo("/"); | |||
| } | |||
| } | |||
| //tokenS = "BQBMgFm6jnFNWWeZEMGIRP_f-ENPid7Kw8JubAyuWAe4JK0S1DPFGlaAdZ_Fey6ePkCnz8-cqC0oyRmrciWUy5ISUTQKDe8PTQn4iBRMYCgM0n4GnS1xAErHJcm4Vpu2TAngk-4vQUOfTQRcedNTfCaHKP4uFJgTlTI7JHGrtB-_EZLnFcZ2OQe31oFQIJ1wM3ZtvwnN"; | |||
| TokenMessage token = new() { Token = tokenS, RefreshToken = refreshT }; | |||
| UserResponse user = new() { Id = userId, RefreshToken = refreshT }; | |||
| try | |||
| { | |||
| CurrentTrackResponse track = await spotifyService.GetCurrentlyPlayingTrack(token); | |||
| track = await spotifyService.GetCurrentlyPlayingTrack(token); | |||
| //if token expired, refresh it | |||
| if (track.ResponseMsg == System.Net.HttpStatusCode.Unauthorized) | |||
| { | |||
| string? tempToken = await SpotifyHelper.TryRefreshToken(AuthService, token, localStorage); | |||
| string? tempToken = await SpotifyHelper.TryRefreshToken(AuthService, token, user, localStorage, identityService); | |||
| tokenS = tempToken == null ? tokenS : tempToken; | |||
| //if refreshed token is null, that means that refresh token was invalid, so you should redirect to login | |||
| } | |||
| @@ -54,7 +74,7 @@ | |||
| if (items.ResponseMsg == System.Net.HttpStatusCode.Unauthorized) | |||
| { | |||
| string? tempToken = await SpotifyHelper.TryRefreshToken(AuthService, token, localStorage); | |||
| string? tempToken = await SpotifyHelper.TryRefreshToken(AuthService, token, user, localStorage, identityService); | |||
| tokenS = tempToken == null ? tokenS : tempToken; | |||
| } | |||
| } | |||
| @@ -68,5 +88,43 @@ | |||
| } | |||
| await identityService.SaveTrackAsync(new GrpcShared.DTO.Db.SaveTrackRequest | |||
| { | |||
| TrackId = track.Item.Id, | |||
| Title = track.Item.Name, | |||
| Album = track.Item.Album.Name, | |||
| Artist = track.Item.Artists[0].Name, | |||
| UserId = userId | |||
| }); | |||
| //var resp = await identityService.ListUsersAsync(new VoidMessage()); | |||
| var tokenFromDb = await identityService.GetTokenByIdAsync(new GrpcShared.DTO.Db.DbRequestMessage | |||
| { | |||
| Id = userId | |||
| }); | |||
| var trackByUser = await identityService.GetTrackByUserAsync(new GrpcShared.DTO.Db.DbRequestMessage | |||
| { | |||
| Id = userId | |||
| }); | |||
| //await identityService.DeleteTrackAsync(new GrpcShared.DTO.Db.DbRequestMessage | |||
| // { | |||
| // Id = | |||
| // }); | |||
| await identityService.SaveTrackAsync(new GrpcShared.DTO.Db.SaveTrackRequest | |||
| { | |||
| TrackId = track.Item.Id, | |||
| Title = track.Item.Name, | |||
| Album = track.Item.Album.Name, | |||
| Artist = track.Item.Artists[0].Name, | |||
| UserId = userId | |||
| }); | |||
| //find id from local storage | |||
| //await identityService.DeleteUserAsync(new GrpcShared.DTO.Db.DbRequestMessage | |||
| // { | |||
| // Id = userId | |||
| // }); | |||
| } | |||
| } | |||
| @@ -9,6 +9,7 @@ | |||
| @inject IAuthClientService AuthService | |||
| @inject ITrackClientService SearchService | |||
| @using System.Security.Claims | |||
| @inject Blazored.LocalStorage.ILocalStorageService localStorage | |||
| @@ -35,7 +36,12 @@ Dobrodošli u našu NemAn aplikaciju. | |||
| @code { | |||
| private string? message; | |||
| protected override async Task OnInitializedAsync() | |||
| { | |||
| var userId = await localStorage.GetItemAsync<string>("user_info"); | |||
| if (userId != null) NavigationManager.NavigateTo("/home"); | |||
| } | |||
| private async Task LoginUser() | |||
| { | |||
| //var response = await SearchService.GetListSearchAsync(new GrpcShared.DTO.Search.SearchRequest() { Query="venom", Type = "track"}); | |||
| @@ -28,6 +28,7 @@ builder.Services.AddAuthorizationCore(); | |||
| builder.Services.AddScoped<ITrackClientService, TrackClientService>(); | |||
| builder.Services.AddScoped<IAuthClientService, AuthClientService>(); | |||
| builder.Services.AddScoped<IStatsClientService, StatsClientService>(); | |||
| builder.Services.AddScoped<IIdentityClientService, IdentityClientService>(); | |||
| builder.Services.AddBlazoredLocalStorage(); | |||
| builder.Services.AddScoped<AuthenticationStateProvider, AuthClientService>(); | |||
| builder.Services.AddAuthorizationCore(); | |||
| @@ -0,0 +1,57 @@ | |||
| using Grpc.Net.Client; | |||
| using GrpcShared.DTO; | |||
| using GrpcShared.DTO.Db; | |||
| using GrpcShared.Interfaces; | |||
| using NemAnBlazor.Services.Interfaces; | |||
| using ProtoBuf.Grpc.Client; | |||
| namespace NemAnBlazor.Services | |||
| { | |||
| public class IdentityClientService : IIdentityClientService | |||
| { | |||
| private IIdentityService _serviceClient; | |||
| public IdentityClientService(GrpcChannel channel) | |||
| { | |||
| _serviceClient = channel.CreateGrpcService<IIdentityService>(); | |||
| } | |||
| public async Task<VoidMessage> DeleteTrackAsync(DbRequestMessage id) | |||
| { | |||
| return await _serviceClient.DeleteTrackAsync(id); | |||
| } | |||
| public async Task<VoidMessage> DeleteUserAsync(DbRequestMessage user) | |||
| { | |||
| return await _serviceClient.DeleteUserAsync(user); | |||
| } | |||
| public async Task<UserResponse> GetTokenByIdAsync(DbRequestMessage id) | |||
| { | |||
| return await _serviceClient.GetTokenByIdAsync(id); | |||
| } | |||
| public async Task<TrackResponse> GetTrackByUserAsync(DbRequestMessage id) | |||
| { | |||
| return await _serviceClient.GetTrackByUserAsync(id); | |||
| } | |||
| public async Task<List<UserResponse>> ListUsersAsync(VoidMessage msg) | |||
| { | |||
| return await _serviceClient.ListUsersAsync(msg); | |||
| } | |||
| public async Task<VoidMessage> SaveTrackAsync(SaveTrackRequest track) | |||
| { | |||
| return await _serviceClient.SaveTrackAsync(track); | |||
| } | |||
| public async Task<VoidMessage> SaveUserAsync(UserResponse user) | |||
| { | |||
| return await _serviceClient.SaveUserAsync(user); | |||
| } | |||
| public async Task<VoidMessage> UpdateTokenAsync(UserResponse user) | |||
| { | |||
| return await _serviceClient.UpdateTokenAsync(user); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| using GrpcShared.DTO; | |||
| using GrpcShared.DTO.Db; | |||
| namespace NemAnBlazor.Services.Interfaces | |||
| { | |||
| public interface IIdentityClientService | |||
| { | |||
| Task<UserResponse> GetTokenByIdAsync(DbRequestMessage id); | |||
| Task<List<UserResponse>> ListUsersAsync(VoidMessage msg); | |||
| Task<TrackResponse> GetTrackByUserAsync(DbRequestMessage id); | |||
| Task<VoidMessage> SaveTrackAsync(SaveTrackRequest track); | |||
| Task<VoidMessage> DeleteTrackAsync(DbRequestMessage id); | |||
| Task<VoidMessage> SaveUserAsync(UserResponse user); | |||
| Task<VoidMessage> DeleteUserAsync(DbRequestMessage user); | |||
| Task<VoidMessage> UpdateTokenAsync(UserResponse user); | |||
| } | |||
| } | |||
| @@ -1,18 +1,28 @@ | |||
| using Blazored.LocalStorage; | |||
| using GrpcShared.DTO; | |||
| using GrpcShared.DTO.Db; | |||
| using NemAnBlazor.Services.Interfaces; | |||
| namespace NemAnBlazor | |||
| { | |||
| public static class SpotifyHelper | |||
| { | |||
| public static async Task<string?> TryRefreshToken(IAuthClientService authService, TokenMessage msg, ILocalStorageService localStorage) | |||
| public static async Task<string?> TryRefreshToken | |||
| (IAuthClientService authService, | |||
| TokenMessage msg,UserResponse user, | |||
| ILocalStorageService localStorage, | |||
| IIdentityClientService identityService) | |||
| { | |||
| var refreshResponse = await authService.RefreshAccessToken(msg); | |||
| if (refreshResponse.AccessToken != null) | |||
| { | |||
| await localStorage.SetItemAsync<string>("token", refreshResponse.AccessToken); | |||
| await identityService.UpdateTokenAsync(new UserResponse | |||
| { | |||
| Id = user.Id, | |||
| Token = refreshResponse.AccessToken, | |||
| RefreshToken = user.RefreshToken | |||
| }); | |||
| return refreshResponse.AccessToken; | |||
| } | |||
| else return null; | |||
| @@ -11,4 +11,9 @@ | |||
| <PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" /> | |||
| <PackageReference Include="protobuf-net.Grpc" Version="1.0.171" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <ProjectReference Include="..\gRPCServer\SpotifyService.csproj" /> | |||
| <ProjectReference Include="..\IdentityProvider\IdentityProvider.csproj" /> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -3,18 +3,23 @@ namespace SpotifyWorker | |||
| public class Worker : BackgroundService | |||
| { | |||
| private readonly ILogger<Worker> _logger; | |||
| private HttpClient _httpClient; | |||
| public Worker(ILogger<Worker> logger) | |||
| { | |||
| _logger = logger; | |||
| } | |||
| public override Task StartAsync(CancellationToken cancellationToken) | |||
| { | |||
| _httpClient = new HttpClient(); | |||
| return base.StartAsync(cancellationToken); | |||
| } | |||
| protected override async Task ExecuteAsync(CancellationToken stoppingToken) | |||
| { | |||
| while (!stoppingToken.IsCancellationRequested) | |||
| { | |||
| _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); | |||
| await Task.Delay(1000, stoppingToken); | |||
| await Task.Delay(5000, stoppingToken); | |||
| } | |||
| } | |||
| } | |||