| @@ -11,7 +11,7 @@ namespace GrpcShared.DTO.Db | |||
| public class DbRequestMessage | |||
| { | |||
| [ProtoMember(1)] | |||
| public string Id { get; set; } | |||
| public string? Id { get; set; } | |||
| } | |||
| } | |||
| @@ -11,6 +11,6 @@ namespace GrpcShared.DTO.Db | |||
| public class SaveTrackRequest : TrackResponse | |||
| { | |||
| [ProtoMember(1)] | |||
| public string UserId { get; set; } | |||
| public string? UserId { get; set; } | |||
| } | |||
| } | |||
| @@ -12,14 +12,14 @@ namespace GrpcShared.DTO.Db | |||
| public class TrackResponse | |||
| { | |||
| [ProtoMember(1)] | |||
| public string Id { get; set; } | |||
| public string? Id { get; set; } | |||
| [ProtoMember(2)] | |||
| public string Title { get; set; } | |||
| public string? Title { get; set; } | |||
| [ProtoMember(3)] | |||
| public string Artist { get; set; } | |||
| public string? Artist { get; set; } | |||
| [ProtoMember(4)] | |||
| public string Album { get; set; } | |||
| public string? Album { get; set; } | |||
| [ProtoMember(5)] | |||
| public string TrackId { get; set; } | |||
| public string? TrackId { get; set; } | |||
| } | |||
| } | |||
| @@ -11,10 +11,10 @@ namespace GrpcShared.DTO.Db | |||
| public class UserResponse | |||
| { | |||
| [ProtoMember(1)] | |||
| public string Id { get; set; } | |||
| public string? Id { get; set; } | |||
| [ProtoMember(2)] | |||
| public string Token { get; set; } | |||
| public string? Token { get; set; } | |||
| [ProtoMember(3)] | |||
| public string RefreshToken{ get; set; } | |||
| public string? RefreshToken{ get; set; } | |||
| } | |||
| } | |||
| @@ -11,7 +11,7 @@ namespace GrpcShared.DTO | |||
| public class VoidMessage | |||
| { | |||
| [ProtoMember(1)] | |||
| public string InsertedId { get; set; } | |||
| public string? InsertedId { get; set; } | |||
| } | |||
| } | |||
| @@ -3,7 +3,7 @@ namespace Shared | |||
| { | |||
| public static class GLOBALS | |||
| { | |||
| public const String SPOTIFYURL = "https://api.spotify.com/v1/"; | |||
| public const String MEDIATYPE = "application/json"; | |||
| public const string SPOTIFYURL = "https://api.spotify.com/v1/"; | |||
| public const string MEDIATYPE = "application/json"; | |||
| } | |||
| } | |||
| @@ -7,11 +7,11 @@ namespace IdentityProvider.Models | |||
| { | |||
| [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; } | |||
| 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; } | |||
| } | |||
| } | |||
| @@ -7,8 +7,8 @@ namespace IdentityProvider.Models | |||
| { | |||
| [BsonId] | |||
| [BsonRepresentation(BsonType.ObjectId)] | |||
| public string Id { get; set; } | |||
| public string Token { get; set; } | |||
| public string RefreshToken { get; set; } | |||
| public string? Id { get; set; } | |||
| public string? Token { get; set; } | |||
| public string? RefreshToken { get; set; } | |||
| } | |||
| } | |||
| @@ -30,8 +30,8 @@ | |||
| if (userResponse != null) | |||
| { | |||
| tokenS = userResponse.Token; | |||
| refreshT = userResponse.RefreshToken; | |||
| tokenS = userResponse.Token!; | |||
| refreshT = userResponse.RefreshToken!; | |||
| } | |||
| else | |||
| { | |||
| @@ -59,23 +59,23 @@ | |||
| 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 | |||
| 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 | |||
| Id = userId! | |||
| }); | |||
| var trackByUser = await identityService.GetTrackByUserAsync(new GrpcShared.DTO.Db.DbRequestMessage | |||
| { | |||
| Id = userId | |||
| Id = userId! | |||
| }); | |||
| //await identityService.DeleteTrackAsync(new GrpcShared.DTO.Db.DbRequestMessage | |||
| // { | |||
| @@ -84,11 +84,11 @@ | |||
| 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 | |||
| 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 | |||
| @@ -34,7 +34,7 @@ Dobrodošli u našu NemAn aplikaciju. | |||
| @code { | |||
| private string? message; | |||
| protected override async Task OnInitializedAsync() | |||
| { | |||
| @@ -3,7 +3,7 @@ namespace SpotifyWorker | |||
| public class Worker : BackgroundService | |||
| { | |||
| private readonly ILogger<Worker> _logger; | |||
| private HttpClient _httpClient; | |||
| private HttpClient? _httpClient; | |||
| public Worker(ILogger<Worker> logger) | |||
| { | |||
| _logger = logger; | |||
| @@ -37,9 +37,10 @@ namespace SpotifyService.HttpUtils | |||
| if (req.StatusCode == System.Net.HttpStatusCode.Unauthorized) | |||
| { | |||
| string newToken = await SpotifyHelper.TryRefreshToken(authService, userResponse, identityService); | |||
| string? newToken = await TryRefreshToken(authService, userResponse, identityService); | |||
| if (newToken != null) | |||
| { | |||
| client.DefaultRequestHeaders.Remove(HeaderNames.Authorization); | |||
| client.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Bearer " + newToken); | |||
| req = await client.GetAsync(url); | |||
| response = JsonConvert.DeserializeObject<T>(await req.Content.ReadAsStringAsync())!; | |||
| @@ -61,24 +62,32 @@ namespace SpotifyService.HttpUtils | |||
| } | |||
| public static async Task PutData(HttpClient client, string url, string userId, IIdentityService identityService, IAuthService authService) | |||
| public static async Task PutData(HttpClient client, | |||
| string url, | |||
| string userId, | |||
| IIdentityService identityService, | |||
| IAuthService authService) | |||
| { | |||
| try | |||
| { | |||
| var tokenMessage = await identityService.GetTokenByIdAsync(new GrpcShared.DTO.Db.DbRequestMessage { Id = userId }); | |||
| var tokenMessage = await identityService.GetTokenByIdAsync(new DbRequestMessage { Id = userId }); | |||
| //add header | |||
| client.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Bearer " + tokenMessage.Token); | |||
| //get request | |||
| var responseMessage = await client.PutAsync(url, null); | |||
| if(responseMessage.StatusCode == System.Net.HttpStatusCode.Unauthorized) | |||
| if (responseMessage.StatusCode == System.Net.HttpStatusCode.Unauthorized) | |||
| { | |||
| string newToken = await SpotifyHelper.TryRefreshToken(authService, tokenMessage, identityService); | |||
| string? newToken = await TryRefreshToken(authService, tokenMessage, identityService); | |||
| if (newToken != null) | |||
| { | |||
| client.DefaultRequestHeaders.Remove(HeaderNames.Authorization); | |||
| client.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Bearer " + newToken); | |||
| responseMessage = await client.PutAsync(url, null); | |||
| } | |||
| } | |||
| } | |||
| @@ -95,5 +104,24 @@ namespace SpotifyService.HttpUtils | |||
| } | |||
| public static async Task<string?> TryRefreshToken( | |||
| IAuthService authService, | |||
| UserResponse user, | |||
| IIdentityService identityService) | |||
| { | |||
| var refreshResponse = await authService.RefreshAccessToken(user); | |||
| if (refreshResponse.AccessToken != null) | |||
| { | |||
| await identityService.UpdateTokenAsync(new UserResponse | |||
| { | |||
| Id = user.Id, | |||
| Token = refreshResponse.AccessToken, | |||
| RefreshToken = user.RefreshToken | |||
| }); | |||
| return refreshResponse.AccessToken; | |||
| } | |||
| else return null; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,30 +0,0 @@ | |||
| using GrpcShared.DTO; | |||
| using GrpcShared.DTO.Db; | |||
| using GrpcShared.Interfaces; | |||
| using NemAnBlazor.Services.Interfaces; | |||
| namespace SpotifyService | |||
| { | |||
| public static class SpotifyHelper | |||
| { | |||
| public static async Task<string?> TryRefreshToken | |||
| (IAuthService authService, | |||
| UserResponse user, | |||
| IIdentityService identityService) | |||
| { | |||
| var refreshResponse = await authService.RefreshAccessToken(user); | |||
| if (refreshResponse.AccessToken != null) | |||
| { | |||
| await identityService.UpdateTokenAsync(new UserResponse | |||
| { | |||
| Id = user.Id, | |||
| Token = refreshResponse.AccessToken, | |||
| RefreshToken = user.RefreshToken | |||
| }); | |||
| return refreshResponse.AccessToken; | |||
| } | |||
| else return null; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,5 +1,6 @@ | |||
| //using IdentityProvider.Protos.AuthService; | |||
| using Blazored.LocalStorage; | |||
| using Grpc.Core; | |||
| using Grpc.Net.Client; | |||
| using GrpcShared; | |||
| using GrpcShared.DTO; | |||
| @@ -47,21 +48,29 @@ namespace SpotifyService.Services | |||
| //AUTHORIZATION HEADER | |||
| http.DefaultRequestHeaders.Add(HeaderNames.Authorization, "Basic " + Convert.ToBase64String(contentType)); | |||
| ////ACCEPT HEADER | |||
| //http.DefaultRequestHeaders.Accept.Add( | |||
| // new MediaTypeWithQualityHeaderValue("application/json")); | |||
| //BODY PARAMS | |||
| var requestBody = new Dictionary<string, string>(); | |||
| requestBody["grant_type"] = tokenRequest.GrantType; | |||
| requestBody["code"] = tokenRequest.Code!; | |||
| requestBody["redirect_uri"] = tokenRequest.RedirectUri!; | |||
| //REQUEST | |||
| var response = await http.PostAsync(url, new FormUrlEncodedContent(requestBody)); | |||
| try | |||
| { | |||
| //REQUEST | |||
| var response = await http.PostAsync(url, new FormUrlEncodedContent(requestBody)); | |||
| var contents = JsonConvert.DeserializeObject<TokenResponse>(await response.Content.ReadAsStringAsync())!; | |||
| return contents; | |||
| } | |||
| catch (RpcException e) | |||
| { | |||
| if (e.StatusCode == StatusCode.Cancelled) | |||
| { | |||
| return new TokenResponse(); | |||
| } | |||
| throw; | |||
| } | |||
| var contents = JsonConvert.DeserializeObject<TokenResponse>(await response.Content.ReadAsStringAsync()); | |||
| return contents; | |||
| } | |||
| @@ -80,7 +89,7 @@ namespace SpotifyService.Services | |||
| public async Task<UserInfoResponse> GetUserInfo(UserResponse tokenM) | |||
| { | |||
| // expired token example "BQBMgFm6jnFNWWeZEMGIRP_f-ENPid7Kw8JubAyuWAe4JK0S1DPFGlaAdZ_Fey6ePkCnz8-cqC0oyRmrciWUy5ISUTQKDe8PTQn4iBRMYCgM0n4GnS1xAErHJcm4Vpu2TAngk-4vQUOfTQRcedNTfCaHKP4uFJgTlTI7JHGrtB-_EZLnFcZ2OQe31oFQIJ1wM3ZtvwnN" | |||
| var http = _httpClientFactory.CreateClient("HttpClient"); | |||
| http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenM.Token!); | |||
| @@ -89,7 +98,7 @@ namespace SpotifyService.Services | |||
| //make this a method in http utils | |||
| if (response.StatusCode == HttpStatusCode.Unauthorized) | |||
| { | |||
| //refresh the token | |||
| var refreshResponse = await RefreshAccessToken(tokenM); | |||
| @@ -97,12 +106,11 @@ namespace SpotifyService.Services | |||
| http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", refreshResponse.AccessToken); | |||
| response = await http.GetAsync("me"); | |||
| } | |||
| //var headerError = response.Headers.WwwAuthenticate.; | |||
| var userInfo = JsonConvert.DeserializeObject<UserInfoResponse>(await response.Content.ReadAsStringAsync())!; | |||
| userInfo.ResponseMsg = response.StatusCode; | |||
| return userInfo; | |||
| } | |||
| @@ -111,6 +119,7 @@ namespace SpotifyService.Services | |||
| { | |||
| var client = _httpClientFactory.CreateClient("HttpClient"); | |||
| client.BaseAddress = new Uri("https://accounts.spotify.com/api/token"); | |||
| //BODY PARAMS | |||
| var requestBody = new Dictionary<string, string>(); | |||
| requestBody["refresh_token"] = tokenM.RefreshToken!; | |||
| @@ -124,12 +133,7 @@ namespace SpotifyService.Services | |||
| //REQUEST | |||
| var response = await client.PostAsync("https://accounts.spotify.com/api/token", new FormUrlEncodedContent(requestBody)); | |||
| if (response.StatusCode == HttpStatusCode.Unauthorized) | |||
| { | |||
| //delete tokens from localstorage | |||
| //redirect to login | |||
| } | |||
| var contents = JsonConvert.DeserializeObject<RefreshTokenResponse>(await response.Content.ReadAsStringAsync())!; | |||
| return contents; | |||
| } | |||
| @@ -26,7 +26,12 @@ namespace SpotifyService.Services | |||
| { | |||
| string url = "me/player/currently-playing"; | |||
| var response = await HttpUtils<CurrentTrackResponse>.GetData(_httpClientFactory, url, message.UserId, _identityService, _authService); | |||
| var response = await HttpUtils<CurrentTrackResponse> | |||
| .GetData(_httpClientFactory, | |||
| url, | |||
| message.UserId!, | |||
| _identityService, | |||
| _authService); | |||
| return response; | |||
| @@ -44,7 +49,12 @@ namespace SpotifyService.Services | |||
| if (request.Limit == null && request.Offset != null) url += $"?offset={request.Offset}"; | |||
| else url += request.Offset == null ? "" : $"&offset={request.Offset}"; | |||
| return await HttpUtils<TopItemResponse>.GetData(_httpClientFactory, url, request.UserId!, _identityService, _authService); | |||
| return await HttpUtils<TopItemResponse> | |||
| .GetData(_httpClientFactory, | |||
| url, | |||
| request.UserId!, | |||
| _identityService, | |||
| _authService); | |||
| } | |||
| } | |||
| @@ -36,7 +36,12 @@ namespace SpotifyService.Services | |||
| string url = $"search?q={request.Query}&type={request.Type}"; | |||
| return await HttpUtils.HttpUtils<SearchResponse>.GetData(_httpClientFactory, url, request.UserId!, _identityService, _authService); | |||
| return await HttpUtils.HttpUtils<SearchResponse> | |||
| .GetData(_httpClientFactory, | |||
| url, | |||
| request.UserId!, | |||
| _identityService, | |||
| _authService); | |||
| } | |||
| @@ -44,7 +49,12 @@ namespace SpotifyService.Services | |||
| { | |||
| string url = $"audio-features/{request.Id}"; | |||
| return await HttpUtils.HttpUtils<SingleTrackResponse>.GetData(_httpClientFactory, url, request.UserId!, _identityService,_authService); | |||
| return await HttpUtils.HttpUtils<SingleTrackResponse> | |||
| .GetData(_httpClientFactory, | |||
| url, | |||
| request.UserId!, | |||
| _identityService, | |||
| _authService); | |||
| } | |||
| public async Task<MultipleTrackResponse> ListMultipleTrackAsync(MultipleTrackRequest request) | |||
| { | |||
| @@ -55,7 +65,12 @@ namespace SpotifyService.Services | |||
| var query = UriUtil(param); | |||
| string url = $"audio-features{query}"; | |||
| return await HttpUtils.HttpUtils<MultipleTrackResponse>.GetData(_httpClientFactory, url, request.UserId, _identityService, _authService); | |||
| return await HttpUtils.HttpUtils<MultipleTrackResponse> | |||
| .GetData(_httpClientFactory, | |||
| url, | |||
| request.UserId!, | |||
| _identityService, | |||
| _authService); | |||
| } | |||
| public async Task SaveTracks(SaveTracksRequest request) | |||
| { | |||
| @@ -68,7 +83,12 @@ namespace SpotifyService.Services | |||
| string url = $"me/tracks/{query}"; | |||
| //the response type has nothing to do with the method, it's there so that the method can be called | |||
| await HttpUtils.HttpUtils<StatusCodeMessage>.PutData(client, url, request.UserId!, _identityService, _authService); | |||
| await HttpUtils.HttpUtils<StatusCodeMessage> | |||
| .PutData(client, | |||
| url, | |||
| request.UserId!, | |||
| _identityService, | |||
| _authService); | |||
| } | |||
| public static string UriUtil(Dictionary<string, List<string>> param) | |||
| @@ -97,7 +117,12 @@ namespace SpotifyService.Services | |||
| string url = $"tracks/{request.TrackID}"; | |||
| return await HttpUtils.HttpUtils<TrackResponse>.GetData(_httpClientFactory, url, request.UserId!, _identityService, _authService); | |||
| return await HttpUtils.HttpUtils<TrackResponse> | |||
| .GetData(_httpClientFactory, | |||
| url, | |||
| request.UserId!, | |||
| _identityService, | |||
| _authService); | |||
| } | |||
| } | |||
| } | |||