ajout de commentaires au code.

This commit is contained in:
bruno 2022-08-10 01:59:10 -04:00
parent eca736bba6
commit 67f571860e
14 changed files with 306 additions and 30 deletions

View File

@ -1 +1,6 @@
# --==--==--==--==--==--==--==--==--==--==-- #
# All configuration are inside the file:
# ==> config.nims
#
nim c -r main.nim
# --==--==--==--==--==--==--==--==--==--==-- #

View File

@ -1,4 +1,13 @@
# Copyright 2019 - Thomas T. Jarløv
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# Bruno Charest
# 2022-08-09
#
# __ DESCRIPTIONS __
# database_utils : procedure related to database
#
# Inspiration of : https://ttj.dk/blog/2019/01/20/setup-a-website-with-nim
# Copyright 2019 - Thomas T. Jarløv
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# import db_sqlite, os, parsecfg, strutils, logging
import db_sqlite, os, parsecfg, logging

View File

@ -1,3 +1,12 @@
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# Bruno Charest
# 2022-08-09
#
# __ DESCRIPTIONS __
# joplin_json_utils : Types and procedure related to json request
#
# [TODO] joplin_json_utils : need to create many procedures
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# Data structure for TAGS
type Tag = object

View File

@ -1,10 +1,24 @@
import std/[asyncdispatch, httpclient]
import std/json
import std/options
import strformat
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# Bruno Charest
# 2022-08-09
#
# __ DESCRIPTIONS __
# joplin_utils : procedure related joplin application
#
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
import net
import times
import osproc
import jester
import std/json
import httpcore
import strutils
import strformat
import std/options
from os import sleep
import httpcore, net, times, strutils
import std/[asyncdispatch, httpclient]
# Setup joplin_ping data
type
@ -224,6 +238,58 @@ proc get_joplin_tags*(token:string): Future[joplin_tags] {.async.} =
return j_tags
# get the token from Joplin Terminal
proc get_joplin_cli_token*(): string =
var flagName: string = ""
var flagValue: string = ""
var result = execCmdEx("joplin config api.token")
if result.exitCode == 0:
let param1 = result.output
let flagSplit = param1.split(" = ")
flagName = flagSplit[0]
flagValue = flagSplit[1]
return flagValue
# start Joplin Terminal
proc joplin_cli_start*(): bool =
var rc = false
var result = execCmdEx("joplin server start &")
if result.exitCode == 0:
echo result.output
rc = true
else:
rc = false
return rc
# check Joplin Terminal staus
proc joplin_cli_status*(): bool =
var rc = false
var result = execCmdEx("joplin server status")
if result.exitCode == 0:
echo result.output
rc = true
else:
rc = false
return rc
# stop Joplin Terminal
proc joplin_cli_stop*(): bool =
var rc = false
var result = execCmdEx("joplin server stop")
if result.exitCode == 0:
echo result.output
rc = true
else:
rc = false
return rc
# proc get_joplin_tags_json*(token:string): Future[] {.async.} =

View File

@ -1,8 +1,18 @@
# Copyright 2019 - Thomas T. Jarløv
# Credit Nimforum - https://github.com/nim-lang/nimforum
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# Bruno Charest
# 2022-08-09
#
# __ DESCRIPTIONS __
# password_utils : procedure related password
#
# Inspiration of : https://ttj.dk/blog/2019/01/20/setup-a-website-with-nim
# Copyright 2019 - Thomas T. Jarløv
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# import md5, bcrypt, math, random, os
import md5, bcrypt, random
import md5
import bcrypt
import random
randomize()
var urandom: File

View File

@ -1,10 +1,26 @@
import joplin_utils
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# Bruno Charest
# 2022-08-09
#
# __ DESCRIPTIONS __
# web_utils : procedure related web interface
#
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
import jester
import joplin_utils
# --==--==--==--==--==--==--==--==--==--==-- #
# TYPE : Selected Option for master web page
# --==--==--==--==--==--==--==--==--==--==-- #
type
selectedOption* = enum
newNote="New Note", search="Search", shortcuts="Shortcuts", notes="Notes", notebooks="Notesbooks", tags="Tags"
# --==--==--==--==--==--==--==--==--==--==-- #
# TYPE : Data Informations for Left Colomn
# --==--==--==--==--==--==--==--==--==--==-- #
type ColomnLeftData* = ref object of RootObj
j_status*: bool
option*: selectedOption

View File

@ -1,5 +1,5 @@
switch("d","release")
switch("d","ssl")
# switch("d","ssl")
# --threads:on
--opt:size
switch("passL","-s")

View File

@ -12,4 +12,8 @@ url = "127.0.0.1"
port = "7000"
[Joplin]
token = "e5f6644fbf6a97ddc55648dae72b11caecda6c6642d8ce0d3b20129b89b196385737eb908923542c3343649ebbf865b55bda031ab4c3a16edc7723ef2ad77d8f"
#token = "e5f6644fbf6a97ddc55648dae72b11caecda6c6642d8ce0d3b20129b89b196385737eb908923542c3343649ebbf865b55bda031ab4c3a16edc7723ef2ad77d8f"
token = "5b05f489016ce8a001ec83a7968419368eb9206340a18f73119c79e2154ab267ddec424658920bb6f88961c170a2680cd07fbd83f38e1c0c8df907a9aed22427"
joplin_server = "https://joplinlab.bcmaison.cf"
joplin_server_user = "joplinlab@zohomail.com"
joplin_server_pwd = "Chab30017405"

21
install_requirment.sh Normal file
View File

@ -0,0 +1,21 @@
# --==--==--==--==--==--==--==--==--==--==-- #
# Install joplin Terminal
# --==--==--==--==--==--==--==--==--==--==-- #
NPM_CONFIG_PREFIX=~/.joplin-bin npm install -g joplin
ln -s /home/joplin/.joplin-bin/bin/joplin /usr/bin/joplin
# --==--==--==--==--==--==--==--==--==--==-- #
# Joplin Configuration
# --==--==--==--==--==--==--==--==--==--==-- #
joplin config sync.target 9
joplin config sync.9.path https://joplinlab.bcmaison.cf
joplin config sync.9.username joplinlab@zohomail.com
joplin config sync.9.password Chab30017405
joplin sync
joplin config locale en_US
# --==--==--==--==--==--==--==--==--==--==-- #
# Get information from Joplin
# --==--==--==--==--==--==--==--==--==--==-- #
joplin config api.token
cat .config/joplin/settings.json

103
main.nim
View File

@ -1,55 +1,83 @@
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# Bruno Charest
# 2022-08-09
#
# __ DESCRIPTIONS __
# main : stating point of the program
#
# Project that create a web interface for Joplin base on
# Joplin Terminal running in background
#
# Inspiration of : https://ttj.dk/blog/2019/01/20/setup-a-website-with-nim
# Copyright 2019 - Thomas T. Jarløv
# [LINK] debug url : http://127.0.0.1:7000/
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
import db_sqlite # SQLite
# --==--==--==--==--==--==--==--==--==--==-- #
# Import section
# --==--==--==--==--==--==--==--==--==--==-- #
import os # Used to get arguments
import uri # We need to encode urls: encodeUrl()
import times # Time and date
import jester # Our webserver
import logging # Logging utils
import os # Used to get arguments
import parsecfg # Parse CFG (config) files
import strutils # Basic functions
import times # Time and date
import uri # We need to encode urls: encodeUrl()
import std/json
import parsecfg # Parse CFG (config) files
import std/json # json manipulation
import db_sqlite # SQLite
import code/database_utils # Utils used in the database
import code/password_utils # Our file with password utils
import code/joplin_utils
import code/web_utils
import code/joplin_utils # Joplin utils procedures and types
import code/web_utils # Web utils procedures and types
# --==--==--==--==--==--==--==--==--==--==-- #
# First we'll load config files
# --==--==--==--==--==--==--==--==--==--==-- #
let dict = loadConfig("config/config.cfg")
# --==--==--==--==--==--==--==--==--==--==-- #
# Get parameters from config.cfg
# --==--==--==--==--==--==--==--==--==--==-- #
# Now we get the values and assign them.
# We do not need to change them later, therefore
# we'll use `let`
# Database
let db_user = dict.getSectionValue("Database", "user")
let db_pass = dict.getSectionValue("Database", "pass")
let db_name = dict.getSectionValue("Database", "name")
let db_host = dict.getSectionValue("Database", "host")
# Website
let mainURL = dict.getSectionValue("Server", "url")
let mainPort = parseInt dict.getSectionValue("Server", "port")
let mainWebsite = dict.getSectionValue("Server", "website")
# Joplin
let joplin_token = dict.getSectionValue("Joplin", "token")
# --==--==--==--==--==--==--==--==--==--==-- #
# Database var
# --==--==--==--==--==--==--==--==--==--==-- #
var db: DbConn
# --==--==--==--==--==--==--==--==--==--==-- #
# Jester setting server settings
# --==--==--==--==--==--==--==--==--==--==-- #
settings:
port = Port(mainPort)
bindAddr = mainURL
# --==--==--==--==--==--==--==--==--==--==-- #
# Setup user data
# --==--==--==--==--==--==--==--==--==--==-- #
type
TData* = ref object of RootObj
loggedIn*: bool
userid, username*, userpass*, email*: string
req*: Request
# --==--==--==--==--==--==--==--==--==--==-- #
# proc init : initialisation variables
# --==--==--==--==--==--==--==--==--==--==-- #
proc init(c: var TData, cld: var ColomnLeftData) =
## Empty out user session data
c.userpass = ""
@ -60,11 +88,16 @@ proc init(c: var TData, cld: var ColomnLeftData) =
## default option
# cld.option = notes
# --==--==--==--==--==--==--==--==--==--==-- #
# function : loggedIn
# --==--==--==--==--==--==--==--==--==--==-- #
func loggedIn(c: TData): bool =
## Check if user is logged in by verifying that c.username exists
c.username.len > 0
# --==--==--==--==--==--==--==--==--==--==-- #
# proc checkLoggedIn
# --==--==--==--==--==--==--==--==--==--==-- #
proc checkLoggedIn(c: var TData) =
## Check if user is logged in
@ -98,6 +131,9 @@ proc checkLoggedIn(c: var TData) =
c.loggedIn = false
# --==--==--==--==--==--==--==--==--==--==-- #
# proc login user
# --==--==--==--==--==--==--==--==--==--==-- #
proc login(c: var TData, email, pass: string): tuple[b: bool, s: string] =
## User login
@ -135,6 +171,9 @@ proc login(c: var TData, email, pass: string): tuple[b: bool, s: string] =
return (false, "Login failed")
# --==--==--==--==--==--==--==--==--==--==-- #
# proc logout user
# --==--==--==--==--==--==--==--==--==--==-- #
proc logout(c: var TData) =
## Logout
@ -143,7 +182,9 @@ proc logout(c: var TData) =
const query = sql"DELETE FROM session WHERE ip = ? AND key = ?"
exec(db, query, c.req.ip, c.req.cookies["sid"])
# --==--==--==--==--==--==--==--==--==--==-- #
# Do the check inside our routes
# --==--==--==--==--==--==--==--==--==--==-- #
template createTFD() =
## Check if logged in and assign data to user
@ -172,6 +213,7 @@ template createTFD() =
# isMainModule
# ---------------------------- #
when isMainModule:
echo "Nim Web is now running: " & $now()
@ -198,11 +240,13 @@ when isMainModule:
# Include template files
# ---------------------------- #
#include "tmpl/main.tmpl"
include "tmpl/user.tmpl"
include "tmpl/website.tmpl"
# Tests pages include
# ---------------------------- #
include "tmpl/tests/test_homepage.tmpl"
include "tmpl/tests/test_ping.tmpl"
include "tmpl/tests/test_notebooks.tmpl"
@ -211,12 +255,19 @@ include "tmpl/tests/test_tags.tmpl"
include "tmpl/tests/test_viewtree.tmpl"
# --==--==--==--==--==--==--==--==--==--==-- #
# Setup routes (URL's)
# --==--==--==--==--==--==--==--==--==--==-- #
routes:
# default route
# --==--==--==--==--==--==--==--==--==--==-- #
get "/":
createTFD()
resp genMain(c)
# master site once login
# --==--==--==--==--==--==--==--==--==--==-- #
get "/secret":
createTFD()
echo c.loggedIn
@ -261,10 +312,14 @@ routes:
resp Http200, {"Access-Control-Allow-Origin": "http://127.0.0.1:7000"}, genSecret(c,cld)
# Login route
# --==--==--==--==--==--==--==--==--==--==-- #
get "/login":
createTFD()
resp Http200, {"Access-Control-Allow-Origin": "http://127.0.0.1:7000"}, genLogin(c, @"msg")
# action route during login
# --==--==--==--==--==--==--==--==--==--==-- #
post "/dologin":
createTFD()
@ -280,19 +335,25 @@ routes:
else:
redirect("/login?msg=" & encodeUrl(loginS))
# Logout route
# --==--==--==--==--==--==--==--==--==--==-- #
get "/logout":
createTFD()
logout(c)
redirect("/")
# # ##
# # TESTS SECTION ##
# # ##
# --==--==--==--==--==--==--==--==--==--==-- #
# # ROUTES TESTS SECTION ##
# --==--==--==--==--==--==--==--==--==--==-- #
# master tests page
# --==--==--==--==--==--==--==--==--==--==-- #
get "/test":
createTFD()
resp test_homepage(c)
# Test ping joplin - query api validation
# --==--==--==--==--==--==--==--==--==--==-- #
get "/test_pingjoplin":
createTFD()
@ -302,25 +363,35 @@ routes:
resp test_ping(c, pingCheck)
# Test geting list of all notebooks
# --==--==--==--==--==--==--==--==--==--==-- #
get "/test_notebooks":
createTFD()
cld.j_notebooks = waitFor get_joplin_notebooks(joplin_token)
resp test_notebooks(c, cld)
# Test geting list of all notes
# --==--==--==--==--==--==--==--==--==--==-- #
get "/test_notes":
createTFD()
cld.j_notes = waitFor get_joplin_notes(joplin_token)
resp test_notes(c, cld)
# Test geting list of all tags
# --==--==--==--==--==--==--==--==--==--==-- #
get "/test_tags":
createTFD()
cld.j_tags = waitFor get_joplin_tags(joplin_token)
resp test_tags(c, cld)
# Test a viewtree
# --==--==--==--==--==--==--==--==--==--==-- #
get "/test_viewtree":
createTFD()
resp test_viewtree(c)
# Test geting all tags as JSON output
# --==--==--==--==--==--==--==--==--==--==-- #
get "/test_tags_json":
createTFD()
var tags: JsonNodeObj

View File

@ -1,22 +1,51 @@
import templates
import ../code/web_utils
# --==--==--==--==--==--==--==--==--==--==-- #
# SVG : HTML title H2
# --==--==--==--==--==--==--==--==--==--==-- #
proc templ_title* (title: string): string = tmpli html"""
<h2>$title</h2>
"""
# --==--==--==--==--==--==--==--==--==--==-- #
# SVG : Status Joplin green icon
# --==--==--==--==--==--==--==--==--==--==-- #
proc status_joplin_green* (): string = tmpli html"""
<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="#3bed18" class="bi bi-caret-right-square-fill" viewBox="0 0 16 16">
<path d="M0 2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2zm5.5 10a.5.5 0 0 0 .832.374l4.5-4a.5.5 0 0 0 0-.748l-4.5-4A.5.5 0 0 0 5.5 4v8z"/>
</svg>
"""
# --==--==--==--==--==--==--==--==--==--==-- #
# SVG : Status Joplin red icon
# --==--==--==--==--==--==--==--==--==--==-- #
proc status_joplin_red* (): string = tmpli html"""
<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="#C9404D" class="bi bi-caret-right-square-fill" viewBox="0 0 16 16">
<path d="M0 2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2zm5.5 10a.5.5 0 0 0 .832.374l4.5-4a.5.5 0 0 0 0-.748l-4.5-4A.5.5 0 0 0 5.5 4v8z"/>
</svg>
"""
proc checkStatus_joplinSyncro* (): string = tmpli html"""
# --==--==--==--==--==--==--==--==--==--==-- #
# SVG : OK Joplin syncro icon
# [TODO] OK Joplin syncro icon
# --==--==--==--==--==--==--==--==--==--==-- #
proc OK_joplinSyncro_icon* (): string = tmpli html"""
"""
# --==--==--==--==--==--==--==--==--==--==-- #
# SVG : NEED Joplin syncro icon
# [TODO] NEED Joplin syncro icon
# --==--==--==--==--==--==--==--==--==--==-- #
proc NEED_joplinSyncro_icon* (): string = tmpli html"""
"""
# --==--==--==--==--==--==--==--==--==--==-- #
# SVG : In Progress Joplin syncro icon
# [TODO] In Progress Joplin syncro icon
# --==--==--==--==--==--==--==--==--==--==-- #
proc InProgress_joplinSyncro_icon* (): string = tmpli html"""
"""

View File

@ -1,5 +1,8 @@
import templates
# --==--==--==--==--==--==--==--==--==--==-- #
# SVG : Menu icon
# --==--==--==--==--==--==--==--==--==--==-- #
proc Menu_icon* (): string = tmpli html"""
<svg class="menu-icon" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 297 297"
@ -30,6 +33,9 @@ proc Menu_icon* (): string = tmpli html"""
</svg>
"""
# --==--==--==--==--==--==--==--==--==--==-- #
# SVG : New Note icon
# --==--==--==--==--==--==--==--==--==--==-- #
proc NewNote_icon*(): string = tmpli html"""
<!-- <svg class="sidebar-icon" viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" ><g ><path d="M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z"></path></g></svg> -->
<svg class="sidebar-icon" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg"
@ -45,6 +51,9 @@ proc NewNote_icon*(): string = tmpli html"""
"""
# --==--==--==--==--==--==--==--==--==--==-- #
# SVG : Search icon
# --==--==--==--==--==--==--==--==--==--==-- #
proc Search_icon*(): string = tmpli html"""
<svg class="sidebar-icon" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" enable-background="new 0 0 512 512"
@ -56,6 +65,9 @@ proc Search_icon*(): string = tmpli html"""
"""
# --==--==--==--==--==--==--==--==--==--==-- #
# SVG : Shortcut icon
# --==--==--==--==--==--==--==--==--==--==-- #
proc Shortcuts_icon*(): string = tmpli html"""
<svg class="sidebar-icon" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 73.357 73.357"
@ -76,13 +88,18 @@ proc Shortcuts_icon*(): string = tmpli html"""
</svg>
"""
# --==--==--==--==--==--==--==--==--==--==-- #
# SVG : All notes icon
# --==--==--==--==--==--==--==--==--==--==-- #
proc Notes_icon*(): string = tmpli html"""
<svg class="sidebar-icon" width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7 0h16v20H5V0h2zm14 18V2H7v16h14zM9 4h10v2H9V4zm10 4H9v2h10V8zM9 12h7v2H9v-2zm10 10H3V4H1v20h18v-2z"/>
</svg>
"""
# --==--==--==--==--==--==--==--==--==--==-- #
# SVG : All notebooks icon
# --==--==--==--==--==--==--==--==--==--==-- #
proc Notebooks_icon*(): string = tmpli html"""
<svg class="sidebar-icon" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
xmlns:xlink="http://www.w3.org/1999/xlink" enable-background="new 0 0 512 512">
@ -101,6 +118,9 @@ proc Notebooks_icon*(): string = tmpli html"""
</svg>
"""
# --==--==--==--==--==--==--==--==--==--==-- #
# SVG : All tags icon
# --==--==--==--==--==--==--==--==--==--==-- #
proc Tags_icon*(): string = tmpli html"""
<svg class="sidebar-icon" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 511.999 511.999"
@ -135,6 +155,9 @@ proc Tags_icon*(): string = tmpli html"""
</svg>
"""
# --==--==--==--==--==--==--==--==--==--==-- #
# SVG : Settings icon
# --==--==--==--==--==--==--==--==--==--==-- #
proc Settings_icon*(): string = tmpli html"""
<svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="sidebar-icon">
<g>
@ -145,6 +168,9 @@ proc Settings_icon*(): string = tmpli html"""
</svg>
"""
# --==--==--==--==--==--==--==--==--==--==-- #
# SVG : Logout icon
# --==--==--==--==--==--==--==--==--==--==-- #
proc Logout_icon*(): string = tmpli html"""
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" class="sidebar-icon" viewBox="0 0 16 16">
<path fill-rule="evenodd"
@ -154,6 +180,9 @@ proc Logout_icon*(): string = tmpli html"""
</svg>
"""
# --==--==--==--==--==--==--==--==--==--==-- #
# SVG : SendFeedback icon
# --==--==--==--==--==--==--==--==--==--==-- #
proc SendFeedback_icon*(): string = tmpli html"""
<svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="sidebar-icon">
<g>

View File

@ -1,5 +1,8 @@
#? stdtmpl | standard
#
# --==--==--==--==--==--==--==--==--==--==-- #
# proc genLogin : Login web page
# --==--==--==--==--==--==--==--==--==--==-- #
#proc genLogin(c: var TData, errorMsg = ""): string =
# result = ""
# if not c.loggedIn:

View File

@ -1,4 +1,8 @@
#? stdtmpl | standard
#
# --==--==--==--==--==--==--==--==--==--==-- #
# proc genMain : master web page once login
# --==--==--==--==--==--==--==--==--==--==-- #
#proc genMain(c: var TData): string =
# result = ""