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

382: Comments DTOs in API #553

Merged
merged 3 commits into from
Apr 22, 2024
Merged
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
4 changes: 4 additions & 0 deletions FU.API/FU.API/DTOs/Chat/ChatResponseDTO.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
namespace FU.API.DTOs.Chat;

/// <summary>
/// The response DTO for chat.
/// Members is a collection of usernames.
/// </summary>
public class ChatResponseDTO
{
public int Id { get; set; }
Expand Down
4 changes: 4 additions & 0 deletions FU.API/FU.API/DTOs/Chat/MessageResponseDTO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

using FU.API.Models;

/// <summary>
/// The response DTO for message.
/// Sender is the user who sent the message, and contains the username and avatar.
/// </summary>
public class MessageResponseDTO
{
public int Id { get; set; }
Expand Down
4 changes: 4 additions & 0 deletions FU.API/FU.API/DTOs/Game/GameDTO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
using FU.API.Validation;
using System.ComponentModel.DataAnnotations;

/// <summary>
/// The DTO for creating/retrieving games.
/// Name is the name of the game.
/// </summary>
public class GameDTO
{
public int Id { get; set; }
Expand Down
4 changes: 4 additions & 0 deletions FU.API/FU.API/DTOs/Game/UpdateGameDTO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
using FU.API.Validation;
using System.ComponentModel.DataAnnotations;

/// <summary>
/// The DTO for updating games.
/// Only Name and ImageUrl can be updated.
/// </summary>
public class UpdateGameDTO
{
[NonEmptyString]
Expand Down
4 changes: 4 additions & 0 deletions FU.API/FU.API/DTOs/LoginRequestDTO.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
namespace FU.API.DTOs;

/// <summary>
/// The request DTO for login.
/// Used for logging in.
/// </summary>
public class LoginRequestDTO
{
public string Username { get; set; } = string.Empty;
Expand Down
5 changes: 5 additions & 0 deletions FU.API/FU.API/DTOs/Post/PostRequestDTO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
using FU.API.Validation;
using System.ComponentModel.DataAnnotations;

/// <summary>
/// The DTO for creating posts.
/// Needs a title and a gameId.
/// TagIds is a list of tag ids.
/// </summary>
public class PostRequestDTO
{
[NonEmptyString]
Expand Down
7 changes: 7 additions & 0 deletions FU.API/FU.API/DTOs/Post/PostResponseDTO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
using FU.API.DTOs.Chat;
using FU.API.Models;

/// <summary>
/// The response DTO for post.
/// May contain reference to the last message in the chat.
/// Includes the creator of the post.
/// Include the game name, and list of tag names.
/// Indicates if the current user has joined the post.
/// </summary>
public class PostResponseDTO
{
public int Id { get; set; }
Expand Down
4 changes: 4 additions & 0 deletions FU.API/FU.API/DTOs/ResendConfirmationDTO.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
namespace FU.API.DTOs;

/// <summary>
/// The DTO for resending a confirmation email.
/// May be trying to find the user by email or username.
/// </summary>
public class ResendConfirmationDTO
{
public string? Email { get; set; }
Expand Down
5 changes: 5 additions & 0 deletions FU.API/FU.API/DTOs/Search/PostSearchRequestDTO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ namespace FU.API.DTOs.Search;

using Microsoft.AspNetCore.Mvc;

/// <summary>
/// Represents a request to search for posts.
/// All properties are optional.
/// Will be converted to a PostQuery.
/// </summary>
public record PostSearchRequestDTO
{
[FromQuery]
Expand Down
5 changes: 5 additions & 0 deletions FU.API/FU.API/DTOs/Search/UserSearchRequestDTO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ namespace FU.API.DTOs.Search;

using Microsoft.AspNetCore.Mvc;

/// <summary>
/// The request DTO for searching for users.
/// All properties are optional.
/// Will be converted to a UserQuery.
/// </summary>
public record UserSearchRequestDTO
{
[FromQuery]
Expand Down
4 changes: 4 additions & 0 deletions FU.API/FU.API/DTOs/Tag/TagRequestDTO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
using System.ComponentModel.DataAnnotations;
using FU.API.Validation;

/// <summary>
/// The DTO for creating tags.
/// Tag names can't be longer than 20 characters.
/// </summary>
public class TagRequestDTO
{
[NoSpaces]
Expand Down
4 changes: 4 additions & 0 deletions FU.API/FU.API/DTOs/Tag/TagResponseDTO.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
namespace FU.API.DTOs.Tag;

/// <summary>
/// The response DTO for tags.
/// Includes the tag's id and name.
/// </summary>
public class TagResponseDTO
{
public int Id { get; set; }
Expand Down
3 changes: 3 additions & 0 deletions FU.API/FU.API/DTOs/UpdateCredentialDTO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
using FU.API.Validation;
using System.ComponentModel.DataAnnotations;

/// <summary>
/// Used for updating credentials.
/// </summary>
public record UpdateCredentailsDTO
{
[NonEmptyString]
Expand Down
3 changes: 3 additions & 0 deletions FU.API/FU.API/DTOs/User/UserRelationDTO.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
namespace FU.API.DTOs.User;

/// <summary>
/// The response DTO for user relations.
/// </summary>
public class UserRelationDTO
{
public string Status { get; set; } = string.Empty;
Expand Down
180 changes: 128 additions & 52 deletions FU.API/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,76 @@
- Azure Communication Service is used to send emails
- Docker can be used for containerization

## Development

### External Requirements

In order to run the project you first have to install:

- [ASP.NET Core 7](https://learn.microsoft.com/en-us/aspnet/core/introduction-to-aspnet-core?view=aspnetcore-7.0)
- [PostgreSQL](https://www.postgresql.org/download/)

### Postgres Setup

Install and start the database by installing Docker and running the following command.

```
docker run --name postgres-490 -e POSTGRES_DB=fu_dev -e POSTGRES_PASSWORD=dev -e POSTGRES_USER=dev -p 5432:5432 postgres:alpine
```

To run the container at a later time, run:

```
docker container start postgres-490
```

Alternatively, install and start a PostgreSQL database manually.

### Config Setup

Config settings are loaded from the environment variables. To automatically load the environment variable from a file, create a `.env` file in this folder.

#### Blob storage

An azure storage account is needed with a storage container. Public anonymous access must be enabled. The `STORAGE_CONNECTION_STRING` and `AVATAR_CONTAINER_NAME` environment variables must be set.

```
STORAGE_CONNECTION_STRING="XXXXXXXX"
AVATAR_CONTAINER_NAME="some-container-name"
```

#### Jwt Secret

A random string of 32+ characters is required in the `JWT_SECRET` environment variable as a Jwt Secret.

```
JWT_SECRET="my-32-character-ultra-secure-and-ultra-long-secret"
```

#### Email service

An azure communication service is needed to send emails.

```
EMAIL_CONNECTION_STRING="XXXXXXXX"
```

#### Connect to Postgres

Set the postgres `CONNECTION_STRING` environment variable.

```
CONNECTION_STRING="Host=localhost; Database=fu_dev; Username=dev; Password=dev"
```

### Coding Style

Follow Google's C# [style guide](https://google.github.io/styleguide/csharp-style.html)

## Testing

Run tests on the backend with `dotnet test`. Tests are located in `FU.API.Tests/`. They consist of service unit tests as behavioral testing is done by the SPA.

## Understanding Controllers

The controllers serve as wrappers around the Services. They take an http request, run a corresponding service calls, and return an http result. For example consider the following `GameController` class.
Expand Down Expand Up @@ -73,72 +143,78 @@ When users navigate to a pages with a chat, they will be connected the chat grou

First an avatar is uploaded to the server via `AvatarController.UploadAvatar`. Then it is validated to be an image, cropped to be square, resized, and converted to a JPEG using the `SkiaSharp` library. Then the image is uploaded to a public azure storage blob and its a url is returned to the user for previewing. If the user wants to use the image, they call `UsersController.UpdateProfile` to set it as their new avatar. After awhile, unused profile pictures are deleted by `PeriodicRemoteStorageCleanerHostedService`.

## Development
## Understanding DTOs

### External Requirements
DTOs, or Data Transfer Objects, serve as simple objects that carry data between processes, typically between a client and a server.

In order to run the project you first have to install:
Consider the following DTO as an example:

- [ASP.NET Core 7](https://learn.microsoft.com/en-us/aspnet/core/introduction-to-aspnet-core?view=aspnetcore-7.0)
- [PostgreSQL](https://www.postgresql.org/download/)

### Postgres Setup

Install and start the database by installing Docker and running the following command.

```
docker run --name postgres-490 -e POSTGRES_DB=fu_dev -e POSTGRES_PASSWORD=dev -e POSTGRES_USER=dev -p 5432:5432 postgres:alpine
```
public record UserSearchRequestDTO
{
[FromQuery]
public string? Keywords { get; set; }

To run the container at a later time, run:
[FromQuery]
public string? Sort { get; set; }

```
docker container start postgres-490
```

Alternatively, install and start a PostgreSQL database manually.

### Config Setup

Config settings are loaded from the environment variables. To automatically load the environment variable from a file, create a `.env` file in this folder.

#### Blob storage

An azure storage account is needed with a storage container. Public anonymous access must be enabled. The `STORAGE_CONNECTION_STRING` and `AVATAR_CONTAINER_NAME` environment variables must be set.
[FromQuery]
public int? Limit { get; set; }

[FromQuery]
public int? Page { get; set; }
}
```
STORAGE_CONNECTION_STRING="XXXXXXXX"
AVATAR_CONTAINER_NAME="some-container-name"
```

In this example, UserSearchRequestDTO is a DTO used for handling user search requests. It contains properties for keywords, sorting criteria, pagination limits, and page numbers. The [FromQuery] attribute indicates that the properties should be bound from the query string when used in our ASP.NET Web API.

#### Jwt Secret

A random string of 32+ characters is required in the `JWT_SECRET` environment variable as a Jwt Secret.
To process the user search request, a static mapper class is utilized to convert the UserSearchRequestDTO to a UserQuery. Here's an example of how it's done:

```
JWT_SECRET="my-32-character-ultra-secure-and-ultra-long-secret"
```

#### Email service

An azure communication service is needed to send emails.
public static class Mapper
{
...
public static UserQuery ToUserQuery(this UserSearchRequestDTO dto)
{
var query = new UserQuery()
{
Limit = dto.Limit ?? 20,
Page = dto.Page ?? 1,
SortType = UserSortType.Username, // Default value
SortDirection = SortDirection.Ascending // Default value
};

// Splitting keywords if provided
if (dto.Keywords is not null)
{
query.Keywords = dto.Keywords.Split(" ").ToList();
}

```
EMAIL_CONNECTION_STRING="XXXXXXXX"
```
// Setting default sort if not provided
dto.Sort ??= "newest:desc";

#### Connect to Postgres
// Parsing and setting sort type and direction
var arr = dto.Sort.ToLower().Split(":");
query.SortType = arr[0] switch
{
"username" => UserSortType.Username,
"dob" => UserSortType.DOB,
"chatactivity" => UserSortType.ChatActivity,
_ => UserSortType.Username,
};

Set the postgres `CONNECTION_STRING` environment variable.
if (arr.Length > 1 && arr[1].StartsWith("desc"))
{
query.SortDirection = SortDirection.Descending;
}
else
{
query.SortDirection = SortDirection.Ascending;
}

return query;
}
}
```
CONNECTION_STRING="Host=localhost; Database=fu_dev; Username=dev; Password=dev"
```

### Coding Style

Follow Google's C# [style guide](https://google.github.io/styleguide/csharp-style.html)

## Testing

Run tests on the backend with `dotnet test`. Tests are located in `FU.API.Tests/`. They consist of service unit tests as behavioral testing is done by the SPA.
This static mapper class contains a method ToUserQuery which takes a UserSearchRequestDTO and converts it into a UserQuery object, which is then used in the search service to perform the actual search operation.
Loading