Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,8 @@ MigrationBackup/
# Fody - auto-generated XML schema
FodyWeavers.xsd

Migrations/

*/**/appsettings.json
*/**/appsettings.Development.json
*/**/bin/Debug
Expand Down
1 change: 1 addition & 0 deletions api-cinema-challenge/api-cinema-challenge.sln
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3C371BAA-344D-4C8A-AF08-7829816D726F}"
ProjectSection(SolutionItems) = preProject
..\.gitignore = ..\.gitignore
api-cinema-challenge\Data\Cinema ERD.png = api-cinema-challenge\Data\Cinema ERD.png
..\README.md = ..\README.md
EndProjectSection
EndProject
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
using api_cinema_challenge.Models;
using api_cinema_challenge.Models.Enums;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using api_cinema_challenge.Data;
using api_cinema_challenge.DataTransfer.Requests;
using api_cinema_challenge.DataTransfer.Response;
using api_cinema_challenge.Services;

namespace api_cinema_challenge.Controllers
{

[ApiController]
[Route("/api/[controller]")]
public class UsersController : ControllerBase
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly CinemaContext _context;
private readonly TokenService _tokenService;

public UsersController(UserManager<ApplicationUser> userManager, CinemaContext context,
TokenService tokenService, ILogger<UsersController> logger)
{
_userManager = userManager;
_context = context;
_tokenService = tokenService;
}


[HttpPost]
[Route("register")]
public async Task<IActionResult> Register(RegistrationRequest request)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

var result = await _userManager.CreateAsync(
new ApplicationUser { UserName = request.Username, Email = request.Email, Role = request.Role },
request.Password!
);

if (result.Succeeded)
{
request.Password = "";
return CreatedAtAction(nameof(Register), new { email = request.Email, role = Role.User }, request);
}

foreach (var error in result.Errors)
{
ModelState.AddModelError(error.Code, error.Description);
}

return BadRequest(ModelState);
}


[HttpPost]
[Route("login")]
public async Task<ActionResult<AuthResponse>> Authenticate([FromBody] AuthRequest request)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

var managedUser = await _userManager.FindByEmailAsync(request.Email!);

if (managedUser == null)
{
return BadRequest("Bad credentials");
}

var isPasswordValid = await _userManager.CheckPasswordAsync(managedUser, request.Password!);

if (!isPasswordValid)
{
return BadRequest("Bad credentials");
}

var userInDb = _context.Users.FirstOrDefault(u => u.Email == request.Email);

if (userInDb is null)
{
return Unauthorized();
}

var accessToken = _tokenService.CreateToken(userInDb);
await _context.SaveChangesAsync();

return Ok(new AuthResponse
{
Username = userInDb.UserName,
Email = userInDb.Email,
Token = accessToken,
});
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 15 additions & 1 deletion api-cinema-challenge/api-cinema-challenge/Data/CinemaContext.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Linq;
using api_cinema_challenge.Models;
using System.Security.Claims;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;

namespace api_cinema_challenge.Data
{
public class CinemaContext : DbContext
public class CinemaContext : IdentityUserContext<ApplicationUser>
{
private string _connectionString;
public CinemaContext(DbContextOptions<CinemaContext> options) : base(options)
Expand All @@ -20,7 +23,18 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
Seeder seeder = new Seeder();

modelBuilder.Entity<Customer>().HasData(seeder.Customers);
modelBuilder.Entity<Movie>().HasData(seeder.Movies);
modelBuilder.Entity<Screening>().HasData(seeder.Screenings);
modelBuilder.Entity<Ticket>().HasData(seeder.Tickets);
base.OnModelCreating(modelBuilder);
}
public DbSet<Customer> Customers { get; set; }
public DbSet<Movie> Movies { get; set; }
public DbSet<Screening> Screenings { get; set; }
public DbSet<Ticket> Tickets { get; set; }

}
}
145 changes: 145 additions & 0 deletions api-cinema-challenge/api-cinema-challenge/Data/Seeder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
using api_cinema_challenge.Models;
using api_cinema_challenge.Models.Enums;

namespace api_cinema_challenge.Data
{
public class Seeder
{
private List<string> _firstNames = new List<string>()
{
"Audrey",
"Donald",
"Elvis",
"Barack",
"Oprah",
"Jimi",
"Mick",
"Kate",
"Charles",
"Kate"
};

private List<string> _lastNames = new List<string>()
{
"Hepburn",
"Trump",
"Presley",
"Obama",
"Winfrey",
"Hendrix",
"Jagger",
"Winslet",
"Windsor",
"Middleton"
};

private List<string> _domains = new List<string>()
{
"gmail.com",
"google.com",
"hotmail.com",
"something.com",
"mcdonalds.com",
"nasa.org.us",
"gov.us",
"gov.gr",
"gov.nl",
"gov.ru"
};

private List<string> _movieTitles = new List<string>()
{
"The Lost Kingdom", "Space Odyssey", "Dreamcatcher",
"Ocean Deep", "Hidden Truths", "Shadows Rising",
"Eternal Flame", "The Great Escape", "Parallel Worlds", "Infinite Loop"
};

private List<string> _descriptions = new List<string>()
{
"An epic adventure across unknown lands.",
"A thrilling journey through space and time.",
"A heartwarming story of friendship and courage.",
"A suspenseful drama filled with mystery.",
"A hilarious comedy for the whole family.",
"A dark tale of betrayal and survival."
};

private List<Customer> _customers = new List<Customer>();
private List<Movie> _movies = new List<Movie>();
private List<Screening> _screenings = new List<Screening>();
private List<Ticket> _tickets = new List<Ticket>();

public Seeder()
{
Random random = new Random();

for (int x = 1; x < 50; x++)
{
var first = _firstNames[random.Next(_firstNames.Count)];
var last = _lastNames[random.Next(_lastNames.Count)];
var domain = _domains[random.Next(_domains.Count)];

Customer customer = new Customer
{
Id = x,
Name = $"{first} {last}",
Email = $"{first}{last}@{domain}",
Phone = $"06{random.Next(1000, 9999)}{random.Next(1000, 9999)}"
};
_customers.Add(customer);
}

for (int y = 1; y < 50; y++)
{
Movie movie = new Movie
{
Id = y,
Title = _movieTitles[random.Next(_movieTitles.Count)],
Rating = (MovieRating)random.Next(Enum.GetNames(typeof(MovieRating)).Length),
Description = _descriptions[random.Next(_descriptions.Count)],
RuntimeMins = random.Next(90, 180)
};
_movies.Add(movie);
}

foreach (var movie in _movies)
{
int screeningsAmount = random.Next(1, 5);
for (int z = 0; z < screeningsAmount; z++)
{
Screening screening = new Screening
{
Id = z,
MovieId = movie.Id,
ScreenNumber = random.Next(1, 5),
Capacity = random.Next(20, 60),
startsAt = DateTime.UtcNow.AddDays(random.Next(1, 15))
};
}
}

foreach (var screening in _screenings)
{
int ticketsAmount = random.Next(1, 60);
for (int a = 0; a < ticketsAmount; a++)
{
var customer = _customers[random.Next(_customers.Count)];

Ticket ticket = new Ticket
{
Id = a,
NumSeats = random.Next(1, 5),
ScreeningId = screening.Id,
CustomerId = customer.Id
};
_tickets.Add(ticket);
}
}
}

public List<Customer> Customers { get { return _customers; } }
public List<Movie> Movies { get { return _movies; } }
public List<Screening> Screenings { get { return _screenings; } }
public List<Ticket> Tickets { get { return _tickets; } }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace api_cinema_challenge.DataTransfer.Requests
{
public class AuthRequest
{
public string? Email { get; set; }
public string? Password { get; set; }

public bool IsValid()
{
return true;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace api_cinema_challenge.DataTransfer.Requests
{
public class CustomerPostRequest
{
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using api_cinema_challenge.Models;
using api_cinema_challenge.Models.Enums;
using Npgsql.PostgresTypes;

namespace api_cinema_challenge.DataTransfer.Requests
{
public class MoviePostRequest
{
public string Title { get; set; }
public MovieRating Rating { get; set; }
public string Description { get; set; }
public int RuntimeMins { get; set; }
public List<Screening> screenings { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using api_cinema_challenge.Models.Enums;
using System.ComponentModel.DataAnnotations;

namespace api_cinema_challenge.DataTransfer.Requests
{
public class RegistrationRequest
{
[Required]
public string? Email { get; set; }

[Required]
public string? Username { get { return this.Email; } set { } }

[Required]
public string? Password { get; set; }

public Role Role { get; set; } = Role.User;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using api_cinema_challenge.Models;
using Npgsql.PostgresTypes;

namespace api_cinema_challenge.DataTransfer.Requests
{
public class ScreenPostRequest
{
public int ScreenNumber { get; set; }
public int Capacity { get; set; }
public DateTime StartsAt { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace api_cinema_challenge.DataTransfer.Requests
{
public class TicketPostRequest
{
public int NumSeats { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace api_cinema_challenge.DataTransfer.Response
{
public class AuthResponse
{
public string? Username { get; set; }
public string? Email { get; set; }
public string? Token { get; set; }
}
}
Loading