diff --git a/GradDemo.Api/Controllers/AuthController.cs b/GradDemo.Api/Controllers/AuthController.cs index 1738499..1fcf8fe 100644 --- a/GradDemo.Api/Controllers/AuthController.cs +++ b/GradDemo.Api/Controllers/AuthController.cs @@ -70,6 +70,27 @@ public async Task> RegisterUser() ClientSecret = password }; } + [HttpPost("register/set/currency/{currency}")] + public async Task> RegisterUser(string currency) + { + string password = GenerateRandomClientSecret(); + string username = GenerateRandomClientId(); + + var currentUser = await _userManager.CreateAsync(new Device() + { + UserName = username, + Email = $"{username}@grademoapi.co.za", + AccessFailedCount = 0, + EmailConfirmed = true, + currency = currency + }, password); + + return new DeviceCredentials + { + ClientId = username, + ClientSecret = password + }; + } private string GenerateRandomClientId() { diff --git a/GradDemo.Api/Controllers/CryptoController.cs b/GradDemo.Api/Controllers/CryptoController.cs index cdbca2f..32918d6 100644 --- a/GradDemo.Api/Controllers/CryptoController.cs +++ b/GradDemo.Api/Controllers/CryptoController.cs @@ -4,13 +4,11 @@ using System.Linq; using System.Threading.Tasks; using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading.Tasks; using GradDemo.Api.Models; -using Newtonsoft.Json; -using GradDemo.Api.Models.CoinGecko; using GradDemo.Api.Providers; +using Microsoft.AspNetCore.Identity; +using GradDemo.Api.Entities; +using Microsoft.AspNetCore.Authorization; // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 @@ -21,19 +19,56 @@ namespace GradDemo.Api.Controllers public class CryptoController : ControllerBase { private readonly CoinGeckoProvider _coinGeckoProvider; - - public CryptoController(CoinGeckoProvider coinProv) + private readonly UserManager _userManager; + private readonly ApplicationDbContext _context; + public CryptoController(CoinGeckoProvider coinProv, UserManager userManager,ApplicationDbContext context) { _coinGeckoProvider = coinProv; + _userManager = userManager; + _context = context; } - [HttpGet("value/for/{coinId}/currency/{currency}")] - public async Task> GetCoin(string coinId, string currency) + [HttpGet("value/for/bitcoin/currency/{currency}")] + public async Task> GetCoin(string currency) { var result = new CryptoCoinResponse(); + var res = await _coinGeckoProvider.GetValueForCoin(currency); - var res = await _coinGeckoProvider.GetValueForCoin(coinId, currency); + if (res.HasValue) + { + return Response.Successful(new CryptoCoinResponse() + { + Value = res.Value + }); + } + return Response.Error("Something went wrong"); + } + [HttpGet("currencies/")] + public async Task>> GetCurrencies() + { + + var res = await _coinGeckoProvider.GetCurrencies(); + + if (res.Count>0) + { + return Response>.Successful(res); + } + + return Response>.Error("Something went wrong"); + } + [Authorize] + [HttpGet("custom/response/")] + public async Task> GetCoinCustom() + { + var user = await _userManager.GetUserAsync(User); + await _context.SaveChangesAsync(); + string currency = user.currency; + if (currency == null) + { + currency = "usd"; + } + var res = await _coinGeckoProvider.GetValueForCoin($"{currency}"); if (res.HasValue) { return Response.Successful(new CryptoCoinResponse() diff --git a/GradDemo.Api/Entities/Device.cs b/GradDemo.Api/Entities/Device.cs index ea06add..13554c9 100644 --- a/GradDemo.Api/Entities/Device.cs +++ b/GradDemo.Api/Entities/Device.cs @@ -8,6 +8,8 @@ namespace GradDemo.Api.Entities { public class Device : IdentityUser { - public string ShirtSize { get; set; } + internal string name; + + public string currency { get; set; } } } diff --git a/GradDemo.Api/GradDemo.Api.csproj b/GradDemo.Api/GradDemo.Api.csproj index 037b56a..c323ec7 100644 --- a/GradDemo.Api/GradDemo.Api.csproj +++ b/GradDemo.Api/GradDemo.Api.csproj @@ -14,4 +14,8 @@ + + + + diff --git a/GradDemo.Api/Migrations/20210126141655_crypto.Designer.cs b/GradDemo.Api/Migrations/20210126141655_crypto.Designer.cs new file mode 100644 index 0000000..0b8b569 --- /dev/null +++ b/GradDemo.Api/Migrations/20210126141655_crypto.Designer.cs @@ -0,0 +1,300 @@ +// +using System; +using GradDemo.Api.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace GradDemo.Api.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20210126141655_crypto")] + partial class crypto + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .UseIdentityColumns() + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.2"); + + modelBuilder.Entity("GradDemo.Api.Entities.Contact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .UseIdentityColumn(); + + b.Property("ContactNumber") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("LastName") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Contacts"); + }); + + modelBuilder.Entity("GradDemo.Api.Entities.Device", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("currency") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .UseIdentityColumn(); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .UseIdentityColumn(); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("GradDemo.Api.Entities.Device", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("GradDemo.Api.Entities.Device", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GradDemo.Api.Entities.Device", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("GradDemo.Api.Entities.Device", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/GradDemo.Api/Migrations/20210126141655_crypto.cs b/GradDemo.Api/Migrations/20210126141655_crypto.cs new file mode 100644 index 0000000..9a43feb --- /dev/null +++ b/GradDemo.Api/Migrations/20210126141655_crypto.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace GradDemo.Api.Migrations +{ + public partial class crypto : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "ShirtSize", + table: "AspNetUsers", + newName: "currency"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "currency", + table: "AspNetUsers", + newName: "ShirtSize"); + } + } +} diff --git a/GradDemo.Api/Migrations/ApplicationDbContextModelSnapshot.cs b/GradDemo.Api/Migrations/ApplicationDbContextModelSnapshot.cs index 3f868a0..534aa6b 100644 --- a/GradDemo.Api/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/GradDemo.Api/Migrations/ApplicationDbContextModelSnapshot.cs @@ -88,9 +88,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("SecurityStamp") .HasColumnType("nvarchar(max)"); - b.Property("ShirtSize") - .HasColumnType("nvarchar(max)"); - b.Property("TwoFactorEnabled") .HasColumnType("bit"); @@ -98,6 +95,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasMaxLength(256) .HasColumnType("nvarchar(256)"); + b.Property("currency") + .HasColumnType("nvarchar(max)"); + b.HasKey("Id"); b.HasIndex("NormalizedEmail") diff --git a/GradDemo.Api/Models/CoinGecko/CoinPrice.cs b/GradDemo.Api/Models/CoinGecko/CoinPrice.cs deleted file mode 100644 index d443130..0000000 --- a/GradDemo.Api/Models/CoinGecko/CoinPrice.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace GradDemo.Api.Models.CoinGecko -{ - public class CoinPrice - { - public Bitcoin bitcoin { get; set; } - } - - public class Bitcoin - { - public int zar { get; set; } - public int usd { get; set; } - } -} diff --git a/GradDemo.Api/Providers/CoinGeckoProvider.cs b/GradDemo.Api/Providers/CoinGeckoProvider.cs index 7885a9b..2bee8b6 100644 --- a/GradDemo.Api/Providers/CoinGeckoProvider.cs +++ b/GradDemo.Api/Providers/CoinGeckoProvider.cs @@ -1,4 +1,5 @@ -using GradDemo.Api.Models.CoinGecko; +using GradDemo.Api.Entities; +using Microsoft.AspNetCore.Identity; using Newtonsoft.Json; using System; using System.Collections.Generic; @@ -11,34 +12,49 @@ namespace GradDemo.Api.Providers public class CoinGeckoProvider { static HttpClient client = new HttpClient(); + string currUrl; + + List currencies = new List(); - public CoinGeckoProvider(string baseUrl) + public CoinGeckoProvider(string baseUrl,string currenciesurl) { client.BaseAddress = new Uri(baseUrl); + currUrl = currenciesurl; } - - public async Task GetValueForCoin(string coinId, string currency) + public async Task> GetCurrencies() { - double? resultValue = null; - - string url = $"api/v3/simple/price?ids={coinId}&vs_currencies={currency}"; - HttpResponseMessage response = await client.GetAsync(url); + HttpResponseMessage response = await client.GetAsync(currUrl); + List curr = new List(); if (response.IsSuccessStatusCode) { string res = await response.Content.ReadAsStringAsync(); - - var coinGeckoResult = JsonConvert.DeserializeObject(res); - - if (currency.Equals("zar", StringComparison.InvariantCultureIgnoreCase)) + string[] splitter = res.Split("\""); + foreach (var item in splitter) { - resultValue = coinGeckoResult.bitcoin.zar; + if (item!= "," && item!= "]" && item!="[") + { + curr.Add(item.Trim()); + } } - else if (currency.Equals("usd", StringComparison.InvariantCultureIgnoreCase)) + } + return curr; + } + public async Task GetValueForCoin(string currency) + { + currencies = await GetCurrencies(); + string url = $"api/v3/simple/price?ids=bitcoin&vs_currencies={currency}"; + HttpResponseMessage response = await client.GetAsync(url); + if (response.IsSuccessStatusCode) + { + string res = await response.Content.ReadAsStringAsync(); + string[] splitter = res.Split(":"); + double? val = double.Parse(splitter[2].Substring(0, splitter[2].Length-2)); + if (val == null) { - resultValue = coinGeckoResult.bitcoin.usd; + return null; } - return resultValue; + return val; } return null; diff --git a/GradDemo.Api/Startup.cs b/GradDemo.Api/Startup.cs index a391b6a..8d2a01c 100644 --- a/GradDemo.Api/Startup.cs +++ b/GradDemo.Api/Startup.cs @@ -105,10 +105,9 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(x => new CoinGeckoProvider( - Configuration.GetValue("CoinGecko:Url") + Configuration.GetValue("CoinGecko:Url"), Configuration.GetValue("Currencies:Url") ) ); - } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/GradDemo.Api/appsettings.json b/GradDemo.Api/appsettings.json index 3cb0ada..c948681 100644 --- a/GradDemo.Api/appsettings.json +++ b/GradDemo.Api/appsettings.json @@ -12,5 +12,8 @@ }, "CoinGecko": { "Url": "https://api.coingecko.com" + }, + "Currencies": { + "Url": "https://api.coingecko.com/api/v3/simple/supported_vs_currencies" } } diff --git a/GradDemo.Tests/UnitTest1.cs b/GradDemo.Tests/UnitTest1.cs index 61af793..09214b6 100644 --- a/GradDemo.Tests/UnitTest1.cs +++ b/GradDemo.Tests/UnitTest1.cs @@ -2,7 +2,6 @@ using GradDemo.Api.Entities; using GradDemo.Api.Models; using GradDemo.Api.Models.Auth; -using GradDemo.Api.Models.CoinGecko; using NUnit.Framework; using System.Collections.Generic; using System.Net.Http;