Add files via upload

This commit is contained in:
jeff_pro_gamer 2025-09-16 22:01:05 +03:00 committed by GitHub
commit 99a1189311
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
97 changed files with 26956 additions and 6939 deletions

View file

@ -1,135 +1,135 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of
any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at:
https://discord.gg/lbpunion
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of
any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at:
https://discord.gg/lbpunion
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

View file

@ -1,99 +1,99 @@
# Contributing
## Setting up MySQL
Project Lighthouse requires a MySQL database. For Linux users running docker, one can be set up using
the `docker-compose.yml` file in the root of the project folder.
Next, make sure the `LIGHTHOUSE_DB_CONNECTION_STRING` environment variable is set correctly. By default, it
is `server=127.0.0.1;uid=root;pwd=lighthouse;database=lighthouse`. If you are running the database via the
above `docker-compose.yml` you shouldn't need to change this. For other development/especially production environments
you will need to change this.
Once you've gotten MySQL running you can run Lighthouse. It will take care of the rest.
## Connecting (PS3)
You can use the Remote Patch utility in [UnionPatcher](https://github.com/LBPUnion/UnionPatcher) to manually patch your EBOOT.BIN; it works over the network and automatically downloads, decrypts, patches, encrypts, and uploads your PSN and Disc EBOOTs.
If you are not using a PS3, see [the RPCS3 section](#connecting-rpcs3).
## Connecting (RPCS3)
Start by getting a copy of LittleBigPlanet 1/2/3 installed. (Check the LittleBigPlanet 1 section, since you'll need to do
extra steps for your game to not crash upon entering the pod computer).
The game can be a digital copy (NPUA80472/NPUA80662/NPUA81116) or a disc copy (BCUS98148/BCUS98245/BCUS98362).
Next, download [UnionPatcher](https://github.com/LBPUnion/UnionPatcher/). Binaries can be found by reading the `README.md`
file.
You should have everything you need now, so open up RPCS3 and go to Utilities -> Decrypt PS3 Binaries. Point this
to `rpcs3/dev_hdd0/game/(title id)/USRDIR/EBOOT.BIN`. You can grab your title ID by right clicking the game in RPCS3 and
clicking Copy Info -> Copy Serial.
This should give you a file named `EBOOT.elf` in the same folder. This is your decrypted EBOOT.
Now that you have your decrypted EBOOT, open UnionPatcher and select the `EBOOT.elf` you got earlier in the top box,
enter `http://localhost:10060/LITTLEBIGPLANETPS3_XML` in the second, and the output filename in the third. For this
guide we'll use `EBOOTlocalhost.elf`.
Now, copy the `EBOOTlocalhost.elf` file to where you got your `EBOOT.elf` file from, and you're now good to go.
To launch the game with the patched EBOOT, open up RPCS3, go to File, Boot S(Elf), and open up `EBOOTlocalhost.elf`.
Assuming you patched the file correctly, the database is migrated, and
Project Lighthouse is running, the game should now connect, and you may begin contributing!
### LittleBigPlanet 1 (RPCS3)
For LittleBigPlanet 1 to work with RPCS3, follow the steps above normally.
First, open your favourite hex editor. We recommend [HxD](https://mh-nexus.de/en/hxd/).
Once you have a hex editor open, open your `EBOOTlocalhost.elf` file and search for the hex
values `73 63 65 4E 70 43 6F 6D 6D 65 72 63 65 32`. In HxD, this would be done by clicking on Search -> Replace,
clicking on the `Hex-values` tab, and entering the hex there.
Then, you can zero it out by replacing it with `00 00 00 00 00 00 00 00 00 00 00 00 00 00`.
What this does is remove all the references to the `sceNpCommerce2` function. The function is used for purchasing DLC,
which at this moment in time crashes RPCS3.
After saving the file your LBP1 EBOOT can be used with RPCS3.
## Contributing Tips
### Database migrations
Some modifications may require updates to the database schema. You can automatically create a migration file by:
1. Making sure the tools are installed. You can do this by running `dotnet tool restore`.
2. Making sure `LIGHTHOUSE_DB_CONNECTION_STRING` is set correctly. See the `Running` section for more details.
3. Modifying the database schema via the C# portion of the code. Do not modify the actual SQL database.
4. Running `dotnet ef migrations add <NameOfMigrationInPascalCase> --project ProjectLighthouse`.
This process will create a migration file from the changes made in the C# code.
The new migrations will automatically be applied upon starting Lighthouse.
### Running tests
You can run tests either through your IDE or by running `dotnet tests`.
Keep in mind while running database tests (which most tests are) you need to have `LIGHTHOUSE_DB_CONNECTION_STRING` set.
### Continuous Integration (CI) Tips
- You can skip CI runs for a commit if you specify `[skip ci]` at the beginning of the commit name. This is useful for
formatting changes, etc.
- When creating your first pull request, CI will not run initially. A team member will have to approve you for use of
running CI on a pull request. This is because of GitHub policy.
### API Documentation
You can access API documentation by looking at the XMLDoc in the controllers under `ProjectLighthouse.Controllers.Api`
You can also access an interactive version by starting Lighthouse and accessing Swagger
at `http://localhost:10060/swagger/index.html`.
# Contributing
## Setting up MySQL
Project Lighthouse requires a MySQL database. For Linux users running docker, one can be set up using
the `docker-compose.yml` file in the root of the project folder.
Next, make sure the `LIGHTHOUSE_DB_CONNECTION_STRING` environment variable is set correctly. By default, it
is `server=127.0.0.1;uid=root;pwd=lighthouse;database=lighthouse`. If you are running the database via the
above `docker-compose.yml` you shouldn't need to change this. For other development/especially production environments
you will need to change this.
Once you've gotten MySQL running you can run Lighthouse. It will take care of the rest.
## Connecting (PS3)
You can use the Remote Patch utility in [UnionPatcher](https://github.com/LBPUnion/UnionPatcher) to manually patch your EBOOT.BIN; it works over the network and automatically downloads, decrypts, patches, encrypts, and uploads your PSN and Disc EBOOTs.
If you are not using a PS3, see [the RPCS3 section](#connecting-rpcs3).
## Connecting (RPCS3)
Start by getting a copy of LittleBigPlanet 1/2/3 installed. (Check the LittleBigPlanet 1 section, since you'll need to do
extra steps for your game to not crash upon entering the pod computer).
The game can be a digital copy (NPUA80472/NPUA80662/NPUA81116) or a disc copy (BCUS98148/BCUS98245/BCUS98362).
Next, download [UnionPatcher](https://github.com/LBPUnion/UnionPatcher/). Binaries can be found by reading the `README.md`
file.
You should have everything you need now, so open up RPCS3 and go to Utilities -> Decrypt PS3 Binaries. Point this
to `rpcs3/dev_hdd0/game/(title id)/USRDIR/EBOOT.BIN`. You can grab your title ID by right clicking the game in RPCS3 and
clicking Copy Info -> Copy Serial.
This should give you a file named `EBOOT.elf` in the same folder. This is your decrypted EBOOT.
Now that you have your decrypted EBOOT, open UnionPatcher and select the `EBOOT.elf` you got earlier in the top box,
enter `http://localhost:10060/LITTLEBIGPLANETPS3_XML` in the second, and the output filename in the third. For this
guide we'll use `EBOOTlocalhost.elf`.
Now, copy the `EBOOTlocalhost.elf` file to where you got your `EBOOT.elf` file from, and you're now good to go.
To launch the game with the patched EBOOT, open up RPCS3, go to File, Boot S(Elf), and open up `EBOOTlocalhost.elf`.
Assuming you patched the file correctly, the database is migrated, and
Project Lighthouse is running, the game should now connect, and you may begin contributing!
### LittleBigPlanet 1 (RPCS3)
For LittleBigPlanet 1 to work with RPCS3, follow the steps above normally.
First, open your favourite hex editor. We recommend [HxD](https://mh-nexus.de/en/hxd/).
Once you have a hex editor open, open your `EBOOTlocalhost.elf` file and search for the hex
values `73 63 65 4E 70 43 6F 6D 6D 65 72 63 65 32`. In HxD, this would be done by clicking on Search -> Replace,
clicking on the `Hex-values` tab, and entering the hex there.
Then, you can zero it out by replacing it with `00 00 00 00 00 00 00 00 00 00 00 00 00 00`.
What this does is remove all the references to the `sceNpCommerce2` function. The function is used for purchasing DLC,
which at this moment in time crashes RPCS3.
After saving the file your LBP1 EBOOT can be used with RPCS3.
## Contributing Tips
### Database migrations
Some modifications may require updates to the database schema. You can automatically create a migration file by:
1. Making sure the tools are installed. You can do this by running `dotnet tool restore`.
2. Making sure `LIGHTHOUSE_DB_CONNECTION_STRING` is set correctly. See the `Running` section for more details.
3. Modifying the database schema via the C# portion of the code. Do not modify the actual SQL database.
4. Running `dotnet ef migrations add <NameOfMigrationInPascalCase> --project ProjectLighthouse`.
This process will create a migration file from the changes made in the C# code.
The new migrations will automatically be applied upon starting Lighthouse.
### Running tests
You can run tests either through your IDE or by running `dotnet tests`.
Keep in mind while running database tests (which most tests are) you need to have `LIGHTHOUSE_DB_CONNECTION_STRING` set.
### Continuous Integration (CI) Tips
- You can skip CI runs for a commit if you specify `[skip ci]` at the beginning of the commit name. This is useful for
formatting changes, etc.
- When creating your first pull request, CI will not run initially. A team member will have to approve you for use of
running CI on a pull request. This is because of GitHub policy.
### API Documentation
You can access API documentation by looking at the XMLDoc in the controllers under `ProjectLighthouse.Controllers.Api`
You can also access an interactive version by starting Lighthouse and accessing Swagger
at `http://localhost:10060/swagger/index.html`.

View file

@ -1,40 +1,40 @@
# Build stage
FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
WORKDIR /ProjectLighthouse
COPY *.sln ./
COPY **/*.csproj ./
RUN dotnet sln list | grep ".csproj" \
| while read -r line; do \
mkdir -p $(dirname $line); \
mv $(basename $line) $(dirname $line); \
done;
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release --property:OutputPath=/ProjectLighthouse/out/ --no-restore
# Final running container
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine AS final
# Add non-root user
RUN addgroup -S lighthouse --gid 1001 && \
adduser -S lighthouse -G lighthouse -h /lighthouse --uid 1001 && \
mkdir -p /lighthouse/data && \
mkdir -p /lighthouse/app && \
mkdir -p /lighthouse/temp && \
apk add --no-cache icu-libs su-exec tzdata
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
# Copy build files
COPY --from=build /ProjectLighthouse/out/publish /lighthouse/app
COPY --from=build /ProjectLighthouse/ProjectLighthouse/StaticFiles /lighthouse/temp/StaticFiles
COPY --from=build /ProjectLighthouse/scripts-and-tools/docker-entrypoint.sh /lighthouse
RUN chown -R lighthouse:lighthouse /lighthouse && \
chmod +x /lighthouse/docker-entrypoint.sh && \
cp /lighthouse/app/appsettings.json /lighthouse/temp
# Build stage
FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
WORKDIR /ProjectLighthouse
COPY *.sln ./
COPY **/*.csproj ./
RUN dotnet sln list | grep ".csproj" \
| while read -r line; do \
mkdir -p $(dirname $line); \
mv $(basename $line) $(dirname $line); \
done;
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release --property:OutputPath=/ProjectLighthouse/out/ --no-restore
# Final running container
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine AS final
# Add non-root user
RUN addgroup -S lighthouse --gid 1001 && \
adduser -S lighthouse -G lighthouse -h /lighthouse --uid 1001 && \
mkdir -p /lighthouse/data && \
mkdir -p /lighthouse/app && \
mkdir -p /lighthouse/temp && \
apk add --no-cache icu-libs su-exec tzdata
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
# Copy build files
COPY --from=build /ProjectLighthouse/out/publish /lighthouse/app
COPY --from=build /ProjectLighthouse/ProjectLighthouse/StaticFiles /lighthouse/temp/StaticFiles
COPY --from=build /ProjectLighthouse/scripts-and-tools/docker-entrypoint.sh /lighthouse
RUN chown -R lighthouse:lighthouse /lighthouse && \
chmod +x /lighthouse/docker-entrypoint.sh && \
cp /lighthouse/app/appsettings.json /lighthouse/temp
ENTRYPOINT ["/lighthouse/docker-entrypoint.sh"]

View file

@ -1,9 +1,9 @@
using Microsoft.AspNetCore.Mvc;
namespace LBPUnion.ProjectLighthouse.Servers.API;
[ApiController]
[Route("/api/v1")]
[Produces("application/json")]
public class ApiEndpointController : ControllerBase
using Microsoft.AspNetCore.Mvc;
namespace LBPUnion.ProjectLighthouse.Servers.API;
[ApiController]
[Route("/api/v1")]
[Produces("application/json")]
public class ApiEndpointController : ControllerBase
{ }

View file

@ -1,18 +1,18 @@
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Servers.API.Responses;
using Microsoft.AspNetCore.Mvc;
namespace LBPUnion.ProjectLighthouse.Servers.API.Controllers;
public class RpcController : ApiEndpointController
{
/// <summary>
/// Returns basic information that Discord RPC clients can use for self-configuration.
/// </summary>
/// <returns>RpcResponse</returns>
/// <response code="200">The RPC configuration.</response>
[HttpGet("rpc")]
[ProducesResponseType(typeof(RpcResponse), StatusCodes.Status200OK)]
public IActionResult GetRpcConfiguration() =>
this.Ok(RpcResponse.CreateFromConfiguration(ServerConfiguration.Instance.RichPresenceConfiguration));
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Servers.API.Responses;
using Microsoft.AspNetCore.Mvc;
namespace LBPUnion.ProjectLighthouse.Servers.API.Controllers;
public class RpcController : ApiEndpointController
{
/// <summary>
/// Returns basic information that Discord RPC clients can use for self-configuration.
/// </summary>
/// <returns>RpcResponse</returns>
/// <response code="200">The RPC configuration.</response>
[HttpGet("rpc")]
[ProducesResponseType(typeof(RpcResponse), StatusCodes.Status200OK)]
public IActionResult GetRpcConfiguration() =>
this.Ok(RpcResponse.CreateFromConfiguration(ServerConfiguration.Instance.RichPresenceConfiguration));
}

View file

@ -1,64 +1,64 @@
#nullable enable
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Servers.API.Responses;
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Servers.API.Controllers;
/// <summary>
/// A collection of endpoints relating to slots.
/// </summary>
public class SlotEndpoints : ApiEndpointController
{
private readonly DatabaseContext database;
public SlotEndpoints(DatabaseContext database)
{
this.database = database;
}
/// <summary>
/// Gets a list of (stripped down) slots from the database.
/// </summary>
/// <param name="limit">How many slots you want to retrieve.</param>
/// <param name="skip">How many slots to skip.</param>
/// <returns>The slot</returns>
/// <response code="200">The slot list, if successful.</response>
[HttpGet("slots")]
[ProducesResponseType(typeof(List<ApiSlot>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetSlots([FromQuery] int limit = 20, [FromQuery] int skip = 0)
{
if (skip < 0) skip = 0;
if (limit < 0) limit = 0;
limit = Math.Min(ServerStatics.PageSize, limit);
List<ApiSlot> minimalSlots = (await this.database.Slots.OrderByDescending(s => s.FirstUploaded)
.Skip(skip)
.Take(limit)
.ToListAsync()).ToSerializableList(MinimalApiSlot.CreateFromEntity);
return this.Ok(minimalSlots);
}
/// <summary>
/// Gets a slot (more commonly known as a level) and its information from the database.
/// </summary>
/// <param name="id">The ID of the slot</param>
/// <returns>The slot</returns>
/// <response code="200">The slot, if successful.</response>
/// <response code="404">The slot could not be found.</response>
[HttpGet("slot/{id:int}")]
[ProducesResponseType(typeof(ApiSlot), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetSlot(int id)
{
SlotEntity? slot = await this.database.Slots.FirstOrDefaultAsync(u => u.SlotId == id);
if (slot == null) return this.NotFound();
return this.Ok(ApiSlot.CreateFromEntity(slot, this.database));
}
#nullable enable
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Servers.API.Responses;
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Servers.API.Controllers;
/// <summary>
/// A collection of endpoints relating to slots.
/// </summary>
public class SlotEndpoints : ApiEndpointController
{
private readonly DatabaseContext database;
public SlotEndpoints(DatabaseContext database)
{
this.database = database;
}
/// <summary>
/// Gets a list of (stripped down) slots from the database.
/// </summary>
/// <param name="limit">How many slots you want to retrieve.</param>
/// <param name="skip">How many slots to skip.</param>
/// <returns>The slot</returns>
/// <response code="200">The slot list, if successful.</response>
[HttpGet("slots")]
[ProducesResponseType(typeof(List<ApiSlot>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetSlots([FromQuery] int limit = 20, [FromQuery] int skip = 0)
{
if (skip < 0) skip = 0;
if (limit < 0) limit = 0;
limit = Math.Min(ServerStatics.PageSize, limit);
List<ApiSlot> minimalSlots = (await this.database.Slots.OrderByDescending(s => s.FirstUploaded)
.Skip(skip)
.Take(limit)
.ToListAsync()).ToSerializableList(MinimalApiSlot.CreateFromEntity);
return this.Ok(minimalSlots);
}
/// <summary>
/// Gets a slot (more commonly known as a level) and its information from the database.
/// </summary>
/// <param name="id">The ID of the slot</param>
/// <returns>The slot</returns>
/// <response code="200">The slot, if successful.</response>
/// <response code="404">The slot could not be found.</response>
[HttpGet("slot/{id:int}")]
[ProducesResponseType(typeof(ApiSlot), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetSlot(int id)
{
SlotEntity? slot = await this.database.Slots.FirstOrDefaultAsync(u => u.SlotId == id);
if (slot == null) return this.NotFound();
return this.Ok(ApiSlot.CreateFromEntity(slot, this.database));
}
}

View file

@ -1,139 +1,139 @@
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Filter;
using LBPUnion.ProjectLighthouse.Filter.Filters;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Servers.API.Responses;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Servers.API.Controllers;
/// <summary>
/// A collection of endpoints relating to statistics.
/// </summary>
public class StatisticsEndpoints : ApiEndpointController
{
private readonly DatabaseContext database;
public StatisticsEndpoints(DatabaseContext database)
{
this.database = database;
}
/// <summary>
/// Gets everything that StatisticsHelper provides.
/// </summary>
/// <returns>An instance of StatisticsResponse</returns>
[HttpGet("statistics")]
[ProducesResponseType(typeof(StatisticsResponse), StatusCodes.Status200OK)]
public async Task<IActionResult> GetStatistics()
=> this.Ok
(
new StatisticsResponse
{
Photos = await StatisticsHelper.PhotoCount(this.database),
Slots = await StatisticsHelper.SlotCount(this.database, new SlotQueryBuilder()),
Users = await StatisticsHelper.UserCount(this.database),
RecentMatches = await StatisticsHelper.RecentMatches(this.database),
TeamPicks = await StatisticsHelper.SlotCount(this.database, new SlotQueryBuilder().AddFilter(new TeamPickFilter())),
}
);
private static readonly List<GameVersion> gameVersions = new()
{
GameVersion.LittleBigPlanet1,
GameVersion.LittleBigPlanet2,
GameVersion.LittleBigPlanet3,
GameVersion.LittleBigPlanetVita,
GameVersion.LittleBigPlanetPSP,
};
private static readonly List<Platform> platforms = new()
{
Platform.PS3,
Platform.RPCS3,
Platform.Vita,
Platform.PSP,
};
/// <summary>
/// Get player counts for each individual title
/// </summary>
/// <returns>An instance of PlayerCountByGameResponse</returns>
[HttpGet("playerCount")]
[HttpGet("playerCount/game")]
[ProducesResponseType(typeof(PlayerCountByGameResponse), StatusCodes.Status200OK)]
public async Task<IActionResult> GetPlayerCounts()
{
List<PlayerCountObject> gameList = new();
foreach (GameVersion version in gameVersions)
{
gameList.Add(new PlayerCountByGameObject
{
Game = version.ToString(),
PlayerCount = await StatisticsHelper.RecentMatches(this.database, l => l.GameVersion == version),
});
}
PlayerCountByGameResponse response = new()
{
TotalPlayerCount = await StatisticsHelper.RecentMatches(this.database),
Games = gameList,
};
return this.Ok(response);
}
/// <summary>
/// Get player counts for each individual platform
/// </summary>
/// <returns>An instance of PlayerCountByPlatformResponse</returns>
[HttpGet("playerCount/platform")]
[ProducesResponseType(typeof(PlayerCountByPlatformResponse), StatusCodes.Status200OK)]
public async Task<IActionResult> GetPlayerCountsByPlatform()
{
List<PlayerCountObject> platformList = new();
foreach (Platform platform in platforms)
{
platformList.Add(new PlayerCountByPlatformObject
{
Platform = platform.ToString(),
PlayerCount = await StatisticsHelper.RecentMatches(this.database, l => l.Platform == platform),
});
}
PlayerCountByPlatformResponse response = new()
{
TotalPlayerCount = await StatisticsHelper.RecentMatches(this.database),
Platforms = platformList,
};
return this.Ok(response);
}
/// <summary>
/// Gets a list of online players
/// </summary>
/// <returns>An instance of PlayerListResponse</returns>
[HttpGet("players")]
[ProducesResponseType(typeof(PlayerListResponse), StatusCodes.Status200OK)]
public async Task<IActionResult> GetPlayerList()
{
List<PlayerListObject> players = await this.database.LastContacts.Where(l => TimeHelper.Timestamp - l.Timestamp < 300)
.Select(l => new PlayerListObject
{
Username = l.User!.Username,
Game = l.GameVersion.ToString(),
Platform = l.Platform.ToString(),
})
.ToListAsync();
PlayerListResponse response = new()
{
Players = players,
};
return this.Ok(response);
}
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Filter;
using LBPUnion.ProjectLighthouse.Filter.Filters;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Servers.API.Responses;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Servers.API.Controllers;
/// <summary>
/// A collection of endpoints relating to statistics.
/// </summary>
public class StatisticsEndpoints : ApiEndpointController
{
private readonly DatabaseContext database;
public StatisticsEndpoints(DatabaseContext database)
{
this.database = database;
}
/// <summary>
/// Gets everything that StatisticsHelper provides.
/// </summary>
/// <returns>An instance of StatisticsResponse</returns>
[HttpGet("statistics")]
[ProducesResponseType(typeof(StatisticsResponse), StatusCodes.Status200OK)]
public async Task<IActionResult> GetStatistics()
=> this.Ok
(
new StatisticsResponse
{
Photos = await StatisticsHelper.PhotoCount(this.database),
Slots = await StatisticsHelper.SlotCount(this.database, new SlotQueryBuilder()),
Users = await StatisticsHelper.UserCount(this.database),
RecentMatches = await StatisticsHelper.RecentMatches(this.database),
TeamPicks = await StatisticsHelper.SlotCount(this.database, new SlotQueryBuilder().AddFilter(new TeamPickFilter())),
}
);
private static readonly List<GameVersion> gameVersions = new()
{
GameVersion.LittleBigPlanet1,
GameVersion.LittleBigPlanet2,
GameVersion.LittleBigPlanet3,
GameVersion.LittleBigPlanetVita,
GameVersion.LittleBigPlanetPSP,
};
private static readonly List<Platform> platforms = new()
{
Platform.PS3,
Platform.RPCS3,
Platform.Vita,
Platform.PSP,
};
/// <summary>
/// Get player counts for each individual title
/// </summary>
/// <returns>An instance of PlayerCountByGameResponse</returns>
[HttpGet("playerCount")]
[HttpGet("playerCount/game")]
[ProducesResponseType(typeof(PlayerCountByGameResponse), StatusCodes.Status200OK)]
public async Task<IActionResult> GetPlayerCounts()
{
List<PlayerCountObject> gameList = new();
foreach (GameVersion version in gameVersions)
{
gameList.Add(new PlayerCountByGameObject
{
Game = version.ToString(),
PlayerCount = await StatisticsHelper.RecentMatches(this.database, l => l.GameVersion == version),
});
}
PlayerCountByGameResponse response = new()
{
TotalPlayerCount = await StatisticsHelper.RecentMatches(this.database),
Games = gameList,
};
return this.Ok(response);
}
/// <summary>
/// Get player counts for each individual platform
/// </summary>
/// <returns>An instance of PlayerCountByPlatformResponse</returns>
[HttpGet("playerCount/platform")]
[ProducesResponseType(typeof(PlayerCountByPlatformResponse), StatusCodes.Status200OK)]
public async Task<IActionResult> GetPlayerCountsByPlatform()
{
List<PlayerCountObject> platformList = new();
foreach (Platform platform in platforms)
{
platformList.Add(new PlayerCountByPlatformObject
{
Platform = platform.ToString(),
PlayerCount = await StatisticsHelper.RecentMatches(this.database, l => l.Platform == platform),
});
}
PlayerCountByPlatformResponse response = new()
{
TotalPlayerCount = await StatisticsHelper.RecentMatches(this.database),
Platforms = platformList,
};
return this.Ok(response);
}
/// <summary>
/// Gets a list of online players
/// </summary>
/// <returns>An instance of PlayerListResponse</returns>
[HttpGet("players")]
[ProducesResponseType(typeof(PlayerListResponse), StatusCodes.Status200OK)]
public async Task<IActionResult> GetPlayerList()
{
List<PlayerListObject> players = await this.database.LastContacts.Where(l => TimeHelper.Timestamp - l.Timestamp < 300)
.Select(l => new PlayerListObject
{
Username = l.User!.Username,
Game = l.GameVersion.ToString(),
Platform = l.Platform.ToString(),
})
.ToListAsync();
PlayerListResponse response = new()
{
Players = players,
};
return this.Ok(response);
}
}

View file

@ -1,9 +1,9 @@
using Microsoft.AspNetCore.Mvc;
namespace LBPUnion.ProjectLighthouse.Servers.API.Controllers;
public class StatusController : ApiEndpointController
{
[AcceptVerbs("GET", "HEAD", Route = "status")]
public IActionResult GetStatus() => this.Ok();
using Microsoft.AspNetCore.Mvc;
namespace LBPUnion.ProjectLighthouse.Servers.API.Controllers;
public class StatusController : ApiEndpointController
{
[AcceptVerbs("GET", "HEAD", Route = "status")]
public IActionResult GetStatus() => this.Ok();
}

View file

@ -1,122 +1,122 @@
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Servers.API.Responses;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Servers.API.Controllers;
/// <summary>
/// A collection of endpoints relating to users.
/// </summary>
public class UserEndpoints : ApiEndpointController
{
private readonly DatabaseContext database;
public UserEndpoints(DatabaseContext database)
{
this.database = database;
}
/// <summary>
/// Gets a user and their information from the database.
/// </summary>
/// <param name="id">The ID of the user</param>
/// <returns>The user</returns>
/// <response code="200">The user, if successful.</response>
/// <response code="404">The user could not be found.</response>
[HttpGet("user/{id:int}")]
[ProducesResponseType(typeof(ApiUser), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetUser(int id)
{
UserEntity? user = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == id);
if (user == null) return this.NotFound();
return this.Ok(ApiUser.CreateFromEntity(user));
}
[HttpGet("username/{username}")]
[ProducesResponseType(typeof(ApiUser), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetUser(string username)
{
UserEntity? user = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
if (user == null) return this.NotFound();
return this.Ok(ApiUser.CreateFromEntity(user));
}
/// <summary>
/// Searches for the user based on the query
/// </summary>
/// <param name="query">The search query</param>
/// <returns>A list of users</returns>
/// <response code="200">The list of users, if any were found</response>
/// <response code="404">No users matched the query</response>
[HttpGet("search/user")]
[ProducesResponseType(typeof(ApiUser), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> SearchUsers(string query)
{
List<ApiUser> users = (await this.database.Users
.Where(u => u.PermissionLevel != PermissionLevel.Banned && u.Username.Contains(query))
.Where(u => u.ProfileVisibility == PrivacyType.All)
.OrderByDescending(b => b.UserId)
.Take(20)
.ToListAsync()).ToSerializableList(ApiUser.CreateFromEntity);
if (!users.Any()) return this.NotFound();
return this.Ok(users);
}
/// <summary>
/// Gets a user and their information from the database.
/// </summary>
/// <param name="id">The ID of the user</param>
/// <returns>The user's status</returns>
/// <response code="200">The user's status, if successful.</response>
/// <response code="404">The user could not be found.</response>
[HttpGet("user/{id:int}/status")]
[ProducesResponseType(typeof(ApiUser), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetUserStatus(int id)
{
UserStatus userStatus = new(this.database, id);
return this.Ok(userStatus);
}
[HttpPost("user/inviteToken")]
[HttpPost("user/inviteToken/{username}")]
public async Task<IActionResult> CreateUserInviteToken([FromRoute] string? username)
{
if (!Configuration.ServerConfiguration.Instance.Authentication.RegistrationEnabled)
return this.NotFound();
ApiKeyEntity? apiKey = this.database.ApiKeyFromWebRequest(this.Request);
if (apiKey == null) return this.StatusCode(403);
if (!string.IsNullOrWhiteSpace(username))
{
bool userExists = await this.database.Users.AnyAsync(u => u.Username == username);
if (userExists) return this.BadRequest();
}
RegistrationTokenEntity token = new()
{
Created = DateTime.UtcNow,
Token = CryptoHelper.GenerateAuthToken(),
Username = username,
};
this.database.RegistrationTokens.Add(token);
await this.database.SaveChangesAsync();
return this.Ok(token.Token);
}
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Servers.API.Responses;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Servers.API.Controllers;
/// <summary>
/// A collection of endpoints relating to users.
/// </summary>
public class UserEndpoints : ApiEndpointController
{
private readonly DatabaseContext database;
public UserEndpoints(DatabaseContext database)
{
this.database = database;
}
/// <summary>
/// Gets a user and their information from the database.
/// </summary>
/// <param name="id">The ID of the user</param>
/// <returns>The user</returns>
/// <response code="200">The user, if successful.</response>
/// <response code="404">The user could not be found.</response>
[HttpGet("user/{id:int}")]
[ProducesResponseType(typeof(ApiUser), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetUser(int id)
{
UserEntity? user = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == id);
if (user == null) return this.NotFound();
return this.Ok(ApiUser.CreateFromEntity(user));
}
[HttpGet("username/{username}")]
[ProducesResponseType(typeof(ApiUser), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetUser(string username)
{
UserEntity? user = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
if (user == null) return this.NotFound();
return this.Ok(ApiUser.CreateFromEntity(user));
}
/// <summary>
/// Searches for the user based on the query
/// </summary>
/// <param name="query">The search query</param>
/// <returns>A list of users</returns>
/// <response code="200">The list of users, if any were found</response>
/// <response code="404">No users matched the query</response>
[HttpGet("search/user")]
[ProducesResponseType(typeof(ApiUser), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> SearchUsers(string query)
{
List<ApiUser> users = (await this.database.Users
.Where(u => u.PermissionLevel != PermissionLevel.Banned && u.Username.Contains(query))
.Where(u => u.ProfileVisibility == PrivacyType.All)
.OrderByDescending(b => b.UserId)
.Take(20)
.ToListAsync()).ToSerializableList(ApiUser.CreateFromEntity);
if (!users.Any()) return this.NotFound();
return this.Ok(users);
}
/// <summary>
/// Gets a user and their information from the database.
/// </summary>
/// <param name="id">The ID of the user</param>
/// <returns>The user's status</returns>
/// <response code="200">The user's status, if successful.</response>
/// <response code="404">The user could not be found.</response>
[HttpGet("user/{id:int}/status")]
[ProducesResponseType(typeof(ApiUser), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetUserStatus(int id)
{
UserStatus userStatus = new(this.database, id);
return this.Ok(userStatus);
}
[HttpPost("user/inviteToken")]
[HttpPost("user/inviteToken/{username}")]
public async Task<IActionResult> CreateUserInviteToken([FromRoute] string? username)
{
if (!Configuration.ServerConfiguration.Instance.Authentication.RegistrationEnabled)
return this.NotFound();
ApiKeyEntity? apiKey = this.database.ApiKeyFromWebRequest(this.Request);
if (apiKey == null) return this.StatusCode(403);
if (!string.IsNullOrWhiteSpace(username))
{
bool userExists = await this.database.Users.AnyAsync(u => u.Username == username);
if (userExists) return this.BadRequest();
}
RegistrationTokenEntity token = new()
{
Created = DateTime.UtcNow,
Token = CryptoHelper.GenerateAuthToken(),
Username = username,
};
this.database.RegistrationTokens.Add(token);
await this.database.SaveChangesAsync();
return this.Ok(token.Token);
}
}

View file

@ -1,8 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View file

@ -1,9 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View file

@ -1,200 +1,200 @@
#nullable enable
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using LBPUnion.ProjectLighthouse.Types.Filter;
using LBPUnion.ProjectLighthouse.Types.Levels;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
[ApiController]
[Authorize]
[Route("LITTLEBIGPLANETPS3_XML/")]
[Produces("text/xml")]
public class CommentController : ControllerBase
{
private readonly DatabaseContext database;
public CommentController(DatabaseContext database)
{
this.database = database;
}
[HttpPost("rateUserComment/{username}")]
[HttpPost("rateComment/{slotType}/{slotId:int}")]
public async Task<IActionResult> RateComment([FromQuery] int commentId, [FromQuery] int rating, string? username, string? slotType, int slotId)
{
GameTokenEntity token = this.GetToken();
// Return bad request if both are true or both are false
if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest();
bool success = await this.database.RateComment(token.UserId, commentId, rating);
if (!success) return this.BadRequest();
return this.Ok();
}
[HttpGet("comments/{slotType}/{slotId:int}")]
[HttpGet("userComments/{username}")]
public async Task<IActionResult> GetComments(string? username, string? slotType, int slotId)
{
GameTokenEntity token = this.GetToken();
UserEntity? user = await this.database.UserFromGameToken(token);
if (user == null) return this.Unauthorized();
if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest();
int originalSlotId = slotId;
if (slotType == "developer") slotId = await SlotHelper.GetPlaceholderSlotId(this.database, slotId, SlotType.Developer);
int targetId;
CommentType type = username == null ? CommentType.Level : CommentType.Profile;
PaginationData pageData = this.Request.GetPaginationData();
IQueryable<CommentEntity> baseQuery = this.database.Comments.Where(c => c.Type == type);
if (type == CommentType.Level)
{
targetId = await this.database.Slots.Where(s => s.SlotId == slotId)
.Where(s => s.CommentsEnabled && !s.Hidden)
.Select(s => s.SlotId)
.FirstOrDefaultAsync();
baseQuery = baseQuery.Where(c => c.TargetSlotId == targetId);
}
else
{
targetId = await this.database.Users.Where(u => u.Username == username)
.Where(u => u.CommentsEnabled)
.Select(u => u.UserId)
.FirstOrDefaultAsync();
baseQuery = baseQuery.Where(c => c.TargetUserId == targetId);
}
if (targetId == 0) return this.NotFound();
List<int> blockedUsers = await (
from blockedProfile in this.database.BlockedProfiles
where blockedProfile.UserId == token.UserId
select blockedProfile.BlockedUserId).ToListAsync();
List<GameComment> comments = (await baseQuery.OrderByDescending(c => c.Timestamp)
.Where(c => !blockedUsers.Contains(c.PosterUserId))
.Include(c => c.Poster)
.Where(c => c.Poster.PermissionLevel != PermissionLevel.Banned)
.ApplyPagination(pageData)
.ToListAsync()).ToSerializableList(c => GameComment.CreateFromEntity(c, token.UserId));
if (type == CommentType.Level && slotType == "developer" && user.IsModerator && pageData.PageStart == 1)
{
comments.Insert(0, new GameComment
{
CommentId = 0,
Timestamp = 0,
AuthorUsername = "LH",
Message = $"Slot ID: {targetId}, Story level ID: {originalSlotId}",
});
}
return this.Ok(new CommentListResponse(comments));
}
[HttpPost("postUserComment/{username}")]
[HttpPost("postComment/{slotType}/{slotId:int}")]
public async Task<IActionResult> PostComment(string? username, string? slotType, int slotId)
{
GameTokenEntity token = this.GetToken();
// Deny request if in read-only mode
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
GameComment? comment = await this.DeserializeBody<GameComment>();
if (comment?.Message == null) return this.BadRequest();
if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest();
if (slotType == "developer") slotId = await SlotHelper.GetPlaceholderSlotId(this.database, slotId, SlotType.Developer);
CommentType type = username == null ? CommentType.Level : CommentType.Profile;
int targetId;
if (type == CommentType.Level)
{
targetId = await this.database.Slots.Where(s => s.SlotId == slotId)
.Where(s => s.CommentsEnabled && !s.Hidden)
.Select(s => s.SlotId)
.FirstOrDefaultAsync();
}
else
{
targetId = await this.database.UserIdFromUsername(username!);
}
string filteredText = CensorHelper.FilterMessage(comment.Message, FilterLocation.ChatMessage, username);
bool success = await this.database.PostComment(token.UserId, targetId, type, filteredText);
if (success) return this.Ok();
return this.BadRequest();
}
[HttpPost("deleteUserComment/{username}")]
[HttpPost("deleteComment/{slotType}/{slotId:int}")]
public async Task<IActionResult> DeleteComment([FromQuery] int commentId, string? username, string? slotType, int slotId)
{
GameTokenEntity token = this.GetToken();
// Deny request if in read-only mode
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest();
CommentEntity? comment = await this.database.Comments.FirstOrDefaultAsync(c => c.CommentId == commentId);
if (comment == null) return this.NotFound();
if (comment.Deleted) return this.Ok();
bool canDelete;
if (comment.Type == CommentType.Profile)
{
canDelete = comment.PosterUserId == token.UserId || comment.TargetUserId == token.UserId;
}
else
{
if (slotType == "developer") slotId = await SlotHelper.GetPlaceholderSlotId(this.database, slotId, SlotType.Developer);
if (slotId != comment.TargetSlotId) return this.BadRequest();
int slotCreator = await this.database.Slots.Where(s => s.SlotId == comment.TargetSlotId)
.Where(s => s.CommentsEnabled)
.Select(s => s.CreatorId)
.FirstOrDefaultAsync();
// Comments are disabled or the slot doesn't have a creator
if (slotCreator == 0) return this.BadRequest();
canDelete = comment.PosterUserId == token.UserId || slotCreator == token.UserId;
}
if (!canDelete) return this.Forbid();
comment.Deleted = true;
comment.DeletedBy = await this.database.UsernameFromGameToken(token);
comment.DeletedType = "user";
await this.database.SaveChangesAsync();
return this.Ok();
}
#nullable enable
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using LBPUnion.ProjectLighthouse.Types.Filter;
using LBPUnion.ProjectLighthouse.Types.Levels;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
[ApiController]
[Authorize]
[Route("LITTLEBIGPLANETPS3_XML/")]
[Produces("text/xml")]
public class CommentController : ControllerBase
{
private readonly DatabaseContext database;
public CommentController(DatabaseContext database)
{
this.database = database;
}
[HttpPost("rateUserComment/{username}")]
[HttpPost("rateComment/{slotType}/{slotId:int}")]
public async Task<IActionResult> RateComment([FromQuery] int commentId, [FromQuery] int rating, string? username, string? slotType, int slotId)
{
GameTokenEntity token = this.GetToken();
// Return bad request if both are true or both are false
if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest();
bool success = await this.database.RateComment(token.UserId, commentId, rating);
if (!success) return this.BadRequest();
return this.Ok();
}
[HttpGet("comments/{slotType}/{slotId:int}")]
[HttpGet("userComments/{username}")]
public async Task<IActionResult> GetComments(string? username, string? slotType, int slotId)
{
GameTokenEntity token = this.GetToken();
UserEntity? user = await this.database.UserFromGameToken(token);
if (user == null) return this.Unauthorized();
if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest();
int originalSlotId = slotId;
if (slotType == "developer") slotId = await SlotHelper.GetPlaceholderSlotId(this.database, slotId, SlotType.Developer);
int targetId;
CommentType type = username == null ? CommentType.Level : CommentType.Profile;
PaginationData pageData = this.Request.GetPaginationData();
IQueryable<CommentEntity> baseQuery = this.database.Comments.Where(c => c.Type == type);
if (type == CommentType.Level)
{
targetId = await this.database.Slots.Where(s => s.SlotId == slotId)
.Where(s => s.CommentsEnabled && !s.Hidden)
.Select(s => s.SlotId)
.FirstOrDefaultAsync();
baseQuery = baseQuery.Where(c => c.TargetSlotId == targetId);
}
else
{
targetId = await this.database.Users.Where(u => u.Username == username)
.Where(u => u.CommentsEnabled)
.Select(u => u.UserId)
.FirstOrDefaultAsync();
baseQuery = baseQuery.Where(c => c.TargetUserId == targetId);
}
if (targetId == 0) return this.NotFound();
List<int> blockedUsers = await (
from blockedProfile in this.database.BlockedProfiles
where blockedProfile.UserId == token.UserId
select blockedProfile.BlockedUserId).ToListAsync();
List<GameComment> comments = (await baseQuery.OrderByDescending(c => c.Timestamp)
.Where(c => !blockedUsers.Contains(c.PosterUserId))
.Include(c => c.Poster)
.Where(c => c.Poster.PermissionLevel != PermissionLevel.Banned)
.ApplyPagination(pageData)
.ToListAsync()).ToSerializableList(c => GameComment.CreateFromEntity(c, token.UserId));
if (type == CommentType.Level && slotType == "developer" && user.IsModerator && pageData.PageStart == 1)
{
comments.Insert(0, new GameComment
{
CommentId = 0,
Timestamp = 0,
AuthorUsername = "LH",
Message = $"Slot ID: {targetId}, Story level ID: {originalSlotId}",
});
}
return this.Ok(new CommentListResponse(comments));
}
[HttpPost("postUserComment/{username}")]
[HttpPost("postComment/{slotType}/{slotId:int}")]
public async Task<IActionResult> PostComment(string? username, string? slotType, int slotId)
{
GameTokenEntity token = this.GetToken();
// Deny request if in read-only mode
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
GameComment? comment = await this.DeserializeBody<GameComment>();
if (comment?.Message == null) return this.BadRequest();
if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest();
if (slotType == "developer") slotId = await SlotHelper.GetPlaceholderSlotId(this.database, slotId, SlotType.Developer);
CommentType type = username == null ? CommentType.Level : CommentType.Profile;
int targetId;
if (type == CommentType.Level)
{
targetId = await this.database.Slots.Where(s => s.SlotId == slotId)
.Where(s => s.CommentsEnabled && !s.Hidden)
.Select(s => s.SlotId)
.FirstOrDefaultAsync();
}
else
{
targetId = await this.database.UserIdFromUsername(username!);
}
string filteredText = CensorHelper.FilterMessage(comment.Message, FilterLocation.ChatMessage, username);
bool success = await this.database.PostComment(token.UserId, targetId, type, filteredText);
if (success) return this.Ok();
return this.BadRequest();
}
[HttpPost("deleteUserComment/{username}")]
[HttpPost("deleteComment/{slotType}/{slotId:int}")]
public async Task<IActionResult> DeleteComment([FromQuery] int commentId, string? username, string? slotType, int slotId)
{
GameTokenEntity token = this.GetToken();
// Deny request if in read-only mode
if (ServerConfiguration.Instance.UserGeneratedContentLimits.ReadOnlyMode) return this.BadRequest();
if ((slotId == 0 || SlotHelper.IsTypeInvalid(slotType)) == (username == null)) return this.BadRequest();
CommentEntity? comment = await this.database.Comments.FirstOrDefaultAsync(c => c.CommentId == commentId);
if (comment == null) return this.NotFound();
if (comment.Deleted) return this.Ok();
bool canDelete;
if (comment.Type == CommentType.Profile)
{
canDelete = comment.PosterUserId == token.UserId || comment.TargetUserId == token.UserId;
}
else
{
if (slotType == "developer") slotId = await SlotHelper.GetPlaceholderSlotId(this.database, slotId, SlotType.Developer);
if (slotId != comment.TargetSlotId) return this.BadRequest();
int slotCreator = await this.database.Slots.Where(s => s.SlotId == comment.TargetSlotId)
.Where(s => s.CommentsEnabled)
.Select(s => s.CreatorId)
.FirstOrDefaultAsync();
// Comments are disabled or the slot doesn't have a creator
if (slotCreator == 0) return this.BadRequest();
canDelete = comment.PosterUserId == token.UserId || slotCreator == token.UserId;
}
if (!canDelete) return this.Forbid();
comment.Deleted = true;
comment.DeletedBy = await this.database.UsernameFromGameToken(token);
comment.DeletedType = "user";
await this.database.SaveChangesAsync();
return this.Ok();
}
}

View file

@ -1,15 +1,15 @@
using LBPUnion.ProjectLighthouse.Types.Serialization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
[ApiController]
[Authorize]
[Route("LITTLEBIGPLANETPS3_XML/")]
[Produces("text/xml")]
public class DeveloperController : Controller
{
[HttpGet("developer_videos")]
public IActionResult DeveloperVideos() => this.Ok(new GameDeveloperVideos());
using LBPUnion.ProjectLighthouse.Types.Serialization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
[ApiController]
[Authorize]
[Route("LITTLEBIGPLANETPS3_XML/")]
[Produces("text/xml")]
public class DeveloperController : Controller
{
[HttpGet("developer_videos")]
public IActionResult DeveloperVideos() => this.Ok(new GameDeveloperVideos());
}

View file

@ -1,93 +1,93 @@
#nullable enable
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Types.Users;
using LBPUnion.ProjectLighthouse.StorableLists.Stores;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
[ApiController]
[Authorize]
[Route("LITTLEBIGPLANETPS3_XML/")]
[Produces("text/xml")]
public class FriendsController : ControllerBase
{
private readonly DatabaseContext database;
public FriendsController(DatabaseContext database)
{
this.database = database;
}
[HttpPost("npdata")]
public async Task<IActionResult> NPData()
{
GameTokenEntity token = this.GetToken();
NPData? npData = await this.DeserializeBody<NPData>();
if (npData == null) return this.BadRequest();
List<UserEntity> friends = new();
foreach (string friendName in npData.Friends ?? new List<string>())
{
UserEntity? friend = await this.database.Users.FirstOrDefaultAsync(u => u.Username == friendName);
if (friend == null) continue;
friends.Add(friend);
}
List<int> blockedUsers = new();
foreach (string blockedUserName in npData.BlockedUsers ?? new List<string>())
{
UserEntity? blockedUser = await this.database.Users.FirstOrDefaultAsync(u => u.Username == blockedUserName);
if (blockedUser == null) continue;
blockedUsers.Add(blockedUser.UserId);
}
UserFriendData friendStore = UserFriendStore.GetUserFriendData(token.UserId) ?? UserFriendStore.CreateUserFriendData(token.UserId);
friendStore.FriendIds = friends.Select(u => u.UserId).ToList();
friendStore.BlockedIds = blockedUsers;
UserFriendStore.UpdateFriendData(friendStore);
List<MinimalUserProfile> minimalFriends =
friends.Select(u => new MinimalUserProfile
{
UserHandle = new NpHandle(u.Username, ""),
}).ToList();
return this.Ok(new FriendResponse(minimalFriends));
}
[HttpGet("myFriends")]
public async Task<IActionResult> MyFriends()
{
GameTokenEntity token = this.GetToken();
UserFriendData? friendStore = UserFriendStore.GetUserFriendData(token.UserId);
GenericUserResponse<GameUser> response = new("myFriends", new List<GameUser>());
if (friendStore == null)
return this.Ok(response);
foreach (int friendId in friendStore.FriendIds)
{
UserEntity? friend = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == friendId);
if (friend == null) continue;
response.Users.Add(GameUser.CreateFromEntity(friend, token.GameVersion));
}
return this.Ok(response);
}
#nullable enable
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Types.Users;
using LBPUnion.ProjectLighthouse.StorableLists.Stores;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
[ApiController]
[Authorize]
[Route("LITTLEBIGPLANETPS3_XML/")]
[Produces("text/xml")]
public class FriendsController : ControllerBase
{
private readonly DatabaseContext database;
public FriendsController(DatabaseContext database)
{
this.database = database;
}
[HttpPost("npdata")]
public async Task<IActionResult> NPData()
{
GameTokenEntity token = this.GetToken();
NPData? npData = await this.DeserializeBody<NPData>();
if (npData == null) return this.BadRequest();
List<UserEntity> friends = new();
foreach (string friendName in npData.Friends ?? new List<string>())
{
UserEntity? friend = await this.database.Users.FirstOrDefaultAsync(u => u.Username == friendName);
if (friend == null) continue;
friends.Add(friend);
}
List<int> blockedUsers = new();
foreach (string blockedUserName in npData.BlockedUsers ?? new List<string>())
{
UserEntity? blockedUser = await this.database.Users.FirstOrDefaultAsync(u => u.Username == blockedUserName);
if (blockedUser == null) continue;
blockedUsers.Add(blockedUser.UserId);
}
UserFriendData friendStore = UserFriendStore.GetUserFriendData(token.UserId) ?? UserFriendStore.CreateUserFriendData(token.UserId);
friendStore.FriendIds = friends.Select(u => u.UserId).ToList();
friendStore.BlockedIds = blockedUsers;
UserFriendStore.UpdateFriendData(friendStore);
List<MinimalUserProfile> minimalFriends =
friends.Select(u => new MinimalUserProfile
{
UserHandle = new NpHandle(u.Username, ""),
}).ToList();
return this.Ok(new FriendResponse(minimalFriends));
}
[HttpGet("myFriends")]
public async Task<IActionResult> MyFriends()
{
GameTokenEntity token = this.GetToken();
UserFriendData? friendStore = UserFriendStore.GetUserFriendData(token.UserId);
GenericUserResponse<GameUser> response = new("myFriends", new List<GameUser>());
if (friendStore == null)
return this.Ok(response);
foreach (int friendId in friendStore.FriendIds)
{
UserEntity? friend = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == friendId);
if (friend == null) continue;
response.Users.Add(GameUser.CreateFromEntity(friend, token.GameVersion));
}
return this.Ok(response);
}
}

View file

@ -1,8 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View file

@ -1,9 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View file

@ -1,3 +1,3 @@
using Xunit;
using Xunit;
[assembly: CollectionBehavior(DisableTestParallelization = true)]

View file

@ -1,84 +1,84 @@
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Startup;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Tests.Integration;
using LBPUnion.ProjectLighthouse.Types.Users;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Integration;
[Trait("Category", "Integration")]
public class AuthenticationTests : LighthouseServerTest<GameServerTestStartup>
{
[Fact]
public async Task ShouldReturnErrorOnNoPostData()
{
await IntegrationHelper.GetIntegrationDatabase();
HttpResponseMessage response = await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", null!);
const HttpStatusCode expectedStatusCode = HttpStatusCode.BadRequest;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task Login_ShouldReturnWithValidData()
{
await IntegrationHelper.GetIntegrationDatabase();
HttpResponseMessage response = await this.AuthenticateResponse();
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, response.StatusCode);
string responseContent = await response.Content.ReadAsStringAsync();
Assert.Contains("MM_AUTH=", responseContent);
Assert.Contains(VersionHelper.EnvVer, responseContent);
}
[Fact]
public async Task Login_CanSerializeBack()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
Assert.NotNull(loginResult);
Assert.NotNull(loginResult.AuthTicket);
Assert.NotNull(loginResult.ServerBrand);
Assert.Contains("MM_AUTH=", loginResult.AuthTicket);
Assert.Equal(VersionHelper.EnvVer, loginResult.ServerBrand);
}
[Fact]
public async Task Login_CanUseToken()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/enterLevel/420", loginResult.AuthTicket);
await response.Content.ReadAsStringAsync();
const HttpStatusCode expectedStatusCode = HttpStatusCode.NotFound;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task Login_ShouldReturnForbiddenWhenNotAuthenticated()
{
await IntegrationHelper.GetIntegrationDatabase();
HttpResponseMessage response = await this.Client.GetAsync("/LITTLEBIGPLANETPS3_XML/announce");
const HttpStatusCode expectedStatusCode = HttpStatusCode.Forbidden;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Startup;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Tests.Integration;
using LBPUnion.ProjectLighthouse.Types.Users;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Integration;
[Trait("Category", "Integration")]
public class AuthenticationTests : LighthouseServerTest<GameServerTestStartup>
{
[Fact]
public async Task ShouldReturnErrorOnNoPostData()
{
await IntegrationHelper.GetIntegrationDatabase();
HttpResponseMessage response = await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", null!);
const HttpStatusCode expectedStatusCode = HttpStatusCode.BadRequest;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task Login_ShouldReturnWithValidData()
{
await IntegrationHelper.GetIntegrationDatabase();
HttpResponseMessage response = await this.AuthenticateResponse();
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, response.StatusCode);
string responseContent = await response.Content.ReadAsStringAsync();
Assert.Contains("MM_AUTH=", responseContent);
Assert.Contains(VersionHelper.EnvVer, responseContent);
}
[Fact]
public async Task Login_CanSerializeBack()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
Assert.NotNull(loginResult);
Assert.NotNull(loginResult.AuthTicket);
Assert.NotNull(loginResult.ServerBrand);
Assert.Contains("MM_AUTH=", loginResult.AuthTicket);
Assert.Equal(VersionHelper.EnvVer, loginResult.ServerBrand);
}
[Fact]
public async Task Login_CanUseToken()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/enterLevel/420", loginResult.AuthTicket);
await response.Content.ReadAsStringAsync();
const HttpStatusCode expectedStatusCode = HttpStatusCode.NotFound;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task Login_ShouldReturnForbiddenWhenNotAuthenticated()
{
await IntegrationHelper.GetIntegrationDatabase();
HttpResponseMessage response = await this.Client.GetAsync("/LITTLEBIGPLANETPS3_XML/announce");
const HttpStatusCode expectedStatusCode = HttpStatusCode.Forbidden;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
}

View file

@ -1,29 +1,29 @@
using System;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Startup;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Tests.Integration;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Integration;
[Trait("Category", "Integration")]
public class DatabaseTests : LighthouseServerTest<GameServerTestStartup>
{
[Fact]
public async Task CanCreateUserTwice()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
int rand = new Random().Next();
UserEntity userA = await database.CreateUser("unitTestUser" + rand, CryptoHelper.BCryptHash(CryptoHelper.GenerateAuthToken()));
UserEntity userB = await database.CreateUser("unitTestUser" + rand, CryptoHelper.BCryptHash(CryptoHelper.GenerateAuthToken()));
Assert.NotNull(userA);
Assert.NotNull(userB);
}
using System;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Startup;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Tests.Integration;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Integration;
[Trait("Category", "Integration")]
public class DatabaseTests : LighthouseServerTest<GameServerTestStartup>
{
[Fact]
public async Task CanCreateUserTwice()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
int rand = new Random().Next();
UserEntity userA = await database.CreateUser("unitTestUser" + rand, CryptoHelper.BCryptHash(CryptoHelper.GenerateAuthToken()));
UserEntity userB = await database.CreateUser("unitTestUser" + rand, CryptoHelper.BCryptHash(CryptoHelper.GenerateAuthToken()));
Assert.NotNull(userA);
Assert.NotNull(userB);
}
}

View file

@ -1,122 +1,122 @@
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Startup;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Tests.Integration;
using LBPUnion.ProjectLighthouse.Tickets;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Users;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Integration;
[Trait("Category", "Integration")]
public class LoginTests : LighthouseServerTest<GameServerTestStartup>
{
[Fact]
public async Task ShouldLoginWithGoodTicket()
{
await IntegrationHelper.GetIntegrationDatabase();
UserEntity user = await this.CreateRandomUser();
byte[] ticketData = new TicketBuilder()
.SetUsername(user.Username)
.SetUserId((ulong)user.UserId)
.Build();
HttpResponseMessage response = await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", new ByteArrayContent(ticketData));
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task ShouldNotLoginWithExpiredTicket()
{
await IntegrationHelper.GetIntegrationDatabase();
UserEntity user = await this.CreateRandomUser();
byte[] ticketData = new TicketBuilder()
.SetUsername(user.Username)
.SetUserId((ulong)user.UserId)
.setExpirationTime((ulong)TimeHelper.TimestampMillis - 1000 * 60)
.Build();
HttpResponseMessage response = await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", new ByteArrayContent(ticketData));
const HttpStatusCode expectedStatusCode = HttpStatusCode.BadRequest;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task ShouldNotLoginWithBadTitleId()
{
await IntegrationHelper.GetIntegrationDatabase();
UserEntity user = await this.CreateRandomUser();
byte[] ticketData = new TicketBuilder()
.SetUsername(user.Username)
.SetUserId((ulong)user.UserId)
.SetTitleId("UP9000-BLUS30079_00")
.Build();
HttpResponseMessage response = await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", new ByteArrayContent(ticketData));
const HttpStatusCode expectedStatusCode = HttpStatusCode.BadRequest;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task ShouldNotLoginWithBadSignature()
{
await IntegrationHelper.GetIntegrationDatabase();
UserEntity user = await this.CreateRandomUser();
byte[] ticketData = new TicketBuilder()
.SetUsername(user.Username)
.SetUserId((ulong)user.UserId)
.Build();
// Create second ticket and replace the first tickets signature with the first.
byte[] ticketData2 = new TicketBuilder()
.SetUsername(user.Username)
.SetUserId((ulong)user.UserId)
.Build();
Array.Copy(ticketData2, ticketData2.Length - 0x38, ticketData, ticketData.Length - 0x38, 0x38);
HttpResponseMessage response = await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", new ByteArrayContent(ticketData));
const HttpStatusCode expectedStatusCode = HttpStatusCode.BadRequest;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task ShouldNotLoginIfBanned()
{
DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
UserEntity user = await this.CreateRandomUser();
user.PermissionLevel = PermissionLevel.Banned;
database.Users.Update(user);
await database.SaveChangesAsync();
byte[] ticketData = new TicketBuilder()
.SetUsername(user.Username)
.SetUserId((ulong)user.UserId)
.Build();
HttpResponseMessage response =
await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", new ByteArrayContent(ticketData));
const HttpStatusCode expectedStatusCode = HttpStatusCode.Forbidden;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
}
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Startup;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Tests.Integration;
using LBPUnion.ProjectLighthouse.Tickets;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Users;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Integration;
[Trait("Category", "Integration")]
public class LoginTests : LighthouseServerTest<GameServerTestStartup>
{
[Fact]
public async Task ShouldLoginWithGoodTicket()
{
await IntegrationHelper.GetIntegrationDatabase();
UserEntity user = await this.CreateRandomUser();
byte[] ticketData = new TicketBuilder()
.SetUsername(user.Username)
.SetUserId((ulong)user.UserId)
.Build();
HttpResponseMessage response = await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", new ByteArrayContent(ticketData));
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task ShouldNotLoginWithExpiredTicket()
{
await IntegrationHelper.GetIntegrationDatabase();
UserEntity user = await this.CreateRandomUser();
byte[] ticketData = new TicketBuilder()
.SetUsername(user.Username)
.SetUserId((ulong)user.UserId)
.setExpirationTime((ulong)TimeHelper.TimestampMillis - 1000 * 60)
.Build();
HttpResponseMessage response = await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", new ByteArrayContent(ticketData));
const HttpStatusCode expectedStatusCode = HttpStatusCode.BadRequest;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task ShouldNotLoginWithBadTitleId()
{
await IntegrationHelper.GetIntegrationDatabase();
UserEntity user = await this.CreateRandomUser();
byte[] ticketData = new TicketBuilder()
.SetUsername(user.Username)
.SetUserId((ulong)user.UserId)
.SetTitleId("UP9000-BLUS30079_00")
.Build();
HttpResponseMessage response = await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", new ByteArrayContent(ticketData));
const HttpStatusCode expectedStatusCode = HttpStatusCode.BadRequest;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task ShouldNotLoginWithBadSignature()
{
await IntegrationHelper.GetIntegrationDatabase();
UserEntity user = await this.CreateRandomUser();
byte[] ticketData = new TicketBuilder()
.SetUsername(user.Username)
.SetUserId((ulong)user.UserId)
.Build();
// Create second ticket and replace the first tickets signature with the first.
byte[] ticketData2 = new TicketBuilder()
.SetUsername(user.Username)
.SetUserId((ulong)user.UserId)
.Build();
Array.Copy(ticketData2, ticketData2.Length - 0x38, ticketData, ticketData.Length - 0x38, 0x38);
HttpResponseMessage response = await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", new ByteArrayContent(ticketData));
const HttpStatusCode expectedStatusCode = HttpStatusCode.BadRequest;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task ShouldNotLoginIfBanned()
{
DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
UserEntity user = await this.CreateRandomUser();
user.PermissionLevel = PermissionLevel.Banned;
database.Users.Update(user);
await database.SaveChangesAsync();
byte[] ticketData = new TicketBuilder()
.SetUsername(user.Username)
.SetUserId((ulong)user.UserId)
.Build();
HttpResponseMessage response =
await this.Client.PostAsync("/LITTLEBIGPLANETPS3_XML/login", new ByteArrayContent(ticketData));
const HttpStatusCode expectedStatusCode = HttpStatusCode.Forbidden;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
}

View file

@ -1,69 +1,69 @@
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Startup;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Tests.Integration;
using LBPUnion.ProjectLighthouse.Types.Users;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Integration;
[Trait("Category", "Integration")]
public class MatchTests : LighthouseServerTest<GameServerTestStartup>
{
[Fact]
public async Task Match_ShouldRejectEmptyData()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage result = await this.AuthenticatedUploadDataRequest("/LITTLEBIGPLANETPS3_XML/match", Array.Empty<byte>(), loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.BadRequest;
Assert.Equal(expectedStatusCode, result.StatusCode);
}
[Fact]
public async Task Match_ShouldReturnOk_WithGoodRequest()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage result = await this.AuthenticatedUploadDataRequest
("/LITTLEBIGPLANETPS3_XML/match", "[UpdateMyPlayerData,[\"Player\":\"1984\"]]"u8.ToArray(), loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, result.StatusCode);
}
[Fact]
public async Task Match_ShouldIncrementPlayerCount()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
await using DatabaseContext database = DatabaseContext.CreateNewInstance();
int oldPlayerCount = await StatisticsHelper.RecentMatches(database);
HttpResponseMessage result = await this.AuthenticatedUploadDataRequest
("/LITTLEBIGPLANETPS3_XML/match", "[UpdateMyPlayerData,[\"Player\":\"1984\"]]"u8.ToArray(), loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, result.StatusCode);
int playerCount = await StatisticsHelper.RecentMatches(database);
Assert.Equal(oldPlayerCount + 1, playerCount);
}
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Startup;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Tests.Integration;
using LBPUnion.ProjectLighthouse.Types.Users;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Integration;
[Trait("Category", "Integration")]
public class MatchTests : LighthouseServerTest<GameServerTestStartup>
{
[Fact]
public async Task Match_ShouldRejectEmptyData()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage result = await this.AuthenticatedUploadDataRequest("/LITTLEBIGPLANETPS3_XML/match", Array.Empty<byte>(), loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.BadRequest;
Assert.Equal(expectedStatusCode, result.StatusCode);
}
[Fact]
public async Task Match_ShouldReturnOk_WithGoodRequest()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage result = await this.AuthenticatedUploadDataRequest
("/LITTLEBIGPLANETPS3_XML/match", "[UpdateMyPlayerData,[\"Player\":\"1984\"]]"u8.ToArray(), loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, result.StatusCode);
}
[Fact]
public async Task Match_ShouldIncrementPlayerCount()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
await using DatabaseContext database = DatabaseContext.CreateNewInstance();
int oldPlayerCount = await StatisticsHelper.RecentMatches(database);
HttpResponseMessage result = await this.AuthenticatedUploadDataRequest
("/LITTLEBIGPLANETPS3_XML/match", "[UpdateMyPlayerData,[\"Player\":\"1984\"]]"u8.ToArray(), loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, result.StatusCode);
int playerCount = await StatisticsHelper.RecentMatches(database);
Assert.Equal(oldPlayerCount + 1, playerCount);
}
}

View file

@ -1,234 +1,234 @@
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Xml.Serialization;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Serialization;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Startup;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Tests.Integration;
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using LBPUnion.ProjectLighthouse.Types.Users;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Integration;
[Trait("Category", "Integration")]
public class SlotFilterTests : LighthouseServerTest<GameServerTestStartup>
{
[Fact]
public async Task GetUserSlot_ShouldReturnOk_WhenSlotExists()
{
DatabaseContext db = await IntegrationHelper.GetIntegrationDatabase();
db.Users.Add(new UserEntity
{
UserId = 23,
});
db.Slots.Add(new SlotEntity
{
SlotId = 23,
CreatorId = 23,
});
await db.SaveChangesAsync();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/s/user/23", loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, response.StatusCode);
string body = await response.Content.ReadAsStringAsync();
Assert.Contains("<id>23</id>", body);
}
[Fact]
public async Task NewestSlots_ShouldReturnSlotsOrderedByTimestampDescending()
{
DatabaseContext db = await IntegrationHelper.GetIntegrationDatabase();
for (int i = 1; i <= 100; i++)
{
db.Users.Add(new UserEntity
{
UserId = i,
Username = $"user{i}",
});
db.Slots.Add(new SlotEntity
{
SlotId = i,
CreatorId = i,
FirstUploaded = i,
});
}
await db.SaveChangesAsync();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response =
await this.AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/slots?pageStart=0&pageSize=10", loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, response.StatusCode);
string body = await response.Content.ReadAsStringAsync();
object? deserialized = LighthouseSerializer
.GetSerializer(typeof(GameUserSlotList), new XmlRootAttribute("slots"))
.Deserialize(new StringReader(body));
Assert.NotNull(deserialized);
Assert.IsType<GameUserSlotList>(deserialized);
GameUserSlotList slotResponse = (GameUserSlotList)deserialized;
Assert.Equal(100, slotResponse.Total);
Assert.Equal(10, slotResponse.Slots.Count);
Assert.Equal(91, slotResponse.Slots[9].FirstUploaded);
}
[Fact]
public async Task NewestSlots_ShouldReturnSlotsWithAuthorLabel()
{
DatabaseContext db = await IntegrationHelper.GetIntegrationDatabase();
db.Users.Add(new UserEntity()
{
UserId = 1,
});
db.Slots.Add(new SlotEntity
{
CreatorId = 1,
SlotId = 1,
AuthorLabels = "LABEL_SinglePlayer,LABEL_Quick,LABEL_Funny",
FirstUploaded = 1,
});
db.Slots.Add(new SlotEntity
{
CreatorId = 1,
SlotId = 2,
AuthorLabels = "LABEL_SinglePlayer",
FirstUploaded = 2,
});
db.Slots.Add(new SlotEntity
{
CreatorId = 1,
SlotId = 3,
AuthorLabels = "LABEL_Quick",
FirstUploaded = 3,
});
db.Slots.Add(new SlotEntity
{
CreatorId = 1,
SlotId = 4,
AuthorLabels = "LABEL_Funny",
FirstUploaded = 4,
});
await db.SaveChangesAsync();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response =
await this.AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/slots?pageStart=0&pageSize=10&labelFilter0=LABEL_Funny",
loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, response.StatusCode);
string body = await response.Content.ReadAsStringAsync();
object? deserialized = LighthouseSerializer
.GetSerializer(typeof(GameUserSlotList), new XmlRootAttribute("slots"))
.Deserialize(new StringReader(body));
Assert.NotNull(deserialized);
Assert.IsType<GameUserSlotList>(deserialized);
GameUserSlotList slotResponse = (GameUserSlotList)deserialized;
const int expectedCount = 2;
Assert.Equal(expectedCount, slotResponse.Slots.Count);
Assert.True(slotResponse.Slots.TrueForAll(s => s.AuthorLabels.Contains("LABEL_Funny")));
}
[Fact]
public async Task NewestSlots_ShouldReturnEmpty_WhenAuthorLabelsDontMatch()
{
DatabaseContext db = await IntegrationHelper.GetIntegrationDatabase();
db.Users.Add(new UserEntity
{
UserId = 1,
});
db.Slots.Add(new SlotEntity
{
CreatorId = 1,
SlotId = 1,
AuthorLabels = "LABEL_SinglePlayer,LABEL_Quick,LABEL_Funny",
FirstUploaded = 1,
});
db.Slots.Add(new SlotEntity
{
CreatorId = 1,
SlotId = 2,
AuthorLabels = "LABEL_SinglePlayer",
FirstUploaded = 2,
});
db.Slots.Add(new SlotEntity
{
CreatorId = 1,
SlotId = 3,
AuthorLabels = "LABEL_Quick",
FirstUploaded = 3,
});
db.Slots.Add(new SlotEntity
{
CreatorId = 1,
SlotId = 4,
AuthorLabels = "LABEL_Funny",
FirstUploaded = 4,
});
await db.SaveChangesAsync();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response =
await this.AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/slots?pageStart=0&pageSize=10&labelFilter0=LABEL_Funny&labelFilter1=LABEL_Quick&labelFilter2=LABEL_Gallery",
loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, response.StatusCode);
string body = await response.Content.ReadAsStringAsync();
object? deserialized = LighthouseSerializer
.GetSerializer(typeof(GameUserSlotList), new XmlRootAttribute("slots"))
.Deserialize(new StringReader(body));
Assert.NotNull(deserialized);
Assert.IsType<GameUserSlotList>(deserialized);
GameUserSlotList slotResponse = (GameUserSlotList)deserialized;
Assert.Empty(slotResponse.Slots);
}
[XmlRoot("slots")]
public class GameUserSlotList
{
[XmlElement("slot")]
public List<GameUserSlot> Slots { get; set; } = new();
[XmlAttribute("total")]
public int Total { get; set; }
[XmlAttribute("hint_start")]
public int HintStart { get; set; }
}
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Xml.Serialization;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Serialization;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Startup;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Tests.Integration;
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using LBPUnion.ProjectLighthouse.Types.Users;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Integration;
[Trait("Category", "Integration")]
public class SlotFilterTests : LighthouseServerTest<GameServerTestStartup>
{
[Fact]
public async Task GetUserSlot_ShouldReturnOk_WhenSlotExists()
{
DatabaseContext db = await IntegrationHelper.GetIntegrationDatabase();
db.Users.Add(new UserEntity
{
UserId = 23,
});
db.Slots.Add(new SlotEntity
{
SlotId = 23,
CreatorId = 23,
});
await db.SaveChangesAsync();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/s/user/23", loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, response.StatusCode);
string body = await response.Content.ReadAsStringAsync();
Assert.Contains("<id>23</id>", body);
}
[Fact]
public async Task NewestSlots_ShouldReturnSlotsOrderedByTimestampDescending()
{
DatabaseContext db = await IntegrationHelper.GetIntegrationDatabase();
for (int i = 1; i <= 100; i++)
{
db.Users.Add(new UserEntity
{
UserId = i,
Username = $"user{i}",
});
db.Slots.Add(new SlotEntity
{
SlotId = i,
CreatorId = i,
FirstUploaded = i,
});
}
await db.SaveChangesAsync();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response =
await this.AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/slots?pageStart=0&pageSize=10", loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, response.StatusCode);
string body = await response.Content.ReadAsStringAsync();
object? deserialized = LighthouseSerializer
.GetSerializer(typeof(GameUserSlotList), new XmlRootAttribute("slots"))
.Deserialize(new StringReader(body));
Assert.NotNull(deserialized);
Assert.IsType<GameUserSlotList>(deserialized);
GameUserSlotList slotResponse = (GameUserSlotList)deserialized;
Assert.Equal(100, slotResponse.Total);
Assert.Equal(10, slotResponse.Slots.Count);
Assert.Equal(91, slotResponse.Slots[9].FirstUploaded);
}
[Fact]
public async Task NewestSlots_ShouldReturnSlotsWithAuthorLabel()
{
DatabaseContext db = await IntegrationHelper.GetIntegrationDatabase();
db.Users.Add(new UserEntity()
{
UserId = 1,
});
db.Slots.Add(new SlotEntity
{
CreatorId = 1,
SlotId = 1,
AuthorLabels = "LABEL_SinglePlayer,LABEL_Quick,LABEL_Funny",
FirstUploaded = 1,
});
db.Slots.Add(new SlotEntity
{
CreatorId = 1,
SlotId = 2,
AuthorLabels = "LABEL_SinglePlayer",
FirstUploaded = 2,
});
db.Slots.Add(new SlotEntity
{
CreatorId = 1,
SlotId = 3,
AuthorLabels = "LABEL_Quick",
FirstUploaded = 3,
});
db.Slots.Add(new SlotEntity
{
CreatorId = 1,
SlotId = 4,
AuthorLabels = "LABEL_Funny",
FirstUploaded = 4,
});
await db.SaveChangesAsync();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response =
await this.AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/slots?pageStart=0&pageSize=10&labelFilter0=LABEL_Funny",
loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, response.StatusCode);
string body = await response.Content.ReadAsStringAsync();
object? deserialized = LighthouseSerializer
.GetSerializer(typeof(GameUserSlotList), new XmlRootAttribute("slots"))
.Deserialize(new StringReader(body));
Assert.NotNull(deserialized);
Assert.IsType<GameUserSlotList>(deserialized);
GameUserSlotList slotResponse = (GameUserSlotList)deserialized;
const int expectedCount = 2;
Assert.Equal(expectedCount, slotResponse.Slots.Count);
Assert.True(slotResponse.Slots.TrueForAll(s => s.AuthorLabels.Contains("LABEL_Funny")));
}
[Fact]
public async Task NewestSlots_ShouldReturnEmpty_WhenAuthorLabelsDontMatch()
{
DatabaseContext db = await IntegrationHelper.GetIntegrationDatabase();
db.Users.Add(new UserEntity
{
UserId = 1,
});
db.Slots.Add(new SlotEntity
{
CreatorId = 1,
SlotId = 1,
AuthorLabels = "LABEL_SinglePlayer,LABEL_Quick,LABEL_Funny",
FirstUploaded = 1,
});
db.Slots.Add(new SlotEntity
{
CreatorId = 1,
SlotId = 2,
AuthorLabels = "LABEL_SinglePlayer",
FirstUploaded = 2,
});
db.Slots.Add(new SlotEntity
{
CreatorId = 1,
SlotId = 3,
AuthorLabels = "LABEL_Quick",
FirstUploaded = 3,
});
db.Slots.Add(new SlotEntity
{
CreatorId = 1,
SlotId = 4,
AuthorLabels = "LABEL_Funny",
FirstUploaded = 4,
});
await db.SaveChangesAsync();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response =
await this.AuthenticatedRequest("/LITTLEBIGPLANETPS3_XML/slots?pageStart=0&pageSize=10&labelFilter0=LABEL_Funny&labelFilter1=LABEL_Quick&labelFilter2=LABEL_Gallery",
loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, response.StatusCode);
string body = await response.Content.ReadAsStringAsync();
object? deserialized = LighthouseSerializer
.GetSerializer(typeof(GameUserSlotList), new XmlRootAttribute("slots"))
.Deserialize(new StringReader(body));
Assert.NotNull(deserialized);
Assert.IsType<GameUserSlotList>(deserialized);
GameUserSlotList slotResponse = (GameUserSlotList)deserialized;
Assert.Empty(slotResponse.Slots);
}
[XmlRoot("slots")]
public class GameUserSlotList
{
[XmlElement("slot")]
public List<GameUserSlot> Slots { get; set; } = new();
[XmlAttribute("total")]
public int Total { get; set; }
[XmlAttribute("hint_start")]
public int HintStart { get; set; }
}
}

View file

@ -1,67 +1,67 @@
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Startup;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Tests.Integration;
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Users;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Integration;
[Trait("Category", "Integration")]
public class SlotTests : LighthouseServerTest<GameServerTestStartup>
{
[Fact]
public async Task ShouldOnlyShowUsersLevels()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
UserEntity userA = await this.CreateRandomUser();
UserEntity userB = await this.CreateRandomUser();
SlotEntity slotA = new()
{
CreatorId = userA.UserId,
Name = "slotA",
ResourceCollection = "",
};
SlotEntity slotB = new()
{
CreatorId = userB.UserId,
Name = "slotB",
ResourceCollection = "",
};
database.Slots.Add(slotA);
database.Slots.Add(slotB);
await database.SaveChangesAsync();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage respMessageA = await this.AuthenticatedRequest
($"/LITTLEBIGPLANETPS3_XML/slots/by?u={userA.Username}&pageStart=1&pageSize=1", loginResult.AuthTicket);
HttpResponseMessage respMessageB = await this.AuthenticatedRequest
($"/LITTLEBIGPLANETPS3_XML/slots/by?u={userB.Username}&pageStart=1&pageSize=1", loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, respMessageA.StatusCode);
Assert.Equal(expectedStatusCode, respMessageB.StatusCode);
string respA = await respMessageA.Content.ReadAsStringAsync();
string respB = await respMessageB.Content.ReadAsStringAsync();
Assert.NotNull(respA);
Assert.NotNull(respB);
Assert.NotEqual(respA, respB);
Assert.DoesNotContain(respA, "slotB");
Assert.DoesNotContain(respB, "slotA");
}
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Startup;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Tests.Integration;
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Users;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Integration;
[Trait("Category", "Integration")]
public class SlotTests : LighthouseServerTest<GameServerTestStartup>
{
[Fact]
public async Task ShouldOnlyShowUsersLevels()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
UserEntity userA = await this.CreateRandomUser();
UserEntity userB = await this.CreateRandomUser();
SlotEntity slotA = new()
{
CreatorId = userA.UserId,
Name = "slotA",
ResourceCollection = "",
};
SlotEntity slotB = new()
{
CreatorId = userB.UserId,
Name = "slotB",
ResourceCollection = "",
};
database.Slots.Add(slotA);
database.Slots.Add(slotB);
await database.SaveChangesAsync();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage respMessageA = await this.AuthenticatedRequest
($"/LITTLEBIGPLANETPS3_XML/slots/by?u={userA.Username}&pageStart=1&pageSize=1", loginResult.AuthTicket);
HttpResponseMessage respMessageB = await this.AuthenticatedRequest
($"/LITTLEBIGPLANETPS3_XML/slots/by?u={userB.Username}&pageStart=1&pageSize=1", loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, respMessageA.StatusCode);
Assert.Equal(expectedStatusCode, respMessageB.StatusCode);
string respA = await respMessageA.Content.ReadAsStringAsync();
string respB = await respMessageB.Content.ReadAsStringAsync();
Assert.NotNull(respA);
Assert.NotNull(respB);
Assert.NotEqual(respA, respB);
Assert.DoesNotContain(respA, "slotB");
Assert.DoesNotContain(respB, "slotA");
}
}

View file

@ -1,92 +1,92 @@
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Startup;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Tests.Integration;
using LBPUnion.ProjectLighthouse.Types.Users;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Integration;
[Trait("Category", "Integration")]
public class UploadTests : LighthouseServerTest<GameServerTestStartup>
{
public UploadTests()
{
string assetsDirectory = Path.Combine(Environment.CurrentDirectory, "r");
if (Directory.Exists(assetsDirectory)) Directory.Delete(assetsDirectory, true);
}
[Fact]
public async Task ShouldNotAcceptScript()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedUploadFileEndpointRequest("ExampleFiles/TestScript.ff", loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.Conflict;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task ShouldNotAcceptFarc()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedUploadFileEndpointRequest("ExampleFiles/TestFarc.farc", loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.Conflict;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task ShouldNotAcceptGarbage()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedUploadFileEndpointRequest("ExampleFiles/TestGarbage.bin", loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.Conflict;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task ShouldAcceptTexture()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedUploadFileEndpointRequest("ExampleFiles/TestTexture.tex", loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task ShouldAcceptLevel()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedUploadFileEndpointRequest("ExampleFiles/TestLevel.lvl", loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Startup;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Tests.Integration;
using LBPUnion.ProjectLighthouse.Types.Users;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Integration;
[Trait("Category", "Integration")]
public class UploadTests : LighthouseServerTest<GameServerTestStartup>
{
public UploadTests()
{
string assetsDirectory = Path.Combine(Environment.CurrentDirectory, "r");
if (Directory.Exists(assetsDirectory)) Directory.Delete(assetsDirectory, true);
}
[Fact]
public async Task ShouldNotAcceptScript()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedUploadFileEndpointRequest("ExampleFiles/TestScript.ff", loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.Conflict;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task ShouldNotAcceptFarc()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedUploadFileEndpointRequest("ExampleFiles/TestFarc.farc", loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.Conflict;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task ShouldNotAcceptGarbage()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedUploadFileEndpointRequest("ExampleFiles/TestGarbage.bin", loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.Conflict;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task ShouldAcceptTexture()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedUploadFileEndpointRequest("ExampleFiles/TestTexture.tex", loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
[Fact]
public async Task ShouldAcceptLevel()
{
await IntegrationHelper.GetIntegrationDatabase();
LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedUploadFileEndpointRequest("ExampleFiles/TestLevel.lvl", loginResult.AuthTicket);
const HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
Assert.Equal(expectedStatusCode, response.StatusCode);
}
}

View file

@ -1,34 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2024.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.18" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.18">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ProjectLighthouse.Servers.GameServer\ProjectLighthouse.Servers.GameServer.csproj" />
<ProjectReference Include="..\ProjectLighthouse.Tests\ProjectLighthouse.Tests.csproj" />
<ProjectReference Include="..\ProjectLighthouse\ProjectLighthouse.csproj" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2024.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.18" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.18">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ProjectLighthouse.Servers.GameServer\ProjectLighthouse.Servers.GameServer.csproj" />
<ProjectReference Include="..\ProjectLighthouse.Tests\ProjectLighthouse.Tests.csproj" />
<ProjectReference Include="..\ProjectLighthouse\ProjectLighthouse.csproj" />
</ItemGroup>
</Project>

View file

@ -1,231 +1,231 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Levels;
using Microsoft.AspNetCore.Mvc;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")]
public class CommentControllerTests
{
[Fact]
public async Task PostComment_ShouldPostProfileComment_WhenBodyIsValid()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>test</message></comment>");
const string expectedCommentMessage = "test";
IActionResult result = await commentController.PostComment("unittest", null, 0);
Assert.IsType<OkResult>(result);
CommentEntity? comment = dbMock.Comments.FirstOrDefault();
Assert.NotNull(comment);
Assert.Equal(expectedCommentMessage, comment.Message);
}
[Fact]
public async Task PostComment_ShouldCensorComment_WhenFilterEnabled()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>zamn</message></comment>");
CensorConfiguration.Instance.FilteredWordList = new List<string>
{
"zamn",
};
CensorConfiguration.Instance.UserInputFilterMode = FilterMode.Asterisks;
const string expectedCommentMessage = "****";
IActionResult result = await commentController.PostComment("unittest", null, 0);
Assert.IsType<OkResult>(result);
CommentEntity? comment = dbMock.Comments.FirstOrDefault();
Assert.NotNull(comment);
Assert.Equal(expectedCommentMessage, comment.Message);
}
[Fact]
public async Task PostComment_ShouldCensorComment_WhenFilterDisabled()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>zamn</message></comment>");
CensorConfiguration.Instance.FilteredWordList = new List<string>
{
"zamn",
};
CensorConfiguration.Instance.UserInputFilterMode = FilterMode.None;
IActionResult result = await commentController.PostComment("unittest", null, 0);
const string expectedCommentMessage = "zamn";
Assert.IsType<OkResult>(result);
CommentEntity? comment = dbMock.Comments.FirstOrDefault();
Assert.NotNull(comment);
Assert.Equal(expectedCommentMessage, comment.Message);
}
[Fact]
public async Task PostComment_ShouldPostUserLevelComment_WhenBodyIsValid()
{
List<SlotEntity> slots = new()
{
new SlotEntity
{
SlotId = 1,
CreatorId = 1,
Type = SlotType.User,
},
};
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(slots);
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>test</message></comment>");
const string expectedCommentMessage = "test";
IActionResult result = await commentController.PostComment(null, "user", 1);
Assert.IsType<OkResult>(result);
CommentEntity? comment = dbMock.Comments.FirstOrDefault();
Assert.NotNull(comment);
Assert.Equal(expectedCommentMessage, comment.Message);
}
[Fact]
public async Task PostComment_ShouldPostDeveloperLevelComment_WhenBodyIsValid()
{
List<SlotEntity> slots = new()
{
new SlotEntity
{
SlotId = 1,
InternalSlotId = 12345,
CreatorId = 1,
Type = SlotType.Developer,
},
};
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(slots);
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>test</message></comment>");
const string expectedCommentMessage = "test";
IActionResult result = await commentController.PostComment(null, "developer", 12345);
Assert.IsType<OkResult>(result);
CommentEntity? comment = dbMock.Comments.FirstOrDefault();
Assert.NotNull(comment);
Assert.Equal(expectedCommentMessage, comment.Message);
}
[Fact]
public async Task PostComment_ShouldNotPostProfileComment_WhenTargetProfileInvalid()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>test</message></comment>");
IActionResult result = await commentController.PostComment("unittest2", null, 0);
Assert.IsType<BadRequestResult>(result);
}
[Fact]
public async Task PostComment_ShouldNotPostUserLevelComment_WhenLevelInvalid()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>test</message></comment>");
IActionResult result = await commentController.PostComment(null, "user", 1);
Assert.IsType<BadRequestResult>(result);
}
[Fact]
public async Task PostComment_ShouldNotPostComment_WhenBodyIsEmpty()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("");
IActionResult result = await commentController.PostComment("unittest", null, 0);
Assert.IsType<BadRequestResult>(result);
}
[Fact]
public async Task PostComment_ShouldNotPostComment_WhenBodyIsInvalid()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment></comment>");
IActionResult result = await commentController.PostComment("unittest", null, 0);
Assert.IsType<BadRequestResult>(result);
}
[Fact]
public async Task PostComment_ShouldFail_WhenSlotTypeIsInvalid()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>test</message></comment>");
IActionResult result = await commentController.PostComment(null, "banana", 0);
Assert.IsType<BadRequestResult>(result);
}
[Fact]
public async Task PostComment_ShouldFail_WhenAllArgumentsAreEmpty()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>test</message></comment>");
IActionResult result = await commentController.PostComment(null, null, 0);
Assert.IsType<BadRequestResult>(result);
}
[Fact]
public async Task PostComment_ShouldFail_WhenSlotTypeAndUsernameAreProvided()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>test</message></comment>");
IActionResult result = await commentController.PostComment("unittest", "user", 10);
Assert.IsType<BadRequestResult>(result);
}
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Levels;
using Microsoft.AspNetCore.Mvc;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")]
public class CommentControllerTests
{
[Fact]
public async Task PostComment_ShouldPostProfileComment_WhenBodyIsValid()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>test</message></comment>");
const string expectedCommentMessage = "test";
IActionResult result = await commentController.PostComment("unittest", null, 0);
Assert.IsType<OkResult>(result);
CommentEntity? comment = dbMock.Comments.FirstOrDefault();
Assert.NotNull(comment);
Assert.Equal(expectedCommentMessage, comment.Message);
}
[Fact]
public async Task PostComment_ShouldCensorComment_WhenFilterEnabled()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>zamn</message></comment>");
CensorConfiguration.Instance.FilteredWordList = new List<string>
{
"zamn",
};
CensorConfiguration.Instance.UserInputFilterMode = FilterMode.Asterisks;
const string expectedCommentMessage = "****";
IActionResult result = await commentController.PostComment("unittest", null, 0);
Assert.IsType<OkResult>(result);
CommentEntity? comment = dbMock.Comments.FirstOrDefault();
Assert.NotNull(comment);
Assert.Equal(expectedCommentMessage, comment.Message);
}
[Fact]
public async Task PostComment_ShouldCensorComment_WhenFilterDisabled()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>zamn</message></comment>");
CensorConfiguration.Instance.FilteredWordList = new List<string>
{
"zamn",
};
CensorConfiguration.Instance.UserInputFilterMode = FilterMode.None;
IActionResult result = await commentController.PostComment("unittest", null, 0);
const string expectedCommentMessage = "zamn";
Assert.IsType<OkResult>(result);
CommentEntity? comment = dbMock.Comments.FirstOrDefault();
Assert.NotNull(comment);
Assert.Equal(expectedCommentMessage, comment.Message);
}
[Fact]
public async Task PostComment_ShouldPostUserLevelComment_WhenBodyIsValid()
{
List<SlotEntity> slots = new()
{
new SlotEntity
{
SlotId = 1,
CreatorId = 1,
Type = SlotType.User,
},
};
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(slots);
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>test</message></comment>");
const string expectedCommentMessage = "test";
IActionResult result = await commentController.PostComment(null, "user", 1);
Assert.IsType<OkResult>(result);
CommentEntity? comment = dbMock.Comments.FirstOrDefault();
Assert.NotNull(comment);
Assert.Equal(expectedCommentMessage, comment.Message);
}
[Fact]
public async Task PostComment_ShouldPostDeveloperLevelComment_WhenBodyIsValid()
{
List<SlotEntity> slots = new()
{
new SlotEntity
{
SlotId = 1,
InternalSlotId = 12345,
CreatorId = 1,
Type = SlotType.Developer,
},
};
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(slots);
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>test</message></comment>");
const string expectedCommentMessage = "test";
IActionResult result = await commentController.PostComment(null, "developer", 12345);
Assert.IsType<OkResult>(result);
CommentEntity? comment = dbMock.Comments.FirstOrDefault();
Assert.NotNull(comment);
Assert.Equal(expectedCommentMessage, comment.Message);
}
[Fact]
public async Task PostComment_ShouldNotPostProfileComment_WhenTargetProfileInvalid()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>test</message></comment>");
IActionResult result = await commentController.PostComment("unittest2", null, 0);
Assert.IsType<BadRequestResult>(result);
}
[Fact]
public async Task PostComment_ShouldNotPostUserLevelComment_WhenLevelInvalid()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>test</message></comment>");
IActionResult result = await commentController.PostComment(null, "user", 1);
Assert.IsType<BadRequestResult>(result);
}
[Fact]
public async Task PostComment_ShouldNotPostComment_WhenBodyIsEmpty()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("");
IActionResult result = await commentController.PostComment("unittest", null, 0);
Assert.IsType<BadRequestResult>(result);
}
[Fact]
public async Task PostComment_ShouldNotPostComment_WhenBodyIsInvalid()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment></comment>");
IActionResult result = await commentController.PostComment("unittest", null, 0);
Assert.IsType<BadRequestResult>(result);
}
[Fact]
public async Task PostComment_ShouldFail_WhenSlotTypeIsInvalid()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>test</message></comment>");
IActionResult result = await commentController.PostComment(null, "banana", 0);
Assert.IsType<BadRequestResult>(result);
}
[Fact]
public async Task PostComment_ShouldFail_WhenAllArgumentsAreEmpty()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>test</message></comment>");
IActionResult result = await commentController.PostComment(null, null, 0);
Assert.IsType<BadRequestResult>(result);
}
[Fact]
public async Task PostComment_ShouldFail_WhenSlotTypeAndUsernameAreProvided()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
CommentController commentController = new(dbMock);
commentController.SetupTestController("<comment><message>test</message></comment>");
IActionResult result = await commentController.PostComment("unittest", "user", 10);
Assert.IsType<BadRequestResult>(result);
}
}

View file

@ -1,445 +1,445 @@
using LBPUnion.ProjectLighthouse.Filter;
using LBPUnion.ProjectLighthouse.Filter.Filters;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Slots;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Extensions;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Http;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")]
public class ControllerExtensionTests
{
[Fact]
public void GetDefaultFilters_ShouldReturnFilterBuilder()
{
SlotQueryBuilder queryBuilder = new SlotsController(null!).GetDefaultFilters(MockHelper.GetUnitTestToken());
Assert.NotEmpty(queryBuilder.GetFilters(typeof(GameVersionFilter)));
Assert.NotEmpty(queryBuilder.GetFilters(typeof(HiddenSlotFilter)));
Assert.NotEmpty(queryBuilder.GetFilters(typeof(SlotTypeFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddExcludeLbp1Filter_WhenTokenNotLbp1()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString(),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ExcludeLBP1OnlyFilter)));
}
[Fact]
public void FilterFromRequest_ShouldReturnFilters_WhenQueryEmpty()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString(),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(GameVersionFilter)));
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ExcludeLBP1OnlyFilter)));
Assert.NotEmpty(queryBuilder.GetFilters(typeof(SubLevelFilter)));
Assert.NotEmpty(queryBuilder.GetFilters(typeof(HiddenSlotFilter)));
Assert.NotEmpty(queryBuilder.GetFilters(typeof(SlotTypeFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddLabelFilter_WhenAuthorLabelPresent()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?labelFilter0=LABEL_TEST"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(AuthorLabelFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddPlayerCountFilter_WhenPlayersPresent()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?players=1"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(PlayerCountFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddTextFilter_WhenTextFilterPresent()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?textFilter=test"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(TextFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddFirstUploadedFilter_WhenDateFilterPresent()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?dateFilterType=thisWeek"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(FirstUploadedFilter)));
}
[Fact]
public void FilterFromRequest_ShouldNotAddFirstUploadedFilter_WhenDateFilterInvalid()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?dateFilterType=thisMillenium"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.Empty(queryBuilder.GetFilters(typeof(FirstUploadedFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddExcludeMoveFilter_WhenMoveEqualsFalse()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?move=false"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ExcludeMovePackFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddMoveFilter_WhenMoveEqualsOnly()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?move=only"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(MovePackFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddCrossControlFilter_WhenCrossControlEqualsTrue()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?crosscontrol=true"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(CrossControlFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddExcludeCrossControlFilter_WhenCrossControlNotTrue()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?crosscontrol=false"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ExcludeCrossControlFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddExcludeCrossControlFilter_WhenCrossControlMissing()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString(),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ExcludeCrossControlFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddAdventureFilter_WhenAdventureEqualsAllMust()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet3;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?adventure=allMust"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(AdventureFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddExcludeAdventureFilter_WhenAdventureEqualsNoneCan()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet3;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?adventure=noneCan"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ExcludeAdventureFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddMovePackFilter_WhenMoveEqualsAllMust()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet3;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?move=allMust"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(MovePackFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddExcludeMoveFilter_WhenMoveEqualsNoneCan()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet3;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?move=noneCan"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ExcludeMovePackFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddGameVersionListFilter_WhenGameFilterIsPresent()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet3;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?gameFilter[]=lbp1&gameFilter[]=lbp3"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(GameVersionListFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddResultTypeFilter_WhenResultTypeIsPresent()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet3;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?resultType[]=slot&resultType[]=playlist"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ResultTypeFilter)));
}
using LBPUnion.ProjectLighthouse.Filter;
using LBPUnion.ProjectLighthouse.Filter.Filters;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Slots;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Extensions;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Http;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")]
public class ControllerExtensionTests
{
[Fact]
public void GetDefaultFilters_ShouldReturnFilterBuilder()
{
SlotQueryBuilder queryBuilder = new SlotsController(null!).GetDefaultFilters(MockHelper.GetUnitTestToken());
Assert.NotEmpty(queryBuilder.GetFilters(typeof(GameVersionFilter)));
Assert.NotEmpty(queryBuilder.GetFilters(typeof(HiddenSlotFilter)));
Assert.NotEmpty(queryBuilder.GetFilters(typeof(SlotTypeFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddExcludeLbp1Filter_WhenTokenNotLbp1()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString(),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ExcludeLBP1OnlyFilter)));
}
[Fact]
public void FilterFromRequest_ShouldReturnFilters_WhenQueryEmpty()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString(),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(GameVersionFilter)));
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ExcludeLBP1OnlyFilter)));
Assert.NotEmpty(queryBuilder.GetFilters(typeof(SubLevelFilter)));
Assert.NotEmpty(queryBuilder.GetFilters(typeof(HiddenSlotFilter)));
Assert.NotEmpty(queryBuilder.GetFilters(typeof(SlotTypeFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddLabelFilter_WhenAuthorLabelPresent()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?labelFilter0=LABEL_TEST"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(AuthorLabelFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddPlayerCountFilter_WhenPlayersPresent()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?players=1"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(PlayerCountFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddTextFilter_WhenTextFilterPresent()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?textFilter=test"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(TextFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddFirstUploadedFilter_WhenDateFilterPresent()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?dateFilterType=thisWeek"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(FirstUploadedFilter)));
}
[Fact]
public void FilterFromRequest_ShouldNotAddFirstUploadedFilter_WhenDateFilterInvalid()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?dateFilterType=thisMillenium"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.Empty(queryBuilder.GetFilters(typeof(FirstUploadedFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddExcludeMoveFilter_WhenMoveEqualsFalse()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?move=false"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ExcludeMovePackFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddMoveFilter_WhenMoveEqualsOnly()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?move=only"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(MovePackFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddCrossControlFilter_WhenCrossControlEqualsTrue()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?crosscontrol=true"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(CrossControlFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddExcludeCrossControlFilter_WhenCrossControlNotTrue()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?crosscontrol=false"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ExcludeCrossControlFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddExcludeCrossControlFilter_WhenCrossControlMissing()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString(),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ExcludeCrossControlFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddAdventureFilter_WhenAdventureEqualsAllMust()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet3;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?adventure=allMust"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(AdventureFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddExcludeAdventureFilter_WhenAdventureEqualsNoneCan()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet3;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?adventure=noneCan"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ExcludeAdventureFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddMovePackFilter_WhenMoveEqualsAllMust()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet3;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?move=allMust"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(MovePackFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddExcludeMoveFilter_WhenMoveEqualsNoneCan()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet3;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?move=noneCan"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ExcludeMovePackFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddGameVersionListFilter_WhenGameFilterIsPresent()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet3;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?gameFilter[]=lbp1&gameFilter[]=lbp3"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(GameVersionListFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddResultTypeFilter_WhenResultTypeIsPresent()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet3;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?resultType[]=slot&resultType[]=playlist"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ResultTypeFilter)));
}
}

View file

@ -1,277 +1,277 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Mail;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Mail;
using Microsoft.AspNetCore.Mvc;
using Moq;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")]
public class MessageControllerTests
{
[Fact]
public void Eula_ShouldReturnLicense_WhenConfigEmpty()
{
MessageController messageController = new(null!);
messageController.SetupTestController();
ServerConfiguration.Instance.EulaText = "";
const string expected = @"
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>." + "\n";
IActionResult result = messageController.Eula();
string eulaMsg = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, eulaMsg);
}
[Fact]
public void Eula_ShouldReturnLicenseAndConfigString_WhenConfigNotEmpty()
{
MessageController messageController = new(null!);
messageController.SetupTestController();
ServerConfiguration.Instance.EulaText = "unit test eula text";
const string expected = @"
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>." + "\nunit test eula text";
IActionResult result = messageController.Eula();
string eulaMsg = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, eulaMsg);
}
[Fact]
public async Task Announcement_WithVariables_ShouldBeResolved()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
MessageController messageController = new(dbMock);
messageController.SetupTestController();
ServerConfiguration.Instance.AnnounceText = "you are now logged in as %user (id: %id)";
const string expected = "you are now logged in as unittest (id: 1)";
IActionResult result = await messageController.Announce();
string announceMsg = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, announceMsg);
}
[Fact]
public async Task Announcement_WithEmptyString_ShouldBeEmpty()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
MessageController messageController = new(dbMock);
messageController.SetupTestController();
ServerConfiguration.Instance.AnnounceText = "";
const string expected = "";
IActionResult result = await messageController.Announce();
string announceMsg = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, announceMsg);
}
[Fact]
public async Task Filter_ShouldNotCensor_WhenCensorDisabled()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
const string request = "unit test message";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
CensorConfiguration.Instance.UserInputFilterMode = FilterMode.None;
const string expectedBody = "unit test message";
IActionResult result = await messageController.Filter(new NullMailService());
string filteredMessage = result.CastTo<OkObjectResult, string>();
Assert.Equal(expectedBody, filteredMessage);
}
[Fact]
public async Task Filter_ShouldCensor_WhenCensorEnabled()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
const string request = "unit test message bruh";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
CensorConfiguration.Instance.UserInputFilterMode = FilterMode.Asterisks;
CensorConfiguration.Instance.FilteredWordList = new List<string>
{
"bruh",
};
const string expectedBody = "unit test message ****";
IActionResult result = await messageController.Filter(new NullMailService());
string filteredMessage = result.CastTo<OkObjectResult, string>();
Assert.Equal(expectedBody, filteredMessage);
}
private static Mock<IMailService> getMailServiceMock()
{
Mock<IMailService> mailMock = new();
mailMock.Setup(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns(Task.FromResult(true));
return mailMock;
}
[Fact]
public async Task Filter_ShouldNotSendEmail_WhenMailDisabled()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittest@unittest.com";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = false;
CensorConfiguration.Instance.FilteredWordList = new List<string>();
const string expected = "/setemail unittest@unittest.com";
IActionResult result = await messageController.Filter(mailMock.Object);
string filteredMessage = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, filteredMessage);
}
[Fact]
public async Task Filter_ShouldSendEmail_WhenMailEnabled_AndEmailNotTaken()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittest@unittest.com";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = true;
const string expectedEmail = "unittest@unittest.com";
IActionResult result = await messageController.Filter(mailMock.Object);
Assert.IsType<OkResult>(result);
Assert.Equal(expectedEmail, dbMock.Users.First().EmailAddress);
mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Once);
}
[Fact]
public async Task Filter_ShouldNotSendEmail_WhenMailEnabled_AndEmailTaken()
{
List<UserEntity> users = new()
{
new UserEntity
{
UserId = 2,
EmailAddress = "unittest@unittest.com",
EmailAddressVerified = false,
},
};
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(users);
Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittest@unittest.com";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = true;
IActionResult result = await messageController.Filter(mailMock.Object);
Assert.IsType<OkResult>(result);
mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never);
}
[Fact]
public async Task Filter_ShouldNotSendEmail_WhenMailEnabled_AndEmailAlreadyVerified()
{
UserEntity unitTestUser = MockHelper.GetUnitTestUser();
unitTestUser.EmailAddressVerified = true;
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(new List<UserEntity>
{
unitTestUser,
});
Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittest@unittest.com";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = true;
IActionResult result = await messageController.Filter(mailMock.Object);
Assert.IsType<OkResult>(result);
mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never);
}
[Fact]
public async Task Filter_ShouldNotSendEmail_WhenMailEnabled_AndEmailFormatInvalid()
{
UserEntity unitTestUser = MockHelper.GetUnitTestUser();
unitTestUser.EmailAddressVerified = true;
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittestinvalidemail@@@";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = true;
IActionResult result = await messageController.Filter(mailMock.Object);
Assert.IsType<OkResult>(result);
mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never);
}
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Mail;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Mail;
using Microsoft.AspNetCore.Mvc;
using Moq;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")]
public class MessageControllerTests
{
[Fact]
public void Eula_ShouldReturnLicense_WhenConfigEmpty()
{
MessageController messageController = new(null!);
messageController.SetupTestController();
ServerConfiguration.Instance.EulaText = "";
const string expected = @"
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>." + "\n";
IActionResult result = messageController.Eula();
string eulaMsg = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, eulaMsg);
}
[Fact]
public void Eula_ShouldReturnLicenseAndConfigString_WhenConfigNotEmpty()
{
MessageController messageController = new(null!);
messageController.SetupTestController();
ServerConfiguration.Instance.EulaText = "unit test eula text";
const string expected = @"
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>." + "\nunit test eula text";
IActionResult result = messageController.Eula();
string eulaMsg = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, eulaMsg);
}
[Fact]
public async Task Announcement_WithVariables_ShouldBeResolved()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
MessageController messageController = new(dbMock);
messageController.SetupTestController();
ServerConfiguration.Instance.AnnounceText = "you are now logged in as %user (id: %id)";
const string expected = "you are now logged in as unittest (id: 1)";
IActionResult result = await messageController.Announce();
string announceMsg = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, announceMsg);
}
[Fact]
public async Task Announcement_WithEmptyString_ShouldBeEmpty()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
MessageController messageController = new(dbMock);
messageController.SetupTestController();
ServerConfiguration.Instance.AnnounceText = "";
const string expected = "";
IActionResult result = await messageController.Announce();
string announceMsg = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, announceMsg);
}
[Fact]
public async Task Filter_ShouldNotCensor_WhenCensorDisabled()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
const string request = "unit test message";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
CensorConfiguration.Instance.UserInputFilterMode = FilterMode.None;
const string expectedBody = "unit test message";
IActionResult result = await messageController.Filter(new NullMailService());
string filteredMessage = result.CastTo<OkObjectResult, string>();
Assert.Equal(expectedBody, filteredMessage);
}
[Fact]
public async Task Filter_ShouldCensor_WhenCensorEnabled()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
const string request = "unit test message bruh";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
CensorConfiguration.Instance.UserInputFilterMode = FilterMode.Asterisks;
CensorConfiguration.Instance.FilteredWordList = new List<string>
{
"bruh",
};
const string expectedBody = "unit test message ****";
IActionResult result = await messageController.Filter(new NullMailService());
string filteredMessage = result.CastTo<OkObjectResult, string>();
Assert.Equal(expectedBody, filteredMessage);
}
private static Mock<IMailService> getMailServiceMock()
{
Mock<IMailService> mailMock = new();
mailMock.Setup(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns(Task.FromResult(true));
return mailMock;
}
[Fact]
public async Task Filter_ShouldNotSendEmail_WhenMailDisabled()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittest@unittest.com";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = false;
CensorConfiguration.Instance.FilteredWordList = new List<string>();
const string expected = "/setemail unittest@unittest.com";
IActionResult result = await messageController.Filter(mailMock.Object);
string filteredMessage = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, filteredMessage);
}
[Fact]
public async Task Filter_ShouldSendEmail_WhenMailEnabled_AndEmailNotTaken()
{
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittest@unittest.com";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = true;
const string expectedEmail = "unittest@unittest.com";
IActionResult result = await messageController.Filter(mailMock.Object);
Assert.IsType<OkResult>(result);
Assert.Equal(expectedEmail, dbMock.Users.First().EmailAddress);
mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Once);
}
[Fact]
public async Task Filter_ShouldNotSendEmail_WhenMailEnabled_AndEmailTaken()
{
List<UserEntity> users = new()
{
new UserEntity
{
UserId = 2,
EmailAddress = "unittest@unittest.com",
EmailAddressVerified = false,
},
};
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(users);
Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittest@unittest.com";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = true;
IActionResult result = await messageController.Filter(mailMock.Object);
Assert.IsType<OkResult>(result);
mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never);
}
[Fact]
public async Task Filter_ShouldNotSendEmail_WhenMailEnabled_AndEmailAlreadyVerified()
{
UserEntity unitTestUser = MockHelper.GetUnitTestUser();
unitTestUser.EmailAddressVerified = true;
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(new List<UserEntity>
{
unitTestUser,
});
Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittest@unittest.com";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = true;
IActionResult result = await messageController.Filter(mailMock.Object);
Assert.IsType<OkResult>(result);
mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never);
}
[Fact]
public async Task Filter_ShouldNotSendEmail_WhenMailEnabled_AndEmailFormatInvalid()
{
UserEntity unitTestUser = MockHelper.GetUnitTestUser();
unitTestUser.EmailAddressVerified = true;
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittestinvalidemail@@@";
MessageController messageController = new(dbMock);
messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = true;
IActionResult result = await messageController.Filter(mailMock.Object);
Assert.IsType<OkResult>(result);
mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never);
}
}

View file

@ -1,100 +1,100 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Slots;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Mvc;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")]
public class ReviewControllerTests
{
private static async Task InsertTestData(DatabaseContext database)
{
database.Slots.Add(new SlotEntity
{
SlotId = 1,
CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet3,
});
database.Slots.Add(new SlotEntity
{
SlotId = 2,
CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet2,
});
database.Reviews.Add(new ReviewEntity
{
ReviewId = 1,
ReviewerId = 1,
SlotId = 1,
});
database.Reviews.Add(new ReviewEntity
{
ReviewId = 2,
ReviewerId = 1,
SlotId = 2,
});
await database.SaveChangesAsync();
}
[Theory]
[InlineData(GameVersion.LittleBigPlanet2, 1)]
[InlineData(GameVersion.LittleBigPlanet3, 2)]
public async Task ReviewsBy_ShouldNotList_HigherGameVersions(GameVersion version, int expected)
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = version;
DatabaseContext database = await MockHelper.GetTestDatabase(new List<GameTokenEntity>
{
token,
});
await InsertTestData(database);
ReviewController controller = new(database);
controller.SetupTestController(token);
IActionResult response = await controller.ReviewsBy("unittest");
ReviewResponse review = response.CastTo<OkObjectResult, ReviewResponse>();
Assert.Equal(expected, review.Reviews.Count);
Assert.True(review.Reviews.All(r => database.Slots.FirstOrDefault(s => s.SlotId == r.Slot.SlotId)?.GameVersion <= version));
}
[Theory]
[InlineData(GameVersion.LittleBigPlanet2, 2, 1)]
[InlineData(GameVersion.LittleBigPlanet2, 1, 0)]
[InlineData(GameVersion.LittleBigPlanet3, 2, 1)]
[InlineData(GameVersion.LittleBigPlanet3, 1, 1)]
public async Task ReviewsFor_ShouldNotList_HigherGameVersions(GameVersion version, int slotId, int expected)
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = version;
DatabaseContext database = await MockHelper.GetTestDatabase(new List<GameTokenEntity>
{
token,
});
await InsertTestData(database);
ReviewController controller = new(database);
controller.SetupTestController(token);
IActionResult response = await controller.ReviewsFor(slotId);
ReviewResponse review = response.CastTo<OkObjectResult, ReviewResponse>();
Assert.Equal(expected, review.Reviews.Count);
Assert.True(review.Reviews.All(r => database.Slots.FirstOrDefault(s => s.SlotId == r.Slot.SlotId)?.GameVersion <= version));
}
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Slots;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Mvc;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")]
public class ReviewControllerTests
{
private static async Task InsertTestData(DatabaseContext database)
{
database.Slots.Add(new SlotEntity
{
SlotId = 1,
CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet3,
});
database.Slots.Add(new SlotEntity
{
SlotId = 2,
CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet2,
});
database.Reviews.Add(new ReviewEntity
{
ReviewId = 1,
ReviewerId = 1,
SlotId = 1,
});
database.Reviews.Add(new ReviewEntity
{
ReviewId = 2,
ReviewerId = 1,
SlotId = 2,
});
await database.SaveChangesAsync();
}
[Theory]
[InlineData(GameVersion.LittleBigPlanet2, 1)]
[InlineData(GameVersion.LittleBigPlanet3, 2)]
public async Task ReviewsBy_ShouldNotList_HigherGameVersions(GameVersion version, int expected)
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = version;
DatabaseContext database = await MockHelper.GetTestDatabase(new List<GameTokenEntity>
{
token,
});
await InsertTestData(database);
ReviewController controller = new(database);
controller.SetupTestController(token);
IActionResult response = await controller.ReviewsBy("unittest");
ReviewResponse review = response.CastTo<OkObjectResult, ReviewResponse>();
Assert.Equal(expected, review.Reviews.Count);
Assert.True(review.Reviews.All(r => database.Slots.FirstOrDefault(s => s.SlotId == r.Slot.SlotId)?.GameVersion <= version));
}
[Theory]
[InlineData(GameVersion.LittleBigPlanet2, 2, 1)]
[InlineData(GameVersion.LittleBigPlanet2, 1, 0)]
[InlineData(GameVersion.LittleBigPlanet3, 2, 1)]
[InlineData(GameVersion.LittleBigPlanet3, 1, 1)]
public async Task ReviewsFor_ShouldNotList_HigherGameVersions(GameVersion version, int slotId, int expected)
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = version;
DatabaseContext database = await MockHelper.GetTestDatabase(new List<GameTokenEntity>
{
token,
});
await InsertTestData(database);
ReviewController controller = new(database);
controller.SetupTestController(token);
IActionResult response = await controller.ReviewsFor(slotId);
ReviewResponse review = response.CastTo<OkObjectResult, ReviewResponse>();
Assert.Equal(expected, review.Reviews.Count);
Assert.True(review.Reviews.All(r => database.Slots.FirstOrDefault(s => s.SlotId == r.Slot.SlotId)?.GameVersion <= version));
}
}

View file

@ -1,161 +1,161 @@
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Slots;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using Microsoft.AspNetCore.Mvc;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")]
public class ScoreControllerTests
{
[Fact]
public async Task SubmitScore_ShouldSubmitValidScore_WhenNoExistingScore()
{
DatabaseContext database = await MockHelper.GetTestDatabase();
SlotEntity slot = new()
{
CreatorId = 1,
SlotId = 1,
};
database.Slots.Add(slot);
await database.SaveChangesAsync();
ScoreController scoreController = new(database);
const string xmlBody = """
<playRecord>
<type>1</type>
<score>10</score>
<playerIds>unittest</playerIds>
</playRecord>
""";
scoreController.SetupTestController(xmlBody);
IActionResult result = await scoreController.SubmitScore("user", 1, 0);
Assert.IsType<OkObjectResult>(result);
Assert.NotNull(database.Scores.FirstOrDefault(s => s.Type == 1 && s.SlotId == 1 && s.UserId == 1));
}
[Fact]
public async Task SubmitScore_ShouldUpdateScore_WhenBetterThanExistingScore()
{
DatabaseContext database = await MockHelper.GetTestDatabase();
SlotEntity slot = new()
{
CreatorId = 1,
SlotId = 1,
};
database.Slots.Add(slot);
ScoreEntity score = new()
{
SlotId = 1,
Type = 1,
UserId = 1,
Points = 5,
Timestamp = 0,
};
database.Scores.Add(score);
await database.SaveChangesAsync();
ScoreController scoreController = new(database);
const string xmlBody = """
<playRecord>
<type>1</type>
<score>10</score>
<playerIds>unittest</playerIds>
</playRecord>
""";
scoreController.SetupTestController(xmlBody);
IActionResult result = await scoreController.SubmitScore("user", 1, 0);
Assert.IsType<OkObjectResult>(result);
ScoreEntity? newScore = database.Scores.FirstOrDefault(s => s.Type == 1 && s.SlotId == 1 && s.UserId == 1);
Assert.NotNull(newScore);
Assert.NotEqual(0, newScore.Timestamp);
Assert.Equal(10, newScore.Points);
}
[Fact]
public async Task SubmitScore_ShouldNotUpdateScore_WhenEqualToExistingScore()
{
DatabaseContext database = await MockHelper.GetTestDatabase();
SlotEntity slot = new()
{
CreatorId = 1,
SlotId = 1,
};
database.Slots.Add(slot);
ScoreEntity score = new()
{
SlotId = 1,
Type = 1,
UserId = 1,
Points = 10,
Timestamp = 0,
};
database.Scores.Add(score);
await database.SaveChangesAsync();
ScoreController scoreController = new(database);
const string xmlBody = """
<playRecord>
<type>1</type>
<score>10</score>
<playerIds>unittest</playerIds>
</playRecord>
""";
scoreController.SetupTestController(xmlBody);
IActionResult result = await scoreController.SubmitScore("user", 1, 0);
Assert.IsType<OkObjectResult>(result);
ScoreEntity? newScore = database.Scores.FirstOrDefault(s => s.Type == 1 && s.SlotId == 1 && s.UserId == 1);
Assert.NotNull(newScore);
Assert.Equal(0, newScore.Timestamp);
Assert.Equal(10, newScore.Points);
}
[Fact]
public async Task SubmitScore_ShouldNotUpdateScore_WhenLessThanExistingScore()
{
DatabaseContext database = await MockHelper.GetTestDatabase();
SlotEntity slot = new()
{
CreatorId = 1,
SlotId = 1,
};
database.Slots.Add(slot);
ScoreEntity score = new()
{
SlotId = 1,
Type = 1,
UserId = 1,
Points = 10,
Timestamp = 0,
};
database.Scores.Add(score);
await database.SaveChangesAsync();
ScoreController scoreController = new(database);
const string xmlBody = """
<playRecord>
<type>1</type>
<score>5</score>
<playerIds>unittest</playerIds>
</playRecord>
""";
scoreController.SetupTestController(xmlBody);
IActionResult result = await scoreController.SubmitScore("user", 1, 0);
Assert.IsType<OkObjectResult>(result);
ScoreEntity? newScore = database.Scores.FirstOrDefault(s => s.Type == 1 && s.SlotId == 1 && s.UserId == 1);
Assert.NotNull(newScore);
Assert.Equal(0, newScore.Timestamp);
Assert.Equal(10, newScore.Points);
}
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Slots;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using Microsoft.AspNetCore.Mvc;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")]
public class ScoreControllerTests
{
[Fact]
public async Task SubmitScore_ShouldSubmitValidScore_WhenNoExistingScore()
{
DatabaseContext database = await MockHelper.GetTestDatabase();
SlotEntity slot = new()
{
CreatorId = 1,
SlotId = 1,
};
database.Slots.Add(slot);
await database.SaveChangesAsync();
ScoreController scoreController = new(database);
const string xmlBody = """
<playRecord>
<type>1</type>
<score>10</score>
<playerIds>unittest</playerIds>
</playRecord>
""";
scoreController.SetupTestController(xmlBody);
IActionResult result = await scoreController.SubmitScore("user", 1, 0);
Assert.IsType<OkObjectResult>(result);
Assert.NotNull(database.Scores.FirstOrDefault(s => s.Type == 1 && s.SlotId == 1 && s.UserId == 1));
}
[Fact]
public async Task SubmitScore_ShouldUpdateScore_WhenBetterThanExistingScore()
{
DatabaseContext database = await MockHelper.GetTestDatabase();
SlotEntity slot = new()
{
CreatorId = 1,
SlotId = 1,
};
database.Slots.Add(slot);
ScoreEntity score = new()
{
SlotId = 1,
Type = 1,
UserId = 1,
Points = 5,
Timestamp = 0,
};
database.Scores.Add(score);
await database.SaveChangesAsync();
ScoreController scoreController = new(database);
const string xmlBody = """
<playRecord>
<type>1</type>
<score>10</score>
<playerIds>unittest</playerIds>
</playRecord>
""";
scoreController.SetupTestController(xmlBody);
IActionResult result = await scoreController.SubmitScore("user", 1, 0);
Assert.IsType<OkObjectResult>(result);
ScoreEntity? newScore = database.Scores.FirstOrDefault(s => s.Type == 1 && s.SlotId == 1 && s.UserId == 1);
Assert.NotNull(newScore);
Assert.NotEqual(0, newScore.Timestamp);
Assert.Equal(10, newScore.Points);
}
[Fact]
public async Task SubmitScore_ShouldNotUpdateScore_WhenEqualToExistingScore()
{
DatabaseContext database = await MockHelper.GetTestDatabase();
SlotEntity slot = new()
{
CreatorId = 1,
SlotId = 1,
};
database.Slots.Add(slot);
ScoreEntity score = new()
{
SlotId = 1,
Type = 1,
UserId = 1,
Points = 10,
Timestamp = 0,
};
database.Scores.Add(score);
await database.SaveChangesAsync();
ScoreController scoreController = new(database);
const string xmlBody = """
<playRecord>
<type>1</type>
<score>10</score>
<playerIds>unittest</playerIds>
</playRecord>
""";
scoreController.SetupTestController(xmlBody);
IActionResult result = await scoreController.SubmitScore("user", 1, 0);
Assert.IsType<OkObjectResult>(result);
ScoreEntity? newScore = database.Scores.FirstOrDefault(s => s.Type == 1 && s.SlotId == 1 && s.UserId == 1);
Assert.NotNull(newScore);
Assert.Equal(0, newScore.Timestamp);
Assert.Equal(10, newScore.Points);
}
[Fact]
public async Task SubmitScore_ShouldNotUpdateScore_WhenLessThanExistingScore()
{
DatabaseContext database = await MockHelper.GetTestDatabase();
SlotEntity slot = new()
{
CreatorId = 1,
SlotId = 1,
};
database.Slots.Add(slot);
ScoreEntity score = new()
{
SlotId = 1,
Type = 1,
UserId = 1,
Points = 10,
Timestamp = 0,
};
database.Scores.Add(score);
await database.SaveChangesAsync();
ScoreController scoreController = new(database);
const string xmlBody = """
<playRecord>
<type>1</type>
<score>5</score>
<playerIds>unittest</playerIds>
</playRecord>
""";
scoreController.SetupTestController(xmlBody);
IActionResult result = await scoreController.SubmitScore("user", 1, 0);
Assert.IsType<OkObjectResult>(result);
ScoreEntity? newScore = database.Scores.FirstOrDefault(s => s.Type == 1 && s.SlotId == 1 && s.UserId == 1);
Assert.NotNull(newScore);
Assert.Equal(0, newScore.Timestamp);
Assert.Equal(10, newScore.Points);
}
}

View file

@ -1,187 +1,187 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Mvc;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")]
public class StatisticsControllerTests
{
[Fact]
public async Task PlanetStats_ShouldReturnCorrectCounts_WhenEmpty()
{
await using DatabaseContext db = await MockHelper.GetTestDatabase();
StatisticsController statsController = new(db);
statsController.SetupTestController();
const int expectedSlots = 0;
const int expectedTeamPicks = 0;
IActionResult result = await statsController.PlanetStats();
PlanetStatsResponse statsResponse = result.CastTo<OkObjectResult, PlanetStatsResponse>();
Assert.Equal(expectedSlots, statsResponse.TotalSlotCount);
Assert.Equal(expectedTeamPicks, statsResponse.TeamPickCount);
}
[Fact]
public async Task PlanetStats_ShouldReturnCorrectCounts_WhenNotEmpty()
{
List<SlotEntity> slots = new()
{
new SlotEntity
{
SlotId = 1,
CreatorId = 1,
},
new SlotEntity
{
SlotId = 2,
CreatorId = 1,
},
new SlotEntity
{
SlotId = 3,
CreatorId = 1,
TeamPickTime = 1,
},
};
await using DatabaseContext db = await MockHelper.GetTestDatabase(slots);
StatisticsController statsController = new(db);
statsController.SetupTestController();
const int expectedSlots = 3;
const int expectedTeamPicks = 1;
IActionResult result = await statsController.PlanetStats();
PlanetStatsResponse statsResponse = result.CastTo<OkObjectResult, PlanetStatsResponse>();
Assert.Equal(expectedSlots, statsResponse.TotalSlotCount);
Assert.Equal(expectedTeamPicks, statsResponse.TeamPickCount);
}
[Fact]
public async Task PlanetStats_ShouldReturnCorrectCounts_WhenSlotsAreIncompatibleGameVersion()
{
List<SlotEntity> slots = new()
{
new SlotEntity
{
SlotId = 1,
CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet2,
},
new SlotEntity
{
SlotId = 2,
CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet2,
},
new SlotEntity
{
SlotId = 3,
CreatorId = 1,
TeamPickTime = 1,
GameVersion = GameVersion.LittleBigPlanet2,
},
};
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(slots);
StatisticsController statsController = new(dbMock);
statsController.SetupTestController();
const int expectedSlots = 0;
const int expectedTeamPicks = 0;
IActionResult result = await statsController.PlanetStats();
PlanetStatsResponse statsResponse = result.CastTo<OkObjectResult, PlanetStatsResponse>();
Assert.Equal(expectedSlots, statsResponse.TotalSlotCount);
Assert.Equal(expectedTeamPicks, statsResponse.TeamPickCount);
}
[Fact]
public async Task TotalLevelCount_ShouldReturnCorrectCount_WhenSlotsAreCompatible()
{
List<SlotEntity> slots = new()
{
new SlotEntity
{
SlotId = 1,
CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet1,
},
new SlotEntity
{
SlotId = 2,
CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet1,
},
new SlotEntity
{
SlotId = 3,
CreatorId = 1,
TeamPickTime = 1,
GameVersion = GameVersion.LittleBigPlanet1,
},
};
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(slots);
StatisticsController statsController = new(dbMock);
statsController.SetupTestController();
const string expectedTotal = "3";
IActionResult result = await statsController.TotalLevelCount();
string totalSlotsResponse = result.CastTo<OkObjectResult, string>();
Assert.Equal(expectedTotal, totalSlotsResponse);
}
[Fact]
public async Task TotalLevelCount_ShouldReturnCorrectCount_WhenSlotsAreNotCompatible()
{
List<SlotEntity> slots = new()
{
new SlotEntity
{
SlotId = 1,
CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet2,
},
new SlotEntity
{
SlotId = 2,
CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet2,
},
new SlotEntity
{
SlotId = 3,
CreatorId = 1,
TeamPickTime = 1,
GameVersion = GameVersion.LittleBigPlanet2,
},
};
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(slots);
StatisticsController statsController = new(dbMock);
statsController.SetupTestController();
const string expectedTotal = "0";
IActionResult result = await statsController.TotalLevelCount();
string totalSlots = result.CastTo<OkObjectResult, string>();
Assert.Equal(expectedTotal, totalSlots);
}
using System.Collections.Generic;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Mvc;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")]
public class StatisticsControllerTests
{
[Fact]
public async Task PlanetStats_ShouldReturnCorrectCounts_WhenEmpty()
{
await using DatabaseContext db = await MockHelper.GetTestDatabase();
StatisticsController statsController = new(db);
statsController.SetupTestController();
const int expectedSlots = 0;
const int expectedTeamPicks = 0;
IActionResult result = await statsController.PlanetStats();
PlanetStatsResponse statsResponse = result.CastTo<OkObjectResult, PlanetStatsResponse>();
Assert.Equal(expectedSlots, statsResponse.TotalSlotCount);
Assert.Equal(expectedTeamPicks, statsResponse.TeamPickCount);
}
[Fact]
public async Task PlanetStats_ShouldReturnCorrectCounts_WhenNotEmpty()
{
List<SlotEntity> slots = new()
{
new SlotEntity
{
SlotId = 1,
CreatorId = 1,
},
new SlotEntity
{
SlotId = 2,
CreatorId = 1,
},
new SlotEntity
{
SlotId = 3,
CreatorId = 1,
TeamPickTime = 1,
},
};
await using DatabaseContext db = await MockHelper.GetTestDatabase(slots);
StatisticsController statsController = new(db);
statsController.SetupTestController();
const int expectedSlots = 3;
const int expectedTeamPicks = 1;
IActionResult result = await statsController.PlanetStats();
PlanetStatsResponse statsResponse = result.CastTo<OkObjectResult, PlanetStatsResponse>();
Assert.Equal(expectedSlots, statsResponse.TotalSlotCount);
Assert.Equal(expectedTeamPicks, statsResponse.TeamPickCount);
}
[Fact]
public async Task PlanetStats_ShouldReturnCorrectCounts_WhenSlotsAreIncompatibleGameVersion()
{
List<SlotEntity> slots = new()
{
new SlotEntity
{
SlotId = 1,
CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet2,
},
new SlotEntity
{
SlotId = 2,
CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet2,
},
new SlotEntity
{
SlotId = 3,
CreatorId = 1,
TeamPickTime = 1,
GameVersion = GameVersion.LittleBigPlanet2,
},
};
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(slots);
StatisticsController statsController = new(dbMock);
statsController.SetupTestController();
const int expectedSlots = 0;
const int expectedTeamPicks = 0;
IActionResult result = await statsController.PlanetStats();
PlanetStatsResponse statsResponse = result.CastTo<OkObjectResult, PlanetStatsResponse>();
Assert.Equal(expectedSlots, statsResponse.TotalSlotCount);
Assert.Equal(expectedTeamPicks, statsResponse.TeamPickCount);
}
[Fact]
public async Task TotalLevelCount_ShouldReturnCorrectCount_WhenSlotsAreCompatible()
{
List<SlotEntity> slots = new()
{
new SlotEntity
{
SlotId = 1,
CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet1,
},
new SlotEntity
{
SlotId = 2,
CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet1,
},
new SlotEntity
{
SlotId = 3,
CreatorId = 1,
TeamPickTime = 1,
GameVersion = GameVersion.LittleBigPlanet1,
},
};
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(slots);
StatisticsController statsController = new(dbMock);
statsController.SetupTestController();
const string expectedTotal = "3";
IActionResult result = await statsController.TotalLevelCount();
string totalSlotsResponse = result.CastTo<OkObjectResult, string>();
Assert.Equal(expectedTotal, totalSlotsResponse);
}
[Fact]
public async Task TotalLevelCount_ShouldReturnCorrectCount_WhenSlotsAreNotCompatible()
{
List<SlotEntity> slots = new()
{
new SlotEntity
{
SlotId = 1,
CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet2,
},
new SlotEntity
{
SlotId = 2,
CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet2,
},
new SlotEntity
{
SlotId = 3,
CreatorId = 1,
TeamPickTime = 1,
GameVersion = GameVersion.LittleBigPlanet2,
},
};
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(slots);
StatisticsController statsController = new(dbMock);
statsController.SetupTestController();
const string expectedTotal = "0";
IActionResult result = await statsController.TotalLevelCount();
string totalSlots = result.CastTo<OkObjectResult, string>();
Assert.Equal(expectedTotal, totalSlots);
}
}

View file

@ -1,23 +1,23 @@
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using Microsoft.AspNetCore.Mvc;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")]
public class StatusControllerTests
{
[Fact]
public void Status_ShouldReturnOk()
{
StatusController statusController = new()
{
ControllerContext = MockHelper.GetMockControllerContext(),
};
IActionResult result = statusController.GetStatus();
Assert.IsType<OkResult>(result);
}
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using Microsoft.AspNetCore.Mvc;
using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")]
public class StatusControllerTests
{
[Fact]
public void Status_ShouldReturnOk()
{
StatusController statusController = new()
{
ControllerContext = MockHelper.GetMockControllerContext(),
};
IActionResult result = statusController.GetStatus();
Assert.IsType<OkResult>(result);
}
}

View file

@ -0,0 +1,22 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("ProjectLighthouse.Tests.GameApiTests")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+509240db396eac0c69bd7ed8e09b71f630a8de72")]
[assembly: System.Reflection.AssemblyProductAttribute("ProjectLighthouse.Tests.GameApiTests")]
[assembly: System.Reflection.AssemblyTitleAttribute("ProjectLighthouse.Tests.GameApiTests")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// Generated by the MSBuild WriteCodeFragment class.

View file

@ -0,0 +1 @@
c3ee125177a364af52566ca8c97497fe46e4fe23e03e9c737cf2fd1caaaee833

View file

@ -0,0 +1,15 @@
is_global = true
build_property.TargetFramework = net8.0
build_property.TargetPlatformMinVersion =
build_property.UsingMicrosoftNETSdkWeb =
build_property.ProjectTypeGuids =
build_property.InvariantGlobalization =
build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules =
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = ProjectLighthouse.Tests.GameApiTests
build_property.ProjectDir = G:\LBP 3 ONLINE ARCHIVE\LBP 3 ONLINE SITE RECREACTION\ProjectLighthouse\ProjectLighthouse.Tests.GameApiTests\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.EffectiveAnalysisLevelStyle = 8.0
build_property.EnableCodeStyleSeverity =

View file

@ -0,0 +1,555 @@
{
"format": 1,
"restore": {
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests.GameApiTests\\ProjectLighthouse.Tests.GameApiTests.csproj": {}
},
"projects": {
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj",
"projectName": "ProjectLighthouse.Localization",
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj",
"packagesPath": "C:\\Users\\Faisa\\.nuget\\packages\\",
"outputPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\obj\\",
"projectStyle": "PackageReference",
"configFilePaths": [
"C:\\Users\\Faisa\\AppData\\Roaming\\NuGet\\NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.300"
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"downloadDependencies": [
{
"name": "Microsoft.AspNetCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.NETCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.WindowsDesktop.App.Ref",
"version": "[8.0.19, 8.0.19]"
}
],
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.304/PortableRuntimeIdentifierGraph.json"
}
}
},
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Servers.GameServer\\ProjectLighthouse.Servers.GameServer.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Servers.GameServer\\ProjectLighthouse.Servers.GameServer.csproj",
"projectName": "LBPUnion.ProjectLighthouse.Servers.GameServer",
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Servers.GameServer\\ProjectLighthouse.Servers.GameServer.csproj",
"packagesPath": "C:\\Users\\Faisa\\.nuget\\packages\\",
"outputPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Servers.GameServer\\obj\\",
"projectStyle": "PackageReference",
"configFilePaths": [
"C:\\Users\\Faisa\\AppData\\Roaming\\NuGet\\NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj": {
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj"
}
}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.300"
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"downloadDependencies": [
{
"name": "Microsoft.AspNetCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.NETCore.App.Host.win-x64",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.NETCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.WindowsDesktop.App.Ref",
"version": "[8.0.19, 8.0.19]"
}
],
"frameworkReferences": {
"Microsoft.AspNetCore.App": {
"privateAssets": "none"
},
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.304/PortableRuntimeIdentifierGraph.json"
}
}
},
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests.GameApiTests\\ProjectLighthouse.Tests.GameApiTests.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests.GameApiTests\\ProjectLighthouse.Tests.GameApiTests.csproj",
"projectName": "ProjectLighthouse.Tests.GameApiTests",
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests.GameApiTests\\ProjectLighthouse.Tests.GameApiTests.csproj",
"packagesPath": "C:\\Users\\Faisa\\.nuget\\packages\\",
"outputPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests.GameApiTests\\obj\\",
"projectStyle": "PackageReference",
"configFilePaths": [
"C:\\Users\\Faisa\\AppData\\Roaming\\NuGet\\NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Servers.GameServer\\ProjectLighthouse.Servers.GameServer.csproj": {
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Servers.GameServer\\ProjectLighthouse.Servers.GameServer.csproj"
},
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\ProjectLighthouse.Tests.csproj": {
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\ProjectLighthouse.Tests.csproj"
},
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj": {
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj"
}
}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.300"
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"dependencies": {
"JetBrains.Annotations": {
"target": "Package",
"version": "[2024.3.0, )"
},
"Microsoft.AspNetCore.Mvc.Testing": {
"target": "Package",
"version": "[8.0.18, )"
},
"Microsoft.EntityFrameworkCore.Design": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[8.0.18, )"
},
"Microsoft.NET.Test.Sdk": {
"target": "Package",
"version": "[17.14.1, )"
},
"coverlet.collector": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[6.0.4, )"
},
"xunit": {
"target": "Package",
"version": "[2.9.3, )"
},
"xunit.runner.visualstudio": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[3.1.1, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"downloadDependencies": [
{
"name": "Microsoft.AspNetCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.NETCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.WindowsDesktop.App.Ref",
"version": "[8.0.19, 8.0.19]"
}
],
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.304/PortableRuntimeIdentifierGraph.json"
}
}
},
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\ProjectLighthouse.Tests.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\ProjectLighthouse.Tests.csproj",
"projectName": "LBPUnion.ProjectLighthouse.Tests",
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\ProjectLighthouse.Tests.csproj",
"packagesPath": "C:\\Users\\Faisa\\.nuget\\packages\\",
"outputPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\obj\\",
"projectStyle": "PackageReference",
"configFilePaths": [
"C:\\Users\\Faisa\\AppData\\Roaming\\NuGet\\NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj": {
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj"
}
}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.300"
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"dependencies": {
"JetBrains.Annotations": {
"target": "Package",
"version": "[2024.3.0, )"
},
"Microsoft.AspNetCore.Mvc.Testing": {
"target": "Package",
"version": "[8.0.18, )"
},
"Microsoft.EntityFrameworkCore.Design": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[8.0.18, )"
},
"Microsoft.EntityFrameworkCore.Sqlite": {
"target": "Package",
"version": "[8.0.6, )"
},
"Microsoft.NET.Test.Sdk": {
"target": "Package",
"version": "[17.14.1, )"
},
"Moq": {
"target": "Package",
"version": "[4.20.72, )"
},
"coverlet.collector": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[6.0.4, )"
},
"xunit": {
"target": "Package",
"version": "[2.9.3, )"
},
"xunit.runner.visualstudio": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[3.1.1, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"downloadDependencies": [
{
"name": "Microsoft.AspNetCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.NETCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.WindowsDesktop.App.Ref",
"version": "[8.0.19, 8.0.19]"
}
],
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.304/PortableRuntimeIdentifierGraph.json"
}
}
},
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj",
"projectName": "LBPUnion.ProjectLighthouse",
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj",
"packagesPath": "C:\\Users\\Faisa\\.nuget\\packages\\",
"outputPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\obj\\",
"projectStyle": "PackageReference",
"configFilePaths": [
"C:\\Users\\Faisa\\AppData\\Roaming\\NuGet\\NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj": {
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj"
}
}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.300"
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"dependencies": {
"BCrypt.Net-Next": {
"target": "Package",
"version": "[4.0.3, )"
},
"BouncyCastle.Cryptography": {
"target": "Package",
"version": "[2.6.1, )"
},
"Discord.Net.Webhook": {
"target": "Package",
"version": "[3.17.4, )"
},
"DistributedLock.MySql": {
"target": "Package",
"version": "[1.0.2, )"
},
"GitInfo": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[3.5.0, )"
},
"JetBrains.Annotations": {
"target": "Package",
"version": "[2024.3.0, )"
},
"Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore": {
"target": "Package",
"version": "[8.0.18, )"
},
"Microsoft.EntityFrameworkCore": {
"target": "Package",
"version": "[8.0.18, )"
},
"Microsoft.EntityFrameworkCore.Design": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[8.0.18, )"
},
"Pfim": {
"target": "Package",
"version": "[0.11.3, )"
},
"Pomelo.EntityFrameworkCore.MySql": {
"target": "Package",
"version": "[8.0.2, )"
},
"Redis.OM": {
"target": "Package",
"version": "[1.0.1, )"
},
"SharpZipLib": {
"target": "Package",
"version": "[1.4.2, )"
},
"SixLabors.ImageSharp": {
"target": "Package",
"version": "[3.1.10, )"
},
"Swashbuckle.AspNetCore": {
"target": "Package",
"version": "[9.0.3, )"
},
"YamlDotNet": {
"target": "Package",
"version": "[16.3.0, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"downloadDependencies": [
{
"name": "Microsoft.AspNetCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.NETCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.WindowsDesktop.App.Ref",
"version": "[8.0.19, 8.0.19]"
}
],
"frameworkReferences": {
"Microsoft.AspNetCore.App": {
"privateAssets": "none"
},
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.304/PortableRuntimeIdentifierGraph.json"
}
}
}
}
}

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\Faisa\.nuget\packages\</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.14.0</NuGetToolVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="C:\Users\Faisa\.nuget\packages\" />
</ItemGroup>
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)xunit.runner.visualstudio\3.1.1\build\net8.0\xunit.runner.visualstudio.props" Condition="Exists('$(NuGetPackageRoot)xunit.runner.visualstudio\3.1.1\build\net8.0\xunit.runner.visualstudio.props')" />
<Import Project="$(NuGetPackageRoot)xunit.core\2.9.3\build\xunit.core.props" Condition="Exists('$(NuGetPackageRoot)xunit.core\2.9.3\build\xunit.core.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore\8.0.18\buildTransitive\net8.0\Microsoft.EntityFrameworkCore.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore\8.0.18\buildTransitive\net8.0\Microsoft.EntityFrameworkCore.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.testplatform.testhost\17.14.1\build\net8.0\Microsoft.TestPlatform.TestHost.props" Condition="Exists('$(NuGetPackageRoot)microsoft.testplatform.testhost\17.14.1\build\net8.0\Microsoft.TestPlatform.TestHost.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.codecoverage\17.14.1\build\netstandard2.0\Microsoft.CodeCoverage.props" Condition="Exists('$(NuGetPackageRoot)microsoft.codecoverage\17.14.1\build\netstandard2.0\Microsoft.CodeCoverage.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.test.sdk\17.14.1\build\net8.0\Microsoft.NET.Test.Sdk.props" Condition="Exists('$(NuGetPackageRoot)microsoft.net.test.sdk\17.14.1\build\net8.0\Microsoft.NET.Test.Sdk.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\8.0.1\buildTransitive\net6.0\Microsoft.Extensions.Configuration.UserSecrets.props" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\8.0.1\buildTransitive\net6.0\Microsoft.Extensions.Configuration.UserSecrets.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore.design\8.0.18\build\net8.0\Microsoft.EntityFrameworkCore.Design.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore.design\8.0.18\build\net8.0\Microsoft.EntityFrameworkCore.Design.props')" />
</ImportGroup>
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Pkgxunit_analyzers Condition=" '$(Pkgxunit_analyzers)' == '' ">C:\Users\Faisa\.nuget\packages\xunit.analyzers\1.18.0</Pkgxunit_analyzers>
<PkgMicrosoft_Extensions_ApiDescription_Server Condition=" '$(PkgMicrosoft_Extensions_ApiDescription_Server)' == '' ">C:\Users\Faisa\.nuget\packages\microsoft.extensions.apidescription.server\8.0.0</PkgMicrosoft_Extensions_ApiDescription_Server>
<PkgMicrosoft_CodeAnalysis_Analyzers Condition=" '$(PkgMicrosoft_CodeAnalysis_Analyzers)' == '' ">C:\Users\Faisa\.nuget\packages\microsoft.codeanalysis.analyzers\3.3.3</PkgMicrosoft_CodeAnalysis_Analyzers>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)xunit.core\2.9.3\build\xunit.core.targets" Condition="Exists('$(NuGetPackageRoot)xunit.core\2.9.3\build\xunit.core.targets')" />
<Import Project="$(NuGetPackageRoot)system.text.json\8.0.5\buildTransitive\net6.0\System.Text.Json.targets" Condition="Exists('$(NuGetPackageRoot)system.text.json\8.0.5\buildTransitive\net6.0\System.Text.Json.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\8.0.2\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\8.0.2\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
<Import Project="$(NuGetPackageRoot)sqlitepclraw.lib.e_sqlite3\2.1.6\buildTransitive\net8.0\SQLitePCLRaw.lib.e_sqlite3.targets" Condition="Exists('$(NuGetPackageRoot)sqlitepclraw.lib.e_sqlite3\2.1.6\buildTransitive\net8.0\SQLitePCLRaw.lib.e_sqlite3.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.options\8.0.2\buildTransitive\net6.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\8.0.2\buildTransitive\net6.0\Microsoft.Extensions.Options.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.testplatform.testhost\17.14.1\build\net8.0\Microsoft.TestPlatform.TestHost.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.testplatform.testhost\17.14.1\build\net8.0\Microsoft.TestPlatform.TestHost.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.codecoverage\17.14.1\build\netstandard2.0\Microsoft.CodeCoverage.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.codecoverage\17.14.1\build\netstandard2.0\Microsoft.CodeCoverage.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.test.sdk\17.14.1\build\net8.0\Microsoft.NET.Test.Sdk.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.net.test.sdk\17.14.1\build\net8.0\Microsoft.NET.Test.Sdk.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.binder\8.0.2\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.binder\8.0.2\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\8.0.1\buildTransitive\net6.0\Microsoft.Extensions.Configuration.UserSecrets.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\8.0.1\buildTransitive\net6.0\Microsoft.Extensions.Configuration.UserSecrets.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.aspnetcore.mvc.testing\8.0.18\buildTransitive\net8.0\Microsoft.AspNetCore.Mvc.Testing.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.aspnetcore.mvc.testing\8.0.18\buildTransitive\net8.0\Microsoft.AspNetCore.Mvc.Testing.targets')" />
<Import Project="$(NuGetPackageRoot)coverlet.collector\6.0.4\build\netstandard2.0\coverlet.collector.targets" Condition="Exists('$(NuGetPackageRoot)coverlet.collector\6.0.4\build\netstandard2.0\coverlet.collector.targets')" />
</ImportGroup>
</Project>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,124 @@
{
"version": 2,
"dgSpecHash": "aVIlhUPul2g=",
"success": true,
"projectFilePath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests.GameApiTests\\ProjectLighthouse.Tests.GameApiTests.csproj",
"expectedPackageFiles": [
"C:\\Users\\Faisa\\.nuget\\packages\\bcrypt.net-next\\4.0.3\\bcrypt.net-next.4.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\bouncycastle.cryptography\\2.6.1\\bouncycastle.cryptography.2.6.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\castle.core\\5.1.1\\castle.core.5.1.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\coverlet.collector\\6.0.4\\coverlet.collector.6.0.4.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\discord.net.core\\3.17.4\\discord.net.core.3.17.4.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\discord.net.rest\\3.17.4\\discord.net.rest.3.17.4.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\discord.net.webhook\\3.17.4\\discord.net.webhook.3.17.4.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\distributedlock.core\\1.0.6\\distributedlock.core.1.0.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\distributedlock.mysql\\1.0.2\\distributedlock.mysql.1.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\humanizer.core\\2.14.1\\humanizer.core.2.14.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\jetbrains.annotations\\2024.3.0\\jetbrains.annotations.2024.3.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.aspnetcore.diagnostics.entityframeworkcore\\8.0.18\\microsoft.aspnetcore.diagnostics.entityframeworkcore.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.aspnetcore.mvc.testing\\8.0.18\\microsoft.aspnetcore.mvc.testing.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.aspnetcore.testhost\\8.0.18\\microsoft.aspnetcore.testhost.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.bcl.asyncinterfaces\\8.0.0\\microsoft.bcl.asyncinterfaces.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codeanalysis.analyzers\\3.3.3\\microsoft.codeanalysis.analyzers.3.3.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codeanalysis.common\\4.5.0\\microsoft.codeanalysis.common.4.5.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codeanalysis.csharp\\4.5.0\\microsoft.codeanalysis.csharp.4.5.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codeanalysis.csharp.workspaces\\4.5.0\\microsoft.codeanalysis.csharp.workspaces.4.5.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codeanalysis.workspaces.common\\4.5.0\\microsoft.codeanalysis.workspaces.common.4.5.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codecoverage\\17.14.1\\microsoft.codecoverage.17.14.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.data.sqlite.core\\8.0.6\\microsoft.data.sqlite.core.8.0.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore\\8.0.18\\microsoft.entityframeworkcore.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.abstractions\\8.0.18\\microsoft.entityframeworkcore.abstractions.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.analyzers\\8.0.18\\microsoft.entityframeworkcore.analyzers.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.design\\8.0.18\\microsoft.entityframeworkcore.design.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.relational\\8.0.18\\microsoft.entityframeworkcore.relational.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.sqlite\\8.0.6\\microsoft.entityframeworkcore.sqlite.8.0.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.sqlite.core\\8.0.6\\microsoft.entityframeworkcore.sqlite.core.8.0.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.apidescription.server\\8.0.0\\microsoft.extensions.apidescription.server.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.caching.abstractions\\8.0.0\\microsoft.extensions.caching.abstractions.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.caching.memory\\8.0.1\\microsoft.extensions.caching.memory.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration\\8.0.0\\microsoft.extensions.configuration.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.abstractions\\8.0.0\\microsoft.extensions.configuration.abstractions.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.binder\\8.0.2\\microsoft.extensions.configuration.binder.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.commandline\\8.0.0\\microsoft.extensions.configuration.commandline.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.environmentvariables\\8.0.0\\microsoft.extensions.configuration.environmentvariables.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.fileextensions\\8.0.1\\microsoft.extensions.configuration.fileextensions.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.json\\8.0.1\\microsoft.extensions.configuration.json.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.usersecrets\\8.0.1\\microsoft.extensions.configuration.usersecrets.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.dependencyinjection\\8.0.1\\microsoft.extensions.dependencyinjection.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.dependencyinjection.abstractions\\8.0.2\\microsoft.extensions.dependencyinjection.abstractions.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.dependencymodel\\8.0.2\\microsoft.extensions.dependencymodel.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.diagnostics\\8.0.1\\microsoft.extensions.diagnostics.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.diagnostics.abstractions\\8.0.1\\microsoft.extensions.diagnostics.abstractions.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.fileproviders.abstractions\\8.0.0\\microsoft.extensions.fileproviders.abstractions.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.fileproviders.physical\\8.0.0\\microsoft.extensions.fileproviders.physical.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.filesystemglobbing\\8.0.0\\microsoft.extensions.filesystemglobbing.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.hosting\\8.0.1\\microsoft.extensions.hosting.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.hosting.abstractions\\8.0.1\\microsoft.extensions.hosting.abstractions.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging\\8.0.1\\microsoft.extensions.logging.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.abstractions\\8.0.2\\microsoft.extensions.logging.abstractions.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.configuration\\8.0.1\\microsoft.extensions.logging.configuration.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.console\\8.0.1\\microsoft.extensions.logging.console.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.debug\\8.0.1\\microsoft.extensions.logging.debug.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.eventlog\\8.0.1\\microsoft.extensions.logging.eventlog.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.eventsource\\8.0.1\\microsoft.extensions.logging.eventsource.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.options\\8.0.2\\microsoft.extensions.options.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.options.configurationextensions\\8.0.0\\microsoft.extensions.options.configurationextensions.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.primitives\\8.0.0\\microsoft.extensions.primitives.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.net.test.sdk\\17.14.1\\microsoft.net.test.sdk.17.14.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.openapi\\1.6.23\\microsoft.openapi.1.6.23.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.testplatform.objectmodel\\17.14.1\\microsoft.testplatform.objectmodel.17.14.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.testplatform.testhost\\17.14.1\\microsoft.testplatform.testhost.17.14.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\mono.texttemplating\\2.2.1\\mono.texttemplating.2.2.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\moq\\4.20.72\\moq.4.20.72.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\mysqlconnector\\2.3.5\\mysqlconnector.2.3.5.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\newtonsoft.json\\13.0.3\\newtonsoft.json.13.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\pfim\\0.11.3\\pfim.0.11.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\pipelines.sockets.unofficial\\2.2.8\\pipelines.sockets.unofficial.2.2.8.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\pomelo.entityframeworkcore.mysql\\8.0.2\\pomelo.entityframeworkcore.mysql.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\redis.om\\1.0.1\\redis.om.1.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sharpziplib\\1.4.2\\sharpziplib.1.4.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sixlabors.imagesharp\\3.1.10\\sixlabors.imagesharp.3.1.10.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sqlitepclraw.bundle_e_sqlite3\\2.1.6\\sqlitepclraw.bundle_e_sqlite3.2.1.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sqlitepclraw.core\\2.1.6\\sqlitepclraw.core.2.1.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sqlitepclraw.lib.e_sqlite3\\2.1.6\\sqlitepclraw.lib.e_sqlite3.2.1.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sqlitepclraw.provider.e_sqlite3\\2.1.6\\sqlitepclraw.provider.e_sqlite3.2.1.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\stackexchange.redis\\2.7.17\\stackexchange.redis.2.7.17.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\swashbuckle.aspnetcore\\9.0.3\\swashbuckle.aspnetcore.9.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\swashbuckle.aspnetcore.swagger\\9.0.3\\swashbuckle.aspnetcore.swagger.9.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\swashbuckle.aspnetcore.swaggergen\\9.0.3\\swashbuckle.aspnetcore.swaggergen.9.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\swashbuckle.aspnetcore.swaggerui\\9.0.3\\swashbuckle.aspnetcore.swaggerui.9.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.codedom\\4.4.0\\system.codedom.4.4.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.collections.immutable\\8.0.0\\system.collections.immutable.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition\\6.0.0\\system.composition.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition.attributedmodel\\6.0.0\\system.composition.attributedmodel.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition.convention\\6.0.0\\system.composition.convention.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition.hosting\\6.0.0\\system.composition.hosting.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition.runtime\\6.0.0\\system.composition.runtime.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition.typedparts\\6.0.0\\system.composition.typedparts.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.diagnostics.eventlog\\8.0.1\\system.diagnostics.eventlog.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.interactive.async\\6.0.1\\system.interactive.async.6.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.io.pipelines\\8.0.0\\system.io.pipelines.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.linq.async\\6.0.1\\system.linq.async.6.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.memory\\4.5.3\\system.memory.4.5.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.reflection.metadata\\8.0.0\\system.reflection.metadata.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.runtime.compilerservices.unsafe\\6.0.0\\system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.text.encoding.codepages\\6.0.0\\system.text.encoding.codepages.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.text.json\\8.0.5\\system.text.json.8.0.5.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.threading.channels\\6.0.0\\system.threading.channels.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.valuetuple\\4.5.0\\system.valuetuple.4.5.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\ulid\\1.2.6\\ulid.1.2.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit\\2.9.3\\xunit.2.9.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.abstractions\\2.0.3\\xunit.abstractions.2.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.analyzers\\1.18.0\\xunit.analyzers.1.18.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.assert\\2.9.3\\xunit.assert.2.9.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.core\\2.9.3\\xunit.core.2.9.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.extensibility.core\\2.9.3\\xunit.extensibility.core.2.9.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.extensibility.execution\\2.9.3\\xunit.extensibility.execution.2.9.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.runner.visualstudio\\3.1.1\\xunit.runner.visualstudio.3.1.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\yamldotnet\\16.3.0\\yamldotnet.16.3.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.netcore.app.ref\\8.0.19\\microsoft.netcore.app.ref.8.0.19.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.windowsdesktop.app.ref\\8.0.19\\microsoft.windowsdesktop.app.ref.8.0.19.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.aspnetcore.app.ref\\8.0.19\\microsoft.aspnetcore.app.ref.8.0.19.nupkg.sha512"
],
"logs": []
}

View file

@ -1,3 +1,3 @@
using Xunit;
using Xunit;
[assembly: CollectionBehavior(DisableTestParallelization = true)]

View file

@ -1,13 +1,13 @@
using System;
using OpenQA.Selenium;
namespace ProjectLighthouse.Tests.WebsiteTests.Extensions;
public static class WebDriverExtensions
{
private static Uri GetUri(this IWebDriver driver) => new(driver.Url);
public static string GetPath(this IWebDriver driver) => driver.GetUri().AbsolutePath;
public static string GetErrorMessage(this IWebDriver driver) => driver.FindElement(By.CssSelector("#error-message > p")).Text;
using System;
using OpenQA.Selenium;
namespace ProjectLighthouse.Tests.WebsiteTests.Extensions;
public static class WebDriverExtensions
{
private static Uri GetUri(this IWebDriver driver) => new(driver.Url);
public static string GetPath(this IWebDriver driver) => driver.GetUri().AbsolutePath;
public static string GetErrorMessage(this IWebDriver driver) => driver.FindElement(By.CssSelector("#error-message > p")).Text;
}

View file

@ -1,72 +1,72 @@
using System;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using LBPUnion.ProjectLighthouse.Types.Users;
using OpenQA.Selenium;
using Xunit;
namespace ProjectLighthouse.Tests.WebsiteTests.Integration;
[Trait("Category", "Integration")]
public class AdminTests : LighthouseWebTest
{
private const string adminPanelButtonXPath = "/html/body/div/header/div/div/div/a[2]/span";
[Fact]
public async Task ShouldShowAdminPanelButtonWhenAdmin()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
this.Driver.Manage().Cookies.DeleteAllCookies();
UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash("i'm an engineering failure"));
WebTokenEntity webToken = new()
{
UserId = user.UserId,
UserToken = CryptoHelper.GenerateAuthToken(),
ExpiresAt = DateTime.UtcNow + TimeSpan.FromHours(1),
Verified = true,
};
database.WebTokens.Add(webToken);
user.PermissionLevel = PermissionLevel.Administrator;
await database.SaveChangesAsync();
this.Driver.Navigate().GoToUrl(this.BaseAddress + "/");
this.Driver.Manage().Cookies.AddCookie(new Cookie("LighthouseToken", webToken.UserToken));
this.Driver.Navigate().Refresh();
Assert.Equal("Admin", this.Driver.FindElement(By.XPath(adminPanelButtonXPath)).Text);
}
[Fact]
public async Task ShouldNotShowAdminPanelButtonWhenNotAdmin()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
this.Driver.Manage().Cookies.DeleteAllCookies();
UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash("i'm an engineering failure"));
WebTokenEntity webToken = new()
{
UserId = user.UserId,
UserToken = CryptoHelper.GenerateAuthToken(),
ExpiresAt = DateTime.UtcNow + TimeSpan.FromHours(1),
Verified = true,
};
database.WebTokens.Add(webToken);
user.PermissionLevel = PermissionLevel.Default;
await database.SaveChangesAsync();
this.Driver.Navigate().GoToUrl(this.BaseAddress + "/");
this.Driver.Manage().Cookies.AddCookie(new Cookie("LighthouseToken", webToken.UserToken));
this.Driver.Navigate().Refresh();
Assert.Empty(this.Driver.FindElements(By.XPath(adminPanelButtonXPath)));
}
using System;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using LBPUnion.ProjectLighthouse.Types.Users;
using OpenQA.Selenium;
using Xunit;
namespace ProjectLighthouse.Tests.WebsiteTests.Integration;
[Trait("Category", "Integration")]
public class AdminTests : LighthouseWebTest
{
private const string adminPanelButtonXPath = "/html/body/div/header/div/div/div/a[2]/span";
[Fact]
public async Task ShouldShowAdminPanelButtonWhenAdmin()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
this.Driver.Manage().Cookies.DeleteAllCookies();
UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash("i'm an engineering failure"));
WebTokenEntity webToken = new()
{
UserId = user.UserId,
UserToken = CryptoHelper.GenerateAuthToken(),
ExpiresAt = DateTime.UtcNow + TimeSpan.FromHours(1),
Verified = true,
};
database.WebTokens.Add(webToken);
user.PermissionLevel = PermissionLevel.Administrator;
await database.SaveChangesAsync();
this.Driver.Navigate().GoToUrl(this.BaseAddress + "/");
this.Driver.Manage().Cookies.AddCookie(new Cookie("LighthouseToken", webToken.UserToken));
this.Driver.Navigate().Refresh();
Assert.Equal("Admin", this.Driver.FindElement(By.XPath(adminPanelButtonXPath)).Text);
}
[Fact]
public async Task ShouldNotShowAdminPanelButtonWhenNotAdmin()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
this.Driver.Manage().Cookies.DeleteAllCookies();
UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash("i'm an engineering failure"));
WebTokenEntity webToken = new()
{
UserId = user.UserId,
UserToken = CryptoHelper.GenerateAuthToken(),
ExpiresAt = DateTime.UtcNow + TimeSpan.FromHours(1),
Verified = true,
};
database.WebTokens.Add(webToken);
user.PermissionLevel = PermissionLevel.Default;
await database.SaveChangesAsync();
this.Driver.Navigate().GoToUrl(this.BaseAddress + "/");
this.Driver.Manage().Cookies.AddCookie(new Cookie("LighthouseToken", webToken.UserToken));
this.Driver.Navigate().Refresh();
Assert.Empty(this.Driver.FindElements(By.XPath(adminPanelButtonXPath)));
}
}

View file

@ -1,112 +1,112 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Localization.StringLists;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using Microsoft.EntityFrameworkCore;
using OpenQA.Selenium;
using ProjectLighthouse.Tests.WebsiteTests.Extensions;
using Xunit;
namespace ProjectLighthouse.Tests.WebsiteTests.Integration;
[Trait("Category", "Integration")]
public class AuthenticationTests : LighthouseWebTest
{
[Fact]
public async Task ShouldLoginWithPassword()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
this.Driver.Manage().Cookies.DeleteAllCookies();
string password = CryptoHelper.Sha256Hash(CryptoHelper.GenerateRandomBytes(64).ToArray());
UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash(CryptoHelper.Sha256Hash(password)));
// Sometimes not having this causes a race condition
// ReSharper disable once MethodHasAsyncOverload
database.SaveChanges();
await this.Driver.Navigate().GoToUrlAsync(this.BaseAddress + "/login");
this.Driver.FindElement(By.Id("text")).SendKeys(user.Username);
this.Driver.FindElement(By.Id("password")).SendKeys(password);
this.Driver.FindElement(By.Id("submit")).Click();
WebTokenEntity? webToken = await database.WebTokens.FirstOrDefaultAsync(t => t.UserId == user.UserId);
Assert.NotNull(webToken);
}
[Fact]
public async Task ShouldNotLoginWithNoPassword()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
this.Driver.Manage().Cookies.DeleteAllCookies();
UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash("just like the hindenberg,"));
this.Driver.Navigate().GoToUrl(this.BaseAddress + "/login");
this.Driver.FindElement(By.Id("text")).SendKeys(user.Username);
this.Driver.FindElement(By.Id("submit")).Click();
WebTokenEntity? webToken = await database.WebTokens.FirstOrDefaultAsync(t => t.UserId == user.UserId);
Assert.Null(webToken);
Assert.Equal("/login", this.Driver.GetPath());
Assert.Equal("The username or password you entered is invalid.", this.Driver.GetErrorMessage());
}
[Fact]
public async Task ShouldNotLoginWithWrongPassword()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
this.Driver.Manage().Cookies.DeleteAllCookies();
UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash("i'm an engineering failure"));
this.Driver.Navigate().GoToUrl(this.BaseAddress + "/login");
this.Driver.FindElement(By.Id("text")).SendKeys(user.Username);
this.Driver.FindElement(By.Id("password")).SendKeys("nah man");
this.Driver.FindElement(By.Id("submit")).Click();
WebTokenEntity? webToken = await database.WebTokens.FirstOrDefaultAsync(t => t.UserId == user.UserId);
Assert.Null(webToken);
}
[Fact]
public async Task ShouldLoginWithInjectedCookie()
{
const string loggedInAsUsernameTextXPath = "/html/body/div/div/div/div/p[1]";
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash("i'm an engineering failure"));
WebTokenEntity webToken = new()
{
UserId = user.UserId,
UserToken = CryptoHelper.GenerateAuthToken(),
ExpiresAt = DateTime.UtcNow + TimeSpan.FromHours(1),
Verified = true,
};
database.WebTokens.Add(webToken);
await database.SaveChangesAsync();
INavigation navigation = this.Driver.Navigate();
navigation.GoToUrl(this.BaseAddress + "/");
Assert.DoesNotContain(user.Username, this.Driver.FindElement(By.XPath(loggedInAsUsernameTextXPath)).Text);
this.Driver.Manage().Cookies.AddCookie(new Cookie("LighthouseToken", webToken.UserToken));
navigation.Refresh();
Assert.Equal(Translate(LandingPageStrings.LoggedInAs, user.Username), this.Driver.FindElement(By.XPath(loggedInAsUsernameTextXPath)).Text);
}
using System;
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Localization.StringLists;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using Microsoft.EntityFrameworkCore;
using OpenQA.Selenium;
using ProjectLighthouse.Tests.WebsiteTests.Extensions;
using Xunit;
namespace ProjectLighthouse.Tests.WebsiteTests.Integration;
[Trait("Category", "Integration")]
public class AuthenticationTests : LighthouseWebTest
{
[Fact]
public async Task ShouldLoginWithPassword()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
this.Driver.Manage().Cookies.DeleteAllCookies();
string password = CryptoHelper.Sha256Hash(CryptoHelper.GenerateRandomBytes(64).ToArray());
UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash(CryptoHelper.Sha256Hash(password)));
// Sometimes not having this causes a race condition
// ReSharper disable once MethodHasAsyncOverload
database.SaveChanges();
await this.Driver.Navigate().GoToUrlAsync(this.BaseAddress + "/login");
this.Driver.FindElement(By.Id("text")).SendKeys(user.Username);
this.Driver.FindElement(By.Id("password")).SendKeys(password);
this.Driver.FindElement(By.Id("submit")).Click();
WebTokenEntity? webToken = await database.WebTokens.FirstOrDefaultAsync(t => t.UserId == user.UserId);
Assert.NotNull(webToken);
}
[Fact]
public async Task ShouldNotLoginWithNoPassword()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
this.Driver.Manage().Cookies.DeleteAllCookies();
UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash("just like the hindenberg,"));
this.Driver.Navigate().GoToUrl(this.BaseAddress + "/login");
this.Driver.FindElement(By.Id("text")).SendKeys(user.Username);
this.Driver.FindElement(By.Id("submit")).Click();
WebTokenEntity? webToken = await database.WebTokens.FirstOrDefaultAsync(t => t.UserId == user.UserId);
Assert.Null(webToken);
Assert.Equal("/login", this.Driver.GetPath());
Assert.Equal("The username or password you entered is invalid.", this.Driver.GetErrorMessage());
}
[Fact]
public async Task ShouldNotLoginWithWrongPassword()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
this.Driver.Manage().Cookies.DeleteAllCookies();
UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash("i'm an engineering failure"));
this.Driver.Navigate().GoToUrl(this.BaseAddress + "/login");
this.Driver.FindElement(By.Id("text")).SendKeys(user.Username);
this.Driver.FindElement(By.Id("password")).SendKeys("nah man");
this.Driver.FindElement(By.Id("submit")).Click();
WebTokenEntity? webToken = await database.WebTokens.FirstOrDefaultAsync(t => t.UserId == user.UserId);
Assert.Null(webToken);
}
[Fact]
public async Task ShouldLoginWithInjectedCookie()
{
const string loggedInAsUsernameTextXPath = "/html/body/div/div/div/div/p[1]";
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
UserEntity user = await database.CreateUser($"unitTestUser{CryptoHelper.GenerateRandomInt32()}", CryptoHelper.BCryptHash("i'm an engineering failure"));
WebTokenEntity webToken = new()
{
UserId = user.UserId,
UserToken = CryptoHelper.GenerateAuthToken(),
ExpiresAt = DateTime.UtcNow + TimeSpan.FromHours(1),
Verified = true,
};
database.WebTokens.Add(webToken);
await database.SaveChangesAsync();
INavigation navigation = this.Driver.Navigate();
navigation.GoToUrl(this.BaseAddress + "/");
Assert.DoesNotContain(user.Username, this.Driver.FindElement(By.XPath(loggedInAsUsernameTextXPath)).Text);
this.Driver.Manage().Cookies.AddCookie(new Cookie("LighthouseToken", webToken.UserToken));
navigation.Refresh();
Assert.Equal(Translate(LandingPageStrings.LoggedInAs, user.Username), this.Driver.FindElement(By.XPath(loggedInAsUsernameTextXPath)).Text);
}
}

View file

@ -1,60 +1,60 @@
using System;
using System.Linq;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Localization;
using LBPUnion.ProjectLighthouse.Servers.Website.Startup;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using Xunit;
namespace ProjectLighthouse.Tests.WebsiteTests.Integration;
[Collection(nameof(LighthouseWebTest))]
public class LighthouseWebTest : IDisposable
{
protected readonly string BaseAddress;
protected readonly IWebDriver Driver;
private readonly IWebHost webHost = new WebHostBuilder().UseKestrel().UseStartup<WebsiteTestStartup>().UseWebRoot("StaticFiles").Build();
protected LighthouseWebTest()
{
ServerConfiguration.Instance.DbConnectionString = "server=127.0.0.1;uid=root;pwd=lighthouse_tests;database=lighthouse_tests";
ServerConfiguration.Instance.TwoFactorConfiguration.TwoFactorEnabled = false;
this.webHost.Start();
IServerAddressesFeature? serverAddressesFeature = this.webHost.ServerFeatures.Get<IServerAddressesFeature>();
if (serverAddressesFeature == null) throw new ArgumentNullException();
this.BaseAddress = serverAddressesFeature.Addresses.First();
ChromeOptions chromeOptions = new();
if (Convert.ToBoolean(Environment.GetEnvironmentVariable("CI") ?? "false"))
{
chromeOptions.AddArgument("headless");
chromeOptions.AddArgument("no-sandbox");
chromeOptions.AddArgument("disable-dev-shm-usage");
Console.WriteLine(@"We are in a CI environment, so chrome headless mode has been enabled.");
}
this.Driver = new ChromeDriver(chromeOptions);
this.Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(1);
}
protected static string Translate(TranslatableString translatableString) => translatableString.Translate(LocalizationManager.DefaultLang);
protected static string Translate(TranslatableString translatableString, params object?[] objects) =>
translatableString.Translate(LocalizationManager.DefaultLang, objects);
public void Dispose()
{
this.Driver.Close();
this.Driver.Dispose();
this.webHost.Dispose();
GC.SuppressFinalize(this);
}
using System;
using System.Linq;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Localization;
using LBPUnion.ProjectLighthouse.Servers.Website.Startup;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using Xunit;
namespace ProjectLighthouse.Tests.WebsiteTests.Integration;
[Collection(nameof(LighthouseWebTest))]
public class LighthouseWebTest : IDisposable
{
protected readonly string BaseAddress;
protected readonly IWebDriver Driver;
private readonly IWebHost webHost = new WebHostBuilder().UseKestrel().UseStartup<WebsiteTestStartup>().UseWebRoot("StaticFiles").Build();
protected LighthouseWebTest()
{
ServerConfiguration.Instance.DbConnectionString = "server=127.0.0.1;uid=root;pwd=lighthouse_tests;database=lighthouse_tests";
ServerConfiguration.Instance.TwoFactorConfiguration.TwoFactorEnabled = false;
this.webHost.Start();
IServerAddressesFeature? serverAddressesFeature = this.webHost.ServerFeatures.Get<IServerAddressesFeature>();
if (serverAddressesFeature == null) throw new ArgumentNullException();
this.BaseAddress = serverAddressesFeature.Addresses.First();
ChromeOptions chromeOptions = new();
if (Convert.ToBoolean(Environment.GetEnvironmentVariable("CI") ?? "false"))
{
chromeOptions.AddArgument("headless");
chromeOptions.AddArgument("no-sandbox");
chromeOptions.AddArgument("disable-dev-shm-usage");
Console.WriteLine(@"We are in a CI environment, so chrome headless mode has been enabled.");
}
this.Driver = new ChromeDriver(chromeOptions);
this.Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(1);
}
protected static string Translate(TranslatableString translatableString) => translatableString.Translate(LocalizationManager.DefaultLang);
protected static string Translate(TranslatableString translatableString, params object?[] objects) =>
translatableString.Translate(LocalizationManager.DefaultLang, objects);
public void Dispose()
{
this.Driver.Close();
this.Driver.Dispose();
this.webHost.Dispose();
GC.SuppressFinalize(this);
}
}

View file

@ -1,112 +1,112 @@
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Localization.StringLists;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using Microsoft.EntityFrameworkCore;
using OpenQA.Selenium;
using ProjectLighthouse.Tests.WebsiteTests.Extensions;
using Xunit;
namespace ProjectLighthouse.Tests.WebsiteTests.Integration;
[Trait("Category", "Integration")]
public class RegisterTests : LighthouseWebTest
{
[Fact]
public async Task ShouldRegister()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
this.Driver.Manage().Cookies.DeleteAllCookies();
ServerConfiguration.Instance.Authentication.RegistrationEnabled = true;
string username = ("unitTestUser" + CryptoHelper.GenerateRandomInt32(0, int.MaxValue))[..16];
string password = CryptoHelper.Sha256Hash(CryptoHelper.GenerateRandomBytes(64).ToArray());
this.Driver.Navigate().GoToUrl(this.BaseAddress + "/register");
this.Driver.FindElement(By.Id("text")).SendKeys(username);
this.Driver.FindElement(By.Id("password")).SendKeys(password);
this.Driver.FindElement(By.Id("confirmPassword")).SendKeys(password);
this.Driver.FindElement(By.Id("age-checkbox")).Click();
this.Driver.FindElement(By.Id("submit")).Click();
UserEntity? user = await database.Users.FirstOrDefaultAsync(u => u.Username == username);
Assert.NotNull(user);
Assert.Equal("/", this.Driver.GetPath());
ServerConfiguration.Instance.Authentication.RegistrationEnabled = false;
}
[Fact]
public async Task ShouldNotRegisterWithMismatchingPasswords()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
this.Driver.Manage().Cookies.DeleteAllCookies();
ServerConfiguration.Instance.Authentication.RegistrationEnabled = true;
string username = ("unitTestUser" + CryptoHelper.GenerateRandomInt32(0, int.MaxValue))[..16];
string password = CryptoHelper.Sha256Hash(CryptoHelper.GenerateRandomBytes(64).ToArray());
this.Driver.Navigate().GoToUrl(this.BaseAddress + "/register");
this.Driver.FindElement(By.Id("text")).SendKeys(username);
this.Driver.FindElement(By.Id("password")).SendKeys(password);
this.Driver.FindElement(By.Id("confirmPassword")).SendKeys(password + "a");
this.Driver.FindElement(By.Id("age-checkbox")).Click();
this.Driver.FindElement(By.Id("submit")).Click();
UserEntity? user = await database.Users.FirstOrDefaultAsync(u => u.Username == username);
Assert.Null(user);
Assert.Equal("/register", this.Driver.GetPath());
Assert.Equal(Translate(ErrorStrings.PasswordDoesntMatch), this.Driver.GetErrorMessage());
ServerConfiguration.Instance.Authentication.RegistrationEnabled = false;
}
[Fact]
public async Task ShouldNotRegisterWithTakenUsername()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
this.Driver.Manage().Cookies.DeleteAllCookies();
ServerConfiguration.Instance.Authentication.RegistrationEnabled = true;
string username = ("unitTestUser" + CryptoHelper.GenerateRandomInt32(0, int.MaxValue))[..16];
string password = CryptoHelper.Sha256Hash(CryptoHelper.GenerateRandomBytes(64).ToArray());
await database.CreateUser(username, CryptoHelper.BCryptHash(password));
UserEntity? user = await database.Users.FirstOrDefaultAsync(u => u.Username == username);
Assert.NotNull(user);
this.Driver.Navigate().GoToUrl(this.BaseAddress + "/register");
this.Driver.FindElement(By.Id("text")).SendKeys(username);
this.Driver.FindElement(By.Id("password")).SendKeys(password);
this.Driver.FindElement(By.Id("confirmPassword")).SendKeys(password);
this.Driver.FindElement(By.Id("age-checkbox")).Click();
this.Driver.FindElement(By.Id("submit")).Click();
Assert.Equal("/register", this.Driver.GetPath());
Assert.Equal(Translate(ErrorStrings.UsernameTaken), this.Driver.GetErrorMessage());
ServerConfiguration.Instance.Authentication.RegistrationEnabled = false;
}
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Localization.StringLists;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using Microsoft.EntityFrameworkCore;
using OpenQA.Selenium;
using ProjectLighthouse.Tests.WebsiteTests.Extensions;
using Xunit;
namespace ProjectLighthouse.Tests.WebsiteTests.Integration;
[Trait("Category", "Integration")]
public class RegisterTests : LighthouseWebTest
{
[Fact]
public async Task ShouldRegister()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
this.Driver.Manage().Cookies.DeleteAllCookies();
ServerConfiguration.Instance.Authentication.RegistrationEnabled = true;
string username = ("unitTestUser" + CryptoHelper.GenerateRandomInt32(0, int.MaxValue))[..16];
string password = CryptoHelper.Sha256Hash(CryptoHelper.GenerateRandomBytes(64).ToArray());
this.Driver.Navigate().GoToUrl(this.BaseAddress + "/register");
this.Driver.FindElement(By.Id("text")).SendKeys(username);
this.Driver.FindElement(By.Id("password")).SendKeys(password);
this.Driver.FindElement(By.Id("confirmPassword")).SendKeys(password);
this.Driver.FindElement(By.Id("age-checkbox")).Click();
this.Driver.FindElement(By.Id("submit")).Click();
UserEntity? user = await database.Users.FirstOrDefaultAsync(u => u.Username == username);
Assert.NotNull(user);
Assert.Equal("/", this.Driver.GetPath());
ServerConfiguration.Instance.Authentication.RegistrationEnabled = false;
}
[Fact]
public async Task ShouldNotRegisterWithMismatchingPasswords()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
this.Driver.Manage().Cookies.DeleteAllCookies();
ServerConfiguration.Instance.Authentication.RegistrationEnabled = true;
string username = ("unitTestUser" + CryptoHelper.GenerateRandomInt32(0, int.MaxValue))[..16];
string password = CryptoHelper.Sha256Hash(CryptoHelper.GenerateRandomBytes(64).ToArray());
this.Driver.Navigate().GoToUrl(this.BaseAddress + "/register");
this.Driver.FindElement(By.Id("text")).SendKeys(username);
this.Driver.FindElement(By.Id("password")).SendKeys(password);
this.Driver.FindElement(By.Id("confirmPassword")).SendKeys(password + "a");
this.Driver.FindElement(By.Id("age-checkbox")).Click();
this.Driver.FindElement(By.Id("submit")).Click();
UserEntity? user = await database.Users.FirstOrDefaultAsync(u => u.Username == username);
Assert.Null(user);
Assert.Equal("/register", this.Driver.GetPath());
Assert.Equal(Translate(ErrorStrings.PasswordDoesntMatch), this.Driver.GetErrorMessage());
ServerConfiguration.Instance.Authentication.RegistrationEnabled = false;
}
[Fact]
public async Task ShouldNotRegisterWithTakenUsername()
{
await using DatabaseContext database = await IntegrationHelper.GetIntegrationDatabase();
this.Driver.Manage().Cookies.DeleteAllCookies();
ServerConfiguration.Instance.Authentication.RegistrationEnabled = true;
string username = ("unitTestUser" + CryptoHelper.GenerateRandomInt32(0, int.MaxValue))[..16];
string password = CryptoHelper.Sha256Hash(CryptoHelper.GenerateRandomBytes(64).ToArray());
await database.CreateUser(username, CryptoHelper.BCryptHash(password));
UserEntity? user = await database.Users.FirstOrDefaultAsync(u => u.Username == username);
Assert.NotNull(user);
this.Driver.Navigate().GoToUrl(this.BaseAddress + "/register");
this.Driver.FindElement(By.Id("text")).SendKeys(username);
this.Driver.FindElement(By.Id("password")).SendKeys(password);
this.Driver.FindElement(By.Id("confirmPassword")).SendKeys(password);
this.Driver.FindElement(By.Id("age-checkbox")).Click();
this.Driver.FindElement(By.Id("submit")).Click();
Assert.Equal("/register", this.Driver.GetPath());
Assert.Equal(Translate(ErrorStrings.UsernameTaken), this.Driver.GetErrorMessage());
ServerConfiguration.Instance.Authentication.RegistrationEnabled = false;
}
}

View file

@ -1,38 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2024.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.18" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.18">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="Selenium.WebDriver" Version="4.34.0" />
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="138.0.7204.9400" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ProjectLighthouse.Servers.Website\ProjectLighthouse.Servers.Website.csproj" />
<ProjectReference Include="..\ProjectLighthouse.Tests\ProjectLighthouse.Tests.csproj" />
<ProjectReference Include="..\ProjectLighthouse\ProjectLighthouse.csproj" />
<ProjectReference Include="..\ProjectLighthouse.Localization\ProjectLighthouse.Localization.csproj" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2024.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.18" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.18">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="Selenium.WebDriver" Version="4.34.0" />
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="138.0.7204.9400" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ProjectLighthouse.Servers.Website\ProjectLighthouse.Servers.Website.csproj" />
<ProjectReference Include="..\ProjectLighthouse.Tests\ProjectLighthouse.Tests.csproj" />
<ProjectReference Include="..\ProjectLighthouse\ProjectLighthouse.csproj" />
<ProjectReference Include="..\ProjectLighthouse.Localization\ProjectLighthouse.Localization.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,22 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("ProjectLighthouse.Tests.WebsiteTests")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+509240db396eac0c69bd7ed8e09b71f630a8de72")]
[assembly: System.Reflection.AssemblyProductAttribute("ProjectLighthouse.Tests.WebsiteTests")]
[assembly: System.Reflection.AssemblyTitleAttribute("ProjectLighthouse.Tests.WebsiteTests")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// Generated by the MSBuild WriteCodeFragment class.

View file

@ -0,0 +1 @@
9114fff14b95c5135b680ce99db8a619d63b955e22fd4bdb8264f2831b631f6f

View file

@ -0,0 +1,15 @@
is_global = true
build_property.TargetFramework = net8.0
build_property.TargetPlatformMinVersion =
build_property.UsingMicrosoftNETSdkWeb =
build_property.ProjectTypeGuids =
build_property.InvariantGlobalization =
build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules =
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = ProjectLighthouse.Tests.WebsiteTests
build_property.ProjectDir = G:\LBP 3 ONLINE ARCHIVE\LBP 3 ONLINE SITE RECREACTION\ProjectLighthouse\ProjectLighthouse.Tests.WebsiteTests\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.EffectiveAnalysisLevelStyle = 8.0
build_property.EnableCodeStyleSeverity =

View file

@ -0,0 +1,575 @@
{
"format": 1,
"restore": {
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests.WebsiteTests\\ProjectLighthouse.Tests.WebsiteTests.csproj": {}
},
"projects": {
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj",
"projectName": "ProjectLighthouse.Localization",
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj",
"packagesPath": "C:\\Users\\Faisa\\.nuget\\packages\\",
"outputPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\obj\\",
"projectStyle": "PackageReference",
"configFilePaths": [
"C:\\Users\\Faisa\\AppData\\Roaming\\NuGet\\NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.300"
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"downloadDependencies": [
{
"name": "Microsoft.AspNetCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.NETCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.WindowsDesktop.App.Ref",
"version": "[8.0.19, 8.0.19]"
}
],
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.304/PortableRuntimeIdentifierGraph.json"
}
}
},
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Servers.Website\\ProjectLighthouse.Servers.Website.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Servers.Website\\ProjectLighthouse.Servers.Website.csproj",
"projectName": "LBPUnion.ProjectLighthouse.Servers.Website",
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Servers.Website\\ProjectLighthouse.Servers.Website.csproj",
"packagesPath": "C:\\Users\\Faisa\\.nuget\\packages\\",
"outputPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Servers.Website\\obj\\",
"projectStyle": "PackageReference",
"configFilePaths": [
"C:\\Users\\Faisa\\AppData\\Roaming\\NuGet\\NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj": {
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj"
},
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj": {
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj"
}
}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.300"
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"dependencies": {
"QRCoder": {
"target": "Package",
"version": "[1.6.0, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"downloadDependencies": [
{
"name": "Microsoft.AspNetCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.NETCore.App.Host.win-x64",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.NETCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.WindowsDesktop.App.Ref",
"version": "[8.0.19, 8.0.19]"
}
],
"frameworkReferences": {
"Microsoft.AspNetCore.App": {
"privateAssets": "none"
},
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.304/PortableRuntimeIdentifierGraph.json"
}
}
},
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests.WebsiteTests\\ProjectLighthouse.Tests.WebsiteTests.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests.WebsiteTests\\ProjectLighthouse.Tests.WebsiteTests.csproj",
"projectName": "ProjectLighthouse.Tests.WebsiteTests",
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests.WebsiteTests\\ProjectLighthouse.Tests.WebsiteTests.csproj",
"packagesPath": "C:\\Users\\Faisa\\.nuget\\packages\\",
"outputPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests.WebsiteTests\\obj\\",
"projectStyle": "PackageReference",
"configFilePaths": [
"C:\\Users\\Faisa\\AppData\\Roaming\\NuGet\\NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj": {
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj"
},
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Servers.Website\\ProjectLighthouse.Servers.Website.csproj": {
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Servers.Website\\ProjectLighthouse.Servers.Website.csproj"
},
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\ProjectLighthouse.Tests.csproj": {
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\ProjectLighthouse.Tests.csproj"
},
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj": {
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj"
}
}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.300"
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"dependencies": {
"JetBrains.Annotations": {
"target": "Package",
"version": "[2024.3.0, )"
},
"Microsoft.AspNetCore.Mvc.Testing": {
"target": "Package",
"version": "[8.0.18, )"
},
"Microsoft.EntityFrameworkCore.Design": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[8.0.18, )"
},
"Microsoft.NET.Test.Sdk": {
"target": "Package",
"version": "[17.14.1, )"
},
"Selenium.WebDriver": {
"target": "Package",
"version": "[4.34.0, )"
},
"Selenium.WebDriver.ChromeDriver": {
"target": "Package",
"version": "[138.0.7204.9400, )"
},
"coverlet.collector": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[6.0.4, )"
},
"xunit": {
"target": "Package",
"version": "[2.9.3, )"
},
"xunit.runner.visualstudio": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[3.1.1, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"downloadDependencies": [
{
"name": "Microsoft.AspNetCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.NETCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.WindowsDesktop.App.Ref",
"version": "[8.0.19, 8.0.19]"
}
],
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.304/PortableRuntimeIdentifierGraph.json"
}
}
},
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\ProjectLighthouse.Tests.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\ProjectLighthouse.Tests.csproj",
"projectName": "LBPUnion.ProjectLighthouse.Tests",
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\ProjectLighthouse.Tests.csproj",
"packagesPath": "C:\\Users\\Faisa\\.nuget\\packages\\",
"outputPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\obj\\",
"projectStyle": "PackageReference",
"configFilePaths": [
"C:\\Users\\Faisa\\AppData\\Roaming\\NuGet\\NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj": {
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj"
}
}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.300"
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"dependencies": {
"JetBrains.Annotations": {
"target": "Package",
"version": "[2024.3.0, )"
},
"Microsoft.AspNetCore.Mvc.Testing": {
"target": "Package",
"version": "[8.0.18, )"
},
"Microsoft.EntityFrameworkCore.Design": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[8.0.18, )"
},
"Microsoft.EntityFrameworkCore.Sqlite": {
"target": "Package",
"version": "[8.0.6, )"
},
"Microsoft.NET.Test.Sdk": {
"target": "Package",
"version": "[17.14.1, )"
},
"Moq": {
"target": "Package",
"version": "[4.20.72, )"
},
"coverlet.collector": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[6.0.4, )"
},
"xunit": {
"target": "Package",
"version": "[2.9.3, )"
},
"xunit.runner.visualstudio": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[3.1.1, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"downloadDependencies": [
{
"name": "Microsoft.AspNetCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.NETCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.WindowsDesktop.App.Ref",
"version": "[8.0.19, 8.0.19]"
}
],
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.304/PortableRuntimeIdentifierGraph.json"
}
}
},
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj",
"projectName": "LBPUnion.ProjectLighthouse",
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj",
"packagesPath": "C:\\Users\\Faisa\\.nuget\\packages\\",
"outputPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\obj\\",
"projectStyle": "PackageReference",
"configFilePaths": [
"C:\\Users\\Faisa\\AppData\\Roaming\\NuGet\\NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj": {
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj"
}
}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.300"
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"dependencies": {
"BCrypt.Net-Next": {
"target": "Package",
"version": "[4.0.3, )"
},
"BouncyCastle.Cryptography": {
"target": "Package",
"version": "[2.6.1, )"
},
"Discord.Net.Webhook": {
"target": "Package",
"version": "[3.17.4, )"
},
"DistributedLock.MySql": {
"target": "Package",
"version": "[1.0.2, )"
},
"GitInfo": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[3.5.0, )"
},
"JetBrains.Annotations": {
"target": "Package",
"version": "[2024.3.0, )"
},
"Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore": {
"target": "Package",
"version": "[8.0.18, )"
},
"Microsoft.EntityFrameworkCore": {
"target": "Package",
"version": "[8.0.18, )"
},
"Microsoft.EntityFrameworkCore.Design": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[8.0.18, )"
},
"Pfim": {
"target": "Package",
"version": "[0.11.3, )"
},
"Pomelo.EntityFrameworkCore.MySql": {
"target": "Package",
"version": "[8.0.2, )"
},
"Redis.OM": {
"target": "Package",
"version": "[1.0.1, )"
},
"SharpZipLib": {
"target": "Package",
"version": "[1.4.2, )"
},
"SixLabors.ImageSharp": {
"target": "Package",
"version": "[3.1.10, )"
},
"Swashbuckle.AspNetCore": {
"target": "Package",
"version": "[9.0.3, )"
},
"YamlDotNet": {
"target": "Package",
"version": "[16.3.0, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"downloadDependencies": [
{
"name": "Microsoft.AspNetCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.NETCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.WindowsDesktop.App.Ref",
"version": "[8.0.19, 8.0.19]"
}
],
"frameworkReferences": {
"Microsoft.AspNetCore.App": {
"privateAssets": "none"
},
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.304/PortableRuntimeIdentifierGraph.json"
}
}
}
}
}

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\Faisa\.nuget\packages\</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.14.0</NuGetToolVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="C:\Users\Faisa\.nuget\packages\" />
</ItemGroup>
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)xunit.runner.visualstudio\3.1.1\build\net8.0\xunit.runner.visualstudio.props" Condition="Exists('$(NuGetPackageRoot)xunit.runner.visualstudio\3.1.1\build\net8.0\xunit.runner.visualstudio.props')" />
<Import Project="$(NuGetPackageRoot)xunit.core\2.9.3\build\xunit.core.props" Condition="Exists('$(NuGetPackageRoot)xunit.core\2.9.3\build\xunit.core.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore\8.0.18\buildTransitive\net8.0\Microsoft.EntityFrameworkCore.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore\8.0.18\buildTransitive\net8.0\Microsoft.EntityFrameworkCore.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.testplatform.testhost\17.14.1\build\net8.0\Microsoft.TestPlatform.TestHost.props" Condition="Exists('$(NuGetPackageRoot)microsoft.testplatform.testhost\17.14.1\build\net8.0\Microsoft.TestPlatform.TestHost.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.codecoverage\17.14.1\build\netstandard2.0\Microsoft.CodeCoverage.props" Condition="Exists('$(NuGetPackageRoot)microsoft.codecoverage\17.14.1\build\netstandard2.0\Microsoft.CodeCoverage.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.test.sdk\17.14.1\build\net8.0\Microsoft.NET.Test.Sdk.props" Condition="Exists('$(NuGetPackageRoot)microsoft.net.test.sdk\17.14.1\build\net8.0\Microsoft.NET.Test.Sdk.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\8.0.1\buildTransitive\net6.0\Microsoft.Extensions.Configuration.UserSecrets.props" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\8.0.1\buildTransitive\net6.0\Microsoft.Extensions.Configuration.UserSecrets.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore.design\8.0.18\build\net8.0\Microsoft.EntityFrameworkCore.Design.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore.design\8.0.18\build\net8.0\Microsoft.EntityFrameworkCore.Design.props')" />
</ImportGroup>
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Pkgxunit_analyzers Condition=" '$(Pkgxunit_analyzers)' == '' ">C:\Users\Faisa\.nuget\packages\xunit.analyzers\1.18.0</Pkgxunit_analyzers>
<PkgMicrosoft_Extensions_ApiDescription_Server Condition=" '$(PkgMicrosoft_Extensions_ApiDescription_Server)' == '' ">C:\Users\Faisa\.nuget\packages\microsoft.extensions.apidescription.server\8.0.0</PkgMicrosoft_Extensions_ApiDescription_Server>
<PkgMicrosoft_CodeAnalysis_Analyzers Condition=" '$(PkgMicrosoft_CodeAnalysis_Analyzers)' == '' ">C:\Users\Faisa\.nuget\packages\microsoft.codeanalysis.analyzers\3.3.3</PkgMicrosoft_CodeAnalysis_Analyzers>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)xunit.core\2.9.3\build\xunit.core.targets" Condition="Exists('$(NuGetPackageRoot)xunit.core\2.9.3\build\xunit.core.targets')" />
<Import Project="$(NuGetPackageRoot)system.text.json\8.0.5\buildTransitive\net6.0\System.Text.Json.targets" Condition="Exists('$(NuGetPackageRoot)system.text.json\8.0.5\buildTransitive\net6.0\System.Text.Json.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\8.0.2\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\8.0.2\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
<Import Project="$(NuGetPackageRoot)sqlitepclraw.lib.e_sqlite3\2.1.6\buildTransitive\net8.0\SQLitePCLRaw.lib.e_sqlite3.targets" Condition="Exists('$(NuGetPackageRoot)sqlitepclraw.lib.e_sqlite3\2.1.6\buildTransitive\net8.0\SQLitePCLRaw.lib.e_sqlite3.targets')" />
<Import Project="$(NuGetPackageRoot)selenium.webdriver.chromedriver\138.0.7204.9400\build\Selenium.WebDriver.ChromeDriver.targets" Condition="Exists('$(NuGetPackageRoot)selenium.webdriver.chromedriver\138.0.7204.9400\build\Selenium.WebDriver.ChromeDriver.targets')" />
<Import Project="$(NuGetPackageRoot)selenium.webdriver\4.34.0\buildTransitive\Selenium.WebDriver.targets" Condition="Exists('$(NuGetPackageRoot)selenium.webdriver\4.34.0\buildTransitive\Selenium.WebDriver.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.options\8.0.2\buildTransitive\net6.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\8.0.2\buildTransitive\net6.0\Microsoft.Extensions.Options.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.testplatform.testhost\17.14.1\build\net8.0\Microsoft.TestPlatform.TestHost.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.testplatform.testhost\17.14.1\build\net8.0\Microsoft.TestPlatform.TestHost.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.codecoverage\17.14.1\build\netstandard2.0\Microsoft.CodeCoverage.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.codecoverage\17.14.1\build\netstandard2.0\Microsoft.CodeCoverage.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.test.sdk\17.14.1\build\net8.0\Microsoft.NET.Test.Sdk.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.net.test.sdk\17.14.1\build\net8.0\Microsoft.NET.Test.Sdk.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.binder\8.0.2\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.binder\8.0.2\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\8.0.1\buildTransitive\net6.0\Microsoft.Extensions.Configuration.UserSecrets.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\8.0.1\buildTransitive\net6.0\Microsoft.Extensions.Configuration.UserSecrets.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.aspnetcore.mvc.testing\8.0.18\buildTransitive\net8.0\Microsoft.AspNetCore.Mvc.Testing.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.aspnetcore.mvc.testing\8.0.18\buildTransitive\net8.0\Microsoft.AspNetCore.Mvc.Testing.targets')" />
<Import Project="$(NuGetPackageRoot)coverlet.collector\6.0.4\build\netstandard2.0\coverlet.collector.targets" Condition="Exists('$(NuGetPackageRoot)coverlet.collector\6.0.4\build\netstandard2.0\coverlet.collector.targets')" />
</ImportGroup>
</Project>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,127 @@
{
"version": 2,
"dgSpecHash": "D2/2MF0NkRs=",
"success": true,
"projectFilePath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests.WebsiteTests\\ProjectLighthouse.Tests.WebsiteTests.csproj",
"expectedPackageFiles": [
"C:\\Users\\Faisa\\.nuget\\packages\\bcrypt.net-next\\4.0.3\\bcrypt.net-next.4.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\bouncycastle.cryptography\\2.6.1\\bouncycastle.cryptography.2.6.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\castle.core\\5.1.1\\castle.core.5.1.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\coverlet.collector\\6.0.4\\coverlet.collector.6.0.4.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\discord.net.core\\3.17.4\\discord.net.core.3.17.4.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\discord.net.rest\\3.17.4\\discord.net.rest.3.17.4.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\discord.net.webhook\\3.17.4\\discord.net.webhook.3.17.4.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\distributedlock.core\\1.0.6\\distributedlock.core.1.0.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\distributedlock.mysql\\1.0.2\\distributedlock.mysql.1.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\humanizer.core\\2.14.1\\humanizer.core.2.14.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\jetbrains.annotations\\2024.3.0\\jetbrains.annotations.2024.3.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.aspnetcore.diagnostics.entityframeworkcore\\8.0.18\\microsoft.aspnetcore.diagnostics.entityframeworkcore.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.aspnetcore.mvc.testing\\8.0.18\\microsoft.aspnetcore.mvc.testing.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.aspnetcore.testhost\\8.0.18\\microsoft.aspnetcore.testhost.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.bcl.asyncinterfaces\\8.0.0\\microsoft.bcl.asyncinterfaces.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codeanalysis.analyzers\\3.3.3\\microsoft.codeanalysis.analyzers.3.3.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codeanalysis.common\\4.5.0\\microsoft.codeanalysis.common.4.5.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codeanalysis.csharp\\4.5.0\\microsoft.codeanalysis.csharp.4.5.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codeanalysis.csharp.workspaces\\4.5.0\\microsoft.codeanalysis.csharp.workspaces.4.5.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codeanalysis.workspaces.common\\4.5.0\\microsoft.codeanalysis.workspaces.common.4.5.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codecoverage\\17.14.1\\microsoft.codecoverage.17.14.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.data.sqlite.core\\8.0.6\\microsoft.data.sqlite.core.8.0.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore\\8.0.18\\microsoft.entityframeworkcore.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.abstractions\\8.0.18\\microsoft.entityframeworkcore.abstractions.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.analyzers\\8.0.18\\microsoft.entityframeworkcore.analyzers.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.design\\8.0.18\\microsoft.entityframeworkcore.design.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.relational\\8.0.18\\microsoft.entityframeworkcore.relational.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.sqlite\\8.0.6\\microsoft.entityframeworkcore.sqlite.8.0.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.sqlite.core\\8.0.6\\microsoft.entityframeworkcore.sqlite.core.8.0.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.apidescription.server\\8.0.0\\microsoft.extensions.apidescription.server.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.caching.abstractions\\8.0.0\\microsoft.extensions.caching.abstractions.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.caching.memory\\8.0.1\\microsoft.extensions.caching.memory.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration\\8.0.0\\microsoft.extensions.configuration.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.abstractions\\8.0.0\\microsoft.extensions.configuration.abstractions.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.binder\\8.0.2\\microsoft.extensions.configuration.binder.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.commandline\\8.0.0\\microsoft.extensions.configuration.commandline.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.environmentvariables\\8.0.0\\microsoft.extensions.configuration.environmentvariables.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.fileextensions\\8.0.1\\microsoft.extensions.configuration.fileextensions.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.json\\8.0.1\\microsoft.extensions.configuration.json.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.usersecrets\\8.0.1\\microsoft.extensions.configuration.usersecrets.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.dependencyinjection\\8.0.1\\microsoft.extensions.dependencyinjection.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.dependencyinjection.abstractions\\8.0.2\\microsoft.extensions.dependencyinjection.abstractions.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.dependencymodel\\8.0.2\\microsoft.extensions.dependencymodel.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.diagnostics\\8.0.1\\microsoft.extensions.diagnostics.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.diagnostics.abstractions\\8.0.1\\microsoft.extensions.diagnostics.abstractions.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.fileproviders.abstractions\\8.0.0\\microsoft.extensions.fileproviders.abstractions.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.fileproviders.physical\\8.0.0\\microsoft.extensions.fileproviders.physical.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.filesystemglobbing\\8.0.0\\microsoft.extensions.filesystemglobbing.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.hosting\\8.0.1\\microsoft.extensions.hosting.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.hosting.abstractions\\8.0.1\\microsoft.extensions.hosting.abstractions.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging\\8.0.1\\microsoft.extensions.logging.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.abstractions\\8.0.2\\microsoft.extensions.logging.abstractions.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.configuration\\8.0.1\\microsoft.extensions.logging.configuration.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.console\\8.0.1\\microsoft.extensions.logging.console.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.debug\\8.0.1\\microsoft.extensions.logging.debug.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.eventlog\\8.0.1\\microsoft.extensions.logging.eventlog.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.eventsource\\8.0.1\\microsoft.extensions.logging.eventsource.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.options\\8.0.2\\microsoft.extensions.options.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.options.configurationextensions\\8.0.0\\microsoft.extensions.options.configurationextensions.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.primitives\\8.0.0\\microsoft.extensions.primitives.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.net.test.sdk\\17.14.1\\microsoft.net.test.sdk.17.14.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.openapi\\1.6.23\\microsoft.openapi.1.6.23.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.testplatform.objectmodel\\17.14.1\\microsoft.testplatform.objectmodel.17.14.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.testplatform.testhost\\17.14.1\\microsoft.testplatform.testhost.17.14.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\mono.texttemplating\\2.2.1\\mono.texttemplating.2.2.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\moq\\4.20.72\\moq.4.20.72.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\mysqlconnector\\2.3.5\\mysqlconnector.2.3.5.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\newtonsoft.json\\13.0.3\\newtonsoft.json.13.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\pfim\\0.11.3\\pfim.0.11.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\pipelines.sockets.unofficial\\2.2.8\\pipelines.sockets.unofficial.2.2.8.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\pomelo.entityframeworkcore.mysql\\8.0.2\\pomelo.entityframeworkcore.mysql.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\qrcoder\\1.6.0\\qrcoder.1.6.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\redis.om\\1.0.1\\redis.om.1.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\selenium.webdriver\\4.34.0\\selenium.webdriver.4.34.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\selenium.webdriver.chromedriver\\138.0.7204.9400\\selenium.webdriver.chromedriver.138.0.7204.9400.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sharpziplib\\1.4.2\\sharpziplib.1.4.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sixlabors.imagesharp\\3.1.10\\sixlabors.imagesharp.3.1.10.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sqlitepclraw.bundle_e_sqlite3\\2.1.6\\sqlitepclraw.bundle_e_sqlite3.2.1.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sqlitepclraw.core\\2.1.6\\sqlitepclraw.core.2.1.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sqlitepclraw.lib.e_sqlite3\\2.1.6\\sqlitepclraw.lib.e_sqlite3.2.1.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sqlitepclraw.provider.e_sqlite3\\2.1.6\\sqlitepclraw.provider.e_sqlite3.2.1.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\stackexchange.redis\\2.7.17\\stackexchange.redis.2.7.17.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\swashbuckle.aspnetcore\\9.0.3\\swashbuckle.aspnetcore.9.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\swashbuckle.aspnetcore.swagger\\9.0.3\\swashbuckle.aspnetcore.swagger.9.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\swashbuckle.aspnetcore.swaggergen\\9.0.3\\swashbuckle.aspnetcore.swaggergen.9.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\swashbuckle.aspnetcore.swaggerui\\9.0.3\\swashbuckle.aspnetcore.swaggerui.9.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.codedom\\4.4.0\\system.codedom.4.4.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.collections.immutable\\8.0.0\\system.collections.immutable.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition\\6.0.0\\system.composition.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition.attributedmodel\\6.0.0\\system.composition.attributedmodel.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition.convention\\6.0.0\\system.composition.convention.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition.hosting\\6.0.0\\system.composition.hosting.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition.runtime\\6.0.0\\system.composition.runtime.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition.typedparts\\6.0.0\\system.composition.typedparts.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.diagnostics.eventlog\\8.0.1\\system.diagnostics.eventlog.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.interactive.async\\6.0.1\\system.interactive.async.6.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.io.pipelines\\8.0.0\\system.io.pipelines.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.linq.async\\6.0.1\\system.linq.async.6.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.memory\\4.5.3\\system.memory.4.5.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.reflection.metadata\\8.0.0\\system.reflection.metadata.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.runtime.compilerservices.unsafe\\6.0.0\\system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.text.encoding.codepages\\6.0.0\\system.text.encoding.codepages.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.text.json\\8.0.5\\system.text.json.8.0.5.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.threading.channels\\6.0.0\\system.threading.channels.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.valuetuple\\4.5.0\\system.valuetuple.4.5.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\ulid\\1.2.6\\ulid.1.2.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit\\2.9.3\\xunit.2.9.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.abstractions\\2.0.3\\xunit.abstractions.2.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.analyzers\\1.18.0\\xunit.analyzers.1.18.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.assert\\2.9.3\\xunit.assert.2.9.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.core\\2.9.3\\xunit.core.2.9.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.extensibility.core\\2.9.3\\xunit.extensibility.core.2.9.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.extensibility.execution\\2.9.3\\xunit.extensibility.execution.2.9.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.runner.visualstudio\\3.1.1\\xunit.runner.visualstudio.3.1.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\yamldotnet\\16.3.0\\yamldotnet.16.3.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.netcore.app.ref\\8.0.19\\microsoft.netcore.app.ref.8.0.19.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.windowsdesktop.app.ref\\8.0.19\\microsoft.windowsdesktop.app.ref.8.0.19.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.aspnetcore.app.ref\\8.0.19\\microsoft.aspnetcore.app.ref.8.0.19.nupkg.sha512"
],
"logs": []
}

View file

@ -1,27 +1,27 @@
<EFBFBD><EFBFBD>N<EFBFBD><EFBFBD><EFBFBD><EFBFBD>g<EFBFBD><EFBFBD>▒;ݎ<>soVy<56><79>ʖQ<CA96><EFBFBD><39>L`<60>
m<EFBFBD>]<5D><> <20><>!<21>p<EFBFBD>x/JY@<40><>{<7B><><EFBFBD><EFBFBD><EFBFBD>Yj<59>G<EFBFBD><47>4<EFBFBD><34><EFBFBD>O<EFBFBD>c{<7B><>9<EFBFBD><39><EFBFBD>|n=<3D>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>З<EFBFBD>O<EFBFBD><4F>œRF<52><46><EFBFBD>{<7B><><EFBFBD><EFBFBD>SQ<53><51>Fх <20><><EFBFBD><EFBFBD><EFBFBD>0><3E> <20><>hλ37=<3D><>,<2C>f<EFBFBD><66><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD>C<EFBFBD><EFBFBD><EFBFBD><EFBFBD>^<5E>ݳrY<72><59>I<EFBFBD><49><EFBFBD><EFBFBD><EFBFBD>/<2F>^<5E>ue<75>ױ~WϮ<57><CFAE><EFBFBD>6ҝ)S</<2F>AP,<2C><>[n<><6E><EFBFBD><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD>j1ܗ׆<DC97><D786><EFBFBD><EFBFBD>v<EFBFBD>J"IS<49>_<EFBFBD><5F>\R<><52>
!<21><>,<2C>1#<23><>o<EFBFBD>)y<><79>ᰅu <20>J<EFBFBD><4A><EFBFBD>a<EFBFBD>>gQ<67>ǰ<EFBFBD>VF~]<5D>~<7E><><EFBFBD><EFBFBD>GY5<59><35>o04<30><34>s[<5B><>FgƄ|<7C><>;<3B>p<EFBFBD>.<2E>O<EFBFBD>[<5B><>>d<>ɉ<EFBFBD>C<EFBFBD><43>M<EFBFBD><4D>9<EFBFBD>T꨿:<3A><>)<29>N<EFBFBD><4E>;z'<27><>7<EFBFBD>>,<2C><><EFBFBD><EFBFBD>cc<63>h0<68><30><EFBFBD>+<2B>c<EFBFBD><63>
B<><42><EFBFBD><E29692>lTFH /<2F>*<2A>m<EFBFBD><6D>F<EFBFBD>W<EFBFBD>̚<EFBFBD><CC9A>Q<EFBFBD><51>q<EFBFBD><71>ϰ<EFBFBD>R{<7B><><EFBFBD>߂O{<7B><>_D<5F><44>mM<6D>!<21><><EFBFBD><EFBFBD>?<3F>i-1(<28><>fK<66><4B>▒&<26><><EFBFBD>&l<><6C><EFBFBD>nI<6E><49>/▒<>6<EFBFBD><36><EFBFBD>
<20>H<EFBFBD>6<EFBFBD><36>m<EFBFBD>Ԯ<EFBFBD><D4AE>,<2C>F<EFBFBD>zuT<75><54><EFBFBD>D<EFBFBD>%<25>d<EFBFBD>C<EFBFBD><43>Q)N<><4E>hS<68>}mZ<6D>~<7E>>x<><78><EFBFBD>@<40> "A<>O<EFBFBD>n<EFBFBD><6E> ¸<><C2B8>jbh<62><68>[<5B><><EFBFBD><EFBFBD>p<EFBFBD>V<EFBFBD><56>^+<2B><><EFBFBD><EFBFBD>r<EFBFBD>F<EFBFBD><46> <20>]<5D><><EFBFBD>m{<7B><><EFBFBD><EFBFBD>ҋ<EFBFBD>v<EFBFBD><76>4^QA+<2B><><EFBFBD><EFBFBD>X^O<>D<EFBFBD><44><EFBFBD><EFBFBD>`<60><><EFBFBD>\Y3<59>q#<23>j<EFBFBD><6A>#E<>n<EFBFBD><6E>[<5B><EFBFBD><E7A6BD>
<EFBFBD>E";<3B>/<2F>`<60>jS/_<>j9Ƒ<39>
<20><><EFBFBD>?<3F><><EFBFBD><EFBFBD><EFBFBD>V<EFBFBD><56><EFBFBD>\<5C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>9M<39><4D>i<EFBFBD><69>;k(<28><><EFBFBD>Z#
k<><6B>w<EFBFBD>M<EFBFBD>O
<20>r
?<3F>s~<7E><>Ԑ<EFBFBD>]<5D>!<21>^<5E>'<27>Kw<4B><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD>q7<71><37>)<29><><EFBFBD>X<EFBFBD>j<EFBFBD>o&<26>|{0<><30>*2<><32><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD>b<EFBFBD>&Jh<4A><EFBFBD>y<EFBFBD><79>7<EFBFBD><37><EFBFBD><<3C><> <20><>ꝱϷ<EA9DB1>g
+~<7E><>&<26>1S<31>\x<>Wf<57><66>J<EFBFBD>Ԓݣpd<70>2=<3D>W<EFBFBD>Ub<55><62><EFBFBD><EFBFBD>i<EFBFBD>?
<20><>5<EFBFBD><35>ں}<7D><>j<EFBFBD>e#=գ<><D5A3>Q<EFBFBD><51><EFBFBD>5<EFBFBD>rX6<58><36><EFBFBD><><DD8B><EFBFBD><EFBFBD>
<20>у<EFBFBD>j:1f<31>MG<4D><47><EFBFBD><EFBFBD><EFBFBD>ϮZ<CFAE><5A>3<EFBFBD><33>7<EFBFBD><37>-<2D>q<EFBFBD><71><EFBFBD><EFBFBD><EFBFBD><EFBFBD>oaE+<2B><>▒ m<> <20><><EFBFBD><EFBFBD>Q<EFBFBD>/7<><37>`<60>x['<27>7<EFBFBD>
-<2D><>nFV桖<56><E6A196>1<EFBFBD>smP<6D><50>v<EFBFBD>;<3B>B<EFBFBD><42>>X<><58>u-
M<EFBFBD>p%<25>3<EFBFBD><33>k )<29>y<EFBFBD> <20><><EFBFBD>œ &Z<>$<24><>(<28>(<28>u<EFBFBD>z<EFBFBD>~<7E><><EFBFBD><EFBFBD>'B%<25>:<3A><><鍷<><E98DB7><EFBFBD>
<20><>T
<EFBFBD><EFBFBD>=<3D>v<EFBFBD><76><EFBFBD>r<EFBFBD>U<EFBFBD><55><EFBFBD><EFBFBD><EFBFBD><EFBFBD>▒)<29><><EFBFBD>m<EFBFBD><6D><EFBFBD>d,<2C><>q(f.<2E><><EFBFBD>ίv<CEAF><20><>:<3A>F <20><>&V<><56>wZ<77>E&<26><><EFBFBD><EFBFBD>D<EFBFBD><44><EFBFBD><EFBFBD>
i <20><>9<EFBFBD><39><EFBFBD>%<25><><EFBFBD><EFBFBD>w<EFBFBD><77>eM▒<4D><E29692>/qH~q@<40><<3C><>YH<59><48><EFBFBD>BLKx<4B>V<EFBFBD><56><EFBFBD>v<EFBFBD>
<20><>t<EFBFBD>U<EFBFBD>1<EFBFBD>I<EFBFBD><49><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>|K<>HL8<4C>G<EFBFBD>O<EFBFBD><4F><EFBFBD><EFBFBD><EFBFBD>6̆~<7E> <20>s)<29><>۹<EFBFBD>zM<7A><4D><EFBFBD>0cG9<47>(<28><><EFBFBD><EFBFBD>$v<>ʑd<CA91>Uy<55><79><EFBFBD>_Sn<53>><3E><>G<EFBFBD><47><EFBFBD><EFBFBD><EFBFBD>y<EFBFBD>\I*(<28><><EFBFBD>
<20>ĀI<C480><49><EFBFBD>x<EFBFBD>cє8<D194>%<25>!c<>ٮb▒l<E29692><6C><EFBFBD><EFBFBD>.M<>u<EFBFBD><<3C>$GPx.-<2D>
<20>޷<EFBFBD><DEB7><EFBFBD>!eF9
H`)[<5B><><EFBFBD><EFBFBD><E29692><EFBFBD><EFBFBD><EFBFBD><EFBFBD>g<EFBFBD><67><EFBFBD>n<EFBFBD>6j <20>͓<EFBFBD>a<EFBFBD>eߞ'<27><><EFBFBD><EFBFBD> ><3E>`28<32><38>0<EFBFBD><30>Q5d/Ǥ<><C7A4>q<EFBFBD>8<EFBFBD><38>J<EFBFBD>赱r<E8B5B1>iD(<28><>*<2A><>Z<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>>K4<4B><34>G<EFBFBD>]<5D>q\<5C>}m<><6D>3<EFBFBD><33><EFBFBD><EFBFBD>)<29>s&<26><>[<5B><><EFBFBD><EFBFBD>1T!<21><>t<EFBFBD>=ӱl<D3B1>;$<24><><EFBFBD><EFBFBD>~<7E><>vH`
Z,޳K<DEB3>_<EFBFBD>F<EFBFBD>?K)<29><><EFBFBD>i<EFBFBD><69>Ի<*)<29>e<EFBFBD>=<3D><>`<60>/i͐+U<>d<EFBFBD><64><EFBFBD>i<EFBFBD><69><EFBFBD><EFBFBD><EFBFBD><57><D2AD><EFBFBD>h<EFBFBD>[̃䝍<CC83>}<7D><>:<3A><><EFBFBD>Z<EFBFBD><5A><EFBFBD>υq<CF85>ɂnRcrx깼36<33><36>b<EFBFBD><62>9<EFBFBD>-"{<7B>a^j;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5>f<EFBFBD>[<5B><>̓o<CD83><6F><EFBFBD><EFBFBD>D`)<29><><EFBFBD><EFBFBD>F7<46><37>ݩ/<2F><>><3E><><EFBFBD><EFBFBD>h<EFBFBD><68>r<EFBFBD><72>M1<4D><31>(Tc0E4
Ol<4F>O<EFBFBD><4F>ƷB<C6B7>c桩<63><E6A1A9>ًM[<5B>{<7B><><EFBFBD>><3E>A^C
<EFBFBD><EFBFBD>N<EFBFBD><EFBFBD><EFBFBD><EFBFBD>g<EFBFBD><EFBFBD>▒;ݎ<>soVy<56><79>ʖQ<CA96><EFBFBD><39>L`<60>
m<EFBFBD>]<5D><> <20><>!<21>p<EFBFBD>x/JY@<40><>{<7B><><EFBFBD><EFBFBD><EFBFBD>Yj<59>G<EFBFBD><47>4<EFBFBD><34><EFBFBD>O<EFBFBD>c{<7B><>9<EFBFBD><39><EFBFBD>|n=<3D>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>З<EFBFBD>O<EFBFBD><4F>œRF<52><46><EFBFBD>{<7B><><EFBFBD><EFBFBD>SQ<53><51>Fх <20><><EFBFBD><EFBFBD><EFBFBD>0><3E> <20><>hλ37=<3D><>,<2C>f<EFBFBD><66><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD>C<EFBFBD><EFBFBD><EFBFBD><EFBFBD>^<5E>ݳrY<72><59>I<EFBFBD><49><EFBFBD><EFBFBD><EFBFBD>/<2F>^<5E>ue<75>ױ~WϮ<57><CFAE><EFBFBD>6ҝ)S</<2F>AP,<2C><>[n<><6E><EFBFBD><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD>j1ܗ׆<DC97><D786><EFBFBD><EFBFBD>v<EFBFBD>J"IS<49>_<EFBFBD><5F>\R<><52>
!<21><>,<2C>1#<23><>o<EFBFBD>)y<><79>ᰅu <20>J<EFBFBD><4A><EFBFBD>a<EFBFBD>>gQ<67>ǰ<EFBFBD>VF~]<5D>~<7E><><EFBFBD><EFBFBD>GY5<59><35>o04<30><34>s[<5B><>FgƄ|<7C><>;<3B>p<EFBFBD>.<2E>O<EFBFBD>[<5B><>>d<>ɉ<EFBFBD>C<EFBFBD><43>M<EFBFBD><4D>9<EFBFBD>T꨿:<3A><>)<29>N<EFBFBD><4E>;z'<27><>7<EFBFBD>>,<2C><><EFBFBD><EFBFBD>cc<63>h0<68><30><EFBFBD>+<2B>c<EFBFBD><63>
B<><42><EFBFBD><E29692>lTFH /<2F>*<2A>m<EFBFBD><6D>F<EFBFBD>W<EFBFBD>̚<EFBFBD><CC9A>Q<EFBFBD><51>q<EFBFBD><71>ϰ<EFBFBD>R{<7B><><EFBFBD>߂O{<7B><>_D<5F><44>mM<6D>!<21><><EFBFBD><EFBFBD>?<3F>i-1(<28><>fK<66><4B>▒&<26><><EFBFBD>&l<><6C><EFBFBD>nI<6E><49>/▒<>6<EFBFBD><36><EFBFBD>
<20>H<EFBFBD>6<EFBFBD><36>m<EFBFBD>Ԯ<EFBFBD><D4AE>,<2C>F<EFBFBD>zuT<75><54><EFBFBD>D<EFBFBD>%<25>d<EFBFBD>C<EFBFBD><43>Q)N<><4E>hS<68>}mZ<6D>~<7E>>x<><78><EFBFBD>@<40> "A<>O<EFBFBD>n<EFBFBD><6E> ¸<><C2B8>jbh<62><68>[<5B><><EFBFBD><EFBFBD>p<EFBFBD>V<EFBFBD><56>^+<2B><><EFBFBD><EFBFBD>r<EFBFBD>F<EFBFBD><46> <20>]<5D><><EFBFBD>m{<7B><><EFBFBD><EFBFBD>ҋ<EFBFBD>v<EFBFBD><76>4^QA+<2B><><EFBFBD><EFBFBD>X^O<>D<EFBFBD><44><EFBFBD><EFBFBD>`<60><><EFBFBD>\Y3<59>q#<23>j<EFBFBD><6A>#E<>n<EFBFBD><6E>[<5B><EFBFBD><E7A6BD>
<EFBFBD>E";<3B>/<2F>`<60>jS/_<>j9Ƒ<39>
<20><><EFBFBD>?<3F><><EFBFBD><EFBFBD><EFBFBD>V<EFBFBD><56><EFBFBD>\<5C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>9M<39><4D>i<EFBFBD><69>;k(<28><><EFBFBD>Z#
k<><6B>w<EFBFBD>M<EFBFBD>O
<20>r
?<3F>s~<7E><>Ԑ<EFBFBD>]<5D>!<21>^<5E>'<27>Kw<4B><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD>q7<71><37>)<29><><EFBFBD>X<EFBFBD>j<EFBFBD>o&<26>|{0<><30>*2<><32><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD>b<EFBFBD>&Jh<4A><EFBFBD>y<EFBFBD><79>7<EFBFBD><37><EFBFBD><<3C><> <20><>ꝱϷ<EA9DB1>g
+~<7E><>&<26>1S<31>\x<>Wf<57><66>J<EFBFBD>Ԓݣpd<70>2=<3D>W<EFBFBD>Ub<55><62><EFBFBD><EFBFBD>i<EFBFBD>?
<20><>5<EFBFBD><35>ں}<7D><>j<EFBFBD>e#=գ<><D5A3>Q<EFBFBD><51><EFBFBD>5<EFBFBD>rX6<58><36><EFBFBD><><DD8B><EFBFBD><EFBFBD>
<20>у<EFBFBD>j:1f<31>MG<4D><47><EFBFBD><EFBFBD><EFBFBD>ϮZ<CFAE><5A>3<EFBFBD><33>7<EFBFBD><37>-<2D>q<EFBFBD><71><EFBFBD><EFBFBD><EFBFBD><EFBFBD>oaE+<2B><>▒ m<> <20><><EFBFBD><EFBFBD>Q<EFBFBD>/7<><37>`<60>x['<27>7<EFBFBD>
-<2D><>nFV桖<56><E6A196>1<EFBFBD>smP<6D><50>v<EFBFBD>;<3B>B<EFBFBD><42>>X<><58>u-
M<EFBFBD>p%<25>3<EFBFBD><33>k )<29>y<EFBFBD> <20><><EFBFBD>œ &Z<>$<24><>(<28>(<28>u<EFBFBD>z<EFBFBD>~<7E><><EFBFBD><EFBFBD>'B%<25>:<3A><><鍷<><E98DB7><EFBFBD>
<20><>T
<EFBFBD><EFBFBD>=<3D>v<EFBFBD><76><EFBFBD>r<EFBFBD>U<EFBFBD><55><EFBFBD><EFBFBD><EFBFBD><EFBFBD>▒)<29><><EFBFBD>m<EFBFBD><6D><EFBFBD>d,<2C><>q(f.<2E><><EFBFBD>ίv<CEAF><20><>:<3A>F <20><>&V<><56>wZ<77>E&<26><><EFBFBD><EFBFBD>D<EFBFBD><44><EFBFBD><EFBFBD>
i <20><>9<EFBFBD><39><EFBFBD>%<25><><EFBFBD><EFBFBD>w<EFBFBD><77>eM▒<4D><E29692>/qH~q@<40><<3C><>YH<59><48><EFBFBD>BLKx<4B>V<EFBFBD><56><EFBFBD>v<EFBFBD>
<20><>t<EFBFBD>U<EFBFBD>1<EFBFBD>I<EFBFBD><49><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>|K<>HL8<4C>G<EFBFBD>O<EFBFBD><4F><EFBFBD><EFBFBD><EFBFBD>6̆~<7E> <20>s)<29><>۹<EFBFBD>zM<7A><4D><EFBFBD>0cG9<47>(<28><><EFBFBD><EFBFBD>$v<>ʑd<CA91>Uy<55><79><EFBFBD>_Sn<53>><3E><>G<EFBFBD><47><EFBFBD><EFBFBD><EFBFBD>y<EFBFBD>\I*(<28><><EFBFBD>
<20>ĀI<C480><49><EFBFBD>x<EFBFBD>cє8<D194>%<25>!c<>ٮb▒l<E29692><6C><EFBFBD><EFBFBD>.M<>u<EFBFBD><<3C>$GPx.-<2D>
<20>޷<EFBFBD><DEB7><EFBFBD>!eF9
H`)[<5B><><EFBFBD><EFBFBD><E29692><EFBFBD><EFBFBD><EFBFBD><EFBFBD>g<EFBFBD><67><EFBFBD>n<EFBFBD>6j <20>͓<EFBFBD>a<EFBFBD>eߞ'<27><><EFBFBD><EFBFBD> ><3E>`28<32><38>0<EFBFBD><30>Q5d/Ǥ<><C7A4>q<EFBFBD>8<EFBFBD><38>J<EFBFBD>赱r<E8B5B1>iD(<28><>*<2A><>Z<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>>K4<4B><34>G<EFBFBD>]<5D>q\<5C>}m<><6D>3<EFBFBD><33><EFBFBD><EFBFBD>)<29>s&<26><>[<5B><><EFBFBD><EFBFBD>1T!<21><>t<EFBFBD>=ӱl<D3B1>;$<24><><EFBFBD><EFBFBD>~<7E><>vH`
Z,޳K<DEB3>_<EFBFBD>F<EFBFBD>?K)<29><><EFBFBD>i<EFBFBD><69>Ի<*)<29>e<EFBFBD>=<3D><>`<60>/i͐+U<>d<EFBFBD><64><EFBFBD>i<EFBFBD><69><EFBFBD><EFBFBD><EFBFBD><57><D2AD><EFBFBD>h<EFBFBD>[̃䝍<CC83>}<7D><>:<3A><><EFBFBD>Z<EFBFBD><5A><EFBFBD>υq<CF85>ɂnRcrx깼36<33><36>b<EFBFBD><62>9<EFBFBD>-"{<7B>a^j;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5>f<EFBFBD>[<5B><>̓o<CD83><6F><EFBFBD><EFBFBD>D`)<29><><EFBFBD><EFBFBD>F7<46><37>ݩ/<2F><>><3E><><EFBFBD><EFBFBD>h<EFBFBD><68>r<EFBFBD><72>M1<4D><31>(Tc0E4
Ol<4F>O<EFBFBD><4F>ƷB<C6B7>c桩<63><E6A1A9>ًM[<5B>{<7B><><EFBFBD>><3E>A^C

View file

@ -1,3 +1,3 @@
FSHb
FSHb
this is not my stuff to upload so its just gonna be a file like this for now :/

View file

@ -1,43 +1,43 @@
using System;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
namespace LBPUnion.ProjectLighthouse.Tests.Helpers;
public static class IntegrationHelper
{
private static readonly Lazy<bool> dbConnected = new(() =>
{
using DatabaseContext database = DatabaseContext.CreateNewInstance();
return database.Database.CanConnect();
});
/// <summary>
/// Resets the database to a clean state and returns a new DatabaseContext.
/// </summary>
/// <returns>A new fresh instance of DatabaseContext</returns>
public static async Task<DatabaseContext> GetIntegrationDatabase()
{
if (!dbConnected.Value)
{
throw new Exception("Database is not connected.\n" +
"Please ensure that the database is running and that the connection string is correct.\n" +
$"Connection string: {ServerConfiguration.Instance.DbConnectionString}");
}
await ClearRooms();
await using DatabaseContext database = DatabaseContext.CreateNewInstance();
await database.Database.EnsureDeletedAsync();
await database.Database.EnsureCreatedAsync();
return DatabaseContext.CreateNewInstance();
}
private static async Task ClearRooms()
{
await RoomHelper.Rooms.RemoveAllAsync();
}
using System;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
namespace LBPUnion.ProjectLighthouse.Tests.Helpers;
public static class IntegrationHelper
{
private static readonly Lazy<bool> dbConnected = new(() =>
{
using DatabaseContext database = DatabaseContext.CreateNewInstance();
return database.Database.CanConnect();
});
/// <summary>
/// Resets the database to a clean state and returns a new DatabaseContext.
/// </summary>
/// <returns>A new fresh instance of DatabaseContext</returns>
public static async Task<DatabaseContext> GetIntegrationDatabase()
{
if (!dbConnected.Value)
{
throw new Exception("Database is not connected.\n" +
"Please ensure that the database is running and that the connection string is correct.\n" +
$"Connection string: {ServerConfiguration.Instance.DbConnectionString}");
}
await ClearRooms();
await using DatabaseContext database = DatabaseContext.CreateNewInstance();
await database.Database.EnsureDeletedAsync();
await database.Database.EnsureCreatedAsync();
return DatabaseContext.CreateNewInstance();
}
private static async Task ClearRooms()
{
await RoomHelper.Rooms.RemoveAllAsync();
}
}

View file

@ -1,149 +1,149 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Helpers;
public static class MockHelper
{
public static UserEntity GetUnitTestUser() =>
new()
{
Username = "unittest",
UserId = 1,
};
public static GameTokenEntity GetUnitTestToken() =>
new()
{
Platform = Platform.UnitTest,
UserId = 1,
ExpiresAt = DateTime.MaxValue,
TokenId = 1,
UserToken = "unittest",
};
public static T2 CastTo<T1, T2>(this IActionResult result) where T1 : ObjectResult
{
T1 typedResult = Assert.IsType<T1>(result);
Assert.NotNull(typedResult);
Assert.NotNull(typedResult.Value);
T2 finalResult = Assert.IsType<T2>(typedResult.Value);
Assert.NotNull(finalResult);
return finalResult;
}
private static async Task<DbContextOptionsBuilder<DatabaseContext>> GetInMemoryDbOptions()
{
DbConnection connection = new SqliteConnection("DataSource=:memory:");
await connection.OpenAsync();
return new DbContextOptionsBuilder<DatabaseContext>().UseSqlite(connection);
}
public static async Task<DatabaseContext> GetTestDatabase(params object[] sets)
{
await RoomHelper.Rooms.RemoveAllAsync();
Dictionary<Type, IList> setDict = new();
foreach (IList list in sets)
{
Type? type = list.GetType().GetGenericArguments().ElementAtOrDefault(0);
if (type == null) continue;
setDict[type] = list;
}
setDict.TryAdd(typeof(GameTokenEntity), new List<GameTokenEntity>());
setDict.TryAdd(typeof(UserEntity), new List<UserEntity>());
// add the default user token if another token with id 1 isn't specified
if (setDict.TryGetValue(typeof(GameTokenEntity), out IList? tokens))
{
if (tokens.Cast<GameTokenEntity>().FirstOrDefault(t => t.TokenId == 1) == null)
{
setDict[typeof(GameTokenEntity)].Add(GetUnitTestToken());
}
}
// add the default user if another user with id 1 isn't specified
if (setDict.TryGetValue(typeof(UserEntity), out IList? users))
{
if (users.Cast<UserEntity>().FirstOrDefault(u => u.UserId == 1) == null)
{
setDict[typeof(UserEntity)].Add(GetUnitTestUser());
}
}
DbContextOptions<DatabaseContext> options = (await GetInMemoryDbOptions()).Options;
await using DatabaseContext context = new(options);
await context.Database.EnsureCreatedAsync();
foreach (IList list in setDict.Select(p => p.Value))
{
foreach (object item in list)
{
context.Add(item);
}
}
await context.SaveChangesAsync();
return new DatabaseContext(options);
}
public static void SetupTestController(this ControllerBase controllerBase, string? body = null)
{
SetupTestController(controllerBase, GetUnitTestToken(), body);
}
public static void SetupTestController(this ControllerBase controllerBase, GameTokenEntity token, string? body = null)
{
controllerBase.ControllerContext = GetMockControllerContext(body);
SetupTestGameToken(controllerBase, token);
}
public static ControllerContext GetMockControllerContext() =>
new()
{
HttpContext = new DefaultHttpContext(),
};
private static ControllerContext GetMockControllerContext(string? body) =>
new()
{
HttpContext = new DefaultHttpContext
{
Request =
{
ContentLength = body?.Length ?? 0,
Body = new MemoryStream(Encoding.ASCII.GetBytes(body ?? string.Empty)),
},
},
ActionDescriptor = new ControllerActionDescriptor
{
ActionName = "",
},
};
private static void SetupTestGameToken(ControllerBase controller, GameTokenEntity token)
{
controller.HttpContext.Items["Token"] = token;
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Helpers;
public static class MockHelper
{
public static UserEntity GetUnitTestUser() =>
new()
{
Username = "unittest",
UserId = 1,
};
public static GameTokenEntity GetUnitTestToken() =>
new()
{
Platform = Platform.UnitTest,
UserId = 1,
ExpiresAt = DateTime.MaxValue,
TokenId = 1,
UserToken = "unittest",
};
public static T2 CastTo<T1, T2>(this IActionResult result) where T1 : ObjectResult
{
T1 typedResult = Assert.IsType<T1>(result);
Assert.NotNull(typedResult);
Assert.NotNull(typedResult.Value);
T2 finalResult = Assert.IsType<T2>(typedResult.Value);
Assert.NotNull(finalResult);
return finalResult;
}
private static async Task<DbContextOptionsBuilder<DatabaseContext>> GetInMemoryDbOptions()
{
DbConnection connection = new SqliteConnection("DataSource=:memory:");
await connection.OpenAsync();
return new DbContextOptionsBuilder<DatabaseContext>().UseSqlite(connection);
}
public static async Task<DatabaseContext> GetTestDatabase(params object[] sets)
{
await RoomHelper.Rooms.RemoveAllAsync();
Dictionary<Type, IList> setDict = new();
foreach (IList list in sets)
{
Type? type = list.GetType().GetGenericArguments().ElementAtOrDefault(0);
if (type == null) continue;
setDict[type] = list;
}
setDict.TryAdd(typeof(GameTokenEntity), new List<GameTokenEntity>());
setDict.TryAdd(typeof(UserEntity), new List<UserEntity>());
// add the default user token if another token with id 1 isn't specified
if (setDict.TryGetValue(typeof(GameTokenEntity), out IList? tokens))
{
if (tokens.Cast<GameTokenEntity>().FirstOrDefault(t => t.TokenId == 1) == null)
{
setDict[typeof(GameTokenEntity)].Add(GetUnitTestToken());
}
}
// add the default user if another user with id 1 isn't specified
if (setDict.TryGetValue(typeof(UserEntity), out IList? users))
{
if (users.Cast<UserEntity>().FirstOrDefault(u => u.UserId == 1) == null)
{
setDict[typeof(UserEntity)].Add(GetUnitTestUser());
}
}
DbContextOptions<DatabaseContext> options = (await GetInMemoryDbOptions()).Options;
await using DatabaseContext context = new(options);
await context.Database.EnsureCreatedAsync();
foreach (IList list in setDict.Select(p => p.Value))
{
foreach (object item in list)
{
context.Add(item);
}
}
await context.SaveChangesAsync();
return new DatabaseContext(options);
}
public static void SetupTestController(this ControllerBase controllerBase, string? body = null)
{
SetupTestController(controllerBase, GetUnitTestToken(), body);
}
public static void SetupTestController(this ControllerBase controllerBase, GameTokenEntity token, string? body = null)
{
controllerBase.ControllerContext = GetMockControllerContext(body);
SetupTestGameToken(controllerBase, token);
}
public static ControllerContext GetMockControllerContext() =>
new()
{
HttpContext = new DefaultHttpContext(),
};
private static ControllerContext GetMockControllerContext(string? body) =>
new()
{
HttpContext = new DefaultHttpContext
{
Request =
{
ContentLength = body?.Length ?? 0,
Body = new MemoryStream(Encoding.ASCII.GetBytes(body ?? string.Empty)),
},
},
ActionDescriptor = new ControllerActionDescriptor
{
ActionName = "",
},
};
private static void SetupTestGameToken(ControllerBase controller, GameTokenEntity token)
{
controller.HttpContext.Items["Token"] = token;
}
}

View file

@ -1,145 +1,145 @@
using System;
using System.IO;
using System.Net.Http;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Xml.Serialization;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Tickets;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.EntityFrameworkCore;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Integration;
[Collection(nameof(LighthouseServerTest<TStartup>))]
public class LighthouseServerTest<TStartup> where TStartup : class
{
protected readonly HttpClient Client;
private readonly TestServer server;
protected LighthouseServerTest()
{
ServerConfiguration.Instance.DbConnectionString = "server=127.0.0.1;uid=root;pwd=lighthouse_tests;database=lighthouse_tests";
ServerConfiguration.Instance.DigestKey.PrimaryDigestKey = "lighthouse";
this.server = new TestServer(new WebHostBuilder().UseStartup<TStartup>());
this.Client = this.server.CreateClient();
}
public TestServer GetTestServer() => this.server;
protected async Task<UserEntity> CreateRandomUser()
{
await using DatabaseContext database = DatabaseContext.CreateNewInstance();
int userId = RandomNumberGenerator.GetInt32(int.MaxValue);
const string username = "unitTestUser";
// if user already exists, find another random number
while (await database.Users.AnyAsync(u => u.Username == $"{username}{userId}"))
{
userId = RandomNumberGenerator.GetInt32(int.MaxValue);
}
UserEntity user = new()
{
UserId = userId,
Username = $"{username}{userId}",
Password = CryptoHelper.BCryptHash($"unitTestPassword{userId}"),
LinkedPsnId = (ulong)userId,
};
database.Add(user);
await database.SaveChangesAsync();
return user;
}
protected async Task<HttpResponseMessage> AuthenticateResponse()
{
UserEntity user = await this.CreateRandomUser();
byte[] ticketData = new TicketBuilder()
.SetUsername($"{user.Username}{user.UserId}")
.SetUserId((ulong)user.UserId)
.Build();
HttpResponseMessage response = await this.Client.PostAsync
($"/LITTLEBIGPLANETPS3_XML/login?titleID={GameVersionHelper.LittleBigPlanet2TitleIds[0]}", new ByteArrayContent(ticketData));
return response;
}
protected async Task<LoginResult> Authenticate()
{
HttpResponseMessage response = await this.AuthenticateResponse();
string responseContent = await response.Content.ReadAsStringAsync();
XmlSerializer serializer = new(typeof(LoginResult));
return (LoginResult)serializer.Deserialize(new StringReader(responseContent))!;
}
protected Task<HttpResponseMessage> AuthenticatedRequest(string endpoint, string mmAuth) => this.AuthenticatedRequest(endpoint, mmAuth, HttpMethod.Get);
private static string GetDigestCookie(string mmAuth) => mmAuth["MM_AUTH=".Length..];
private Task<HttpResponseMessage> AuthenticatedRequest(string endpoint, string mmAuth, HttpMethod method)
{
if (!endpoint.StartsWith("/")) endpoint = $"/{endpoint}";
using HttpRequestMessage requestMessage = new(method, endpoint);
requestMessage.Headers.Add("Cookie", mmAuth);
string path = endpoint.Split("?", StringSplitOptions.RemoveEmptyEntries)[0];
string digest = CryptoHelper.ComputeDigest(path, GetDigestCookie(mmAuth), Array.Empty<byte>(), "lighthouse");
requestMessage.Headers.Add("X-Digest-A", digest);
return this.Client.SendAsync(requestMessage);
}
public async Task<HttpResponseMessage> UploadFileEndpointRequest(string filePath)
{
byte[] bytes = await File.ReadAllBytesAsync(filePath);
string hash = CryptoHelper.Sha1Hash(bytes).ToLower();
return await this.Client.PostAsync($"/LITTLEBIGPLANETPS3_XML/upload/{hash}", new ByteArrayContent(bytes));
}
protected async Task<HttpResponseMessage> AuthenticatedUploadFileEndpointRequest(string filePath, string mmAuth)
{
byte[] bytes = await File.ReadAllBytesAsync(filePath);
string hash = CryptoHelper.Sha1Hash(bytes).ToLower();
using HttpRequestMessage requestMessage = new(HttpMethod.Post, $"/LITTLEBIGPLANETPS3_XML/upload/{hash}");
requestMessage.Headers.Add("Cookie", mmAuth);
requestMessage.Content = new ByteArrayContent(bytes);
string digest = CryptoHelper.ComputeDigest($"/LITTLEBIGPLANETPS3_XML/upload/{hash}", GetDigestCookie(mmAuth), bytes, "lighthouse", true);
requestMessage.Headers.Add("X-Digest-B", digest);
return await this.Client.SendAsync(requestMessage);
}
public async Task<HttpResponseMessage> UploadFileRequest(string endpoint, string filePath)
=> await this.Client.PostAsync(endpoint, new StringContent(await File.ReadAllTextAsync(filePath)));
public async Task<HttpResponseMessage> UploadDataRequest(string endpoint, byte[] data) => await this.Client.PostAsync(endpoint, new ByteArrayContent(data));
public async Task<HttpResponseMessage> AuthenticatedUploadFileRequest(string endpoint, string filePath, string mmAuth)
{
using HttpRequestMessage requestMessage = new(HttpMethod.Post, endpoint);
requestMessage.Headers.Add("Cookie", mmAuth);
requestMessage.Content = new StringContent(await File.ReadAllTextAsync(filePath));
return await this.Client.SendAsync(requestMessage);
}
protected async Task<HttpResponseMessage> AuthenticatedUploadDataRequest(string endpoint, byte[] data, string mmAuth)
{
using HttpRequestMessage requestMessage = new(HttpMethod.Post, endpoint);
requestMessage.Headers.Add("Cookie", mmAuth);
requestMessage.Content = new ByteArrayContent(data);
string digest = CryptoHelper.ComputeDigest(endpoint, GetDigestCookie(mmAuth), data, "lighthouse");
requestMessage.Headers.Add("X-Digest-A", digest);
return await this.Client.SendAsync(requestMessage);
}
using System;
using System.IO;
using System.Net.Http;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Xml.Serialization;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Tickets;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.EntityFrameworkCore;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Integration;
[Collection(nameof(LighthouseServerTest<TStartup>))]
public class LighthouseServerTest<TStartup> where TStartup : class
{
protected readonly HttpClient Client;
private readonly TestServer server;
protected LighthouseServerTest()
{
ServerConfiguration.Instance.DbConnectionString = "server=127.0.0.1;uid=root;pwd=lighthouse_tests;database=lighthouse_tests";
ServerConfiguration.Instance.DigestKey.PrimaryDigestKey = "lighthouse";
this.server = new TestServer(new WebHostBuilder().UseStartup<TStartup>());
this.Client = this.server.CreateClient();
}
public TestServer GetTestServer() => this.server;
protected async Task<UserEntity> CreateRandomUser()
{
await using DatabaseContext database = DatabaseContext.CreateNewInstance();
int userId = RandomNumberGenerator.GetInt32(int.MaxValue);
const string username = "unitTestUser";
// if user already exists, find another random number
while (await database.Users.AnyAsync(u => u.Username == $"{username}{userId}"))
{
userId = RandomNumberGenerator.GetInt32(int.MaxValue);
}
UserEntity user = new()
{
UserId = userId,
Username = $"{username}{userId}",
Password = CryptoHelper.BCryptHash($"unitTestPassword{userId}"),
LinkedPsnId = (ulong)userId,
};
database.Add(user);
await database.SaveChangesAsync();
return user;
}
protected async Task<HttpResponseMessage> AuthenticateResponse()
{
UserEntity user = await this.CreateRandomUser();
byte[] ticketData = new TicketBuilder()
.SetUsername($"{user.Username}{user.UserId}")
.SetUserId((ulong)user.UserId)
.Build();
HttpResponseMessage response = await this.Client.PostAsync
($"/LITTLEBIGPLANETPS3_XML/login?titleID={GameVersionHelper.LittleBigPlanet2TitleIds[0]}", new ByteArrayContent(ticketData));
return response;
}
protected async Task<LoginResult> Authenticate()
{
HttpResponseMessage response = await this.AuthenticateResponse();
string responseContent = await response.Content.ReadAsStringAsync();
XmlSerializer serializer = new(typeof(LoginResult));
return (LoginResult)serializer.Deserialize(new StringReader(responseContent))!;
}
protected Task<HttpResponseMessage> AuthenticatedRequest(string endpoint, string mmAuth) => this.AuthenticatedRequest(endpoint, mmAuth, HttpMethod.Get);
private static string GetDigestCookie(string mmAuth) => mmAuth["MM_AUTH=".Length..];
private Task<HttpResponseMessage> AuthenticatedRequest(string endpoint, string mmAuth, HttpMethod method)
{
if (!endpoint.StartsWith("/")) endpoint = $"/{endpoint}";
using HttpRequestMessage requestMessage = new(method, endpoint);
requestMessage.Headers.Add("Cookie", mmAuth);
string path = endpoint.Split("?", StringSplitOptions.RemoveEmptyEntries)[0];
string digest = CryptoHelper.ComputeDigest(path, GetDigestCookie(mmAuth), Array.Empty<byte>(), "lighthouse");
requestMessage.Headers.Add("X-Digest-A", digest);
return this.Client.SendAsync(requestMessage);
}
public async Task<HttpResponseMessage> UploadFileEndpointRequest(string filePath)
{
byte[] bytes = await File.ReadAllBytesAsync(filePath);
string hash = CryptoHelper.Sha1Hash(bytes).ToLower();
return await this.Client.PostAsync($"/LITTLEBIGPLANETPS3_XML/upload/{hash}", new ByteArrayContent(bytes));
}
protected async Task<HttpResponseMessage> AuthenticatedUploadFileEndpointRequest(string filePath, string mmAuth)
{
byte[] bytes = await File.ReadAllBytesAsync(filePath);
string hash = CryptoHelper.Sha1Hash(bytes).ToLower();
using HttpRequestMessage requestMessage = new(HttpMethod.Post, $"/LITTLEBIGPLANETPS3_XML/upload/{hash}");
requestMessage.Headers.Add("Cookie", mmAuth);
requestMessage.Content = new ByteArrayContent(bytes);
string digest = CryptoHelper.ComputeDigest($"/LITTLEBIGPLANETPS3_XML/upload/{hash}", GetDigestCookie(mmAuth), bytes, "lighthouse", true);
requestMessage.Headers.Add("X-Digest-B", digest);
return await this.Client.SendAsync(requestMessage);
}
public async Task<HttpResponseMessage> UploadFileRequest(string endpoint, string filePath)
=> await this.Client.PostAsync(endpoint, new StringContent(await File.ReadAllTextAsync(filePath)));
public async Task<HttpResponseMessage> UploadDataRequest(string endpoint, byte[] data) => await this.Client.PostAsync(endpoint, new ByteArrayContent(data));
public async Task<HttpResponseMessage> AuthenticatedUploadFileRequest(string endpoint, string filePath, string mmAuth)
{
using HttpRequestMessage requestMessage = new(HttpMethod.Post, endpoint);
requestMessage.Headers.Add("Cookie", mmAuth);
requestMessage.Content = new StringContent(await File.ReadAllTextAsync(filePath));
return await this.Client.SendAsync(requestMessage);
}
protected async Task<HttpResponseMessage> AuthenticatedUploadDataRequest(string endpoint, byte[] data, string mmAuth)
{
using HttpRequestMessage requestMessage = new(HttpMethod.Post, endpoint);
requestMessage.Headers.Add("Cookie", mmAuth);
requestMessage.Content = new ByteArrayContent(data);
string digest = CryptoHelper.ComputeDigest(endpoint, GetDigestCookie(mmAuth), data, "lighthouse");
requestMessage.Headers.Add("X-Digest-A", digest);
return await this.Client.SendAsync(requestMessage);
}
}

View file

@ -1,160 +1,160 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Xml.Serialization;
using LBPUnion.ProjectLighthouse.Serialization;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Integration.Serialization;
[Trait("Category", "Integration")]
public class SerializationDependencyTests
{
private static IServiceProvider GetTestServiceProvider(params object[] dependencies)
{
ServiceCollection collection = new();
foreach (object o in dependencies)
{
ServiceDescriptor descriptor = new(o.GetType(), o);
collection.Add(descriptor);
}
return new DefaultServiceProviderFactory().CreateServiceProvider(collection);
}
public class TestDependency
{
public TestDependency(string secret)
{
this.Secret = secret;
}
public string Secret { get; }
}
public class DependencyTest : TestSerializable, INeedsPreparationForSerialization
{
[DefaultValue("")]
[XmlElement("secret")]
public string Secret { get; set; } = "";
public void PrepareSerialization(TestDependency testDependency)
{
this.Secret = testDependency.Secret;
}
}
[Fact]
public void ShouldInjectDependency()
{
DependencyTest serializable = new();
TestDependency testDependency = new("bruh");
string serialized = LighthouseSerializer.Serialize(GetTestServiceProvider(testDependency), serializable);
Assert.True(serialized == "<xmlRoot><secret>bruh</secret></xmlRoot>");
}
public class RecursiveDependencyTest : TestSerializable
{
[XmlElement("dependency")]
public DependencyTest Dependency { get; set; } = new();
}
[Fact]
public void ShouldInjectDependencyIntoNestedClass()
{
RecursiveDependencyTest serializable = new();
TestDependency testDependency = new("bruh");
string serialized = LighthouseSerializer.Serialize(GetTestServiceProvider(testDependency), serializable);
Assert.True(serialized == "<xmlRoot><dependency><secret>bruh</secret></dependency></xmlRoot>");
}
public class RecursiveDependencyTestWithPreparation : TestSerializable, INeedsPreparationForSerialization
{
[XmlElement("dependency")]
public DependencyTest Dependency { get; set; } = new();
[XmlElement("prepared")]
public string PreparedField { get; set; } = "";
public void PrepareSerialization()
{
this.PreparedField = "test";
}
}
public class DependencyOrderTest : TestSerializable, INeedsPreparationForSerialization
{
[XmlElement("dependency")]
public DependencyTest Dependency { get; set; } = null!;
[XmlElement("nestedDependency")]
public RecursiveDependencyTestWithPreparation RecursiveDependency { get; set; } = null!;
public void PrepareSerialization(TestDependency testDependency)
{
this.Dependency = new DependencyTest();
this.RecursiveDependency = new RecursiveDependencyTestWithPreparation();
}
}
[Fact]
public void ShouldDependenciesBePreparedInOrder()
{
DependencyOrderTest serializable = new();
TestDependency testDependency = new("bruh");
string serialized = LighthouseSerializer.Serialize(GetTestServiceProvider(testDependency), serializable);
Assert.True(serialized ==
"<xmlRoot>" +
"<dependency><secret>bruh</secret></dependency>" +
"<nestedDependency><dependency><secret>bruh</secret></dependency><prepared>test</prepared></nestedDependency>" +
"</xmlRoot>");
}
public class CounterDependency
{
private int counter;
public int Counter => this.counter++;
public CounterDependency()
{
this.counter = 0;
}
}
public class ListDependencyItem : ILbpSerializable, INeedsPreparationForSerialization
{
[XmlElement("counter")]
public int Counter { get; set; } = -1;
public void PrepareSerialization(CounterDependency counter)
{
this.Counter = counter.Counter;
}
}
public class ListDependencyTest : TestSerializable
{
[XmlElement("item")]
public List<ListDependencyItem> Items { get; set; } = new();
}
[Fact]
public void ShouldPrepareItemsInList()
{
ListDependencyTest serializable = new()
{
Items = new List<ListDependencyItem>
{
new(),
new(),
new(),
},
};
CounterDependency counterDependency = new();
string serialized = LighthouseSerializer.Serialize(GetTestServiceProvider(counterDependency), serializable);
Assert.True(serialized == "<xmlRoot><item><counter>0</counter></item><item><counter>1</counter></item><item><counter>2</counter></item></xmlRoot>");
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Xml.Serialization;
using LBPUnion.ProjectLighthouse.Serialization;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Integration.Serialization;
[Trait("Category", "Integration")]
public class SerializationDependencyTests
{
private static IServiceProvider GetTestServiceProvider(params object[] dependencies)
{
ServiceCollection collection = new();
foreach (object o in dependencies)
{
ServiceDescriptor descriptor = new(o.GetType(), o);
collection.Add(descriptor);
}
return new DefaultServiceProviderFactory().CreateServiceProvider(collection);
}
public class TestDependency
{
public TestDependency(string secret)
{
this.Secret = secret;
}
public string Secret { get; }
}
public class DependencyTest : TestSerializable, INeedsPreparationForSerialization
{
[DefaultValue("")]
[XmlElement("secret")]
public string Secret { get; set; } = "";
public void PrepareSerialization(TestDependency testDependency)
{
this.Secret = testDependency.Secret;
}
}
[Fact]
public void ShouldInjectDependency()
{
DependencyTest serializable = new();
TestDependency testDependency = new("bruh");
string serialized = LighthouseSerializer.Serialize(GetTestServiceProvider(testDependency), serializable);
Assert.True(serialized == "<xmlRoot><secret>bruh</secret></xmlRoot>");
}
public class RecursiveDependencyTest : TestSerializable
{
[XmlElement("dependency")]
public DependencyTest Dependency { get; set; } = new();
}
[Fact]
public void ShouldInjectDependencyIntoNestedClass()
{
RecursiveDependencyTest serializable = new();
TestDependency testDependency = new("bruh");
string serialized = LighthouseSerializer.Serialize(GetTestServiceProvider(testDependency), serializable);
Assert.True(serialized == "<xmlRoot><dependency><secret>bruh</secret></dependency></xmlRoot>");
}
public class RecursiveDependencyTestWithPreparation : TestSerializable, INeedsPreparationForSerialization
{
[XmlElement("dependency")]
public DependencyTest Dependency { get; set; } = new();
[XmlElement("prepared")]
public string PreparedField { get; set; } = "";
public void PrepareSerialization()
{
this.PreparedField = "test";
}
}
public class DependencyOrderTest : TestSerializable, INeedsPreparationForSerialization
{
[XmlElement("dependency")]
public DependencyTest Dependency { get; set; } = null!;
[XmlElement("nestedDependency")]
public RecursiveDependencyTestWithPreparation RecursiveDependency { get; set; } = null!;
public void PrepareSerialization(TestDependency testDependency)
{
this.Dependency = new DependencyTest();
this.RecursiveDependency = new RecursiveDependencyTestWithPreparation();
}
}
[Fact]
public void ShouldDependenciesBePreparedInOrder()
{
DependencyOrderTest serializable = new();
TestDependency testDependency = new("bruh");
string serialized = LighthouseSerializer.Serialize(GetTestServiceProvider(testDependency), serializable);
Assert.True(serialized ==
"<xmlRoot>" +
"<dependency><secret>bruh</secret></dependency>" +
"<nestedDependency><dependency><secret>bruh</secret></dependency><prepared>test</prepared></nestedDependency>" +
"</xmlRoot>");
}
public class CounterDependency
{
private int counter;
public int Counter => this.counter++;
public CounterDependency()
{
this.counter = 0;
}
}
public class ListDependencyItem : ILbpSerializable, INeedsPreparationForSerialization
{
[XmlElement("counter")]
public int Counter { get; set; } = -1;
public void PrepareSerialization(CounterDependency counter)
{
this.Counter = counter.Counter;
}
}
public class ListDependencyTest : TestSerializable
{
[XmlElement("item")]
public List<ListDependencyItem> Items { get; set; } = new();
}
[Fact]
public void ShouldPrepareItemsInList()
{
ListDependencyTest serializable = new()
{
Items = new List<ListDependencyItem>
{
new(),
new(),
new(),
},
};
CounterDependency counterDependency = new();
string serialized = LighthouseSerializer.Serialize(GetTestServiceProvider(counterDependency), serializable);
Assert.True(serialized == "<xmlRoot><item><counter>0</counter></item><item><counter>1</counter></item><item><counter>2</counter></item></xmlRoot>");
}
}

View file

@ -1,219 +1,219 @@
using System;
using System.ComponentModel;
using System.Xml.Serialization;
using LBPUnion.ProjectLighthouse.Serialization;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Integration.Serialization;
public class TestSerializable : ILbpSerializable, IHasCustomRoot
{
public virtual string GetRoot() => "xmlRoot";
}
[Trait("Category", "Integration")]
public class SerializationTests
{
private static IServiceProvider GetEmptyServiceProvider() => new DefaultServiceProviderFactory().CreateServiceProvider(new ServiceCollection());
[Fact]
public void ShouldNotSerializeNullObject()
{
TestSerializable? serializable = null;
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.True(serialized == "");
}
[Fact]
public void ShouldSerializeFullEmptyTag()
{
TestSerializable serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.True(serialized == "<xmlRoot></xmlRoot>");
}
[Fact]
public void ShouldSerializeWithCustomRoot()
{
TestSerializable serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.True(serialized == "<xmlRoot></xmlRoot>");
}
public class OverriddenRoot : TestSerializable
{
public override string GetRoot() => "xmlRoot2";
}
[Fact]
public void ShouldSerializeWithOverriddenRoot()
{
OverriddenRoot serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.True(serialized == "<xmlRoot2></xmlRoot2>");
}
[XmlRoot("xmlRoot3")]
public class RootAttribute : ILbpSerializable { }
[Fact]
public void ShouldSerializeWithRootAttribute()
{
RootAttribute serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.True(serialized == "<xmlRoot3></xmlRoot3>");
}
public class DefaultValueInt : TestSerializable
{
[DefaultValue(6)]
[XmlElement("defaultValueInt")]
public int DefaultValueTest { get; set; } = 6;
}
[Fact]
public void ShouldNotSerializeDefaultValueInt()
{
DefaultValueInt serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot></xmlRoot>");
}
public class NonDefaultValueInt : TestSerializable
{
[DefaultValue(6)]
[XmlElement("nonDefaultValueInt")]
public int NonDefaultValueTest { get; set; }
}
[Fact]
public void ShouldNotSerializeNonDefaultValueInt()
{
NonDefaultValueInt serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot><nonDefaultValueInt>0</nonDefaultValueInt></xmlRoot>");
}
public class DefaultNullableStringTest : TestSerializable
{
[DefaultValue(null)]
[XmlElement("defaultNullableString")]
public string? DefaultNullableString { get; set; }
}
[Fact]
public void ShouldNotSerializeDefaultNullableString()
{
DefaultNullableStringTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot></xmlRoot>");
}
public class NullNullableStringTest : TestSerializable
{
[XmlElement("nullableString")]
public string? NullableString { get; set; }
}
[Fact]
public void ShouldNotSerializeNullNullableString()
{
NullNullableStringTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot></xmlRoot>");
}
[Fact]
public void ShouldSerializeNonNullNullableString()
{
NullNullableStringTest serializable = new()
{
NullableString = "notNull",
};
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot><nullableString>notNull</nullableString></xmlRoot>");
}
public class NonEmptyStringTest : TestSerializable
{
[XmlElement("stringTest")]
public string StringTest { get; set; } = "test";
}
[Fact]
public void ShouldSerializeNonNullableString()
{
NonEmptyStringTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot><stringTest>test</stringTest></xmlRoot>");
}
[XmlRoot("xmlRoot", Namespace = "test")]
public class NameSpaceTest : TestSerializable
{
[XmlElement("test", Namespace = "test2")]
public int TestValue { get; set; } = 1;
}
[Fact]
public void ShouldExcludeNamespace()
{
NameSpaceTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot><test>1</test></xmlRoot>");
}
public class AttributeTest : TestSerializable
{
[XmlAttribute("string")]
public string StringAttribute { get; set; } = "test";
[XmlAttribute("int")]
public int NumberAttribute { get; set; } = 5;
}
[Fact]
public void ShouldSerializeAttributes()
{
AttributeTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot string=\"test\" int=\"5\"></xmlRoot>");
}
public class NestingTest : TestSerializable
{
[XmlElement("nested")]
public NestedType NestedType { get; set; } = new();
}
public class NestedType : ILbpSerializable
{
[XmlElement("attributeTest")]
public AttributeTest AttributeTest { get; set; } = new();
[XmlElement("nestedString")]
public NonEmptyStringTest NonEmptyString { get; set; } = new();
}
[Fact]
public void ShouldSerializeNestedType()
{
NestingTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized ==
"<xmlRoot><nested>" +
"<attributeTest string=\"test\" int=\"5\"></attributeTest>" +
"<nestedString><stringTest>test</stringTest></nestedString>" +
"</nested></xmlRoot>");
}
using System;
using System.ComponentModel;
using System.Xml.Serialization;
using LBPUnion.ProjectLighthouse.Serialization;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Integration.Serialization;
public class TestSerializable : ILbpSerializable, IHasCustomRoot
{
public virtual string GetRoot() => "xmlRoot";
}
[Trait("Category", "Integration")]
public class SerializationTests
{
private static IServiceProvider GetEmptyServiceProvider() => new DefaultServiceProviderFactory().CreateServiceProvider(new ServiceCollection());
[Fact]
public void ShouldNotSerializeNullObject()
{
TestSerializable? serializable = null;
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.True(serialized == "");
}
[Fact]
public void ShouldSerializeFullEmptyTag()
{
TestSerializable serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.True(serialized == "<xmlRoot></xmlRoot>");
}
[Fact]
public void ShouldSerializeWithCustomRoot()
{
TestSerializable serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.True(serialized == "<xmlRoot></xmlRoot>");
}
public class OverriddenRoot : TestSerializable
{
public override string GetRoot() => "xmlRoot2";
}
[Fact]
public void ShouldSerializeWithOverriddenRoot()
{
OverriddenRoot serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.True(serialized == "<xmlRoot2></xmlRoot2>");
}
[XmlRoot("xmlRoot3")]
public class RootAttribute : ILbpSerializable { }
[Fact]
public void ShouldSerializeWithRootAttribute()
{
RootAttribute serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.True(serialized == "<xmlRoot3></xmlRoot3>");
}
public class DefaultValueInt : TestSerializable
{
[DefaultValue(6)]
[XmlElement("defaultValueInt")]
public int DefaultValueTest { get; set; } = 6;
}
[Fact]
public void ShouldNotSerializeDefaultValueInt()
{
DefaultValueInt serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot></xmlRoot>");
}
public class NonDefaultValueInt : TestSerializable
{
[DefaultValue(6)]
[XmlElement("nonDefaultValueInt")]
public int NonDefaultValueTest { get; set; }
}
[Fact]
public void ShouldNotSerializeNonDefaultValueInt()
{
NonDefaultValueInt serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot><nonDefaultValueInt>0</nonDefaultValueInt></xmlRoot>");
}
public class DefaultNullableStringTest : TestSerializable
{
[DefaultValue(null)]
[XmlElement("defaultNullableString")]
public string? DefaultNullableString { get; set; }
}
[Fact]
public void ShouldNotSerializeDefaultNullableString()
{
DefaultNullableStringTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot></xmlRoot>");
}
public class NullNullableStringTest : TestSerializable
{
[XmlElement("nullableString")]
public string? NullableString { get; set; }
}
[Fact]
public void ShouldNotSerializeNullNullableString()
{
NullNullableStringTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot></xmlRoot>");
}
[Fact]
public void ShouldSerializeNonNullNullableString()
{
NullNullableStringTest serializable = new()
{
NullableString = "notNull",
};
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot><nullableString>notNull</nullableString></xmlRoot>");
}
public class NonEmptyStringTest : TestSerializable
{
[XmlElement("stringTest")]
public string StringTest { get; set; } = "test";
}
[Fact]
public void ShouldSerializeNonNullableString()
{
NonEmptyStringTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot><stringTest>test</stringTest></xmlRoot>");
}
[XmlRoot("xmlRoot", Namespace = "test")]
public class NameSpaceTest : TestSerializable
{
[XmlElement("test", Namespace = "test2")]
public int TestValue { get; set; } = 1;
}
[Fact]
public void ShouldExcludeNamespace()
{
NameSpaceTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot><test>1</test></xmlRoot>");
}
public class AttributeTest : TestSerializable
{
[XmlAttribute("string")]
public string StringAttribute { get; set; } = "test";
[XmlAttribute("int")]
public int NumberAttribute { get; set; } = 5;
}
[Fact]
public void ShouldSerializeAttributes()
{
AttributeTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot string=\"test\" int=\"5\"></xmlRoot>");
}
public class NestingTest : TestSerializable
{
[XmlElement("nested")]
public NestedType NestedType { get; set; } = new();
}
public class NestedType : ILbpSerializable
{
[XmlElement("attributeTest")]
public AttributeTest AttributeTest { get; set; } = new();
[XmlElement("nestedString")]
public NonEmptyStringTest NonEmptyString { get; set; } = new();
}
[Fact]
public void ShouldSerializeNestedType()
{
NestingTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized ==
"<xmlRoot><nested>" +
"<attributeTest string=\"test\" int=\"5\"></attributeTest>" +
"<nestedString><stringTest>test</stringTest></nestedString>" +
"</nested></xmlRoot>");
}
}

View file

@ -1,42 +1,42 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<TargetFramework>net8.0</TargetFramework>
<AssemblyName>LBPUnion.ProjectLighthouse.Tests</AssemblyName>
<RootNamespace>LBPUnion.ProjectLighthouse.Tests</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2024.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.18" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.18">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.6" />
</ItemGroup>
<ItemGroup>
<Content Include="ExampleFiles\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<ProjectReference Include="..\ProjectLighthouse\ProjectLighthouse.csproj" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<TargetFramework>net8.0</TargetFramework>
<AssemblyName>LBPUnion.ProjectLighthouse.Tests</AssemblyName>
<RootNamespace>LBPUnion.ProjectLighthouse.Tests</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2024.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.18" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.18">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.6" />
</ItemGroup>
<ItemGroup>
<Content Include="ExampleFiles\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<ProjectReference Include="..\ProjectLighthouse\ProjectLighthouse.csproj" />
</ItemGroup>
</Project>

View file

@ -1,2 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=tests/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View file

@ -1,97 +1,97 @@
using System.Collections.Concurrent;
using System.Reflection;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")]
public class EmailCooldownTests
{
private static ConcurrentDictionary<int, long>? GetInternalDict =>
typeof(SMTPHelper).GetField("recentlySentMail", BindingFlags.NonPublic | BindingFlags.Static)?.GetValue(null) as ConcurrentDictionary<int, long>;
/*
* TODO This way of testing sucks because it relies on internal implementation,
* but half of this codebase is static singletons so my hand has kinda been forced
*/
[Fact]
public void CanSendMail_WhenExpirationReached()
{
MethodInfo? canSendMethod = typeof(SMTPHelper).GetMethod("CanSendMail", BindingFlags.NonPublic | BindingFlags.Static);
Assert.NotNull(canSendMethod);
UserEntity userEntity = new()
{
UserId = 1,
};
Assert.NotNull(GetInternalDict);
GetInternalDict.Clear();
GetInternalDict.TryAdd(1, 0);
bool? canSend = (bool?)canSendMethod.Invoke(null, new object?[] { userEntity, });
const bool expectedValue = true;
Assert.NotNull(canSend);
Assert.Equal(expectedValue, canSend);
}
[Fact]
public void CanSendMail_WhenExpirationNotReached()
{
MethodInfo? canSendMethod =
typeof(SMTPHelper).GetMethod("CanSendMail", BindingFlags.NonPublic | BindingFlags.Static);
Assert.NotNull(canSendMethod);
UserEntity userEntity = new()
{
UserId = 1,
};
Assert.NotNull(GetInternalDict);
GetInternalDict.Clear();
GetInternalDict.TryAdd(1, long.MaxValue);
bool? canSend = (bool?)canSendMethod.Invoke(null, new object?[] { userEntity, });
const bool expectedValue = false;
Assert.NotNull(canSend);
Assert.Equal(expectedValue, canSend);
}
[Fact]
public void CanSendMail_ExpiredEntriesAreRemoved()
{
MethodInfo? canSendMethod = typeof(SMTPHelper).GetMethod("CanSendMail", BindingFlags.NonPublic | BindingFlags.Static);
Assert.NotNull(canSendMethod);
UserEntity userEntity = new()
{
UserId = 1,
};
Assert.NotNull(GetInternalDict);
GetInternalDict.Clear();
GetInternalDict.TryAdd(2, 0);
GetInternalDict.TryAdd(3, TimeHelper.TimestampMillis - 100);
GetInternalDict.TryAdd(4, long.MaxValue);
canSendMethod.Invoke(null, new object?[] { userEntity, });
Assert.False(GetInternalDict.TryGetValue(2, out _));
Assert.False(GetInternalDict.TryGetValue(3, out _));
Assert.True(GetInternalDict.TryGetValue(4, out _));
}
using System.Collections.Concurrent;
using System.Reflection;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")]
public class EmailCooldownTests
{
private static ConcurrentDictionary<int, long>? GetInternalDict =>
typeof(SMTPHelper).GetField("recentlySentMail", BindingFlags.NonPublic | BindingFlags.Static)?.GetValue(null) as ConcurrentDictionary<int, long>;
/*
* TODO This way of testing sucks because it relies on internal implementation,
* but half of this codebase is static singletons so my hand has kinda been forced
*/
[Fact]
public void CanSendMail_WhenExpirationReached()
{
MethodInfo? canSendMethod = typeof(SMTPHelper).GetMethod("CanSendMail", BindingFlags.NonPublic | BindingFlags.Static);
Assert.NotNull(canSendMethod);
UserEntity userEntity = new()
{
UserId = 1,
};
Assert.NotNull(GetInternalDict);
GetInternalDict.Clear();
GetInternalDict.TryAdd(1, 0);
bool? canSend = (bool?)canSendMethod.Invoke(null, new object?[] { userEntity, });
const bool expectedValue = true;
Assert.NotNull(canSend);
Assert.Equal(expectedValue, canSend);
}
[Fact]
public void CanSendMail_WhenExpirationNotReached()
{
MethodInfo? canSendMethod =
typeof(SMTPHelper).GetMethod("CanSendMail", BindingFlags.NonPublic | BindingFlags.Static);
Assert.NotNull(canSendMethod);
UserEntity userEntity = new()
{
UserId = 1,
};
Assert.NotNull(GetInternalDict);
GetInternalDict.Clear();
GetInternalDict.TryAdd(1, long.MaxValue);
bool? canSend = (bool?)canSendMethod.Invoke(null, new object?[] { userEntity, });
const bool expectedValue = false;
Assert.NotNull(canSend);
Assert.Equal(expectedValue, canSend);
}
[Fact]
public void CanSendMail_ExpiredEntriesAreRemoved()
{
MethodInfo? canSendMethod = typeof(SMTPHelper).GetMethod("CanSendMail", BindingFlags.NonPublic | BindingFlags.Static);
Assert.NotNull(canSendMethod);
UserEntity userEntity = new()
{
UserId = 1,
};
Assert.NotNull(GetInternalDict);
GetInternalDict.Clear();
GetInternalDict.TryAdd(2, 0);
GetInternalDict.TryAdd(3, TimeHelper.TimestampMillis - 100);
GetInternalDict.TryAdd(4, long.MaxValue);
canSendMethod.Invoke(null, new object?[] { userEntity, });
Assert.False(GetInternalDict.TryGetValue(2, out _));
Assert.False(GetInternalDict.TryGetValue(3, out _));
Assert.True(GetInternalDict.TryGetValue(4, out _));
}
}

View file

@ -1,60 +1,60 @@
using System;
using System.IO;
using LBPUnion.ProjectLighthouse.Types.Resources;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")]
public class FileTypeTests
{
[Fact]
public void ShouldRecognizeLevel()
{
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestLevel.lvl"));
Assert.True(file.FileType == LbpFileType.Level);
}
[Fact]
public void ShouldRecognizeScript()
{
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestScript.ff"));
Assert.True(file.FileType == LbpFileType.Script);
}
[Fact]
public void ShouldRecognizeTexture()
{
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestTexture.tex"));
Assert.True(file.FileType == LbpFileType.Texture);
}
[Fact]
public void ShouldRecognizeFileArchive()
{
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestFarc.farc"));
Assert.True(file.FileType == LbpFileType.FileArchive);
}
[Fact]
public void ShouldNotRecognizeFileArchiveAsScript()
{
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestFarc.farc"));
Assert.False(file.FileType == LbpFileType.Script);
Assert.True(file.FileType == LbpFileType.FileArchive);
}
[Fact]
public void ShouldRecognizeNothingAsUnknown()
{
LbpFile file = new(Array.Empty<byte>());
Assert.True(file.FileType == LbpFileType.Unknown);
}
[Fact]
public void ShouldRecognizeGarbageAsUnknown()
{
LbpFile file = new("free pc only $900"u8.ToArray());
Assert.True(file.FileType == LbpFileType.Unknown);
}
using System;
using System.IO;
using LBPUnion.ProjectLighthouse.Types.Resources;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")]
public class FileTypeTests
{
[Fact]
public void ShouldRecognizeLevel()
{
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestLevel.lvl"));
Assert.True(file.FileType == LbpFileType.Level);
}
[Fact]
public void ShouldRecognizeScript()
{
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestScript.ff"));
Assert.True(file.FileType == LbpFileType.Script);
}
[Fact]
public void ShouldRecognizeTexture()
{
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestTexture.tex"));
Assert.True(file.FileType == LbpFileType.Texture);
}
[Fact]
public void ShouldRecognizeFileArchive()
{
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestFarc.farc"));
Assert.True(file.FileType == LbpFileType.FileArchive);
}
[Fact]
public void ShouldNotRecognizeFileArchiveAsScript()
{
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestFarc.farc"));
Assert.False(file.FileType == LbpFileType.Script);
Assert.True(file.FileType == LbpFileType.FileArchive);
}
[Fact]
public void ShouldRecognizeNothingAsUnknown()
{
LbpFile file = new(Array.Empty<byte>());
Assert.True(file.FileType == LbpFileType.Unknown);
}
[Fact]
public void ShouldRecognizeGarbageAsUnknown()
{
LbpFile file = new("free pc only $900"u8.ToArray());
Assert.True(file.FileType == LbpFileType.Unknown);
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,85 +1,85 @@
using System.IO;
using System.Xml.Serialization;
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Misc;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")]
public class LocationTests
{
[Fact]
public void ShouldSetAndReadUserLocation()
{
Location expected = new()
{
X = 1000,
Y = 5000,
};
UserEntity user = new()
{
Location = new Location
{
X = expected.X,
Y = expected.Y,
},
};
Assert.True(user.Location.X == expected.X);
Assert.True(user.Location.Y == expected.Y);
Assert.True(user.LocationPacked == 4_294_967_301_000);
}
[Fact]
public void ShouldSetAndReadSlotLocation()
{
Location expected = new()
{
X = 1000,
Y = 5000,
};
SlotEntity slot = new()
{
Location = new Location
{
X = expected.X,
Y = expected.Y,
},
};
Assert.True(slot.Location.X == expected.X);
Assert.True(slot.Location.Y == expected.Y);
Assert.True(slot.LocationPacked == 4_294_967_301_000);
}
[Fact]
public void ShouldReadLocationAfterDeserialization()
{
XmlSerializer deserializer = new(typeof(GameUserSlot));
const string slotData = "<slot><name>test</name><resource>test</resource><location><x>4000</x><y>9000</y></location></slot>";
GameUserSlot? deserialized = (GameUserSlot?)deserializer.Deserialize(new StringReader(slotData));
Assert.True(deserialized != null);
Assert.True(deserialized.Name == "test");
Assert.True(deserialized.Location.X == 4000);
Assert.True(deserialized.Location.Y == 9000);
SlotEntity entity = SlotBase.ConvertToEntity(deserialized);
Assert.True(entity.LocationPacked == 17_179_869_193_000);
}
[Fact]
public void ShouldDeserializeEmptyLocation()
{
XmlSerializer deserializer = new(typeof(GameUserSlot));
const string slotData = "<slot><name>test</name></slot>";
GameUserSlot? deserialized = (GameUserSlot?)deserializer.Deserialize(new StringReader(slotData));
Assert.True(deserialized != null);
Assert.True(deserialized.Name == "test");
Assert.True(deserialized.Location.X == 0);
Assert.True(deserialized.Location.Y == 0);
SlotEntity entity = SlotBase.ConvertToEntity(deserialized);
Assert.True(entity.LocationPacked == 0);
}
using System.IO;
using System.Xml.Serialization;
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Misc;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")]
public class LocationTests
{
[Fact]
public void ShouldSetAndReadUserLocation()
{
Location expected = new()
{
X = 1000,
Y = 5000,
};
UserEntity user = new()
{
Location = new Location
{
X = expected.X,
Y = expected.Y,
},
};
Assert.True(user.Location.X == expected.X);
Assert.True(user.Location.Y == expected.Y);
Assert.True(user.LocationPacked == 4_294_967_301_000);
}
[Fact]
public void ShouldSetAndReadSlotLocation()
{
Location expected = new()
{
X = 1000,
Y = 5000,
};
SlotEntity slot = new()
{
Location = new Location
{
X = expected.X,
Y = expected.Y,
},
};
Assert.True(slot.Location.X == expected.X);
Assert.True(slot.Location.Y == expected.Y);
Assert.True(slot.LocationPacked == 4_294_967_301_000);
}
[Fact]
public void ShouldReadLocationAfterDeserialization()
{
XmlSerializer deserializer = new(typeof(GameUserSlot));
const string slotData = "<slot><name>test</name><resource>test</resource><location><x>4000</x><y>9000</y></location></slot>";
GameUserSlot? deserialized = (GameUserSlot?)deserializer.Deserialize(new StringReader(slotData));
Assert.True(deserialized != null);
Assert.True(deserialized.Name == "test");
Assert.True(deserialized.Location.X == 4000);
Assert.True(deserialized.Location.Y == 9000);
SlotEntity entity = SlotBase.ConvertToEntity(deserialized);
Assert.True(entity.LocationPacked == 17_179_869_193_000);
}
[Fact]
public void ShouldDeserializeEmptyLocation()
{
XmlSerializer deserializer = new(typeof(GameUserSlot));
const string slotData = "<slot><name>test</name></slot>";
GameUserSlot? deserialized = (GameUserSlot?)deserializer.Deserialize(new StringReader(slotData));
Assert.True(deserialized != null);
Assert.True(deserialized.Name == "test");
Assert.True(deserialized.Location.X == 0);
Assert.True(deserialized.Location.Y == 0);
SlotEntity entity = SlotBase.ConvertToEntity(deserialized);
Assert.True(entity.LocationPacked == 0);
}
}

View file

@ -1,86 +1,86 @@
using System;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Administration.Maintenance.RepeatingTasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Moderation;
using Microsoft.EntityFrameworkCore;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")]
public class ModerationTests
{
[Fact]
public async Task DismissExpiredCases_ShouldDismissExpiredCase()
{
await using DatabaseContext database = await MockHelper.GetTestDatabase();
ModerationCaseEntity @case = new()
{
CaseId = 1,
CreatorId = 1,
ExpiresAt = DateTime.UnixEpoch,
CreatorUsername = "unitTestUser",
};
database.Cases.Add(@case);
await database.SaveChangesAsync();
DismissExpiredCasesTask task = new();
await task.Run(database);
Assert.NotNull(await database.Cases.FirstOrDefaultAsync(c => c.CaseId == 1 && c.DismissedAt != null));
}
[Fact]
public async Task DismissExpiredCases_ShouldNotDismissActiveCase()
{
await using DatabaseContext database = await MockHelper.GetTestDatabase();
ModerationCaseEntity @case = new()
{
CaseId = 2,
CreatorId = 1,
ExpiresAt = DateTime.UtcNow.AddHours(1),
CreatorUsername = "unitTestUser",
};
database.Cases.Add(@case);
await database.SaveChangesAsync();
DismissExpiredCasesTask task = new();
await task.Run(database);
Assert.NotNull(await database.Cases.FirstOrDefaultAsync(c => c.CaseId == 2 && c.DismissedAt == null));
}
[Fact]
public async Task DismissExpiredCases_ShouldNotDismissAlreadyDismissedCase()
{
await using DatabaseContext database = await MockHelper.GetTestDatabase();
ModerationCaseEntity @case = new()
{
CaseId = 3,
CreatorId = 1,
ExpiresAt = DateTime.UnixEpoch,
DismissedAt = DateTime.UnixEpoch,
CreatorUsername = "unitTestUser",
};
database.Cases.Add(@case);
await database.SaveChangesAsync();
DismissExpiredCasesTask task = new();
await task.Run(database);
// check that the case was not dismissed again by comparing original time to new time
Assert.NotNull(
await database.Cases.FirstOrDefaultAsync(c => c.CaseId == 3 && c.DismissedAt == DateTime.UnixEpoch));
}
using System;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Administration.Maintenance.RepeatingTasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Moderation;
using Microsoft.EntityFrameworkCore;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")]
public class ModerationTests
{
[Fact]
public async Task DismissExpiredCases_ShouldDismissExpiredCase()
{
await using DatabaseContext database = await MockHelper.GetTestDatabase();
ModerationCaseEntity @case = new()
{
CaseId = 1,
CreatorId = 1,
ExpiresAt = DateTime.UnixEpoch,
CreatorUsername = "unitTestUser",
};
database.Cases.Add(@case);
await database.SaveChangesAsync();
DismissExpiredCasesTask task = new();
await task.Run(database);
Assert.NotNull(await database.Cases.FirstOrDefaultAsync(c => c.CaseId == 1 && c.DismissedAt != null));
}
[Fact]
public async Task DismissExpiredCases_ShouldNotDismissActiveCase()
{
await using DatabaseContext database = await MockHelper.GetTestDatabase();
ModerationCaseEntity @case = new()
{
CaseId = 2,
CreatorId = 1,
ExpiresAt = DateTime.UtcNow.AddHours(1),
CreatorUsername = "unitTestUser",
};
database.Cases.Add(@case);
await database.SaveChangesAsync();
DismissExpiredCasesTask task = new();
await task.Run(database);
Assert.NotNull(await database.Cases.FirstOrDefaultAsync(c => c.CaseId == 2 && c.DismissedAt == null));
}
[Fact]
public async Task DismissExpiredCases_ShouldNotDismissAlreadyDismissedCase()
{
await using DatabaseContext database = await MockHelper.GetTestDatabase();
ModerationCaseEntity @case = new()
{
CaseId = 3,
CreatorId = 1,
ExpiresAt = DateTime.UnixEpoch,
DismissedAt = DateTime.UnixEpoch,
CreatorUsername = "unitTestUser",
};
database.Cases.Add(@case);
await database.SaveChangesAsync();
DismissExpiredCasesTask task = new();
await task.Run(database);
// check that the case was not dismissed again by comparing original time to new time
Assert.NotNull(
await database.Cases.FirstOrDefaultAsync(c => c.CaseId == 3 && c.DismissedAt == DateTime.UnixEpoch));
}
}

View file

@ -1,238 +1,238 @@
using System.Collections.Generic;
using System.Linq;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Types.Filter;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")]
public class PaginationTests
{
[Fact]
public void GetPaginationData_IsReadFromQuery()
{
DefaultHttpContext defaultHttpContext = new()
{
Request =
{
Query = new QueryCollection(new Dictionary<string, StringValues>
{
{
"pageStart", new StringValues("10")
},
{
"pageSize", new StringValues("15")
},
}),
},
};
PaginationData pageData = defaultHttpContext.Request.GetPaginationData();
const int expectedPageStart = 10;
const int expectedPageSize = 15;
Assert.Equal(expectedPageStart, pageData.PageStart);
Assert.Equal(expectedPageSize, pageData.PageSize);
}
[Fact]
public void GetPaginationData_IsPageStartSetToDefault_WhenMissing()
{
DefaultHttpContext defaultHttpContext = new()
{
Request =
{
Query = new QueryCollection(new Dictionary<string, StringValues>
{
{
"pageSize", new StringValues("15")
},
}),
},
};
PaginationData pageData = defaultHttpContext.Request.GetPaginationData();
const int expectedPageStart = 0;
const int expectedPageSize = 15;
Assert.Equal(expectedPageStart, pageData.PageStart);
Assert.Equal(expectedPageSize, pageData.PageSize);
}
[Fact]
public void GetPaginationData_IsPageSizeSetToDefault_WhenMissing()
{
ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots = 50;
DefaultHttpContext defaultHttpContext = new()
{
Request =
{
Query = new QueryCollection(new Dictionary<string, StringValues>
{
{
"pageStart", new StringValues("10")
},
}),
},
};
PaginationData pageData = defaultHttpContext.Request.GetPaginationData();
const int expectedPageStart = 10;
const int expectedPageSize = 50;
Assert.Equal(expectedPageStart, pageData.PageStart);
Assert.Equal(expectedPageSize, pageData.PageSize);
}
[Fact]
public void GetPaginationData_NegativeValuesAreSetToZero()
{
ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots = 50;
DefaultHttpContext defaultHttpContext = new()
{
Request =
{
Query = new QueryCollection(new Dictionary<string, StringValues>
{
{
"pageStart", new StringValues("-10")
},
{
"pageSize", new StringValues("-10")
},
}),
},
};
PaginationData pageData = defaultHttpContext.Request.GetPaginationData();
const int expectedPageStart = 0;
const int expectedPageSize = 10;
Assert.Equal(expectedPageStart, pageData.PageStart);
Assert.Equal(expectedPageSize, pageData.PageSize);
}
[Fact]
public void ApplyPagination_ShouldApplyCorrectPagination()
{
List<GameUser> users = new();
for (int i = 0; i < 30; i++)
{
users.Add(new GameUser
{
UserId = i+1,
});
}
PaginationData pageData = new()
{
PageSize = 5,
PageStart = 6,
};
List<GameUser> pagedUsers = users.AsQueryable().ApplyPagination(pageData).ToList();
Assert.Equal(pageData.PageSize, pagedUsers.Count);
Assert.Equal(6, pagedUsers[0].UserId);
Assert.Equal(10, pagedUsers[4].UserId);
}
[Fact]
public void ApplyPagination_ShouldClampPageStart_WhenNegative()
{
List<GameUser> users = new();
for (int i = 0; i < 30; i++)
{
users.Add(new GameUser
{
UserId = i + 1,
});
}
PaginationData pageData = new()
{
PageSize = 5,
PageStart = -5,
};
List<GameUser> pagedUsers = users.AsQueryable().ApplyPagination(pageData).ToList();
Assert.Equal(pageData.PageSize, pagedUsers.Count);
Assert.Equal(1, pagedUsers[0].UserId);
Assert.Equal(5, pagedUsers[4].UserId);
}
[Fact]
public void ApplyPagination_ShouldReturnEmpty_WhenPageSizeNegative()
{
List<GameUser> users = new();
for (int i = 0; i < 30; i++)
{
users.Add(new GameUser
{
UserId = i + 1,
});
}
PaginationData pageData = new()
{
PageSize = -5,
PageStart = 0,
};
List<GameUser> pagedUsers = users.AsQueryable().ApplyPagination(pageData).ToList();
Assert.Empty(pagedUsers);
}
[Fact]
public void ApplyPagination_ShouldClampPageSize_WhenSizeExceedsMaxElements()
{
List<GameUser> users = new();
for (int i = 0; i < 30; i++)
{
users.Add(new GameUser
{
UserId = i + 1,
});
}
PaginationData pageData = new()
{
PageSize = 10,
PageStart = 0,
MaxElements = 1,
};
List<GameUser> pagedUsers = users.AsQueryable().ApplyPagination(pageData).ToList();
Assert.Single(pagedUsers);
}
[Fact]
public void ApplyPagination_ShouldClampPageSize_WhenSizeExceedsInternalLimit()
{
List<GameUser> users = new();
for (int i = 0; i < 1001; i++)
{
users.Add(new GameUser
{
UserId = i + 1,
});
}
PaginationData pageData = new()
{
PageSize = int.MaxValue,
PageStart = 0,
MaxElements = int.MaxValue,
};
List<GameUser> pagedUsers = users.AsQueryable().ApplyPagination(pageData).ToList();
Assert.Equal(1000, pagedUsers.Count);
}
using System.Collections.Generic;
using System.Linq;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Types.Filter;
using LBPUnion.ProjectLighthouse.Types.Serialization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")]
public class PaginationTests
{
[Fact]
public void GetPaginationData_IsReadFromQuery()
{
DefaultHttpContext defaultHttpContext = new()
{
Request =
{
Query = new QueryCollection(new Dictionary<string, StringValues>
{
{
"pageStart", new StringValues("10")
},
{
"pageSize", new StringValues("15")
},
}),
},
};
PaginationData pageData = defaultHttpContext.Request.GetPaginationData();
const int expectedPageStart = 10;
const int expectedPageSize = 15;
Assert.Equal(expectedPageStart, pageData.PageStart);
Assert.Equal(expectedPageSize, pageData.PageSize);
}
[Fact]
public void GetPaginationData_IsPageStartSetToDefault_WhenMissing()
{
DefaultHttpContext defaultHttpContext = new()
{
Request =
{
Query = new QueryCollection(new Dictionary<string, StringValues>
{
{
"pageSize", new StringValues("15")
},
}),
},
};
PaginationData pageData = defaultHttpContext.Request.GetPaginationData();
const int expectedPageStart = 0;
const int expectedPageSize = 15;
Assert.Equal(expectedPageStart, pageData.PageStart);
Assert.Equal(expectedPageSize, pageData.PageSize);
}
[Fact]
public void GetPaginationData_IsPageSizeSetToDefault_WhenMissing()
{
ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots = 50;
DefaultHttpContext defaultHttpContext = new()
{
Request =
{
Query = new QueryCollection(new Dictionary<string, StringValues>
{
{
"pageStart", new StringValues("10")
},
}),
},
};
PaginationData pageData = defaultHttpContext.Request.GetPaginationData();
const int expectedPageStart = 10;
const int expectedPageSize = 50;
Assert.Equal(expectedPageStart, pageData.PageStart);
Assert.Equal(expectedPageSize, pageData.PageSize);
}
[Fact]
public void GetPaginationData_NegativeValuesAreSetToZero()
{
ServerConfiguration.Instance.UserGeneratedContentLimits.EntitledSlots = 50;
DefaultHttpContext defaultHttpContext = new()
{
Request =
{
Query = new QueryCollection(new Dictionary<string, StringValues>
{
{
"pageStart", new StringValues("-10")
},
{
"pageSize", new StringValues("-10")
},
}),
},
};
PaginationData pageData = defaultHttpContext.Request.GetPaginationData();
const int expectedPageStart = 0;
const int expectedPageSize = 10;
Assert.Equal(expectedPageStart, pageData.PageStart);
Assert.Equal(expectedPageSize, pageData.PageSize);
}
[Fact]
public void ApplyPagination_ShouldApplyCorrectPagination()
{
List<GameUser> users = new();
for (int i = 0; i < 30; i++)
{
users.Add(new GameUser
{
UserId = i+1,
});
}
PaginationData pageData = new()
{
PageSize = 5,
PageStart = 6,
};
List<GameUser> pagedUsers = users.AsQueryable().ApplyPagination(pageData).ToList();
Assert.Equal(pageData.PageSize, pagedUsers.Count);
Assert.Equal(6, pagedUsers[0].UserId);
Assert.Equal(10, pagedUsers[4].UserId);
}
[Fact]
public void ApplyPagination_ShouldClampPageStart_WhenNegative()
{
List<GameUser> users = new();
for (int i = 0; i < 30; i++)
{
users.Add(new GameUser
{
UserId = i + 1,
});
}
PaginationData pageData = new()
{
PageSize = 5,
PageStart = -5,
};
List<GameUser> pagedUsers = users.AsQueryable().ApplyPagination(pageData).ToList();
Assert.Equal(pageData.PageSize, pagedUsers.Count);
Assert.Equal(1, pagedUsers[0].UserId);
Assert.Equal(5, pagedUsers[4].UserId);
}
[Fact]
public void ApplyPagination_ShouldReturnEmpty_WhenPageSizeNegative()
{
List<GameUser> users = new();
for (int i = 0; i < 30; i++)
{
users.Add(new GameUser
{
UserId = i + 1,
});
}
PaginationData pageData = new()
{
PageSize = -5,
PageStart = 0,
};
List<GameUser> pagedUsers = users.AsQueryable().ApplyPagination(pageData).ToList();
Assert.Empty(pagedUsers);
}
[Fact]
public void ApplyPagination_ShouldClampPageSize_WhenSizeExceedsMaxElements()
{
List<GameUser> users = new();
for (int i = 0; i < 30; i++)
{
users.Add(new GameUser
{
UserId = i + 1,
});
}
PaginationData pageData = new()
{
PageSize = 10,
PageStart = 0,
MaxElements = 1,
};
List<GameUser> pagedUsers = users.AsQueryable().ApplyPagination(pageData).ToList();
Assert.Single(pagedUsers);
}
[Fact]
public void ApplyPagination_ShouldClampPageSize_WhenSizeExceedsInternalLimit()
{
List<GameUser> users = new();
for (int i = 0; i < 1001; i++)
{
users.Add(new GameUser
{
UserId = i + 1,
});
}
PaginationData pageData = new()
{
PageSize = int.MaxValue,
PageStart = 0,
MaxElements = int.MaxValue,
};
List<GameUser> pagedUsers = users.AsQueryable().ApplyPagination(pageData).ToList();
Assert.Equal(1000, pagedUsers.Count);
}
}

View file

@ -1,120 +1,120 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Services;
using LBPUnion.ProjectLighthouse.Types.Maintenance;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")]
public class RepeatingTaskTests
{
private class TestTask : IRepeatingTask
{
public string Name { get; init; } = "";
public TimeSpan RepeatInterval => TimeSpan.FromSeconds(5);
public DateTime LastRan { get; set; }
public Task Run(DatabaseContext database) => Task.CompletedTask;
}
[Fact]
public void GetNextTask_ShouldReturnNull_WhenTaskListEmpty()
{
List<IRepeatingTask> tasks = new();
IServiceProvider provider = new DefaultServiceProviderFactory().CreateServiceProvider(new ServiceCollection());
RepeatingTaskService service = new(provider, tasks);
bool gotTask = service.TryGetNextTask(out IRepeatingTask? outTask);
Assert.False(gotTask);
Assert.Null(outTask);
}
[Fact]
public void GetNextTask_ShouldReturnTask_WhenTaskListContainsOne()
{
List<IRepeatingTask> tasks = new()
{
new TestTask(),
};
IServiceProvider provider = new DefaultServiceProviderFactory().CreateServiceProvider(new ServiceCollection());
RepeatingTaskService service = new(provider, tasks);
bool gotTask = service.TryGetNextTask(out IRepeatingTask? outTask);
Assert.True(gotTask);
Assert.NotNull(outTask);
}
[Fact]
public void GetNextTask_ShouldReturnShortestTask_WhenTaskListContainsMultiple()
{
List<IRepeatingTask> tasks = new()
{
new TestTask
{
Name = "Task 1",
LastRan = DateTime.UtcNow,
},
new TestTask
{
Name = "Task 2",
LastRan = DateTime.UtcNow.AddMinutes(1),
},
new TestTask
{
Name = "Task 3",
LastRan = DateTime.UtcNow.AddMinutes(-1),
},
};
IServiceProvider provider = new DefaultServiceProviderFactory().CreateServiceProvider(new ServiceCollection());
RepeatingTaskService service = new(provider, tasks);
bool gotTask = service.TryGetNextTask(out IRepeatingTask? outTask);
Assert.True(gotTask);
Assert.NotNull(outTask);
Assert.Equal("Task 3", outTask.Name);
}
[Fact]
public async Task BackgroundService_ShouldExecuteTask_AndUpdateTime()
{
Mock<IRepeatingTask> taskMock = new();
taskMock.Setup(t => t.Run(It.IsAny<DatabaseContext>())).Returns(Task.CompletedTask);
taskMock.SetupGet(t => t.RepeatInterval).Returns(TimeSpan.FromSeconds(10));
TaskCompletionSource taskCompletion = new();
DateTime lastRan = default;
taskMock.SetupSet(t => t.LastRan = It.IsAny<DateTime>())
.Callback<DateTime>(time =>
{
lastRan = time;
taskCompletion.TrySetResult();
});
taskMock.SetupGet(t => t.LastRan).Returns(() => lastRan);
List<IRepeatingTask> tasks = new()
{
taskMock.Object,
};
ServiceCollection serviceCollection = new();
serviceCollection.AddScoped(_ => new Mock<DatabaseContext>().Object);
IServiceProvider provider = new DefaultServiceProviderFactory().CreateServiceProvider(serviceCollection);
RepeatingTaskService service = new(provider, tasks);
CancellationTokenSource stoppingToken = new();
await service.StartAsync(stoppingToken.Token);
await taskCompletion.Task;
stoppingToken.Cancel();
Assert.NotNull(service.ExecuteTask);
await service.ExecuteTask;
taskMock.Verify(x => x.Run(It.IsAny<DatabaseContext>()), Times.Once);
taskMock.VerifySet(x => x.LastRan = It.IsAny<DateTime>(), Times.Once());
}
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Services;
using LBPUnion.ProjectLighthouse.Types.Maintenance;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")]
public class RepeatingTaskTests
{
private class TestTask : IRepeatingTask
{
public string Name { get; init; } = "";
public TimeSpan RepeatInterval => TimeSpan.FromSeconds(5);
public DateTime LastRan { get; set; }
public Task Run(DatabaseContext database) => Task.CompletedTask;
}
[Fact]
public void GetNextTask_ShouldReturnNull_WhenTaskListEmpty()
{
List<IRepeatingTask> tasks = new();
IServiceProvider provider = new DefaultServiceProviderFactory().CreateServiceProvider(new ServiceCollection());
RepeatingTaskService service = new(provider, tasks);
bool gotTask = service.TryGetNextTask(out IRepeatingTask? outTask);
Assert.False(gotTask);
Assert.Null(outTask);
}
[Fact]
public void GetNextTask_ShouldReturnTask_WhenTaskListContainsOne()
{
List<IRepeatingTask> tasks = new()
{
new TestTask(),
};
IServiceProvider provider = new DefaultServiceProviderFactory().CreateServiceProvider(new ServiceCollection());
RepeatingTaskService service = new(provider, tasks);
bool gotTask = service.TryGetNextTask(out IRepeatingTask? outTask);
Assert.True(gotTask);
Assert.NotNull(outTask);
}
[Fact]
public void GetNextTask_ShouldReturnShortestTask_WhenTaskListContainsMultiple()
{
List<IRepeatingTask> tasks = new()
{
new TestTask
{
Name = "Task 1",
LastRan = DateTime.UtcNow,
},
new TestTask
{
Name = "Task 2",
LastRan = DateTime.UtcNow.AddMinutes(1),
},
new TestTask
{
Name = "Task 3",
LastRan = DateTime.UtcNow.AddMinutes(-1),
},
};
IServiceProvider provider = new DefaultServiceProviderFactory().CreateServiceProvider(new ServiceCollection());
RepeatingTaskService service = new(provider, tasks);
bool gotTask = service.TryGetNextTask(out IRepeatingTask? outTask);
Assert.True(gotTask);
Assert.NotNull(outTask);
Assert.Equal("Task 3", outTask.Name);
}
[Fact]
public async Task BackgroundService_ShouldExecuteTask_AndUpdateTime()
{
Mock<IRepeatingTask> taskMock = new();
taskMock.Setup(t => t.Run(It.IsAny<DatabaseContext>())).Returns(Task.CompletedTask);
taskMock.SetupGet(t => t.RepeatInterval).Returns(TimeSpan.FromSeconds(10));
TaskCompletionSource taskCompletion = new();
DateTime lastRan = default;
taskMock.SetupSet(t => t.LastRan = It.IsAny<DateTime>())
.Callback<DateTime>(time =>
{
lastRan = time;
taskCompletion.TrySetResult();
});
taskMock.SetupGet(t => t.LastRan).Returns(() => lastRan);
List<IRepeatingTask> tasks = new()
{
taskMock.Object,
};
ServiceCollection serviceCollection = new();
serviceCollection.AddScoped(_ => new Mock<DatabaseContext>().Object);
IServiceProvider provider = new DefaultServiceProviderFactory().CreateServiceProvider(serviceCollection);
RepeatingTaskService service = new(provider, tasks);
CancellationTokenSource stoppingToken = new();
await service.StartAsync(stoppingToken.Token);
await taskCompletion.Task;
stoppingToken.Cancel();
Assert.NotNull(service.ExecuteTask);
await service.ExecuteTask;
taskMock.Verify(x => x.Run(It.IsAny<DatabaseContext>()), Times.Once);
taskMock.VerifySet(x => x.LastRan = It.IsAny<DateTime>(), Times.Once());
}
}

View file

@ -1,100 +1,100 @@
using System;
using System.IO;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Files;
using LBPUnion.ProjectLighthouse.Types.Resources;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")]
public class ResourceTests
{
[Fact]
public void IsResourceValid_ReturnsTrue_ForValidResource()
{
string[] resources = {
"g123456", "g123", "98f54143ab4e86b28c3afee0f50f2f51cfb2ed38", "0ebe53fc820a544798000188d39bfda94f53fe37"
};
Assert.Multiple(() =>
{
foreach (string resource in resources)
{
Assert.True(FileHelper.IsResourceValid(resource));
}
});
}
[Fact]
public void IsResourceValid_ReturnsFalse_ForInvalidResource()
{
string[] resources =
{
"G0234", "g123456789012334567", "b28c3afee0f50f2f51cfb2ed38", "../Test",
};
Assert.Multiple(() =>
{
foreach (string resource in resources)
{
Assert.False(FileHelper.IsResourceValid(resource));
}
});
}
[Fact]
public void ShouldNotDeleteResourceFolder()
{
FileHelper.EnsureDirectoryCreated(FileHelper.ResourcePath);
Assert.True(Directory.Exists(FileHelper.ResourcePath));
FileHelper.DeleteResource(FileHelper.ResourcePath);
Assert.True(Directory.Exists(FileHelper.ResourcePath));
}
[Fact]
public void ShouldNotDeleteImagesFolder()
{
FileHelper.EnsureDirectoryCreated(FileHelper.ImagePath);
Assert.True(Directory.Exists(FileHelper.ImagePath));
FileHelper.DeleteResource(FileHelper.ImagePath);
Assert.True(Directory.Exists(FileHelper.ImagePath));
}
[Fact]
public void ShouldNotRecursivelyTraverseImage()
{
string path = Path.Combine(FileHelper.ImagePath, $"..{Path.DirectorySeparatorChar}appsettings.json");
FileHelper.DeleteResource(path);
Assert.True(File.Exists(Path.Combine(FileHelper.ImagePath, $"..{Path.DirectorySeparatorChar}appsettings.json")));
}
[Fact]
public void ShouldNotRecursivelyTraverseResource()
{
string path = Path.Combine(FileHelper.ResourcePath, $"..{Path.DirectorySeparatorChar}appsettings.json");
FileHelper.DeleteResource(path);
Assert.True(File.Exists(Path.Combine(FileHelper.ResourcePath, $"..{Path.DirectorySeparatorChar}appsettings.json")));
}
[Fact]
public async Task ShouldDeleteResourceAndImage()
{
FileHelper.EnsureDirectoryCreated(FileHelper.ResourcePath);
FileHelper.EnsureDirectoryCreated(FileHelper.ImagePath);
string? hash = await FileHelper.ParseBase64Image("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8r8NQDwAFCQGsNA7jBAAAAABJRU5ErkJggg==");
LbpFile? file = LbpFile.FromHash("ed4e2857a2e315e4487ea976d1b398f57b863ff4");
Assert.True(file != null);
// Convert resource to png
FileHelper.LbpFileToPNG(file);
Assert.True(hash != null);
Assert.True(hash.Equals("ed4e2857a2e315e4487ea976d1b398f57b863ff4", StringComparison.InvariantCultureIgnoreCase));
Assert.True(File.Exists(Path.Combine(FileHelper.ResourcePath, hash)));
Assert.True(File.Exists(Path.Combine(FileHelper.ImagePath, $"{hash}.png")));
FileHelper.DeleteResource(hash);
Assert.False(File.Exists(Path.Combine(FileHelper.ResourcePath, hash)));
Assert.False(File.Exists(Path.Combine(FileHelper.ImagePath, $"{hash}.png")));
}
using System;
using System.IO;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Files;
using LBPUnion.ProjectLighthouse.Types.Resources;
using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")]
public class ResourceTests
{
[Fact]
public void IsResourceValid_ReturnsTrue_ForValidResource()
{
string[] resources = {
"g123456", "g123", "98f54143ab4e86b28c3afee0f50f2f51cfb2ed38", "0ebe53fc820a544798000188d39bfda94f53fe37"
};
Assert.Multiple(() =>
{
foreach (string resource in resources)
{
Assert.True(FileHelper.IsResourceValid(resource));
}
});
}
[Fact]
public void IsResourceValid_ReturnsFalse_ForInvalidResource()
{
string[] resources =
{
"G0234", "g123456789012334567", "b28c3afee0f50f2f51cfb2ed38", "../Test",
};
Assert.Multiple(() =>
{
foreach (string resource in resources)
{
Assert.False(FileHelper.IsResourceValid(resource));
}
});
}
[Fact]
public void ShouldNotDeleteResourceFolder()
{
FileHelper.EnsureDirectoryCreated(FileHelper.ResourcePath);
Assert.True(Directory.Exists(FileHelper.ResourcePath));
FileHelper.DeleteResource(FileHelper.ResourcePath);
Assert.True(Directory.Exists(FileHelper.ResourcePath));
}
[Fact]
public void ShouldNotDeleteImagesFolder()
{
FileHelper.EnsureDirectoryCreated(FileHelper.ImagePath);
Assert.True(Directory.Exists(FileHelper.ImagePath));
FileHelper.DeleteResource(FileHelper.ImagePath);
Assert.True(Directory.Exists(FileHelper.ImagePath));
}
[Fact]
public void ShouldNotRecursivelyTraverseImage()
{
string path = Path.Combine(FileHelper.ImagePath, $"..{Path.DirectorySeparatorChar}appsettings.json");
FileHelper.DeleteResource(path);
Assert.True(File.Exists(Path.Combine(FileHelper.ImagePath, $"..{Path.DirectorySeparatorChar}appsettings.json")));
}
[Fact]
public void ShouldNotRecursivelyTraverseResource()
{
string path = Path.Combine(FileHelper.ResourcePath, $"..{Path.DirectorySeparatorChar}appsettings.json");
FileHelper.DeleteResource(path);
Assert.True(File.Exists(Path.Combine(FileHelper.ResourcePath, $"..{Path.DirectorySeparatorChar}appsettings.json")));
}
[Fact]
public async Task ShouldDeleteResourceAndImage()
{
FileHelper.EnsureDirectoryCreated(FileHelper.ResourcePath);
FileHelper.EnsureDirectoryCreated(FileHelper.ImagePath);
string? hash = await FileHelper.ParseBase64Image("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8r8NQDwAFCQGsNA7jBAAAAABJRU5ErkJggg==");
LbpFile? file = LbpFile.FromHash("ed4e2857a2e315e4487ea976d1b398f57b863ff4");
Assert.True(file != null);
// Convert resource to png
FileHelper.LbpFileToPNG(file);
Assert.True(hash != null);
Assert.True(hash.Equals("ed4e2857a2e315e4487ea976d1b398f57b863ff4", StringComparison.InvariantCultureIgnoreCase));
Assert.True(File.Exists(Path.Combine(FileHelper.ResourcePath, hash)));
Assert.True(File.Exists(Path.Combine(FileHelper.ImagePath, $"{hash}.png")));
FileHelper.DeleteResource(hash);
Assert.False(File.Exists(Path.Combine(FileHelper.ResourcePath, hash)));
Assert.False(File.Exists(Path.Combine(FileHelper.ImagePath, $"{hash}.png")));
}
}

View file

@ -0,0 +1,22 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("LBPUnion.ProjectLighthouse.Tests")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+509240db396eac0c69bd7ed8e09b71f630a8de72")]
[assembly: System.Reflection.AssemblyProductAttribute("LBPUnion.ProjectLighthouse.Tests")]
[assembly: System.Reflection.AssemblyTitleAttribute("LBPUnion.ProjectLighthouse.Tests")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// Generated by the MSBuild WriteCodeFragment class.

View file

@ -0,0 +1 @@
6b89ea06ddc2a1c8a938ca178c0f85915603434fc871268ec6f76c4cd69a13e7

View file

@ -0,0 +1,15 @@
is_global = true
build_property.TargetFramework = net8.0
build_property.TargetPlatformMinVersion =
build_property.UsingMicrosoftNETSdkWeb =
build_property.ProjectTypeGuids =
build_property.InvariantGlobalization =
build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules =
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = LBPUnion.ProjectLighthouse.Tests
build_property.ProjectDir = G:\LBP 3 ONLINE ARCHIVE\LBP 3 ONLINE SITE RECREACTION\ProjectLighthouse\ProjectLighthouse.Tests\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.EffectiveAnalysisLevelStyle = 8.0
build_property.EnableCodeStyleSeverity =

View file

@ -0,0 +1,352 @@
{
"format": 1,
"restore": {
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\ProjectLighthouse.Tests.csproj": {}
},
"projects": {
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj",
"projectName": "ProjectLighthouse.Localization",
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj",
"packagesPath": "C:\\Users\\Faisa\\.nuget\\packages\\",
"outputPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\obj\\",
"projectStyle": "PackageReference",
"configFilePaths": [
"C:\\Users\\Faisa\\AppData\\Roaming\\NuGet\\NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.300"
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"downloadDependencies": [
{
"name": "Microsoft.AspNetCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.NETCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.WindowsDesktop.App.Ref",
"version": "[8.0.19, 8.0.19]"
}
],
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.304/PortableRuntimeIdentifierGraph.json"
}
}
},
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\ProjectLighthouse.Tests.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\ProjectLighthouse.Tests.csproj",
"projectName": "LBPUnion.ProjectLighthouse.Tests",
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\ProjectLighthouse.Tests.csproj",
"packagesPath": "C:\\Users\\Faisa\\.nuget\\packages\\",
"outputPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\obj\\",
"projectStyle": "PackageReference",
"configFilePaths": [
"C:\\Users\\Faisa\\AppData\\Roaming\\NuGet\\NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj": {
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj"
}
}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.300"
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"dependencies": {
"JetBrains.Annotations": {
"target": "Package",
"version": "[2024.3.0, )"
},
"Microsoft.AspNetCore.Mvc.Testing": {
"target": "Package",
"version": "[8.0.18, )"
},
"Microsoft.EntityFrameworkCore.Design": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[8.0.18, )"
},
"Microsoft.EntityFrameworkCore.Sqlite": {
"target": "Package",
"version": "[8.0.6, )"
},
"Microsoft.NET.Test.Sdk": {
"target": "Package",
"version": "[17.14.1, )"
},
"Moq": {
"target": "Package",
"version": "[4.20.72, )"
},
"coverlet.collector": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[6.0.4, )"
},
"xunit": {
"target": "Package",
"version": "[2.9.3, )"
},
"xunit.runner.visualstudio": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[3.1.1, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"downloadDependencies": [
{
"name": "Microsoft.AspNetCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.NETCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.WindowsDesktop.App.Ref",
"version": "[8.0.19, 8.0.19]"
}
],
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.304/PortableRuntimeIdentifierGraph.json"
}
}
},
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj",
"projectName": "LBPUnion.ProjectLighthouse",
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\ProjectLighthouse.csproj",
"packagesPath": "C:\\Users\\Faisa\\.nuget\\packages\\",
"outputPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse\\obj\\",
"projectStyle": "PackageReference",
"configFilePaths": [
"C:\\Users\\Faisa\\AppData\\Roaming\\NuGet\\NuGet.Config"
],
"originalTargetFrameworks": [
"net8.0"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"projectReferences": {
"G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj": {
"projectPath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Localization\\ProjectLighthouse.Localization.csproj"
}
}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "9.0.300"
},
"frameworks": {
"net8.0": {
"targetAlias": "net8.0",
"dependencies": {
"BCrypt.Net-Next": {
"target": "Package",
"version": "[4.0.3, )"
},
"BouncyCastle.Cryptography": {
"target": "Package",
"version": "[2.6.1, )"
},
"Discord.Net.Webhook": {
"target": "Package",
"version": "[3.17.4, )"
},
"DistributedLock.MySql": {
"target": "Package",
"version": "[1.0.2, )"
},
"GitInfo": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[3.5.0, )"
},
"JetBrains.Annotations": {
"target": "Package",
"version": "[2024.3.0, )"
},
"Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore": {
"target": "Package",
"version": "[8.0.18, )"
},
"Microsoft.EntityFrameworkCore": {
"target": "Package",
"version": "[8.0.18, )"
},
"Microsoft.EntityFrameworkCore.Design": {
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
"suppressParent": "All",
"target": "Package",
"version": "[8.0.18, )"
},
"Pfim": {
"target": "Package",
"version": "[0.11.3, )"
},
"Pomelo.EntityFrameworkCore.MySql": {
"target": "Package",
"version": "[8.0.2, )"
},
"Redis.OM": {
"target": "Package",
"version": "[1.0.1, )"
},
"SharpZipLib": {
"target": "Package",
"version": "[1.4.2, )"
},
"SixLabors.ImageSharp": {
"target": "Package",
"version": "[3.1.10, )"
},
"Swashbuckle.AspNetCore": {
"target": "Package",
"version": "[9.0.3, )"
},
"YamlDotNet": {
"target": "Package",
"version": "[16.3.0, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"downloadDependencies": [
{
"name": "Microsoft.AspNetCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.NETCore.App.Ref",
"version": "[8.0.19, 8.0.19]"
},
{
"name": "Microsoft.WindowsDesktop.App.Ref",
"version": "[8.0.19, 8.0.19]"
}
],
"frameworkReferences": {
"Microsoft.AspNetCore.App": {
"privateAssets": "none"
},
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.304/PortableRuntimeIdentifierGraph.json"
}
}
}
}
}

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\Faisa\.nuget\packages\</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.14.0</NuGetToolVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="C:\Users\Faisa\.nuget\packages\" />
</ItemGroup>
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)xunit.runner.visualstudio\3.1.1\build\net8.0\xunit.runner.visualstudio.props" Condition="Exists('$(NuGetPackageRoot)xunit.runner.visualstudio\3.1.1\build\net8.0\xunit.runner.visualstudio.props')" />
<Import Project="$(NuGetPackageRoot)xunit.core\2.9.3\build\xunit.core.props" Condition="Exists('$(NuGetPackageRoot)xunit.core\2.9.3\build\xunit.core.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore\8.0.18\buildTransitive\net8.0\Microsoft.EntityFrameworkCore.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore\8.0.18\buildTransitive\net8.0\Microsoft.EntityFrameworkCore.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.testplatform.testhost\17.14.1\build\net8.0\Microsoft.TestPlatform.TestHost.props" Condition="Exists('$(NuGetPackageRoot)microsoft.testplatform.testhost\17.14.1\build\net8.0\Microsoft.TestPlatform.TestHost.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.codecoverage\17.14.1\build\netstandard2.0\Microsoft.CodeCoverage.props" Condition="Exists('$(NuGetPackageRoot)microsoft.codecoverage\17.14.1\build\netstandard2.0\Microsoft.CodeCoverage.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.test.sdk\17.14.1\build\net8.0\Microsoft.NET.Test.Sdk.props" Condition="Exists('$(NuGetPackageRoot)microsoft.net.test.sdk\17.14.1\build\net8.0\Microsoft.NET.Test.Sdk.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\8.0.1\buildTransitive\net6.0\Microsoft.Extensions.Configuration.UserSecrets.props" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\8.0.1\buildTransitive\net6.0\Microsoft.Extensions.Configuration.UserSecrets.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore.design\8.0.18\build\net8.0\Microsoft.EntityFrameworkCore.Design.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore.design\8.0.18\build\net8.0\Microsoft.EntityFrameworkCore.Design.props')" />
</ImportGroup>
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Pkgxunit_analyzers Condition=" '$(Pkgxunit_analyzers)' == '' ">C:\Users\Faisa\.nuget\packages\xunit.analyzers\1.18.0</Pkgxunit_analyzers>
<PkgMicrosoft_Extensions_ApiDescription_Server Condition=" '$(PkgMicrosoft_Extensions_ApiDescription_Server)' == '' ">C:\Users\Faisa\.nuget\packages\microsoft.extensions.apidescription.server\8.0.0</PkgMicrosoft_Extensions_ApiDescription_Server>
<PkgMicrosoft_CodeAnalysis_Analyzers Condition=" '$(PkgMicrosoft_CodeAnalysis_Analyzers)' == '' ">C:\Users\Faisa\.nuget\packages\microsoft.codeanalysis.analyzers\3.3.3</PkgMicrosoft_CodeAnalysis_Analyzers>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)xunit.core\2.9.3\build\xunit.core.targets" Condition="Exists('$(NuGetPackageRoot)xunit.core\2.9.3\build\xunit.core.targets')" />
<Import Project="$(NuGetPackageRoot)system.text.json\8.0.5\buildTransitive\net6.0\System.Text.Json.targets" Condition="Exists('$(NuGetPackageRoot)system.text.json\8.0.5\buildTransitive\net6.0\System.Text.Json.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\8.0.2\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\8.0.2\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
<Import Project="$(NuGetPackageRoot)sqlitepclraw.lib.e_sqlite3\2.1.6\buildTransitive\net8.0\SQLitePCLRaw.lib.e_sqlite3.targets" Condition="Exists('$(NuGetPackageRoot)sqlitepclraw.lib.e_sqlite3\2.1.6\buildTransitive\net8.0\SQLitePCLRaw.lib.e_sqlite3.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.options\8.0.2\buildTransitive\net6.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\8.0.2\buildTransitive\net6.0\Microsoft.Extensions.Options.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.testplatform.testhost\17.14.1\build\net8.0\Microsoft.TestPlatform.TestHost.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.testplatform.testhost\17.14.1\build\net8.0\Microsoft.TestPlatform.TestHost.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.codecoverage\17.14.1\build\netstandard2.0\Microsoft.CodeCoverage.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.codecoverage\17.14.1\build\netstandard2.0\Microsoft.CodeCoverage.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.test.sdk\17.14.1\build\net8.0\Microsoft.NET.Test.Sdk.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.net.test.sdk\17.14.1\build\net8.0\Microsoft.NET.Test.Sdk.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.binder\8.0.2\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.binder\8.0.2\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\8.0.1\buildTransitive\net6.0\Microsoft.Extensions.Configuration.UserSecrets.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\8.0.1\buildTransitive\net6.0\Microsoft.Extensions.Configuration.UserSecrets.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.aspnetcore.mvc.testing\8.0.18\buildTransitive\net8.0\Microsoft.AspNetCore.Mvc.Testing.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.aspnetcore.mvc.testing\8.0.18\buildTransitive\net8.0\Microsoft.AspNetCore.Mvc.Testing.targets')" />
<Import Project="$(NuGetPackageRoot)coverlet.collector\6.0.4\build\netstandard2.0\coverlet.collector.targets" Condition="Exists('$(NuGetPackageRoot)coverlet.collector\6.0.4\build\netstandard2.0\coverlet.collector.targets')" />
</ImportGroup>
</Project>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,124 @@
{
"version": 2,
"dgSpecHash": "PUGSl1dxGbw=",
"success": true,
"projectFilePath": "G:\\LBP 3 ONLINE ARCHIVE\\LBP 3 ONLINE SITE RECREACTION\\ProjectLighthouse\\ProjectLighthouse.Tests\\ProjectLighthouse.Tests.csproj",
"expectedPackageFiles": [
"C:\\Users\\Faisa\\.nuget\\packages\\bcrypt.net-next\\4.0.3\\bcrypt.net-next.4.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\bouncycastle.cryptography\\2.6.1\\bouncycastle.cryptography.2.6.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\castle.core\\5.1.1\\castle.core.5.1.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\coverlet.collector\\6.0.4\\coverlet.collector.6.0.4.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\discord.net.core\\3.17.4\\discord.net.core.3.17.4.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\discord.net.rest\\3.17.4\\discord.net.rest.3.17.4.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\discord.net.webhook\\3.17.4\\discord.net.webhook.3.17.4.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\distributedlock.core\\1.0.6\\distributedlock.core.1.0.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\distributedlock.mysql\\1.0.2\\distributedlock.mysql.1.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\humanizer.core\\2.14.1\\humanizer.core.2.14.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\jetbrains.annotations\\2024.3.0\\jetbrains.annotations.2024.3.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.aspnetcore.diagnostics.entityframeworkcore\\8.0.18\\microsoft.aspnetcore.diagnostics.entityframeworkcore.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.aspnetcore.mvc.testing\\8.0.18\\microsoft.aspnetcore.mvc.testing.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.aspnetcore.testhost\\8.0.18\\microsoft.aspnetcore.testhost.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.bcl.asyncinterfaces\\8.0.0\\microsoft.bcl.asyncinterfaces.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codeanalysis.analyzers\\3.3.3\\microsoft.codeanalysis.analyzers.3.3.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codeanalysis.common\\4.5.0\\microsoft.codeanalysis.common.4.5.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codeanalysis.csharp\\4.5.0\\microsoft.codeanalysis.csharp.4.5.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codeanalysis.csharp.workspaces\\4.5.0\\microsoft.codeanalysis.csharp.workspaces.4.5.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codeanalysis.workspaces.common\\4.5.0\\microsoft.codeanalysis.workspaces.common.4.5.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.codecoverage\\17.14.1\\microsoft.codecoverage.17.14.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.data.sqlite.core\\8.0.6\\microsoft.data.sqlite.core.8.0.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore\\8.0.18\\microsoft.entityframeworkcore.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.abstractions\\8.0.18\\microsoft.entityframeworkcore.abstractions.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.analyzers\\8.0.18\\microsoft.entityframeworkcore.analyzers.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.design\\8.0.18\\microsoft.entityframeworkcore.design.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.relational\\8.0.18\\microsoft.entityframeworkcore.relational.8.0.18.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.sqlite\\8.0.6\\microsoft.entityframeworkcore.sqlite.8.0.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.entityframeworkcore.sqlite.core\\8.0.6\\microsoft.entityframeworkcore.sqlite.core.8.0.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.apidescription.server\\8.0.0\\microsoft.extensions.apidescription.server.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.caching.abstractions\\8.0.0\\microsoft.extensions.caching.abstractions.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.caching.memory\\8.0.1\\microsoft.extensions.caching.memory.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration\\8.0.0\\microsoft.extensions.configuration.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.abstractions\\8.0.0\\microsoft.extensions.configuration.abstractions.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.binder\\8.0.2\\microsoft.extensions.configuration.binder.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.commandline\\8.0.0\\microsoft.extensions.configuration.commandline.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.environmentvariables\\8.0.0\\microsoft.extensions.configuration.environmentvariables.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.fileextensions\\8.0.1\\microsoft.extensions.configuration.fileextensions.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.json\\8.0.1\\microsoft.extensions.configuration.json.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.configuration.usersecrets\\8.0.1\\microsoft.extensions.configuration.usersecrets.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.dependencyinjection\\8.0.1\\microsoft.extensions.dependencyinjection.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.dependencyinjection.abstractions\\8.0.2\\microsoft.extensions.dependencyinjection.abstractions.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.dependencymodel\\8.0.2\\microsoft.extensions.dependencymodel.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.diagnostics\\8.0.1\\microsoft.extensions.diagnostics.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.diagnostics.abstractions\\8.0.1\\microsoft.extensions.diagnostics.abstractions.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.fileproviders.abstractions\\8.0.0\\microsoft.extensions.fileproviders.abstractions.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.fileproviders.physical\\8.0.0\\microsoft.extensions.fileproviders.physical.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.filesystemglobbing\\8.0.0\\microsoft.extensions.filesystemglobbing.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.hosting\\8.0.1\\microsoft.extensions.hosting.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.hosting.abstractions\\8.0.1\\microsoft.extensions.hosting.abstractions.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging\\8.0.1\\microsoft.extensions.logging.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.abstractions\\8.0.2\\microsoft.extensions.logging.abstractions.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.configuration\\8.0.1\\microsoft.extensions.logging.configuration.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.console\\8.0.1\\microsoft.extensions.logging.console.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.debug\\8.0.1\\microsoft.extensions.logging.debug.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.eventlog\\8.0.1\\microsoft.extensions.logging.eventlog.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.logging.eventsource\\8.0.1\\microsoft.extensions.logging.eventsource.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.options\\8.0.2\\microsoft.extensions.options.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.options.configurationextensions\\8.0.0\\microsoft.extensions.options.configurationextensions.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.extensions.primitives\\8.0.0\\microsoft.extensions.primitives.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.net.test.sdk\\17.14.1\\microsoft.net.test.sdk.17.14.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.openapi\\1.6.23\\microsoft.openapi.1.6.23.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.testplatform.objectmodel\\17.14.1\\microsoft.testplatform.objectmodel.17.14.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.testplatform.testhost\\17.14.1\\microsoft.testplatform.testhost.17.14.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\mono.texttemplating\\2.2.1\\mono.texttemplating.2.2.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\moq\\4.20.72\\moq.4.20.72.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\mysqlconnector\\2.3.5\\mysqlconnector.2.3.5.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\newtonsoft.json\\13.0.3\\newtonsoft.json.13.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\pfim\\0.11.3\\pfim.0.11.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\pipelines.sockets.unofficial\\2.2.8\\pipelines.sockets.unofficial.2.2.8.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\pomelo.entityframeworkcore.mysql\\8.0.2\\pomelo.entityframeworkcore.mysql.8.0.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\redis.om\\1.0.1\\redis.om.1.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sharpziplib\\1.4.2\\sharpziplib.1.4.2.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sixlabors.imagesharp\\3.1.10\\sixlabors.imagesharp.3.1.10.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sqlitepclraw.bundle_e_sqlite3\\2.1.6\\sqlitepclraw.bundle_e_sqlite3.2.1.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sqlitepclraw.core\\2.1.6\\sqlitepclraw.core.2.1.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sqlitepclraw.lib.e_sqlite3\\2.1.6\\sqlitepclraw.lib.e_sqlite3.2.1.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\sqlitepclraw.provider.e_sqlite3\\2.1.6\\sqlitepclraw.provider.e_sqlite3.2.1.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\stackexchange.redis\\2.7.17\\stackexchange.redis.2.7.17.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\swashbuckle.aspnetcore\\9.0.3\\swashbuckle.aspnetcore.9.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\swashbuckle.aspnetcore.swagger\\9.0.3\\swashbuckle.aspnetcore.swagger.9.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\swashbuckle.aspnetcore.swaggergen\\9.0.3\\swashbuckle.aspnetcore.swaggergen.9.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\swashbuckle.aspnetcore.swaggerui\\9.0.3\\swashbuckle.aspnetcore.swaggerui.9.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.codedom\\4.4.0\\system.codedom.4.4.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.collections.immutable\\8.0.0\\system.collections.immutable.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition\\6.0.0\\system.composition.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition.attributedmodel\\6.0.0\\system.composition.attributedmodel.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition.convention\\6.0.0\\system.composition.convention.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition.hosting\\6.0.0\\system.composition.hosting.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition.runtime\\6.0.0\\system.composition.runtime.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.composition.typedparts\\6.0.0\\system.composition.typedparts.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.diagnostics.eventlog\\8.0.1\\system.diagnostics.eventlog.8.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.interactive.async\\6.0.1\\system.interactive.async.6.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.io.pipelines\\8.0.0\\system.io.pipelines.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.linq.async\\6.0.1\\system.linq.async.6.0.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.memory\\4.5.3\\system.memory.4.5.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.reflection.metadata\\8.0.0\\system.reflection.metadata.8.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.runtime.compilerservices.unsafe\\6.0.0\\system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.text.encoding.codepages\\6.0.0\\system.text.encoding.codepages.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.text.json\\8.0.5\\system.text.json.8.0.5.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.threading.channels\\6.0.0\\system.threading.channels.6.0.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\system.valuetuple\\4.5.0\\system.valuetuple.4.5.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\ulid\\1.2.6\\ulid.1.2.6.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit\\2.9.3\\xunit.2.9.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.abstractions\\2.0.3\\xunit.abstractions.2.0.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.analyzers\\1.18.0\\xunit.analyzers.1.18.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.assert\\2.9.3\\xunit.assert.2.9.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.core\\2.9.3\\xunit.core.2.9.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.extensibility.core\\2.9.3\\xunit.extensibility.core.2.9.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.extensibility.execution\\2.9.3\\xunit.extensibility.execution.2.9.3.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\xunit.runner.visualstudio\\3.1.1\\xunit.runner.visualstudio.3.1.1.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\yamldotnet\\16.3.0\\yamldotnet.16.3.0.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.netcore.app.ref\\8.0.19\\microsoft.netcore.app.ref.8.0.19.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.windowsdesktop.app.ref\\8.0.19\\microsoft.windowsdesktop.app.ref.8.0.19.nupkg.sha512",
"C:\\Users\\Faisa\\.nuget\\packages\\microsoft.aspnetcore.app.ref\\8.0.19\\microsoft.aspnetcore.app.ref.8.0.19.nupkg.sha512"
],
"logs": []
}

View file

@ -1,72 +1,72 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse", "ProjectLighthouse\ProjectLighthouse.csproj", "{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Tests", "ProjectLighthouse.Tests\ProjectLighthouse.Tests.csproj", "{AFC74569-B289-4ACC-B21C-313A3A62C017}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D360C08E-EA47-43AC-A566-FDF413442980}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Tests.GameApiTests", "ProjectLighthouse.Tests.GameApiTests\ProjectLighthouse.Tests.GameApiTests.csproj", "{200EED99-FE3E-45C6-A51E-76ED9819CA2B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Tests.WebsiteTests", "ProjectLighthouse.Tests.WebsiteTests\ProjectLighthouse.Tests.WebsiteTests.csproj", "{CF65EB5B-5364-4D2A-8639-F147A67F08E7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Servers.API", "ProjectLighthouse.Servers.API\ProjectLighthouse.Servers.API.csproj", "{5593825E-F5C9-467F-9125-3E3249CFEEAB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Servers.GameServer", "ProjectLighthouse.Servers.GameServer\ProjectLighthouse.Servers.GameServer.csproj", "{0CD7F64B-7827-4AC9-B7D8-CE371D505544}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Servers.Website", "ProjectLighthouse.Servers.Website\ProjectLighthouse.Servers.Website.csproj", "{FA9AEA06-D6B5-4E68-8370-DB9188108635}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Servers", "Servers", "{1DE7A758-1F4F-4BA5-BE1C-74F9D0AB9EA3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source Code", "Source Code", "{7805B410-9260-4907-A7C6-D739369B2F25}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Localization", "ProjectLighthouse.Localization\ProjectLighthouse.Localization.csproj", "{18B76DAC-5DCB-44EA-B74D-0B4554BB161C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}.Release|Any CPU.Build.0 = Release|Any CPU
{AFC74569-B289-4ACC-B21C-313A3A62C017}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AFC74569-B289-4ACC-B21C-313A3A62C017}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AFC74569-B289-4ACC-B21C-313A3A62C017}.Release|Any CPU.ActiveCfg = Release|Any CPU
{200EED99-FE3E-45C6-A51E-76ED9819CA2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{200EED99-FE3E-45C6-A51E-76ED9819CA2B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{200EED99-FE3E-45C6-A51E-76ED9819CA2B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CF65EB5B-5364-4D2A-8639-F147A67F08E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CF65EB5B-5364-4D2A-8639-F147A67F08E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CF65EB5B-5364-4D2A-8639-F147A67F08E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5593825E-F5C9-467F-9125-3E3249CFEEAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5593825E-F5C9-467F-9125-3E3249CFEEAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5593825E-F5C9-467F-9125-3E3249CFEEAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5593825E-F5C9-467F-9125-3E3249CFEEAB}.Release|Any CPU.Build.0 = Release|Any CPU
{0CD7F64B-7827-4AC9-B7D8-CE371D505544}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0CD7F64B-7827-4AC9-B7D8-CE371D505544}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0CD7F64B-7827-4AC9-B7D8-CE371D505544}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0CD7F64B-7827-4AC9-B7D8-CE371D505544}.Release|Any CPU.Build.0 = Release|Any CPU
{FA9AEA06-D6B5-4E68-8370-DB9188108635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FA9AEA06-D6B5-4E68-8370-DB9188108635}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FA9AEA06-D6B5-4E68-8370-DB9188108635}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FA9AEA06-D6B5-4E68-8370-DB9188108635}.Release|Any CPU.Build.0 = Release|Any CPU
{18B76DAC-5DCB-44EA-B74D-0B4554BB161C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{18B76DAC-5DCB-44EA-B74D-0B4554BB161C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18B76DAC-5DCB-44EA-B74D-0B4554BB161C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18B76DAC-5DCB-44EA-B74D-0B4554BB161C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{AFC74569-B289-4ACC-B21C-313A3A62C017} = {D360C08E-EA47-43AC-A566-FDF413442980}
{200EED99-FE3E-45C6-A51E-76ED9819CA2B} = {D360C08E-EA47-43AC-A566-FDF413442980}
{CF65EB5B-5364-4D2A-8639-F147A67F08E7} = {D360C08E-EA47-43AC-A566-FDF413442980}
{5593825E-F5C9-467F-9125-3E3249CFEEAB} = {1DE7A758-1F4F-4BA5-BE1C-74F9D0AB9EA3}
{0CD7F64B-7827-4AC9-B7D8-CE371D505544} = {1DE7A758-1F4F-4BA5-BE1C-74F9D0AB9EA3}
{FA9AEA06-D6B5-4E68-8370-DB9188108635} = {1DE7A758-1F4F-4BA5-BE1C-74F9D0AB9EA3}
{1DE7A758-1F4F-4BA5-BE1C-74F9D0AB9EA3} = {7805B410-9260-4907-A7C6-D739369B2F25}
{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC} = {7805B410-9260-4907-A7C6-D739369B2F25}
{18B76DAC-5DCB-44EA-B74D-0B4554BB161C} = {7805B410-9260-4907-A7C6-D739369B2F25}
EndGlobalSection
EndGlobal

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse", "ProjectLighthouse\ProjectLighthouse.csproj", "{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Tests", "ProjectLighthouse.Tests\ProjectLighthouse.Tests.csproj", "{AFC74569-B289-4ACC-B21C-313A3A62C017}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D360C08E-EA47-43AC-A566-FDF413442980}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Tests.GameApiTests", "ProjectLighthouse.Tests.GameApiTests\ProjectLighthouse.Tests.GameApiTests.csproj", "{200EED99-FE3E-45C6-A51E-76ED9819CA2B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Tests.WebsiteTests", "ProjectLighthouse.Tests.WebsiteTests\ProjectLighthouse.Tests.WebsiteTests.csproj", "{CF65EB5B-5364-4D2A-8639-F147A67F08E7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Servers.API", "ProjectLighthouse.Servers.API\ProjectLighthouse.Servers.API.csproj", "{5593825E-F5C9-467F-9125-3E3249CFEEAB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Servers.GameServer", "ProjectLighthouse.Servers.GameServer\ProjectLighthouse.Servers.GameServer.csproj", "{0CD7F64B-7827-4AC9-B7D8-CE371D505544}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Servers.Website", "ProjectLighthouse.Servers.Website\ProjectLighthouse.Servers.Website.csproj", "{FA9AEA06-D6B5-4E68-8370-DB9188108635}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Servers", "Servers", "{1DE7A758-1F4F-4BA5-BE1C-74F9D0AB9EA3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source Code", "Source Code", "{7805B410-9260-4907-A7C6-D739369B2F25}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Localization", "ProjectLighthouse.Localization\ProjectLighthouse.Localization.csproj", "{18B76DAC-5DCB-44EA-B74D-0B4554BB161C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}.Release|Any CPU.Build.0 = Release|Any CPU
{AFC74569-B289-4ACC-B21C-313A3A62C017}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AFC74569-B289-4ACC-B21C-313A3A62C017}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AFC74569-B289-4ACC-B21C-313A3A62C017}.Release|Any CPU.ActiveCfg = Release|Any CPU
{200EED99-FE3E-45C6-A51E-76ED9819CA2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{200EED99-FE3E-45C6-A51E-76ED9819CA2B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{200EED99-FE3E-45C6-A51E-76ED9819CA2B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CF65EB5B-5364-4D2A-8639-F147A67F08E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CF65EB5B-5364-4D2A-8639-F147A67F08E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CF65EB5B-5364-4D2A-8639-F147A67F08E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5593825E-F5C9-467F-9125-3E3249CFEEAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5593825E-F5C9-467F-9125-3E3249CFEEAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5593825E-F5C9-467F-9125-3E3249CFEEAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5593825E-F5C9-467F-9125-3E3249CFEEAB}.Release|Any CPU.Build.0 = Release|Any CPU
{0CD7F64B-7827-4AC9-B7D8-CE371D505544}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0CD7F64B-7827-4AC9-B7D8-CE371D505544}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0CD7F64B-7827-4AC9-B7D8-CE371D505544}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0CD7F64B-7827-4AC9-B7D8-CE371D505544}.Release|Any CPU.Build.0 = Release|Any CPU
{FA9AEA06-D6B5-4E68-8370-DB9188108635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FA9AEA06-D6B5-4E68-8370-DB9188108635}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FA9AEA06-D6B5-4E68-8370-DB9188108635}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FA9AEA06-D6B5-4E68-8370-DB9188108635}.Release|Any CPU.Build.0 = Release|Any CPU
{18B76DAC-5DCB-44EA-B74D-0B4554BB161C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{18B76DAC-5DCB-44EA-B74D-0B4554BB161C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18B76DAC-5DCB-44EA-B74D-0B4554BB161C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18B76DAC-5DCB-44EA-B74D-0B4554BB161C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{AFC74569-B289-4ACC-B21C-313A3A62C017} = {D360C08E-EA47-43AC-A566-FDF413442980}
{200EED99-FE3E-45C6-A51E-76ED9819CA2B} = {D360C08E-EA47-43AC-A566-FDF413442980}
{CF65EB5B-5364-4D2A-8639-F147A67F08E7} = {D360C08E-EA47-43AC-A566-FDF413442980}
{5593825E-F5C9-467F-9125-3E3249CFEEAB} = {1DE7A758-1F4F-4BA5-BE1C-74F9D0AB9EA3}
{0CD7F64B-7827-4AC9-B7D8-CE371D505544} = {1DE7A758-1F4F-4BA5-BE1C-74F9D0AB9EA3}
{FA9AEA06-D6B5-4E68-8370-DB9188108635} = {1DE7A758-1F4F-4BA5-BE1C-74F9D0AB9EA3}
{1DE7A758-1F4F-4BA5-BE1C-74F9D0AB9EA3} = {7805B410-9260-4907-A7C6-D739369B2F25}
{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC} = {7805B410-9260-4907-A7C6-D739369B2F25}
{18B76DAC-5DCB-44EA-B74D-0B4554BB161C} = {7805B410-9260-4907-A7C6-D739369B2F25}
EndGlobalSection
EndGlobal

View file

@ -1,176 +1,176 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:System;assembly=mscorlib"
xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/Asp/FormatOnClosingTag/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/CSharpAnnotationTypingAssist/IsEnabledAfterTypeName/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/CSharpAnnotationTypingAssist/IsEnabledAtOtherPositions/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/CSharpAnnotationTypingAssist/IsInsertNullCheckWhenAlreadyAnnotated/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeEditing/TypingAssist/FormatOnPaste/@EntryValue">FullFormat</s:String>
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/VirtualSpaceOnEnter/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeConstructorOrDestructorBody/@EntryIndexedValue">HINT</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeLocalFunctionBody/@EntryIndexedValue">HINT</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeMethodOrOperatorBody/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeObjectCreationWhenTypeNotEvident/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeTrailingCommaInMultilineLists/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeTrailingCommaInSinglelineLists/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FBuiltInTypes/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FSimpleTypes/@EntryIndexedValue">ERROR</s:String>
<s:Boolean x:Key="/Default/CodeInspection/Highlighting/RunLongAnalysisInSwa/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/LOCAL_FUNCTION_BODY/@EntryValue">ExpressionBody</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/METHOD_OR_OPERATOR_BODY/@EntryValue">ExpressionBody</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ThisQualifier/INSTANCE_MEMBERS_QUALIFY_MEMBERS/@EntryValue">Field, Property, Event, Method</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/TRAILING_COMMA_IN_MULTILINE_LISTS/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/TRAILING_COMMA_IN_SINGLELINE_LISTS/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/CASE_BLOCK_BRACES/@EntryValue">NEXT_LINE</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/EMPTY_BLOCK_STYLE/@EntryValue">TOGETHER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_INSIDE_NAMESPACE/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_PREPROCESSOR_IF/@EntryValue">USUAL_INDENT</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_PREPROCESSOR_OTHER/@EntryValue">USUAL_INDENT</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INITIALIZER_BRACES/@EntryValue">NEXT_LINE</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INVOCABLE_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue">1</s:Int64>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_DECLARATION_PARENS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EMBEDDED_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EXPR_MEMBER_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_INITIALIZER_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_INVOCATION_PARENS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_PROPERTY_PATTERNS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_SWITCH_EXPRESSION_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_USER_LINEBREAKS/@EntryValue">False</s:Boolean>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_FORMAL_PARAMETERS_ON_LINE/@EntryValue">5</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_INITIALIZER_ELEMENTS_ON_LINE/@EntryValue">1</s:Int64>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/NESTED_TERNARY_STYLE/@EntryValue">EXPANDED</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/OTHER_BRACES/@EntryValue">NEXT_LINE</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ANONYMOUSMETHOD_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_CASE_STATEMENT_ON_SAME_LINE/@EntryValue">IF_OWNER_IS_SINGLE_LINE</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_INITIALIZER_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_PROPERTY_PATTERN_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_WHILE_ON_NEW_LINE/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AROUND_ARROW_OP/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_FOREACH_PARENTHESES/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_IF_PARENTHESES/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_SWITCH_PARENTHESES/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_USING_PARENTHESES/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_WHILE_PARENTHESES/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/TYPE_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_DECLARATION_LPAR/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_INVOCATION_LPAR/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARGUMENTS_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARRAY_INITIALIZER_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_FIRST_TYPE_PARAMETER_CONSTRAINT/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_LINQ_EXPRESSION/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_CHAINED_BINARY_EXPRESSIONS/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_CHAINED_METHOD_CALLS/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_EXTENDS_LIST_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_OBJECT_AND_COLLECTION_INITIALIZER_STYLE/@EntryValue">CHOP_ALWAYS</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_PARAMETERS_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_PROPERTY_PATTERN/@EntryValue">CHOP_ALWAYS</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForBuiltInTypes/@EntryValue">UseExplicitType</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForOtherTypes/@EntryValue">UseExplicitType</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForSimpleTypes/@EntryValue">UseExplicitType</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BE/@EntryIndexedValue">BE</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DB/@EntryIndexedValue">DB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DDS/@EntryIndexedValue">DDS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DLC/@EntryIndexedValue">DLC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IP/@EntryIndexedValue">IP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=JPG/@EntryIndexedValue">JPG</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LBP/@EntryIndexedValue">LBP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MM/@EntryIndexedValue">MM</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NAT/@EntryIndexedValue">NAT</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NP/@EntryIndexedValue">NP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PNG/@EntryIndexedValue">PNG</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PS/@EntryIndexedValue">PS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PSN/@EntryIndexedValue">PSN</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PSP/@EntryIndexedValue">PSP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RPCS/@EntryIndexedValue">RPCS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SMTP/@EntryIndexedValue">SMTP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SSL/@EntryIndexedValue">SSL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TLS/@EntryIndexedValue">TLS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Method/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=15b5b1f1_002D457c_002D4ca6_002Db278_002D5615aedc07d3/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=236f7aa5_002D7b06_002D43ca_002Dbf2a_002D9b31bfcff09a/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="CONSTANT_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=8284009d_002De743_002D4d89_002D9402_002Da5bf9a89b657/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Any" Description="Methods"&gt;&lt;ElementKinds&gt;&lt;Kind Name="METHOD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;&lt;/Policy&gt;</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EPredefinedNamingRulesToUserRulesUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Affero/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=airfryer/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ARRRRRRRRRR/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=asdf/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCAS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCES/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCET/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCJB/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCJS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCKS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCUS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Braaains/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=brun/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=deflater/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Dismisser/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=dpadrate/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=dumbass/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ezoiar/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=farc/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=FLUSHALL/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=friendscores/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Ingame/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Kettu/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=lbpme/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=LBPU/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=LBPV/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=lbpvita/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=leveltype/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=lolcatftw/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=luckydip/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mmpick/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mmpicks/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=npdata/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPEA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPEG/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPHA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPHG/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPHO/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPJA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPJG/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPUA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPUG/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPWR/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCAS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCJS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCKS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCSA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCSD/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCSF/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Rpcn/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Sublevels/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Swingy/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=thumbsdown/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=thumbsup/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=topscores/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=UCAS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=UCES/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=UCJS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=UCUS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=unfavourite/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Unheart/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Unpublish/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Unpushed/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=VCAS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=VCJS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=VCKS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=yourlbp/@EntryIndexedValue">True</s:Boolean>
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:System;assembly=mscorlib"
xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/Asp/FormatOnClosingTag/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/CSharpAnnotationTypingAssist/IsEnabledAfterTypeName/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/CSharpAnnotationTypingAssist/IsEnabledAtOtherPositions/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/CSharpAnnotationTypingAssist/IsInsertNullCheckWhenAlreadyAnnotated/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeEditing/TypingAssist/FormatOnPaste/@EntryValue">FullFormat</s:String>
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/VirtualSpaceOnEnter/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeConstructorOrDestructorBody/@EntryIndexedValue">HINT</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeLocalFunctionBody/@EntryIndexedValue">HINT</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeMethodOrOperatorBody/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeObjectCreationWhenTypeNotEvident/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeTrailingCommaInMultilineLists/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ArrangeTrailingCommaInSinglelineLists/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FBuiltInTypes/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FSimpleTypes/@EntryIndexedValue">ERROR</s:String>
<s:Boolean x:Key="/Default/CodeInspection/Highlighting/RunLongAnalysisInSwa/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/LOCAL_FUNCTION_BODY/@EntryValue">ExpressionBody</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/METHOD_OR_OPERATOR_BODY/@EntryValue">ExpressionBody</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ThisQualifier/INSTANCE_MEMBERS_QUALIFY_MEMBERS/@EntryValue">Field, Property, Event, Method</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/TRAILING_COMMA_IN_MULTILINE_LISTS/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/TRAILING_COMMA_IN_SINGLELINE_LISTS/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/CASE_BLOCK_BRACES/@EntryValue">NEXT_LINE</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/EMPTY_BLOCK_STYLE/@EntryValue">TOGETHER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_INSIDE_NAMESPACE/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_PREPROCESSOR_IF/@EntryValue">USUAL_INDENT</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_PREPROCESSOR_OTHER/@EntryValue">USUAL_INDENT</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INITIALIZER_BRACES/@EntryValue">NEXT_LINE</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INVOCABLE_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue">1</s:Int64>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_DECLARATION_PARENS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EMBEDDED_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EXPR_MEMBER_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_INITIALIZER_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_INVOCATION_PARENS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_PROPERTY_PATTERNS_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_SWITCH_EXPRESSION_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_USER_LINEBREAKS/@EntryValue">False</s:Boolean>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_FORMAL_PARAMETERS_ON_LINE/@EntryValue">5</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_INITIALIZER_ELEMENTS_ON_LINE/@EntryValue">1</s:Int64>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/NESTED_TERNARY_STYLE/@EntryValue">EXPANDED</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/OTHER_BRACES/@EntryValue">NEXT_LINE</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ANONYMOUSMETHOD_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_CASE_STATEMENT_ON_SAME_LINE/@EntryValue">IF_OWNER_IS_SINGLE_LINE</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_INITIALIZER_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_PROPERTY_PATTERN_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_WHILE_ON_NEW_LINE/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AROUND_ARROW_OP/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_FOREACH_PARENTHESES/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_IF_PARENTHESES/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_SWITCH_PARENTHESES/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_USING_PARENTHESES/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_WHILE_PARENTHESES/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/TYPE_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_DECLARATION_LPAR/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_INVOCATION_LPAR/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARGUMENTS_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARRAY_INITIALIZER_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_FIRST_TYPE_PARAMETER_CONSTRAINT/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_LINQ_EXPRESSION/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_CHAINED_BINARY_EXPRESSIONS/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_CHAINED_METHOD_CALLS/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_EXTENDS_LIST_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_OBJECT_AND_COLLECTION_INITIALIZER_STYLE/@EntryValue">CHOP_ALWAYS</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_PARAMETERS_STYLE/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_PROPERTY_PATTERN/@EntryValue">CHOP_ALWAYS</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForBuiltInTypes/@EntryValue">UseExplicitType</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForOtherTypes/@EntryValue">UseExplicitType</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForSimpleTypes/@EntryValue">UseExplicitType</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BE/@EntryIndexedValue">BE</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DB/@EntryIndexedValue">DB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DDS/@EntryIndexedValue">DDS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DLC/@EntryIndexedValue">DLC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IP/@EntryIndexedValue">IP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=JPG/@EntryIndexedValue">JPG</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LBP/@EntryIndexedValue">LBP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MM/@EntryIndexedValue">MM</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NAT/@EntryIndexedValue">NAT</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NP/@EntryIndexedValue">NP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PNG/@EntryIndexedValue">PNG</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PS/@EntryIndexedValue">PS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PSN/@EntryIndexedValue">PSN</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PSP/@EntryIndexedValue">PSP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RPCS/@EntryIndexedValue">RPCS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SMTP/@EntryIndexedValue">SMTP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SSL/@EntryIndexedValue">SSL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TLS/@EntryIndexedValue">TLS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Method/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=15b5b1f1_002D457c_002D4ca6_002Db278_002D5615aedc07d3/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=236f7aa5_002D7b06_002D43ca_002Dbf2a_002D9b31bfcff09a/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="CONSTANT_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=8284009d_002De743_002D4d89_002D9402_002Da5bf9a89b657/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Any" Description="Methods"&gt;&lt;ElementKinds&gt;&lt;Kind Name="METHOD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;&lt;/Policy&gt;</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EPredefinedNamingRulesToUserRulesUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Affero/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=airfryer/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ARRRRRRRRRR/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=asdf/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCAS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCES/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCET/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCJB/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCJS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCKS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCUS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Braaains/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=brun/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=deflater/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Dismisser/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=dpadrate/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=dumbass/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ezoiar/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=farc/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=FLUSHALL/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=friendscores/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Ingame/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Kettu/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=lbpme/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=LBPU/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=LBPV/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=lbpvita/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=leveltype/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=lolcatftw/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=luckydip/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mmpick/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mmpicks/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=npdata/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPEA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPEG/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPHA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPHG/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPHO/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPJA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPJG/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPUA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPUG/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPWR/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCAS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCJS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCKS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCSA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCSD/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCSF/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Rpcn/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Sublevels/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Swingy/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=thumbsdown/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=thumbsup/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=topscores/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=UCAS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=UCES/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=UCJS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=UCUS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=unfavourite/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Unheart/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Unpublish/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Unpushed/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=VCAS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=VCJS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=VCKS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=yourlbp/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=yourthumb/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

148
README.md
View file

@ -1,74 +1,74 @@
# Project Lighthouse
[![Continuous Integration](https://github.com/LBPUnion/ProjectLighthouse/actions/workflows/ci.yml/badge.svg)](https://github.com/LBPUnion/ProjectLighthouse/actions/workflows/ci.yml)
![GitHub commit activity](https://img.shields.io/github/commit-activity/m/LBPUnion/ProjectLighthouse)
![GitHub contributors](https://img.shields.io/github/contributors/LBPUnion/ProjectLighthouse)
![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/LBPUnion/ProjectLighthouse)
![Source Lines of Code](https://tokei.ekzhang.com/b1/github/LBPUnion/ProjectLighthouse)
Project Lighthouse is a clean-room, open-source custom server for LittleBigPlanet. This is a project conducted by
the LBP Union Ministry of Technology Research and Development team.
For concerns and inquiries about the project, please contact us [here](https://www.lbpunion.com/contact).
## DISCLAIMERS (Please read!)
### This is not a final product.
This is **beta software**, and thus is **not stable nor is it secure**.
While Project Lighthouse is in a mostly working state, **we ask that our software not be used in a production
environment until release**.
This is because we have not entirely nailed security down yet, and **your instance WILL get attacked** as a result. It's
happened before, and it'll happen again.
Simply put, **Project Lighthouse is not ready for the public yet**.
In addition, we're not responsible if someone hacks your machine and wipes your database, so make frequent backups, and
be sure to report any vulnerabilities. Thank you in advance.
### We are not obligated to provide support.
Project Lighthouse is open source. However, it is licensed under the GNU Affero General Public License version 3 (
AGPLv3)
meaning that Project Lighthouse is provided to you as-is, with **absolutely no warranty.**
Please understand that while this license gives you freedom to do pretty much anything you would want to do, including
allowing you to run your instance,
**this doesn't mean we are obligated to support you or your instance**. When you set up an instance of Project
Lighthouse, you are entirely on your own.
### Sony is not related nor liable.
[//]: # (Referenced from https://www.lbpunion.com/post/project-lighthouse-littlebigplanet-private-servers)
It is very important to stress that the LBP Union and Project Lighthouse is not affiliated with Sony Group
Corporation *(collectively referred to as “Sony”)* and its subordinate entities and studios. We are not the official
developers of LittleBigPlanet or it's online services. Project Lighthouse is a clean-room reimplementation of its
server, not the official servers.
By using Project Lighthouse you release Sony, as well as any employees or agents of Sony, from any and all liability,
corporate, or personal loss caused to you or others by the use of Project Lighthouse or any features we provide.
## Building
This will be written when we're out of beta. Consider this your barrier to entry ;).
It is recommended to build with `Release` if you plan to use Lighthouse in a production environment.
## Contributing
Please see [`CONTRIBUTING.md`](https://github.com/LBPUnion/ProjectLighthouse/blob/main/CONTRIBUTING.md) for more
information.
## Compatibility across games and platforms
| Game | Console (PS3/Vita/PSP) | Emulator (RPCS3/Vita3k/PPSSPP) | Next-Gen (PS4/PS5/Adrenaline) |
|----------|------------------------|-------------------------------------------|-------------------------------|
| LBP1 | Compatible | Compatible | No next-gen equivalent |
| LBP2 | Compatible | Compatible | No next-gen equivalent |
| LBP3 | Compatible | Compatible | Incompatible |
| LBP Vita | Compatible | Incompatible, PSN not supported on Vita3k | No next-gen equivalent |
| LBP PSP | Potentially compatible | Incompatible, PSN not supported on PPSSPP | Potentially Compatible |
Project Lighthouse is mostly a work in progress, so this chart is subject to change at any point.
# Project Lighthouse
[![Continuous Integration](https://github.com/LBPUnion/ProjectLighthouse/actions/workflows/ci.yml/badge.svg)](https://github.com/LBPUnion/ProjectLighthouse/actions/workflows/ci.yml)
![GitHub commit activity](https://img.shields.io/github/commit-activity/m/LBPUnion/ProjectLighthouse)
![GitHub contributors](https://img.shields.io/github/contributors/LBPUnion/ProjectLighthouse)
![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/LBPUnion/ProjectLighthouse)
![Source Lines of Code](https://tokei.ekzhang.com/b1/github/LBPUnion/ProjectLighthouse)
Project Lighthouse is a clean-room, open-source custom server for LittleBigPlanet. This is a project conducted by
the LBP Union Ministry of Technology Research and Development team.
For concerns and inquiries about the project, please contact us [here](https://www.lbpunion.com/contact).
## DISCLAIMERS (Please read!)
### This is not a final product.
This is **beta software**, and thus is **not stable nor is it secure**.
While Project Lighthouse is in a mostly working state, **we ask that our software not be used in a production
environment until release**.
This is because we have not entirely nailed security down yet, and **your instance WILL get attacked** as a result. It's
happened before, and it'll happen again.
Simply put, **Project Lighthouse is not ready for the public yet**.
In addition, we're not responsible if someone hacks your machine and wipes your database, so make frequent backups, and
be sure to report any vulnerabilities. Thank you in advance.
### We are not obligated to provide support.
Project Lighthouse is open source. However, it is licensed under the GNU Affero General Public License version 3 (
AGPLv3)
meaning that Project Lighthouse is provided to you as-is, with **absolutely no warranty.**
Please understand that while this license gives you freedom to do pretty much anything you would want to do, including
allowing you to run your instance,
**this doesn't mean we are obligated to support you or your instance**. When you set up an instance of Project
Lighthouse, you are entirely on your own.
### Sony is not related nor liable.
[//]: # (Referenced from https://www.lbpunion.com/post/project-lighthouse-littlebigplanet-private-servers)
It is very important to stress that the LBP Union and Project Lighthouse is not affiliated with Sony Group
Corporation *(collectively referred to as “Sony”)* and its subordinate entities and studios. We are not the official
developers of LittleBigPlanet or it's online services. Project Lighthouse is a clean-room reimplementation of its
server, not the official servers.
By using Project Lighthouse you release Sony, as well as any employees or agents of Sony, from any and all liability,
corporate, or personal loss caused to you or others by the use of Project Lighthouse or any features we provide.
## Building
This will be written when we're out of beta. Consider this your barrier to entry ;).
It is recommended to build with `Release` if you plan to use Lighthouse in a production environment.
## Contributing
Please see [`CONTRIBUTING.md`](https://github.com/LBPUnion/ProjectLighthouse/blob/main/CONTRIBUTING.md) for more
information.
## Compatibility across games and platforms
| Game | Console (PS3/Vita/PSP) | Emulator (RPCS3/Vita3k/PPSSPP) | Next-Gen (PS4/PS5/Adrenaline) |
|----------|------------------------|-------------------------------------------|-------------------------------|
| LBP1 | Compatible | Compatible | No next-gen equivalent |
| LBP2 | Compatible | Compatible | No next-gen equivalent |
| LBP3 | Compatible | Compatible | Incompatible |
| LBP Vita | Compatible | Incompatible, PSN not supported on Vita3k | No next-gen equivalent |
| LBP PSP | Potentially compatible | Incompatible, PSN not supported on PPSSPP | Potentially Compatible |
Project Lighthouse is mostly a work in progress, so this chart is subject to change at any point.

View file

@ -1,9 +1,9 @@
project_id_env: CROWDIN_PROJECT_ID
api_token_env: CROWDIN_PERSONAL_TOKEN
preserve_hierarchy: true
files:
- source: /ProjectLighthouse.Localization/*.resx
translation: /ProjectLighthouse.Localization/%file_name%.lang-%locale%.%file_extension%
ignore:
- /ProjectLighthouse.Localization/%file_name%.*.%file_extension%
project_id_env: CROWDIN_PROJECT_ID
api_token_env: CROWDIN_PERSONAL_TOKEN
preserve_hierarchy: true
files:
- source: /ProjectLighthouse.Localization/*.resx
translation: /ProjectLighthouse.Localization/%file_name%.lang-%locale%.%file_extension%
ignore:
- /ProjectLighthouse.Localization/%file_name%.*.%file_extension%

View file

@ -1,89 +1,89 @@
version: '3.4'
volumes:
database:
redis:
services:
gameserver:
image: lighthouse:latest
container_name: gameserver
build: .
restart: unless-stopped
ports:
- "10061:10061"
environment:
SERVER: GameServer
healthcheck:
test: wget --spider -t1 -nv http://localhost:10061/LITTLEBIGPLANETPS3_XML/status || exit 1
timeout: 10s
retries: 5
start_period: 60s
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
volumes:
- "./data:/lighthouse/data:z"
- "./data/.aspnet:/lighthouse/.aspnet:z"
website:
image: lighthouse:latest
container_name: website
restart: unless-stopped
ports:
- "10060:10060"
environment:
SERVER: Website
healthcheck:
test: wget --spider -t1 -nv http://localhost:10060/status || exit 1
timeout: 10s
retries: 5
start_period: 60s
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
volumes:
- "./data:/lighthouse/data:z"
- "./data/.aspnet:/lighthouse/.aspnet:z"
api:
image: lighthouse:latest
container_name: api
restart: unless-stopped
ports:
- "10062:10062"
environment:
SERVER: API
healthcheck:
test: wget --spider -t1 -nv http://localhost:10062/api/v1/status || exit 1
timeout: 10s
retries: 5
start_period: 60s
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
volumes:
- "./data:/lighthouse/data:z"
- "./data/.aspnet:/lighthouse/.aspnet:z"
db:
image: mariadb:latest
container_name: db
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: lighthouse
MARIADB_DATABASE: lighthouse
healthcheck:
test: ["CMD", "healthcheck.sh", "--su-mysql", "--connect"]
timeout: 10s
interval: 5s
retries: 5
volumes:
- "database:/var/lib/mysql"
redis:
image: redis/redis-stack-server:latest
container_name: redis
restart: unless-stopped
volumes:
version: '3.4'
volumes:
database:
redis:
services:
gameserver:
image: lighthouse:latest
container_name: gameserver
build: .
restart: unless-stopped
ports:
- "10061:10061"
environment:
SERVER: GameServer
healthcheck:
test: wget --spider -t1 -nv http://localhost:10061/LITTLEBIGPLANETPS3_XML/status || exit 1
timeout: 10s
retries: 5
start_period: 60s
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
volumes:
- "./data:/lighthouse/data:z"
- "./data/.aspnet:/lighthouse/.aspnet:z"
website:
image: lighthouse:latest
container_name: website
restart: unless-stopped
ports:
- "10060:10060"
environment:
SERVER: Website
healthcheck:
test: wget --spider -t1 -nv http://localhost:10060/status || exit 1
timeout: 10s
retries: 5
start_period: 60s
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
volumes:
- "./data:/lighthouse/data:z"
- "./data/.aspnet:/lighthouse/.aspnet:z"
api:
image: lighthouse:latest
container_name: api
restart: unless-stopped
ports:
- "10062:10062"
environment:
SERVER: API
healthcheck:
test: wget --spider -t1 -nv http://localhost:10062/api/v1/status || exit 1
timeout: 10s
retries: 5
start_period: 60s
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
volumes:
- "./data:/lighthouse/data:z"
- "./data/.aspnet:/lighthouse/.aspnet:z"
db:
image: mariadb:latest
container_name: db
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: lighthouse
MARIADB_DATABASE: lighthouse
healthcheck:
test: ["CMD", "healthcheck.sh", "--su-mysql", "--connect"]
timeout: 10s
interval: 5s
retries: 5
volumes:
- "database:/var/lib/mysql"
redis:
image: redis/redis-stack-server:latest
container_name: redis
restart: unless-stopped
volumes:
- "redis:/var/lib/redis"

View file

@ -1,7 +1,7 @@
{
"sdk": {
"version": "8.0.0",
"rollForward": "latestMajor",
"allowPrerelease": true
}
{
"sdk": {
"version": "8.0.0",
"rollForward": "latestMajor",
"allowPrerelease": true
}
}

View file

@ -1,15 +1,15 @@
version: "1.0"
linter: jetbrains/qodana-dotnet:2024.3
profile:
name: qodana.recommended
include:
- name: CheckDependencyLicenses
exclude:
- name: All
paths:
- ProjectLighthouse.Localization
- ProjectLighthouse/Migrations
- ProjectLighthouse/StaticFiles/css/themes
- ProjectLighthouse/StaticFiles/safari-pinned-tab.svg
dependencyIgnores:
version: "1.0"
linter: jetbrains/qodana-dotnet:2024.3
profile:
name: qodana.recommended
include:
- name: CheckDependencyLicenses
exclude:
- name: All
paths:
- ProjectLighthouse.Localization
- ProjectLighthouse/Migrations
- ProjectLighthouse/StaticFiles/css/themes
- ProjectLighthouse/StaticFiles/safari-pinned-tab.svg
dependencyIgnores:
- name: "SixLabors.ImageSharp" # We're open source, so we come under the Apache License