Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Light_Shop.sln.DotSettings.user
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
<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:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AExceptionDispatchInfo_002Ecs_002Fl_003AC_0021_003FUsers_003FGamers_0020zone_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fbd1d5c50194fea68ff3559c160230b0ab50f5acf4ce3061bffd6d62958e2182_003FExceptionDispatchInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AExceptionDispatchInfo_002Ecs_002Fl_003AC_0021_003FUsers_003FGamers_0020zone_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fbd1d5c50194fea68ff3559c160230b0ab50f5acf4ce3061bffd6d62958e2182_003FExceptionDispatchInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIdentityDbContext_002Ecs_002Fl_003AC_0021_003FUsers_003FGamers_0020zone_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Ff9342fb513b7b524925c79d9822cd3ecaf072c50231aa3b469875f4c2cdf_003FIdentityDbContext_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIdentityUser_002Ecs_002Fl_003AC_0021_003FUsers_003FGamers_0020zone_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F7d382df578ec93391918cfaa4ce7f4b8f35c9aed1241d6556dc9be26df13c_003FIdentityUser_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIEmailSender_002Ecs_002Fl_003AC_0021_003FUsers_003FGamers_0020zone_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F3575299287ee4ce3ae8dfe36f3c926fa8c930_003Fdd_003F80e6becf_003FIEmailSender_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
74 changes: 65 additions & 9 deletions Light_Shp.API/Controllers/AccountController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,27 +40,70 @@ public async Task<IActionResult> Register([FromBody] RegisterRequest registerReq

if (result.Succeeded)
{
var filePath = Path.Combine(Directory.GetCurrentDirectory(), "Emails", "welcomeMessage.html");

string welcomeMessage = await System.IO.File.ReadAllTextAsync(filePath);
await emailSender.SendEmailAsync(applicationUser.Email, "Welcome "+applicationUser.FirstName, welcomeMessage);

await userManager.AddToRoleAsync(applicationUser, StaticData.Customer);

await signInManager.SignInAsync(applicationUser, false);

var token = await userManager.GenerateEmailConfirmationTokenAsync(applicationUser);
var emailConfirmUrl = Url.Action( nameof(ConfirmEmail), "Account" ,new {token, userId = applicationUser.Id},
protocol: Request.Scheme,
host: Request.Host.Value
);

await emailSender.SendEmailAsync(
applicationUser.Email,
"Confirm Email",
$@"
<html>
<body>
<h1>Hello, {applicationUser.UserName}</h1>
<p>Welcome to <b>Light Shop</b> — please confirm your email:</p>
<p>
<a href='{emailConfirmUrl}'
style='display:inline-block; padding:10px 15px; background-color:#6dc97e; color:white; text-decoration:none; border-radius:6px;'>
Confirm Email
</a>
</p>
</body>
</html>
"
);
return NoContent();
}

return BadRequest(result.Errors);
}

[HttpGet("ConfirmEmail")]
public async Task<IActionResult> ConfirmEmail(string token, string userId)
{
var user = await userManager.FindByIdAsync(userId);

if (user is not null)
{
var result = await userManager.ConfirmEmailAsync(user, token);
if (result.Succeeded)
{
return Ok(new { message = "Email confirmed" });
}
else
{
return BadRequest(result.Errors);
}
}
return NotFound();
}

[HttpPost("login")]
public async Task<IActionResult> Login([FromBody] LoginRequest loginRequest)
{
var applicationUser = await userManager.FindByEmailAsync(loginRequest.Email);
if (applicationUser != null)
{
bool result = await userManager.CheckPasswordAsync(applicationUser, loginRequest.Password);
var result = await signInManager.PasswordSignInAsync(applicationUser, loginRequest.Password, loginRequest.RememberMe, false);



List<Claim> claims = new();
claims.Add(new(ClaimTypes.Name,applicationUser.UserName));
var userRoles = await userManager.GetRolesAsync(applicationUser);
Expand All @@ -73,10 +116,10 @@ public async Task<IActionResult> Login([FromBody] LoginRequest loginRequest)
}
}

if (result)
if (result.Succeeded)
{
SymmetricSecurityKey symmetricSecurityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("tstNdVvKmZmOQlahHTbWaSSoBKfSTfds"));
SigningCredentials signingCredentials = new SigningCredentials(symmetricSecurityKey,SecurityAlgorithms.HmacSha256);
SigningCredentials signingCredentials = new SigningCredentials(symmetricSecurityKey, SecurityAlgorithms.HmacSha256);
var JwtToken = new JwtSecurityToken(
expires: DateTime.Now.AddDays(1),
claims: claims,
Expand All @@ -86,8 +129,21 @@ public async Task<IActionResult> Login([FromBody] LoginRequest loginRequest)
string token = new JwtSecurityTokenHandler().WriteToken(JwtToken);
return Ok(new { token });
}
else
{
if (result.IsLockedOut)
{
return BadRequest(new { message = "Your Account is Locked, Please Try Again later" });
}
else if (result.IsNotAllowed) {
{
return BadRequest(new { message = "Email Not confirm Please Confirm Your Email" });
}
}
}

}
return BadRequest(new {message = "Invalid Email or Password"});
return BadRequest(new { message = "invalid email or password" });
}

[HttpGet("logout")]
Expand Down
12 changes: 12 additions & 0 deletions Light_Shp.API/Controllers/UsersController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,17 @@ public async Task<IActionResult> ChangeRole([FromRoute] string userId, [FromQuer
return Ok(result);
}

[HttpPatch("LockUnlock/{userId}")]
public async Task<IActionResult> LockUnLock(string userId)
{
var result = await usersService.LockUnLock(userId);

if(result == true )
{
return Ok(result);
}
return BadRequest();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Incorrect Error Handling for Lock/Unlock

The LockUnLock endpoint's logic for handling the service's bool? return value is off. It returns BadRequest() when an account is successfully unlocked (false), and also when a user isn't found (null), where NotFound() would be more appropriate.

Fix in Cursor Fix in Web


}
}
24 changes: 24 additions & 0 deletions Light_Shp.API/Light_Shp.API.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Light_Shop.API", "Light_Shop.API.csproj", "{EEF1FFE0-0578-CC6B-323C-3D61D1A5596C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{EEF1FFE0-0578-CC6B-323C-3D61D1A5596C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EEF1FFE0-0578-CC6B-323C-3D61D1A5596C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EEF1FFE0-0578-CC6B-323C-3D61D1A5596C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EEF1FFE0-0578-CC6B-323C-3D61D1A5596C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {171984C9-326D-4B37-9997-CFFE8838F258}
EndGlobalSection
EndGlobal
5 changes: 1 addition & 4 deletions Light_Shp.API/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,7 @@ public class Program
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();


Expand All @@ -43,6 +39,7 @@ public static void Main(string[] args)
builder.Services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.User.RequireUniqueEmail = false;
options.SignIn.RequireConfirmedEmail = true;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
Expand Down
31 changes: 28 additions & 3 deletions Light_Shp.API/Services/Implementations/UsersService .cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ public class UsersService : Service<ApplicationUser>, IUsersService
public UsersService(
ApplicationDbContext context,
UserManager<ApplicationUser> userManager
):base(context)

) : base(context)
{
this._context = context;
this.userManager = userManager;
Expand All @@ -40,11 +40,36 @@ public async Task<bool> ChangeRole(string userId, string roleName)
{
return true;
}

}

return false;

}

public async Task<bool?> LockUnLock(string userId)
{
var user = await userManager.FindByIdAsync(userId);

if (user is null) return null;

var isLockedNow = user.LockoutEnabled && user.LockoutEnd > DateTime.Now;

if (isLockedNow)
{
// remove block from user
user.LockoutEnabled = false;
user.LockoutEnd = null;
}
else
{
user.LockoutEnabled = true;
user.LockoutEnd = DateTime.Now.AddMinutes(1);
}
await userManager.UpdateAsync(user);
return !isLockedNow;


}
}
}
1 change: 1 addition & 0 deletions Light_Shp.API/Services/Interfaces/IUsersService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace Light_Shop.API.Services.Interfaces
public interface IUsersService : IService<ApplicationUser>
{
Task<bool> ChangeRole(string userId, string roleName);
Task<bool?> LockUnLock(string userId);

}
}
Binary file modified Light_Shp.API/bin/Debug/net9.0/Light_Shop.API.dll
Binary file not shown.
Binary file modified Light_Shp.API/bin/Debug/net9.0/Light_Shop.API.pdb
Binary file not shown.
37 changes: 37 additions & 0 deletions Light_Shp.API/obj/Debug/net9.0/ApiEndpoints.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,27 @@
],
"ReturnTypes": []
},
{
"ContainingType": "Light_Shop.API.Controllers.AccountController",
"Method": "ConfirmEmail",
"RelativePath": "api/Account/ConfirmEmail",
"HttpMethod": "GET",
"IsController": true,
"Order": 0,
"Parameters": [
{
"Name": "token",
"Type": "System.String",
"IsRequired": false
},
{
"Name": "userId",
"Type": "System.String",
"IsRequired": false
}
],
"ReturnTypes": []
},
{
"ContainingType": "Light_Shop.API.Controllers.AccountController",
"Method": "Login",
Expand Down Expand Up @@ -467,5 +488,21 @@
}
],
"ReturnTypes": []
},
{
"ContainingType": "Light_Shop.API.Controllers.UsersController",
"Method": "LockUnLock",
"RelativePath": "api/Users/LockUnlock/{userId}",
"HttpMethod": "PATCH",
"IsController": true,
"Order": 0,
"Parameters": [
{
"Name": "userId",
"Type": "System.String",
"IsRequired": true
}
],
"ReturnTypes": []
}
]
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
Expand All @@ -14,7 +13,7 @@
[assembly: System.Reflection.AssemblyCompanyAttribute("Light_Shop.API")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+5e306d32f45147443318898a8463aaa52b371567")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+1147e89f50fc580f1484c95e0ce8d6b005050c64")]
[assembly: System.Reflection.AssemblyProductAttribute("Light_Shop.API")]
[assembly: System.Reflection.AssemblyTitleAttribute("Light_Shop.API")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0c015f011126fa62066c4a267adc8f7404e1a8b8b17c9cc0e141053faf64c162
459818d04383db78fd5839511e7518cd3bb189961344743d4c0875bf9e292189
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,5 +172,5 @@ D:\Projects\Light_Shop\Light_Shp.API\bin\Debug\net9.0\Microsoft.AspNetCore.Crypt
D:\Projects\Light_Shop\Light_Shp.API\bin\Debug\net9.0\Microsoft.AspNetCore.Identity.EntityFrameworkCore.dll
D:\Projects\Light_Shop\Light_Shp.API\bin\Debug\net9.0\Microsoft.Extensions.Identity.Core.dll
D:\Projects\Light_Shop\Light_Shp.API\bin\Debug\net9.0\Microsoft.Extensions.Identity.Stores.dll
D:\Projects\Light_Shop\Light_Shp.API\obj\Debug\net9.0\staticwebassets.upToDateCheck.txt
D:\Projects\Light_Shop\Light_Shp.API\bin\Debug\net9.0\Microsoft.AspNetCore.Authentication.JwtBearer.dll
D:\Projects\Light_Shop\Light_Shp.API\obj\Debug\net9.0\staticwebassets.upToDateCheck.txt
Binary file modified Light_Shp.API/obj/Debug/net9.0/Light_Shop.API.dll
Binary file not shown.
Binary file modified Light_Shp.API/obj/Debug/net9.0/Light_Shop.API.pdb
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"documents":{"D:\\Projects\\Light_Shop\\*":"https://raw.githubusercontent.com/shareefmwafy/Light-Shop/5e306d32f45147443318898a8463aaa52b371567/*"}}
{"documents":{"D:\\Projects\\Light_Shop\\*":"https://raw.githubusercontent.com/shareefmwafy/Light-Shop/1147e89f50fc580f1484c95e0ce8d6b005050c64/*"}}
Binary file modified Light_Shp.API/obj/Debug/net9.0/ref/Light_Shop.API.dll
Binary file not shown.
Binary file modified Light_Shp.API/obj/Debug/net9.0/refint/Light_Shop.API.dll
Binary file not shown.
2 changes: 1 addition & 1 deletion Light_Shp.API/obj/Light_Shop.API.csproj.nuget.g.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\Gamers zone\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.13.2</NuGetToolVersion>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.12.2</NuGetToolVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="C:\Users\Gamers zone\.nuget\packages\" />
Expand Down
2 changes: 1 addition & 1 deletion Light_Shp.API/obj/project.packagespec.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"restore":{"projectUniqueName":"D:\\Projects\\Light_Shop\\Light_Shp.API\\Light_Shop.API.csproj","projectName":"Light_Shop.API","projectPath":"D:\\Projects\\Light_Shop\\Light_Shp.API\\Light_Shop.API.csproj","outputPath":"D:\\Projects\\Light_Shop\\Light_Shp.API\\obj\\","projectStyle":"PackageReference","fallbackFolders":["C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"],"originalTargetFrameworks":["net9.0"],"sources":{"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\":{},"https://api.nuget.org/v3/index.json":{}},"frameworks":{"net9.0":{"targetAlias":"net9.0","projectReferences":{}}},"warningProperties":{"warnAsError":["NU1605"]},"restoreAuditProperties":{"enableAudit":"true","auditLevel":"low","auditMode":"direct"},"SdkAnalysisLevel":"9.0.200"}"frameworks":{"net9.0":{"targetAlias":"net9.0","dependencies":{"Mapster":{"target":"Package","version":"[7.4.0, )"},"Microsoft.AspNetCore.Identity.EntityFrameworkCore":{"target":"Package","version":"[9.0.4, )"},"Microsoft.AspNetCore.OpenApi":{"target":"Package","version":"[9.0.3, )"},"Microsoft.EntityFrameworkCore.SqlServer":{"target":"Package","version":"[9.0.3, )"},"Microsoft.EntityFrameworkCore.Tools":{"include":"Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive","suppressParent":"All","target":"Package","version":"[9.0.3, )"},"Scalar.AspNetCore":{"target":"Package","version":"[2.1.3, )"},"Swashbuckle.AspNetCore":{"target":"Package","version":"[6.6.2, )"}},"imports":["net461","net462","net47","net471","net472","net48","net481"],"assetTargetFallback":true,"warn":true,"frameworkReferences":{"Microsoft.AspNetCore.App":{"privateAssets":"none"},"Microsoft.NETCore.App":{"privateAssets":"all"}},"runtimeIdentifierGraphPath":"C:\\Program Files\\dotnet\\sdk\\9.0.201/PortableRuntimeIdentifierGraph.json"}}
"restore":{"projectUniqueName":"D:\\Projects\\Light_Shop\\Light_Shp.API\\Light_Shop.API.csproj","projectName":"Light_Shop.API","projectPath":"D:\\Projects\\Light_Shop\\Light_Shp.API\\Light_Shop.API.csproj","outputPath":"D:\\Projects\\Light_Shop\\Light_Shp.API\\obj\\","projectStyle":"PackageReference","fallbackFolders":["C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"],"originalTargetFrameworks":["net9.0"],"sources":{"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\":{},"https://api.nuget.org/v3/index.json":{}},"frameworks":{"net9.0":{"targetAlias":"net9.0","projectReferences":{}}},"warningProperties":{"warnAsError":["NU1605"]},"restoreAuditProperties":{"enableAudit":"true","auditLevel":"low","auditMode":"direct"},"SdkAnalysisLevel":"9.0.200"}"frameworks":{"net9.0":{"targetAlias":"net9.0","dependencies":{"Mapster":{"target":"Package","version":"[7.4.0, )"},"Microsoft.AspNetCore.Authentication.JwtBearer":{"target":"Package","version":"[9.0.5, )"},"Microsoft.AspNetCore.Identity.EntityFrameworkCore":{"target":"Package","version":"[9.0.4, )"},"Microsoft.AspNetCore.OpenApi":{"target":"Package","version":"[9.0.3, )"},"Microsoft.EntityFrameworkCore.SqlServer":{"target":"Package","version":"[9.0.3, )"},"Microsoft.EntityFrameworkCore.Tools":{"include":"Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive","suppressParent":"All","target":"Package","version":"[9.0.3, )"},"Scalar.AspNetCore":{"target":"Package","version":"[2.1.3, )"},"Swashbuckle.AspNetCore":{"target":"Package","version":"[6.6.2, )"}},"imports":["net461","net462","net47","net471","net472","net48","net481"],"assetTargetFallback":true,"warn":true,"frameworkReferences":{"Microsoft.AspNetCore.App":{"privateAssets":"none"},"Microsoft.NETCore.App":{"privateAssets":"all"}},"runtimeIdentifierGraphPath":"C:\\Program Files\\dotnet\\sdk\\9.0.201/PortableRuntimeIdentifierGraph.json"}}
2 changes: 1 addition & 1 deletion Light_Shp.API/obj/rider.project.model.nuget.info
Original file line number Diff line number Diff line change
@@ -1 +1 @@
17441656314703536
17488970852461020
2 changes: 1 addition & 1 deletion Light_Shp.API/obj/rider.project.restore.info
Original file line number Diff line number Diff line change
@@ -1 +1 @@
17444319473774255
17488970852461020
Loading