Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/test user #23

Merged
merged 10 commits into from
Sep 13, 2024
10 changes: 6 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /build

ENV DOTNET_NUGET_SIGNATURE_VERIFICATION=false
RUN apt-get update && \
apt-get install -y \
curl \
vim \
nano

# Copy csproj and restore as distinct layers
COPY ["TumbleBackend/*.csproj", "TumbleBackend/"]
RUN dotnet restore "TumbleBackend/TumbleBackend.csproj"
Expand All @@ -17,13 +22,10 @@ RUN dotnet publish "TumbleBackend.csproj" -c Release -o /app/publish

# Stage 2: Prepare the runtime image
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS final
ENV DOTNET_NUGET_SIGNATURE_VERIFICATION=false

WORKDIR /app
COPY --from=build /app/publish .

# Open port 443 for SSL/TLS
EXPOSE 80
EXPOSE 7036

ENTRYPOINT ["dotnet", "TumbleBackend.dll"]
8 changes: 5 additions & 3 deletions KronoxAPI/Utilities/MultiRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ public class MultiRequest
public MultiRequest(int timeout = 5)
{
var httpClientHandler = new HttpClientHandler();
client = new HttpClient(httpClientHandler, false);
client.Timeout = TimeSpan.FromSeconds(timeout);
client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36");
client = new HttpClient(httpClientHandler, false)
{
Timeout = TimeSpan.FromSeconds(timeout)
};
//client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36");
adisve marked this conversation as resolved.
Show resolved Hide resolved
}

/// <summary>
Expand Down
37 changes: 18 additions & 19 deletions Models/ResponseModels/UserEventCollection.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Text.Json.Serialization;
using KronoxAPI.Model.Users;

namespace WebAPIModels.ResponseModels;

public class UserEventCollection
namespace WebAPIModels.ResponseModels
{
private readonly List<UpcomingUserEvent> _upcomingEvents;
private readonly List<AvailableUserEvent> _registeredEvents;
private readonly List<AvailableUserEvent> _unregisteredEvents;
public class UserEventCollection
{
// Use public properties for JSON deserialization
public List<UpcomingUserEvent> UpcomingEvents { get; set; }

public List<UpcomingUserEvent> UpcomingEvents => _upcomingEvents;
public List<AvailableUserEvent> RegisteredEvents { get; set; }

public List<AvailableUserEvent> RegisteredEvents => _registeredEvents;
public List<AvailableUserEvent> UnregisteredEvents { get; set; }

public List<AvailableUserEvent> UnregisteredEvents => _unregisteredEvents;
// Parameterless constructor is required for deserialization
public UserEventCollection() { }

public UserEventCollection(List<UpcomingUserEvent> upcomingUserEvents, List<AvailableUserEvent> registeredUserEvents, List<AvailableUserEvent> unregisteredUserEvents)
{
_upcomingEvents = upcomingUserEvents;
_registeredEvents = registeredUserEvents;
_unregisteredEvents = unregisteredUserEvents;
}
public UserEventCollection(List<UpcomingUserEvent> upcomingUserEvents, List<AvailableUserEvent> registeredUserEvents, List<AvailableUserEvent> unregisteredUserEvents)
{
UpcomingEvents = upcomingUserEvents;
RegisteredEvents = registeredUserEvents;
UnregisteredEvents = unregisteredUserEvents;
}

public string ToJson() => JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
public string ToJson() => JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
}
}
7 changes: 2 additions & 5 deletions TumbleBackend/Controllers/AdminController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,8 @@ public class AdminController : Controller
[HttpPut("notification")]
public async Task<IActionResult> SendMessage([FromServices] MobileMessagingClient messaging, [FromServices] IConfiguration configuration, [FromServices] IDbNewsService newsService, [FromHeader] string auth, [FromQuery] NotificationContent notificationContent)
{
string? adminPassword = configuration[UserSecrets.AdminPass] ?? Environment.GetEnvironmentVariable(EnvVar.AdminPass);

if (adminPassword == null)
throw new NullReferenceException("Ensure that AdminPass is defined in the environment.");

string? adminPassword = (configuration[UserSecrets.AdminPass] ?? Environment.GetEnvironmentVariable(EnvVar.AdminPass)) ?? throw new NullReferenceException("Ensure that AdminPass is defined in the environment.");

if (auth != adminPassword)
{
return Unauthorized();
Expand Down
26 changes: 22 additions & 4 deletions TumbleBackend/Controllers/UserController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
using TumbleBackend.Extensions;
using WebAPIModels.ResponseModels;
using WebAPIModels.RequestModels;
using KronoxAPI.Model.Users;
using KronoxAPI.Exceptions;
using TumbleBackend.Utilities;
using WebAPIModels.Extensions;
using TumbleBackend.InternalModels;
using TumbleBackend.StringConstants;
using TumbleBackend.ActionFilters;
using Microsoft.AspNetCore.Cors;
Expand All @@ -29,6 +27,19 @@ public UserController(ILogger<UserController> logger)
_logger = logger;
}

/// <summary>
/// Retrieves a KronoxUser object for the user with the provided refreshToken. If the user is a test user, a test user object is returned with mock data upon further requests.
/// </summary>
/// <param name="jwtUtil"></param>
/// <param name="schoolId"></param>
/// <param name="refreshToken"></param>
/// <returns></returns> <summary>
///
/// </summary>
/// <param name="jwtUtil"></param>
/// <param name="schoolId"></param>
/// <param name="refreshToken"></param>
/// <returns></returns>
[HttpGet]
public async Task<IActionResult> GetKronoxUserAsync([FromServices] JwtUtil jwtUtil, [FromQuery] SchoolEnum schoolId, [FromHeader(Name = "X-auth-token")] string refreshToken)
{
Expand Down Expand Up @@ -63,11 +74,18 @@ public async Task<IActionResult> GetKronoxUserAsync([FromServices] JwtUtil jwtUt
}
}

/// <summary>
/// Logs in a user with the provided username and password. If the user is a test user, a test user object is returned with mock data upon further requests.
/// </summary>
/// <param name="jwtUtil"></param>
/// <param name="testUserUtil"></param>
/// <param name="schoolId"></param>
/// <param name="body"></param>
/// <returns></returns>
[HttpPost("login")]
public async Task<IActionResult> LoginKronoxUserAsync([FromServices] JwtUtil jwtUtil, [FromQuery] SchoolEnum schoolId, [FromBody] LoginRequest body)
{
var kronoxReqClient = (IKronoxRequestClient)HttpContext.Items[KronoxReqClientKeys.SingleClient]!;
var school = schoolId.GetSchool()!;

try
{
Expand All @@ -77,11 +95,11 @@ public async Task<IActionResult> LoginKronoxUserAsync([FromServices] JwtUtil jwt
return StatusCode(StatusCodes.Status500InternalServerError, new Error("There was an unknown error while fetching user data from Kronox."));

var newRefreshToken = jwtUtil.GenerateRefreshToken(body.Username, body.Password);

SessionDetails sessionDetails = new(kronoxUser.SessionToken, kronoxReqClient.BaseUrl!.ToString());

Response.Headers.Add("X-auth-token", newRefreshToken);
Response.Headers.Add("X-session-token", sessionDetails.ToJson());

return Ok(kronoxUser.ToWebModel(newRefreshToken, "", sessionDetails));
}
catch (LoginException e)
Expand Down
Loading