Skip to content

Commit

Permalink
Merge branch 'feature/auth'
Browse files Browse the repository at this point in the history
  • Loading branch information
arackaf committed Dec 23, 2022
2 parents 34b07c4 + 7447b4b commit c5dc051
Show file tree
Hide file tree
Showing 17 changed files with 3,111 additions and 159 deletions.
2,883 changes: 2,753 additions & 130 deletions svelte-kit/package-lock.json

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions svelte-kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
"devDependencies": {
"@sveltejs/adapter-auto": "next",
"@types/blueimp-md5": "^2.18.0",
"@types/d3-array": "^3.0.3",
"@types/d3-scale": "^4.0.2",
"@types/lodash.debounce": "^4.0.7",
Expand All @@ -26,8 +27,14 @@
},
"type": "module",
"dependencies": {
"@auth/core": "^0.1.4",
"@auth/sveltekit": "^0.1.6",
"@aws-sdk/client-dynamodb": "^3.199.0",
"@aws-sdk/lib-dynamodb": "^3.199.0",
"@next-auth/dynamodb-adapter": "^1.0.5",
"@popperjs/core": "^2.11.6",
"@sveltejs/kit": "^1.0.1",
"blueimp-md5": "2.3.0",
"classnames": "^2.3.2",
"d3-array": "1.2.0",
"d3-axis": "1.0.8",
Expand Down
58 changes: 58 additions & 0 deletions svelte-kit/src/data/dynamoHelpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import AWS from "aws-sdk";

import { env } from "$env/dynamic/private";
export const TABLE_NAME = env.BOOKLIST_DYNAMO;

export const getGetPacket = (pk, sk, rest = {}) => ({ TableName: TABLE_NAME, Key: { pk, sk }, ...rest });
export const getQueryPacket = (keyExpression, rest = {}) => ({
TableName: TABLE_NAME,
KeyConditionExpression: keyExpression,
...rest
});
export const getPutPacket = (obj, rest = {}) => ({ TableName: TABLE_NAME, Item: obj, ...rest });
export const getUpdatePacket = (pk, sk, rest) => ({ TableName: TABLE_NAME, Key: { pk, sk }, ...rest });

const dynamo = new AWS.DynamoDB.DocumentClient({
region: "us-east-1"
});

export { dynamo };

export const db = {
async put(packet) {
await dynamo.put(packet).promise();
},

async get(packet) {
let result = await dynamo.get(packet).promise();
return result.Item || null;
},

async queryOne(packet) {
let res = await dynamo.query(packet).promise();

if (!res || !res.Items || !res.Items[0]) {
return null;
}

return res.Items[0];
},

async pagedQuery(packet) {
let result = await dynamo.query(packet).promise();

return { items: result.Items || null, lastEvaluatedKey: result.LastEvaluatedKey };
},

async update(packet) {
return dynamo.update(packet).promise();
},

async transactWrite(packet) {
return dynamo.transactWrite(packet).promise();
},

async deleteItem(pk, sk) {
return dynamo.delete({ TableName: TABLE_NAME, Key: { pk, sk } }).promise();
}
};
65 changes: 65 additions & 0 deletions svelte-kit/src/data/legacyUser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import md5 from "blueimp-md5";
import { env } from "$env/dynamic/private";

import { db, getQueryPacket, getPutPacket } from "./dynamoHelpers";

const getUserAliasKey = (userId: string) => `UserAlias#${userId}`;

const salt = env.SALT;

export async function lookupUser(email: string, password: string) {
email = email.toLowerCase();
password = saltAndHashPassword(password);
const userKey = `User#${email}`;

try {
let userFound = await db.queryOne(
getQueryPacket(` pk = :userKey AND sk = :userKey `, {
ExpressionAttributeValues: { ":password": password, ":userKey": userKey, ":true": true },
FilterExpression: ` password = :password AND awaitingActivation <> :true `
})
);

if (!userFound) {
return null;
}

const id = userFound.userId;

return {
id
};
} catch (loginErr) {
console.log("Login error", loginErr);
return null;
}
}

export async function syncUser(newId: string, legacyId: string) {
const userSync = {
pk: getUserAliasKey(newId),
sk: legacyId
};

db.put(getPutPacket(userSync));
}

export async function getUserSync(userId: string) {
const key = getUserAliasKey(userId);

try {
const syncEntry = await db.queryOne(
getQueryPacket(` pk = :key `, {
ExpressionAttributeValues: { ":key": key }
})
);

return syncEntry;
} catch (er) {
return null;
}
}

function saltAndHashPassword(password: string) {
return md5(`${salt}${password}${salt}`);
}
71 changes: 70 additions & 1 deletion svelte-kit/src/hooks.server.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,78 @@
import { sequence } from "@sveltejs/kit/hooks";
import SvelteKitAuth from "@auth/sveltekit";
import GoogleProvider from "@auth/core/providers/google";
import { GOOGLE_AUTH_CLIENT_ID, GOOGLE_AUTH_SECRET, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, DYNAMO_AUTH_TABLE } from "$env/static/private";

import { DynamoDB, type DynamoDBClientConfig } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocument } from "@aws-sdk/lib-dynamodb";
import { DynamoDBAdapter } from "@next-auth/dynamodb-adapter";
import { getUserSync } from "$data/legacyUser";

const dynamoConfig: DynamoDBClientConfig = {
credentials: {
accessKeyId: AWS_ACCESS_KEY_ID,
secretAccessKey: AWS_SECRET_ACCESS_KEY
},

region: "us-east-1"
};

const client = DynamoDBDocument.from(new DynamoDB(dynamoConfig), {
marshallOptions: {
convertEmptyValues: true,
removeUndefinedValues: true,
convertClassInstanceToMap: true
}
});

const auth = SvelteKitAuth({
providers: [
GoogleProvider({
clientId: GOOGLE_AUTH_CLIENT_ID,
clientSecret: GOOGLE_AUTH_SECRET
})
],
session: {
maxAge: 60 * 60 * 24 * 365,
strategy: "jwt"
},

secret: process.env.NEXTAUTH_SECRET,

// adapter: DynamoDBAdapter(client, { tableName: DYNAMO_AUTH_TABLE }) as any

callbacks: {
async signIn({ account }) {
(account as any).overridden = "HELLO";

if (account == null) {
return false;
}

const userSync = await getUserSync(account.providerAccountId);
console.log({ userSync });

return true;
},
async jwt({ token, account }) {
token.userId ??= account?.providerAccountId;
return token;
},
async session({ session, user, token }) {
(session as any).userId = token.userId;
return session;
}
}
});

const PRELOAD = new Set(["font", "js", "css"]);

export async function handle({ event, resolve }: any) {
export async function preload({ event, resolve }: any) {
const response = await resolve(event, {
preload: ({ type }: any) => PRELOAD.has(type)
});

return response;
}

export const handle = sequence(preload, auth);
32 changes: 14 additions & 18 deletions svelte-kit/src/lib/components/navigation/MainNavigation.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
import { page } from "$app/stores";
import { signIn, signOut } from "@auth/sveltekit/client";
import NavBarItem from "./NavBarItem.svelte";
import ModuleLink from "./ModuleLink.svelte";
Expand All @@ -15,20 +16,15 @@
import "./mobile-menu.scss";
import { onMount } from "svelte";
$: currentModule = $page.route.id;
$: ({ loggedIn } = $page.data);
const logout = () => {};
// const logout = () => {
// ajaxUtil.postAuth("/logout", {}, () => ((window as any).location = "/"));
// };
$: currentModule = $page.route.id;
//let isAdminUser = isAdmin();
let isAdminUser = false;
//$: isLoginModule = currentModule == 'authenticate';
let isLoginModule = false;
//$: isLoggedIn = $appState.isLoggedIn;
let isLoggedIn = true;
//$: isPublic = $appState.isPublic;
let isPublic = false;
Expand All @@ -50,7 +46,7 @@

<header class="master-nav">
<nav class="nav">
<div class={`nav-header hidden-xs ${isHome && isLoggedIn ? "active" : ""}`}>
<div class={`nav-header hidden-xs ${isHome && loggedIn ? "active" : ""}`}>
<ModuleLink href="/home">
<BookSvg height="18" style="margin-right: 10px; color: white; fill: var(--primary-10);" />
<span>My Library</span>
Expand All @@ -61,7 +57,7 @@
<NavBarItem class="visible-xs" disabled={isPublic} href="/home" style="margin-top: '2px';">
<i class="fal fa-fw fa-home visible-xs" />
</NavBarItem>
{#if isLoggedIn || isPublic}
{#if loggedIn || isPublic}
<NavBarItem disabled={isPublic} href="/scan" style="position: relative;">
<span class="hidden-xs">Book entry</span>
<i class="visible-xs fal fa-fw fa-scanner" />
Expand All @@ -75,48 +71,48 @@
{/if}
</NavBarItem>
{/if}
{#if isLoggedIn || isPublic}
{#if loggedIn || isPublic}
<NavBarItem href={isPublic ? "/view" : "/books"}
><span class="hidden-xs">Books</span>
<i class="visible-xs fal fa-fw fa-books" />
</NavBarItem>
{/if}
{#if isLoggedIn || isPublic}
{#if loggedIn || isPublic}
<NavBarItem disabled={isPublic} href="/subjects">
<span class="hidden-xs">Subjects</span>
<i class="visible-xs fal fa-fw fa-sitemap" />
</NavBarItem>
{/if}
{#if isLoggedIn || isPublic}
{#if loggedIn || isPublic}
<NavBarItem href="/settings"
><span class="hidden-xs">Settings</span>
<i class="visible-xs fal fa-fw fa-cogs" />
</NavBarItem>
{/if}
{#if isLoggedIn || isPublic}
{#if loggedIn || isPublic}
<NavBarItem href="/intro"
><span class="hidden-xs">Intro</span>
<i class="visible-xs fal fa-fw fa-cogs" />
</NavBarItem>
{/if}
{#if isLoggedIn && isAdminUser}
{#if loggedIn && isAdminUser}
<NavBarItem href="/admin">
<span class="hidden-xs">Admin</span>
<i class="visible-xs fal fa-fw fa-users-cog" />
</NavBarItem>
{/if}
</ul>
<ul class="nav-items-right">
{#if !isLoggedIn && !isLoginModule}
<NavBarItem href="/login">
{#if !loggedIn && !isLoginModule}
<NavBarItem onClick={() => signIn("google")}>
<span class="hidden-xs">Login</span>
<i class="visible-xs fal fa-fw fa-sign-in" />
</NavBarItem>
{/if}
</ul>
{#if isLoggedIn}
{#if loggedIn}
<ul class="nav-items-right">
<NavBarItem href="/logout">
<NavBarItem onClick={signOut}>
<span class="hidden-xs">Logout</span>
<i class="visible-xs fal fa-fw fa-sign-out" />
</NavBarItem>
Expand Down
12 changes: 11 additions & 1 deletion svelte-kit/src/lib/components/navigation/ModuleLink.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@
export let href: string;
export let style = "";
export let disabled = false;
export let onClick: (() => void) | null = null;
const linkClicked = (evt: any) => {
if (!onClick) {
return;
}
evt.preventDefault();
onClick();
};
</script>

<a href={disabled ? null : href} {style}>
<a on:click={linkClicked} href={disabled ? null : href} {style}>
<slot />
</a>
5 changes: 3 additions & 2 deletions svelte-kit/src/lib/components/navigation/NavBarItem.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
export let disabled = false;
let className = "";
export { className as class };
export let onClick: (() => void) | null = null;
$: currentModule = $page.route.id;
$: active = currentModule?.indexOf(href) !== -1;
$: active = href && currentModule?.indexOf(href) !== -1;
const spreadClassNames = (baseCssClasses = "", ...userClasses: string[]) => `${baseCssClasses} ${userClasses.join(" ")}`;
</script>

<li class={spreadClassNames(className || "", !!disabled ? "disabled" : "", active ? "active" : "")}>
<ModuleLink {style} {href}>
<ModuleLink {onClick} {style} {href}>
<slot />
</ModuleLink>
</li>
10 changes: 9 additions & 1 deletion svelte-kit/src/routes/(logged-in)/+layout.server.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { redirect } from "@sveltejs/kit";

import { allSubjects } from "$data/subjects";
import { allTags } from "$data/tags";

export function load() {
export async function load({ parent, locals }: any) {
const session = await locals.getSession();

if (!session?.user) {
throw redirect(302, "/");
}

const subjects = allSubjects();
const tags = allTags();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@
//const { queryState } = query(barCharQuery, { initialSearch: { subjectIds, searchChildSubjects: true, publicUserId: "" } });
$: graphData = stackGraphData(subjectHash, subjectIds, books, chartIndex > 0);
$: {
console.log({ chartIndex, books, subjectIds, graphData });
}
const margin = { top: 30, right: 20, bottom: 180, left: 20 };
</script>
Expand Down
Loading

0 comments on commit c5dc051

Please sign in to comment.