diff --git a/crystallib/webserver/heroweb/analytics_controller.v b/crystallib/webserver/heroweb/analytics_controller.v
deleted file mode 100644
index 87328e99f..000000000
--- a/crystallib/webserver/heroweb/analytics_controller.v
+++ /dev/null
@@ -1,31 +0,0 @@
-module heroweb
-
-import json
-import veb
-import freeflowuniverse.crystallib.core.pathlib
-import freeflowuniverse.crystallib.webserver.log {Log}
-
-@[POST; '/analytics/:name']
-pub fn (mut app App) analytics_document_post(mut ctx Context, name string) veb.Result {
- infoptr := app.db.infopointers[name] or {
- return ctx.not_found()
- }
-
- new_log := json.decode(Log, ctx.req.data) or {
- return ctx.server_error(err.str())
- }
- app.db.logger.new_log(Log{...new_log, subject: ctx.user_id.str()}) or {
- return ctx.server_error(err.str())
- }
-
- return ctx.json('ok')
-}
-
-@['/analytics/:name']
-pub fn (mut app App) analytics_document_get(mut ctx Context, name string) veb.Result {
- logs := app.db.logger.get_logs(object: name) or {
- return ctx.not_found()
- }
-
- return ctx.json(logs)
-}
diff --git a/crystallib/webserver/heroweb/assets_controller.v b/crystallib/webserver/heroweb/assets_controller.v
deleted file mode 100644
index 1bf99dbd5..000000000
--- a/crystallib/webserver/heroweb/assets_controller.v
+++ /dev/null
@@ -1,39 +0,0 @@
-module heroweb
-
-import veb
-import freeflowuniverse.crystallib.core.pathlib
-
-@['/assets']
-pub fn (mut app App) assets(mut ctx Context) veb.Result {
- ptrs := app.db.authorized_ptrs(ctx.user_id, .read) or {
- return ctx.server_error(err.str())
- }
- docs := ptrs.map(Document{
- title: it.name.title()
- description: it.description
- url: '/view/asset/${it.name}'
- })
-
- return ctx.json(docs)
-}
-
-// @['/document/:name']
-// pub fn (app &App) document(mut ctx Context, name string) veb.Result {
-// infoptr := app.db.infopointers[name] or {
-// return ctx.not_found()
-// }
-
-// path := pathlib.get(infoptr.path_content)
-
-// file := if path.is_file() {
-// path
-// } else {
-// // mount the folder 'static' at path '/public', the path has to start with '/'
-// pathlib.get_file(path: '${path.path}/index.html') or {
-// return ctx.server_error(err.str())
-// }
-// }
-
-// ctx.set_content_type('application/pdf')
-// return ctx.file(file.path)
-// }
diff --git a/crystallib/webserver/heroweb/controller_assets.v b/crystallib/webserver/heroweb/controller_assets.v
new file mode 100644
index 000000000..34a10d41f
--- /dev/null
+++ b/crystallib/webserver/heroweb/controller_assets.v
@@ -0,0 +1,61 @@
+module heroweb
+
+import veb
+import freeflowuniverse.crystallib.core.pathlib
+import freeflowuniverse.crystallib.webserver.log
+import time
+
+@['/assets']
+pub fn (mut app App) assets(mut ctx Context) veb.Result {
+ ptrs := app.db.authorized_ptrs(ctx.user_id, .read) or {
+ return ctx.server_error(err.str())
+ }
+ docs := ptrs.map(Document{
+ title: it.name.title()
+ description: it.description
+ url: '/view/asset/${it.name}'
+ })
+
+ return ctx.json(docs)
+}
+
+// this endpoint serves assets dynamically
+@['/asset/:paths...']
+pub fn (app &App) asset(mut ctx Context, paths string) veb.Result {
+ name := paths.all_before('/')
+ infoptr := app.db.infopointers[name] or {
+ return ctx.not_found()
+ }
+
+ mut path := pathlib.get('${infoptr.path_content}${paths.all_after(name)}')
+ println('debugzopath ${path}')
+
+ logger := log.new('logger.sqlite') or {
+ return ctx.server_error(err.str())
+ }
+ // if infoptr.cat == .website && ctx.req.url.ends_with('.html') {
+ // logger.new_log(log.Log{
+ // object: infoptr.name
+ // timestamp: time.now()
+ // subject: ctx.user_id.str()
+ // message: 'access path ${ctx.req.url}'
+ // event: 'view'
+ // }) or {
+ // return ctx.server_error(err.str())
+ // }
+ // }
+ // println('debugzopath ${infoptr}')
+
+ file := if path.is_file() {
+ path
+ } else {
+ // mount the folder 'static' at path '/public', the path has to start with '/'
+ pathlib.get_file(path: '${path.path}/index.html') or {
+ return ctx.server_error(err.str())
+ }
+ }
+ println('debugzopath2 ${file}')
+
+ // ctx.set_content_type('application/pdf')
+ return ctx.file(file.path)
+}
diff --git a/crystallib/webserver/heroweb/authentication_controller.v b/crystallib/webserver/heroweb/controller_authentication.v
similarity index 100%
rename from crystallib/webserver/heroweb/authentication_controller.v
rename to crystallib/webserver/heroweb/controller_authentication.v
diff --git a/crystallib/webserver/heroweb/controller_log.v b/crystallib/webserver/heroweb/controller_log.v
new file mode 100644
index 000000000..d89074b8e
--- /dev/null
+++ b/crystallib/webserver/heroweb/controller_log.v
@@ -0,0 +1,39 @@
+module heroweb
+
+import json
+import veb
+import time
+import freeflowuniverse.crystallib.core.pathlib
+import freeflowuniverse.crystallib.webserver.log
+
+@[POST; '/log/:name']
+pub fn (mut app App) log_post(mut ctx Context, name string) veb.Result {
+ infoptr := app.db.infopointers[name] or {
+ return ctx.not_found()
+ }
+
+ // new_log := json.decode(log.Log, ctx.req.data) or {
+ // return ctx.server_error(err.str())
+ // }
+ // app.db.new_log(log.Log{...new_log,
+ // subject: ctx.user_id.str()
+ // timestamp: time.now()
+ // }) or {
+ // return ctx.server_error(err.str())
+ // }
+
+ return ctx.json('ok')
+}
+
+@[GET; '/logs']
+pub fn (mut app App) logs(mut ctx Context) veb.Result {
+ // logs := app.db.filter_logs(
+ // event: ctx.query['event'] or { '' }
+ // subject: ctx.query['subject'] or { '' }
+ // object: ctx.query['object'] or { '' }
+ // ) or {
+ // return ctx.server_error(err.str())
+ // }
+
+ return ctx.json('logs')
+}
diff --git a/crystallib/webserver/heroweb/factory.v b/crystallib/webserver/heroweb/factory.v
index 6e95da2eb..77b2ea400 100755
--- a/crystallib/webserver/heroweb/factory.v
+++ b/crystallib/webserver/heroweb/factory.v
@@ -8,57 +8,14 @@ import freeflowuniverse.crystallib.data.markdownparser
import freeflowuniverse.crystallib.ui.console
import freeflowuniverse.crystallib.clients.mailclient
import freeflowuniverse.crystallib.webserver.auth.jwt
-import freeflowuniverse.crystallib.webserver.log
+import freeflowuniverse.crystallib.webserver.log {Logger}
import db.sqlite
-pub fn (app &App) index(mut ctx Context) veb.Result {
- doc := Doc{
- navbar: Navbar{
- brand: NavItem{
- href: "/",
- text: "OurWorld",
- class_name: "brand"
- },
- items: [
- NavItem{
- href: "/about",
- text: "About Us",
- class_name: "nav-item"
- },
- NavItem{
- href: "/projects",
- text: "Projects",
- class_name: "nav-item"
- },
- NavItem{
- href: "/contact",
- text: "Contact",
- class_name: "nav-item"
- }
- ]
- },
- content: markdownparser.new(path: '${os.dir(@FILE)}/content/index.md') or {
- return ctx.server_error(err.str())
- }
- }
- return ctx.html($tmpl('./templates/index.html'))
-}
-
-pub fn (app &App) dashboard(mut ctx Context) veb.Result {
- user := app.db.users[ctx.user_id]
- return ctx.html($tmpl('./templates/dashboard.html'))
-}
-
//the path is pointing to the instructions
pub fn new(path string) !&App {
mut app := &App{
db: WebDB{
- logger: log.new(
- backend: log.new_backend(
- db:
- sqlite.connect('${os.dir(@FILE)}/logger.sqlite')!
- )!
- )!
+ // Logger: log.new('${os.dir(@FILE)}/logger.sqlite')!
}
}
@@ -86,7 +43,7 @@ fn (mut app App) mount_middlewares() {
// must be authorized to fetch infopointers and pointed assets
app.route_use('/infopointer/:path...', handler: app.is_authorized)
- app.route_use('/assets/:path...', handler: app.is_authorized)
+ app.route_use('/asset/:path...', handler: app.is_authorized)
}
fn (mut app App) play(path string) ! {
@@ -100,6 +57,7 @@ fn (mut app App) play(path string) ! {
}
fn (mut app App) run_infopointer_heroscripts() ! {
+ // QUESTION: we have some .mmd files in our collections, not sure what they do
app.static_mime_types['.mmd'] = 'txt/plain'
for key, ptr in app.db.infopointers{
app.db.infopointer_run(key)!
@@ -107,16 +65,17 @@ fn (mut app App) run_infopointer_heroscripts() ! {
continue
}
- mut asset := pathlib.get(ptr.path_content)
- if !asset.exists() {
- return error('Asset ${ptr.name} does not exist on path ${ptr.path_content}')
- }
- if asset.is_file() {
- app.serve_static('/assets/${ptr.name}.${asset.extension()}', asset.path)!
- } else if asset.is_dir() {
- app.mount_static_folder_at(asset.path, '/assets/${ptr.name}')!
- } else {
- return error('unsupported path ${asset}')
- }
+ // QUESTION: this was serving files statically. Might there be a case where we nneed to reintroduce this?
+ // mut asset := pathlib.get(ptr.path_content)
+ // if !asset.exists() {
+ // return error('Asset ${ptr.name} does not exist on path ${ptr.path_content}')
+ // }
+ // if asset.is_file() {
+ // app.serve_static('/assets/${ptr.name}.${asset.extension()}', asset.path)!
+ // } else if asset.is_dir() {
+ // app.mount_static_folder_at(asset.path, '/assets/${ptr.name}')!
+ // } else {
+ // return error('unsupported path ${asset}')
+ // }
}
}
\ No newline at end of file
diff --git a/crystallib/webserver/heroweb/middleware.v b/crystallib/webserver/heroweb/middleware.v
index 77f60128c..9b24f4b65 100644
--- a/crystallib/webserver/heroweb/middleware.v
+++ b/crystallib/webserver/heroweb/middleware.v
@@ -1,7 +1,9 @@
module heroweb
import freeflowuniverse.crystallib.webserver.auth.jwt
+import freeflowuniverse.crystallib.webserver.log
import veb
+import time
// middleware to set user id to context from jwt
pub fn (app App) set_user(mut ctx Context) bool {
@@ -40,16 +42,17 @@ pub fn (app App) is_logged_in(mut ctx Context) bool {
// middleware to check if user is authorized to access an infopointer or asset
pub fn (app App) is_authorized(mut ctx Context) bool {
+ println('running is authorized')
if !app.is_logged_in(mut ctx) {
return false
}
if ctx.user_id == 0 {
- panic('this should never happen')
+ panic('this should never happen as user must be logged in to reach this stage')
}
- infoptr_name := if ctx.req.url.starts_with('/assets/') {
- ctx.req.url.all_after('/assets/').all_before('/')
+ infoptr_name := if ctx.req.url.starts_with('/asset/') {
+ ctx.req.url.all_after('/asset/').all_before('/')
} else if ctx.req.url.starts_with('/infopointer/') {
ctx.req.url.all_after('/infopointer/').all_before('/')
} else {
@@ -71,14 +74,6 @@ pub fn (app App) is_authorized(mut ctx Context) bool {
return false
}
{
- // app.db.logger.new_log(Log{
- // object: infoptr_name
- // subject: ctx.user_id.str() or {
- // return ctx.server_error(err.str())
- // }
- // message: 'access path ${app.req.url}'
- // event: 'view'
- // })
return true
} else {
// ctx.res.set_status(.unauthorized)
diff --git a/crystallib/webserver/heroweb/model.v b/crystallib/webserver/heroweb/model.v
index 663c8d147..d97609aa6 100644
--- a/crystallib/webserver/heroweb/model.v
+++ b/crystallib/webserver/heroweb/model.v
@@ -10,6 +10,7 @@ import veb
pub struct App {
veb.StaticHandler
veb.Middleware[Context]
+ veb.Controller
jwt_secret string = jwt.create_secret()
mut:
db WebDB
@@ -19,9 +20,9 @@ pub:
}
pub struct WebDB {
+ // Logger
pub mut:
authenticator StatelessAuthenticator
- logger Logger
users map[u16]&User
groups map[string]&Group
acls map[string]&ACL
diff --git a/crystallib/webserver/heroweb/play_infopointers.v b/crystallib/webserver/heroweb/play_infopointers.v
index df30b75bc..ee8d27297 100644
--- a/crystallib/webserver/heroweb/play_infopointers.v
+++ b/crystallib/webserver/heroweb/play_infopointers.v
@@ -52,6 +52,7 @@ pub fn (mut db WebDB) play_infopointers(mut plbook playbook.PlayBook) ! {
'slides' { InfoType.slides }
'pdf' { InfoType.pdf }
'wiki' { InfoType.wiki }
+ 'website' { InfoType.website }
else {
println('Invalid category')
// Handle the error or set a default value
diff --git a/crystallib/webserver/heroweb/slides.v b/crystallib/webserver/heroweb/slides.v
index ab2f4d7ab..23eb0d3ab 100644
--- a/crystallib/webserver/heroweb/slides.v
+++ b/crystallib/webserver/heroweb/slides.v
@@ -6,6 +6,7 @@ pub struct Slides {
pub:
url string
name string
+ log_endpoint string
}
pub fn (slides Slides) html() string {
diff --git a/crystallib/webserver/heroweb/templates/logs.html b/crystallib/webserver/heroweb/templates/logs.html
new file mode 100644
index 000000000..8f86f09a4
--- /dev/null
+++ b/crystallib/webserver/heroweb/templates/logs.html
@@ -0,0 +1,135 @@
+
+
+
+
+
+ View Logs
+
+
+
+
+
+ View Logs
+
+
+
+
+
+
+
+
+ Timestamp |
+ Event |
+ Subject |
+ Object |
+ Message |
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/crystallib/webserver/heroweb/templates/slides.html b/crystallib/webserver/heroweb/templates/slides.html
index edaf1aa0b..3ed1f3224 100644
--- a/crystallib/webserver/heroweb/templates/slides.html
+++ b/crystallib/webserver/heroweb/templates/slides.html
@@ -117,7 +117,7 @@
let socket;
function sendInteraction(action, data) {
- fetch("/analytics/@{slides.name}", {
+ fetch("@{slides.log_endpoint}", {
method: "POST",
headers: {
"Content-Type": "application/json",
diff --git a/crystallib/webserver/heroweb/view.v b/crystallib/webserver/heroweb/view.v
new file mode 100755
index 000000000..306f7d202
--- /dev/null
+++ b/crystallib/webserver/heroweb/view.v
@@ -0,0 +1,51 @@
+module heroweb
+
+import veb
+import os
+import freeflowuniverse.crystallib.core.playbook
+import freeflowuniverse.crystallib.core.pathlib
+import freeflowuniverse.crystallib.data.markdownparser
+import freeflowuniverse.crystallib.ui.console
+import freeflowuniverse.crystallib.clients.mailclient
+import freeflowuniverse.crystallib.webserver.auth.jwt
+import freeflowuniverse.crystallib.webserver.log
+import db.sqlite
+
+pub fn (app &App) index(mut ctx Context) veb.Result {
+ doc := Doc{
+ navbar: Navbar{
+ brand: NavItem{
+ href: "/",
+ text: "OurWorld",
+ class_name: "brand"
+ },
+ items: [
+ NavItem{
+ href: "/about",
+ text: "About Us",
+ class_name: "nav-item"
+ },
+ NavItem{
+ href: "/projects",
+ text: "Projects",
+ class_name: "nav-item"
+ },
+ NavItem{
+ href: "/contact",
+ text: "Contact",
+ class_name: "nav-item"
+ }
+ ]
+ },
+ content: markdownparser.new(path: '${os.dir(@FILE)}/content/index.md') or {
+ return ctx.server_error(err.str())
+ }
+ }
+ return ctx.html($tmpl('./templates/index.html'))
+}
+
+pub fn (app &App) dashboard(mut ctx Context) veb.Result {
+ user := app.db.users[ctx.user_id]
+ return ctx.html($tmpl('./templates/dashboard.html'))
+}
+
diff --git a/crystallib/webserver/heroweb/assets_view.v b/crystallib/webserver/heroweb/view_assets.v
similarity index 86%
rename from crystallib/webserver/heroweb/assets_view.v
rename to crystallib/webserver/heroweb/view_assets.v
index 0666bdc75..7560e6d75 100644
--- a/crystallib/webserver/heroweb/assets_view.v
+++ b/crystallib/webserver/heroweb/view_assets.v
@@ -17,13 +17,14 @@ pub fn (app &App) view_asset(mut ctx Context, name string) veb.Result {
infoptr := app.db.infopointers[name]
if infoptr.cat == .website {
- return ctx.redirect('/assets/${name}')
+ return ctx.redirect('/asset/${name}/index.html')
}
html := match infoptr.cat {
.pdf {
slides := Slides{
- url:'/assets/${name}.pdf'
+ url:'/asset/${name}'
+ log_endpoint: '/log/${name}'
name: name
}
slides.html()
diff --git a/crystallib/webserver/heroweb/authentication_view.v b/crystallib/webserver/heroweb/view_authentication.v
similarity index 100%
rename from crystallib/webserver/heroweb/authentication_view.v
rename to crystallib/webserver/heroweb/view_authentication.v
diff --git a/crystallib/webserver/heroweb/kanban_view.v b/crystallib/webserver/heroweb/view_kanban.v
similarity index 100%
rename from crystallib/webserver/heroweb/kanban_view.v
rename to crystallib/webserver/heroweb/view_kanban.v
diff --git a/crystallib/webserver/heroweb/view_log.v b/crystallib/webserver/heroweb/view_log.v
new file mode 100644
index 000000000..da33a4de2
--- /dev/null
+++ b/crystallib/webserver/heroweb/view_log.v
@@ -0,0 +1,11 @@
+module heroweb
+
+import json
+import veb
+import freeflowuniverse.crystallib.core.pathlib
+import freeflowuniverse.crystallib.webserver.log
+
+@[GET; '/view/logs']
+pub fn (mut app App) view_logs(mut ctx Context) veb.Result {
+ return ctx.html($tmpl('./templates/logs.html'))
+}
diff --git a/crystallib/webserver/log/app.v b/crystallib/webserver/log/app.v
new file mode 100644
index 000000000..4431539f7
--- /dev/null
+++ b/crystallib/webserver/log/app.v
@@ -0,0 +1,26 @@
+module log
+
+import db.sqlite
+import veb
+
+// pub struct App {
+// Logger
+// }
+
+// pub struct Context {
+// veb.Context
+// }
+
+// pub fn new_app(db_path string) !&App {
+// return &App{
+// Logger: log.new(
+// DBBackend: log.new_backend(
+// db: sqlite.connect(db_path)!
+// )!
+// )!
+// }
+// }
+
+// pub fn (mut app App) index(mut ctx Context) veb.Result {
+// return ctx.html('hello')
+// }
\ No newline at end of file
diff --git a/crystallib/webserver/log/controller.v b/crystallib/webserver/log/controller.v
index 7af76d09d..15da2a94f 100644
--- a/crystallib/webserver/log/controller.v
+++ b/crystallib/webserver/log/controller.v
@@ -4,34 +4,34 @@ import vweb
import db.sqlite
import json
-pub struct Controller {
- vweb.Context
-pub mut:
- db sqlite.DB
-}
+// pub struct Controller {
+// vweb.Context
+// pub mut:
+// db sqlite.DB
+// }
-@[post]
-pub fn (mut ctrl Controller) log() vweb.Result {
- log := json.decode(Log, ctrl.req.data) or {
- ctrl.set_status(400, '')
- return ctrl.text('Failed to decode request data.')
- }
- sql ctrl.db {
- insert log into Log
- } or {
- ctrl.set_status(500, '')
- return ctrl.text('Failed insert log into db.')
- }
- return ctrl.ok('')
-}
+// @[post]
+// pub fn (mut ctrl Controller) log() vweb.Result {
+// log := json.decode(Log, ctrl.req.data) or {
+// ctrl.set_status(400, '')
+// return ctrl.text('Failed to decode request data.')
+// }
+// sql ctrl.db {
+// insert log into Log
+// } or {
+// ctrl.set_status(500, '')
+// return ctrl.text('Failed insert log into db.')
+// }
+// return ctrl.ok('')
+// }
-@[get]
-pub fn (mut ctrl Controller) logs() vweb.Result {
- logs := sql ctrl.db {
- select from Log
- } or {
- ctrl.set_status(500, '')
- return ctrl.text('Failed insert log into db.')
- }
- return ctrl.json(logs)
-}
+// @[get]
+// pub fn (mut ctrl Controller) logs() vweb.Result {
+// logs := sql ctrl.db {
+// select from Log
+// } or {
+// ctrl.set_status(500, '')
+// return ctrl.text('Failed insert log into db.')
+// }
+// return ctrl.json(logs)
+// }
diff --git a/crystallib/webserver/log/controller_test.v b/crystallib/webserver/log/controller_test.v
index 64f99163a..93565a72e 100644
--- a/crystallib/webserver/log/controller_test.v
+++ b/crystallib/webserver/log/controller_test.v
@@ -6,29 +6,29 @@ import db.sqlite
import time
import net.http
-const port = 8080
-const url = 'http://localhost:${port}'
+// const port = 8080
+// const url = 'http://localhost:${port}'
-fn testsuite_begin() {
- mut db := sqlite.connect('test.sqlite')!
- sql db {
- create table Log
- } or { panic(err) }
- ctrl := &Controller{
- db: db
- }
- spawn vweb.run(ctrl, 8080)
-}
+// fn testsuite_begin() {
+// mut db := sqlite.connect('test.sqlite')!
+// sql db {
+// create table Log
+// } or { panic(err) }
+// ctrl := &Controller{
+// db: db
+// }
+// spawn vweb.run(ctrl, 8080)
+// }
-fn test_log() {
- log := Log{
- subject: 'test_user'
- object: 'test_asset'
- event: 'access'
- timestamp: time.now()
- }
- data := json.encode(log)
- req := http.new_request(.post, '${analytics.url}/log', data)
- resp := req.do()!
- assert resp.status_code == 200
-}
+// fn test_log() {
+// log := Log{
+// subject: 'test_user'
+// object: 'test_asset'
+// event: 'access'
+// timestamp: time.now()
+// }
+// data := json.encode(log)
+// req := http.new_request(.post, '${analytics.url}/log', data)
+// resp := req.do()!
+// assert resp.status_code == 200
+// }
diff --git a/crystallib/webserver/log/factory.v b/crystallib/webserver/log/factory.v
index 5f79c4ee0..f506f3b09 100644
--- a/crystallib/webserver/log/factory.v
+++ b/crystallib/webserver/log/factory.v
@@ -1,18 +1,16 @@
module log
-pub struct Logger {
-pub mut:
- backend DBBackend
-}
+import db.sqlite
-@[params]
-pub struct LoggerConfig {
-pub:
- backend ?DBBackend
+pub struct Logger {
+ db_path string
+ // DBBackend
}
-pub fn new(config LoggerConfig) !Logger {
+pub fn new(db_path string) !Logger {
+ // db := sqlite.connect(db_path)!
return Logger{
- backend: config.backend or { new_backend()! }
+ db_path: db_path
+ // DBBackend: new_backend(db: db)!
}
}
diff --git a/crystallib/webserver/log/log_controller.v b/crystallib/webserver/log/log_controller.v
new file mode 100644
index 000000000..048e8002b
--- /dev/null
+++ b/crystallib/webserver/log/log_controller.v
@@ -0,0 +1,70 @@
+module log
+
+import json
+import veb
+import freeflowuniverse.crystallib.core.pathlib
+
+// @[POST; '/log/:name']
+// pub fn (mut app App) log_post(mut ctx Context, name string) veb.Result {
+// infoptr := app.db.infopointers[name] or {
+// return ctx.not_found()
+// }
+
+// new_log := json.decode(Log, ctx.req.data) or {
+// return ctx.server_error(err.str())
+// }
+// app.db.logger.new_log(Log{...new_log, subject: ctx.user_id.str()}) or {
+// return ctx.server_error(err.str())
+// }
+
+// return ctx.json('ok')
+// }
+
+// @[GET; '/logs']
+// pub fn (mut app App) logs(mut ctx Context) veb.Result {
+// // Initialize the query parameters if present
+// mut query := 'SELECT * FROM Log WHERE'
+// event_filter := ctx.query['event'] or { '' }
+// if event_filter != '' {
+// query += ' event = ${event_filter}'
+// }
+
+// subject_filter := ctx.query['subject'] or { '' }
+// if subject_filter != '' {
+// query += ' subject = ${subject_filter}'
+// }
+
+// object_filter := ctx.query['object'] or { '' }
+// if object_filter != '' {
+// query += ' subject = ${object_filter}'
+// }
+
+// response := app.db.exec(query) or {
+// return ctx.server_error(err.str())
+// }
+
+// if response.len == 0 {
+// panic('response shouldnt be 0')
+// }
+// println('resp ${response}')
+
+// // return response[0].vals
+
+// // Build the SQL query dynamically based on the provided filters
+// logs := sql app.db {
+// select from Log where
+// object == object_filter &&
+// (event_filter == '' || event.contains(event_filter)) &&
+// (subject_filter == '' || subject.contains(subject_filter)) &&
+// (message_filter == '' || message.contains(message_filter))
+// } or {
+// return ctx.not_found()
+// }
+
+// // Return the filtered logs or a message if no logs match the criteria
+// if logs.len == 0 {
+// return ctx.text('No logs found matching the criteria')
+// }
+
+// return ctx.json(logs)
+// }
diff --git a/crystallib/webserver/log/logger.v b/crystallib/webserver/log/logger.v
index 42c51155a..c0da7edb9 100644
--- a/crystallib/webserver/log/logger.v
+++ b/crystallib/webserver/log/logger.v
@@ -1,14 +1,55 @@
module log
-pub fn (mut logger Logger) new_log(log Log) ! {
- sql logger.backend.db {
+import db.sqlite
+
+pub fn (logger Logger) new_log(log Log) ! {
+ db := sqlite.connect(logger.db_path)!
+
+ sql db {
insert log into Log
}!
}
-pub fn (mut logger Logger) get_logs(log Log) ![]Log {
- logs := sql logger.backend.db {
- select from Log
- }!
+pub struct LogFilter {
+ Log
+ matches_all bool
+ limit int
+}
+
+pub fn (logger Logger) filter_logs(filter LogFilter) ![]Log {
+ db := sqlite.connect(logger.db_path)!
+ mut select_stmt := 'select * from Log'
+
+ mut matchers := []string{}
+ if filter.event != '' {
+ matchers << 'event == ${filter.event}'
+ }
+
+ if filter.subject != '' {
+ matchers << 'subject == ${filter.subject}'
+ }
+
+ if filter.object != '' {
+ matchers << 'object == ${filter.object}'
+ }
+
+ if matchers.len > 0 {
+ matchers_str := if filter.matches_all {
+ matchers.join(' AND ')
+ } else {
+ matchers.join(' OR ')
+ }
+ select_stmt += ' where ${matchers_str}'
+ }
+
+ responses := db.exec(select_stmt)!
+
+ mut logs := []Log{}
+ for response in responses {
+ logs << sql db {
+ select from Log where id == response.vals[0].int()
+ }!
+ }
+
return logs
}
\ No newline at end of file
diff --git a/crystallib/webserver/log/model.v b/crystallib/webserver/log/model.v
index eb939215e..852b2021f 100644
--- a/crystallib/webserver/log/model.v
+++ b/crystallib/webserver/log/model.v
@@ -3,6 +3,8 @@ module log
import time
pub struct Log {
+ id int @[primary; sql: serial]
+pub:
timestamp time.Time
pub mut:
event string
diff --git a/examples/webserver/herowebexample/heroscripts/threefold_info.hero b/examples/webserver/herowebexample/heroscripts/threefold_info.hero
index 6cd65471c..f56a3975d 100644
--- a/examples/webserver/herowebexample/heroscripts/threefold_info.hero
+++ b/examples/webserver/herowebexample/heroscripts/threefold_info.hero
@@ -5,9 +5,9 @@
hero_url_reset: false
content_path: '~/hero/www/info/tech'
acl: 'heroweb'
- cat: 'wiki'
+ cat: 'website'
description: '
- Wiki for technology of threedold
+ Website for technology of threedold
'
//will have 2 documents inside