diff --git a/backend/backend/Controllers/AuthController.cs b/backend/backend/Controllers/AuthController.cs index 85cc48e..994913b 100644 --- a/backend/backend/Controllers/AuthController.cs +++ b/backend/backend/Controllers/AuthController.cs @@ -5,73 +5,62 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.IdentityModel.Tokens; using backend.Models; - public class UserLogin - { - public string Username { get; set; } - public string Password { get; set; } - } +namespace backend.Controllers; + +public class UserLogin { + public required string Username { get; set; } + public required string Password { get; set; } +} [ApiController] -[Route("api/[controller]")] -public class AuthController : ControllerBase -{ - private readonly GameContext _context; +[Route("api/v1/[controller]")] +public class AuthController(GameContext context) : ControllerBase { + private readonly GameContext _context = context; -public static string CreateMD5(string input) -{ - // Use input string to calculate MD5 hash - using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create()) - { - byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input); - byte[] hashBytes = md5.ComputeHash(inputBytes); + [HttpPost("login")] + public IActionResult Login([FromBody] UserLogin loginData) { + var salt = Environment.GetEnvironmentVariable("MD5_SALT") ?? ""; + var passwordHash = CreateMD5(loginData.Password + salt); - return Convert.ToHexString(hashBytes); // .NET 5 + + var user = _context + .Users + .Where(u => u.Username == loginData.Username && u.PasswordHash == passwordHash) + .FirstOrDefault(); - // Convert the byte array to hexadecimal string prior to .NET 5 - // StringBuilder sb = new System.Text.StringBuilder(); - // for (int i = 0; i < hashBytes.Length; i++) - // { - // sb.Append(hashBytes[i].ToString("X2")); - // } - // return sb.ToString(); - } -} - - public AuthController(GameContext context) { - _context = context; - } - - [HttpPost("login")] - public IActionResult Login([FromBody] UserLogin user) { - var salt = Environment.GetEnvironmentVariable("MD5_SALT") ?? ""; - var passwordHash = CreateMD5(user.Password + salt); - var dbUser = _context.Users.Where(u => u.Username == user.Username && u.PasswordHash == passwordHash).FirstOrDefault(); - if (dbUser != null) { - var token = GenerateJwtToken(dbUser.Id.ToString()); - return Ok(new { token }); - } - - return Unauthorized(); - } - - private string GenerateJwtToken(string userId) - { - var claims = new[] - { - new Claim(JwtRegisteredClaimNames.Sub, userId), - new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) - }; - - var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Environment.GetEnvironmentVariable("JWT_SECRET"))); - var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); - - var token = new JwtSecurityToken( - issuer: "wessel.gg", - audience: "wessel.gg", - claims: claims, - expires: DateTime.Now.AddMinutes(30), - signingCredentials: creds); - - return new JwtSecurityTokenHandler().WriteToken(token); + if (user != null) { + var token = GenerateJwtToken(user.Id.ToString()); + + return Ok(new { token }); } + + return Unauthorized(); + } + + private static string GenerateJwtToken(string userId) { + var secret = Environment.GetEnvironmentVariable("JWT_SECRET") ?? ""; + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret)); + var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); + + var claims = new[] { + new Claim(JwtRegisteredClaimNames.Sub, userId), + new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) + }; + + var token = new JwtSecurityToken( + signingCredentials: creds, + issuer: Environment.GetEnvironmentVariable("JWT_ISSUER") ?? "", + audience: Environment.GetEnvironmentVariable("JWT_AUDIENCE") ?? "", + claims: claims, + expires: DateTime.Now.AddHours(6) + ); + + return new JwtSecurityTokenHandler().WriteToken(token); + } + + public static string CreateMD5(string input) { + byte[] inputBytes = Encoding.ASCII.GetBytes(input); + byte[] hashBytes = System.Security.Cryptography.MD5.HashData(inputBytes); + + return Convert.ToHexString(hashBytes); + } } diff --git a/backend/backend/Controllers/GamesController.cs b/backend/backend/Controllers/GamesController.cs index 8ad29a7..9d04128 100755 --- a/backend/backend/Controllers/GamesController.cs +++ b/backend/backend/Controllers/GamesController.cs @@ -1,178 +1,172 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using backend.Models; using Microsoft.AspNetCore.Authorization; using System.Security.Claims; -using System.IdentityModel.Tokens.Jwt; -namespace backend.Controllers -{ - [Route("/api/v1/[controller]")] - [ApiController] - public class GamesController : ControllerBase { - private readonly GameContext _context; +namespace backend.Controllers; - public GamesController(GameContext context) { - _context = context; +[Route("/api/v1/[controller]")] +[ApiController] +public class GamesController(GameContext context) : ControllerBase { + private readonly GameContext _context = context; + + private long? ParseUserId() { + var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier)?.Value; + + if (long.TryParse(userIdClaim, out var userId)) { + return userId; } - // GET: api/Games - [HttpGet] - [Authorize] - public async Task>> GetGames() { - var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier)?.Value; + return null; + } - if (!long.TryParse(userIdClaim, out var userId)) { - return Unauthorized(); - } - - // return await _context.Games.ToListAsync(); - return await _context.Games.Where(g => g.UserId == userId).ToListAsync(); + // GET: api/Games + [HttpGet] + [Authorize] + public async Task>> GetGames() { + var user = ParseUserId(); + if (user == null) { + return BadRequest(); } - // GET: api/Games/5 - [HttpGet("{id}")] - [Authorize] - public async Task> GetGame(long id) - { - var game = await _context.Games.FindAsync(id); + return await _context.Games + .Where(g => g.UserId == user) + .ToListAsync(); + } - if (game == null) - { - return NotFound(); - } - - return game; + // GET: api/Games/5 + [HttpGet("{id}")] + [Authorize] + public async Task> GetGame(long id) { + var user = ParseUserId(); + if (user == null) { + return BadRequest(); } - // PUT: api/Games/5 - // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 - [HttpPut("{id}")] - [Authorize] - public async Task PutGame(long id, Game game) - { - if (id != game.Id) - { - return BadRequest(); - } + var game = await _context.Games + .Where(g => g.Id == id && g.UserId == user) + .FirstOrDefaultAsync(); - _context.Entry(game).State = EntityState.Modified; - - try { - await _context.SaveChangesAsync(); - } catch (DbUpdateConcurrencyException) { - if (!GameExists(id)) { - return NotFound(); - } else { - throw; - } - } - - return NoContent(); + if (game == null || game.UserId != user) { + return NotFound(); } - // POST: api/Games - // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 - [HttpPost] - [Authorize] - public async Task> PostGame() { - - var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier)?.Value; + return game; + } - if (!long.TryParse(userIdClaim, out var userId)) { - return Unauthorized(); - } - - var newGame = new Game { - Deck = ( - from shape in Enum.GetValues(typeof(CardShape)).Cast() - from color in Enum.GetValues(typeof(CardColor)).Cast() - from count in Enum.GetValues(typeof(CardCount)).Cast() - from shade in Enum.GetValues(typeof(CardShade)).Cast() - select new Card { - Shape = shape, - Color = color, - Count = count, - Shade = shade - }.ToUshort()).ToArray(), - UserId = userId - }; - - newGame.ShuffleDeck(); - newGame.DealHand(); - - _context.Games.Add(newGame); - await _context.SaveChangesAsync(); - - return CreatedAtAction(nameof(GetGame), new { id = newGame.Id }, newGame); + // POST: api/Games + // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 + [HttpPost] + [Authorize] + public async Task> PostGame() { + var user = ParseUserId(); + if (user == null) { + return BadRequest(); } - // DELETE: api/Games/5 - [HttpDelete("{id}")] - [Authorize] - public async Task DeleteGame(long id) { - var game = await _context.Games.FindAsync(id); - if (game == null) - { - return NotFound(); - } + var newGame = new Game { + UserId = (long)user, + Deck = [.. + from shape in Enum.GetValues().Cast() + from color in Enum.GetValues().Cast() + from count in Enum.GetValues().Cast() + from shade in Enum.GetValues().Cast() + select new Card { + Shape = shape, + Color = color, + Count = count, + Shade = shade + }.ToUshort() + ] + }; - _context.Games.Remove(game); - await _context.SaveChangesAsync(); + newGame.ShuffleDeck(); + newGame.DealHand(); - return NoContent(); + _context.Games.Add(newGame); + await _context.SaveChangesAsync(); + + return CreatedAtAction(nameof(GetGame), new { id = newGame.Id }, newGame); + } + + // DELETE: api/Games/5 + [HttpDelete("{id}")] + [Authorize] + public async Task DeleteGame(long id) { + var user = ParseUserId(); + if (user == null) { + return BadRequest(); } - private bool GameExists(long id) { - return _context.Games.Any(e => e.Id == id); + var game = await _context.Games + .Where(g => g.Id == id && g.UserId == user) + .FirstOrDefaultAsync(); + + if (game == null) { + return NotFound(); } - [HttpPost] - [Route("[action]/{id}")] - [Authorize] + _context.Games.Remove(game); + await _context.SaveChangesAsync(); + + return NoContent(); + } + + [HttpPost] + [Route("[action]/{id}")] + [Authorize] public async Task> CheckSet( long id, [FromBody] ushort[] cardIndices ) { - var game = await _context.Games.FindAsync(id); - if (game == null) { - return NotFound(); - } - - var res = game.IsSet(cardIndices); - - if (res == null) { - return BadRequest(); - } - - await _context.SaveChangesAsync(); - - return res; + var user = ParseUserId(); + if (user == null) { + return BadRequest(); } - [HttpGet] - [Route("[action]/{id}")] - [Authorize] - public async Task>> SetsInHand(long id) { - var game = await _context.Games.FindAsync(id); - if (game == null) { - return NotFound(); - } + var game = await _context.Games + .Where(g => g.Id == id && g.UserId == user) + .FirstOrDefaultAsync(); - var res = game.GetIndicesOfSet(); - - if (res == null) { - return BadRequest(); - } - - Console.WriteLine($"Found {res.Count} sets in hand"); - - return res; + if (game == null) { + return NotFound(); } + + var res = game.IsSet(cardIndices); + + if (res == null) { + return BadRequest(); + } + + await _context.SaveChangesAsync(); + + return res; } -} + + [HttpGet] + [Route("[action]/{id}")] + [Authorize] + public async Task>> SetsInHand(long id) { + var user = ParseUserId(); + if (user == null) { + return BadRequest(); + } + + var game = await _context.Games + .Where(g => g.Id == id && g.UserId == user) + .FirstOrDefaultAsync(); + + if (game == null) { + return NotFound(); + } + + var res = game.GetIndicesOfSet(); + + if (res == null) { + return BadRequest(); + } + + return res; + } +} \ No newline at end of file diff --git a/backend/backend/Migrations/20250325111947_initial.Designer.cs b/backend/backend/Migrations/20250325145201_InitialDatabase.Designer.cs similarity index 95% rename from backend/backend/Migrations/20250325111947_initial.Designer.cs rename to backend/backend/Migrations/20250325145201_InitialDatabase.Designer.cs index 9745138..5c3e7e6 100644 --- a/backend/backend/Migrations/20250325111947_initial.Designer.cs +++ b/backend/backend/Migrations/20250325145201_InitialDatabase.Designer.cs @@ -12,8 +12,8 @@ using backend.Models; namespace backend.Migrations { [DbContext(typeof(GameContext))] - [Migration("20250325111947_initial")] - partial class initial + [Migration("20250325145201_InitialDatabase")] + partial class InitialDatabase { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -102,13 +102,11 @@ namespace backend.Migrations modelBuilder.Entity("backend.Models.Game", b => { - b.HasOne("backend.Models.User", "User") + b.HasOne("backend.Models.User", null) .WithMany("Games") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - - b.Navigation("User"); }); modelBuilder.Entity("backend.Models.User", b => diff --git a/backend/backend/Migrations/20250325111947_initial.cs b/backend/backend/Migrations/20250325145201_InitialDatabase.cs similarity index 98% rename from backend/backend/Migrations/20250325111947_initial.cs rename to backend/backend/Migrations/20250325145201_InitialDatabase.cs index 24a7f9d..724cc19 100644 --- a/backend/backend/Migrations/20250325111947_initial.cs +++ b/backend/backend/Migrations/20250325145201_InitialDatabase.cs @@ -7,7 +7,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace backend.Migrations { /// - public partial class initial : Migration + public partial class InitialDatabase : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) diff --git a/backend/backend/Migrations/GameContextModelSnapshot.cs b/backend/backend/Migrations/GameContextModelSnapshot.cs index 15c132d..2c534c5 100644 --- a/backend/backend/Migrations/GameContextModelSnapshot.cs +++ b/backend/backend/Migrations/GameContextModelSnapshot.cs @@ -99,13 +99,11 @@ namespace backend.Migrations modelBuilder.Entity("backend.Models.Game", b => { - b.HasOne("backend.Models.User", "User") + b.HasOne("backend.Models.User", null) .WithMany("Games") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - - b.Navigation("User"); }); modelBuilder.Entity("backend.Models.User", b => diff --git a/backend/backend/Models/Game.cs b/backend/backend/Models/Game.cs index d763ce0..32bd88e 100755 --- a/backend/backend/Models/Game.cs +++ b/backend/backend/Models/Game.cs @@ -18,8 +18,6 @@ public class Game { public ushort[]? Deck { get; set; } public ushort[] Found { get; set; } = Array.Empty(); - public User User { get; set; } = null!; - public void ShuffleDeck() { if (Deck == null) return; diff --git a/frontend/src/service/auth/auth.service.ts b/frontend/src/service/auth/auth.service.ts index 73a96e2..443306e 100644 --- a/frontend/src/service/auth/auth.service.ts +++ b/frontend/src/service/auth/auth.service.ts @@ -11,7 +11,7 @@ interface LoginResponse { providedIn: 'root' }) export class AuthService { - private API_URL = 'http://localhost:5224/api/Auth'; + private API_URL = 'http://localhost:5224/api/v1/Auth'; private tokenKey = 'auth_token'; private isAuthenticatedSubject = new BehaviorSubject(this.hasToken()); public redirectUrl: string | null = null; diff --git a/frontend/src/service/game/game.service.ts b/frontend/src/service/game/game.service.ts index d0686ad..e213a16 100755 --- a/frontend/src/service/game/game.service.ts +++ b/frontend/src/service/game/game.service.ts @@ -1,13 +1,13 @@ import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; import { Card, toCard } from '../../app/models/card'; -// todo: Rewrite to use angular http client instead of axios, supports always sending tokens -import axios from 'axios'; - -axios.defaults.headers.common['Authorization'] = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbiIsImp0aSI6ImRmNThhYTU3LWZkNzItNGIzYS05OTNmLTY4NjAyNGMzYjdlNSIsImV4cCI6MTc0MjgxODEzOCwiaXNzIjoid2Vzc2VsLmdnIiwiYXVkIjoid2Vzc2VsLmdnIn0.hDf8qcxXeSFQhmgnMzBrH3ZJJMplwZ-1RQwNxeZo5ok'; +import { lastValueFrom } from 'rxjs'; +import { AuthService } from '../auth/auth.service'; @Injectable({ providedIn: 'root' }) - export class GameService { + private API_URL = 'http://localhost:5224/api/v1/Games'; + public deck: Card[] = []; public hand: Card[] = []; public foundSets: Card[][] = []; @@ -20,8 +20,9 @@ export class GameService { public finishedAt?: Date; public selectedCards: Card[] = []; - constructor() { - } + constructor( + private http: HttpClient, + ) {} public initGame(gameId?: string): Promise { this.deck = []; @@ -35,58 +36,113 @@ export class GameService { } public async initializeExistingGame(gameId: string): Promise { - const req = await axios.get('http://localhost:5224/api/v1/Games/' + gameId); - req.data.deck.forEach((card: number) => { - this.deck.push(toCard(card)); - - }); - req.data.hand.forEach((card: number) => { + try { + const response = await lastValueFrom(this.http.get(`${this.API_URL}/${gameId}`)); + + response.deck.forEach((card: number) => { + this.deck.push(toCard(card)); + }); + + response.hand.forEach((card: number) => { this.hand.push(toCard(card)); }); - this.startDate = new Date(req.data.startedAt); - this.fails = req.data.fails; - this.hints = req.data.hints; - this.finishedAt = req.data.finishedAt; + + this.startDate = new Date(response.startedAt); + this.fails = response.fails; + this.hints = response.hints; + this.finishedAt = response.finishedAt ? new Date(response.finishedAt) : undefined; + this.foundSets = []; - for (let i = 0; i < req.data.found.length; i += 3) { - this.foundSets.push(req.data.found.slice(i, i + 3).map((card: number) => toCard(card))); + for (let i = 0; i < response.found.length; i += 3) { + this.foundSets.push(response.found.slice(i, i + 3).map((card: number) => toCard(card))); } - this.gameId = req.data.id; - await this.updateSets(); - - return req.data.id; - + this.gameId = response.id; + this.updateSets(); + return response.id.toString(); + } catch (error) { + console.error('Error initializing existing game', error); + throw error; + } } private async initializeDeck(): Promise { - const res = await axios.post('http://localhost:5224/api/v1/Games', {}); - res.data.deck.forEach((card: number) => { + try { + const response = await lastValueFrom(this.http.post(this.API_URL, {})); + + response.deck.forEach((card: number) => { this.deck.push(toCard(card)); - }); - - res.data.hand.forEach((card: number) => { + }); + + response.hand.forEach((card: number) => { this.hand.push(toCard(card)); }); - - this.startDate = new Date(res.data.startedAt); - this.fails = res.data.fails; - this.hints = res.data.hints; - this.gameId = res.data.id; - this.finishedAt = res.data.finishedAt; + + this.startDate = new Date(response.startedAt); + this.fails = response.fails; + this.hints = response.hints; + this.gameId = response.id; + this.finishedAt = response.finishedAt ? new Date(response.finishedAt) : undefined; + this.foundSets = []; - for (let i = 0; i < res.data.newState.found.length; i += 3) { - this.foundSets.push(res.data.newState.found.slice(i, i + 3).map((card: number) => toCard(card))); + for (let i = 0; i < response.found.length; i += 3) { + this.foundSets.push(response.found.slice(i, i + 3).map((card: number) => toCard(card))); } + + this.updateSets(); + return response.id.toString(); + } catch (error) { + console.error('Error initializing deck', error); + throw error; + } + } + public async updateSets(): Promise { + try { + const response = await lastValueFrom( + this.http.get(`${this.API_URL}/SetsInHand/${this.gameId}`) + ); + + const cards = response.map((set: number[]) => + set.map((card: number) => this.hand[card]) + ); + + this.possibleSets = cards; + return cards; + } catch (error) { + console.error('Error updating sets', error); + throw error; + } + } + + public async checkSet(cards: number[]): Promise { + try { + const response = await lastValueFrom( + this.http.post(`${this.API_URL}/CheckSet/${this.gameId}`, cards) + ); + + this.hand = response.newState.hand.map((card: number) => toCard(card)); + this.deck = response.newState.deck.map((card: number) => toCard(card)); + this.fails = response.newState.fails; + this.hints = response.newState.hints; + this.finishedAt = response.newState.finishedAt ? new Date(response.newState.finishedAt) : undefined; + + this.foundSets = []; + for (let i = 0; i < response.newState.found.length; i += 3) { + this.foundSets.push(response.newState.found.slice(i, i + 3).map((card: number) => toCard(card))); + } + await this.updateSets(); - - return res.data.id; + return response.isSet; + } catch (error) { + console.error('Error checking set', error); + throw error; + } } public selectCard(card: Card): void { const cardIndex = this.hand.indexOf(card); - if (cardIndex === -1) return; // Card not found on the board + if (cardIndex === -1) return; // Card not found in hand if (this.selectedCards.includes(card)) { this.selectedCards = this.selectedCards.filter(c => c !== card); @@ -95,58 +151,29 @@ export class GameService { } if (this.selectedCards.length === 3) { - const [card1, card2, card3] = this.selectedCards as [Card, Card, Card]; // ✅ Explicitly cast to a tuple - if (this.isSet([this.hand.indexOf(card1), this.hand.indexOf(card2), this.hand.indexOf(card3)])) { - this.replaceSet(); - } + const indices = this.selectedCards.map(c => this.hand.indexOf(c)); + this.checkSet(indices).then(isSet => { + this.selectedCards = []; + }); } } - public async updateSets(): Promise { - const req = await axios.get(`http://localhost:5224/api/v1/Games/SetsInHand/${this.gameId}`); - const cards = req.data - .map((set: number[]) => - set.map((card: number) => this.hand[card]) - ); - - this.possibleSets = cards; - - return cards; + public async deleteGame(): Promise { + try { + await lastValueFrom(this.http.delete(`${this.API_URL}/${this.gameId}`)); + } catch (error) { + console.error('Error deleting game', error); + throw error; + } } - private isSet(cards: number[]): boolean { - this.selectedCards = []; - - axios.post(`http://localhost:5224/api/v1/Games/CheckSet/${this.gameId}`, cards).then((response) => { - this.hand = response.data.newState.hand.map((card: number) => toCard(card)); - this.deck = response.data.newState.deck.map((card: number) => toCard(card)); - this.fails = response.data.newState.fails; - this.hints = response.data.newState.hints; - this.finishedAt = response.data.newState.finishedAt; - this.foundSets = []; - for (let i = 0; i < response.data.newState.found.length; i += 3) { - this.foundSets.push(response.data.newState.found.slice(i, i + 3).map((card: number) => toCard(card))); - } - - this.updateSets(); - - return response.data.isSet; - }); - - return false; + public async showHint(): Promise { + try { + await lastValueFrom(this.http.post(`${this.API_URL}/Hint/${this.gameId}`, {})); + this.hints++; + } catch (error) { + console.error('Error showing hint', error); + throw error; + } } - - - private replaceSet(): void { - this.hand.find((c, i) => { - if (this.selectedCards.includes(c)) { - this.hand[i] = this.deck.splice(0, 1)[0]; - } - }); - this.selectedCards = []; - } - - public async deleteGame() { - await axios.delete('http://localhost:5224/api/v1/Games/' + this.gameId); - } -} +} \ No newline at end of file diff --git a/frontend/src/service/user/user-data.service.ts b/frontend/src/service/user/user-data.service.ts index 97ef7ab..483d322 100644 --- a/frontend/src/service/user/user-data.service.ts +++ b/frontend/src/service/user/user-data.service.ts @@ -1,43 +1,40 @@ import { Injectable } from '@angular/core'; -import axios, { AxiosError } from 'axios'; - -// axios.defaults.headers.common['Authorization'] = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbiIsImp0aSI6ImRmNThhYTU3LWZkNzItNGIzYS05OTNmLTY4NjAyNGMzYjdlNSIsImV4cCI6MTc0MjgxODEzOCwiaXNzIjoid2Vzc2VsLmdnIiwiYXVkIjoid2Vzc2VsLmdnIn0.hDf8qcxXeSFQhmgnMzBrH3ZJJMplwZ-1RQwNxeZo5ok'; -axios.interceptors.request.use( - (config) => { - const token = localStorage.getItem('token'); - if (token) { - config.headers.Authorization = `Bearer ${token}`; - } - return config; - }, - (error) => { - return Promise.reject(error); - } -); +import { HttpClient } from '@angular/common/http'; +import { lastValueFrom } from 'rxjs'; +import { AuthService } from '../auth/auth.service'; @Injectable({ providedIn: 'root' }) export class UserDataService { + private GAMES_API_URL = 'http://localhost:5224/api/v1/Games'; - constructor() { - // this.login({ username: 'admin', password: 'password' }); + constructor( + private http: HttpClient, + private authService: AuthService + ) {} + + public async login(credentials: { username: string, password: string }): Promise { + try { + await lastValueFrom(this.authService.login(credentials.username, credentials.password)); + } catch (error) { + console.error('Login error:', error); + throw error; + } } - public async login(credentials: any) { - const response = await axios.post('http://localhost:5224/api/Auth/login', credentials); - localStorage.setItem('token', response.data.token); + public async getGames(): Promise { + try { + const data = await lastValueFrom(this.http.get(this.GAMES_API_URL)); + + const sortedGames = data + .sort((a: any, b: any) => new Date(a.startedAt).getTime() - new Date(b.startedAt).getTime()) + .reverse(); + + return sortedGames; + } catch (error) { + console.error('Error getting games:', error); + throw error; + } } - - public async getGames(): Promise { - const req = await axios.get('http://localhost:5224/api/v1/Games', { - headers: { - 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbiIsImp0aSI6ImRmNThhYTU3LWZkNzItNGIzYS05OTNmLTY4NjAyNGMzYjdlNSIsImV4cCI6MTc0MjgxODEzOCwiaXNzIjoid2Vzc2VsLmdnIiwiYXVkIjoid2Vzc2VsLmdnIn0.hDf8qcxXeSFQhmgnMzBrH3ZJJMplwZ-1RQwNxeZo5ok' - } - }); - const sortedGames = req.data - .sort((a: any, b: any) => new Date(a.startedAt).getTime() - new Date(b.startedAt).getTime()) - .reverse(); - return sortedGames; - } -} +} \ No newline at end of file