Skip to content

Commit

Permalink
Gitignore server tool dependencies and swagger, validation and email …
Browse files Browse the repository at this point in the history
…confirm page for login flow
  • Loading branch information
Zekiah-A committed Mar 23, 2024
1 parent a866f44 commit 9db8524
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 48 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,6 @@ msbuild.wrn
# Node
node_modules/

# Database
SubliminalServer/Data/
# Server
SubliminalServer/Data/
SubliminalServer/Migrations/
116 changes: 74 additions & 42 deletions Other/login-template.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ class LoginSignup extends HTMLElement {
this.value = true

this.shadowRoot.innerHTML = html`
<link rel="stylesheet" href="styles.css"> <!-- TODO: Find a more efficient way if possible, perhaps a separate popup CSS which styles imports, but just this component could import -->
<!-- TODO: Find a more efficient style application if possible (perhaps remove shadowroot nesting if singleton) -->
<link rel="stylesheet" href="styles.css">
<div id="login" class="popup" currentpage="signin">
<div style="display: flex;flex-grow: 1;">
<div id="back" onclick="this.shadowThis.login.setAttribute('currentpage', 'signin')">
Expand All @@ -20,7 +21,8 @@ class LoginSignup extends HTMLElement {
<h2>Login to Subliminal:</h2>
</div>
<div id="loginSignin" class="page">
<input id="loginSigninUsername" type="text" class="popup-input" placeholder="Username">
<input id="loginSigninUsername" maxlength="16" type="text" class="popup-input" placeholder="Username" oninput="
this.shadowThis.validateUsername(this)">
<input id="loginSigninEmail" type="text" class="popup-input" placeholder="Email">
<input id="loginQRInput" type="file" accept="image/*" capture="environment" style="display: none;">
<div class="popup-button" onclick="this.shadowThis.signin(this.shadowThis.loginSigninUsername.value, this.shadowThis.loginSigninEmail.value); this.shadowThis.login.style.display = 'none';"
Expand All @@ -33,44 +35,47 @@ class LoginSignup extends HTMLElement {
</div>
</div>
<div id="loginSignup" class="page">
<input id="loginUsername" type="text" class="popup-input" oninput="this.shadowThis.validateLoginSignup()"
placeholder="Username*">
<input id="loginEmail" type="text" oninput="this.shadowThis.validateLoginSignup()" class="popup-input" placeholder="Email*">
<input id="signupUsername" type="text" class="popup-input" maxlength="16" oninput="
this.shadowThis.validateUsername(this)
this.shadowThis.validateLoginSignup()"
placeholder="Username*"
onblur="this.reportValidity()"
onchange="this.reportValidity()">
<input id="signupEmail" type="text"
oninput="this.shadowThis.validateLoginSignup()"
onblur="this.reportValidity()"
onchange="this.reportValidity()" class="popup-input" placeholder="Email*">
<div>
<label for="loginPromise">I promise to be a cool member of subliminal*</label>
<input id="loginPromise" type="checkbox" oninput="this.shadowThis.validateLoginSignup()">
<label for="signupPromise">I promise to be a cool member of subliminal*</label>
<input id="signupPromise" type="checkbox"
oninput="this.shadowThis.validateLoginSignup()"
onblur="this.reportValidity()"
onchange="this.reportValidity()">
</div>
<div style="display:flex;column-gap:8px;margin-top:8px">
<div id="signupButton" class="popup-button"
onclick="
this.shadowThis.signup(this.shadowThis.loginUsername.value, this.shadowThis.loginEmail.value)
.then(() => {
this.shadowThis.login.setAttribute('currentpage', 'code');
setTimeout(() => this.shadowThis.loginClose.removeAttribute('disabled'), 4000);
this.shadowThis.signup(this.shadowThis.signupUsername.value, this.shadowThis.signupEmail.value)
.then(() => { this.shadowThis.login.setAttribute('currentpage', 'code') });
})
" disabled>Create account
</div>
</div>
</div>
<div id="loginCode" class="page">
<p>Your account code is the key for acessing your account, keep it private!</p>
<p id="loginCodeText" class="signup-code-hidden"
onmouseenter="this.style.background = 'transparent'; this.style.color = 'black';"
style="background: transparent; color: black;font-size: 64px;font-weight: bold;text-align: center;margin: 0px;">00000000</p>
<div style="position: relative;">
<img id="loginCodeQR" style="filter: blur(16px); aspect-ratio: 1/1; width: 100%;"
onmouseenter="this.style.filter = 'blur(0px)';">
<img src="./Resources/SmallLogo.png"
style="width:64px;height:64px;position:absolute;left:50%;top:50%;opacity:0.4;transform: translate(-50%, -50%);"
width="64" height="64">
<div class="login-code-banner">
<img src="./Resources/SmallLogo.png" width="32" height="32">
<h3>It's time to confirm your account!</h3>
</div>
<p>If you're lucky we have sent you an email to verify your account, enter the code we sent you below to continue!</p>
<input id="signupCode" type="text" class="popup-input" placeholder="email-code">
<br>
<div id="loginClose" class="popup-button" onclick="
this.shadowThis.login.setAttribute('currentpage', 'signin')
this.shadowThis.login.style.display = 'none'
const finishEvent = new CustomEvent('finished', { type: 'signup' })
this.dispatchEvent(finishEvent)
" disabled="">Close
" disabled="">Finish
</div>
</div>
<div id="loginError" class="page">
Expand All @@ -97,7 +102,7 @@ class LoginSignup extends HTMLElement {
}
#login[currentpage="code"] {
height: 680px;
height: 316px;
}
#back {
Expand Down Expand Up @@ -132,6 +137,23 @@ class LoginSignup extends HTMLElement {
#login[currentpage="loginerror"] > #loginError, #login[currentpage="code"] > #loginCode {
display: flex !important;
}
.login-code-banner {
display: flex;
column-gap: 16px;
align-items: center;
justify-content: center;
}
.login-code-banner > h3 {
margin: 0;
}
#signupCode {
height: 64px;
font-size: 48px;
text-align: center;
}
`
this.shadowRoot.append(style)

Expand All @@ -149,26 +171,12 @@ class LoginSignup extends HTMLElement {
})

if (!response.ok) {
confirmFail("Signup response was denied.")
this.confirmFail("Signup response was denied.")
return
}

const dataObject = await response.json()
localStorage.accountCode = dataObject.code
localStorage.accountGuid = dataObject.guid
loginCodeText.textContent = dataObject.code

const qr = new QRious({
element: loginCodeQR,
background: "white",
foreground: "#007bd3",
level: "L",
size: 512,
value: window.location + "?accountCode=" + dataObject.code
})
loginCodeQR.src = qr.toDataURL()

showMyAccount()
console.log(dataObject)
}
catch (error) {
this.confirmFail(error)
Expand Down Expand Up @@ -205,6 +213,10 @@ class LoginSignup extends HTMLElement {
this.dispatchEvent(finishEvent)
}

validateUsername(input) {
input.value = input.value.replace(/\W+/g, '').toLowerCase()
}

confirmFail(err) {
this.errorMessage.textContent = err
this.login.setAttribute("currentPage", "loginerror")
Expand All @@ -213,10 +225,30 @@ class LoginSignup extends HTMLElement {
validateLoginSignup() {
const validUsernamePattern = /^[a-z][a-z0-9_.]{0,15}$/;
const validEmailPattern = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
let valid = true
if (this.signupUsername.value.length == 0 || !this.signupUsername.value.match(validUsernamePattern)) {
this.signupUsername.setCustomValidity("Invalid username, usernames should be lowercase with only digit, _ and . special characters")
valid = false
}
else {
this.signupUsername.setCustomValidity("")
}
if (!this.signupPromise.checked) {
this.signupPromise.setCustomValidity("You have to agree to this!")
valid = false
}
else {
this.signupPromise.setCustomValidity("")
}
if (!this.signupEmail.value.match(validEmailPattern)) {
this.signupEmail.setCustomValidity("Invalid email!")
valid = false
}
else {
this.signupEmail.setCustomValidity("")
}

if (!this.loginPromise.checked || this.loginUsername.value.length == 0
|| !this.loginEmail.value.match(validEmailPattern)
|| !this.loginUsername.value.match(validUsernamePattern)) {
if (!valid) {
this.signupButton.setAttribute("disabled", "true")
}
else {
Expand Down
12 changes: 12 additions & 0 deletions SubliminalServer/.config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "8.0.3",
"commands": [
"dotnet-ef"
]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class AccountAddressConfiguration : IEntityTypeConfiguration<AccountAddre
public void Configure(EntityTypeBuilder<AccountAddress> builder)
{
builder.HasKey(address => address.AddressKey);
builder.Property(a => a.AddressKey)
builder.Property(address => address.AddressKey)
.ValueGeneratedOnAdd();

// One to many (AccountData)
Expand Down
13 changes: 11 additions & 2 deletions SubliminalServer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@
using JsonOptions = Microsoft.AspNetCore.Http.Json.JsonOptions;

// EFCore database setup:
// dotnet tool install --global dotnet-ef
// dotnet ef migrations add InitialCreate
// dotnet ef database update
// Prerelease .NET 8 may require "dotnet tool install --global dotnet-ef --prerelease"
// Prerelease .NET 9 may require "dotnet tool install --global dotnet-ef --prerelease"
// to update from a non-prerelease, do "dotnet tool update --global dotnet-ef --prerelease"

var dataDir = new DirectoryInfo("Data");
Expand Down Expand Up @@ -84,6 +83,10 @@
});
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

// Swagger
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// Configure middlewares and runtime services, including global authorization middleware that will
// validate accounts for all site endpoints
var httpServer = builder.Build();
Expand All @@ -99,6 +102,12 @@
RequestPath = "/ProfileImage"
});

if (httpServer.Environment.IsDevelopment())
{
httpServer.UseSwagger();
httpServer.UseSwaggerUI();
}

static string GenerateToken()
{
var tokenBytes = RandomNumberGenerator.GetBytes(32);
Expand Down
1 change: 1 addition & 0 deletions SubliminalServer/SubliminalServer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0-preview.7.23375.4" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>

<ItemGroup>
Expand Down
6 changes: 5 additions & 1 deletion styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ h2 {
.popup-input {
display: block;
line-height: 1.5;
height: 2.1em;
height: 32px;
padding: 4px 8px;
border: 1px solid #aaa;
background-color: #fff;
Expand All @@ -213,6 +213,10 @@ h2 {
width: 100%;
}

.popup-input:invalid {
border: 1px solid red;
}

.popup-input:focus {
border: 1px solid var(--input-hilight);
outline: 0;
Expand Down

0 comments on commit 9db8524

Please sign in to comment.