Skip to content

Commit

Permalink
v.0.7.0
Browse files Browse the repository at this point in the history
  • Loading branch information
guildenstern70 committed Jan 12, 2024
1 parent 617f794 commit a1ea25f
Show file tree
Hide file tree
Showing 20 changed files with 83 additions and 62 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2020-23 Alessio Saltarin
Copyright (c) 2020-24 Alessio Saltarin

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,9 @@ This application is compatible with [Deno Deploy](https://deno.com/deploy) and c
docker build -t smart-deno .
docker run -p 8000:8000 smart-deno

## Version

Version info is stored in `VERSION` and `/src/version.ts` files.



2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.6.0
0.7.0
2 changes: 1 addition & 1 deletion deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
"importMap": "./import_map.json",
"tasks": {
"start": "deno run --allow-net --allow-env --allow-read --unstable src/main.ts"
"start": "deno run --allow-net --allow-env --allow-read --allow-write --unstable src/main.ts"
}
}

14 changes: 8 additions & 6 deletions src/controller/rest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@ export default class RestRouter extends Router
{

private readonly logger: DyeLog;
private readonly denokv: DenoKV;

constructor(logger: DyeLog)
{
super();
this.logger = logger;
this.denokv = new DenoKV(logger);
this.setupRoutes();
}

Expand All @@ -49,8 +47,9 @@ export default class RestRouter extends Router

private getUsers = async (ctx: any) =>
{
const denokv: DenoKV = await DenoKV.Create(this.logger);
this.logger.info("/api/v1/user");
const users: User[]|null = await this.denokv.getAllUsers();
const users: User[]|null = await denokv.getAllUsers();
if (users != null) {
ctx.response.status = Status.OK;
ctx.response.type = "json";
Expand All @@ -72,7 +71,8 @@ export default class RestRouter extends Router
ctx.response.body = {message: "User not found."};
return;
}
const user = await this.denokv.getSingleUser(username);
const denokv: DenoKV = await DenoKV.Create(this.logger);
const user = await denokv.getSingleUser(username);
if (user)
{
ctx.response.status = 200;
Expand All @@ -87,12 +87,13 @@ export default class RestRouter extends Router

private addUser = async (ctx: any) =>
{
const denokv: DenoKV = await DenoKV.Create(this.logger);
const {username, password} = await ctx.request.body().value;
const newUser = {username, password};
this.logger.info("Received " + JSON.stringify(newUser));
if (newUser.username && newUser.password)
{
await this.denokv.createUser(username, password);
await denokv.createUser(username, password);
ctx.response.body = { message: "OK - User inserted with username = " + username };
ctx.response.status = 201;
}
Expand All @@ -113,7 +114,8 @@ export default class RestRouter extends Router
ctx.response.body = {message: "Missing user name."};
return;
}
await this.denokv.deleteUser(username);
const denokv: DenoKV = await DenoKV.Create(this.logger);
await denokv.deleteUser(username);
ctx.response.body = {message: "OK - Deleted user " + username};
ctx.response.status = 200;
};
Expand Down
5 changes: 3 additions & 2 deletions src/controller/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import { Home } from "../page/home.ts";
import { Login } from "../page/login.ts";
import { Features } from "../page/features.ts";
import { Restapi } from "../page/restapi.ts";
import { DyeLog, Router } from "oak";
import { Router } from "oak";
import { DyeLog } from "dyelog";

export default class WebRouter extends Router
{
Expand All @@ -22,7 +23,7 @@ export default class WebRouter extends Router
{
super();
this.logger = logger;
this.setupRoutes().then(this.logger.info("Web routes set up."));
this.setupRoutes();
}


Expand Down
31 changes: 22 additions & 9 deletions src/db/denokv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,38 @@ import { User } from "../model/types.ts";
export class DenoKV
{
private readonly logger: DyeLog;
private kv: Deno.Kv | undefined;

constructor(logger: DyeLog)
public static Create = async (logger: DyeLog): Promise<DenoKV> => {
const me = new DenoKV(logger);
me.kv = await Deno.openKv();
return me;
};

private constructor(logger: DyeLog)
{
this.logger = logger;
}

async isReady(): Promise<boolean>
{
if (this.kv == null) this.kv = await Deno.openKv();
return this.kv != null;
}

async getSingleUser(username: string): Promise<User|null>
{
const kv: Deno.Kv = await Deno.openKv();
if (this.kv == null) this.kv = await Deno.openKv();
console.log("Looking for user " + username + " in Deno KV...");
const user: Deno.KvEntryMaybe<User> = await kv.get(["users", username]);
const user: Deno.KvEntryMaybe<User> = await this.kv.get(["users", username]);
console.log("Retrieved user " + JSON.stringify(user.value));
return user.value;
}

async getAllUsers(): Promise<User[]|null>
{
const kv: Deno.Kv = await Deno.openKv();
const entries: Deno.KvListIterator<User> = kv.list({ prefix: ["users"] });
if (this.kv == null) this.kv = await Deno.openKv();
const entries: Deno.KvListIterator<User> = this.kv.list({ prefix: ["users"] });
if (entries.next == null) return null;
const users: User[] = [];
for await (const entry of entries) {
Expand All @@ -43,13 +56,13 @@ export class DenoKV

async deleteUser(username: string)
{
const kv: Deno.Kv = await Deno.openKv();
await kv.delete(["users", username]);
if (this.kv == null) this.kv = await Deno.openKv();
await this.kv.delete(["users", username]);
}

async createUser(username: string, password: string)
{
const kv: Deno.Kv = await Deno.openKv();
await kv.set(["users", username], { username , password });
if (this.kv == null) this.kv = await Deno.openKv();
await this.kv.set(["users", username], { username , password });
}
}
13 changes: 8 additions & 5 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { Session } from "oak_sessions";
import { DyeLog, LogLevel } from "dyelog";
import RestRouter from "./controller/rest.ts";
import WebRouter from "./controller/web.ts";
import { DenoKV } from "./db/denokv.ts";
import { VERSION } from "./version.ts";

type AppState = {
session: Session
Expand All @@ -28,6 +30,8 @@ const logger = new DyeLog({
level: LogLevel.TRACE
});

logger.info("Welcome to SmartDeno v."+ VERSION);

// Timing (Logger and Response Header)
app.use(async (ctx, next) =>
{
Expand All @@ -44,12 +48,11 @@ app.use(async (ctx, next) =>
});

// Deno KV (Users DB)
const kv = await Deno.openKv();
const denoKvUsers = await kv.get(["users"]);
if (denoKvUsers.value == null) {
const kv = await DenoKV.Create(logger);
if (!(await kv.isReady())) {
logger.info('Deno KV Users DB not found... Creating...');
await kv.set(["users", "guest"], { name: "guest", password: "guest" });
await kv.set(["users", "alessio"], { name: "alessio", password: "doctor" });
await kv.createUser("guest", "guest");
await kv.createUser("alessio", "doctor");
logger.info('Deno KV DB has been initialized.');
}

Expand Down
1 change: 1 addition & 0 deletions src/page/features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class Features extends Page
this.logger.info("GET /features");
this.ctx.response.body = await View.render("./static/templates/features.eta", {
appname: "SmartDeno",
appversion: this.version,
title: "Features",
description: "🦕 SmartDeno has been made with the following building blocks: 🦕",
features: {
Expand Down
1 change: 1 addition & 0 deletions src/page/home.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export class Home extends Page

this.ctx.response.body = await View.render("./static/templates/home.eta", {
appname: "SmartDeno",
appversion: this.version,
appdescription: welcomeMessage,
sessionUser
});
Expand Down
23 changes: 13 additions & 10 deletions src/page/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,28 +75,31 @@ export class Login extends Page

this.ctx.response.body = await View.render("./static/templates/login.eta", {
appname: "SmartDeno",
appversion: this.version,
title: "Contact",
loginerrors: loginErrors,
description: "🦕 SmartDeno has been made by Alessio Saltarin <alessiosaltarin@gmail.com> 🦕"
});
}

private checkLogin(postedUser: User): Promise<boolean>
private async checkLogin(postedUser: User): Promise<boolean>
{

this.logger.info("Got login request with User=" + postedUser.username
+ " and password=" + postedUser.password);

return new Promise((resolve, _reject) =>
const denokv = await DenoKV.Create(this.logger);
const user = await denokv.getSingleUser(postedUser.username);
if (user)
{
const denokv = new DenoKV(this.logger);
denokv.getSingleUser(postedUser.username).then((user: User | null) =>
{
if (user == null) resolve(false);
resolve(user!.password === postedUser.password);
});
});

this.logger.info("User found: " + JSON.stringify(user));
return user.password === postedUser.password;
}
else
{
this.logger.info("User not found");
return false;
}
}

}
5 changes: 4 additions & 1 deletion src/page/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,22 @@
*/

import { DyeLog } from "dyelog";
import { VERSION } from "../version.ts";

export abstract class Page
{

protected ctx: any;
protected logger: DyeLog;
protected version: string;

protected abstract async render(): Promise<void>;
protected abstract render(): Promise<void>;

protected constructor(logger: DyeLog, ctx: any)
{
this.logger = logger;
this.ctx = ctx;
this.version = VERSION;
ctx.response.headers.set("Content-Type", "text/html");
}

Expand Down
4 changes: 2 additions & 2 deletions src/page/restapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { View } from "../view/view.ts";

export class Restapi extends Page
{

constructor(logger: DyeLog, ctx: any)
{
super(logger, ctx);
Expand All @@ -23,7 +22,8 @@ export class Restapi extends Page
{
this.logger.info("GET /restapi");
this.ctx.response.body = await View.render("./static/templates/restapi.eta", {
appname: "SmartDeno"
appname: "SmartDeno",
appversion: this.version
});
}

Expand Down
1 change: 1 addition & 0 deletions src/version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const VERSION = "0.7.0";
2 changes: 1 addition & 1 deletion src/view/layout/layoutview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
*
* Smart Deno
* A web template project for Deno
* Copyright (c) 2020-23 Alessio Saltarin
* Copyright (c) 2020-24 Alessio Saltarin
* MIT License
*
*/
Expand Down
2 changes: 1 addition & 1 deletion src/view/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { render } from "eta";

export class View
{
static async render(etaTemplatePath: string, data: Record<string, string>)
static async render(etaTemplatePath: string, data: object)
{
const html = await View.get(etaTemplatePath);
return render(html, data);
Expand Down
8 changes: 4 additions & 4 deletions static/css/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@ body {

a:link {
text-decoration: none;
color: lightblue;
color: #7d20a6;
}

a:visited {
text-decoration: none;
color: cadetblue;
color: #7d20a6;
}

a:hover {
text-decoration: none;
font-weight: bold;
color: lightgreen;
color: #7d20a6;
}

a:active {
text-decoration: none;
color: hotpink;
color: #7d20a6;
}

.featuresfiller {
Expand Down
13 changes: 1 addition & 12 deletions static/templates/features.eta
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<p class="mt-2 py-3">
<ul class="list-group features">
<% Object.keys(it.features).forEach((f) => { %>
<li class="list-group-item"><a href="<%= it.features[f] %>" target="_blank"><%= f %></a></li>
<li class="list-group-item list-group-item-dark"><a href="<%= it.features[f] %>" target="_blank"><%= f %></a></li>
<% }) %>
</ul>
</p>
Expand All @@ -28,17 +28,6 @@
&nbsp;
</div>
</div>
<div class="row">
<div class="col">
&nbsp;
</div>
<div class="col-8">
&nbsp;
</div>
<div class="col">
&nbsp;
</div>
</div>
<div class="row featuresfiller">
<div class="col">
&nbsp;
Expand Down
2 changes: 1 addition & 1 deletion static/templates/layout.eta
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<% if (it.sessionUser) { %>
You are logged in as <b><%= it.sessionUser %></b>. <a href="/logout">Logout</a>.
<% } else { %>
<%= it.appname %> Powered by
<%= it.appname %> v.<%= it.appversion %> is powered by
<a href="https://deno.land/" target="_blank" class="text-white">Deno</a>.
<% } %>
</div>
Expand Down
Loading

0 comments on commit a1ea25f

Please sign in to comment.