Blog Engine with Fresh: Authenticating User
Tags: javascript, webdev, react, fresh
Published: 2022-08-09 05:57:00

{% embed https://dev.to/sokhavuth/table-of-contents-41pd %}
GitHub: [https://github.com/Sokhavuth/deno-fresh](https://github.com/Sokhavuth/deno-fresh)
Deno Deploy: [https://khmerweb-fresh.deno.dev/login](https://khmerweb-fresh.deno.dev/login)
<br/>

```js
// routes/login.jsx

/** @jsx h */
import { h } from "preact";
import VLogin from '../components/front/login.jsx';
import CLogin from "../controllers/front/login.js";


export const handler = {
  async GET(req, ctx){
      return await CLogin.getForm(req, ctx);
  },  

  async POST(req, ctx){
      return await CLogin.checkUser(req, ctx);
  },
}


export default function Template(props){
    return (
        <VLogin data={props.data} />
    )
}
```

```js
// controllers/front/login.js

import { setCookie, getCookies, deleteCookie } from "cookies";
import { setting, secret_key, myredis } from 'setting';
import { create, verify, getNumericDate } from "jwt";
import userdb from "../../models/user.ts";
import { bcrypt } from "bcrypt";


class Login{
    async getForm(req, ctx){
        const cookies = getCookies(req.headers);

        if((cookies)&&(cookies.session_id)){
            const jwt = await myredis.get(cookies.session_id);
            try{
                const payload = await verify(jwt, secret_key, "HS512");
                if(payload.user){
                    return new Response(undefined, { headers: {location: `/admin/post`}, status: 302 });
                }
            }catch(error){
                console.log(error);
                const config = setting();
                config.page_title = "Login Page";
                const resp = new Response();
                deleteCookie(resp.headers, "session_id");
                return await ctx.render({"setting": config});
            }
        }   

        const config = setting();
        config.page_title = "Login Page";
        return await ctx.render({"setting": config});
    }

    async checkUser(req, ctx){
        const formData = await req.formData();
    
        const user = await userdb.checkUser(formData.get("email"));
        
        if(user){
            if(user.role in {'Admin':1,'Editor':1,'Author':1,"Guest":1}){
                if(await bcrypt.compareSync(formData.get("password"), user.password)){
                    const payload = { 
                        user: user, 
                        exp: getNumericDate(60 * 60 * 24), 
                    };
                    const jwt = await create({ alg: "HS512", typ: "JWT" }, payload, secret_key);
                    const resp = new Response(undefined, { headers: {location: `/admin/post`}, status: 302 });
                    const random_id = crypto.randomUUID();
                    await myredis.set(`${random_id}`, jwt, {ex: 60 * 60 * 24});
                    setCookie(resp.headers, { name: "session_id", value: `${random_id}` });
                    return resp;
                }else{
                    const config = setting();
                    config.page_title = "Login Page";
                    config.message = "The password is wrong!";
                    return await ctx.render({"setting": config});
                }
            }else{
                const config = setting();
                config.page_title = "Login Page";
                config.message = "You are not registered yet";
                return await ctx.render({"setting": config});
            }
        }else{
            const config = setting();
            config.page_title = "Login Page";
            config.message = "The email is wrong!";
            return await ctx.render({"setting": config});
        }    
    }
}

export default new Login();
```

```js
// models/user.ts

import { mydb } from "setting";
import { bcrypt } from "bcrypt";

interface UserSchema {
    _id: ObjectId;
    id: string; 
    title: string;
    content: string;
    thumb: string;
    date: string;
    role: string;
    email: string;
    password: string;
}

class User{
    async createRootUser(){
        const id = crypto.randomUUID();
        const salt = await bcrypt.genSalt(8);
        const hashPassword = bcrypt.hashSync('xxxxxxxxxxxxxxxxxx', salt);
        const newUser = {
            id: id, 
            title: 'Guest',
            content: '',
            thumb: '',
            date: '',
            role: 'Guest',
            email: 'guest@khmerweb.app',
            password: hashPassword,
        }
     
        const users = mydb.collection<UserSchema>("users");
        await users.insertOne(newUser);
    }

    async checkUser(email: string){
        const users = mydb.collection<UserSchema>("users");
        return await users.findOne({email: email});
    }
}

export default new User();
```