diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/api/Controllers/AccountController.cs b/api/Controllers/AccountController.cs deleted file mode 100644 index 182fa135..00000000 --- a/api/Controllers/AccountController.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using api.Dtos.Account; -using api.Interfaces; -using api.Models; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; - -namespace api.Controllers -{ - [Route("api/account")] - [ApiController] - public class AccountController : ControllerBase - { - private readonly UserManager _userManager; - private readonly ITokenService _tokenService; - private readonly SignInManager _signinManager; - public AccountController(UserManager userManager, ITokenService tokenService, SignInManager signInManager) - { - _userManager = userManager; - _tokenService = tokenService; - _signinManager = signInManager; - } - - [HttpPost("login")] - public async Task Login(LoginDto loginDto) - { - if (!ModelState.IsValid) - return BadRequest(ModelState); - - var user = await _userManager.Users.FirstOrDefaultAsync(x => x.UserName == loginDto.Username.ToLower()); - - if (user == null) return Unauthorized("Invalid username!"); - - var result = await _signinManager.CheckPasswordSignInAsync(user, loginDto.Password, false); - - if (!result.Succeeded) return Unauthorized("Username not found and/or password incorrect"); - - return Ok( - new NewUserDto - { - UserName = user.UserName, - Email = user.Email, - Token = _tokenService.CreateToken(user) - } - ); - } - - [HttpPost("register")] - public async Task Register([FromBody] RegisterDto registerDto) - { - try - { - if (!ModelState.IsValid) - return BadRequest(ModelState); - - var appUser = new AppUser - { - UserName = registerDto.Username, - Email = registerDto.Email - }; - - var createdUser = await _userManager.CreateAsync(appUser, registerDto.Password); - - if (createdUser.Succeeded) - { - var roleResult = await _userManager.AddToRoleAsync(appUser, "User"); - if (roleResult.Succeeded) - { - return Ok( - new NewUserDto - { - UserName = appUser.UserName, - Email = appUser.Email, - Token = _tokenService.CreateToken(appUser) - } - ); - } - else - { - return StatusCode(500, roleResult.Errors); - } - } - else - { - return StatusCode(500, createdUser.Errors); - } - } - catch (Exception e) - { - return StatusCode(500, e); - } - } - } -} \ No newline at end of file diff --git a/api/Controllers/CommentController.cs b/api/Controllers/CommentController.cs deleted file mode 100644 index ad524c8f..00000000 --- a/api/Controllers/CommentController.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using api.Dtos.Comment; -using api.Extensions; -using api.Helpers; -using api.Interfaces; -using api.Mappers; -using api.Models; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; - -namespace api.Controllers -{ - [Route("api/comment")] - [ApiController] - public class CommentController : ControllerBase - { - private readonly ICommentRepository _commentRepo; - private readonly IStockRepository _stockRepo; - private readonly UserManager _userManager; - private readonly IFMPService _fmpService; - public CommentController(ICommentRepository commentRepo, - IStockRepository stockRepo, UserManager userManager, - IFMPService fmpService) - { - _commentRepo = commentRepo; - _stockRepo = stockRepo; - _userManager = userManager; - _fmpService = fmpService; - } - - [HttpGet] - [Authorize] - public async Task GetAll([FromQuery] CommentQueryObject queryObject) - { - if (!ModelState.IsValid) - return BadRequest(ModelState); - - var comments = await _commentRepo.GetAllAsync(queryObject); - - var commentDto = comments.Select(s => s.ToCommentDto()); - - return Ok(commentDto); - } - - [HttpGet("{id:int}")] - public async Task GetById([FromRoute] int id) - { - if (!ModelState.IsValid) - return BadRequest(ModelState); - - var comment = await _commentRepo.GetByIdAsync(id); - - if (comment == null) - { - return NotFound(); - } - - return Ok(comment.ToCommentDto()); - } - - [HttpPost] - [Route("{symbol:alpha}")] - public async Task Create([FromRoute] string symbol, CreateCommentDto commentDto) - { - if (!ModelState.IsValid) - return BadRequest(ModelState); - - var stock = await _stockRepo.GetBySymbolAsync(symbol); - - if (stock == null) - { - stock = await _fmpService.FindStockBySymbolAsync(symbol); - if (stock == null) - { - return BadRequest("Stock does not exists"); - } - else - { - await _stockRepo.CreateAsync(stock); - } - } - - var username = User.GetUsername(); - var appUser = await _userManager.FindByNameAsync(username); - - var commentModel = commentDto.ToCommentFromCreate(stock.Id); - commentModel.AppUserId = appUser.Id; - await _commentRepo.CreateAsync(commentModel); - return CreatedAtAction(nameof(GetById), new { id = commentModel.Id }, commentModel.ToCommentDto()); - } - - [HttpPut] - [Route("{id:int}")] - public async Task Update([FromRoute] int id, [FromBody] UpdateCommentRequestDto updateDto) - { - if (!ModelState.IsValid) - return BadRequest(ModelState); - - var comment = await _commentRepo.UpdateAsync(id, updateDto.ToCommentFromUpdate(id)); - - if (comment == null) - { - return NotFound("Comment not found"); - } - - return Ok(comment.ToCommentDto()); - } - - [HttpDelete] - [Route("{id:int}")] - public async Task Delete([FromRoute] int id) - { - if (!ModelState.IsValid) - return BadRequest(ModelState); - - var commentModel = await _commentRepo.DeleteAsync(id); - - if (commentModel == null) - { - return NotFound("Comment does not exist"); - } - - return Ok(commentModel); - } - } -} \ No newline at end of file diff --git a/api/Controllers/PortfolioController.cs b/api/Controllers/PortfolioController.cs deleted file mode 100644 index 57e02fff..00000000 --- a/api/Controllers/PortfolioController.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using api.Extensions; -using api.Interfaces; -using api.Models; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; - -namespace api.Controllers -{ - [Route("api/portfolio")] - [ApiController] - public class PortfolioController : ControllerBase - { - private readonly UserManager _userManager; - private readonly IStockRepository _stockRepo; - private readonly IPortfolioRepository _portfolioRepo; - private readonly IFMPService _fmpService; - public PortfolioController(UserManager userManager, - IStockRepository stockRepo, IPortfolioRepository portfolioRepo, - IFMPService fmpService) - { - _userManager = userManager; - _stockRepo = stockRepo; - _portfolioRepo = portfolioRepo; - _fmpService = fmpService; - } - - [HttpGet] - [Authorize] - public async Task GetUserPortfolio() - { - var username = User.GetUsername(); - var appUser = await _userManager.FindByNameAsync(username); - var userPortfolio = await _portfolioRepo.GetUserPortfolio(appUser); - return Ok(userPortfolio); - } - - [HttpPost] - [Authorize] - public async Task AddPortfolio(string symbol) - { - var username = User.GetUsername(); - var appUser = await _userManager.FindByNameAsync(username); - var stock = await _stockRepo.GetBySymbolAsync(symbol); - - if (stock == null) - { - stock = await _fmpService.FindStockBySymbolAsync(symbol); - if (stock == null) - { - return BadRequest("Stock does not exists"); - } - else - { - await _stockRepo.CreateAsync(stock); - } - } - - if (stock == null) return BadRequest("Stock not found"); - - var userPortfolio = await _portfolioRepo.GetUserPortfolio(appUser); - - if (userPortfolio.Any(e => e.Symbol.ToLower() == symbol.ToLower())) return BadRequest("Cannot add same stock to portfolio"); - - var portfolioModel = new Portfolio - { - StockId = stock.Id, - AppUserId = appUser.Id - }; - - await _portfolioRepo.CreateAsync(portfolioModel); - - if (portfolioModel == null) - { - return StatusCode(500, "Could not create"); - } - else - { - return Created(); - } - } - - [HttpDelete] - [Authorize] - public async Task DeletePortfolio(string symbol) - { - var username = User.GetUsername(); - var appUser = await _userManager.FindByNameAsync(username); - - var userPortfolio = await _portfolioRepo.GetUserPortfolio(appUser); - - var filteredStock = userPortfolio.Where(s => s.Symbol.ToLower() == symbol.ToLower()).ToList(); - - if (filteredStock.Count() == 1) - { - await _portfolioRepo.DeletePortfolio(appUser, symbol); - } - else - { - return BadRequest("Stock not in your portfolio"); - } - - return Ok(); - } - - } -} \ No newline at end of file diff --git a/api/Controllers/StockController.cs b/api/Controllers/StockController.cs index eed8ce86..c10ae5e5 100644 --- a/api/Controllers/StockController.cs +++ b/api/Controllers/StockController.cs @@ -1,15 +1,8 @@ -using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; using api.Data; -using api.Dtos.Stock; -using api.Helpers; -using api.Interfaces; using api.Mappers; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; +using api.Dtos.Stock; namespace api.Controllers { @@ -18,34 +11,24 @@ namespace api.Controllers public class StockController : ControllerBase { private readonly ApplicationDBContext _context; - private readonly IStockRepository _stockRepo; - public StockController(ApplicationDBContext context, IStockRepository stockRepo) + + public StockController(ApplicationDBContext context) { - _stockRepo = stockRepo; _context = context; } [HttpGet] - [Authorize] - public async Task GetAll([FromQuery] QueryObject query) + public IActionResult GetAll() { - if (!ModelState.IsValid) - return BadRequest(ModelState); - - var stocks = await _stockRepo.GetAllAsync(query); - - var stockDto = stocks.Select(s => s.ToStockDto()).ToList(); - - return Ok(stockDto); + var stocks = _context.Stock.ToList() + .Select(s => s.ToStockDto()); + return Ok(stocks); } - [HttpGet("{id:int}")] - public async Task GetById([FromRoute] int id) + [HttpGet("{id}")] + public IActionResult GetById([FromRoute] int id) { - if (!ModelState.IsValid) - return BadRequest(ModelState); - - var stock = await _stockRepo.GetByIdAsync(id); + var stock = _context.Stock.Find(id); if (stock == null) { @@ -53,54 +36,41 @@ public async Task GetById([FromRoute] int id) } return Ok(stock.ToStockDto()); + + } [HttpPost] - public async Task Create([FromBody] CreateStockRequestDto stockDto) - { - if (!ModelState.IsValid) - return BadRequest(ModelState); - + public IActionResult Create([FromBody] CreateStockRequestDto stockDto){ var stockModel = stockDto.ToStockFromCreateDTO(); + _context.Stock.Add(stockModel); + _context.SaveChanges(); + return CreatedAtAction(nameof(GetById),new {id=stockModel.Id},stockModel.ToStockDto()); - await _stockRepo.CreateAsync(stockModel); - return CreatedAtAction(nameof(GetById), new { id = stockModel.Id }, stockModel.ToStockDto()); } - [HttpPut] - [Route("{id:int}")] - public async Task Update([FromRoute] int id, [FromBody] UpdateStockRequestDto updateDto) - { - if (!ModelState.IsValid) - return BadRequest(ModelState); - - var stockModel = await _stockRepo.UpdateAsync(id, updateDto); - - if (stockModel == null) - { + [Route("{id}")] + public IActionResult Update([FromRoute] int id,[FromBody] UpdateStockRequestDto updateDto ){ + var stockModel=_context.Stock.FirstOrDefault(x => x.Id==id); + if(stockModel==null){ return NotFound(); } - return Ok(stockModel.ToStockDto()); - } + stockModel.Symbol=updateDto.Symbol; + stockModel.CompanyName=updateDto.CompanyName; + stockModel.Purchase=updateDto.Purchase; + stockModel.Lastdiv=updateDto.Lastdiv; + stockModel.Industry=updateDto.Industry; + stockModel.MarketCap=updateDto.MarketCap; - [HttpDelete] - [Route("{id:int}")] - public async Task Delete([FromRoute] int id) - { - if (!ModelState.IsValid) - return BadRequest(ModelState); + _context.SaveChanges(); - var stockModel = await _stockRepo.DeleteAsync(id); + return Ok(stockModel.ToStockDto()); - if (stockModel == null) - { - return NotFound(); - } - return NoContent(); } + } -} \ No newline at end of file +} diff --git a/api/Data/ApplicationDBContext.cs b/api/Data/ApplicationDBContext.cs index aab429f7..31c4dbe1 100644 --- a/api/Data/ApplicationDBContext.cs +++ b/api/Data/ApplicationDBContext.cs @@ -3,55 +3,19 @@ using System.Linq; using System.Threading.Tasks; using api.Models; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; namespace api.Data { - public class ApplicationDBContext : IdentityDbContext + public class ApplicationDBContext : DbContext + { public ApplicationDBContext(DbContextOptions dbContextOptions) + : base(dbContextOptions) { - public ApplicationDBContext(DbContextOptions dbContextOptions) - : base(dbContextOptions) - { - - } - - public DbSet Stocks { get; set; } - public DbSet Comments { get; set; } - public DbSet Portfolios { get; set; } - - protected override void OnModelCreating(ModelBuilder builder) - { - base.OnModelCreating(builder); - - builder.Entity(x => x.HasKey(p => new { p.AppUserId, p.StockId })); - - builder.Entity() - .HasOne(u => u.AppUser) - .WithMany(u => u.Portfolios) - .HasForeignKey(p => p.AppUserId); - - builder.Entity() - .HasOne(u => u.Stock) - .WithMany(u => u.Portfolios) - .HasForeignKey(p => p.StockId); - + + } - List roles = new List - { - new IdentityRole - { - Name = "Admin", - NormalizedName = "ADMIN" - }, - new IdentityRole - { - Name = "User", - NormalizedName = "USER" - }, - }; - builder.Entity().HasData(roles); - } + public DbSet Stock {get;set;} + public DbSet Comments {get;set;} + } } \ No newline at end of file diff --git a/api/Dtos/Account/LoginDto.cs b/api/Dtos/Account/LoginDto.cs deleted file mode 100644 index 78b3fda5..00000000 --- a/api/Dtos/Account/LoginDto.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; - -namespace api.Dtos.Account -{ - public class LoginDto - { - [Required] - public string Username { get; set; } - [Required] - public string Password { get; set; } - } -} \ No newline at end of file diff --git a/api/Dtos/Account/NewUserDto.cs b/api/Dtos/Account/NewUserDto.cs deleted file mode 100644 index 37648db9..00000000 --- a/api/Dtos/Account/NewUserDto.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace api.Dtos.Account -{ - public class NewUserDto - { - public string UserName { get; set; } - public string Email { get; set; } - public string Token { get; set; } - } -} \ No newline at end of file diff --git a/api/Dtos/Account/RegisterDto.cs b/api/Dtos/Account/RegisterDto.cs deleted file mode 100644 index 0599460b..00000000 --- a/api/Dtos/Account/RegisterDto.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; - -namespace api.Dtos.Account -{ - public class RegisterDto - { - [Required] - public string? Username { get; set; } - [Required] - [EmailAddress] - public string? Email { get; set; } - [Required] - public string? Password { get; set; } - } -} \ No newline at end of file diff --git a/api/Dtos/Comment/CommentDto.cs b/api/Dtos/Comment/CommentDto.cs deleted file mode 100644 index 48333cef..00000000 --- a/api/Dtos/Comment/CommentDto.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace api.Dtos.Comment -{ - public class CommentDto - { - public int Id { get; set; } - public string Title { get; set; } = string.Empty; - public string Content { get; set; } = string.Empty; - public DateTime CreatedOn { get; set; } = DateTime.Now; - public string CreatedBy { get; set; } = string.Empty; - public int? StockId { get; set; } - } -} \ No newline at end of file diff --git a/api/Dtos/Comment/CreateCommentDto.cs b/api/Dtos/Comment/CreateCommentDto.cs deleted file mode 100644 index 3dd6da5a..00000000 --- a/api/Dtos/Comment/CreateCommentDto.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; - -namespace api.Dtos.Comment -{ - public class CreateCommentDto - { - [Required] - [MinLength(5, ErrorMessage = "Title must be 5 characters")] - [MaxLength(280, ErrorMessage = "Title cannot be over 280 characters")] - public string Title { get; set; } = string.Empty; - [Required] - [MinLength(5, ErrorMessage = "Content must be 5 characters")] - [MaxLength(280, ErrorMessage = "Content cannot be over 280 characters")] - public string Content { get; set; } = string.Empty; - } -} \ No newline at end of file diff --git a/api/Dtos/Comment/UpdateCommentRequestDto.cs b/api/Dtos/Comment/UpdateCommentRequestDto.cs deleted file mode 100644 index 6080eb6c..00000000 --- a/api/Dtos/Comment/UpdateCommentRequestDto.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; - -namespace api.Dtos.Comment -{ - public class UpdateCommentRequestDto - { - [Required] - [MinLength(5, ErrorMessage = "Title must be 5 characters")] - [MaxLength(280, ErrorMessage = "Title cannot be over 280 characters")] - public string Title { get; set; } = string.Empty; - [Required] - [MinLength(5, ErrorMessage = "Content must be 5 characters")] - [MaxLength(280, ErrorMessage = "Content cannot be over 280 characters")] - public string Content { get; set; } = string.Empty; - } -} \ No newline at end of file diff --git a/api/Dtos/Stock/CreateStockRequestDto.cs b/api/Dtos/Stock/CreateStockRequestDto.cs index 14ae7d76..f6554a1f 100644 --- a/api/Dtos/Stock/CreateStockRequestDto.cs +++ b/api/Dtos/Stock/CreateStockRequestDto.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; @@ -8,22 +7,17 @@ namespace api.Dtos.Stock { public class CreateStockRequestDto { - [Required] - [MaxLength(10, ErrorMessage = "Symbol cannot be over 10 over characters")] - public string Symbol { get; set; } = string.Empty; - [Required] - [MaxLength(10, ErrorMessage = "Company Name cannot be over 10 over characters")] - public string CompanyName { get; set; } = string.Empty; - [Required] - [Range(1, 1000000000)] + public string Symbol { get; set; }=string.Empty; + public string CompanyName { get; set; }=string.Empty; + + public decimal Purchase { get; set; } - [Required] - [Range(0.001, 100)] - public decimal LastDiv { get; set; } - [Required] - [MaxLength(10, ErrorMessage = "Industry cannot be over 10 characters")] - public string Industry { get; set; } = string.Empty; - [Range(1, 5000000000)] + + + + public decimal Lastdiv { get; set; } + public string Industry { get; set; }=string.Empty; public long MarketCap { get; set; } + } } \ No newline at end of file diff --git a/api/Dtos/Stock/FMPStock.cs b/api/Dtos/Stock/FMPStock.cs deleted file mode 100644 index 2cc95547..00000000 --- a/api/Dtos/Stock/FMPStock.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace api.Dtos.Stock -{ - public class FMPStock - { - public string symbol { get; set; } - public double price { get; set; } - public double beta { get; set; } - public int volAvg { get; set; } - public long mktCap { get; set; } - public double lastDiv { get; set; } - public string range { get; set; } - public double changes { get; set; } - public string companyName { get; set; } - public string currency { get; set; } - public string cik { get; set; } - public string isin { get; set; } - public string cusip { get; set; } - public string exchange { get; set; } - public string exchangeShortName { get; set; } - public string industry { get; set; } - public string website { get; set; } - public string description { get; set; } - public string ceo { get; set; } - public string sector { get; set; } - public string country { get; set; } - public string fullTimeEmployees { get; set; } - public string phone { get; set; } - public string address { get; set; } - public string city { get; set; } - public string state { get; set; } - public string zip { get; set; } - public double dcfDiff { get; set; } - public double dcf { get; set; } - public string image { get; set; } - public string ipoDate { get; set; } - public bool defaultImage { get; set; } - public bool isEtf { get; set; } - public bool isActivelyTrading { get; set; } - public bool isAdr { get; set; } - public bool isFund { get; set; } - } -} \ No newline at end of file diff --git a/api/Dtos/Stock/StockDto.cs b/api/Dtos/Stock/StockDto.cs index f525b8d6..23639b66 100644 --- a/api/Dtos/Stock/StockDto.cs +++ b/api/Dtos/Stock/StockDto.cs @@ -2,19 +2,25 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using api.Dtos.Comment; namespace api.Dtos.Stock { public class StockDto { - public int Id { get; set; } - public string Symbol { get; set; } = string.Empty; - public string CompanyName { get; set; } = string.Empty; + public int Id { get; set; } + public string Symbol { get; set; }=string.Empty; + public string CompanyName { get; set; }=string.Empty; + + public decimal Purchase { get; set; } - public decimal LastDiv { get; set; } - public string Industry { get; set; } = string.Empty; + + + + public decimal Lastdiv { get; set; } + public string Industry { get; set; }=string.Empty; public long MarketCap { get; set; } - public List Comments { get; set; } + + + } } \ No newline at end of file diff --git a/api/Dtos/Stock/UpdateStockRequestDto.cs b/api/Dtos/Stock/UpdateStockRequestDto.cs index a14421d5..a15dcc7e 100644 --- a/api/Dtos/Stock/UpdateStockRequestDto.cs +++ b/api/Dtos/Stock/UpdateStockRequestDto.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; @@ -8,22 +7,20 @@ namespace api.Dtos.Stock { public class UpdateStockRequestDto { - [Required] - [MaxLength(10, ErrorMessage = "Symbol cannot be over 10 over characters")] - public string Symbol { get; set; } = string.Empty; - [Required] - [MaxLength(10, ErrorMessage = "Company Name cannot be over 10 over characters")] - public string CompanyName { get; set; } = string.Empty; - [Required] - [Range(1, 1000000000)] + + public int Id { get; set; } + public string Symbol { get; set; }=string.Empty; + public string CompanyName { get; set; }=string.Empty; + + public decimal Purchase { get; set; } - [Required] - [Range(0.001, 100)] - public decimal LastDiv { get; set; } - [Required] - [MaxLength(10, ErrorMessage = "Industry cannot be over 10 characters")] - public string Industry { get; set; } = string.Empty; - [Range(1, 5000000000)] + + + + public decimal Lastdiv { get; set; } + public string Industry { get; set; }=string.Empty; public long MarketCap { get; set; } + + } } \ No newline at end of file diff --git a/api/Extensions/ClaimsExtensions.cs b/api/Extensions/ClaimsExtensions.cs deleted file mode 100644 index eb895f34..00000000 --- a/api/Extensions/ClaimsExtensions.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; - -namespace api.Extensions -{ - public static class ClaimsExtensions - { - public static string GetUsername(this ClaimsPrincipal user) - { - return user.Claims.SingleOrDefault(x => x.Type.Equals("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname")).Value; - } - } -} \ No newline at end of file diff --git a/api/Helpers/CommentQueryObject.cs b/api/Helpers/CommentQueryObject.cs deleted file mode 100644 index acbc3786..00000000 --- a/api/Helpers/CommentQueryObject.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace api.Helpers -{ - public class CommentQueryObject - { - public string Symbol { get; set; } - public bool IsDecsending { get; set; } = true; - } -} \ No newline at end of file diff --git a/api/Helpers/QueryObject.cs b/api/Helpers/QueryObject.cs deleted file mode 100644 index 3e292508..00000000 --- a/api/Helpers/QueryObject.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace api.Helpers -{ - public class QueryObject - { - public string? Symbol { get; set; } = null; - public string? CompanyName { get; set; } = null; - public string? SortBy { get; set; } = null; - public bool IsDecsending { get; set; } = false; - public int PageNumber { get; set; } = 1; - public int PageSize { get; set; } = 20; - } -} \ No newline at end of file diff --git a/api/Interfaces/ICommentRepository.cs b/api/Interfaces/ICommentRepository.cs deleted file mode 100644 index c64179a1..00000000 --- a/api/Interfaces/ICommentRepository.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using api.Helpers; -using api.Models; - -namespace api.Interfaces -{ - public interface ICommentRepository - { - Task> GetAllAsync(CommentQueryObject queryObject); - Task GetByIdAsync(int id); - Task CreateAsync(Comment commentModel); - Task UpdateAsync(int id, Comment commentModel); - Task DeleteAsync(int id); - } -} \ No newline at end of file diff --git a/api/Interfaces/IFMPService.cs b/api/Interfaces/IFMPService.cs deleted file mode 100644 index 159d0756..00000000 --- a/api/Interfaces/IFMPService.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using api.Models; - -namespace api.Interfaces -{ - public interface IFMPService - { - Task FindStockBySymbolAsync(string symbol); - } -} \ No newline at end of file diff --git a/api/Interfaces/IPortfolioRepository.cs b/api/Interfaces/IPortfolioRepository.cs deleted file mode 100644 index 31fb4f09..00000000 --- a/api/Interfaces/IPortfolioRepository.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using api.Models; - -namespace api.Interfaces -{ - public interface IPortfolioRepository - { - Task> GetUserPortfolio(AppUser user); - Task CreateAsync(Portfolio portfolio); - Task DeletePortfolio(AppUser appUser, string symbol); - } -} \ No newline at end of file diff --git a/api/Interfaces/IStockRepository.cs b/api/Interfaces/IStockRepository.cs deleted file mode 100644 index 83e6667a..00000000 --- a/api/Interfaces/IStockRepository.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using api.Dtos.Stock; -using api.Helpers; -using api.Models; - -namespace api.Interfaces -{ - public interface IStockRepository - { - Task> GetAllAsync(QueryObject query); - Task GetByIdAsync(int id); - Task GetBySymbolAsync(string symbol); - Task CreateAsync(Stock stockModel); - Task UpdateAsync(int id, UpdateStockRequestDto stockDto); - Task DeleteAsync(int id); - Task StockExists(int id); - } -} \ No newline at end of file diff --git a/api/Interfaces/ITokenService.cs b/api/Interfaces/ITokenService.cs deleted file mode 100644 index dc185e4b..00000000 --- a/api/Interfaces/ITokenService.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using api.Models; - -namespace api.Interfaces -{ - public interface ITokenService - { - string CreateToken(AppUser user); - } -} \ No newline at end of file diff --git a/api/Mappers/CommentMapper.cs b/api/Mappers/CommentMapper.cs deleted file mode 100644 index 44d1b8c5..00000000 --- a/api/Mappers/CommentMapper.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using api.Dtos.Comment; -using api.Models; - -namespace api.Mappers -{ - public static class CommentMapper - { - public static CommentDto ToCommentDto(this Comment commentModel) - { - return new CommentDto - { - Id = commentModel.Id, - Title = commentModel.Title, - Content = commentModel.Content, - CreatedOn = commentModel.CreatedOn, - CreatedBy = commentModel.AppUser.UserName, - StockId = commentModel.StockId - }; - } - - public static Comment ToCommentFromCreate(this CreateCommentDto commentDto, int stockId) - { - return new Comment - { - Title = commentDto.Title, - Content = commentDto.Content, - StockId = stockId - }; - } - - public static Comment ToCommentFromUpdate(this UpdateCommentRequestDto commentDto, int stockId) - { - return new Comment - { - Title = commentDto.Title, - Content = commentDto.Content, - StockId = stockId - }; - } - - } -} \ No newline at end of file diff --git a/api/Mappers/StockMappers.cs b/api/Mappers/StockMappers.cs index e6b94b47..f7ba4fbe 100644 --- a/api/Mappers/StockMappers.cs +++ b/api/Mappers/StockMappers.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using api.Dtos.Stock; using api.Models; @@ -9,6 +6,7 @@ namespace api.Mappers { public static class StockMappers { + // Maps a Stock model to a StockDto public static StockDto ToStockDto(this Stock stockModel) { return new StockDto @@ -17,13 +15,13 @@ public static StockDto ToStockDto(this Stock stockModel) Symbol = stockModel.Symbol, CompanyName = stockModel.CompanyName, Purchase = stockModel.Purchase, - LastDiv = stockModel.LastDiv, + Lastdiv = stockModel.Lastdiv, Industry = stockModel.Industry, - MarketCap = stockModel.MarketCap, - Comments = stockModel.Comments.Select(c => c.ToCommentDto()).ToList() + MarketCap = stockModel.MarketCap }; } + // Maps a CreateStockRequestDto to a Stock model public static Stock ToStockFromCreateDTO(this CreateStockRequestDto stockDto) { return new Stock @@ -31,23 +29,10 @@ public static Stock ToStockFromCreateDTO(this CreateStockRequestDto stockDto) Symbol = stockDto.Symbol, CompanyName = stockDto.CompanyName, Purchase = stockDto.Purchase, - LastDiv = stockDto.LastDiv, + Lastdiv = stockDto.Lastdiv, Industry = stockDto.Industry, MarketCap = stockDto.MarketCap }; } - - public static Stock ToStockFromFMP(this FMPStock fmpStock) - { - return new Stock - { - Symbol = fmpStock.symbol, - CompanyName = fmpStock.companyName, - Purchase = (decimal)fmpStock.price, - LastDiv = (decimal)fmpStock.lastDiv, - Industry = fmpStock.industry, - MarketCap = fmpStock.mktCap - }; - } } -} \ No newline at end of file +} diff --git a/api/Migrations/20231228175321_Identity.Designer.cs b/api/Migrations/20231228175321_Identity.Designer.cs deleted file mode 100644 index 948a0d52..00000000 --- a/api/Migrations/20231228175321_Identity.Designer.cs +++ /dev/null @@ -1,356 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using api.Data; - -#nullable disable - -namespace api.Migrations -{ - [DbContext(typeof(ApplicationDBContext))] - [Migration("20231228175321_Identity")] - partial class Identity - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - 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", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - 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", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - 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", (string)null); - }); - - 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", (string)null); - }); - - 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", (string)null); - }); - - 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", (string)null); - }); - - modelBuilder.Entity("api.Models.AppUser", 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.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("api.Models.Comment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Content") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("CreatedOn") - .HasColumnType("datetime2"); - - b.Property("StockId") - .HasColumnType("int"); - - b.Property("Title") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("StockId"); - - b.ToTable("Comments"); - }); - - modelBuilder.Entity("api.Models.Stock", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("CompanyName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Industry") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastDiv") - .HasColumnType("decimal(18,2)"); - - b.Property("MarketCap") - .HasColumnType("bigint"); - - b.Property("Purchase") - .HasColumnType("decimal(18,2)"); - - b.Property("Symbol") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Stocks"); - }); - - 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("api.Models.AppUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("api.Models.AppUser", 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("api.Models.AppUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("api.Models.AppUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("api.Models.Comment", b => - { - b.HasOne("api.Models.Stock", "Stock") - .WithMany("Comments") - .HasForeignKey("StockId"); - - b.Navigation("Stock"); - }); - - modelBuilder.Entity("api.Models.Stock", b => - { - b.Navigation("Comments"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/api/Migrations/20231228175321_Identity.cs b/api/Migrations/20231228175321_Identity.cs deleted file mode 100644 index 4dca9007..00000000 --- a/api/Migrations/20231228175321_Identity.cs +++ /dev/null @@ -1,224 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace api.Migrations -{ - /// - public partial class Identity : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "AspNetRoles", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoles", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AspNetUsers", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), - EmailConfirmed = table.Column(type: "bit", nullable: false), - PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), - SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), - ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), - PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), - PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), - TwoFactorEnabled = table.Column(type: "bit", nullable: false), - LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), - LockoutEnabled = table.Column(type: "bit", nullable: false), - AccessFailedCount = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUsers", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AspNetRoleClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - RoleId = table.Column(type: "nvarchar(450)", nullable: false), - ClaimType = table.Column(type: "nvarchar(max)", nullable: true), - ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserClaims", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - UserId = table.Column(type: "nvarchar(450)", nullable: false), - ClaimType = table.Column(type: "nvarchar(max)", nullable: true), - ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); - table.ForeignKey( - name: "FK_AspNetUserClaims_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserLogins", - columns: table => new - { - LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), - ProviderKey = table.Column(type: "nvarchar(450)", nullable: false), - ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), - UserId = table.Column(type: "nvarchar(450)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); - table.ForeignKey( - name: "FK_AspNetUserLogins_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserRoles", - columns: table => new - { - UserId = table.Column(type: "nvarchar(450)", nullable: false), - RoleId = table.Column(type: "nvarchar(450)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetRoles_RoleId", - column: x => x.RoleId, - principalTable: "AspNetRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_AspNetUserRoles_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AspNetUserTokens", - columns: table => new - { - UserId = table.Column(type: "nvarchar(450)", nullable: false), - LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(450)", nullable: false), - Value = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); - table.ForeignKey( - name: "FK_AspNetUserTokens_AspNetUsers_UserId", - column: x => x.UserId, - principalTable: "AspNetUsers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_AspNetRoleClaims_RoleId", - table: "AspNetRoleClaims", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "RoleNameIndex", - table: "AspNetRoles", - column: "NormalizedName", - unique: true, - filter: "[NormalizedName] IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserClaims_UserId", - table: "AspNetUserClaims", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserLogins_UserId", - table: "AspNetUserLogins", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_AspNetUserRoles_RoleId", - table: "AspNetUserRoles", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "EmailIndex", - table: "AspNetUsers", - column: "NormalizedEmail"); - - migrationBuilder.CreateIndex( - name: "UserNameIndex", - table: "AspNetUsers", - column: "NormalizedUserName", - unique: true, - filter: "[NormalizedUserName] IS NOT NULL"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AspNetRoleClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserClaims"); - - migrationBuilder.DropTable( - name: "AspNetUserLogins"); - - migrationBuilder.DropTable( - name: "AspNetUserRoles"); - - migrationBuilder.DropTable( - name: "AspNetUserTokens"); - - migrationBuilder.DropTable( - name: "AspNetRoles"); - - migrationBuilder.DropTable( - name: "AspNetUsers"); - } - } -} diff --git a/api/Migrations/20231230165657_SeedRole.Designer.cs b/api/Migrations/20231230165657_SeedRole.Designer.cs deleted file mode 100644 index 283c3157..00000000 --- a/api/Migrations/20231230165657_SeedRole.Designer.cs +++ /dev/null @@ -1,370 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using api.Data; - -#nullable disable - -namespace api.Migrations -{ - [DbContext(typeof(ApplicationDBContext))] - [Migration("20231230165657_SeedRole")] - partial class SeedRole - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - 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", (string)null); - - b.HasData( - new - { - Id = "79f392bf-21e3-4e59-a899-f2a066f3884a", - Name = "Admin", - NormalizedName = "ADMIN" - }, - new - { - Id = "5849bcbd-fa3c-46ad-8ac1-00ff8cd9a6d7", - Name = "User", - NormalizedName = "USER" - }); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - 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", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - 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", (string)null); - }); - - 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", (string)null); - }); - - 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", (string)null); - }); - - 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", (string)null); - }); - - modelBuilder.Entity("api.Models.AppUser", 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.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("api.Models.Comment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Content") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("CreatedOn") - .HasColumnType("datetime2"); - - b.Property("StockId") - .HasColumnType("int"); - - b.Property("Title") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("StockId"); - - b.ToTable("Comments"); - }); - - modelBuilder.Entity("api.Models.Stock", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("CompanyName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Industry") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastDiv") - .HasColumnType("decimal(18,2)"); - - b.Property("MarketCap") - .HasColumnType("bigint"); - - b.Property("Purchase") - .HasColumnType("decimal(18,2)"); - - b.Property("Symbol") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Stocks"); - }); - - 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("api.Models.AppUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("api.Models.AppUser", 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("api.Models.AppUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("api.Models.AppUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("api.Models.Comment", b => - { - b.HasOne("api.Models.Stock", "Stock") - .WithMany("Comments") - .HasForeignKey("StockId"); - - b.Navigation("Stock"); - }); - - modelBuilder.Entity("api.Models.Stock", b => - { - b.Navigation("Comments"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/api/Migrations/20231230165657_SeedRole.cs b/api/Migrations/20231230165657_SeedRole.cs deleted file mode 100644 index 8ea2ab98..00000000 --- a/api/Migrations/20231230165657_SeedRole.cs +++ /dev/null @@ -1,58 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional - -namespace api.Migrations -{ - /// - public partial class SeedRole : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DeleteData( - table: "AspNetRoles", - keyColumn: "Id", - keyValue: "7bdc0619-6bfd-476d-804d-7add9a1f75af"); - - migrationBuilder.DeleteData( - table: "AspNetRoles", - keyColumn: "Id", - keyValue: "8811e782-4262-4abf-b967-ef2ace5505c6"); - - migrationBuilder.InsertData( - table: "AspNetRoles", - columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" }, - values: new object[,] - { - { "5849bcbd-fa3c-46ad-8ac1-00ff8cd9a6d7", null, "User", "USER" }, - { "79f392bf-21e3-4e59-a899-f2a066f3884a", null, "Admin", "ADMIN" } - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DeleteData( - table: "AspNetRoles", - keyColumn: "Id", - keyValue: "5849bcbd-fa3c-46ad-8ac1-00ff8cd9a6d7"); - - migrationBuilder.DeleteData( - table: "AspNetRoles", - keyColumn: "Id", - keyValue: "79f392bf-21e3-4e59-a899-f2a066f3884a"); - - migrationBuilder.InsertData( - table: "AspNetRoles", - columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" }, - values: new object[,] - { - { "7bdc0619-6bfd-476d-804d-7add9a1f75af", null, "User", "USER" }, - { "8811e782-4262-4abf-b967-ef2ace5505c6", null, "Admin", "ADMIN" } - }); - } - } -} diff --git a/api/Migrations/20231202125736_init.Designer.cs b/api/Migrations/20241217134339_init.Designer.cs similarity index 96% rename from api/Migrations/20231202125736_init.Designer.cs rename to api/Migrations/20241217134339_init.Designer.cs index 33723d16..cf190915 100644 --- a/api/Migrations/20231202125736_init.Designer.cs +++ b/api/Migrations/20241217134339_init.Designer.cs @@ -12,7 +12,7 @@ namespace api.Migrations { [DbContext(typeof(ApplicationDBContext))] - [Migration("20231202125736_init")] + [Migration("20241217134339_init")] partial class init { /// @@ -70,7 +70,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(max)"); - b.Property("LastDiv") + b.Property("Lastdiv") .HasColumnType("decimal(18,2)"); b.Property("MarketCap") @@ -85,7 +85,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasKey("Id"); - b.ToTable("Stocks"); + b.ToTable("Stock"); }); modelBuilder.Entity("api.Models.Comment", b => diff --git a/api/Migrations/20231202125736_init.cs b/api/Migrations/20241217134339_init.cs similarity index 89% rename from api/Migrations/20231202125736_init.cs rename to api/Migrations/20241217134339_init.cs index 8887e0b5..ce35da7e 100644 --- a/api/Migrations/20231202125736_init.cs +++ b/api/Migrations/20241217134339_init.cs @@ -12,7 +12,7 @@ public partial class init : Migration protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.CreateTable( - name: "Stocks", + name: "Stock", columns: table => new { Id = table.Column(type: "int", nullable: false) @@ -20,13 +20,13 @@ protected override void Up(MigrationBuilder migrationBuilder) Symbol = table.Column(type: "nvarchar(max)", nullable: false), CompanyName = table.Column(type: "nvarchar(max)", nullable: false), Purchase = table.Column(type: "decimal(18,2)", nullable: false), - LastDiv = table.Column(type: "decimal(18,2)", nullable: false), + Lastdiv = table.Column(type: "decimal(18,2)", nullable: false), Industry = table.Column(type: "nvarchar(max)", nullable: false), MarketCap = table.Column(type: "bigint", nullable: false) }, constraints: table => { - table.PrimaryKey("PK_Stocks", x => x.Id); + table.PrimaryKey("PK_Stock", x => x.Id); }); migrationBuilder.CreateTable( @@ -44,9 +44,9 @@ protected override void Up(MigrationBuilder migrationBuilder) { table.PrimaryKey("PK_Comments", x => x.Id); table.ForeignKey( - name: "FK_Comments_Stocks_StockId", + name: "FK_Comments_Stock_StockId", column: x => x.StockId, - principalTable: "Stocks", + principalTable: "Stock", principalColumn: "Id"); }); @@ -63,7 +63,7 @@ protected override void Down(MigrationBuilder migrationBuilder) name: "Comments"); migrationBuilder.DropTable( - name: "Stocks"); + name: "Stock"); } } } diff --git a/api/Migrations/ApplicationDBContextModelSnapshot.cs b/api/Migrations/ApplicationDBContextModelSnapshot.cs index dbc498ed..464b3aa5 100644 --- a/api/Migrations/ApplicationDBContextModelSnapshot.cs +++ b/api/Migrations/ApplicationDBContextModelSnapshot.cs @@ -22,218 +22,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - 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", (string)null); - - b.HasData( - new - { - Id = "79f392bf-21e3-4e59-a899-f2a066f3884a", - Name = "Admin", - NormalizedName = "ADMIN" - }, - new - { - Id = "5849bcbd-fa3c-46ad-8ac1-00ff8cd9a6d7", - Name = "User", - NormalizedName = "USER" - }); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - 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", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - 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", (string)null); - }); - - 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", (string)null); - }); - - 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", (string)null); - }); - - 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", (string)null); - }); - - modelBuilder.Entity("api.Models.AppUser", 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.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - modelBuilder.Entity("api.Models.Comment", b => { b.Property("Id") @@ -279,7 +67,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(max)"); - b.Property("LastDiv") + b.Property("Lastdiv") .HasColumnType("decimal(18,2)"); b.Property("MarketCap") @@ -294,58 +82,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); - b.ToTable("Stocks"); - }); - - 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("api.Models.AppUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("api.Models.AppUser", 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("api.Models.AppUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("api.Models.AppUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + b.ToTable("Stock"); }); modelBuilder.Entity("api.Models.Comment", b => diff --git a/api/Models/AppUser.cs b/api/Models/AppUser.cs deleted file mode 100644 index 2692b0eb..00000000 --- a/api/Models/AppUser.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Identity; - -namespace api.Models -{ - public class AppUser : IdentityUser - { - public List Portfolios { get; set; } = new List(); - } -} \ No newline at end of file diff --git a/api/Models/Comment.cs b/api/Models/Comment.cs index c2618fb9..2bc494b4 100644 --- a/api/Models/Comment.cs +++ b/api/Models/Comment.cs @@ -1,21 +1,16 @@ using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Threading.Tasks; namespace api.Models { - [Table("Comments")] public class Comment - { - public int Id { get; set; } - public string Title { get; set; } = string.Empty; - public string Content { get; set; } = string.Empty; - public DateTime CreatedOn { get; set; } = DateTime.Now; + { public int Id { get; set; } + public string Title { get; set; }=string.Empty; + public string Content { get; set; }=string.Empty; + public DateTime CreatedOn { get; set; }=DateTime.Now; public int? StockId { get; set; } public Stock? Stock { get; set; } - public string AppUserId { get; set; } - public AppUser AppUser { get; set; } } } \ No newline at end of file diff --git a/api/Models/Portfolio.cs b/api/Models/Portfolio.cs deleted file mode 100644 index 29ec73e3..00000000 --- a/api/Models/Portfolio.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; -using System.Threading.Tasks; - -namespace api.Models -{ - [Table("Portfolios")] - public class Portfolio - { - public string AppUserId { get; set; } - public int StockId { get; set; } - public AppUser AppUser { get; set; } - public Stock Stock { get; set; } - } -} \ No newline at end of file diff --git a/api/Models/Stock.cs b/api/Models/Stock.cs index d34120d8..613b03d9 100644 --- a/api/Models/Stock.cs +++ b/api/Models/Stock.cs @@ -6,21 +6,25 @@ namespace api.Models { - [Table("Stocks")] public class Stock { - public int Id { get; set; } - public string Symbol { get; set; } = string.Empty; - public string CompanyName { get; set; } = string.Empty; - [Column(TypeName = "decimal(18,2)")] + public int Id { get; set; } + public string Symbol { get; set; }=string.Empty; + public string CompanyName { get; set; }=string.Empty; + [Column(TypeName = "decimal(18,2)")] + public decimal Purchase { get; set; } - [Column(TypeName = "decimal(18,2)")] - public decimal LastDiv { get; set; } - public string Industry { get; set; } = string.Empty; + + [Column(TypeName = "decimal(18,2)")] + + public decimal Lastdiv { get; set; } + public string Industry { get; set; }=string.Empty; public long MarketCap { get; set; } - public List Comments { get; set; } = new List(); - public List Portfolios { get; set; } = new List(); + public List Comments { get; set; }=new List(); + + + } } \ No newline at end of file diff --git a/api/Program.cs b/api/Program.cs index bdc5fd66..17c35287 100644 --- a/api/Program.cs +++ b/api/Program.cs @@ -1,13 +1,7 @@ + + using api.Data; -using api.Interfaces; -using api.Models; -using api.Repository; -using api.Service; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; -using Microsoft.IdentityModel.Tokens; -using Microsoft.OpenApi.Models; var builder = WebApplication.CreateBuilder(args); @@ -17,85 +11,11 @@ builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); -builder.Services.AddSwaggerGen(option => -{ - option.SwaggerDoc("v1", new OpenApiInfo { Title = "Demo API", Version = "v1" }); - option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme - { - In = ParameterLocation.Header, - Description = "Please enter a valid token", - Name = "Authorization", - Type = SecuritySchemeType.Http, - BearerFormat = "JWT", - Scheme = "Bearer" - }); - option.AddSecurityRequirement(new OpenApiSecurityRequirement - { - { - new OpenApiSecurityScheme - { - Reference = new OpenApiReference - { - Type=ReferenceType.SecurityScheme, - Id="Bearer" - } - }, - new string[]{} - } - }); -}); - -builder.Services.AddControllers().AddNewtonsoftJson(options => -{ - options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; -}); +builder.Services.AddDbContext(options =>{ + options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")); -builder.Services.AddDbContext(options => -{ - options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")); }); -builder.Services.AddIdentity(options => -{ - options.Password.RequireDigit = true; - options.Password.RequireLowercase = true; - options.Password.RequireUppercase = true; - options.Password.RequireNonAlphanumeric = true; - options.Password.RequiredLength = 12; -}) -.AddEntityFrameworkStores(); - -builder.Services.AddAuthentication(options => -{ - options.DefaultAuthenticateScheme = - options.DefaultChallengeScheme = - options.DefaultForbidScheme = - options.DefaultScheme = - options.DefaultSignInScheme = - options.DefaultSignOutScheme = JwtBearerDefaults.AuthenticationScheme; -}).AddJwtBearer(options => -{ - options.TokenValidationParameters = new TokenValidationParameters - { - ValidateIssuer = true, - ValidIssuer = builder.Configuration["JWT:Issuer"], - ValidateAudience = true, - ValidAudience = builder.Configuration["JWT:Audience"], - ValidateIssuerSigningKey = true, - IssuerSigningKey = new SymmetricSecurityKey( - System.Text.Encoding.UTF8.GetBytes(builder.Configuration["JWT:SigningKey"]) - ) - }; -}); - - -builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddHttpClient(); - var app = builder.Build(); @@ -108,17 +28,8 @@ app.UseHttpsRedirection(); -app.UseCors(x => x - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials() - //.WithOrigins("https://localhost:44351)) - .SetIsOriginAllowed(origin => true)); - -app.UseAuthentication(); -app.UseAuthorization(); - app.MapControllers(); + app.Run(); diff --git a/api/Repository/CommentRepository.cs b/api/Repository/CommentRepository.cs deleted file mode 100644 index ed588d4c..00000000 --- a/api/Repository/CommentRepository.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using api.Data; -using api.Helpers; -using api.Interfaces; -using api.Models; -using Microsoft.EntityFrameworkCore; - -namespace api.Repository -{ - public class CommentRepository : ICommentRepository - { - private readonly ApplicationDBContext _context; - public CommentRepository(ApplicationDBContext context) - { - _context = context; - } - - public async Task CreateAsync(Comment commentModel) - { - await _context.Comments.AddAsync(commentModel); - await _context.SaveChangesAsync(); - return commentModel; - } - - public async Task DeleteAsync(int id) - { - var commentModel = await _context.Comments.FirstOrDefaultAsync(x => x.Id == id); - - if (commentModel == null) - { - return null; - } - - _context.Comments.Remove(commentModel); - await _context.SaveChangesAsync(); - return commentModel; - } - - public async Task> GetAllAsync(CommentQueryObject queryObject) - { - var comments = _context.Comments.Include(a => a.AppUser).AsQueryable(); - - if (!string.IsNullOrWhiteSpace(queryObject.Symbol)) - { - comments = comments.Where(s => s.Stock.Symbol == queryObject.Symbol); - }; - if (queryObject.IsDecsending == true) - { - comments = comments.OrderByDescending(c => c.CreatedOn); - } - return await comments.ToListAsync(); - } - - public async Task GetByIdAsync(int id) - { - return await _context.Comments.Include(a => a.AppUser).FirstOrDefaultAsync(c => c.Id == id); - } - - public async Task UpdateAsync(int id, Comment commentModel) - { - var existingComment = await _context.Comments.FindAsync(id); - - if (existingComment == null) - { - return null; - } - - existingComment.Title = commentModel.Title; - existingComment.Content = commentModel.Content; - - await _context.SaveChangesAsync(); - - return existingComment; - } - } -} \ No newline at end of file diff --git a/api/Repository/PortfolioRepository.cs b/api/Repository/PortfolioRepository.cs deleted file mode 100644 index 61275029..00000000 --- a/api/Repository/PortfolioRepository.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using api.Data; -using api.Interfaces; -using api.Models; -using Microsoft.EntityFrameworkCore; - -namespace api.Repository -{ - public class PortfolioRepository : IPortfolioRepository - { - private readonly ApplicationDBContext _context; - public PortfolioRepository(ApplicationDBContext context) - { - _context = context; - } - - public async Task CreateAsync(Portfolio portfolio) - { - await _context.Portfolios.AddAsync(portfolio); - await _context.SaveChangesAsync(); - return portfolio; - } - - public async Task DeletePortfolio(AppUser appUser, string symbol) - { - var portfolioModel = await _context.Portfolios.FirstOrDefaultAsync(x => x.AppUserId == appUser.Id && x.Stock.Symbol.ToLower() == symbol.ToLower()); - - if (portfolioModel == null) - { - return null; - } - - _context.Portfolios.Remove(portfolioModel); - await _context.SaveChangesAsync(); - return portfolioModel; - } - - public async Task> GetUserPortfolio(AppUser user) - { - return await _context.Portfolios.Where(u => u.AppUserId == user.Id) - .Select(stock => new Stock - { - Id = stock.StockId, - Symbol = stock.Stock.Symbol, - CompanyName = stock.Stock.CompanyName, - Purchase = stock.Stock.Purchase, - LastDiv = stock.Stock.LastDiv, - Industry = stock.Stock.Industry, - MarketCap = stock.Stock.MarketCap - }).ToListAsync(); - } - } -} \ No newline at end of file diff --git a/api/Repository/StockRepository.cs b/api/Repository/StockRepository.cs deleted file mode 100644 index 8d896c4f..00000000 --- a/api/Repository/StockRepository.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using api.Data; -using api.Dtos.Stock; -using api.Helpers; -using api.Interfaces; -using api.Models; -using Microsoft.EntityFrameworkCore; - -namespace api.Repository -{ - public class StockRepository : IStockRepository - { - private readonly ApplicationDBContext _context; - public StockRepository(ApplicationDBContext context) - { - _context = context; - } - - public async Task CreateAsync(Stock stockModel) - { - await _context.Stocks.AddAsync(stockModel); - await _context.SaveChangesAsync(); - return stockModel; - } - - public async Task DeleteAsync(int id) - { - var stockModel = await _context.Stocks.FirstOrDefaultAsync(x => x.Id == id); - - if (stockModel == null) - { - return null; - } - - _context.Stocks.Remove(stockModel); - await _context.SaveChangesAsync(); - return stockModel; - } - - public async Task> GetAllAsync(QueryObject query) - { - var stocks = _context.Stocks.Include(c => c.Comments).ThenInclude(a => a.AppUser).AsQueryable(); - - if (!string.IsNullOrWhiteSpace(query.CompanyName)) - { - stocks = stocks.Where(s => s.CompanyName.Contains(query.CompanyName)); - } - - if (!string.IsNullOrWhiteSpace(query.Symbol)) - { - stocks = stocks.Where(s => s.Symbol.Contains(query.Symbol)); - } - - if (!string.IsNullOrWhiteSpace(query.SortBy)) - { - if (query.SortBy.Equals("Symbol", StringComparison.OrdinalIgnoreCase)) - { - stocks = query.IsDecsending ? stocks.OrderByDescending(s => s.Symbol) : stocks.OrderBy(s => s.Symbol); - } - } - - var skipNumber = (query.PageNumber - 1) * query.PageSize; - - - return await stocks.Skip(skipNumber).Take(query.PageSize).ToListAsync(); - } - - public async Task GetByIdAsync(int id) - { - return await _context.Stocks.Include(c => c.Comments).FirstOrDefaultAsync(i => i.Id == id); - } - - public async Task GetBySymbolAsync(string symbol) - { - return await _context.Stocks.FirstOrDefaultAsync(s => s.Symbol == symbol); - } - - public Task StockExists(int id) - { - return _context.Stocks.AnyAsync(s => s.Id == id); - } - - public async Task UpdateAsync(int id, UpdateStockRequestDto stockDto) - { - var existingStock = await _context.Stocks.FirstOrDefaultAsync(x => x.Id == id); - - if (existingStock == null) - { - return null; - } - - existingStock.Symbol = stockDto.Symbol; - existingStock.CompanyName = stockDto.CompanyName; - existingStock.Purchase = stockDto.Purchase; - existingStock.LastDiv = stockDto.LastDiv; - existingStock.Industry = stockDto.Industry; - existingStock.MarketCap = stockDto.MarketCap; - - await _context.SaveChangesAsync(); - - return existingStock; - } - } -} \ No newline at end of file diff --git a/api/Service/FMPService.cs b/api/Service/FMPService.cs deleted file mode 100644 index 2cdafebc..00000000 --- a/api/Service/FMPService.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using api.Dtos.Stock; -using api.Interfaces; -using api.Mappers; -using api.Models; -using Newtonsoft.Json; - -namespace api.Service -{ - public class FMPService : IFMPService - { - private HttpClient _httpClient; - private IConfiguration _config; - public FMPService(HttpClient httpClient, IConfiguration config) - { - _httpClient = httpClient; - _config = config; - } - public async Task FindStockBySymbolAsync(string symbol) - { - try - { - var result = await _httpClient.GetAsync($"https://financialmodelingprep.com/api/v3/profile/{symbol}?apikey={_config["FMPKey"]}"); - if (result.IsSuccessStatusCode) - { - var content = await result.Content.ReadAsStringAsync(); - var tasks = JsonConvert.DeserializeObject(content); - var stock = tasks[0]; - if (stock != null) - { - return stock.ToStockFromFMP(); - } - return null; - } - return null; - } - catch (Exception e) - { - Console.WriteLine(e); - return null; - } - } - } -} \ No newline at end of file diff --git a/api/Service/TokenService.cs b/api/Service/TokenService.cs deleted file mode 100644 index 7944a429..00000000 --- a/api/Service/TokenService.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IdentityModel.Tokens.Jwt; -using System.Linq; -using System.Security.Claims; -using System.Text; -using System.Threading.Tasks; -using api.Interfaces; -using api.Models; -using Microsoft.IdentityModel.Tokens; - -namespace api.Service -{ - public class TokenService : ITokenService - { - private readonly IConfiguration _config; - private readonly SymmetricSecurityKey _key; - - public TokenService(IConfiguration config) - { - _config = config; - _key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["JWT:SigningKey"])); - } - public string CreateToken(AppUser user) - { - var claims = new List - { - new Claim(JwtRegisteredClaimNames.Email, user.Email), - new Claim(JwtRegisteredClaimNames.GivenName, user.UserName) - }; - - var creds = new SigningCredentials(_key, SecurityAlgorithms.HmacSha512Signature); - - var tokenDescriptor = new SecurityTokenDescriptor - { - Subject = new ClaimsIdentity(claims), - Expires = DateTime.Now.AddDays(7), - SigningCredentials = creds, - Issuer = _config["JWT:Issuer"], - Audience = _config["JWT:Audience"] - }; - - var tokenHandler = new JwtSecurityTokenHandler(); - - var token = tokenHandler.CreateToken(tokenDescriptor); - - return tokenHandler.WriteToken(token); - } - } -} \ No newline at end of file diff --git a/api/appsettings.json b/api/appsettings.json index c4abd065..457c5fb0 100644 --- a/api/appsettings.json +++ b/api/appsettings.json @@ -1,6 +1,6 @@ { "ConnectionStrings": { - "DefaultConnection": "Data Source=DESKTOP-U39R90D\\SQLEXPRESS;Initial Catalog=finshark;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" + "DefaultConnection": "Data Source=DESKTOP-DJBNJJD\\SQLEXPRESS;Initial Catalog=finshark;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" }, "Logging": { "LogLevel": {