refactor: Migrate from vweb to veb web framework

- Update all references from `vweb` to `veb`
- Add `veb.StaticHandler` to `Playground` struct
- Ensure error propagation for static file serving calls
- Apply consistent indentation across various module definitions
- Adjust documentation and comments for `veb` framework
This commit is contained in:
Mahmoud-Emad
2025-09-01 13:00:17 +03:00
parent dde5f2f7e6
commit 46a3bcb840
8 changed files with 163 additions and 156 deletions

View File

@@ -1,26 +1,26 @@
module net module net
## Description ## Description
`net` provides networking functions. It is mostly a wrapper to BSD sockets, so you can listen on a port, connect to remote TCP/UDP services, and communicate with them. `net` provides networking functions. It is mostly a wrapper to BSD sockets, so you can listen on a port, connect to remote TCP/UDP services, and communicate with them.
const msg_nosignal = 0x4000 const msg_nosignal = 0x4000
const err_connection_refused = error_with_code('net: connection refused', errors_base + 10) const err_connection_refused = error_with_code('net: connection refused', errors_base + 10)
const err_option_wrong_type = error_with_code('net: set_option_xxx option wrong type', const err_option_wrong_type = error_with_code('net: set_option_xxx option wrong type',
errors_base + 3) errors_base + 3)
const opts_can_set = [ const opts_can_set = [
SocketOption.broadcast, SocketOption.broadcast,
.debug, .debug,
.dont_route, .dont_route,
.keep_alive, .keep_alive,
.linger, .linger,
.oob_inline, .oob_inline,
.receive_buf_size, .receive_buf_size,
.receive_low_size, .receive_low_size,
.receive_timeout, .receive_timeout,
.send_buf_size, .send_buf_size,
.send_low_size, .send_low_size,
.send_timeout, .send_timeout,
.ipv6_only, .ipv6_only,
] ]
const error_eagain = C.EAGAIN const error_eagain = C.EAGAIN
const err_port_out_of_range = error_with_code('net: port out of range', errors_base + 5) const err_port_out_of_range = error_with_code('net: port out of range', errors_base + 5)
@@ -29,12 +29,12 @@ const err_connect_failed = error_with_code('net: connect failed', errors_base +
const errors_base = 0 const errors_base = 0
Well defined errors that are returned from socket functions Well defined errors that are returned from socket functions
const opts_int = [ const opts_int = [
SocketOption.receive_buf_size, SocketOption.receive_buf_size,
.receive_low_size, .receive_low_size,
.receive_timeout, .receive_timeout,
.send_buf_size, .send_buf_size,
.send_low_size, .send_low_size,
.send_timeout, .send_timeout,
] ]
const error_eintr = C.EINTR const error_eintr = C.EINTR
const error_ewouldblock = C.EWOULDBLOCK const error_ewouldblock = C.EWOULDBLOCK
@@ -43,17 +43,17 @@ const error_einprogress = C.EINPROGRESS
const err_timed_out_code = errors_base + 9 const err_timed_out_code = errors_base + 9
const err_connect_timed_out = error_with_code('net: connect timed out', errors_base + 8) const err_connect_timed_out = error_with_code('net: connect timed out', errors_base + 8)
const err_new_socket_failed = error_with_code('net: new_socket failed to create socket', const err_new_socket_failed = error_with_code('net: new_socket failed to create socket',
errors_base + 1) errors_base + 1)
const msg_dontwait = C.MSG_DONTWAIT const msg_dontwait = C.MSG_DONTWAIT
const infinite_timeout = time.infinite const infinite_timeout = time.infinite
infinite_timeout should be given to functions when an infinite_timeout is wanted (i.e. functions only ever return with data) infinite_timeout should be given to functions when an infinite_timeout is wanted (i.e. functions only ever return with data)
const no_timeout = time.Duration(0) const no_timeout = time.Duration(0)
no_timeout should be given to functions when no timeout is wanted (i.e. all functions return instantly) no_timeout should be given to functions when no timeout is wanted (i.e. all functions return instantly)
const err_timed_out = error_with_code('net: op timed out', errors_base + 9) const err_timed_out = error_with_code('net: op timed out', errors_base + 9)
const tcp_default_read_timeout = 30 * time.second const tcp_default_read_timeout = 30 *time.second
const err_option_not_settable = error_with_code('net: set_option_xxx option not settable', const err_option_not_settable = error_with_code('net: set_option_xxx option not settable',
errors_base + 2) errors_base + 2)
const tcp_default_write_timeout = 30 * time.second const tcp_default_write_timeout = 30* time.second
fn addr_from_socket_handle(handle int) Addr fn addr_from_socket_handle(handle int) Addr
addr_from_socket_handle returns an address, based on the given integer socket `handle` addr_from_socket_handle returns an address, based on the given integer socket `handle`
fn close(handle int) ! fn close(handle int) !
@@ -94,16 +94,16 @@ fn validate_port(port int) !u16
validate_port checks whether a port is valid and returns the port or an error validate_port checks whether a port is valid and returns the port or an error
fn wrap_error(error_code int) ! fn wrap_error(error_code int) !
interface Connection { interface Connection {
addr() !Addr addr() !Addr
peer_addr() !Addr peer_addr() !Addr
mut: mut:
read(mut []u8) !int read(mut []u8) !int
write([]u8) !int write([]u8) !int
close() ! close() !
} }
Connection provides a generic SOCK_STREAM style interface that protocols can use as a base connection object to support TCP, UNIX Domain Sockets and various proxying solutions. Connection provides a generic SOCK_STREAM style interface that protocols can use as a base connection object to support TCP, UNIX Domain Sockets and various proxying solutions.
interface Dialer { interface Dialer {
dial(address string) !Connection dial(address string) !Connection
} }
Dialer is an abstract dialer interface for producing connections to adresses. Dialer is an abstract dialer interface for producing connections to adresses.
fn (mut s TcpSocket) set_option_bool(opt SocketOption, value bool) ! fn (mut s TcpSocket) set_option_bool(opt SocketOption, value bool) !
@@ -114,49 +114,49 @@ fn (mut s TcpSocket) bind(addr string) !
fn (mut s UdpSocket) set_option_bool(opt SocketOption, value bool) ! fn (mut s UdpSocket) set_option_bool(opt SocketOption, value bool) !
fn (mut s UdpSocket) set_dualstack(on bool) ! fn (mut s UdpSocket) set_dualstack(on bool) !
enum AddrFamily { enum AddrFamily {
unix = C.AF_UNIX unix = C.AF_UNIX
ip = C.AF_INET ip = C.AF_INET
ip6 = C.AF_INET6 ip6 = C.AF_INET6
unspec = C.AF_UNSPEC unspec = C.AF_UNSPEC
} }
AddrFamily are the available address families AddrFamily are the available address families
enum ShutdownDirection { enum ShutdownDirection {
read read
write write
read_and_write read_and_write
} }
ShutdownDirection is used by `net.shutdown`, for specifying the direction for which the communication will be cut. ShutdownDirection is used by `net.shutdown`, for specifying the direction for which the communication will be cut.
enum SocketOption { enum SocketOption {
// TODO: SO_ACCEPT_CONN is not here because windows doesn't support it // TODO: SO_ACCEPT_CONN is not here because windows doesn't support it
// and there is no easy way to define it // and there is no easy way to define it
broadcast = C.SO_BROADCAST broadcast = C.SO_BROADCAST
debug = C.SO_DEBUG debug = C.SO_DEBUG
dont_route = C.SO_DONTROUTE dont_route = C.SO_DONTROUTE
error = C.SO_ERROR error = C.SO_ERROR
keep_alive = C.SO_KEEPALIVE keep_alive = C.SO_KEEPALIVE
linger = C.SO_LINGER linger = C.SO_LINGER
oob_inline = C.SO_OOBINLINE oob_inline = C.SO_OOBINLINE
reuse_addr = C.SO_REUSEADDR reuse_addr = C.SO_REUSEADDR
receive_buf_size = C.SO_RCVBUF receive_buf_size = C.SO_RCVBUF
receive_low_size = C.SO_RCVLOWAT receive_low_size = C.SO_RCVLOWAT
receive_timeout = C.SO_RCVTIMEO receive_timeout = C.SO_RCVTIMEO
send_buf_size = C.SO_SNDBUF send_buf_size = C.SO_SNDBUF
send_low_size = C.SO_SNDLOWAT send_low_size = C.SO_SNDLOWAT
send_timeout = C.SO_SNDTIMEO send_timeout = C.SO_SNDTIMEO
socket_type = C.SO_TYPE socket_type = C.SO_TYPE
ipv6_only = C.IPV6_V6ONLY ipv6_only = C.IPV6_V6ONLY
} }
enum SocketType { enum SocketType {
udp = C.SOCK_DGRAM udp = C.SOCK_DGRAM
tcp = C.SOCK_STREAM tcp = C.SOCK_STREAM
seqpacket = C.SOCK_SEQPACKET seqpacket = C.SOCK_SEQPACKET
} }
SocketType are the available sockets SocketType are the available sockets
struct Addr { struct Addr {
pub: pub:
len u8 len u8
f u8 f u8
addr AddrData addr AddrData
} }
fn (a Addr) family() AddrFamily fn (a Addr) family() AddrFamily
family returns the family/kind of the given address `a` family returns the family/kind of the given address `a`
@@ -168,72 +168,72 @@ fn (a Addr) str() string
str returns a string representation of the address `a` str returns a string representation of the address `a`
struct C.addrinfo { struct C.addrinfo {
mut: mut:
ai_family int ai_family int
ai_socktype int ai_socktype int
ai_flags int ai_flags int
ai_protocol int ai_protocol int
ai_addrlen int ai_addrlen int
ai_addr voidptr ai_addr voidptr
ai_canonname voidptr ai_canonname voidptr
ai_next voidptr ai_next voidptr
} }
struct C.fd_set {} struct C.fd_set {}
struct C.sockaddr_in { struct C.sockaddr_in {
mut: mut:
sin_len u8 sin_len u8
sin_family u8 sin_family u8
sin_port u16 sin_port u16
sin_addr u32 sin_addr u32
sin_zero [8]char sin_zero [8]char
} }
struct C.sockaddr_in6 { struct C.sockaddr_in6 {
mut: mut:
// 1 + 1 + 2 + 4 + 16 + 4 = 28; // 1 + 1 + 2 + 4 + 16 + 4 = 28;
sin6_len u8 // 1 sin6_len u8 // 1
sin6_family u8 // 1 sin6_family u8 // 1
sin6_port u16 // 2 sin6_port u16 // 2
sin6_flowinfo u32 // 4 sin6_flowinfo u32 // 4
sin6_addr [16]u8 // 16 sin6_addr [16]u8 // 16
sin6_scope_id u32 // 4 sin6_scope_id u32 // 4
} }
struct C.sockaddr_un { struct C.sockaddr_un {
mut: mut:
sun_len u8 sun_len u8
sun_family u8 sun_family u8
sun_path [max_unix_path]char sun_path [max_unix_path]char
} }
struct Ip { struct Ip {
port u16 port u16
addr [4]u8 addr [4]u8
// Pad to size so that socket functions // Pad to size so that socket functions
// dont complain to us (see in.h and bind()) // dont complain to us (see in.h and bind())
// TODO(emily): I would really like to use // TODO(emily): I would really like to use
// some constant calculations here // some constant calculations here
// so that this doesnt have to be hardcoded // so that this doesnt have to be hardcoded
sin_pad [8]u8 sin_pad [8]u8
} }
fn (a Ip) str() string fn (a Ip) str() string
str returns a string representation of `a` str returns a string representation of `a`
struct Ip6 { struct Ip6 {
port u16 port u16
flow_info u32 flow_info u32
addr [16]u8 addr [16]u8
scope_id u32 scope_id u32
} }
fn (a Ip6) str() string fn (a Ip6) str() string
str returns a string representation of `a` str returns a string representation of `a`
struct ListenOptions { struct ListenOptions {
pub: pub:
dualstack bool = true dualstack bool = true
backlog int = 128 backlog int = 128
} }
struct ShutdownConfig { struct ShutdownConfig {
pub: pub:
how ShutdownDirection = .read_and_write how ShutdownDirection = .read_and_write
} }
struct Socket { struct Socket {
pub: pub:
handle int handle int
} }
fn (s &Socket) address() !Addr fn (s &Socket) address() !Addr
address gets the address of a socket address gets the address of a socket
@@ -243,13 +243,13 @@ fn (t TCPDialer) dial(address string) !Connection
dial will try to create a new abstract connection to the given address. It will return an error, if that is not possible. dial will try to create a new abstract connection to the given address. It will return an error, if that is not possible.
struct TcpConn { struct TcpConn {
pub mut: pub mut:
sock TcpSocket sock TcpSocket
handle int handle int
write_deadline time.Time write_deadline time.Time
read_deadline time.Time read_deadline time.Time
read_timeout time.Duration read_timeout time.Duration
write_timeout time.Duration write_timeout time.Duration
is_blocking bool = true is_blocking bool = true
} }
fn (c &TcpConn) addr() !Addr fn (c &TcpConn) addr() !Addr
fn (mut c TcpConn) close() ! fn (mut c TcpConn) close() !
@@ -265,7 +265,7 @@ fn (c TcpConn) read(mut buf []u8) !int
fn (mut c TcpConn) read_deadline() !time.Time fn (mut c TcpConn) read_deadline() !time.Time
fn (mut con TcpConn) read_line() string fn (mut con TcpConn) read_line() string
read_line is a *simple*, *non customizable*, blocking line reader. It will return a line, ending with LF, or just '', on EOF. read_line is a *simple*, *non customizable*, blocking line reader. It will return a line, ending with LF, or just '', on EOF.
Note: if you want more control over the buffer, please use a buffered IO reader instead: `io.new_buffered_reader({reader: io.make_reader(con)})` Note: if you want more control over the buffer, please use a buffered IO reader instead: `io.new_buffered_reader({reader: io.make_reader(con)})`
fn (mut con TcpConn) read_line_max(max_line_len int) string fn (mut con TcpConn) read_line_max(max_line_len int) string
read_line_max is a *simple*, *non customizable*, blocking line reader. It will return a line, ending with LF, '' on EOF. It stops reading, when the result line length exceeds max_line_len. read_line_max is a *simple*, *non customizable*, blocking line reader. It will return a line, ending with LF, '' on EOF. It stops reading, when the result line length exceeds max_line_len.
@@ -278,7 +278,7 @@ fn (mut c TcpConn) set_read_deadline(deadline time.Time)
fn (mut c TcpConn) set_read_timeout(t time.Duration) fn (mut c TcpConn) set_read_timeout(t time.Duration)
fn (mut c TcpConn) set_sock() ! fn (mut c TcpConn) set_sock() !
set_sock initialises the c.sock field. It should be called after `.accept_only()!`. set_sock initialises the c.sock field. It should be called after `.accept_only()!`.
Note: just use `.accept()!`. In most cases it is simpler, and calls `.set_sock()!` for you. Note: just use `.accept()!`. In most cases it is simpler, and calls `.set_sock()!` for you.
fn (mut c TcpConn) set_write_deadline(deadline time.Time) fn (mut c TcpConn) set_write_deadline(deadline time.Time)
fn (mut c TcpConn) set_write_timeout(t time.Duration) fn (mut c TcpConn) set_write_timeout(t time.Duration)
@@ -295,19 +295,17 @@ fn (mut c TcpConn) write_string(s string) !int
fn (c &TcpConn) write_timeout() time.Duration fn (c &TcpConn) write_timeout() time.Duration
struct TcpListener { struct TcpListener {
pub mut: pub mut:
sock TcpSocket sock TcpSocket
accept_timeout time.Duration accept_timeout time.Duration
accept_deadline time.Time accept_deadline time.Time
is_blocking bool = true is_blocking bool = true
} }
fn (mut l TcpListener) accept() !&TcpConn fn (mut l TcpListener) accept() !&TcpConn
accept a tcp connection from an external source to the listener `l`. accept a tcp connection from an external source to the listener `l`.
fn (mut l TcpListener) accept_only() !&TcpConn fn (mut l TcpListener) accept_only() !&TcpConn
accept_only accepts a tcp connection from an external source to the listener `l`. Unlike `accept`, `accept_only` *will not call* `.set_sock()!` on the result, and is thus faster. accept_only accepts a tcp connection from an external source to the listener `l`. Unlike `accept`, `accept_only` *will not call* `.set_sock()!` on the result, and is thus faster.
Note: you *need* to call `.set_sock()!` manually, before using theconnection after calling `.accept_only()!`, but that does not have to happen in the same thread that called `.accept_only()!`. The intention of this API, is to have a more efficient way to accept connections, that are later processed by a thread pool, while the main thread remains active, so that it can accept other connections. See also vlib/veb/veb.v .
Note: you *need* to call `.set_sock()!` manually, before using theconnection after calling `.accept_only()!`, but that does not have to happen in the same thread that called `.accept_only()!`. The intention of this API, is to have a more efficient way to accept connections, that are later processed by a thread pool, while the main thread remains active, so that it can accept other connections. See also vlib/vweb/vweb.v .
If you do not need that, just call `.accept()!` instead, which will call `.set_sock()!` for you. If you do not need that, just call `.accept()!` instead, which will call `.set_sock()!` for you.
fn (c &TcpListener) accept_deadline() !time.Time fn (c &TcpListener) accept_deadline() !time.Time
@@ -319,12 +317,12 @@ fn (mut c TcpListener) close() !
fn (c &TcpListener) addr() !Addr fn (c &TcpListener) addr() !Addr
struct UdpConn { struct UdpConn {
pub mut: pub mut:
sock UdpSocket sock UdpSocket
mut: mut:
write_deadline time.Time write_deadline time.Time
read_deadline time.Time read_deadline time.Time
read_timeout time.Duration read_timeout time.Duration
write_timeout time.Duration write_timeout time.Duration
} }
fn (mut c UdpConn) write_ptr(b &u8, len int) !int fn (mut c UdpConn) write_ptr(b &u8, len int) !int
sock := UdpSocket{ handle: sbase.handle l: local r: resolve_wrapper(raddr) } } sock := UdpSocket{ handle: sbase.handle l: local r: resolve_wrapper(raddr) } }
@@ -350,5 +348,5 @@ fn (mut c UdpConn) wait_for_write() !
fn (c &UdpConn) str() string fn (c &UdpConn) str() string
fn (mut c UdpConn) close() ! fn (mut c UdpConn) close() !
struct Unix { struct Unix {
path [max_unix_path]char path [max_unix_path]char
} }

View File

@@ -1,6 +1,6 @@
# **WebDAV Server in V** # **WebDAV Server in V**
This project implements a WebDAV server using the `vweb` framework and modules from `crystallib`. The server supports essential WebDAV file operations such as reading, writing, copying, moving, and deleting files and directories. It also includes **authentication** and **request logging** for better control and debugging. This project implements a WebDAV server using the `veb` framework and modules from `crystallib`. The server supports essential WebDAV file operations such as reading, writing, copying, moving, and deleting files and directories. It also includes **authentication** and **request logging** for better control and debugging.
--- ---
@@ -47,6 +47,7 @@ sudo mount -t davfs <server_url> <mount_point>
``` ```
For example: For example:
```bash ```bash
sudo mount -t davfs http://localhost:8080 /mnt/webdav sudo mount -t davfs http://localhost:8080 /mnt/webdav
``` ```
@@ -82,6 +83,7 @@ Authorization: Basic <base64-encoded-credentials>
**Example**: **Example**:
For the credentials `admin:admin`, the header would look like this: For the credentials `admin:admin`, the header would look like this:
```http ```http
Authorization: Basic YWRtaW46YWRtaW4= Authorization: Basic YWRtaW46YWRtaW4=
``` ```
@@ -103,25 +105,32 @@ You can configure the WebDAV server using the following parameters when calling
## **Example Workflow** ## **Example Workflow**
1. Start the server: 1. Start the server:
```bash ```bash
v run webdav_server.v v run webdav_server.v
``` ```
2. Mount the server using `davfs`: 2. Mount the server using `davfs`:
```bash ```bash
sudo mount -t davfs http://localhost:8080 /mnt/webdav sudo mount -t davfs http://localhost:8080 /mnt/webdav
``` ```
3. Perform operations: 3. Perform operations:
- Create a new file: - Create a new file:
```bash ```bash
echo "Hello WebDAV!" > /mnt/webdav/hello.txt echo "Hello WebDAV!" > /mnt/webdav/hello.txt
``` ```
- List files: - List files:
```bash ```bash
ls /mnt/webdav ls /mnt/webdav
``` ```
- Delete a file: - Delete a file:
```bash ```bash
rm /mnt/webdav/hello.txt rm /mnt/webdav/hello.txt
``` ```
@@ -150,7 +159,6 @@ You can configure the WebDAV server using the following parameters when calling
- Integration with persistent databases for user credentials. - Integration with persistent databases for user credentials.
- TLS/SSL support for secure connections. - TLS/SSL support for secure connections.
# WebDAV Property Model # WebDAV Property Model
This file implements the WebDAV property model as defined in [RFC 4918](https://tools.ietf.org/html/rfc4918). It provides a set of property types that represent various WebDAV properties used in PROPFIND and PROPPATCH operations. This file implements the WebDAV property model as defined in [RFC 4918](https://tools.ietf.org/html/rfc4918). It provides a set of property types that represent various WebDAV properties used in PROPFIND and PROPPATCH operations.
@@ -167,12 +175,13 @@ The `model_property.v` file defines:
```v ```v
pub interface Property { pub interface Property {
xml() string xml() string
xml_name() string xml_name() string
} }
``` ```
All WebDAV properties must implement: All WebDAV properties must implement:
- `xml()`: Returns the full XML representation of the property with its value - `xml()`: Returns the full XML representation of the property with its value
- `xml_name()`: Returns just the XML tag name of the property (used in property requests) - `xml_name()`: Returns just the XML tag name of the property (used in property requests)
@@ -200,7 +209,6 @@ The file implements the following WebDAV property types:
These property types are used when responding to WebDAV PROPFIND requests to describe resources in the WebDAV server. These property types are used when responding to WebDAV PROPFIND requests to describe resources in the WebDAV server.
# WebDAV Locker # WebDAV Locker
This file implements a locking mechanism for resources in a WebDAV context. It provides functionality to manage locks on resources, ensuring that they are not modified by multiple clients simultaneously. This file implements a locking mechanism for resources in a WebDAV context. It provides functionality to manage locks on resources, ensuring that they are not modified by multiple clients simultaneously.
@@ -218,7 +226,7 @@ The `locker.v` file defines:
```v ```v
struct Locker { struct Locker {
mut: mut:
locks map[string]Lock locks map[string]Lock
} }
``` ```
@@ -229,8 +237,8 @@ mut:
```v ```v
pub struct LockResult { pub struct LockResult {
pub: pub:
token string // The lock token token string // The lock token
is_new_lock bool // Whether this is a new lock or an existing one is_new_lock bool // Whether this is a new lock or an existing one
} }
``` ```

View File

@@ -4,12 +4,13 @@ import x.json2 as json
// import freeflowuniverse.herolib.develop.gittools // import freeflowuniverse.herolib.develop.gittools
import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.core.pathlib
import freeflowuniverse.herolib.core.texttools import freeflowuniverse.herolib.core.texttools
import vweb import veb
import os import os
pub struct Playground { pub struct Playground {
vweb.Context veb.Context
build pathlib.Path @[vweb_global] veb.StaticHandler
build pathlib.Path @[veb_global]
} }
@[params] @[params]
@@ -50,11 +51,11 @@ pub fn new_playground(config PlaygroundConfig) !&Playground {
build: build_dir build: build_dir
} }
pg.serve_examples(config.specs) or { return error('failed to serve examples:\n${err}') } pg.serve_examples(config.specs) or { return error('failed to serve examples:\n${err}') }
pg.mount_static_folder_at('${build_dir.path}/static', '/static') pg.mount_static_folder_at('${build_dir.path}/static', '/static')!
mut env_file := pathlib.get_file(path: '${build_dir.path}/env.js')! mut env_file := pathlib.get_file(path: '${build_dir.path}/env.js')!
env_file.write(encode_env(config.specs)!)! env_file.write(encode_env(config.specs)!)!
pg.serve_static('/env.js', env_file.path) pg.serve_static('/env.js', env_file.path)!
return &pg return &pg
} }
@@ -86,11 +87,11 @@ fn (mut pg Playground) serve_examples(specs_ []pathlib.Path) ! {
return error('Failed to decode OpenRPC Spec ${spec}:\n${err}') return error('Failed to decode OpenRPC Spec ${spec}:\n${err}')
} }
name := texttools.name_fix(o.info.title) name := texttools.name_fix(o.info.title)
pg.serve_static('/specs/${name}.json', spec.path) pg.serve_static('/specs/${name}.json', spec.path)!
} }
} }
pub fn (mut pg Playground) index() vweb.Result { pub fn (mut pg Playground) index() veb.Result {
mut index := pathlib.get_file(path: '${pg.build.path}/index.html') or { panic(err) } mut index := pathlib.get_file(path: '${pg.build.path}/index.html') or { panic(err) }
return pg.html(index.read() or { panic(err) }) return pg.html(index.read() or { panic(err) })
} }

View File

@@ -4,7 +4,7 @@ import net.http
import time import time
import json import json
// session controller that be be added to vweb projects // session controller that be be added to veb projects
pub struct EmailClient { pub struct EmailClient {
url string @[required] url string @[required]
} }

View File

@@ -1,6 +1,6 @@
module authentication module authentication
import vweb import veb
import time import time
import json import json
import log import log
@@ -8,13 +8,13 @@ import freeflowuniverse.herolib.ui.console
const agent = 'Email Authentication Controller' const agent = 'Email Authentication Controller'
// email authentication controller that be be added to vweb projects // email authentication controller that be be added to veb projects
@[heap] @[heap]
pub struct Controller { pub struct Controller {
vweb.Context veb.Context
callback string @[vweb_global] callback string @[veb_global]
mut: mut:
authenticator Authenticator @[vweb_global] authenticator Authenticator @[veb_global]
} }
@[params] @[params]
@@ -32,7 +32,7 @@ pub fn new_controller(params ControllerParams) Controller {
// route responsible for verifying email, email form should be posted here // route responsible for verifying email, email form should be posted here
@[POST] @[POST]
pub fn (mut app Controller) send_verification_mail() !vweb.Result { pub fn (mut app Controller) send_verification_mail() !veb.Result {
config := json.decode(SendMailConfig, app.req.data)! config := json.decode(SendMailConfig, app.req.data)!
app.authenticator.send_verification_mail(config) or { panic(err) } app.authenticator.send_verification_mail(config) or { panic(err) }
return app.ok('') return app.ok('')
@@ -40,7 +40,7 @@ pub fn (mut app Controller) send_verification_mail() !vweb.Result {
// route responsible for verifying email, email form should be posted here // route responsible for verifying email, email form should be posted here
@[POST] @[POST]
pub fn (mut app Controller) is_verified() vweb.Result { pub fn (mut app Controller) is_verified() veb.Result {
address := app.req.data address := app.req.data
// checks if email verified every 2 seconds // checks if email verified every 2 seconds
for { for {
@@ -55,7 +55,7 @@ pub fn (mut app Controller) is_verified() vweb.Result {
// route responsible for verifying email, email form should be posted here // route responsible for verifying email, email form should be posted here
@[POST] @[POST]
pub fn (mut app Controller) email_authentication() vweb.Result { pub fn (mut app Controller) email_authentication() veb.Result {
config_ := json.decode(SendMailConfig, app.req.data) or { config_ := json.decode(SendMailConfig, app.req.data) or {
app.set_status(422, 'Request payload does not follow anticipated formatting.') app.set_status(422, 'Request payload does not follow anticipated formatting.')
return app.text('Request payload does not follow anticipated formatting.') return app.text('Request payload does not follow anticipated formatting.')
@@ -84,7 +84,7 @@ pub fn (mut app Controller) email_authentication() vweb.Result {
// route responsible for verifying email, email form should be posted here // route responsible for verifying email, email form should be posted here
@[POST] @[POST]
pub fn (mut app Controller) verify() vweb.Result { pub fn (mut app Controller) verify() veb.Result {
config_ := json.decode(SendMailConfig, app.req.data) or { config_ := json.decode(SendMailConfig, app.req.data) or {
app.set_status(422, 'Request payload does not follow anticipated formatting.') app.set_status(422, 'Request payload does not follow anticipated formatting.')
return app.text('Request payload does not follow anticipated formatting.') return app.text('Request payload does not follow anticipated formatting.')
@@ -126,7 +126,7 @@ pub:
} }
@[POST] @[POST]
pub fn (mut app Controller) authenticate() !vweb.Result { pub fn (mut app Controller) authenticate() !veb.Result {
attempt := json.decode(AuthAttempt, app.req.data)! attempt := json.decode(AuthAttempt, app.req.data)!
app.authenticator.authenticate(attempt.address, attempt.cypher) or { app.authenticator.authenticate(attempt.address, attempt.cypher) or {
app.set_status(401, err.msg()) app.set_status(401, err.msg())
@@ -136,7 +136,7 @@ pub fn (mut app Controller) authenticate() !vweb.Result {
} }
@['/authentication_link/:address/:cypher'] @['/authentication_link/:address/:cypher']
pub fn (mut app Controller) authentication_link(address string, cypher string) !vweb.Result { pub fn (mut app Controller) authentication_link(address string, cypher string) !veb.Result {
app.authenticator.authenticate(address, cypher) or { app.authenticator.authenticate(address, cypher) or {
app.set_status(401, err.msg()) app.set_status(401, err.msg())
return app.text('Failed to authenticate') return app.text('Failed to authenticate')

View File

@@ -10,7 +10,7 @@ import crypto.rand
import os import os
// JWT code in this page is from // JWT code in this page is from
// https://github.com/vlang/v/blob/master/examples/vweb_orm_jwt/src/auth_services.v // https://github.com/vlang/v/blob/master/examples/veb_orm_jwt/src/auth_services.v
// credit to https://github.com/enghitalo // credit to https://github.com/enghitalo
pub struct JsonWebToken { pub struct JsonWebToken {

View File

@@ -2,7 +2,7 @@ module @{name}
import os import os
import cli { Command } import cli { Command }
import vweb import veb
import freeflowuniverse.herolib.schemas.openrpc import freeflowuniverse.herolib.schemas.openrpc
import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.core.pathlib
@@ -54,7 +54,7 @@ fn playground(cmd Command) ! {
dest: pathlib.get_dir(path: playground_path)! dest: pathlib.get_dir(path: playground_path)!
specs: [pathlib.get_file(path:openrpc_path)!] specs: [pathlib.get_file(path:openrpc_path)!]
)! )!
vweb.run(pg, 8080) veb.run(pg, 8080)
} }

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env -S v -n -cg -w -enable-globals run #!/usr/bin/env -S v -n -cg -w -enable-globals run
import freeflowuniverse.herolib.baobab.stages.accountant import freeflowuniverse.herolib.baobab.stages.accountant
import vweb import veb
import freeflowuniverse.herolib.schemas.openrpc import freeflowuniverse.herolib.schemas.openrpc
import os import os
import freeflowuniverse.herolib.core.pathlib import freeflowuniverse.herolib.core.pathlib
@@ -13,4 +13,4 @@ pg := openrpc.new_playground(
dest: pathlib.get_dir(path: playground_path)! dest: pathlib.get_dir(path: playground_path)!
specs: [pathlib.get_file(path:openrpc_path)!] specs: [pathlib.get_file(path:openrpc_path)!]
)! )!
vweb.run(pg, 8080) veb.run(pg, 8080)