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

View file

@ -1,99 +1,99 @@
# Contributing # Contributing
## Setting up MySQL ## Setting up MySQL
Project Lighthouse requires a MySQL database. For Linux users running docker, one can be set up using 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. 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 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 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 above `docker-compose.yml` you shouldn't need to change this. For other development/especially production environments
you will need to change this. you will need to change this.
Once you've gotten MySQL running you can run Lighthouse. It will take care of the rest. Once you've gotten MySQL running you can run Lighthouse. It will take care of the rest.
## Connecting (PS3) ## 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. 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). If you are not using a PS3, see [the RPCS3 section](#connecting-rpcs3).
## 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 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). 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). 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` Next, download [UnionPatcher](https://github.com/LBPUnion/UnionPatcher/). Binaries can be found by reading the `README.md`
file. file.
You should have everything you need now, so open up RPCS3 and go to Utilities -> Decrypt PS3 Binaries. Point this 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 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. clicking Copy Info -> Copy Serial.
This should give you a file named `EBOOT.elf` in the same folder. This is your decrypted EBOOT. 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, 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 enter `http://localhost:10060/LITTLEBIGPLANETPS3_XML` in the second, and the output filename in the third. For this
guide we'll use `EBOOTlocalhost.elf`. 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. 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`. 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 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! Project Lighthouse is running, the game should now connect, and you may begin contributing!
### LittleBigPlanet 1 (RPCS3) ### LittleBigPlanet 1 (RPCS3)
For LittleBigPlanet 1 to work with RPCS3, follow the steps above normally. 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/). 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 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, 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. 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`. 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, 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. which at this moment in time crashes RPCS3.
After saving the file your LBP1 EBOOT can be used with RPCS3. After saving the file your LBP1 EBOOT can be used with RPCS3.
## Contributing Tips ## Contributing Tips
### Database migrations ### Database migrations
Some modifications may require updates to the database schema. You can automatically create a migration file by: 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`. 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. 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. 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`. 4. Running `dotnet ef migrations add <NameOfMigrationInPascalCase> --project ProjectLighthouse`.
This process will create a migration file from the changes made in the C# code. 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. The new migrations will automatically be applied upon starting Lighthouse.
### Running tests ### Running tests
You can run tests either through your IDE or by running `dotnet 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. Keep in mind while running database tests (which most tests are) you need to have `LIGHTHOUSE_DB_CONNECTION_STRING` set.
### Continuous Integration (CI) Tips ### 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 - 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. 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 - 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. running CI on a pull request. This is because of GitHub policy.
### API Documentation ### API Documentation
You can access API documentation by looking at the XMLDoc in the controllers under `ProjectLighthouse.Controllers.Api` 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 You can also access an interactive version by starting Lighthouse and accessing Swagger
at `http://localhost:10060/swagger/index.html`. at `http://localhost:10060/swagger/index.html`.

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,277 +1,277 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Configuration; using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database; using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Mail; using LBPUnion.ProjectLighthouse.Mail;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers; using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
using LBPUnion.ProjectLighthouse.Tests.Helpers; using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile; using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Mail; using LBPUnion.ProjectLighthouse.Types.Mail;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Moq; using Moq;
using Xunit; using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers; namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")] [Trait("Category", "Unit")]
public class MessageControllerTests public class MessageControllerTests
{ {
[Fact] [Fact]
public void Eula_ShouldReturnLicense_WhenConfigEmpty() public void Eula_ShouldReturnLicense_WhenConfigEmpty()
{ {
MessageController messageController = new(null!); MessageController messageController = new(null!);
messageController.SetupTestController(); messageController.SetupTestController();
ServerConfiguration.Instance.EulaText = ""; ServerConfiguration.Instance.EulaText = "";
const string expected = @" const string expected = @"
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version. License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details. GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License 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"; along with this program. If not, see <https://www.gnu.org/licenses/>." + "\n";
IActionResult result = messageController.Eula(); IActionResult result = messageController.Eula();
string eulaMsg = result.CastTo<OkObjectResult, string>(); string eulaMsg = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, eulaMsg); Assert.Equal(expected, eulaMsg);
} }
[Fact] [Fact]
public void Eula_ShouldReturnLicenseAndConfigString_WhenConfigNotEmpty() public void Eula_ShouldReturnLicenseAndConfigString_WhenConfigNotEmpty()
{ {
MessageController messageController = new(null!); MessageController messageController = new(null!);
messageController.SetupTestController(); messageController.SetupTestController();
ServerConfiguration.Instance.EulaText = "unit test eula text"; ServerConfiguration.Instance.EulaText = "unit test eula text";
const string expected = @" const string expected = @"
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version. License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details. GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License 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"; along with this program. If not, see <https://www.gnu.org/licenses/>." + "\nunit test eula text";
IActionResult result = messageController.Eula(); IActionResult result = messageController.Eula();
string eulaMsg = result.CastTo<OkObjectResult, string>(); string eulaMsg = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, eulaMsg); Assert.Equal(expected, eulaMsg);
} }
[Fact] [Fact]
public async Task Announcement_WithVariables_ShouldBeResolved() public async Task Announcement_WithVariables_ShouldBeResolved()
{ {
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(); await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
MessageController messageController = new(dbMock); MessageController messageController = new(dbMock);
messageController.SetupTestController(); messageController.SetupTestController();
ServerConfiguration.Instance.AnnounceText = "you are now logged in as %user (id: %id)"; ServerConfiguration.Instance.AnnounceText = "you are now logged in as %user (id: %id)";
const string expected = "you are now logged in as unittest (id: 1)"; const string expected = "you are now logged in as unittest (id: 1)";
IActionResult result = await messageController.Announce(); IActionResult result = await messageController.Announce();
string announceMsg = result.CastTo<OkObjectResult, string>(); string announceMsg = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, announceMsg); Assert.Equal(expected, announceMsg);
} }
[Fact] [Fact]
public async Task Announcement_WithEmptyString_ShouldBeEmpty() public async Task Announcement_WithEmptyString_ShouldBeEmpty()
{ {
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(); await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
MessageController messageController = new(dbMock); MessageController messageController = new(dbMock);
messageController.SetupTestController(); messageController.SetupTestController();
ServerConfiguration.Instance.AnnounceText = ""; ServerConfiguration.Instance.AnnounceText = "";
const string expected = ""; const string expected = "";
IActionResult result = await messageController.Announce(); IActionResult result = await messageController.Announce();
string announceMsg = result.CastTo<OkObjectResult, string>(); string announceMsg = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, announceMsg); Assert.Equal(expected, announceMsg);
} }
[Fact] [Fact]
public async Task Filter_ShouldNotCensor_WhenCensorDisabled() public async Task Filter_ShouldNotCensor_WhenCensorDisabled()
{ {
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(); await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
const string request = "unit test message"; const string request = "unit test message";
MessageController messageController = new(dbMock); MessageController messageController = new(dbMock);
messageController.SetupTestController(request); messageController.SetupTestController(request);
CensorConfiguration.Instance.UserInputFilterMode = FilterMode.None; CensorConfiguration.Instance.UserInputFilterMode = FilterMode.None;
const string expectedBody = "unit test message"; const string expectedBody = "unit test message";
IActionResult result = await messageController.Filter(new NullMailService()); IActionResult result = await messageController.Filter(new NullMailService());
string filteredMessage = result.CastTo<OkObjectResult, string>(); string filteredMessage = result.CastTo<OkObjectResult, string>();
Assert.Equal(expectedBody, filteredMessage); Assert.Equal(expectedBody, filteredMessage);
} }
[Fact] [Fact]
public async Task Filter_ShouldCensor_WhenCensorEnabled() public async Task Filter_ShouldCensor_WhenCensorEnabled()
{ {
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(); await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
const string request = "unit test message bruh"; const string request = "unit test message bruh";
MessageController messageController = new(dbMock); MessageController messageController = new(dbMock);
messageController.SetupTestController(request); messageController.SetupTestController(request);
CensorConfiguration.Instance.UserInputFilterMode = FilterMode.Asterisks; CensorConfiguration.Instance.UserInputFilterMode = FilterMode.Asterisks;
CensorConfiguration.Instance.FilteredWordList = new List<string> CensorConfiguration.Instance.FilteredWordList = new List<string>
{ {
"bruh", "bruh",
}; };
const string expectedBody = "unit test message ****"; const string expectedBody = "unit test message ****";
IActionResult result = await messageController.Filter(new NullMailService()); IActionResult result = await messageController.Filter(new NullMailService());
string filteredMessage = result.CastTo<OkObjectResult, string>(); string filteredMessage = result.CastTo<OkObjectResult, string>();
Assert.Equal(expectedBody, filteredMessage); Assert.Equal(expectedBody, filteredMessage);
} }
private static Mock<IMailService> getMailServiceMock() private static Mock<IMailService> getMailServiceMock()
{ {
Mock<IMailService> mailMock = new(); Mock<IMailService> mailMock = new();
mailMock.Setup(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())) mailMock.Setup(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns(Task.FromResult(true)); .Returns(Task.FromResult(true));
return mailMock; return mailMock;
} }
[Fact] [Fact]
public async Task Filter_ShouldNotSendEmail_WhenMailDisabled() public async Task Filter_ShouldNotSendEmail_WhenMailDisabled()
{ {
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(); await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
Mock<IMailService> mailMock = getMailServiceMock(); Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittest@unittest.com"; const string request = "/setemail unittest@unittest.com";
MessageController messageController = new(dbMock); MessageController messageController = new(dbMock);
messageController.SetupTestController(request); messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = false; ServerConfiguration.Instance.Mail.MailEnabled = false;
CensorConfiguration.Instance.FilteredWordList = new List<string>(); CensorConfiguration.Instance.FilteredWordList = new List<string>();
const string expected = "/setemail unittest@unittest.com"; const string expected = "/setemail unittest@unittest.com";
IActionResult result = await messageController.Filter(mailMock.Object); IActionResult result = await messageController.Filter(mailMock.Object);
string filteredMessage = result.CastTo<OkObjectResult, string>(); string filteredMessage = result.CastTo<OkObjectResult, string>();
Assert.Equal(expected, filteredMessage); Assert.Equal(expected, filteredMessage);
} }
[Fact] [Fact]
public async Task Filter_ShouldSendEmail_WhenMailEnabled_AndEmailNotTaken() public async Task Filter_ShouldSendEmail_WhenMailEnabled_AndEmailNotTaken()
{ {
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(); await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
Mock<IMailService> mailMock = getMailServiceMock(); Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittest@unittest.com"; const string request = "/setemail unittest@unittest.com";
MessageController messageController = new(dbMock); MessageController messageController = new(dbMock);
messageController.SetupTestController(request); messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = true; ServerConfiguration.Instance.Mail.MailEnabled = true;
const string expectedEmail = "unittest@unittest.com"; const string expectedEmail = "unittest@unittest.com";
IActionResult result = await messageController.Filter(mailMock.Object); IActionResult result = await messageController.Filter(mailMock.Object);
Assert.IsType<OkResult>(result); Assert.IsType<OkResult>(result);
Assert.Equal(expectedEmail, dbMock.Users.First().EmailAddress); Assert.Equal(expectedEmail, dbMock.Users.First().EmailAddress);
mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Once); mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Once);
} }
[Fact] [Fact]
public async Task Filter_ShouldNotSendEmail_WhenMailEnabled_AndEmailTaken() public async Task Filter_ShouldNotSendEmail_WhenMailEnabled_AndEmailTaken()
{ {
List<UserEntity> users = new() List<UserEntity> users = new()
{ {
new UserEntity new UserEntity
{ {
UserId = 2, UserId = 2,
EmailAddress = "unittest@unittest.com", EmailAddress = "unittest@unittest.com",
EmailAddressVerified = false, EmailAddressVerified = false,
}, },
}; };
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(users); await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(users);
Mock<IMailService> mailMock = getMailServiceMock(); Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittest@unittest.com"; const string request = "/setemail unittest@unittest.com";
MessageController messageController = new(dbMock); MessageController messageController = new(dbMock);
messageController.SetupTestController(request); messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = true; ServerConfiguration.Instance.Mail.MailEnabled = true;
IActionResult result = await messageController.Filter(mailMock.Object); IActionResult result = await messageController.Filter(mailMock.Object);
Assert.IsType<OkResult>(result); Assert.IsType<OkResult>(result);
mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never); mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never);
} }
[Fact] [Fact]
public async Task Filter_ShouldNotSendEmail_WhenMailEnabled_AndEmailAlreadyVerified() public async Task Filter_ShouldNotSendEmail_WhenMailEnabled_AndEmailAlreadyVerified()
{ {
UserEntity unitTestUser = MockHelper.GetUnitTestUser(); UserEntity unitTestUser = MockHelper.GetUnitTestUser();
unitTestUser.EmailAddressVerified = true; unitTestUser.EmailAddressVerified = true;
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(new List<UserEntity> await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(new List<UserEntity>
{ {
unitTestUser, unitTestUser,
}); });
Mock<IMailService> mailMock = getMailServiceMock(); Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittest@unittest.com"; const string request = "/setemail unittest@unittest.com";
MessageController messageController = new(dbMock); MessageController messageController = new(dbMock);
messageController.SetupTestController(request); messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = true; ServerConfiguration.Instance.Mail.MailEnabled = true;
IActionResult result = await messageController.Filter(mailMock.Object); IActionResult result = await messageController.Filter(mailMock.Object);
Assert.IsType<OkResult>(result); Assert.IsType<OkResult>(result);
mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never); mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never);
} }
[Fact] [Fact]
public async Task Filter_ShouldNotSendEmail_WhenMailEnabled_AndEmailFormatInvalid() public async Task Filter_ShouldNotSendEmail_WhenMailEnabled_AndEmailFormatInvalid()
{ {
UserEntity unitTestUser = MockHelper.GetUnitTestUser(); UserEntity unitTestUser = MockHelper.GetUnitTestUser();
unitTestUser.EmailAddressVerified = true; unitTestUser.EmailAddressVerified = true;
await using DatabaseContext dbMock = await MockHelper.GetTestDatabase(); await using DatabaseContext dbMock = await MockHelper.GetTestDatabase();
Mock<IMailService> mailMock = getMailServiceMock(); Mock<IMailService> mailMock = getMailServiceMock();
const string request = "/setemail unittestinvalidemail@@@"; const string request = "/setemail unittestinvalidemail@@@";
MessageController messageController = new(dbMock); MessageController messageController = new(dbMock);
messageController.SetupTestController(request); messageController.SetupTestController(request);
ServerConfiguration.Instance.Mail.MailEnabled = true; ServerConfiguration.Instance.Mail.MailEnabled = true;
IActionResult result = await messageController.Filter(mailMock.Object); IActionResult result = await messageController.Filter(mailMock.Object);
Assert.IsType<OkResult>(result); Assert.IsType<OkResult>(result);
mailMock.Verify(x => x.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Never); 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.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database; using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Slots; using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Slots;
using LBPUnion.ProjectLighthouse.Tests.Helpers; using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Entities.Token; using LBPUnion.ProjectLighthouse.Types.Entities.Token;
using LBPUnion.ProjectLighthouse.Types.Serialization; using LBPUnion.ProjectLighthouse.Types.Serialization;
using LBPUnion.ProjectLighthouse.Types.Users; using LBPUnion.ProjectLighthouse.Types.Users;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Xunit; using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers; namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")] [Trait("Category", "Unit")]
public class ReviewControllerTests public class ReviewControllerTests
{ {
private static async Task InsertTestData(DatabaseContext database) private static async Task InsertTestData(DatabaseContext database)
{ {
database.Slots.Add(new SlotEntity database.Slots.Add(new SlotEntity
{ {
SlotId = 1, SlotId = 1,
CreatorId = 1, CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet3, GameVersion = GameVersion.LittleBigPlanet3,
}); });
database.Slots.Add(new SlotEntity database.Slots.Add(new SlotEntity
{ {
SlotId = 2, SlotId = 2,
CreatorId = 1, CreatorId = 1,
GameVersion = GameVersion.LittleBigPlanet2, GameVersion = GameVersion.LittleBigPlanet2,
}); });
database.Reviews.Add(new ReviewEntity database.Reviews.Add(new ReviewEntity
{ {
ReviewId = 1, ReviewId = 1,
ReviewerId = 1, ReviewerId = 1,
SlotId = 1, SlotId = 1,
}); });
database.Reviews.Add(new ReviewEntity database.Reviews.Add(new ReviewEntity
{ {
ReviewId = 2, ReviewId = 2,
ReviewerId = 1, ReviewerId = 1,
SlotId = 2, SlotId = 2,
}); });
await database.SaveChangesAsync(); await database.SaveChangesAsync();
} }
[Theory] [Theory]
[InlineData(GameVersion.LittleBigPlanet2, 1)] [InlineData(GameVersion.LittleBigPlanet2, 1)]
[InlineData(GameVersion.LittleBigPlanet3, 2)] [InlineData(GameVersion.LittleBigPlanet3, 2)]
public async Task ReviewsBy_ShouldNotList_HigherGameVersions(GameVersion version, int expected) public async Task ReviewsBy_ShouldNotList_HigherGameVersions(GameVersion version, int expected)
{ {
GameTokenEntity token = MockHelper.GetUnitTestToken(); GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = version; token.GameVersion = version;
DatabaseContext database = await MockHelper.GetTestDatabase(new List<GameTokenEntity> DatabaseContext database = await MockHelper.GetTestDatabase(new List<GameTokenEntity>
{ {
token, token,
}); });
await InsertTestData(database); await InsertTestData(database);
ReviewController controller = new(database); ReviewController controller = new(database);
controller.SetupTestController(token); controller.SetupTestController(token);
IActionResult response = await controller.ReviewsBy("unittest"); IActionResult response = await controller.ReviewsBy("unittest");
ReviewResponse review = response.CastTo<OkObjectResult, ReviewResponse>(); ReviewResponse review = response.CastTo<OkObjectResult, ReviewResponse>();
Assert.Equal(expected, review.Reviews.Count); Assert.Equal(expected, review.Reviews.Count);
Assert.True(review.Reviews.All(r => database.Slots.FirstOrDefault(s => s.SlotId == r.Slot.SlotId)?.GameVersion <= version)); Assert.True(review.Reviews.All(r => database.Slots.FirstOrDefault(s => s.SlotId == r.Slot.SlotId)?.GameVersion <= version));
} }
[Theory] [Theory]
[InlineData(GameVersion.LittleBigPlanet2, 2, 1)] [InlineData(GameVersion.LittleBigPlanet2, 2, 1)]
[InlineData(GameVersion.LittleBigPlanet2, 1, 0)] [InlineData(GameVersion.LittleBigPlanet2, 1, 0)]
[InlineData(GameVersion.LittleBigPlanet3, 2, 1)] [InlineData(GameVersion.LittleBigPlanet3, 2, 1)]
[InlineData(GameVersion.LittleBigPlanet3, 1, 1)] [InlineData(GameVersion.LittleBigPlanet3, 1, 1)]
public async Task ReviewsFor_ShouldNotList_HigherGameVersions(GameVersion version, int slotId, int expected) public async Task ReviewsFor_ShouldNotList_HigherGameVersions(GameVersion version, int slotId, int expected)
{ {
GameTokenEntity token = MockHelper.GetUnitTestToken(); GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = version; token.GameVersion = version;
DatabaseContext database = await MockHelper.GetTestDatabase(new List<GameTokenEntity> DatabaseContext database = await MockHelper.GetTestDatabase(new List<GameTokenEntity>
{ {
token, token,
}); });
await InsertTestData(database); await InsertTestData(database);
ReviewController controller = new(database); ReviewController controller = new(database);
controller.SetupTestController(token); controller.SetupTestController(token);
IActionResult response = await controller.ReviewsFor(slotId); IActionResult response = await controller.ReviewsFor(slotId);
ReviewResponse review = response.CastTo<OkObjectResult, ReviewResponse>(); ReviewResponse review = response.CastTo<OkObjectResult, ReviewResponse>();
Assert.Equal(expected, review.Reviews.Count); Assert.Equal(expected, review.Reviews.Count);
Assert.True(review.Reviews.All(r => database.Slots.FirstOrDefault(s => s.SlotId == r.Slot.SlotId)?.GameVersion <= version)); 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.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Database; using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Slots; using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Slots;
using LBPUnion.ProjectLighthouse.Tests.Helpers; using LBPUnion.ProjectLighthouse.Tests.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Xunit; using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers; namespace ProjectLighthouse.Tests.GameApiTests.Unit.Controllers;
[Trait("Category", "Unit")] [Trait("Category", "Unit")]
public class ScoreControllerTests public class ScoreControllerTests
{ {
[Fact] [Fact]
public async Task SubmitScore_ShouldSubmitValidScore_WhenNoExistingScore() public async Task SubmitScore_ShouldSubmitValidScore_WhenNoExistingScore()
{ {
DatabaseContext database = await MockHelper.GetTestDatabase(); DatabaseContext database = await MockHelper.GetTestDatabase();
SlotEntity slot = new() SlotEntity slot = new()
{ {
CreatorId = 1, CreatorId = 1,
SlotId = 1, SlotId = 1,
}; };
database.Slots.Add(slot); database.Slots.Add(slot);
await database.SaveChangesAsync(); await database.SaveChangesAsync();
ScoreController scoreController = new(database); ScoreController scoreController = new(database);
const string xmlBody = """ const string xmlBody = """
<playRecord> <playRecord>
<type>1</type> <type>1</type>
<score>10</score> <score>10</score>
<playerIds>unittest</playerIds> <playerIds>unittest</playerIds>
</playRecord> </playRecord>
"""; """;
scoreController.SetupTestController(xmlBody); scoreController.SetupTestController(xmlBody);
IActionResult result = await scoreController.SubmitScore("user", 1, 0); IActionResult result = await scoreController.SubmitScore("user", 1, 0);
Assert.IsType<OkObjectResult>(result); Assert.IsType<OkObjectResult>(result);
Assert.NotNull(database.Scores.FirstOrDefault(s => s.Type == 1 && s.SlotId == 1 && s.UserId == 1)); Assert.NotNull(database.Scores.FirstOrDefault(s => s.Type == 1 && s.SlotId == 1 && s.UserId == 1));
} }
[Fact] [Fact]
public async Task SubmitScore_ShouldUpdateScore_WhenBetterThanExistingScore() public async Task SubmitScore_ShouldUpdateScore_WhenBetterThanExistingScore()
{ {
DatabaseContext database = await MockHelper.GetTestDatabase(); DatabaseContext database = await MockHelper.GetTestDatabase();
SlotEntity slot = new() SlotEntity slot = new()
{ {
CreatorId = 1, CreatorId = 1,
SlotId = 1, SlotId = 1,
}; };
database.Slots.Add(slot); database.Slots.Add(slot);
ScoreEntity score = new() ScoreEntity score = new()
{ {
SlotId = 1, SlotId = 1,
Type = 1, Type = 1,
UserId = 1, UserId = 1,
Points = 5, Points = 5,
Timestamp = 0, Timestamp = 0,
}; };
database.Scores.Add(score); database.Scores.Add(score);
await database.SaveChangesAsync(); await database.SaveChangesAsync();
ScoreController scoreController = new(database); ScoreController scoreController = new(database);
const string xmlBody = """ const string xmlBody = """
<playRecord> <playRecord>
<type>1</type> <type>1</type>
<score>10</score> <score>10</score>
<playerIds>unittest</playerIds> <playerIds>unittest</playerIds>
</playRecord> </playRecord>
"""; """;
scoreController.SetupTestController(xmlBody); scoreController.SetupTestController(xmlBody);
IActionResult result = await scoreController.SubmitScore("user", 1, 0); IActionResult result = await scoreController.SubmitScore("user", 1, 0);
Assert.IsType<OkObjectResult>(result); Assert.IsType<OkObjectResult>(result);
ScoreEntity? newScore = database.Scores.FirstOrDefault(s => s.Type == 1 && s.SlotId == 1 && s.UserId == 1); ScoreEntity? newScore = database.Scores.FirstOrDefault(s => s.Type == 1 && s.SlotId == 1 && s.UserId == 1);
Assert.NotNull(newScore); Assert.NotNull(newScore);
Assert.NotEqual(0, newScore.Timestamp); Assert.NotEqual(0, newScore.Timestamp);
Assert.Equal(10, newScore.Points); Assert.Equal(10, newScore.Points);
} }
[Fact] [Fact]
public async Task SubmitScore_ShouldNotUpdateScore_WhenEqualToExistingScore() public async Task SubmitScore_ShouldNotUpdateScore_WhenEqualToExistingScore()
{ {
DatabaseContext database = await MockHelper.GetTestDatabase(); DatabaseContext database = await MockHelper.GetTestDatabase();
SlotEntity slot = new() SlotEntity slot = new()
{ {
CreatorId = 1, CreatorId = 1,
SlotId = 1, SlotId = 1,
}; };
database.Slots.Add(slot); database.Slots.Add(slot);
ScoreEntity score = new() ScoreEntity score = new()
{ {
SlotId = 1, SlotId = 1,
Type = 1, Type = 1,
UserId = 1, UserId = 1,
Points = 10, Points = 10,
Timestamp = 0, Timestamp = 0,
}; };
database.Scores.Add(score); database.Scores.Add(score);
await database.SaveChangesAsync(); await database.SaveChangesAsync();
ScoreController scoreController = new(database); ScoreController scoreController = new(database);
const string xmlBody = """ const string xmlBody = """
<playRecord> <playRecord>
<type>1</type> <type>1</type>
<score>10</score> <score>10</score>
<playerIds>unittest</playerIds> <playerIds>unittest</playerIds>
</playRecord> </playRecord>
"""; """;
scoreController.SetupTestController(xmlBody); scoreController.SetupTestController(xmlBody);
IActionResult result = await scoreController.SubmitScore("user", 1, 0); IActionResult result = await scoreController.SubmitScore("user", 1, 0);
Assert.IsType<OkObjectResult>(result); Assert.IsType<OkObjectResult>(result);
ScoreEntity? newScore = database.Scores.FirstOrDefault(s => s.Type == 1 && s.SlotId == 1 && s.UserId == 1); ScoreEntity? newScore = database.Scores.FirstOrDefault(s => s.Type == 1 && s.SlotId == 1 && s.UserId == 1);
Assert.NotNull(newScore); Assert.NotNull(newScore);
Assert.Equal(0, newScore.Timestamp); Assert.Equal(0, newScore.Timestamp);
Assert.Equal(10, newScore.Points); Assert.Equal(10, newScore.Points);
} }
[Fact] [Fact]
public async Task SubmitScore_ShouldNotUpdateScore_WhenLessThanExistingScore() public async Task SubmitScore_ShouldNotUpdateScore_WhenLessThanExistingScore()
{ {
DatabaseContext database = await MockHelper.GetTestDatabase(); DatabaseContext database = await MockHelper.GetTestDatabase();
SlotEntity slot = new() SlotEntity slot = new()
{ {
CreatorId = 1, CreatorId = 1,
SlotId = 1, SlotId = 1,
}; };
database.Slots.Add(slot); database.Slots.Add(slot);
ScoreEntity score = new() ScoreEntity score = new()
{ {
SlotId = 1, SlotId = 1,
Type = 1, Type = 1,
UserId = 1, UserId = 1,
Points = 10, Points = 10,
Timestamp = 0, Timestamp = 0,
}; };
database.Scores.Add(score); database.Scores.Add(score);
await database.SaveChangesAsync(); await database.SaveChangesAsync();
ScoreController scoreController = new(database); ScoreController scoreController = new(database);
const string xmlBody = """ const string xmlBody = """
<playRecord> <playRecord>
<type>1</type> <type>1</type>
<score>5</score> <score>5</score>
<playerIds>unittest</playerIds> <playerIds>unittest</playerIds>
</playRecord> </playRecord>
"""; """;
scoreController.SetupTestController(xmlBody); scoreController.SetupTestController(xmlBody);
IActionResult result = await scoreController.SubmitScore("user", 1, 0); IActionResult result = await scoreController.SubmitScore("user", 1, 0);
Assert.IsType<OkObjectResult>(result); Assert.IsType<OkObjectResult>(result);
ScoreEntity? newScore = database.Scores.FirstOrDefault(s => s.Type == 1 && s.SlotId == 1 && s.UserId == 1); ScoreEntity? newScore = database.Scores.FirstOrDefault(s => s.Type == 1 && s.SlotId == 1 && s.UserId == 1);
Assert.NotNull(newScore); Assert.NotNull(newScore);
Assert.Equal(0, newScore.Timestamp); Assert.Equal(0, newScore.Timestamp);
Assert.Equal(10, newScore.Points); Assert.Equal(10, newScore.Points);
} }
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,38 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2024.3.0" /> <PackageReference Include="JetBrains.Annotations" Version="2024.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.18" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.18" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.18"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.18">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="Selenium.WebDriver" Version="4.34.0" /> <PackageReference Include="Selenium.WebDriver" Version="4.34.0" />
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="138.0.7204.9400" /> <PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="138.0.7204.9400" />
<PackageReference Include="xunit" Version="2.9.3" /> <PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.1"> <PackageReference Include="xunit.runner.visualstudio" Version="3.1.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.4"> <PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ProjectLighthouse.Servers.Website\ProjectLighthouse.Servers.Website.csproj" /> <ProjectReference Include="..\ProjectLighthouse.Servers.Website\ProjectLighthouse.Servers.Website.csproj" />
<ProjectReference Include="..\ProjectLighthouse.Tests\ProjectLighthouse.Tests.csproj" /> <ProjectReference Include="..\ProjectLighthouse.Tests\ProjectLighthouse.Tests.csproj" />
<ProjectReference Include="..\ProjectLighthouse\ProjectLighthouse.csproj" /> <ProjectReference Include="..\ProjectLighthouse\ProjectLighthouse.csproj" />
<ProjectReference Include="..\ProjectLighthouse.Localization\ProjectLighthouse.Localization.csproj" /> <ProjectReference Include="..\ProjectLighthouse.Localization\ProjectLighthouse.Localization.csproj" />
</ItemGroup> </ItemGroup>
</Project> </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> <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> 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> <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> !<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> 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> <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> <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# <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 k<><6B>w<EFBFBD>M<EFBFBD>O
<20>r <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> ?<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 <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>? +~<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><>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> <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- -<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> 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 <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> <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> 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><>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>Ā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 <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> 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` <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 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 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 :/ 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;
using System.Threading.Tasks; using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Configuration; using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Database; using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Helpers;
namespace LBPUnion.ProjectLighthouse.Tests.Helpers; namespace LBPUnion.ProjectLighthouse.Tests.Helpers;
public static class IntegrationHelper public static class IntegrationHelper
{ {
private static readonly Lazy<bool> dbConnected = new(() => private static readonly Lazy<bool> dbConnected = new(() =>
{ {
using DatabaseContext database = DatabaseContext.CreateNewInstance(); using DatabaseContext database = DatabaseContext.CreateNewInstance();
return database.Database.CanConnect(); return database.Database.CanConnect();
}); });
/// <summary> /// <summary>
/// Resets the database to a clean state and returns a new DatabaseContext. /// Resets the database to a clean state and returns a new DatabaseContext.
/// </summary> /// </summary>
/// <returns>A new fresh instance of DatabaseContext</returns> /// <returns>A new fresh instance of DatabaseContext</returns>
public static async Task<DatabaseContext> GetIntegrationDatabase() public static async Task<DatabaseContext> GetIntegrationDatabase()
{ {
if (!dbConnected.Value) if (!dbConnected.Value)
{ {
throw new Exception("Database is not connected.\n" + throw new Exception("Database is not connected.\n" +
"Please ensure that the database is running and that the connection string is correct.\n" + "Please ensure that the database is running and that the connection string is correct.\n" +
$"Connection string: {ServerConfiguration.Instance.DbConnectionString}"); $"Connection string: {ServerConfiguration.Instance.DbConnectionString}");
} }
await ClearRooms(); await ClearRooms();
await using DatabaseContext database = DatabaseContext.CreateNewInstance(); await using DatabaseContext database = DatabaseContext.CreateNewInstance();
await database.Database.EnsureDeletedAsync(); await database.Database.EnsureDeletedAsync();
await database.Database.EnsureCreatedAsync(); await database.Database.EnsureCreatedAsync();
return DatabaseContext.CreateNewInstance(); return DatabaseContext.CreateNewInstance();
} }
private static async Task ClearRooms() private static async Task ClearRooms()
{ {
await RoomHelper.Rooms.RemoveAllAsync(); await RoomHelper.Rooms.RemoveAllAsync();
} }
} }

View file

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

View file

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

View file

@ -1,160 +1,160 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Xml.Serialization; using System.Xml.Serialization;
using LBPUnion.ProjectLighthouse.Serialization; using LBPUnion.ProjectLighthouse.Serialization;
using LBPUnion.ProjectLighthouse.Types.Serialization; using LBPUnion.ProjectLighthouse.Types.Serialization;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Xunit; using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Integration.Serialization; namespace LBPUnion.ProjectLighthouse.Tests.Integration.Serialization;
[Trait("Category", "Integration")] [Trait("Category", "Integration")]
public class SerializationDependencyTests public class SerializationDependencyTests
{ {
private static IServiceProvider GetTestServiceProvider(params object[] dependencies) private static IServiceProvider GetTestServiceProvider(params object[] dependencies)
{ {
ServiceCollection collection = new(); ServiceCollection collection = new();
foreach (object o in dependencies) foreach (object o in dependencies)
{ {
ServiceDescriptor descriptor = new(o.GetType(), o); ServiceDescriptor descriptor = new(o.GetType(), o);
collection.Add(descriptor); collection.Add(descriptor);
} }
return new DefaultServiceProviderFactory().CreateServiceProvider(collection); return new DefaultServiceProviderFactory().CreateServiceProvider(collection);
} }
public class TestDependency public class TestDependency
{ {
public TestDependency(string secret) public TestDependency(string secret)
{ {
this.Secret = secret; this.Secret = secret;
} }
public string Secret { get; } public string Secret { get; }
} }
public class DependencyTest : TestSerializable, INeedsPreparationForSerialization public class DependencyTest : TestSerializable, INeedsPreparationForSerialization
{ {
[DefaultValue("")] [DefaultValue("")]
[XmlElement("secret")] [XmlElement("secret")]
public string Secret { get; set; } = ""; public string Secret { get; set; } = "";
public void PrepareSerialization(TestDependency testDependency) public void PrepareSerialization(TestDependency testDependency)
{ {
this.Secret = testDependency.Secret; this.Secret = testDependency.Secret;
} }
} }
[Fact] [Fact]
public void ShouldInjectDependency() public void ShouldInjectDependency()
{ {
DependencyTest serializable = new(); DependencyTest serializable = new();
TestDependency testDependency = new("bruh"); TestDependency testDependency = new("bruh");
string serialized = LighthouseSerializer.Serialize(GetTestServiceProvider(testDependency), serializable); string serialized = LighthouseSerializer.Serialize(GetTestServiceProvider(testDependency), serializable);
Assert.True(serialized == "<xmlRoot><secret>bruh</secret></xmlRoot>"); Assert.True(serialized == "<xmlRoot><secret>bruh</secret></xmlRoot>");
} }
public class RecursiveDependencyTest : TestSerializable public class RecursiveDependencyTest : TestSerializable
{ {
[XmlElement("dependency")] [XmlElement("dependency")]
public DependencyTest Dependency { get; set; } = new(); public DependencyTest Dependency { get; set; } = new();
} }
[Fact] [Fact]
public void ShouldInjectDependencyIntoNestedClass() public void ShouldInjectDependencyIntoNestedClass()
{ {
RecursiveDependencyTest serializable = new(); RecursiveDependencyTest serializable = new();
TestDependency testDependency = new("bruh"); TestDependency testDependency = new("bruh");
string serialized = LighthouseSerializer.Serialize(GetTestServiceProvider(testDependency), serializable); string serialized = LighthouseSerializer.Serialize(GetTestServiceProvider(testDependency), serializable);
Assert.True(serialized == "<xmlRoot><dependency><secret>bruh</secret></dependency></xmlRoot>"); Assert.True(serialized == "<xmlRoot><dependency><secret>bruh</secret></dependency></xmlRoot>");
} }
public class RecursiveDependencyTestWithPreparation : TestSerializable, INeedsPreparationForSerialization public class RecursiveDependencyTestWithPreparation : TestSerializable, INeedsPreparationForSerialization
{ {
[XmlElement("dependency")] [XmlElement("dependency")]
public DependencyTest Dependency { get; set; } = new(); public DependencyTest Dependency { get; set; } = new();
[XmlElement("prepared")] [XmlElement("prepared")]
public string PreparedField { get; set; } = ""; public string PreparedField { get; set; } = "";
public void PrepareSerialization() public void PrepareSerialization()
{ {
this.PreparedField = "test"; this.PreparedField = "test";
} }
} }
public class DependencyOrderTest : TestSerializable, INeedsPreparationForSerialization public class DependencyOrderTest : TestSerializable, INeedsPreparationForSerialization
{ {
[XmlElement("dependency")] [XmlElement("dependency")]
public DependencyTest Dependency { get; set; } = null!; public DependencyTest Dependency { get; set; } = null!;
[XmlElement("nestedDependency")] [XmlElement("nestedDependency")]
public RecursiveDependencyTestWithPreparation RecursiveDependency { get; set; } = null!; public RecursiveDependencyTestWithPreparation RecursiveDependency { get; set; } = null!;
public void PrepareSerialization(TestDependency testDependency) public void PrepareSerialization(TestDependency testDependency)
{ {
this.Dependency = new DependencyTest(); this.Dependency = new DependencyTest();
this.RecursiveDependency = new RecursiveDependencyTestWithPreparation(); this.RecursiveDependency = new RecursiveDependencyTestWithPreparation();
} }
} }
[Fact] [Fact]
public void ShouldDependenciesBePreparedInOrder() public void ShouldDependenciesBePreparedInOrder()
{ {
DependencyOrderTest serializable = new(); DependencyOrderTest serializable = new();
TestDependency testDependency = new("bruh"); TestDependency testDependency = new("bruh");
string serialized = LighthouseSerializer.Serialize(GetTestServiceProvider(testDependency), serializable); string serialized = LighthouseSerializer.Serialize(GetTestServiceProvider(testDependency), serializable);
Assert.True(serialized == Assert.True(serialized ==
"<xmlRoot>" + "<xmlRoot>" +
"<dependency><secret>bruh</secret></dependency>" + "<dependency><secret>bruh</secret></dependency>" +
"<nestedDependency><dependency><secret>bruh</secret></dependency><prepared>test</prepared></nestedDependency>" + "<nestedDependency><dependency><secret>bruh</secret></dependency><prepared>test</prepared></nestedDependency>" +
"</xmlRoot>"); "</xmlRoot>");
} }
public class CounterDependency public class CounterDependency
{ {
private int counter; private int counter;
public int Counter => this.counter++; public int Counter => this.counter++;
public CounterDependency() public CounterDependency()
{ {
this.counter = 0; this.counter = 0;
} }
} }
public class ListDependencyItem : ILbpSerializable, INeedsPreparationForSerialization public class ListDependencyItem : ILbpSerializable, INeedsPreparationForSerialization
{ {
[XmlElement("counter")] [XmlElement("counter")]
public int Counter { get; set; } = -1; public int Counter { get; set; } = -1;
public void PrepareSerialization(CounterDependency counter) public void PrepareSerialization(CounterDependency counter)
{ {
this.Counter = counter.Counter; this.Counter = counter.Counter;
} }
} }
public class ListDependencyTest : TestSerializable public class ListDependencyTest : TestSerializable
{ {
[XmlElement("item")] [XmlElement("item")]
public List<ListDependencyItem> Items { get; set; } = new(); public List<ListDependencyItem> Items { get; set; } = new();
} }
[Fact] [Fact]
public void ShouldPrepareItemsInList() public void ShouldPrepareItemsInList()
{ {
ListDependencyTest serializable = new() ListDependencyTest serializable = new()
{ {
Items = new List<ListDependencyItem> Items = new List<ListDependencyItem>
{ {
new(), new(),
new(), new(),
new(), new(),
}, },
}; };
CounterDependency counterDependency = new(); CounterDependency counterDependency = new();
string serialized = LighthouseSerializer.Serialize(GetTestServiceProvider(counterDependency), serializable); 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>"); 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;
using System.ComponentModel; using System.ComponentModel;
using System.Xml.Serialization; using System.Xml.Serialization;
using LBPUnion.ProjectLighthouse.Serialization; using LBPUnion.ProjectLighthouse.Serialization;
using LBPUnion.ProjectLighthouse.Types.Serialization; using LBPUnion.ProjectLighthouse.Types.Serialization;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Xunit; using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Integration.Serialization; namespace LBPUnion.ProjectLighthouse.Tests.Integration.Serialization;
public class TestSerializable : ILbpSerializable, IHasCustomRoot public class TestSerializable : ILbpSerializable, IHasCustomRoot
{ {
public virtual string GetRoot() => "xmlRoot"; public virtual string GetRoot() => "xmlRoot";
} }
[Trait("Category", "Integration")] [Trait("Category", "Integration")]
public class SerializationTests public class SerializationTests
{ {
private static IServiceProvider GetEmptyServiceProvider() => new DefaultServiceProviderFactory().CreateServiceProvider(new ServiceCollection()); private static IServiceProvider GetEmptyServiceProvider() => new DefaultServiceProviderFactory().CreateServiceProvider(new ServiceCollection());
[Fact] [Fact]
public void ShouldNotSerializeNullObject() public void ShouldNotSerializeNullObject()
{ {
TestSerializable? serializable = null; TestSerializable? serializable = null;
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable); string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.True(serialized == ""); Assert.True(serialized == "");
} }
[Fact] [Fact]
public void ShouldSerializeFullEmptyTag() public void ShouldSerializeFullEmptyTag()
{ {
TestSerializable serializable = new(); TestSerializable serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable); string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.True(serialized == "<xmlRoot></xmlRoot>"); Assert.True(serialized == "<xmlRoot></xmlRoot>");
} }
[Fact] [Fact]
public void ShouldSerializeWithCustomRoot() public void ShouldSerializeWithCustomRoot()
{ {
TestSerializable serializable = new(); TestSerializable serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable); string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.True(serialized == "<xmlRoot></xmlRoot>"); Assert.True(serialized == "<xmlRoot></xmlRoot>");
} }
public class OverriddenRoot : TestSerializable public class OverriddenRoot : TestSerializable
{ {
public override string GetRoot() => "xmlRoot2"; public override string GetRoot() => "xmlRoot2";
} }
[Fact] [Fact]
public void ShouldSerializeWithOverriddenRoot() public void ShouldSerializeWithOverriddenRoot()
{ {
OverriddenRoot serializable = new(); OverriddenRoot serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable); string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.True(serialized == "<xmlRoot2></xmlRoot2>"); Assert.True(serialized == "<xmlRoot2></xmlRoot2>");
} }
[XmlRoot("xmlRoot3")] [XmlRoot("xmlRoot3")]
public class RootAttribute : ILbpSerializable { } public class RootAttribute : ILbpSerializable { }
[Fact] [Fact]
public void ShouldSerializeWithRootAttribute() public void ShouldSerializeWithRootAttribute()
{ {
RootAttribute serializable = new(); RootAttribute serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable); string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.True(serialized == "<xmlRoot3></xmlRoot3>"); Assert.True(serialized == "<xmlRoot3></xmlRoot3>");
} }
public class DefaultValueInt : TestSerializable public class DefaultValueInt : TestSerializable
{ {
[DefaultValue(6)] [DefaultValue(6)]
[XmlElement("defaultValueInt")] [XmlElement("defaultValueInt")]
public int DefaultValueTest { get; set; } = 6; public int DefaultValueTest { get; set; } = 6;
} }
[Fact] [Fact]
public void ShouldNotSerializeDefaultValueInt() public void ShouldNotSerializeDefaultValueInt()
{ {
DefaultValueInt serializable = new(); DefaultValueInt serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable); string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized)); Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot></xmlRoot>"); Assert.True(serialized == "<xmlRoot></xmlRoot>");
} }
public class NonDefaultValueInt : TestSerializable public class NonDefaultValueInt : TestSerializable
{ {
[DefaultValue(6)] [DefaultValue(6)]
[XmlElement("nonDefaultValueInt")] [XmlElement("nonDefaultValueInt")]
public int NonDefaultValueTest { get; set; } public int NonDefaultValueTest { get; set; }
} }
[Fact] [Fact]
public void ShouldNotSerializeNonDefaultValueInt() public void ShouldNotSerializeNonDefaultValueInt()
{ {
NonDefaultValueInt serializable = new(); NonDefaultValueInt serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable); string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized)); Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot><nonDefaultValueInt>0</nonDefaultValueInt></xmlRoot>"); Assert.True(serialized == "<xmlRoot><nonDefaultValueInt>0</nonDefaultValueInt></xmlRoot>");
} }
public class DefaultNullableStringTest : TestSerializable public class DefaultNullableStringTest : TestSerializable
{ {
[DefaultValue(null)] [DefaultValue(null)]
[XmlElement("defaultNullableString")] [XmlElement("defaultNullableString")]
public string? DefaultNullableString { get; set; } public string? DefaultNullableString { get; set; }
} }
[Fact] [Fact]
public void ShouldNotSerializeDefaultNullableString() public void ShouldNotSerializeDefaultNullableString()
{ {
DefaultNullableStringTest serializable = new(); DefaultNullableStringTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable); string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized)); Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot></xmlRoot>"); Assert.True(serialized == "<xmlRoot></xmlRoot>");
} }
public class NullNullableStringTest : TestSerializable public class NullNullableStringTest : TestSerializable
{ {
[XmlElement("nullableString")] [XmlElement("nullableString")]
public string? NullableString { get; set; } public string? NullableString { get; set; }
} }
[Fact] [Fact]
public void ShouldNotSerializeNullNullableString() public void ShouldNotSerializeNullNullableString()
{ {
NullNullableStringTest serializable = new(); NullNullableStringTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable); string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized)); Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot></xmlRoot>"); Assert.True(serialized == "<xmlRoot></xmlRoot>");
} }
[Fact] [Fact]
public void ShouldSerializeNonNullNullableString() public void ShouldSerializeNonNullNullableString()
{ {
NullNullableStringTest serializable = new() NullNullableStringTest serializable = new()
{ {
NullableString = "notNull", NullableString = "notNull",
}; };
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable); string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized)); Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot><nullableString>notNull</nullableString></xmlRoot>"); Assert.True(serialized == "<xmlRoot><nullableString>notNull</nullableString></xmlRoot>");
} }
public class NonEmptyStringTest : TestSerializable public class NonEmptyStringTest : TestSerializable
{ {
[XmlElement("stringTest")] [XmlElement("stringTest")]
public string StringTest { get; set; } = "test"; public string StringTest { get; set; } = "test";
} }
[Fact] [Fact]
public void ShouldSerializeNonNullableString() public void ShouldSerializeNonNullableString()
{ {
NonEmptyStringTest serializable = new(); NonEmptyStringTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable); string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized)); Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot><stringTest>test</stringTest></xmlRoot>"); Assert.True(serialized == "<xmlRoot><stringTest>test</stringTest></xmlRoot>");
} }
[XmlRoot("xmlRoot", Namespace = "test")] [XmlRoot("xmlRoot", Namespace = "test")]
public class NameSpaceTest : TestSerializable public class NameSpaceTest : TestSerializable
{ {
[XmlElement("test", Namespace = "test2")] [XmlElement("test", Namespace = "test2")]
public int TestValue { get; set; } = 1; public int TestValue { get; set; } = 1;
} }
[Fact] [Fact]
public void ShouldExcludeNamespace() public void ShouldExcludeNamespace()
{ {
NameSpaceTest serializable = new(); NameSpaceTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable); string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized)); Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot><test>1</test></xmlRoot>"); Assert.True(serialized == "<xmlRoot><test>1</test></xmlRoot>");
} }
public class AttributeTest : TestSerializable public class AttributeTest : TestSerializable
{ {
[XmlAttribute("string")] [XmlAttribute("string")]
public string StringAttribute { get; set; } = "test"; public string StringAttribute { get; set; } = "test";
[XmlAttribute("int")] [XmlAttribute("int")]
public int NumberAttribute { get; set; } = 5; public int NumberAttribute { get; set; } = 5;
} }
[Fact] [Fact]
public void ShouldSerializeAttributes() public void ShouldSerializeAttributes()
{ {
AttributeTest serializable = new(); AttributeTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable); string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized)); Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == "<xmlRoot string=\"test\" int=\"5\"></xmlRoot>"); Assert.True(serialized == "<xmlRoot string=\"test\" int=\"5\"></xmlRoot>");
} }
public class NestingTest : TestSerializable public class NestingTest : TestSerializable
{ {
[XmlElement("nested")] [XmlElement("nested")]
public NestedType NestedType { get; set; } = new(); public NestedType NestedType { get; set; } = new();
} }
public class NestedType : ILbpSerializable public class NestedType : ILbpSerializable
{ {
[XmlElement("attributeTest")] [XmlElement("attributeTest")]
public AttributeTest AttributeTest { get; set; } = new(); public AttributeTest AttributeTest { get; set; } = new();
[XmlElement("nestedString")] [XmlElement("nestedString")]
public NonEmptyStringTest NonEmptyString { get; set; } = new(); public NonEmptyStringTest NonEmptyString { get; set; } = new();
} }
[Fact] [Fact]
public void ShouldSerializeNestedType() public void ShouldSerializeNestedType()
{ {
NestingTest serializable = new(); NestingTest serializable = new();
string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable); string serialized = LighthouseSerializer.Serialize(GetEmptyServiceProvider(), serializable);
Assert.False(string.IsNullOrWhiteSpace(serialized)); Assert.False(string.IsNullOrWhiteSpace(serialized));
Assert.True(serialized == Assert.True(serialized ==
"<xmlRoot><nested>" + "<xmlRoot><nested>" +
"<attributeTest string=\"test\" int=\"5\"></attributeTest>" + "<attributeTest string=\"test\" int=\"5\"></attributeTest>" +
"<nestedString><stringTest>test</stringTest></nestedString>" + "<nestedString><stringTest>test</stringTest></nestedString>" +
"</nested></xmlRoot>"); "</nested></xmlRoot>");
} }
} }

View file

@ -1,42 +1,42 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AssemblyName>LBPUnion.ProjectLighthouse.Tests</AssemblyName> <AssemblyName>LBPUnion.ProjectLighthouse.Tests</AssemblyName>
<RootNamespace>LBPUnion.ProjectLighthouse.Tests</RootNamespace> <RootNamespace>LBPUnion.ProjectLighthouse.Tests</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2024.3.0" /> <PackageReference Include="JetBrains.Annotations" Version="2024.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.18" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.18" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.18"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.18">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="xunit" Version="2.9.3" /> <PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.1"> <PackageReference Include="xunit.runner.visualstudio" Version="3.1.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.4"> <PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Moq" Version="4.20.72" /> <PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.6" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="ExampleFiles\**"> <Content Include="ExampleFiles\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<ProjectReference Include="..\ProjectLighthouse\ProjectLighthouse.csproj" /> <ProjectReference Include="..\ProjectLighthouse\ProjectLighthouse.csproj" />
</ItemGroup> </ItemGroup>
</Project> </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> <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.Collections.Concurrent;
using System.Reflection; using System.Reflection;
using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile; using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using Xunit; using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit; namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")] [Trait("Category", "Unit")]
public class EmailCooldownTests public class EmailCooldownTests
{ {
private static ConcurrentDictionary<int, long>? GetInternalDict => private static ConcurrentDictionary<int, long>? GetInternalDict =>
typeof(SMTPHelper).GetField("recentlySentMail", BindingFlags.NonPublic | BindingFlags.Static)?.GetValue(null) as ConcurrentDictionary<int, long>; 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, * 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 * but half of this codebase is static singletons so my hand has kinda been forced
*/ */
[Fact] [Fact]
public void CanSendMail_WhenExpirationReached() public void CanSendMail_WhenExpirationReached()
{ {
MethodInfo? canSendMethod = typeof(SMTPHelper).GetMethod("CanSendMail", BindingFlags.NonPublic | BindingFlags.Static); MethodInfo? canSendMethod = typeof(SMTPHelper).GetMethod("CanSendMail", BindingFlags.NonPublic | BindingFlags.Static);
Assert.NotNull(canSendMethod); Assert.NotNull(canSendMethod);
UserEntity userEntity = new() UserEntity userEntity = new()
{ {
UserId = 1, UserId = 1,
}; };
Assert.NotNull(GetInternalDict); Assert.NotNull(GetInternalDict);
GetInternalDict.Clear(); GetInternalDict.Clear();
GetInternalDict.TryAdd(1, 0); GetInternalDict.TryAdd(1, 0);
bool? canSend = (bool?)canSendMethod.Invoke(null, new object?[] { userEntity, }); bool? canSend = (bool?)canSendMethod.Invoke(null, new object?[] { userEntity, });
const bool expectedValue = true; const bool expectedValue = true;
Assert.NotNull(canSend); Assert.NotNull(canSend);
Assert.Equal(expectedValue, canSend); Assert.Equal(expectedValue, canSend);
} }
[Fact] [Fact]
public void CanSendMail_WhenExpirationNotReached() public void CanSendMail_WhenExpirationNotReached()
{ {
MethodInfo? canSendMethod = MethodInfo? canSendMethod =
typeof(SMTPHelper).GetMethod("CanSendMail", BindingFlags.NonPublic | BindingFlags.Static); typeof(SMTPHelper).GetMethod("CanSendMail", BindingFlags.NonPublic | BindingFlags.Static);
Assert.NotNull(canSendMethod); Assert.NotNull(canSendMethod);
UserEntity userEntity = new() UserEntity userEntity = new()
{ {
UserId = 1, UserId = 1,
}; };
Assert.NotNull(GetInternalDict); Assert.NotNull(GetInternalDict);
GetInternalDict.Clear(); GetInternalDict.Clear();
GetInternalDict.TryAdd(1, long.MaxValue); GetInternalDict.TryAdd(1, long.MaxValue);
bool? canSend = (bool?)canSendMethod.Invoke(null, new object?[] { userEntity, }); bool? canSend = (bool?)canSendMethod.Invoke(null, new object?[] { userEntity, });
const bool expectedValue = false; const bool expectedValue = false;
Assert.NotNull(canSend); Assert.NotNull(canSend);
Assert.Equal(expectedValue, canSend); Assert.Equal(expectedValue, canSend);
} }
[Fact] [Fact]
public void CanSendMail_ExpiredEntriesAreRemoved() public void CanSendMail_ExpiredEntriesAreRemoved()
{ {
MethodInfo? canSendMethod = typeof(SMTPHelper).GetMethod("CanSendMail", BindingFlags.NonPublic | BindingFlags.Static); MethodInfo? canSendMethod = typeof(SMTPHelper).GetMethod("CanSendMail", BindingFlags.NonPublic | BindingFlags.Static);
Assert.NotNull(canSendMethod); Assert.NotNull(canSendMethod);
UserEntity userEntity = new() UserEntity userEntity = new()
{ {
UserId = 1, UserId = 1,
}; };
Assert.NotNull(GetInternalDict); Assert.NotNull(GetInternalDict);
GetInternalDict.Clear(); GetInternalDict.Clear();
GetInternalDict.TryAdd(2, 0); GetInternalDict.TryAdd(2, 0);
GetInternalDict.TryAdd(3, TimeHelper.TimestampMillis - 100); GetInternalDict.TryAdd(3, TimeHelper.TimestampMillis - 100);
GetInternalDict.TryAdd(4, long.MaxValue); GetInternalDict.TryAdd(4, long.MaxValue);
canSendMethod.Invoke(null, new object?[] { userEntity, }); canSendMethod.Invoke(null, new object?[] { userEntity, });
Assert.False(GetInternalDict.TryGetValue(2, out _)); Assert.False(GetInternalDict.TryGetValue(2, out _));
Assert.False(GetInternalDict.TryGetValue(3, out _)); Assert.False(GetInternalDict.TryGetValue(3, out _));
Assert.True(GetInternalDict.TryGetValue(4, out _)); Assert.True(GetInternalDict.TryGetValue(4, out _));
} }
} }

View file

@ -1,60 +1,60 @@
using System; using System;
using System.IO; using System.IO;
using LBPUnion.ProjectLighthouse.Types.Resources; using LBPUnion.ProjectLighthouse.Types.Resources;
using Xunit; using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit; namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")] [Trait("Category", "Unit")]
public class FileTypeTests public class FileTypeTests
{ {
[Fact] [Fact]
public void ShouldRecognizeLevel() public void ShouldRecognizeLevel()
{ {
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestLevel.lvl")); LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestLevel.lvl"));
Assert.True(file.FileType == LbpFileType.Level); Assert.True(file.FileType == LbpFileType.Level);
} }
[Fact] [Fact]
public void ShouldRecognizeScript() public void ShouldRecognizeScript()
{ {
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestScript.ff")); LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestScript.ff"));
Assert.True(file.FileType == LbpFileType.Script); Assert.True(file.FileType == LbpFileType.Script);
} }
[Fact] [Fact]
public void ShouldRecognizeTexture() public void ShouldRecognizeTexture()
{ {
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestTexture.tex")); LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestTexture.tex"));
Assert.True(file.FileType == LbpFileType.Texture); Assert.True(file.FileType == LbpFileType.Texture);
} }
[Fact] [Fact]
public void ShouldRecognizeFileArchive() public void ShouldRecognizeFileArchive()
{ {
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestFarc.farc")); LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestFarc.farc"));
Assert.True(file.FileType == LbpFileType.FileArchive); Assert.True(file.FileType == LbpFileType.FileArchive);
} }
[Fact] [Fact]
public void ShouldNotRecognizeFileArchiveAsScript() public void ShouldNotRecognizeFileArchiveAsScript()
{ {
LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestFarc.farc")); LbpFile file = new(File.ReadAllBytes("ExampleFiles/TestFarc.farc"));
Assert.False(file.FileType == LbpFileType.Script); Assert.False(file.FileType == LbpFileType.Script);
Assert.True(file.FileType == LbpFileType.FileArchive); Assert.True(file.FileType == LbpFileType.FileArchive);
} }
[Fact] [Fact]
public void ShouldRecognizeNothingAsUnknown() public void ShouldRecognizeNothingAsUnknown()
{ {
LbpFile file = new(Array.Empty<byte>()); LbpFile file = new(Array.Empty<byte>());
Assert.True(file.FileType == LbpFileType.Unknown); Assert.True(file.FileType == LbpFileType.Unknown);
} }
[Fact] [Fact]
public void ShouldRecognizeGarbageAsUnknown() public void ShouldRecognizeGarbageAsUnknown()
{ {
LbpFile file = new("free pc only $900"u8.ToArray()); LbpFile file = new("free pc only $900"u8.ToArray());
Assert.True(file.FileType == LbpFileType.Unknown); 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.IO;
using System.Xml.Serialization; using System.Xml.Serialization;
using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile; using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Misc; using LBPUnion.ProjectLighthouse.Types.Misc;
using LBPUnion.ProjectLighthouse.Types.Serialization; using LBPUnion.ProjectLighthouse.Types.Serialization;
using Xunit; using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit; namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")] [Trait("Category", "Unit")]
public class LocationTests public class LocationTests
{ {
[Fact] [Fact]
public void ShouldSetAndReadUserLocation() public void ShouldSetAndReadUserLocation()
{ {
Location expected = new() Location expected = new()
{ {
X = 1000, X = 1000,
Y = 5000, Y = 5000,
}; };
UserEntity user = new() UserEntity user = new()
{ {
Location = new Location Location = new Location
{ {
X = expected.X, X = expected.X,
Y = expected.Y, Y = expected.Y,
}, },
}; };
Assert.True(user.Location.X == expected.X); Assert.True(user.Location.X == expected.X);
Assert.True(user.Location.Y == expected.Y); Assert.True(user.Location.Y == expected.Y);
Assert.True(user.LocationPacked == 4_294_967_301_000); Assert.True(user.LocationPacked == 4_294_967_301_000);
} }
[Fact] [Fact]
public void ShouldSetAndReadSlotLocation() public void ShouldSetAndReadSlotLocation()
{ {
Location expected = new() Location expected = new()
{ {
X = 1000, X = 1000,
Y = 5000, Y = 5000,
}; };
SlotEntity slot = new() SlotEntity slot = new()
{ {
Location = new Location Location = new Location
{ {
X = expected.X, X = expected.X,
Y = expected.Y, Y = expected.Y,
}, },
}; };
Assert.True(slot.Location.X == expected.X); Assert.True(slot.Location.X == expected.X);
Assert.True(slot.Location.Y == expected.Y); Assert.True(slot.Location.Y == expected.Y);
Assert.True(slot.LocationPacked == 4_294_967_301_000); Assert.True(slot.LocationPacked == 4_294_967_301_000);
} }
[Fact] [Fact]
public void ShouldReadLocationAfterDeserialization() public void ShouldReadLocationAfterDeserialization()
{ {
XmlSerializer deserializer = new(typeof(GameUserSlot)); XmlSerializer deserializer = new(typeof(GameUserSlot));
const string slotData = "<slot><name>test</name><resource>test</resource><location><x>4000</x><y>9000</y></location></slot>"; 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)); GameUserSlot? deserialized = (GameUserSlot?)deserializer.Deserialize(new StringReader(slotData));
Assert.True(deserialized != null); Assert.True(deserialized != null);
Assert.True(deserialized.Name == "test"); Assert.True(deserialized.Name == "test");
Assert.True(deserialized.Location.X == 4000); Assert.True(deserialized.Location.X == 4000);
Assert.True(deserialized.Location.Y == 9000); Assert.True(deserialized.Location.Y == 9000);
SlotEntity entity = SlotBase.ConvertToEntity(deserialized); SlotEntity entity = SlotBase.ConvertToEntity(deserialized);
Assert.True(entity.LocationPacked == 17_179_869_193_000); Assert.True(entity.LocationPacked == 17_179_869_193_000);
} }
[Fact] [Fact]
public void ShouldDeserializeEmptyLocation() public void ShouldDeserializeEmptyLocation()
{ {
XmlSerializer deserializer = new(typeof(GameUserSlot)); XmlSerializer deserializer = new(typeof(GameUserSlot));
const string slotData = "<slot><name>test</name></slot>"; const string slotData = "<slot><name>test</name></slot>";
GameUserSlot? deserialized = (GameUserSlot?)deserializer.Deserialize(new StringReader(slotData)); GameUserSlot? deserialized = (GameUserSlot?)deserializer.Deserialize(new StringReader(slotData));
Assert.True(deserialized != null); Assert.True(deserialized != null);
Assert.True(deserialized.Name == "test"); Assert.True(deserialized.Name == "test");
Assert.True(deserialized.Location.X == 0); Assert.True(deserialized.Location.X == 0);
Assert.True(deserialized.Location.Y == 0); Assert.True(deserialized.Location.Y == 0);
SlotEntity entity = SlotBase.ConvertToEntity(deserialized); SlotEntity entity = SlotBase.ConvertToEntity(deserialized);
Assert.True(entity.LocationPacked == 0); Assert.True(entity.LocationPacked == 0);
} }
} }

View file

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

View file

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

View file

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

View file

@ -1,100 +1,100 @@
using System; using System;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Files; using LBPUnion.ProjectLighthouse.Files;
using LBPUnion.ProjectLighthouse.Types.Resources; using LBPUnion.ProjectLighthouse.Types.Resources;
using Xunit; using Xunit;
namespace LBPUnion.ProjectLighthouse.Tests.Unit; namespace LBPUnion.ProjectLighthouse.Tests.Unit;
[Trait("Category", "Unit")] [Trait("Category", "Unit")]
public class ResourceTests public class ResourceTests
{ {
[Fact] [Fact]
public void IsResourceValid_ReturnsTrue_ForValidResource() public void IsResourceValid_ReturnsTrue_ForValidResource()
{ {
string[] resources = { string[] resources = {
"g123456", "g123", "98f54143ab4e86b28c3afee0f50f2f51cfb2ed38", "0ebe53fc820a544798000188d39bfda94f53fe37" "g123456", "g123", "98f54143ab4e86b28c3afee0f50f2f51cfb2ed38", "0ebe53fc820a544798000188d39bfda94f53fe37"
}; };
Assert.Multiple(() => Assert.Multiple(() =>
{ {
foreach (string resource in resources) foreach (string resource in resources)
{ {
Assert.True(FileHelper.IsResourceValid(resource)); Assert.True(FileHelper.IsResourceValid(resource));
} }
}); });
} }
[Fact] [Fact]
public void IsResourceValid_ReturnsFalse_ForInvalidResource() public void IsResourceValid_ReturnsFalse_ForInvalidResource()
{ {
string[] resources = string[] resources =
{ {
"G0234", "g123456789012334567", "b28c3afee0f50f2f51cfb2ed38", "../Test", "G0234", "g123456789012334567", "b28c3afee0f50f2f51cfb2ed38", "../Test",
}; };
Assert.Multiple(() => Assert.Multiple(() =>
{ {
foreach (string resource in resources) foreach (string resource in resources)
{ {
Assert.False(FileHelper.IsResourceValid(resource)); Assert.False(FileHelper.IsResourceValid(resource));
} }
}); });
} }
[Fact] [Fact]
public void ShouldNotDeleteResourceFolder() public void ShouldNotDeleteResourceFolder()
{ {
FileHelper.EnsureDirectoryCreated(FileHelper.ResourcePath); FileHelper.EnsureDirectoryCreated(FileHelper.ResourcePath);
Assert.True(Directory.Exists(FileHelper.ResourcePath)); Assert.True(Directory.Exists(FileHelper.ResourcePath));
FileHelper.DeleteResource(FileHelper.ResourcePath); FileHelper.DeleteResource(FileHelper.ResourcePath);
Assert.True(Directory.Exists(FileHelper.ResourcePath)); Assert.True(Directory.Exists(FileHelper.ResourcePath));
} }
[Fact] [Fact]
public void ShouldNotDeleteImagesFolder() public void ShouldNotDeleteImagesFolder()
{ {
FileHelper.EnsureDirectoryCreated(FileHelper.ImagePath); FileHelper.EnsureDirectoryCreated(FileHelper.ImagePath);
Assert.True(Directory.Exists(FileHelper.ImagePath)); Assert.True(Directory.Exists(FileHelper.ImagePath));
FileHelper.DeleteResource(FileHelper.ImagePath); FileHelper.DeleteResource(FileHelper.ImagePath);
Assert.True(Directory.Exists(FileHelper.ImagePath)); Assert.True(Directory.Exists(FileHelper.ImagePath));
} }
[Fact] [Fact]
public void ShouldNotRecursivelyTraverseImage() public void ShouldNotRecursivelyTraverseImage()
{ {
string path = Path.Combine(FileHelper.ImagePath, $"..{Path.DirectorySeparatorChar}appsettings.json"); string path = Path.Combine(FileHelper.ImagePath, $"..{Path.DirectorySeparatorChar}appsettings.json");
FileHelper.DeleteResource(path); FileHelper.DeleteResource(path);
Assert.True(File.Exists(Path.Combine(FileHelper.ImagePath, $"..{Path.DirectorySeparatorChar}appsettings.json"))); Assert.True(File.Exists(Path.Combine(FileHelper.ImagePath, $"..{Path.DirectorySeparatorChar}appsettings.json")));
} }
[Fact] [Fact]
public void ShouldNotRecursivelyTraverseResource() public void ShouldNotRecursivelyTraverseResource()
{ {
string path = Path.Combine(FileHelper.ResourcePath, $"..{Path.DirectorySeparatorChar}appsettings.json"); string path = Path.Combine(FileHelper.ResourcePath, $"..{Path.DirectorySeparatorChar}appsettings.json");
FileHelper.DeleteResource(path); FileHelper.DeleteResource(path);
Assert.True(File.Exists(Path.Combine(FileHelper.ResourcePath, $"..{Path.DirectorySeparatorChar}appsettings.json"))); Assert.True(File.Exists(Path.Combine(FileHelper.ResourcePath, $"..{Path.DirectorySeparatorChar}appsettings.json")));
} }
[Fact] [Fact]
public async Task ShouldDeleteResourceAndImage() public async Task ShouldDeleteResourceAndImage()
{ {
FileHelper.EnsureDirectoryCreated(FileHelper.ResourcePath); FileHelper.EnsureDirectoryCreated(FileHelper.ResourcePath);
FileHelper.EnsureDirectoryCreated(FileHelper.ImagePath); FileHelper.EnsureDirectoryCreated(FileHelper.ImagePath);
string? hash = await FileHelper.ParseBase64Image("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8r8NQDwAFCQGsNA7jBAAAAABJRU5ErkJggg=="); string? hash = await FileHelper.ParseBase64Image("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8r8NQDwAFCQGsNA7jBAAAAABJRU5ErkJggg==");
LbpFile? file = LbpFile.FromHash("ed4e2857a2e315e4487ea976d1b398f57b863ff4"); LbpFile? file = LbpFile.FromHash("ed4e2857a2e315e4487ea976d1b398f57b863ff4");
Assert.True(file != null); Assert.True(file != null);
// Convert resource to png // Convert resource to png
FileHelper.LbpFileToPNG(file); FileHelper.LbpFileToPNG(file);
Assert.True(hash != null); Assert.True(hash != null);
Assert.True(hash.Equals("ed4e2857a2e315e4487ea976d1b398f57b863ff4", StringComparison.InvariantCultureIgnoreCase)); Assert.True(hash.Equals("ed4e2857a2e315e4487ea976d1b398f57b863ff4", StringComparison.InvariantCultureIgnoreCase));
Assert.True(File.Exists(Path.Combine(FileHelper.ResourcePath, hash))); Assert.True(File.Exists(Path.Combine(FileHelper.ResourcePath, hash)));
Assert.True(File.Exists(Path.Combine(FileHelper.ImagePath, $"{hash}.png"))); Assert.True(File.Exists(Path.Combine(FileHelper.ImagePath, $"{hash}.png")));
FileHelper.DeleteResource(hash); FileHelper.DeleteResource(hash);
Assert.False(File.Exists(Path.Combine(FileHelper.ResourcePath, hash))); Assert.False(File.Exists(Path.Combine(FileHelper.ResourcePath, hash)));
Assert.False(File.Exists(Path.Combine(FileHelper.ImagePath, $"{hash}.png"))); 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 Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse", "ProjectLighthouse\ProjectLighthouse.csproj", "{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse", "ProjectLighthouse\ProjectLighthouse.csproj", "{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Tests", "ProjectLighthouse.Tests\ProjectLighthouse.Tests.csproj", "{AFC74569-B289-4ACC-B21C-313A3A62C017}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Tests", "ProjectLighthouse.Tests\ProjectLighthouse.Tests.csproj", "{AFC74569-B289-4ACC-B21C-313A3A62C017}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D360C08E-EA47-43AC-A566-FDF413442980}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D360C08E-EA47-43AC-A566-FDF413442980}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Tests.GameApiTests", "ProjectLighthouse.Tests.GameApiTests\ProjectLighthouse.Tests.GameApiTests.csproj", "{200EED99-FE3E-45C6-A51E-76ED9819CA2B}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Tests.GameApiTests", "ProjectLighthouse.Tests.GameApiTests\ProjectLighthouse.Tests.GameApiTests.csproj", "{200EED99-FE3E-45C6-A51E-76ED9819CA2B}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Tests.WebsiteTests", "ProjectLighthouse.Tests.WebsiteTests\ProjectLighthouse.Tests.WebsiteTests.csproj", "{CF65EB5B-5364-4D2A-8639-F147A67F08E7}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Tests.WebsiteTests", "ProjectLighthouse.Tests.WebsiteTests\ProjectLighthouse.Tests.WebsiteTests.csproj", "{CF65EB5B-5364-4D2A-8639-F147A67F08E7}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Servers.API", "ProjectLighthouse.Servers.API\ProjectLighthouse.Servers.API.csproj", "{5593825E-F5C9-467F-9125-3E3249CFEEAB}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Servers.API", "ProjectLighthouse.Servers.API\ProjectLighthouse.Servers.API.csproj", "{5593825E-F5C9-467F-9125-3E3249CFEEAB}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Servers.GameServer", "ProjectLighthouse.Servers.GameServer\ProjectLighthouse.Servers.GameServer.csproj", "{0CD7F64B-7827-4AC9-B7D8-CE371D505544}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Servers.GameServer", "ProjectLighthouse.Servers.GameServer\ProjectLighthouse.Servers.GameServer.csproj", "{0CD7F64B-7827-4AC9-B7D8-CE371D505544}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Servers.Website", "ProjectLighthouse.Servers.Website\ProjectLighthouse.Servers.Website.csproj", "{FA9AEA06-D6B5-4E68-8370-DB9188108635}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Servers.Website", "ProjectLighthouse.Servers.Website\ProjectLighthouse.Servers.Website.csproj", "{FA9AEA06-D6B5-4E68-8370-DB9188108635}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Servers", "Servers", "{1DE7A758-1F4F-4BA5-BE1C-74F9D0AB9EA3}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Servers", "Servers", "{1DE7A758-1F4F-4BA5-BE1C-74F9D0AB9EA3}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source Code", "Source Code", "{7805B410-9260-4907-A7C6-D739369B2F25}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source Code", "Source Code", "{7805B410-9260-4907-A7C6-D739369B2F25}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Localization", "ProjectLighthouse.Localization\ProjectLighthouse.Localization.csproj", "{18B76DAC-5DCB-44EA-B74D-0B4554BB161C}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectLighthouse.Localization", "ProjectLighthouse.Localization\ProjectLighthouse.Localization.csproj", "{18B76DAC-5DCB-44EA-B74D-0B4554BB161C}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {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}.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.ActiveCfg = Release|Any CPU
{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC}.Release|Any CPU.Build.0 = 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.ActiveCfg = Debug|Any CPU
{AFC74569-B289-4ACC-B21C-313A3A62C017}.Debug|Any CPU.Build.0 = 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 {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.ActiveCfg = Debug|Any CPU
{200EED99-FE3E-45C6-A51E-76ED9819CA2B}.Debug|Any CPU.Build.0 = 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 {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.ActiveCfg = Debug|Any CPU
{CF65EB5B-5364-4D2A-8639-F147A67F08E7}.Debug|Any CPU.Build.0 = 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 {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.ActiveCfg = Debug|Any CPU
{5593825E-F5C9-467F-9125-3E3249CFEEAB}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
{5593825E-F5C9-467F-9125-3E3249CFEEAB}.Release|Any CPU.Build.0 = 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.ActiveCfg = Debug|Any CPU
{0CD7F64B-7827-4AC9-B7D8-CE371D505544}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
{0CD7F64B-7827-4AC9-B7D8-CE371D505544}.Release|Any CPU.Build.0 = 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.ActiveCfg = Debug|Any CPU
{FA9AEA06-D6B5-4E68-8370-DB9188108635}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
{FA9AEA06-D6B5-4E68-8370-DB9188108635}.Release|Any CPU.Build.0 = 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.ActiveCfg = Debug|Any CPU
{18B76DAC-5DCB-44EA-B74D-0B4554BB161C}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
{18B76DAC-5DCB-44EA-B74D-0B4554BB161C}.Release|Any CPU.Build.0 = Release|Any CPU {18B76DAC-5DCB-44EA-B74D-0B4554BB161C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
{AFC74569-B289-4ACC-B21C-313A3A62C017} = {D360C08E-EA47-43AC-A566-FDF413442980} {AFC74569-B289-4ACC-B21C-313A3A62C017} = {D360C08E-EA47-43AC-A566-FDF413442980}
{200EED99-FE3E-45C6-A51E-76ED9819CA2B} = {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} {CF65EB5B-5364-4D2A-8639-F147A67F08E7} = {D360C08E-EA47-43AC-A566-FDF413442980}
{5593825E-F5C9-467F-9125-3E3249CFEEAB} = {1DE7A758-1F4F-4BA5-BE1C-74F9D0AB9EA3} {5593825E-F5C9-467F-9125-3E3249CFEEAB} = {1DE7A758-1F4F-4BA5-BE1C-74F9D0AB9EA3}
{0CD7F64B-7827-4AC9-B7D8-CE371D505544} = {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} {FA9AEA06-D6B5-4E68-8370-DB9188108635} = {1DE7A758-1F4F-4BA5-BE1C-74F9D0AB9EA3}
{1DE7A758-1F4F-4BA5-BE1C-74F9D0AB9EA3} = {7805B410-9260-4907-A7C6-D739369B2F25} {1DE7A758-1F4F-4BA5-BE1C-74F9D0AB9EA3} = {7805B410-9260-4907-A7C6-D739369B2F25}
{C6CFD4AD-47ED-4C86-B0C4-A4216D82E0DC} = {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} {18B76DAC-5DCB-44EA-B74D-0B4554BB161C} = {7805B410-9260-4907-A7C6-D739369B2F25}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View file

@ -1,176 +1,176 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:s="clr-namespace:System;assembly=mscorlib"
xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> 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/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/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/IsEnabledAtOtherPositions/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/CSharpAnnotationTypingAssist/IsInsertNullCheckWhenAlreadyAnnotated/@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:String x:Key="/Default/CodeEditing/TypingAssist/FormatOnPaste/@EntryValue">FullFormat</s:String>
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/VirtualSpaceOnEnter/@EntryValue">True</s:Boolean> <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/=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/=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/=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/=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/=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/=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_005FBuiltInTypes/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FSimpleTypes/@EntryIndexedValue">ERROR</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: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/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/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: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_MULTILINE_LISTS/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/TRAILING_COMMA_IN_SINGLELINE_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/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/CASE_BLOCK_BRACES/@EntryValue">NEXT_LINE</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/EMPTY_BLOCK_STYLE/@EntryValue">TOGETHER</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: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_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/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/INITIALIZER_BRACES/@EntryValue">NEXT_LINE</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INVOCABLE_DECLARATION_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_CODE/@EntryValue">1</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@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_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_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_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_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_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_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_EXISTING_SWITCH_EXPRESSION_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_USER_LINEBREAKS/@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_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: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/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/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_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_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: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: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: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_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_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/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_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_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_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_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_USING_PARENTHESES/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_WHILE_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: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_DECLARATION_LPAR/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_INVOCATION_LPAR/@EntryValue">False</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_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: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_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_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_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_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_INVOCATION_RPAR/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_LINQ_EXPRESSION/@EntryValue">True</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_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_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_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_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_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/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/ForBuiltInTypes/@EntryValue">UseExplicitType</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForOtherTypes/@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/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/=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/=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/=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/=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/=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/=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/=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/=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/=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/=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/=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/=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/=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/=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/=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/=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/=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/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/=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/=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/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/=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/=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: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_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_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_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_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/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/=Affero/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=airfryer/@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/=ARRRRRRRRRR/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=asdf/@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/=BCAS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCES/@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/=BCET/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCJB/@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/=BCJS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=BCKS/@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/=BCUS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Braaains/@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/=brun/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=deflater/@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/=Dismisser/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=dpadrate/@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/=dumbass/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ezoiar/@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/=farc/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=FLUSHALL/@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/=friendscores/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Ingame/@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/=Kettu/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=lbpme/@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/=LBPU/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=LBPV/@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/=lbpvita/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=leveltype/@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/=lolcatftw/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=luckydip/@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/=mmpick/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mmpicks/@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/=npdata/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPEA/@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/=NPEG/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPHA/@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/=NPHG/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPHO/@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/=NPJA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPJG/@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/=NPUA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NPUG/@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/=NPWR/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCAS/@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/=PCJS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCKS/@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/=PCSA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCSD/@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/=PCSF/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Rpcn/@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/=Sublevels/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Swingy/@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/=thumbsdown/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=thumbsup/@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/=topscores/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=UCAS/@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/=UCES/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=UCJS/@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/=UCUS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=unfavourite/@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/=Unheart/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Unpublish/@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/=Unpushed/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=VCAS/@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/=VCJS/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=VCKS/@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/=yourlbp/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=yourthumb/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> <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 # Project Lighthouse
[![Continuous Integration](https://github.com/LBPUnion/ProjectLighthouse/actions/workflows/ci.yml/badge.svg)](https://github.com/LBPUnion/ProjectLighthouse/actions/workflows/ci.yml) [![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 commit activity](https://img.shields.io/github/commit-activity/m/LBPUnion/ProjectLighthouse)
![GitHub contributors](https://img.shields.io/github/contributors/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) ![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) ![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 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. 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). For concerns and inquiries about the project, please contact us [here](https://www.lbpunion.com/contact).
## DISCLAIMERS (Please read!) ## DISCLAIMERS (Please read!)
### This is not a final product. ### This is not a final product.
This is **beta software**, and thus is **not stable nor is it secure**. 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 While Project Lighthouse is in a mostly working state, **we ask that our software not be used in a production
environment until release**. 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 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. happened before, and it'll happen again.
Simply put, **Project Lighthouse is not ready for the public yet**. 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 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. be sure to report any vulnerabilities. Thank you in advance.
### We are not obligated to provide support. ### 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 ( Project Lighthouse is open source. However, it is licensed under the GNU Affero General Public License version 3 (
AGPLv3) AGPLv3)
meaning that Project Lighthouse is provided to you as-is, with **absolutely no warranty.** 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 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, 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 **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. Lighthouse, you are entirely on your own.
### Sony is not related nor liable. ### Sony is not related nor liable.
[//]: # (Referenced from https://www.lbpunion.com/post/project-lighthouse-littlebigplanet-private-servers) [//]: # (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 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 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 developers of LittleBigPlanet or it's online services. Project Lighthouse is a clean-room reimplementation of its
server, not the official servers. 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, 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. corporate, or personal loss caused to you or others by the use of Project Lighthouse or any features we provide.
## Building ## Building
This will be written when we're out of beta. Consider this your barrier to entry ;). 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. It is recommended to build with `Release` if you plan to use Lighthouse in a production environment.
## Contributing ## Contributing
Please see [`CONTRIBUTING.md`](https://github.com/LBPUnion/ProjectLighthouse/blob/main/CONTRIBUTING.md) for more Please see [`CONTRIBUTING.md`](https://github.com/LBPUnion/ProjectLighthouse/blob/main/CONTRIBUTING.md) for more
information. information.
## Compatibility across games and platforms ## Compatibility across games and platforms
| Game | Console (PS3/Vita/PSP) | Emulator (RPCS3/Vita3k/PPSSPP) | Next-Gen (PS4/PS5/Adrenaline) | | Game | Console (PS3/Vita/PSP) | Emulator (RPCS3/Vita3k/PPSSPP) | Next-Gen (PS4/PS5/Adrenaline) |
|----------|------------------------|-------------------------------------------|-------------------------------| |----------|------------------------|-------------------------------------------|-------------------------------|
| LBP1 | Compatible | Compatible | No next-gen equivalent | | LBP1 | Compatible | Compatible | No next-gen equivalent |
| LBP2 | Compatible | Compatible | No next-gen equivalent | | LBP2 | Compatible | Compatible | No next-gen equivalent |
| LBP3 | Compatible | Compatible | Incompatible | | LBP3 | Compatible | Compatible | Incompatible |
| LBP Vita | Compatible | Incompatible, PSN not supported on Vita3k | No next-gen equivalent | | 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 | | 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 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 project_id_env: CROWDIN_PROJECT_ID
api_token_env: CROWDIN_PERSONAL_TOKEN api_token_env: CROWDIN_PERSONAL_TOKEN
preserve_hierarchy: true preserve_hierarchy: true
files: files:
- source: /ProjectLighthouse.Localization/*.resx - source: /ProjectLighthouse.Localization/*.resx
translation: /ProjectLighthouse.Localization/%file_name%.lang-%locale%.%file_extension% translation: /ProjectLighthouse.Localization/%file_name%.lang-%locale%.%file_extension%
ignore: ignore:
- /ProjectLighthouse.Localization/%file_name%.*.%file_extension% - /ProjectLighthouse.Localization/%file_name%.*.%file_extension%

View file

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

View file

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

View file

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