Skip to content

Commit

Permalink
Mastermind API V1
Browse files Browse the repository at this point in the history
  • Loading branch information
Szabó Gábor committed Apr 6, 2020
1 parent 493de64 commit 24f4b8e
Show file tree
Hide file tree
Showing 26 changed files with 988 additions and 0 deletions.
39 changes: 39 additions & 0 deletions Controllers/GamesController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Mastermind.Api.Models;
using Mastermind.Api.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Mastermind.Api.Controllers
{
[Authorize]
[ApiController]
public class GamesController : ControllerBase
{
public GamesController(GameService gameService) => GameService = gameService;

public GameService GameService { get; }

[HttpGet("api/games")]
public IEnumerable<Game> GetGames() =>
GameService.GetGames();

[HttpGet("api/games/{gameId}")]
public Game GetGame(Guid gameId) =>
GameService.GetGame(gameId);

[HttpPost("api/games")]
public Game AddNewGame([FromBody]GameOptions options) =>
GameService.AddNewGame(options);

[HttpPost("api/games/{gameId}/guess")]
public async Task<ActionResult<Game>> PostGuessAsync([FromRoute]Guid gameId, [FromBody] IReadOnlyList<int> numbers) =>
await GameService.GuessAsync(gameId, numbers);

[HttpGet("api/highscores")]
public async Task<IEnumerable<HighScore>> GetHighScores(int entries = 20) =>
await GameService.GetHighScores(entries);
}
}
38 changes: 38 additions & 0 deletions Controllers/UserController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Mastermind.Api.Models;
using Mastermind.Api.Services;
using Microsoft.AspNetCore.Mvc;
using System.Net;
using System.Threading.Tasks;

namespace Mastermind.Api.Controllers
{
[ApiController]
public class UserController : ControllerBase
{
public UserService UserService { get; }

public UserController(UserService userService) => UserService = userService;

[HttpPost("api/user/register")]
[ProducesResponseType((int)HttpStatusCode.NoContent)]
public async Task<IActionResult> RegisterAsync([FromBody] UserAuthModel userAuthModel)
{
await UserService.HttpCookieSignInAsync(await UserService.RegisterAsync(userAuthModel.Username, userAuthModel.Password));
return NoContent();
}

[HttpPost("api/user/login")]
[ProducesResponseType((int)HttpStatusCode.NoContent)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
public async Task<IActionResult> LoginAsync([FromBody] UserAuthModel userAuthModel)
{
var id = await UserService.CheckPasswordAsync(userAuthModel.Username, userAuthModel.Password);
if (id != null)
{
await UserService.HttpCookieSignInAsync(id.Value);
return NoContent();
}
return BadRequest();
}
}
}
20 changes: 20 additions & 0 deletions Data/Entities/Score.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace Mastermind.Api.Data.Entities
{
public class Score
{
public int Id { get; set; }
public Guid GameId { get; set; }
public DateTimeOffset GameStarted { get; set; }
public int KeyLength { get; set; }
public double DurationInSeconds { get; set; }
public Guid PlayerId { get; set; }
public User Player { get; set; } = null!;
public int GuessesMade { get; set; }
public int PossibleValues { get; set; }
public int MaximumPossibleGuesses { get; set; }
public bool AllowDuplicates { get; set; }
public bool Won { get; set; }
}
}
13 changes: 13 additions & 0 deletions Data/Entities/User.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;

namespace Mastermind.Api.Data.Entities
{
public class User
{
public Guid Id { get; set; }
public string Username { get; set; } = null!;
public string PasswordHash { get; set; } = null!;
public ICollection<Score> UserScores { get; set; } = null!;
}
}
30 changes: 30 additions & 0 deletions Data/MastermindDbContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Mastermind.Api.Data.Entities;
using Microsoft.EntityFrameworkCore;

namespace Mastermind.Api.Data
{
public class MastermindDbContext : DbContext
{
public MastermindDbContext(DbContextOptions<MastermindDbContext> options)
: base(options)
{
}

public DbSet<User> Users { get; set; } = null!;
public DbSet<Score> Scores { get; set; } = null!;

protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Score>(e =>
{
e.HasIndex(s => s.Won);
e.HasIndex(s => new { s.KeyLength, s.PossibleValues, s.MaximumPossibleGuesses, s.GuessesMade, s.DurationInSeconds });
});

builder.Entity<User>(e =>
{
e.HasIndex(u => u.Username).IsUnique();
});
}
}
}
105 changes: 105 additions & 0 deletions Data/Migrations/20200406101101_InitialMastermindSchema.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

82 changes: 82 additions & 0 deletions Data/Migrations/20200406101101_InitialMastermindSchema.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;

namespace Mastermind.Api.Data.Migrations
{
public partial class InitialMastermindSchema : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<Guid>(nullable: false),
Username = table.Column<string>(nullable: false),
PasswordHash = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
});

migrationBuilder.CreateTable(
name: "Scores",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
GameId = table.Column<Guid>(nullable: false),
GameStarted = table.Column<DateTimeOffset>(nullable: false),
KeyLength = table.Column<int>(nullable: false),
DurationInSeconds = table.Column<double>(nullable: false),
PlayerId = table.Column<Guid>(nullable: false),
GuessesMade = table.Column<int>(nullable: false),
PossibleValues = table.Column<int>(nullable: false),
MaximumPossibleGuesses = table.Column<int>(nullable: false),
AllowDuplicates = table.Column<bool>(nullable: false),
Won = table.Column<bool>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Scores", x => x.Id);
table.ForeignKey(
name: "FK_Scores_Users_PlayerId",
column: x => x.PlayerId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});

migrationBuilder.CreateIndex(
name: "IX_Scores_PlayerId",
table: "Scores",
column: "PlayerId");

migrationBuilder.CreateIndex(
name: "IX_Scores_Won",
table: "Scores",
column: "Won");

migrationBuilder.CreateIndex(
name: "IX_Scores_KeyLength_PossibleValues_MaximumPossibleGuesses_GuessesMade_DurationInSeconds",
table: "Scores",
columns: new[] { "KeyLength", "PossibleValues", "MaximumPossibleGuesses", "GuessesMade", "DurationInSeconds" });

migrationBuilder.CreateIndex(
name: "IX_Users_Username",
table: "Users",
column: "Username",
unique: true);
}

protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Scores");

migrationBuilder.DropTable(
name: "Users");
}
}
}
Loading

0 comments on commit 24f4b8e

Please sign in to comment.