Added new website
This commit is contained in:
1 parent
293b7727e2
commit
df26a3fe96
34 files changed
+10488
No files matched your search
@@ -0,0 +1,95 @@
|
||||
import {
|
||||
assert,
|
||||
assertFalse,
|
||||
} from "https://deno.land/std@0.224.0/assert/mod.ts";
|
||||
|
||||
type User = { username: string; passwordHashWithSalt: string };
|
||||
|
||||
const officialUsers: User[] = [
|
||||
{
|
||||
username: "marqueur",
|
||||
passwordHashWithSalt:
|
||||
"5603007580f73044864e7a0b66744f405406eaaf28fa514d724ccf11d010bd89:070b1a477e6a877d44f31961dc0402a9f3258465eed73ab6a9110c461ac68714",
|
||||
},
|
||||
];
|
||||
|
||||
export class LoginService {
|
||||
private readonly users: User[];
|
||||
|
||||
constructor(users: User[]) {
|
||||
this.users = users;
|
||||
}
|
||||
|
||||
public static officialLoginService(): LoginService {
|
||||
return new LoginService(officialUsers);
|
||||
}
|
||||
|
||||
private async hashMessage(message: string): Promise<string> {
|
||||
const msgUint8 = new TextEncoder().encode(message); // encode as (utf-8) Uint8Array
|
||||
const hashBuffer = await crypto.subtle.digest("SHA-256", msgUint8); // hash the message
|
||||
const hashArray = Array.from(new Uint8Array(hashBuffer)); // convert buffer to byte array
|
||||
const hashHex = hashArray
|
||||
.map((b) => b.toString(16).padStart(2, "0"))
|
||||
.join(""); // convert bytes to hex string
|
||||
return hashHex;
|
||||
}
|
||||
|
||||
private async shittyHmac(message: string, salt: string): Promise<string> {
|
||||
const h1 = await this.hashMessage(message + salt);
|
||||
const h2 = await this.hashMessage(salt + message);
|
||||
return await this.hashMessage(h1 + h2);
|
||||
}
|
||||
|
||||
async hashPassword(password: string): Promise<string> {
|
||||
const salt = await this.hashMessage(`${Math.random()}`);
|
||||
const hash = await this.shittyHmac(password, salt);
|
||||
return `${salt}:${hash}`;
|
||||
}
|
||||
|
||||
async verifyPassword(
|
||||
password: string,
|
||||
passwordHashWithSalt: string,
|
||||
): Promise<boolean> {
|
||||
const [passwordSalt, passwordHash] = passwordHashWithSalt.split(":");
|
||||
return passwordHash === (await this.shittyHmac(password, passwordSalt));
|
||||
}
|
||||
|
||||
async validateCredentials(
|
||||
username: string,
|
||||
password: string,
|
||||
): Promise<boolean> {
|
||||
for (const user of this.users) {
|
||||
if (user.username === username) {
|
||||
return this.verifyPassword(password, user.passwordHashWithSalt);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async login(ctx: any): Promise<void> {
|
||||
const nDays = 90;
|
||||
const maxAgesInSecond = nDays * 24 * 3600;
|
||||
const maxUnixEpoch = Math.floor(Date.now() / 1000) + maxAgesInSecond;
|
||||
|
||||
await ctx.cookies.set("phenix-session", `${maxUnixEpoch}`, {
|
||||
maxAge: maxAgesInSecond,
|
||||
});
|
||||
}
|
||||
|
||||
async isLoggedIn(ctx: any): Promise<boolean> {
|
||||
const expiration = await ctx.cookies.get("phenix-session");
|
||||
if (!expiration || !/^\d+$/.test(expiration)) {
|
||||
return false;
|
||||
}
|
||||
return Date.now() < parseInt(expiration) * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
Deno.test("login service", async (t) => {
|
||||
await t.step("hashing password", async () => {
|
||||
const service = new LoginService([]);
|
||||
const passwordHashWithSalt = await service.hashPassword("qwerty");
|
||||
assert(await service.verifyPassword("qwerty", passwordHashWithSalt));
|
||||
assertFalse(await service.verifyPassword("ytrewq", passwordHashWithSalt));
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user