Lots of changes:

- Switching build system to pure rollup without too much custom logic
- Restructuring files
- Adding Popup View
- Make everything typescript compatible
- Adding @hibas123/theme
- Start switching to @hibas123/theme
This commit is contained in:
Fabian Stamm
2020-11-03 23:22:24 +01:00
parent 4191522b24
commit 8e4c292959
50 changed files with 4554 additions and 3145 deletions

View File

@ -1,7 +0,0 @@
import App from "./App.svelte";
var app = new App({
target: document.getElementById("content"),
});
export default app;

View File

@ -1,7 +0,0 @@
import App from "./App.svelte";
var app = new App({
target: document.getElementById("content"),
});
export default app;

View File

@ -1,7 +0,0 @@
import App from "./App.svelte";
var app = new App({
target: document.getElementById("content"),
});
export default app;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,90 @@
<script lang="ts">
// import { Tile } from "carbon-components-svelte";
export let title: string;
export let loading = false;
export let hide = false;
</script>
<style>
.wrapper {
min-height: 100vh;
width: 100vw;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
box-sizing: border-box;
}
.container {
border-radius: 4px;
position: relative;
padding-top: 2.5rem;
min-height: calc(100px + 2.5rem);
min-width: 100px;
margin-top: 3rem;
}
.title-container {
margin: -4.8rem auto 0 auto;
max-width: 250px;
background-color: var(--primary);
color: white;
border-radius: 4px;
/* padding: 5px 20px; */
}
.title-container > h1 {
font-size: 2rem;
line-height: 1;
}
.content-container {
padding: 2em;
margin: 0 auto;
max-width: 380px;
overflow: hidden;
}
.loading_container {
filter: blur(1px) opacity(50%);
}
.loader_container {
position: absolute;
display: flex;
flex-direction: column;
justify-content: center;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 2;
}
</style>
<div class="wrapper">
<div class="card-elevated container">
<!-- <div class="container card"> -->
<div class="card elv-8 title-container">
<h1 style="margin:0">{title}</h1>
</div>
{#if loading}
<div class="loader_container">
<div class="loader_box">
<div class="loader" />
</div>
</div>
{/if}
<div class="content-container" class:loading_container={loading}>
{#if !(loading && hide)}
<slot />
{/if}
</div>
<!-- </div> -->
</div>
</div>

View File

@ -0,0 +1,15 @@
<script lang="ts">
// import { onMount, afterUpdate, setContext } from "svelte";
// import { writable, derived } from "svelte/store";
// type Theme = "white" | "g10" | "g90" | "g100";
// export let persist: boolean = false;
// export let persistKey: string = "theme";
export let dark = false;
</script>
<div class={dark ? 'dark-theme' : 'light-theme'}>
<slot />
</div>

View File

@ -0,0 +1,42 @@
import "@hibas123/theme/out/base.css";
import "./theme.css";
import { default as Theme } from "./Theme.svelte";
(() => {
const elements = new WeakSet();
function check() {
document
.querySelectorAll(".floating>input")
.forEach((e: HTMLInputElement) => {
if (elements.has(e)) return;
elements.add(e);
function checkState() {
console.log("Check State");
if (e.value !== "") {
if (e.classList.contains("used")) return;
e.classList.add("used");
} else {
if (e.classList.contains("used")) e.classList.remove("used");
}
}
e.addEventListener("change", () => checkState());
checkState();
});
}
const observer = new MutationObserver((mutations) => {
check();
});
// Start observing the target node for configured mutations
observer.observe(window.document, {
childList: true,
subtree: true,
});
check();
})();
export default Theme;

View File

@ -21,6 +21,9 @@ body {
background: #eee;
height: 100%;
font-size: var(--default-font-size);
min-width: 100vw;
min-height: 100vh;
box-sizing: border-box;
}
.group {

View File

@ -1,34 +0,0 @@
(() => {
const elements = new WeakSet();
function check() {
document.querySelectorAll(".floating>input").forEach((e) => {
if (elements.has(e)) return;
elements.add(e);
function checkState() {
console.log("Check State");
if (e.value !== "") {
if (e.classList.contains("used")) return;
e.classList.add("used");
} else {
if (e.classList.contains("used")) e.classList.remove("used");
}
}
e.addEventListener("change", () => checkState());
checkState();
});
}
const observer = new MutationObserver((mutations) => {
check();
});
// Start observing the target node for configured mutations
observer.observe(window.document, {
childList: true,
subtree: true,
});
check();
})();

View File

@ -1,7 +1,5 @@
import { getCookie } from "./cookie";
// const baseURL = "https://auth.stamm.me";
// const baseURL = "http://localhost:3000";
const baseURL = "";
export default async function request(

8
src/pages/Home/main.ts Normal file
View File

@ -0,0 +1,8 @@
import "../../components/theme";
import App from "./App.svelte";
new App({
target: document.body,
});
export default app;

View File

@ -1,4 +1,6 @@
<script>
import Theme from "../../components/theme";
import HoveringContentBox from "../../components/HoveringContentBox.svelte";
import Api from "./api.ts";
import Credentials from "./Credentials.svelte";
import Redirect from "./Redirect.svelte";
@ -9,7 +11,7 @@
const states = {
credentials: 1,
twofactor: 3,
redirect: 4
redirect: 4,
};
let username = Api.getUsername();
@ -95,41 +97,6 @@
</script>
<style>
.card {
box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
background: #fafafa;
border-radius: 4px;
}
.form-container {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
box-sizing: border-box;
}
form {
width: 100%;
max-width: 380px;
margin: 0 auto;
box-shadow: 0 19px 38px rgba(0, 0, 0, 0.3), 0 15px 12px rgba(0, 0, 0, 0.22);
position: relative;
padding: 1px;
background-color: white !important;
margin-bottom: 40px;
}
.container {
overflow: hidden;
padding: 2em;
}
button {
margin-top: 16px;
}
footer {
text-align: center;
position: absolute;
@ -137,63 +104,21 @@
left: 0;
right: 0;
}
.floating {
margin-top: 8px;
}
h3 {
font-weight: 200;
}
.title-container {
margin: -30px auto 0 auto;
max-width: 250px;
background-color: var(--primary);
color: white;
padding: 5px 20px;
}
.loading_container {
filter: blur(1px) opacity(50%);
}
.loader_container {
position: absolute;
display: flex;
flex-direction: column;
justify-content: center;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 2;
}
</style>
<div class="form-container">
<form action="JavaScript:void(0)" class="card">
<div class="card title-container">
<h1>Login</h1>
</div>
{#if loading}
<div class="loader_container">
<div class="loader_box">
<div class="loader" />
</div>
</div>
{/if}
<div class="container" class:loading_container={loading}>
<Theme>
<HoveringContentBox title="Login" {loading}>
<form action="JavaScript:void(0)">
{#if state === states.redirect}
<Redirect />
{:else if state === states.credentials}
<Credentials next={afterCredentials} setLoading={s => (loading = s)} />
<Credentials next={afterCredentials} setLoading={(s) => (loading = s)} />
{:else if state === states.twofactor}
<Twofactor finish={afterTwoFactor} setLoading={s => (loading = s)} />
<Twofactor finish={afterTwoFactor} setLoading={(s) => (loading = s)} />
{/if}
</div>
</form>
</div>
<footer>
<p>Powered by {appname}</p>
</footer>
</form>
</HoveringContentBox>
<footer>
<p>Powered by {appname}</p>
</footer>
</Theme>

View File

@ -47,8 +47,7 @@
padding: 4px;
}
.btn {
background-color: var(--primary);
.wide-button {
width: 100%;
margin: 0;
}
@ -82,4 +81,4 @@
</div>
{/if}
<button class="btn" on:click={buttonClick}>Next</button>
<button class="btn btn-primary wide-button" on:click={buttonClick}>Next</button>

View File

@ -1,6 +1,6 @@
import request from "../request";
import sha from "../sha512";
import { setCookie, getCookie } from "../cookie";
import request from "../../helper/request";
import sha from "../../helper/sha512";
import { setCookie, getCookie } from "../../helper/cookie";
export interface TwoFactor {
id: string;

View File

Before

Width:  |  Height:  |  Size: 992 B

After

Width:  |  Height:  |  Size: 992 B

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 927 B

After

Width:  |  Height:  |  Size: 927 B

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

5
src/pages/Login/main.ts Normal file
View File

@ -0,0 +1,5 @@
import App from "./App.svelte";
new App({
target: document.body,
});

View File

@ -1,9 +1,9 @@
<script>
import Cleave from "../../cleave";
import Cleave from "cleave.js";
import { onMount } from "svelte";
export let error;
export let label;
// export let label;
export let value;
export let length = 6;
@ -12,7 +12,7 @@
const cleaveCustom = new Cleave(input, {
blocks: [length / 2, length / 2],
delimiter: " ",
numericOnly: true
numericOnly: true,
});
});
</script>
@ -25,9 +25,9 @@
</style>
<div class="floating group">
<input bind:this={input} autofocus bind:value />
<input id="noasidhglk" bind:this={input} autofocus bind:value />
<span class="highlight" />
<span class="bar" />
<label>Code</label>
<label for="noasidhglk">Code</label>
<div class="error" style={!error ? 'display: none;' : ''}>{error}</div>
</div>

View File

@ -33,8 +33,7 @@
align-items: center;
}
.btn {
background-color: var(--primary);
.btn-next {
margin: 0;
margin-left: auto;
min-width: 80px;
@ -47,7 +46,5 @@
<div class="actions">
<ToList {finish} />
<button class="btn" style="margin-left: auto" on:click={sendCode}>
Send
</button>
<button class="btn btn-primary btn-next" on:click={sendCode}> Send </button>
</div>

View File

@ -4,7 +4,7 @@
let error = "";
let code = "";
export let device = "Handy01";
export let deviceId = "";
// export let deviceId = "";
export let finish;
@ -365,10 +365,7 @@
<h3>SMS</h3>
<p>
A code was sent to your Device
<b>{device}</b>
</p>
<p>A code was sent to your Device <b>{device}</b></p>
<div class="windows8">
<div class="wBall" id="wBall_1">

View File

@ -3,7 +3,7 @@
const states = {
approve: 1,
enter: 2
enter: 2,
};
let state = states.approve;
@ -34,11 +34,11 @@
<h3>SMS</h3>
{#if state === states.approve}
<p>Send SMS to {number}</p>
<button class="btn" on:click={sendCode}>Send</button>
<button class="btn btn-primary" on:click={sendCode}>Send</button>
{:else}
<p>A code was sent to you. Please enter</p>
<input type="number" placeholder="Code" bind:value={code} />
<button on:click={validateCode}>Send</button>
<button class="btn btn-primary" on:click={validateCode}>Send</button>
<br />
<a href="# " on:click|preventDefault={() => (state = states.approve)}>
Not received?

View File

@ -6,6 +6,7 @@
a {
color: var(--primary);
text-decoration: none;
margin-right: 1rem;
}
</style>

View File

@ -0,0 +1,59 @@
<script lang="ts">
import HoveringContentBox from "../../components/HoveringContentBox.svelte";
import Theme from "../../components/theme/Theme.svelte";
export let loading = true;
export let appName = "";
export let permissions: any[] = [];
export let accept: () => void;
const base_perm = {
name: "Access Profile",
description:
"Access your identity and some basic informations like your username",
};
$: view_perms = [base_perm, ...permissions];
$: console.log({ loading, appName, permissions, accept });
function deny() {
window.close();
}
</script>
<style>
.permission > h3 {
}
.permission > p {
}
</style>
<Theme dark={false}>
<HoveringContentBox title="Authorize" {loading} hide>
<div class="title margin">
<h2 style="font-weight: normal">
Grant
<span id="hostname" style="font-weight: bold;">{appName}</span>
the following permissions?
</h2>
</div>
<ul class="list list-divider">
{#each view_perms as permission (permission._íd)}
<li class="permission">
<h3>{permission.name}</h3>
<p>{permission.description}</p>
</li>
{/each}
</ul>
<div>
<div style="text-align: right;">
<button class="btn btn-primary" on:click={accept}>Allow</button>
<button class="btn btn-primary" on:click={deny}>Deny</button>
</div>
</div>
</HoveringContentBox>
</Theme>

0
src/pages/Popup/api.ts Normal file
View File

146
src/pages/Popup/main.ts Normal file
View File

@ -0,0 +1,146 @@
import "../../components/theme";
import App from "./App.svelte";
import request from "../../helper/request";
interface IPermission {
_id: string;
name: string;
description: string;
}
let loading = true;
let appName: string;
let permissions: IPermission[] = [];
let accept: () => void;
const app = new App({
target: document.body,
props: { loading },
});
const setLoading = (_loading: boolean) => {
loading = _loading;
app.$set({ loading });
};
const setAppName = (_appName: string) => {
appName = _appName;
app.$set({ appName });
};
const setPermissions = (_permissions: IPermission[]) => {
permissions = _permissions;
app.$set({ permissions });
};
const setAccept = (_accept: () => void) => {
accept = _accept;
app.$set({ accept });
};
async function getJWT(client_id: string, origin: string) {
origin = encodeURIComponent(origin);
client_id = encodeURIComponent(client_id);
const res = await request(`/api/user/oauth/jwt`, {
client_id,
origin,
}).then((res) => res.json());
return res;
}
async function getRefreshToken(
client_id: string,
origin: string,
permissions: string[]
) {
origin = encodeURIComponent(origin);
client_id = encodeURIComponent(client_id);
const perm = permissions.map((e) => encodeURIComponent(e)).join(",");
const res = await request(`/api/user/oauth/refresh_token`, {
client_id,
origin,
permissions: perm,
});
return res;
}
let started = false;
async function onMessage(msg: MessageEvent<any>) {
const sendResponse = (data: any) => {
try {
console.log("Sending response:", data);
(msg.source.postMessage as any)(data, msg.origin);
} catch (err) {
alert("Something went wrong, please try again later!");
}
};
console.log("Received message", msg, started);
if (!started) {
started = true;
const url = new URL(msg.origin);
setAppName(url.hostname);
try {
if (!msg.data.type || msg.data.type === "jwt") {
console.log("JWT Request");
await new Promise((yes) => {
console.log("Await user acceptance");
setLoading(false);
setAccept(yes);
});
console.log("User has accepted");
const res = await getJWT(msg.data.client_id, url.hostname);
sendResponse(res);
} else if (msg.data.type === "refresh") {
console.log("RefreshToken Request");
let permissions = msg.data.permissions || [];
let permissions_resolved = [];
if (permissions.length > 0) {
permissions_resolved = await request(
"/api/user/oauth/permissions",
{
client_id: msg.data.client_id,
origin: url.hostname,
permissions: permissions.join(","),
}
).then(({ permissions }) => permissions);
}
await new Promise((yes) => {
console.log("Await user acceptance");
setLoading(false);
setPermissions(permissions_resolved);
setAccept(yes);
});
console.log("User has accepted");
const res = await getRefreshToken(
msg.data.client_id,
url.hostname,
permissions
);
sendResponse(res);
}
} catch (err) {
sendResponse({ error: true, message: err.message });
}
window.close();
}
}
setTimeout(() => {
if (!started) {
console.log("No authentication request received!");
alert(
"The site requesting the login does not respond. Please try again later"
);
}
}, 10000);
window.addEventListener("message", onMessage);

View File

@ -3,7 +3,7 @@
import BoxItem from "./BoxItem.svelte";
import NextIcon from "./NextIcon.svelte";
import request from "../../request.ts";
import request from "../../../helper/request.ts";
export let loading = false;
let account_error = undefined;
@ -67,8 +67,8 @@
true
);
email = contact.mails.map(e => e.mail);
phone = contact.phones.map(e => e.phone);
email = contact.mails.map((e) => e.mail);
phone = contact.phones.map((e) => e.phone);
contact_error = undefined;
} catch (err) {
console.error(err);
@ -154,10 +154,14 @@
<BoxItem name="Name" value={name}>
<div class="input-container">
<div class="floating group">
<input type="text" autocomplete="username" bind:value={name} />
<input
id="name-inp"
type="text"
autocomplete="username"
bind:value={name} />
<span class="highlight" />
<span class="bar" />
<label>Name</label>
<label for="name-inp">Name</label>
</div>
<button class="btn" on:click={saveName}>Save</button>
</div>

View File

@ -10,7 +10,7 @@
import Box from "./Box.svelte";
import BoxItem from "./BoxItem.svelte";
import NextIcon from "./NextIcon.svelte";
import request from "../../request.ts";
import request from "../../../helper/request.ts";
export let loading = false;
@ -181,9 +181,7 @@
Revoke
</button>
</BoxItem>
{:else}
<span>No Tokens</span>
{/each}
{:else}<span>No Tokens</span>{/each}
<!-- <BoxItem name="E-Mail" value={email} />
<BoxItem name="Phone" value={phone} /> -->

6
src/pages/User/main.ts Normal file
View File

@ -0,0 +1,6 @@
import "../../components/theme";
import App from "./App.svelte";
new App({
target: document.body,
});

View File

@ -1,6 +0,0 @@
{
"compilerOptions": {
"module": "esnext",
"sourceMap": true
}
}