-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
examples: fullstack vweb example (#16761)
- Loading branch information
Showing
27 changed files
with
759 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[*] | ||
charset = utf-8 | ||
end_of_line = lf | ||
insert_final_newline = true | ||
trim_trailing_whitespace = true | ||
|
||
[*.v] | ||
indent_style = tab | ||
indent_size = 4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
* text=auto eol=lf | ||
*.bat eol=crlf | ||
|
||
**/*.v linguist-language=V | ||
**/*.vv linguist-language=V | ||
**/*.vsh linguist-language=V | ||
**/v.mod linguist-language=V |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Binaries for programs and plugins | ||
main | ||
batata | ||
*.exe | ||
*.exe~ | ||
*.so | ||
*.dylib | ||
*.dll | ||
*.sql | ||
|
||
# Ignore binary output folders | ||
bin/ | ||
|
||
# Ignore common editor/system specific metadata | ||
.DS_Store | ||
.idea/ | ||
.vscode/ | ||
*.iml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2022 Hitalo Souza | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
module main | ||
|
||
import vweb | ||
|
||
['/controller/auth'; post] | ||
pub fn (mut app App) controller_auth(username string, password string) vweb.Result { | ||
response := app.service_auth(username, password) or { | ||
app.set_status(400, '') | ||
return app.text('error: ${err}') | ||
} | ||
|
||
return app.json(response) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module main | ||
|
||
struct AuthRequestDto { | ||
username string [required] | ||
password string [required] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
module main | ||
|
||
import crypto.hmac | ||
import crypto.sha256 | ||
import crypto.bcrypt | ||
import encoding.base64 | ||
import json | ||
import databases | ||
import time | ||
|
||
struct JwtHeader { | ||
alg string | ||
typ string | ||
} | ||
|
||
struct JwtPayload { | ||
sub string // (subject) = Entity to whom the token belongs, usually the user ID; | ||
iss string // (issuer) = Token issuer; | ||
exp string // (expiration) = Timestamp of when the token will expire; | ||
iat time.Time // (issued at) = Timestamp of when the token was created; | ||
aud string // (audience) = Token recipient, represents the application that will use it. | ||
name string | ||
roles string | ||
permissions string | ||
} | ||
|
||
fn (mut app App) service_auth(username string, password string) !string { | ||
mut db := databases.create_db_connection() or { | ||
eprintln(err) | ||
panic(err) | ||
} | ||
|
||
defer { | ||
db.close() or { panic('fail to close database') } | ||
} | ||
|
||
user := sql db { | ||
select from User where username == username limit 1 | ||
} | ||
if user.username != username { | ||
return error('user not found') | ||
} | ||
|
||
if !user.active { | ||
return error('user is not active') | ||
} | ||
|
||
bcrypt.compare_hash_and_password(password.bytes(), user.password.bytes()) or { | ||
return error('Failed to auth user, ${err}') | ||
} | ||
|
||
token := make_token(user) | ||
return token | ||
} | ||
|
||
fn make_token(user User) string { | ||
secret := 'SECRET_KEY' // os.getenv('SECRET_KEY') | ||
|
||
jwt_header := JwtHeader{'HS256', 'JWT'} | ||
jwt_payload := JwtPayload{ | ||
sub: '${user.id}' | ||
name: '${user.username}' | ||
iat: time.now() | ||
} | ||
|
||
header := base64.url_encode(json.encode(jwt_header).bytes()) | ||
payload := base64.url_encode(json.encode(jwt_payload).bytes()) | ||
signature := base64.url_encode(hmac.new(secret.bytes(), '${header}.${payload}'.bytes(), | ||
sha256.sum, sha256.block_size).bytestr().bytes()) | ||
|
||
jwt := '${header}.${payload}.${signature}' | ||
|
||
return jwt | ||
} | ||
|
||
fn auth_verify(token string) bool { | ||
if token == '' { | ||
return false | ||
} | ||
secret := 'SECRET_KEY' // os.getenv('SECRET_KEY') | ||
token_split := token.split('.') | ||
|
||
signature_mirror := hmac.new(secret.bytes(), '${token_split[0]}.${token_split[1]}'.bytes(), | ||
sha256.sum, sha256.block_size).bytestr().bytes() | ||
|
||
signature_from_token := base64.url_decode(token_split[2]) | ||
|
||
return hmac.equal(signature_from_token, signature_mirror) | ||
// return true | ||
} |
8 changes: 8 additions & 0 deletions
8
examples/vweb_fullstack/src/databases/config_databases_sqlite.v
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module databases | ||
|
||
import sqlite // can change to 'mysql', 'pg' | ||
|
||
pub fn create_db_connection() !sqlite.DB { | ||
mut db := sqlite.connect('vweb.sql')! | ||
return db | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
<!DOCTYPE html> | ||
<head> | ||
<!--Let browser know website is optimized for mobile--> | ||
<meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<!-- Compiled and minified CSS --> | ||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css"> | ||
<!-- Compiled and minified JavaScript --> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script> | ||
<!-- Material UI icons --> | ||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> | ||
<title>${title}</title> | ||
</head> | ||
<body> | ||
<div>@include 'templates/header_component.html'</div> | ||
<div class="card-panel center-align" style="max-width: 240px; padding: 10px; margin: 10px; border-radius: 5px;"> | ||
<form id="index_form" method='post' action=''> | ||
<div style="display:flex; flex-direction: column;"> | ||
<input type='text' name='username' placeholder='Username' required autofocus> | ||
<input type='password' name='password' placeholder='Password' required> | ||
</div> | ||
<div style="margin-top: 10px;"> | ||
<input class="waves-effect waves-light btn-small" type='submit' onclick="login()" formaction="javascript:void(0);" value='Login'> | ||
<input class="waves-effect waves-light btn-small" type='submit' onclick="addUser()" formaction="javascript:void(0);" value='Register'> | ||
</div> | ||
</form> | ||
<script type="text/javascript"> | ||
// function eraseCookie(name) { | ||
// document.cookie = name + '=; Max-Age=0' | ||
// } | ||
async function addUser() { | ||
const form = document.querySelector('#index_form'); | ||
const formData = new FormData(form); | ||
await fetch('/controller/user/create', { | ||
method: 'POST', | ||
body: formData | ||
}) | ||
.then( async (response) => { | ||
if (response.status != 201) { | ||
throw await response.text() | ||
} | ||
return await response.text() | ||
}) | ||
.then((data) => { | ||
alert("User created successfully") | ||
}) | ||
.catch((error) => { | ||
alert(error); | ||
}); | ||
} | ||
async function login() { | ||
const form = document.querySelector('#index_form'); | ||
const formData = new FormData(form); | ||
await fetch('/controller/auth', { | ||
method: 'POST', | ||
body: formData | ||
}) | ||
.then( async (response) => { | ||
if (response.status != 200) { | ||
throw await response.text() | ||
} | ||
return response.json() | ||
}) | ||
.then((data) => { | ||
document.cookie = 'token='+data+';'; | ||
window.location.href = '/products' | ||
}) | ||
.catch((error) => { | ||
alert(error); | ||
}); | ||
} | ||
</script> | ||
</div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
module main | ||
|
||
import vweb | ||
import databases | ||
import os | ||
|
||
const ( | ||
port = 8082 | ||
) | ||
|
||
struct App { | ||
vweb.Context | ||
} | ||
|
||
pub fn (app App) before_request() { | ||
println('[web] before_request: ${app.req.method} ${app.req.url}') | ||
} | ||
|
||
fn main() { | ||
mut db := databases.create_db_connection() or { panic(err) } | ||
|
||
sql db { | ||
create table User | ||
} or { panic('error on create table: ${err}') } | ||
|
||
db.close() or { panic(err) } | ||
|
||
mut app := &App{} | ||
app.serve_static('/favicon.ico', 'src/assets/favicon.ico') | ||
// makes all static files available. | ||
app.mount_static_folder_at(os.resource_abs_path('.'), '/') | ||
|
||
vweb.run(app, port) | ||
} | ||
|
||
pub fn (mut app App) index() vweb.Result { | ||
title := 'vweb app' | ||
|
||
return $vweb.html() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
module main | ||
|
||
import vweb | ||
import encoding.base64 | ||
import json | ||
|
||
['/controller/products'; get] | ||
pub fn (mut app App) controller_get_all_products() vweb.Result { | ||
token := app.req.header.get_custom('token') or { '' } | ||
|
||
if !auth_verify(token) { | ||
app.set_status(401, '') | ||
return app.text('Not valid token') | ||
} | ||
|
||
jwt_payload_stringify := base64.url_decode_str(token.split('.')[1]) | ||
|
||
jwt_payload := json.decode(JwtPayload, jwt_payload_stringify) or { | ||
app.set_status(501, '') | ||
return app.text('jwt decode error') | ||
} | ||
|
||
user_id := jwt_payload.sub | ||
|
||
response := app.service_get_all_products_from(user_id.int()) or { | ||
app.set_status(400, '') | ||
return app.text('${err}') | ||
} | ||
return app.json(response) | ||
// return app.text('response') | ||
} | ||
|
||
['/controller/product/create'; post] | ||
pub fn (mut app App) controller_create_product(product_name string) vweb.Result { | ||
if product_name == '' { | ||
app.set_status(400, '') | ||
return app.text('product name cannot be empty') | ||
} | ||
|
||
token := app.req.header.get_custom('token') or { '' } | ||
|
||
if !auth_verify(token) { | ||
app.set_status(401, '') | ||
return app.text('Not valid token') | ||
} | ||
|
||
jwt_payload_stringify := base64.url_decode_str(token.split('.')[1]) | ||
|
||
jwt_payload := json.decode(JwtPayload, jwt_payload_stringify) or { | ||
app.set_status(501, '') | ||
return app.text('jwt decode error') | ||
} | ||
|
||
user_id := jwt_payload.sub | ||
|
||
app.service_add_product(product_name, user_id.int()) or { | ||
app.set_status(400, '') | ||
return app.text('error: ${err}') | ||
} | ||
app.set_status(201, '') | ||
return app.text('product created successfully') | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
module main | ||
|
||
[table: 'products'] | ||
struct Product { | ||
id int [primary; sql: serial] | ||
user_id int | ||
name string [required; sql_type: 'TEXT'] | ||
created_at string [default: 'CURRENT_TIMESTAMP'] | ||
} |
Oops, something went wrong.