initial commit
All checks were successful
Build and Publish / Build Yale Access Backend (push) Successful in 28s
Build and Publish / Build Yale Access Frontend (push) Successful in 47s
Build and Publish / Push Yale Access Backend Docker Image (push) Successful in 9s
Build and Publish / Push Yale Access Frontend Docker Image (push) Successful in 10s

This commit is contained in:
2025-01-10 08:37:18 +11:00
commit f577617b4d
80 changed files with 10113 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Serilog;
using System.Security.Claims;
using YaleAccess.Models;
namespace YaleAccess.Controllers
{
[ApiController]
[Route("api/[controller]")]
[EnableCors]
[Authorize]
public class AuthenticationController : ControllerBase
{
private readonly Models.Options.AuthenticationOptions _authenticationOptions;
public AuthenticationController(IOptions<Models.Options.AuthenticationOptions> authenticationOptions)
{
_authenticationOptions = authenticationOptions.Value;
}
[HttpPost("login")]
[AllowAnonymous]
public async Task<IActionResult> Login([FromBody] string password)
{
try
{
// Check if the password is correct
if (password != _authenticationOptions.Password)
{
return Unauthorized(new ApiResponse("Incorrect password."));
}
// Log the user in
List<Claim> claims = new()
{
new Claim(ClaimTypes.Name, "YaleAccess")
};
ClaimsIdentity claimsIdentity = new(claims, CookieAuthenticationDefaults.AuthenticationScheme);
ClaimsPrincipal claimsPrincipal = new(claimsIdentity);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal);
// Return the response
return Ok(new ApiResponse(true));
}
catch(Exception ex)
{
Log.Logger.Error(ex, "An error occurred logging in.");
return BadRequest(new ApiResponse("An error occurred logging in."));
}
}
[HttpPost("logout")]
[AllowAnonymous]
public async Task<IActionResult> Logout()
{
try
{
// Sign the user out
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return Ok(new ApiResponse(true));
}
catch (Exception ex)
{
Log.Logger.Error(ex, "An error occured logging out.");
return BadRequest(new ApiResponse("An error occured logging out."));
}
}
}
}

View File

@@ -0,0 +1,22 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Serilog;
namespace YaleAccess.Controllers
{
[ApiController]
[Route("api/[controller]")]
[EnableCors]
[Authorize]
public class HealthController : ControllerBase
{
[HttpGet]
[AllowAnonymous]
public IActionResult Health()
{
Log.Logger.Information("Hit the health endpoint.");
return Ok("Service is healthy");
}
}
}

View File

@@ -0,0 +1,84 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Serilog;
using YaleAccess.Data;
using YaleAccess.Models;
namespace YaleAccess.Controllers
{
[ApiController]
[Route("api/[controller]")]
[EnableCors]
[Authorize]
public class PeopleController : ControllerBase
{
private readonly YaleContext _context;
public PeopleController(YaleContext context)
{
_context = context;
}
[HttpGet]
public async Task<IActionResult> GetPeople()
{
try
{
// Return all people
List<Person> people = await _context.People.ToListAsync();
return Ok(new ApiResponse(people));
}
catch (Exception ex)
{
Log.Logger.Error(ex, "An error occured retriving the people.");
return BadRequest(new ApiResponse("An error occured retriving the people."));
}
}
[HttpPost]
public async Task<IActionResult> CreatePerson([FromBody] Person person)
{
try
{
// Create a new person
Person newPerson = new() { Name = person.Name, PhoneNumber = person.PhoneNumber };
// Add the person
await _context.AddAsync(newPerson);
await _context.SaveChangesAsync();
// Return the newly created person
return Ok(new ApiResponse(newPerson));
}
catch (Exception ex)
{
Log.Logger.Error(ex, "An error occured creating the person.");
return BadRequest(new ApiResponse("An error occured creating the person."));
}
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeletePerson([FromRoute] int id)
{
try
{
// Ensure the person exists
Person person = await _context.People.FindAsync(id) ?? throw new Exception("Person not found.");
// Remove the person
_context.Remove(person);
await _context.SaveChangesAsync();
// Return the newly removed person
return Ok(new ApiResponse(person));
}
catch (Exception ex)
{
Log.Logger.Error(ex, "An error occured deletiong the person.");
return BadRequest(new ApiResponse("An error occured deletiong the person."));
}
}
}
}

View File

@@ -0,0 +1,148 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Serilog;
using YaleAccess.Models;
using YaleAccess.Models.Options;
using YaleAccess.Services;
using YaleAccess.Services.Interfaces;
namespace YaleAccess.Controllers
{
[ApiController]
[Route("api/[controller]")]
[EnableCors]
[Authorize]
public class YaleController : ControllerBase
{
private readonly IYaleAccessor _yaleAccessor;
private readonly CodesOptions _codeOptions;
private readonly SMSService _smsService;
public YaleController(IYaleAccessor yaleAccessor, IOptions<CodesOptions> codeOptions, SMSService smsService)
{
_yaleAccessor = yaleAccessor;
_codeOptions = codeOptions.Value;
_smsService = smsService;
}
[HttpGet("codes")]
public async Task<IActionResult> GetUserCodes()
{
try
{
// Get the home code first
YaleUserCode homeCode = await _yaleAccessor.GetCodeInformationAsync(_codeOptions.Home);
homeCode.IsHome = true;
// Get the guest codes
List<YaleUserCode> guestCodes = new();
foreach (int code in Enumerable.Range(_codeOptions.GuestCodeRangeStart, _codeOptions.GuestCodeRangeCount))
{
guestCodes.Add(await _yaleAccessor.GetCodeInformationAsync(code));
}
// Add the home code to the list
guestCodes.Add(homeCode);
// Return the codes
return Ok(new ApiResponse(guestCodes));
}
catch(Exception ex)
{
Log.Logger.Error(ex, "An error occurred retriving the codes.");
return BadRequest(new ApiResponse("An error occurred retriving the codes."));
}
}
[HttpPost("code/{id}")]
public async Task<IActionResult> SetUserCode([FromRoute] int id, [FromBody] string newCode)
{
try
{
// First validate the user code
string validCode = YaleAccessor.ValidateCode(newCode);
if (validCode != string.Empty)
{
return BadRequest(new ApiResponse(validCode));
}
// Set the new code
bool result = await _yaleAccessor.SetUserCode(id, newCode);
// Return the result
if (result)
{
Log.Logger.Information("Updated code for user {id} to {code}", id, newCode);
return Ok(new ApiResponse(true));
}
else
{
Log.Logger.Information("Failed to update code for user {id} to {code}", id, newCode);
return BadRequest(new ApiResponse("An error occurred setting the code."));
}
}
catch (Exception ex)
{
Log.Logger.Error(ex, "An error occurred setting the code.");
return BadRequest(new ApiResponse("An error occurred setting the code."));
}
}
[HttpPost("code/{id}/status")]
public async Task<IActionResult> SetUserCodeStatusAsAvailable([FromRoute] int id)
{
try
{
// First validate the user code
string validCode = YaleAccessor.ValidateClearCode(id, _codeOptions.Home);
if (validCode != string.Empty)
{
return BadRequest(new ApiResponse(validCode));
}
// Set the available status
bool result = await _yaleAccessor.SetCodeAsAvailable(id);
// Return the result
if (result)
{
Log.Logger.Information("Updated code status for user {id} to available", id);
return Ok(new ApiResponse(true));
}
else
{
Log.Logger.Information("Failed to update code status for user {id} to available", id);
return BadRequest(new ApiResponse("An error occurred setting the code status."));
}
}
catch (Exception ex)
{
Log.Logger.Error(ex, "An error occurred setting the code status.");
return BadRequest(new ApiResponse("An error occurred setting the code status."));
}
}
[HttpPost("code/{id}/send")]
public async Task<IActionResult> SendUserCode([FromRoute] int id, [FromBody] string phoneNumber)
{
try
{
// Get the user code
YaleUserCode userCode = await _yaleAccessor.GetCodeInformationAsync(id);
// Send the code via SMS to the phone number
await _smsService.SendCodeViaSMSAsync(userCode.Code, phoneNumber);
// Return success
return Ok(new ApiResponse(true));
}
catch (Exception ex)
{
Log.Logger.Error(ex, "An error occurred sending the code.");
return BadRequest(new ApiResponse("An error occurred sending the code."));
}
}
}
}