Skip to content

Commit 722d380

Browse files
committed
feat: basic homepage with leaderboard
1 parent 996b613 commit 722d380

File tree

118 files changed

+5006
-175
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

118 files changed

+5006
-175
lines changed

Intersect (Core)/Logging/Output/FileOutput.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,12 @@ params object[] args
126126
args
127127
);
128128

129-
Writer.Write(line);
130-
Writer.Write(Spacer);
131-
Writer.Flush();
129+
lock (Writer)
130+
{
131+
Writer.Write(line);
132+
Writer.Write(Spacer);
133+
Writer.Flush();
134+
}
132135
}
133136
catch (Exception exceptionWhileWriting)
134137
{

Intersect.Server.Core/Database/PlayerData/Api/RefreshToken.cs

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Collections.Concurrent;
22
using System.ComponentModel.DataAnnotations;
33
using System.ComponentModel.DataAnnotations.Schema;
4+
using System.Diagnostics.CodeAnalysis;
45
using Intersect.Logging;
56
using Microsoft.AspNetCore.Identity;
67
using Microsoft.EntityFrameworkCore;
@@ -118,34 +119,44 @@ public static bool TryFind(Guid id, out RefreshToken refreshToken)
118119
}
119120
}
120121

121-
public static RefreshToken FindForTicket(Guid ticketId)
122+
public static bool TryFindForTicket(
123+
Guid ticketId,
124+
[NotNullWhen(true)] out RefreshToken? refreshToken,
125+
bool includeUser = false
126+
)
122127
{
123128
if (ticketId == Guid.Empty)
124129
{
125-
return null;
130+
refreshToken = null;
131+
return true;
126132
}
127133

128134
try
129135
{
130-
using (var context = DbInterface.CreatePlayerContext())
131-
{
132-
var refreshToken = context?.RefreshTokens.FirstOrDefault(queryToken => queryToken.TicketId == ticketId);
136+
using var context = DbInterface.CreatePlayerContext();
133137

134-
if (refreshToken == null || DateTime.UtcNow < refreshToken.Expires)
135-
{
136-
return refreshToken;
137-
}
138+
IQueryable<RefreshToken> refreshTokens = context.RefreshTokens;
139+
if (includeUser)
140+
{
141+
refreshTokens = refreshTokens.Include(t => t.User);
142+
}
138143

139-
_ = Remove(refreshToken);
144+
refreshToken = refreshTokens.FirstOrDefault(queryToken => queryToken.TicketId == ticketId);
140145

141-
return null;
146+
if (refreshToken == null || DateTime.UtcNow < refreshToken.Expires)
147+
{
148+
return refreshToken != null;
142149
}
150+
151+
_ = Remove(refreshToken);
143152
}
144-
catch (Exception ex)
153+
catch (Exception exception)
145154
{
146-
Log.Error(ex);
147-
return null;
155+
Log.Error(exception, $"Failed to load RefreshToken for {ticketId}");
148156
}
157+
158+
refreshToken = null;
159+
return false;
149160
}
150161

151162
public static IEnumerable<RefreshToken> FindForClient(Guid clientId)

Intersect.Server.Core/Database/PlayerData/User.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Concurrent;
2+
using System.Collections.Immutable;
23
using System.ComponentModel.DataAnnotations.Schema;
34
using System.Diagnostics.CodeAnalysis;
45
using System.Net;
@@ -73,6 +74,8 @@ public string PowerJson
7374

7475
[NotMapped] public UserRights Power { get; set; }
7576

77+
[JsonIgnore, NotMapped] public ImmutableList<string> Roles => Power.Roles;
78+
7679
[JsonIgnore] public virtual List<Player> Players { get; set; } = new();
7780

7881
[JsonIgnore] public virtual List<RefreshToken> RefreshTokens { get; set; } = new();
@@ -559,6 +562,51 @@ public static bool TryFetch(LookupKey lookupKey, [NotNullWhen(true)] out User? u
559562
return user != default;
560563
}
561564

565+
public bool TryLoadAvatarName([NotNullWhen(true)] out string? avatarName, out bool isFace)
566+
{
567+
(avatarName, isFace) = Players
568+
.Select(
569+
player => player.TryLoadAvatarName(out var avatarName, out var isFace)
570+
? (Name: avatarName, IsFace: isFace)
571+
: default
572+
)
573+
.FirstOrDefault(avatarInfo => !string.IsNullOrWhiteSpace(avatarInfo.Name));
574+
return !string.IsNullOrWhiteSpace(avatarName);
575+
}
576+
577+
public static bool TryAuthenticate(string username, string password, [NotNullWhen(true)] out User? user)
578+
{
579+
user = FindOnline(username);
580+
if (user != default)
581+
{
582+
var hashedPassword = SaltPasswordHash(password, user.Salt);
583+
if (string.Equals(user.Password, hashedPassword, StringComparison.Ordinal))
584+
{
585+
return true;
586+
}
587+
588+
user = default;
589+
return false;
590+
}
591+
592+
try
593+
{
594+
using var context = DbInterface.CreatePlayerContext();
595+
var salt = GetUserSalt(username);
596+
if (!string.IsNullOrWhiteSpace(salt))
597+
{
598+
var pass = SaltPasswordHash(password, salt);
599+
user = QueryUserByNameAndPasswordShallow(context, username, pass);
600+
}
601+
}
602+
catch (Exception exception)
603+
{
604+
Log.Error(exception);
605+
}
606+
607+
return user != default;
608+
}
609+
562610
public static bool TryLogin(
563611
string username,
564612
string ptPassword,
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Diagnostics.CodeAnalysis;
2+
3+
namespace Intersect.Server.Entities;
4+
5+
public partial class Player
6+
{
7+
public bool TryLoadAvatarName([NotNullWhen(true)] out string? avatarName, out bool isFace)
8+
{
9+
if (!string.IsNullOrWhiteSpace(Face))
10+
{
11+
avatarName = Face;
12+
isFace = true;
13+
return true;
14+
}
15+
16+
isFace = false;
17+
18+
if (!string.IsNullOrWhiteSpace(Sprite))
19+
{
20+
avatarName = Sprite;
21+
return true;
22+
}
23+
24+
avatarName = default;
25+
return false;
26+
}
27+
}

Intersect.Server.Core/Localization/Strings.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,9 @@ public sealed partial class GeneralNamespace : LocaleNamespace
662662

663663
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
664664
public readonly LocalizedString NoticeError = @"Error Notice";
665+
666+
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
667+
public readonly LocalizedString UnknownErrorPleaseTryAgain = @"An unknown error occurred, please try again.";
665668
}
666669

667670
public sealed partial class GuildsNamespace : LocaleNamespace

Intersect.Server/Intersect.Server.csproj

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
22

33
<PropertyGroup>
44
<Nullable>disable</Nullable>
@@ -41,21 +41,33 @@
4141
</ItemGroup>
4242

4343
<ItemGroup>
44+
<Content Update="wwwroot\favicon.ico" CopyToOutputDirectory="PreserveNewest" />
45+
<Content Update="wwwroot\css\theme.css" CopyToOutputDirectory="PreserveNewest" />
46+
<Content Update="wwwroot\css\site.css" CopyToOutputDirectory="PreserveNewest" />
47+
</ItemGroup>
48+
49+
<ItemGroup Label="Resources (ResX)">
4450
<Compile Update="Properties\Resources.Designer.cs">
4551
<DesignTime>True</DesignTime>
4652
<AutoGen>True</AutoGen>
4753
<DependentUpon>Resources.resx</DependentUpon>
4854
</Compile>
49-
</ItemGroup>
50-
51-
<ItemGroup>
5255
<EmbeddedResource Update="Properties\Resources.resx">
5356
<Generator>ResXFileCodeGenerator</Generator>
5457
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
5558
</EmbeddedResource>
59+
<Compile Update="Web\WebResources.Designer.cs">
60+
<DesignTime>True</DesignTime>
61+
<AutoGen>True</AutoGen>
62+
<DependentUpon>WebResources.resx</DependentUpon>
63+
</Compile>
64+
<EmbeddedResource Update="Web\WebResources.resx">
65+
<Generator>ResXFileCodeGenerator</Generator>
66+
<LastGenOutput>WebResources.Designer.cs</LastGenOutput>
67+
</EmbeddedResource>
5668
</ItemGroup>
5769

58-
<ItemGroup>
70+
<ItemGroup Label="Embedded Resources">
5971
<EmbeddedResource Include="$(NetworkHandshakePublicKey)" />
6072
<EmbeddedResource Include="$(NetworkHandshakePrivateKey)" />
6173
<EmbeddedResource Include="appsettings.json">
@@ -78,10 +90,12 @@
7890
<EmbeddedResource Include="Resources\e_sqlite3x86.dll" />
7991
</ItemGroup>
8092

81-
<ItemGroup>
93+
<ItemGroup Label="Package References">
8294
<PackageReference Include="AscensionGameDev.Open.NAT" Version="3.0.0.7" />
8395
<PackageReference Include="AscensionGameDev.WebSocketSharp" Version="1.0.0.7-beta" />
8496
<PackageReference Include="Asp.Versioning.OData.ApiExplorer" Version="8.1.0" />
97+
<PackageReference Include="Htmx" Version="1.6.1" />
98+
<PackageReference Include="Htmx.TagHelpers" Version="1.6.1" />
8599
<PackageReference Include="MailKit" Version="4.9.0" />
86100
<PackageReference Include="Markdown" Version="2.2.1" />
87101
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.11" />
@@ -101,6 +115,7 @@
101115
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
102116
<PackageReference Include="Pomelo.JsonObject" Version="2.2.1" />
103117
<PackageReference Include="Remotion.Linq" Version="2.2.0" />
118+
<PackageReference Include="SixLabors.ImageSharp" Version="3.0.2" />
104119
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
105120
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="7.2.0" />
106121
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen.ConventionalRouting" Version="4.3.0" />

Intersect.Server/Networking/LiteNetLib/ServerNetwork.LiteNetLib.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Intersect.Server.Core;
1212
using Intersect.Server.Networking.Helpers;
1313
using LiteNetLib.Utils;
14+
using LogLevel = Intersect.Logging.LogLevel;
1415

1516
namespace Intersect.Server.Networking.LiteNetLib;
1617

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System.Diagnostics.CodeAnalysis;
2+
using System.Security.Claims;
3+
using Intersect.Server.Database.PlayerData.Api;
4+
5+
namespace Intersect.Server.Web.Authentication;
6+
7+
public sealed record AuthenticationResult(
8+
AuthenticationResultType Type,
9+
ClaimsIdentity? Identity = default,
10+
ClaimsPrincipal? Principal = default
11+
)
12+
{
13+
public DateTime ExpiresAt { get; init; }
14+
15+
public DateTime IssuedAt { get; init; }
16+
17+
[NotNullIfNotNull(nameof(Identity))] public RefreshToken? RefreshToken { get; init; }
18+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace Intersect.Server.Web.Authentication;
2+
3+
public enum AuthenticationResultType
4+
{
5+
Unknown,
6+
Success,
7+
ErrorOccurred,
8+
Expired,
9+
Unauthorized,
10+
}

0 commit comments

Comments
 (0)