diff --git a/git/libgit.v b/git/libgit.v index da1aeec0..08882054 100644 --- a/git/libgit.v +++ b/git/libgit.v @@ -168,7 +168,7 @@ pub fn new_repo(path string) &Repo { println('ff ${ret}') // git_reference_free(head_ref); return &Repo{ - obj: repo_obj + obj: repo_obj path: path } } diff --git a/git/util.v b/git/util.v index eee4f8f5..69a4d7b1 100644 --- a/git/util.v +++ b/git/util.v @@ -51,7 +51,7 @@ pub fn check_git_repo_url(url string) bool { headers.add_custom('User-Agent', 'git/2.30.0') or {} headers.add_custom('Git-Protocol', 'version=2') or {} config := http.FetchConfig{ - url: refs_url + url: refs_url header: headers } response := http.fetch(config) or { return false } diff --git a/highlight/c.v b/highlight/c.v index de4fe6dc..0aa27897 100644 --- a/highlight/c.v +++ b/highlight/c.v @@ -2,13 +2,13 @@ module highlight fn init_c() Lang { return Lang{ - name: 'C' + name: 'C' lang_extensions: ['c'] - line_comments: '//' - mline_comments: ['/*', '*/'] - string_start: ['"', "'"] - color: '#555555' - keywords: [ + line_comments: '//' + mline_comments: ['/*', '*/'] + string_start: ['"', "'"] + color: '#555555' + keywords: [ 'auto', 'double', 'int', diff --git a/highlight/cpp.v b/highlight/cpp.v index dfe5ad74..7c6cf76f 100644 --- a/highlight/cpp.v +++ b/highlight/cpp.v @@ -2,13 +2,13 @@ module highlight fn init_cpp() Lang { return Lang{ - name: 'C++' + name: 'C++' lang_extensions: ['cpp', 'cc', 'hh', 'h'] - line_comments: '//' - mline_comments: ['/*', '*/'] - string_start: ['"', "'"] - color: '#f34b7d' - keywords: [ + line_comments: '//' + mline_comments: ['/*', '*/'] + string_start: ['"', "'"] + color: '#f34b7d' + keywords: [ 'int', 'float', 'while', diff --git a/highlight/d.v b/highlight/d.v index dc9f7382..07690be2 100644 --- a/highlight/d.v +++ b/highlight/d.v @@ -2,13 +2,13 @@ module highlight fn init_d() Lang { return Lang{ - name: 'D' + name: 'D' lang_extensions: ['d'] - line_comments: '//' - mline_comments: ['/*', '*/', '/+', '+/'] - string_start: ['"', "'"] - color: '#ba595e' - keywords: [ + line_comments: '//' + mline_comments: ['/*', '*/', '/+', '+/'] + string_start: ['"', "'"] + color: '#ba595e' + keywords: [ 'abstract', 'alias', 'align', diff --git a/highlight/go.v b/highlight/go.v index b85b3e47..83448de6 100644 --- a/highlight/go.v +++ b/highlight/go.v @@ -2,13 +2,13 @@ module highlight fn init_go() Lang { return Lang{ - name: 'Go' + name: 'Go' lang_extensions: ['go'] - line_comments: '//' - mline_comments: ['/*', '*/'] - string_start: ['"', '`'] - color: '#00add8' - keywords: [ + line_comments: '//' + mline_comments: ['/*', '*/'] + string_start: ['"', '`'] + color: '#00add8' + keywords: [ 'break', 'chan', 'const', diff --git a/highlight/highlight.v b/highlight/highlight.v index dc8a65b4..0503711c 100644 --- a/highlight/highlight.v +++ b/highlight/highlight.v @@ -2,9 +2,7 @@ // Use of this source code is governed by a GPL license that can be found in the LICENSE file. module highlight -const ( - tab = ' ' // ' -) +const tab = ' ' // ' // returns HTML code, number of lines, number of lines with source code pub fn highlight_text(st string, file_path string, commit bool) (string, int, int) { @@ -69,7 +67,7 @@ pub fn highlight_text(st string, file_path string, commit bool) (string, int, in continue } if c == `\t` { - res << highlight.tab.bytes() + res << tab.bytes() continue } if in_comment { diff --git a/highlight/javascript.v b/highlight/javascript.v index bfd0f1d3..3f2cb5f0 100644 --- a/highlight/javascript.v +++ b/highlight/javascript.v @@ -2,13 +2,13 @@ module highlight fn init_js() Lang { return Lang{ - name: 'JavaScript' + name: 'JavaScript' lang_extensions: ['js', 'mjs', 'jsx'] - line_comments: '//' - mline_comments: ['/*', '*/'] - string_start: ['"', "'"] - color: '#f1e05a' - keywords: [ + line_comments: '//' + mline_comments: ['/*', '*/'] + string_start: ['"', "'"] + color: '#f1e05a' + keywords: [ 'break', 'do', 'instanceof', diff --git a/highlight/langs.v b/highlight/langs.v index c8637fd0..6de4a6df 100644 --- a/highlight/langs.v +++ b/highlight/langs.v @@ -2,13 +2,9 @@ // Use of this source code is governed by a GPL license that can be found in the LICENSE file. module highlight -const ( - lang_path = 'langs' -) +const lang_path = 'langs' -const ( - langs = init_langs() -) +const langs = init_langs() pub struct Lang { keywords []string @@ -28,7 +24,7 @@ fn is_source(ext string) bool { pub fn extension_to_lang(ext string) !Lang { ending := ext.split('.').last() - for lang in highlight.langs { + for lang in langs { if ending in lang.lang_extensions { return lang } diff --git a/highlight/lua.v b/highlight/lua.v index 7f764b5d..6a5cfdca 100644 --- a/highlight/lua.v +++ b/highlight/lua.v @@ -2,13 +2,13 @@ module highlight fn init_lua() Lang { return Lang{ - name: 'Lua' + name: 'Lua' lang_extensions: ['lua'] - line_comments: '--' - mline_comments: ['--[[', ']]'] - string_start: ['"', "'"] - color: '#00007d' - keywords: [ + line_comments: '--' + mline_comments: ['--[[', ']]'] + string_start: ['"', "'"] + color: '#00007d' + keywords: [ 'and', 'break', 'do', diff --git a/highlight/markdown.v b/highlight/markdown.v index b4bda8c2..493fe486 100644 --- a/highlight/markdown.v +++ b/highlight/markdown.v @@ -3,73 +3,71 @@ module highlight import markdown import pcre -const ( - allowed_tags = [ - 'a', - 'abbr', - 'b', - 'blockquote', - 'body', - 'br', - 'center', - 'code', - 'dd', - 'details', - 'div', - 'dl', - 'dt', - 'em', - 'font', - 'h1', - 'h2', - 'h3', - 'h4', - 'h5', - 'h6', - 'hr', - 'i', - 'img', - 'kbd', - 'label', - 'li', - 'ol', - 'p', - 'pre', - 'small', - 'source', - 'span', - 'strong', - 'sub', - 'summary', - 'sup', - 'table', - 'tbody', - 'tr', - 'td', - 'th', - 'thead', - 'ul', - 'u', - 'video', - ] - allowed_attributes = [ - 'align', - 'color', - 'controls', - 'height', - 'href', - 'id', - 'src', - 'style', - 'target', - 'title', - 'type', - 'width', - ] - unallowed_schemas = [ - 'javascript:', - ] -) +const allowed_tags = [ + 'a', + 'abbr', + 'b', + 'blockquote', + 'body', + 'br', + 'center', + 'code', + 'dd', + 'details', + 'div', + 'dl', + 'dt', + 'em', + 'font', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'hr', + 'i', + 'img', + 'kbd', + 'label', + 'li', + 'ol', + 'p', + 'pre', + 'small', + 'source', + 'span', + 'strong', + 'sub', + 'summary', + 'sup', + 'table', + 'tbody', + 'tr', + 'td', + 'th', + 'thead', + 'ul', + 'u', + 'video', +] +const allowed_attributes = [ + 'align', + 'color', + 'controls', + 'height', + 'href', + 'id', + 'src', + 'style', + 'target', + 'title', + 'type', + 'width', +] +const unallowed_schemas = [ + 'javascript:', +] pub fn convert_markdown_to_html(code string) string { markdown_code := sanitize_markdown_code(code) @@ -121,7 +119,7 @@ fn sanitize_html_tags_with_re(re string, code string) string { tag_name := tag_parts[0].trim_space().to_lower() tag_attributes := tag_parts[1].trim_space() tag_content := tag_parts[2].trim_space() - is_allowed_tag := highlight.allowed_tags.contains(tag_name) + is_allowed_tag := allowed_tags.contains(tag_name) if !is_allowed_tag { result = result.replace(tag, '') @@ -174,8 +172,8 @@ fn sanitize_html_attributes(attributes string) string { attribute_name := attribute_parts[0].trim_space().to_lower() attribute_value := attribute_parts[1].trim_space() - is_allowed_attribute := highlight.allowed_attributes.contains(attribute_name) - is_unallowed_schemas := highlight.unallowed_schemas.any(attribute_value.starts_with(it)) + is_allowed_attribute := allowed_attributes.contains(attribute_name) + is_unallowed_schemas := unallowed_schemas.any(attribute_value.starts_with(it)) if !is_allowed_attribute || is_unallowed_schemas { result = result.replace(attribute, '') diff --git a/highlight/markdown_test.v b/highlight/markdown_test.v index f8847e70..87b6b4be 100644 --- a/highlight/markdown_test.v +++ b/highlight/markdown_test.v @@ -1,10 +1,8 @@ module highlight -const ( - markdown = ' test' - html = '
test
' -) +const markdown = ' test' +const html = 'test
' fn test_convert_markdown_to_html() { - assert convert_markdown_to_html(highlight.markdown) == highlight.html + assert convert_markdown_to_html(markdown) == html } diff --git a/highlight/python.v b/highlight/python.v index 998a4c0d..92aa1047 100644 --- a/highlight/python.v +++ b/highlight/python.v @@ -2,12 +2,12 @@ module highlight fn init_py() Lang { return Lang{ - name: 'Python' + name: 'Python' lang_extensions: ['py', 'ipynb'] - line_comments: '#' - string_start: ['"', "'", '"""', "'''"] - color: '#3572A5' - keywords: [ + line_comments: '#' + string_start: ['"', "'", '"""', "'''"] + color: '#3572A5' + keywords: [ 'None', 'True', 'and', diff --git a/highlight/typescript.v b/highlight/typescript.v index 54529073..5bbbe698 100644 --- a/highlight/typescript.v +++ b/highlight/typescript.v @@ -2,13 +2,13 @@ module highlight fn init_ts() Lang { return Lang{ - name: 'TypeScript' + name: 'TypeScript' lang_extensions: ['ts', 'tsx'] - line_comments: '//' - mline_comments: ['/*', '*/'] - string_start: ['"', "'"] - color: '#2b7489' - keywords: [ + line_comments: '//' + mline_comments: ['/*', '*/'] + string_start: ['"', "'"] + color: '#2b7489' + keywords: [ 'any', 'as', 'boolean', diff --git a/highlight/v.v b/highlight/v.v index 7b6cfc1f..95e9d581 100644 --- a/highlight/v.v +++ b/highlight/v.v @@ -2,13 +2,13 @@ module highlight fn init_v() Lang { return Lang{ - name: 'V' + name: 'V' lang_extensions: ['v', 'vsh'] - line_comments: '//' - mline_comments: ['/*', '*/'] - string_start: ['"', "'"] - color: '#5d87bd' - keywords: [ + line_comments: '//' + mline_comments: ['/*', '*/'] + string_start: ['"', "'"] + color: '#5d87bd' + keywords: [ 'break', 'const', 'continue', diff --git a/src/activity.v b/src/activity.v index 44bc1721..d3a74b39 100644 --- a/src/activity.v +++ b/src/activity.v @@ -4,7 +4,7 @@ import time struct Activity { mut: - id int @[primary; sql: serial] + id int @[primary; sql: serial] user_id int name string created_at time.Time @@ -12,8 +12,8 @@ mut: fn (app App) add_activity(user_id int, name string) ! { activity := Activity{ - user_id: user_id - name: name + user_id: user_id + name: name created_at: time.now() } diff --git a/src/admin.v b/src/admin.v index 7ba06360..5313f9d4 100644 --- a/src/admin.v +++ b/src/admin.v @@ -40,6 +40,6 @@ pub fn (mut app App) update_gitly_settings(oauth_client_id string, oauth_client_ app.load_settings() } -fn (mut app App) is_admin() bool { - return app.logged_in && app.user.is_admin +fn (mut ctx Context) is_admin() bool { + return ctx.logged_in && ctx.user.is_admin } diff --git a/src/admin_routes.v b/src/admin_routes.v index a4800aee..350d1289 100644 --- a/src/admin_routes.v +++ b/src/admin_routes.v @@ -1,57 +1,55 @@ module main -import vweb +import veb -const ( - admin_users_per_page = 30 -) +const admin_users_per_page = 30 // TODO move to admin controller @['/admin/settings'] -pub fn (mut app App) admin_settings() vweb.Result { - if !app.is_admin() { - return app.redirect_to_index() +pub fn (mut app App) admin_settings() veb.Result { + if !ctx.is_admin() { + return ctx.redirect_to_index() } - return $vweb.html() + return $veb.html() } @['/admin/settings'; post] -pub fn (mut app App) handle_admin_update_settings(oauth_client_id string, oauth_client_secret string) vweb.Result { - if !app.is_admin() { - return app.redirect_to_index() +pub fn (mut app App) handle_admin_update_settings(oauth_client_id string, oauth_client_secret string) veb.Result { + if !ctx.is_admin() { + return ctx.redirect_to_index() } app.update_gitly_settings(oauth_client_id, oauth_client_secret) or { app.info(err.str()) } - return app.redirect('/admin') + return ctx.redirect('/admin') } @['/admin/users/:user'; post] -pub fn (mut app App) handle_admin_edit_user(user_id string) vweb.Result { - if !app.is_admin() { - return app.redirect_to_index() +pub fn (mut app App) handle_admin_edit_user(user_id string) veb.Result { + if !ctx.is_admin() { + return ctx.redirect_to_index() } - clear_session := 'stop-session' in app.form - is_blocked := 'is-blocked' in app.form - is_admin := 'is-admin' in app.form + clear_session := 'stop-session' in ctx.form + is_blocked := 'is-blocked' in ctx.form + is_admin := 'is-admin' in ctx.form app.edit_user(user_id.int(), clear_session, is_blocked, is_admin) or { app.info(err.str()) } - return app.redirect('/admin') + return ctx.redirect('/admin') } @['/admin/users'] -pub fn (mut app App) admin_users_default() vweb.Result { +pub fn (mut app App) admin_users_default() veb.Result { return app.admin_users(0) } @['/admin/users/:page'] -pub fn (mut app App) admin_users(page int) vweb.Result { - if !app.is_admin() { - return app.redirect_to_index() +pub fn (mut app App) admin_users(page int) veb.Result { + if !ctx.is_admin() { + return ctx.redirect_to_index() } user_count := app.get_all_registered_user_count() @@ -62,14 +60,13 @@ pub fn (mut app App) admin_users(page int) vweb.Result { is_last_page := check_last_page(user_count, offset, admin_users_per_page) prev_page, next_page := generate_prev_next_pages(page) - return $vweb.html() + return $veb.html() } @['/admin/statistics'] -pub fn (mut app App) admin_statistics() vweb.Result { - if !app.is_admin() { - return app.redirect_to_index() +pub fn (mut app App) admin_statistics() veb.Result { + if !ctx.is_admin() { + return ctx.redirect_to_index() } - - return $vweb.html() + return $veb.html() } diff --git a/src/avatar.v b/src/avatar.v index 34f0de36..100b3215 100644 --- a/src/avatar.v +++ b/src/avatar.v @@ -2,16 +2,15 @@ module main import os -const ( - default_avatar_name = 'default_avatar.png' - assets_path = 'assets' - avatar_max_file_size = 1 * 1024 * 1024 // 1 megabyte - supported_mime_types = [ - 'image/jpeg', - 'image/png', - 'image/webp', - ] -) +const default_avatar_name = 'default_avatar.png' +const assets_path = 'assets' +const avatar_max_file_size = 1 * 1024 * 1024 // 1 megabyte + +const supported_mime_types = [ + 'image/jpeg', + 'image/png', + 'image/webp', +] fn validate_avatar_content_type(content_type string) bool { return supported_mime_types.contains(content_type) diff --git a/src/branch.v b/src/branch.v index 0b7fb3cb..560131a6 100644 --- a/src/branch.v +++ b/src/branch.v @@ -60,10 +60,10 @@ fn (mut app App) create_branch_or_update(repository_id int, branch_name string, new_branch := Branch{ repo_id: repository_id - name: branch_name - author: author - hash: hash - date: date + name: branch_name + author: author + hash: hash + date: date } sql app.db { diff --git a/src/branch_routes.v b/src/branch_routes.v index d925a770..41e246dd 100644 --- a/src/branch_routes.v +++ b/src/branch_routes.v @@ -1,33 +1,34 @@ module main -import vweb +import veb import api @['/api/v1/:user/:repo_name/branches/count'] -fn (mut app App) handle_branch_count(username string, repo_name string) vweb.Result { - has_access := app.has_user_repo_read_access_by_repo_name(app.user.id, username, repo_name) +fn (mut app App) handle_branch_count(username string, repo_name string) veb.Result { + has_access := app.has_user_repo_read_access_by_repo_name(ctx, ctx.user.id, username, + repo_name) if !has_access { - return app.json_error('Not found') + return ctx.json_error('Not found') } repo := app.find_repo_by_name_and_username(repo_name, username) or { - return app.json_error('Not found') + return ctx.json_error('Not found') } count := app.get_count_repo_branches(repo.id) - return app.json(api.ApiBranchCount{ + return ctx.json(api.ApiBranchCount{ success: true - result: count + result: count }) } @['/:user/:repo/branches'] -pub fn (mut app App) branches(username string, repo_name string) vweb.Result { +pub fn (mut app App) branches(username string, repo_name string) veb.Result { repo := app.find_repo_by_name_and_username(repo_name, username) or { - return app.json_error('Not found') + return ctx.json_error('Not found') } branches := app.get_all_repo_branches(repo.id) - return $vweb.html() + return $veb.html() } diff --git a/src/comment.v b/src/comment.v index 223f02cd..a4248423 100644 --- a/src/comment.v +++ b/src/comment.v @@ -2,13 +2,13 @@ // Use of this source code is governed by a GPL license that can be found in the LICENSE file. module main -import vweb +import veb import validation import time struct Comment { mut: - id int @[primary; sql: serial] + id int @[primary; sql: serial] author_id int issue_id int created_at int @@ -16,31 +16,31 @@ mut: } @['/:username/:repo_name/comments'; post] -pub fn (mut app App) handle_add_comment(username string, repo_name string) vweb.Result { - app.find_repo_by_name_and_username(repo_name, username) or { return app.not_found() } - text := app.form['text'] - issue_id := app.form['issue_id'] +pub fn (mut app App) handle_add_comment(username string, repo_name string) veb.Result { + app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() } + text := ctx.form['text'] + issue_id := ctx.form['issue_id'] is_text_empty := validation.is_string_empty(text) is_issue_id_empty := validation.is_string_empty(issue_id) - if is_text_empty || is_issue_id_empty || !app.logged_in { - app.error('Issue comment is not valid') + if is_text_empty || is_issue_id_empty || !ctx.logged_in { + ctx.error('Issue comment is not valid') return app.issue(username, repo_name, issue_id) } - app.add_issue_comment(app.user.id, issue_id.int(), text) or { - app.error('There was an error while inserting the comment') + app.add_issue_comment(ctx.user.id, issue_id.int(), text) or { + ctx.error('There was an error while inserting the comment') return app.issue(username, repo_name, issue_id) } // TODO: count comments app.increment_issue_comments(issue_id.int()) or { app.info(err.str()) } - return app.redirect('/${username}/${repo_name}/issue/${issue_id}') + return ctx.redirect('/${username}/${repo_name}/issue/${issue_id}') } fn (mut app App) add_issue_comment(author_id int, issue_id int, text string) ! { comment := Comment{ - author_id: author_id - issue_id: issue_id + author_id: author_id + issue_id: issue_id created_at: int(time.now().unix()) - text: text + text: text } sql app.db { diff --git a/src/commit.v b/src/commit.v index eaee504f..624eed5a 100644 --- a/src/commit.v +++ b/src/commit.v @@ -6,13 +6,13 @@ import time struct Commit { mut: - id int @[primary; sql: serial] + id int @[primary; sql: serial] author_id int author string hash string @[unique: 'commit'] created_at int - repo_id int @[unique: 'commit'] - branch_id int @[unique: 'commit'] + repo_id int @[unique: 'commit'] + branch_id int @[unique: 'commit'] message string } @@ -91,13 +91,13 @@ fn (mut app App) add_commit_if_not_exist(repo_id int, branch_id int, last_hash s } new_commit := Commit{ - author_id: author_id - author: author - hash: last_hash + author_id: author_id + author: author + hash: last_hash created_at: date - repo_id: repo_id - branch_id: branch_id - message: message + repo_id: repo_id + branch_id: branch_id + message: message } sql app.db { diff --git a/src/commit_routes.v b/src/commit_routes.v index cd2eda16..098b1c9f 100644 --- a/src/commit_routes.v +++ b/src/commit_routes.v @@ -1,34 +1,35 @@ module main -import vweb +import veb import highlight import time import api @['/api/v1/:user/:repo_name/:branch_name/commits/count'] -fn (mut app App) handle_commits_count(username string, repo_name string, branch_name string) vweb.Result { - has_access := app.has_user_repo_read_access_by_repo_name(app.user.id, username, repo_name) +fn (mut app App) handle_commits_count(username string, repo_name string, branch_name string) veb.Result { + has_access := app.has_user_repo_read_access_by_repo_name(ctx, ctx.user.id, username, + repo_name) if !has_access { - return app.json_error('Not found') + return ctx.json_error('Not found') } repo := app.find_repo_by_name_and_username(repo_name, username) or { - return app.json_error('Not found') + return ctx.json_error('Not found') } branch := app.find_repo_branch_by_name(repo.id, branch_name) count := app.get_repo_commit_count(repo.id, branch.id) - return app.json(api.ApiCommitCount{ + return ctx.json(api.ApiCommitCount{ success: true - result: count + result: count }) } @['/:username/:repo_name/:branch_name/commits/:page'] -pub fn (mut app App) commits(username string, repo_name string, branch_name string, page int) vweb.Result { - repo := app.find_repo_by_name_and_username(repo_name, username) or { return app.not_found() } +pub fn (mut app App) commits(username string, repo_name string, branch_name string, page int) veb.Result { + repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() } branch := app.find_repo_branch_by_name(repo.id, branch_name) commits_count := app.get_repo_commit_count(repo.id, branch.id) @@ -67,20 +68,20 @@ pub fn (mut app App) commits(username string, repo_name string, branch_name stri } } - return $vweb.html() + return $veb.html() } @['/:username/:repo_name/commit/:hash'] -pub fn (mut app App) commit(username string, repo_name string, hash string) vweb.Result { - repo := app.find_repo_by_name_and_username(repo_name, username) or { return app.not_found() } +pub fn (mut app App) commit(username string, repo_name string, hash string) veb.Result { + repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() } is_patch_request := hash.ends_with('.patch') if is_patch_request { commit_hash := hash.trim_string_right('.patch') - patch := repo.get_commit_patch(commit_hash) or { return app.not_found() } + patch := repo.get_commit_patch(commit_hash) or { return ctx.not_found() } - return app.ok(patch) + return ctx.ok(patch) } patch_url := '/${username}/${repo_name}/commit/${hash}.patch' @@ -89,13 +90,13 @@ pub fn (mut app App) commit(username string, repo_name string, hash string) vweb mut all_adds := 0 mut all_dels := 0 - mut sources := map[string]vweb.RawHtml{} + mut sources := map[string]veb.RawHtml{} for change in changes { all_adds += change.additions all_dels += change.deletions src, _, _ := highlight.highlight_text(change.message, change.file, true) - sources[change.file] = vweb.RawHtml(src) + sources[change.file] = veb.RawHtml(src) } - return $vweb.html() + return $veb.html() } diff --git a/src/feed.v b/src/feed.v index 19b22323..a0d54c0e 100644 --- a/src/feed.v +++ b/src/feed.v @@ -43,13 +43,13 @@ fn (mut app App) build_user_feed_as_page(user_id int, offset int) []FeedItem { created_at := time.unix(created_at_unix) item := FeedItem{ - id: item_id++ + id: item_id++ author_name: author_name - created_at: created_at - repo_name: repo.name - repo_owner: repo_owner + created_at: created_at + repo_name: repo.name + repo_owner: repo_owner branch_name: branch.name - message: '${commit_message} (${commit_hash})' + message: '${commit_message} (${commit_hash})' } feed << item diff --git a/src/feed_routes.v b/src/feed_routes.v index 9395f4f3..ae3233d9 100644 --- a/src/feed_routes.v +++ b/src/feed_routes.v @@ -1,21 +1,21 @@ module main -import vweb +import veb @['/:username/feed'] -pub fn (mut app App) user_feed_default(username string) vweb.Result { +pub fn (mut app App) user_feed_default(username string) veb.Result { return app.user_feed(username, 0) } @['/:username/feed/:page'] -pub fn (mut app App) user_feed(username string, page int) vweb.Result { +pub fn (mut app App) user_feed(username string, page int) veb.Result { exists, user := app.check_username(username) - if !exists || app.user.username != user.username { - return app.not_found() + if !exists || ctx.user.username != user.username { + return ctx.not_found() } - user_id := app.user.id + user_id := ctx.user.id item_count := app.get_feed_items_count(user_id) offset := feed_items_per_page * page page_count := calculate_pages(item_count, feed_items_per_page) @@ -37,5 +37,5 @@ pub fn (mut app App) user_feed(username string, page int) vweb.Result { } } - return $vweb.html() + return $veb.html() } diff --git a/src/file_template.v b/src/file_template.v index a0b18344..5ddf6f05 100644 --- a/src/file_template.v +++ b/src/file_template.v @@ -1,6 +1,6 @@ module main -import vweb +import veb import regex fn replace_issue_id(re regex.RE, in_txt string, _ int, _ int) string { @@ -9,7 +9,7 @@ fn replace_issue_id(re regex.RE, in_txt string, _ int, _ int) string { return in_txt.replace(issue_id, '${issue_id}') } -fn (f File) format_commit_message() vweb.RawHtml { +fn (f File) format_commit_message() veb.RawHtml { id_query := r'(#\d+)' mut re := regex.regex_opt(id_query) or { panic(err) } diff --git a/src/git_routes.v b/src/git_routes.v index deddad70..0a6e81ea 100644 --- a/src/git_routes.v +++ b/src/git_routes.v @@ -2,97 +2,98 @@ // Use of this source code is governed by a GPL license that can be found in the LICENSE file. module main -import vweb +import veb import git import compress.deflate +import net.http @['/:username/:repo_name/info/refs'] -fn (mut app App) handle_git_info(username string, git_repo_name string) vweb.Result { +fn (mut app App) handle_git_info(username string, git_repo_name string) veb.Result { repo_name := git.remove_git_extension_if_exists(git_repo_name) - user := app.get_user_by_username(username) or { return app.not_found() } - repo := app.find_repo_by_name_and_user_id(repo_name, user.id) or { return app.not_found() } - service := extract_service_from_url(app.req.url) + user := app.get_user_by_username(username) or { return ctx.not_found() } + repo := app.find_repo_by_name_and_user_id(repo_name, user.id) or { return ctx.not_found() } + service := extract_service_from_url(ctx.req.url) if service == .unknown { - return app.not_found() + return ctx.not_found() } is_receive_service := service == .receive is_private_repo := !repo.is_public if is_receive_service || is_private_repo { - app.check_git_http_access(username, repo_name) or { return app.ok('') } + app.check_git_http_access(mut ctx, username, repo_name) or { return ctx.ok('') } } refs := repo.git_advertise(service.str()) git_response := build_git_service_response(service, refs) - app.set_content_type('application/x-git-${service}-advertisement') - app.set_no_cache_headers() + ctx.set_content_type('application/x-git-${service}-advertisement') + ctx.set_no_cache_headers() - return app.ok(git_response) + return ctx.ok(git_response) } @['/:user/:repo_name/git-upload-pack'; post] -fn (mut app App) handle_git_upload_pack(username string, git_repo_name string) vweb.Result { - body := app.parse_body() +fn (mut app App) handle_git_upload_pack(username string, git_repo_name string) veb.Result { + body := ctx.parse_body() repo_name := git.remove_git_extension_if_exists(git_repo_name) - user := app.get_user_by_username(username) or { return app.not_found() } - repo := app.find_repo_by_name_and_user_id(repo_name, user.id) or { return app.not_found() } + user := app.get_user_by_username(username) or { return ctx.not_found() } + repo := app.find_repo_by_name_and_user_id(repo_name, user.id) or { return ctx.not_found() } is_private_repo := !repo.is_public if is_private_repo { - app.check_git_http_access(username, repo_name) or { return app.ok('') } + app.check_git_http_access(mut ctx, username, repo_name) or { return ctx.ok('') } } git_response := repo.git_smart('upload-pack', body) - app.set_git_content_type_headers(.upload) + ctx.set_git_content_type_headers(.upload) - return app.ok(git_response) + return ctx.ok(git_response) } @['/:user/:repo_name/git-receive-pack'; post] -fn (mut app App) handle_git_receive_pack(username string, git_repo_name string) vweb.Result { - body := app.parse_body() +fn (mut app App) handle_git_receive_pack(username string, git_repo_name string) veb.Result { + body := ctx.parse_body() repo_name := git.remove_git_extension_if_exists(git_repo_name) - user := app.get_user_by_username(username) or { return app.not_found() } - repo := app.find_repo_by_name_and_user_id(repo_name, user.id) or { return app.not_found() } + user := app.get_user_by_username(username) or { return ctx.not_found() } + repo := app.find_repo_by_name_and_user_id(repo_name, user.id) or { return ctx.not_found() } - app.check_git_http_access(username, repo_name) or { return app.ok('') } + app.check_git_http_access(mut ctx, username, repo_name) or { return ctx.ok('') } git_response := repo.git_smart('receive-pack', body) branch_name := git.parse_branch_name_from_receive_upload(body) or { - app.send_internal_error('Receive upload parsing error') + ctx.send_internal_error('Receive upload parsing error') - return app.ok('') + return ctx.ok('') } app.update_repo_after_push(repo.id, branch_name) or { - app.send_internal_error('There was an error while updating the repo') + ctx.send_internal_error('There was an error while updating the repo') - return app.ok('') + return ctx.ok('') } - app.set_git_content_type_headers(.receive) + ctx.set_git_content_type_headers(.receive) - return app.ok(git_response) + return ctx.ok(git_response) } -fn (mut app App) check_git_http_access(repository_owner string, repository_name string) ?bool { - has_valid_auth_header := app.check_basic_authorization_header() +fn (mut app App) check_git_http_access(mut ctx Context, repository_owner string, repository_name string) ?bool { + has_valid_auth_header := ctx.check_basic_authorization_header() if !has_valid_auth_header { - app.set_authenticate_headers() - app.send_unauthorized() + ctx.set_authenticate_headers() + ctx.send_unauthorized() } - has_user_valid_credentials := app.check_user_credentials() + has_user_valid_credentials := app.check_user_credentials(ctx) if has_user_valid_credentials { - username, _ := app.extract_user_credentials() or { - app.send_unauthorized() + username, _ := ctx.extract_user_credentials() or { + ctx.send_unauthorized() return none } @@ -101,36 +102,25 @@ fn (mut app App) check_git_http_access(repository_owner string, repository_name if has_user_access { return true } else { - app.send_not_found() + ctx.send_not_found() return none } } - app.send_unauthorized() + ctx.send_unauthorized() return none } -fn (mut app App) check_basic_authorization_header() bool { - auth_header := app.get_header('Authorization') - has_auth_header := auth_header.len > 0 - - if !has_auth_header { - return false - } - +fn (ctx &Context) check_basic_authorization_header() bool { + auth_header := ctx.get_header(.authorization) or { return false } auth_header_parts := auth_header.fields() auth_type := auth_header_parts[0] is_basic_auth_type := auth_type == 'Basic' - - if auth_header_parts.len == 2 || is_basic_auth_type { - return true - } - - return false + return auth_header_parts.len == 2 || is_basic_auth_type } -fn (mut app App) extract_user_credentials() ?(string, string) { - auth_header := app.get_header('Authorization') +fn (ctx &Context) extract_user_credentials() ?(string, string) { + auth_header := ctx.get_header(.authorization) or { return none } auth_header_parts := auth_header.fields() if auth_header_parts.len < 2 { @@ -140,24 +130,24 @@ fn (mut app App) extract_user_credentials() ?(string, string) { return decode_basic_auth(auth_header_parts[1]) } -fn (mut app App) check_user_credentials() bool { - username, password := app.extract_user_credentials() or { return false } +fn (mut app App) check_user_credentials(ctx &Context) bool { + username, password := ctx.extract_user_credentials() or { return false } user := app.get_user_by_username(username) or { return false } return compare_password_with_hash(password, user.salt, user.password) } -fn (mut app App) set_no_cache_headers() { - app.add_header('Expires', 'Fri, 01 Jan 1980 00:00:00 GMT') - app.add_header('Pragma', 'no-cache') - app.add_header('Cache-Control', 'no-cache, max-age=0, must-revalidate') +fn (mut app Context) set_no_cache_headers() { + app.set_header(.expires, 'Fri, 01 Jan 1980 00:00:00 GMT') + app.set_header(.pragma, 'no-cache') + app.set_header(.cache_control, 'no-cache, max-age=0, must-revalidate') } -fn (mut app App) set_authenticate_headers() { - app.add_header('WWW-Authenticate', 'Basic realm="."') +fn (mut app Context) set_authenticate_headers() { + app.set_header(.www_authenticate, 'Basic realm="."') } -fn (mut app App) set_git_content_type_headers(service GitService) { +fn (mut app Context) set_git_content_type_headers(service GitService) { if service == .upload { app.set_content_type('application/x-git-upload-pack-result') } else if service == .receive { @@ -165,35 +155,38 @@ fn (mut app App) set_git_content_type_headers(service GitService) { } } -fn (mut app App) send_internal_error(custom_message string) { +fn (mut app Context) send_internal_error(custom_message string) { message := if custom_message == '' { 'Internal Server error' } else { custom_message } app.send_custom_error(500, message) } -fn (mut app App) send_unauthorized() { +fn (mut app Context) send_unauthorized() { app.send_custom_error(401, 'Unauthorized') } -fn (mut app App) send_not_found() { +fn (mut app Context) send_not_found() { app.send_custom_error(404, 'Not Found') } -fn (mut app App) send_custom_error(code int, text string) { - app.set_status(code, text) - app.send_response_to_client(vweb.mime_types['.txt'], '') +fn (mut app Context) send_custom_error(code int, text string) { + // app.set_status(code, text) + app.res.set_status(unsafe { http.Status(code) }) + app.send_response_to_client(veb.mime_types['.txt'], '') } -fn (mut app App) parse_body() string { +fn (mut app Context) parse_body() string { body := app.req.data - if app.get_header('Content-Encoding') == 'gzip' { - decompressed := deflate.decompress(body.bytes()[10..]) or { - println(err) - return body - } + if h := app.get_header(.content_encoding) { + if h == 'gzip' { + decompressed := deflate.decompress(body.bytes()[10..]) or { + println(err) + return body + } - return decompressed.bytestr() + return decompressed.bytestr() + } } return body diff --git a/src/github.v b/src/github.v index b30540af..748d8613 100644 --- a/src/github.v +++ b/src/github.v @@ -2,10 +2,11 @@ // Use of this source code is governed by a GPL license that can be found in the LICENSE file. module main -import vweb +import veb import json import net.http -import veb.auth as oauth +// import veb.auth as oauth +import veb.oauth struct GitHubUser { username string @[json: 'login'] @@ -15,43 +16,43 @@ struct GitHubUser { } @['/oauth'] -pub fn (mut app App) handle_oauth() vweb.Result { - code := app.query['code'] - state := app.query['state'] +pub fn (mut app App) handle_oauth() veb.Result { + code := ctx.query['code'] + state := ctx.query['state'] if code == '' { - app.add_security_log(user_id: app.user.id, kind: .empty_oauth_code) or { + app.add_security_log(user_id: ctx.user.id, kind: .empty_oauth_code) or { app.info(err.str()) } app.info('Code is empty') - return app.redirect_to_index() + return ctx.redirect_to_index() } - csrf := app.get_cookie('csrf') or { return app.redirect_to_index() } + csrf := ctx.get_cookie('csrf') or { return ctx.redirect_to_index() } if csrf != state || csrf == '' { app.add_security_log( - user_id: app.user.id - kind: .wrong_oauth_state - arg1: 'csrf=${csrf}' - arg2: 'state=${state}' + user_id: ctx.user.id + kind: .wrong_oauth_state + arg1: 'csrf=${csrf}' + arg2: 'state=${state}' ) or { app.info(err.str()) } - return app.redirect_to_index() + return ctx.redirect_to_index() } oauth_request := oauth.Request{ - client_id: app.settings.oauth_client_id + client_id: app.settings.oauth_client_id client_secret: app.settings.oauth_client_secret - code: code - state: csrf + code: code + state: csrf } js := json.encode(oauth_request) access_response := http.post_json('https://github.com/login/oauth/access_token', js) or { app.info(err.msg()) - return app.redirect_to_index() + return ctx.redirect_to_index() } mut token := access_response.body.find_between('access_token=', '&') @@ -61,22 +62,22 @@ pub fn (mut app App) handle_oauth() vweb.Result { user_response := request.do() or { app.info(err.msg()) - return app.redirect_to_index() + return ctx.redirect_to_index() } if user_response.status_code != 200 { app.info(user_response.status_code.str()) app.info(user_response.body) - return app.text('Received ${user_response.status_code} error while attempting to contact GitHub') + return ctx.text('Received ${user_response.status_code} error while attempting to contact GitHub') } - github_user := json.decode(GitHubUser, user_response.body) or { return app.redirect_to_index() } + github_user := json.decode(GitHubUser, user_response.body) or { return ctx.redirect_to_index() } if github_user.email.trim_space().len == 0 { app.add_security_log( - user_id: app.user.id - kind: .empty_oauth_email - arg1: user_response.body + user_id: ctx.user.id + kind: .empty_oauth_email + arg1: user_response.body ) or { app.info(err.str()) } app.info('Email is empty') } @@ -87,8 +88,8 @@ pub fn (mut app App) handle_oauth() vweb.Result { // Register a new user via github app.add_security_log( user_id: user.id - kind: .registered_via_github - arg1: user_response.body + kind: .registered_via_github + arg1: user_response.body ) or { app.info(err.str()) } app.register_user(github_user.username, '', '', [github_user.email], true, false) or { @@ -96,16 +97,16 @@ pub fn (mut app App) handle_oauth() vweb.Result { } user = app.get_user_by_github_username(github_user.username) or { - return app.redirect_to_index() + return ctx.redirect_to_index() } app.update_user_avatar(user.id, github_user.avatar) or { app.info(err.msg()) } } - app.auth_user(user, app.ip()) or { app.info(err.msg()) } + app.auth_user(mut ctx, user, ctx.ip()) or { app.info(err.msg()) } app.add_security_log(user_id: user.id, kind: .logged_in_via_github, arg1: user_response.body) or { app.info(err.str()) } - return app.redirect_to_index() + return ctx.redirect_to_index() } diff --git a/src/gitly.v b/src/gitly.v index da61d235..4adab955 100644 --- a/src/gitly.v +++ b/src/gitly.v @@ -2,7 +2,7 @@ // Use of this source code is governed by a GPL license that can be found in the LICENSE file. module main -import vweb +import veb import time import os import log @@ -10,33 +10,37 @@ import db.sqlite import api import config -const ( - commits_per_page = 35 - expire_length = 200 - posts_per_day = 5 - max_username_len = 40 - max_login_attempts = 5 - max_user_repos = 10 - max_repo_name_len = 100 - max_namechanges = 3 - namechange_period = time.hour * 24 -) - -struct App { - vweb.Context - started_at i64 @[vweb_global] +const commits_per_page = 35 +const expire_length = 200 +const posts_per_day = 5 +const max_username_len = 40 +const max_login_attempts = 5 +const max_user_repos = 10 +const max_repo_name_len = 100 +const max_namechanges = 3 +const namechange_period = time.hour * 24 + +@[heap] +pub struct App { + veb.StaticHandler + started_at i64 pub mut: db sqlite.DB mut: - version string @[vweb_global] - logger log.Log @[vweb_global] - config config.Config @[vweb_global] - settings Settings + version string + logger log.Log + config config.Config + settings Settings +} + +pub struct Context { + veb.Context +mut: + user User current_path string page_gen_time string is_tree bool logged_in bool - user User path_split []string branch string } @@ -47,7 +51,7 @@ fn new_app() !&App { C.sqlite3_config(3) mut app := &App{ - db: sqlite.connect('gitly.sqlite') or { panic(err) } + db: sqlite.connect('gitly.sqlite') or { panic(err) } started_at: time.now().unix() } @@ -72,8 +76,8 @@ fn new_app() !&App { app.version = version - app.handle_static('src/static', true) - app.handle_static('avatars', false) + app.handle_static('src/static', true)! + app.handle_static('avatars', false)! app.load_settings() @@ -123,40 +127,40 @@ pub fn (mut app App) debug(msg string) { pub fn (mut app App) init_server() { } -pub fn (mut app App) before_request() { - app.logged_in = app.is_logged_in() +pub fn (mut app App) before_request(mut ctx Context) { + ctx.logged_in = app.is_logged_in() app.load_settings() - if app.logged_in { - app.user = app.get_user_from_cookies() or { - app.logged_in = false + if ctx.logged_in { + ctx.user = app.get_user_from_cookies() or { + ctx.logged_in = false User{} } } } @['/'] -pub fn (mut app App) index() vweb.Result { +pub fn (mut app App) index() veb.Result { user_count := app.get_users_count() or { 0 } no_users := user_count == 0 if no_users { - return app.redirect('/register') + return ctx.redirect('/register') } - return $vweb.html() + return $veb.html() } -pub fn (mut app App) redirect_to_index() vweb.Result { - return app.redirect('/') +pub fn (mut ctx Context) redirect_to_index() veb.Result { + return ctx.redirect('/') } -pub fn (mut app App) redirect_to_login() vweb.Result { - return app.redirect('/login') +pub fn (mut ctx Context) redirect_to_login() veb.Result { + return ctx.redirect('/login') } -pub fn (mut app App) redirect_to_repository(username string, repo_name string) vweb.Result { - return app.redirect('/${username}/${repo_name}') +pub fn (mut ctx Context) redirect_to_repository(username string, repo_name string) veb.Result { + return ctx.redirect('/${username}/${repo_name}') } fn (mut app App) create_tables() ! { @@ -223,25 +227,25 @@ fn (mut app App) create_tables() ! { }! } -fn (mut app App) json_success[T](result T) vweb.Result { +fn (mut ctx Context) json_success[T](result T) veb.Result { response := api.ApiSuccessResponse[T]{ success: true - result: result + result: result } - return app.json(response) + return ctx.json(response) } -fn (mut app App) json_error(message string) vweb.Result { - return app.json(api.ApiErrorResponse{ +fn (mut ctx Context) json_error(message string) veb.Result { + return ctx.json(api.ApiErrorResponse{ success: false message: message }) } // maybe it should be implemented with another static server, in dev -fn (mut app App) send_file(filname string, content string) vweb.Result { - app.add_header('Content-Disposition', 'attachment; filename="${filname}"') +fn (mut app App) send_file(filname string, content string) veb.Result { + ctx.set_header(.content_disposition, 'attachment; filename="${filname}"') - return app.ok(content) + return ctx.ok(content) } diff --git a/src/issue.v b/src/issue.v index 8c3c4bdc..c384f9ab 100644 --- a/src/issue.v +++ b/src/issue.v @@ -10,8 +10,8 @@ mut: author_id int repo_id int is_pr bool - assigned []int @[skip] - labels []int @[skip] + assigned []int @[skip] + labels []int @[skip] comments_count int title string text string @@ -35,10 +35,10 @@ struct Label { fn (mut app App) add_issue(repo_id int, author_id int, title string, text string) ! { issue := Issue{ - title: title - text: text - repo_id: repo_id - author_id: author_id + title: title + text: text + repo_id: repo_id + author_id: author_id created_at: int(time.now().unix()) } diff --git a/src/issue_routes.v b/src/issue_routes.v index edc515b2..823fd41b 100644 --- a/src/issue_routes.v +++ b/src/issue_routes.v @@ -1,6 +1,6 @@ module main -import vweb +import veb import validation import api @@ -13,67 +13,68 @@ type IssueWithUser = ItemWithUser[Issue] type CommentWithUser = ItemWithUser[Comment] @['/api/v1/:username/:repo_name/issues/count'] -fn (mut app App) handle_issues_count(username string, repo_name string) vweb.Result { - has_access := app.has_user_repo_read_access_by_repo_name(app.user.id, username, repo_name) +fn (mut app App) handle_issues_count(username string, repo_name string) veb.Result { + has_access := app.has_user_repo_read_access_by_repo_name(ctx, ctx.user.id, username, + repo_name) if !has_access { - return app.json_error('Not found') + return ctx.json_error('Not found') } repo := app.find_repo_by_name_and_username(repo_name, username) or { - return app.json_error('Not found') + return ctx.json_error('Not found') } count := app.get_repo_issue_count(repo.id) - return app.json(api.ApiIssueCount{ + return ctx.json(api.ApiIssueCount{ success: true - result: count + result: count }) } @['/:username/:repo_name/issues/new'] -pub fn (mut app App) new_issue(username string, repo_name string) vweb.Result { - if !app.logged_in { - return app.not_found() +pub fn (mut app App) new_issue(username string, repo_name string) veb.Result { + if !ctx.logged_in { + return ctx.not_found() } - repo := app.find_repo_by_name_and_username(repo_name, username) or { return app.not_found() } - return $vweb.html() + repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() } + return $veb.html() } @['/:username/issues'] -pub fn (mut app App) handle_get_user_issues(username string) vweb.Result { +pub fn (mut app App) handle_get_user_issues(username string) veb.Result { return app.user_issues(username, 0) } @['/:username/:repo_name/issues'; post] -pub fn (mut app App) handle_add_repo_issue(username string, repo_name string) vweb.Result { +pub fn (mut app App) handle_add_repo_issue(username string, repo_name string) veb.Result { // TODO: use captcha instead of user restrictions - if !app.logged_in || (app.logged_in && app.user.posts_count >= posts_per_day) { - return app.redirect_to_index() + if !ctx.logged_in || (ctx.logged_in && ctx.user.posts_count >= posts_per_day) { + return ctx.redirect_to_index() } - repo := app.find_repo_by_name_and_username(repo_name, username) or { return app.not_found() } - title := app.form['title'] - text := app.form['text'] + repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() } + title := ctx.form['title'] + text := ctx.form['text'] is_title_empty := validation.is_string_empty(title) is_text_empty := validation.is_string_empty(text) if is_title_empty || is_text_empty { - return app.redirect('/${username}/${repo_name}/issues/new') + return ctx.redirect('/${username}/${repo_name}/issues/new') } - app.increment_user_post(mut app.user) or { app.info(err.str()) } - app.add_issue(repo.id, app.user.id, title, text) or { app.info(err.str()) } + app.increment_user_post(mut ctx.user) or { app.info(err.str()) } + app.add_issue(repo.id, ctx.user.id, title, text) or { app.info(err.str()) } app.increment_repo_issues(repo.id) or { app.info(err.str()) } - has_first_issue_activity := app.has_activity(app.user.id, 'first_issue') + has_first_issue_activity := app.has_activity(ctx.user.id, 'first_issue') if !has_first_issue_activity { - app.add_activity(app.user.id, 'first_issue') or { app.info(err.str()) } + app.add_activity(ctx.user.id, 'first_issue') or { app.info(err.str()) } } - return app.redirect('/${username}/${repo_name}/issues') + return ctx.redirect('/${username}/${repo_name}/issues') } @['/:username/:repo_name/issues'] -pub fn (mut app App) handle_get_repo_issues(username string, repo_name string) vweb.Result { +pub fn (mut app App) handle_get_repo_issues(username string, repo_name string) veb.Result { return app.issues(username, repo_name, 0) } @['/:username/:repo_name/issues/:page'] -pub fn (mut app App) issues(username string, repo_name string, page int) vweb.Result { - repo := app.find_repo_by_name_and_username(repo_name, username) or { return app.not_found() } +pub fn (mut app App) issues(username string, repo_name string, page int) veb.Result { + repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() } mut issues_with_users := []IssueWithUser{} for issue in app.find_repo_issues_as_page(repo.id, page) { user := app.get_user_by_id(issue.author_id) or { continue } @@ -100,14 +101,14 @@ pub fn (mut app App) issues(username string, repo_name string, page int) vweb.Re } page_count := calculate_pages(repo.nr_open_issues, commits_per_page) prev_page, next_page := generate_prev_next_pages(page) - return $vweb.html() + return $veb.html() } @['/:username/:repo_name/issue/:id'] -pub fn (mut app App) issue(username string, repo_name string, id string) vweb.Result { - repo := app.find_repo_by_name_and_username(repo_name, username) or { return app.not_found() } - issue := app.find_issue_by_id(id.int()) or { return app.not_found() } - issue_author := app.get_user_by_id(issue.author_id) or { return app.not_found() } +pub fn (mut app App) issue(username string, repo_name string, id string) veb.Result { + repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() } + issue := app.find_issue_by_id(id.int()) or { return ctx.not_found() } + issue_author := app.get_user_by_id(issue.author_id) or { return ctx.not_found() } mut comments_with_users := []CommentWithUser{} for comment in app.get_all_issue_comments(issue.id) { user := app.get_user_by_id(comment.author_id) or { continue } @@ -116,20 +117,20 @@ pub fn (mut app App) issue(username string, repo_name string, id string) vweb.Re user: user } } - return $vweb.html() + return $veb.html() } @['/:username/issues/:page'] -pub fn (mut app App) user_issues(username string, page int) vweb.Result { - if !app.logged_in { - return app.not_found() +pub fn (mut app App) user_issues(username string, page int) veb.Result { + if !ctx.logged_in { + return ctx.not_found() } - if app.user.username != username { - return app.not_found() + if ctx.user.username != username { + return ctx.not_found() } exists, user := app.check_username(username) if !exists { - return app.not_found() + return ctx.not_found() } mut issues := app.find_user_issues(user.id) mut first := false @@ -166,5 +167,5 @@ pub fn (mut app App) user_issues(username string, page int) vweb.Result { last_site = page - 1 } next_site := page + 1 - return $vweb.html() + return $veb.html() } diff --git a/src/lang_stats.v b/src/lang_stats.v index 3179b6d6..fe0461e4 100644 --- a/src/lang_stats.v +++ b/src/lang_stats.v @@ -1,6 +1,6 @@ module main -import vweb +import veb struct LangStat { id int @[primary; sql: serial] @@ -11,22 +11,20 @@ struct LangStat { color string } -const ( - test_lang_stats = [ - LangStat{ - name: 'V' - pct: 989 - lines_count: 96657 - color: '#5d87bd' - }, - LangStat{ - name: 'JavaScript' - lines_count: 1131 - color: '#f1e05a' - pct: 11 - }, - ] -) +const test_lang_stats = [ + LangStat{ + name: 'V' + pct: 989 + lines_count: 96657 + color: '#5d87bd' + }, + LangStat{ + name: 'JavaScript' + lines_count: 1131 + color: '#f1e05a' + pct: 11 + }, +] fn (app App) add_lang_stat(lang_stat LangStat) ! { sql app.db { @@ -34,7 +32,7 @@ fn (app App) add_lang_stat(lang_stat LangStat) ! { }! } -pub fn (l &LangStat) pct_html() vweb.RawHtml { +pub fn (l &LangStat) pct_html() veb.RawHtml { x := f64(l.pct) / 10.0 sloc := if l.lines_count < 1000 { l.lines_count.str() diff --git a/src/main.v b/src/main.v index 676f4adf..ac4f69e8 100644 --- a/src/main.v +++ b/src/main.v @@ -1,5 +1,5 @@ import os -import vweb +import veb const http_port = os.getenv_opt('GITLY_PORT') or { '8080' }.int() @@ -7,5 +7,10 @@ fn main() { if os.args.contains('ci_run') { return } - vweb.run(new_app()!, http_port) + mut app := new_app()! + // vweb.run_at(new_app()!, http_port) + + veb.run_at[App, Context](mut app, port: http_port, family: .ip, timeout_in_seconds: 2) or { + panic(err) + } } diff --git a/src/release.v b/src/release.v index 48fa5c5f..fd133b2b 100644 --- a/src/release.v +++ b/src/release.v @@ -6,20 +6,20 @@ struct Release { id int @[primary; sql: serial] repo_id int @[unique: 'release'] mut: - tag_id int @[unique: 'release'] + tag_id int @[unique: 'release'] notes string - tag_name string @[skip] - tag_hash string @[skip] - user string @[skip] + tag_name string @[skip] + tag_hash string @[skip] + user string @[skip] date time.Time } pub fn (mut app App) add_release(tag_id int, repo_id int, date time.Time, notes string) ! { release := Release{ - tag_id: tag_id + tag_id: tag_id repo_id: repo_id - notes: notes - date: date + notes: notes + date: date } sql app.db { diff --git a/src/release_routes.v b/src/release_routes.v index 7b633c5e..a5f7b929 100644 --- a/src/release_routes.v +++ b/src/release_routes.v @@ -1,18 +1,18 @@ module main -import vweb +import veb import time const releases_per_page = 20 @['/:username/:repo_name/releases'] -pub fn (mut app App) releases_default(username string, repo_name string) vweb.Result { +pub fn (mut app App) releases_default(username string, repo_name string) veb.Result { return app.releases(username, repo_name, 0) } @['/:username/:repo_name/releases/:page'] -pub fn (mut app App) releases(username string, repo_name string, page int) vweb.Result { - repo := app.find_repo_by_name_and_username(repo_name, username) or { return app.not_found() } +pub fn (mut app App) releases(username string, repo_name string, page int) veb.Result { + repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() } repo_id := repo.id mut releases := []Release{} @@ -53,5 +53,5 @@ pub fn (mut app App) releases(username string, repo_name string, page int) vweb. releases << release } - return $vweb.html() + return $veb.html() } diff --git a/src/repo.v b/src/repo.v index 4609a966..e249ea3c 100644 --- a/src/repo.v +++ b/src/repo.v @@ -9,32 +9,32 @@ import highlight import validation struct Repo { - id int @[primary; sql: serial] + id int @[primary; sql: serial] git_dir string name string user_id int user_name string - clone_url string @[skip] + clone_url string @[skip] primary_branch string description string is_public bool - users_contributed []string @[skip] - users_authorized []string @[skip] - nr_topics int @[skip] + users_contributed []string @[skip] + users_authorized []string @[skip] + nr_topics int @[skip] views_count int latest_update_hash string @[skip] latest_activity time.Time @[skip] mut: - git_repo &git.Repo = unsafe { nil } @[skip] // libgit wrapper repo + git_repo &git.Repo = unsafe { nil } @[skip] // libgit wrapper repo webhook_secret string tags_count int - nr_open_issues int @[orm: 'open_issues_count'] - nr_open_prs int @[orm: 'open_prs_count'] - nr_releases int @[orm: 'releases_count'] - nr_branches int @[orm: 'branches_count'] + nr_open_issues int @[orm: 'open_issues_count'] + nr_open_prs int @[orm: 'open_prs_count'] + nr_releases int @[orm: 'releases_count'] + nr_branches int @[orm: 'branches_count'] nr_tags int - nr_stars int @[orm: 'stars_count'] - lang_stats []LangStat @[skip] + nr_stars int @[orm: 'stars_count'] + lang_stats []LangStat @[skip] created_at int nr_contributors int labels []Label @[skip] @@ -144,12 +144,12 @@ fn (app App) search_public_repos(query string) []Repo { user := app.get_user_by_id(user_id) or { User{} } repos << Repo{ - id: row.vals[0].int() - git_repo: unsafe { nil } - name: row.vals[1] - user_name: user.username + id: row.vals[0].int() + git_repo: unsafe { nil } + name: row.vals[1] + user_name: user.username description: row.vals[3] - nr_stars: row.vals[4].int() + nr_stars: row.vals[4].int() } } @@ -452,10 +452,10 @@ fn (r &Repo) analyze_lang(app &App) ! { } lang_data := langs[lang] d_lang_stats << LangStat{ - repo_id: r.id - name: lang_data.name - pct: pct - color: lang_data.color + repo_id: r.id + name: lang_data.name + pct: pct + color: lang_data.color lines_count: amount } } @@ -584,13 +584,13 @@ fn (r &Repo) parse_ls(ls_line string, branch string) ?File { } return File{ - name: item_name + name: item_name parent_path: parent_path - repo_id: r.id - last_hash: item_hash - branch: branch - is_dir: item_type == 'tree' - size: if item_type == 'blob' { item_size.int() } else { 0 } + repo_id: r.id + last_hash: item_hash + branch: branch + is_dir: item_type == 'tree' + size: if item_type == 'blob' { item_size.int() } else { 0 } } } @@ -833,44 +833,35 @@ fn find_readme_file(items []File) ?File { fn find_license_file(items []File) ?File { files := items.filter(it.name.to_lower() == 'license') - if files.len == 0 { return none } - return files[0] } -fn (app App) has_user_repo_read_access(user_id int, repo_id int) bool { - if !app.logged_in { +fn (app &App) has_user_repo_read_access(ctx Context, user_id int, repo_id int) bool { + if !ctx.logged_in { return false } - repo := app.find_repo_by_id(repo_id) or { return false } - if repo.is_public { return true } - is_repo_owner := repo.user_id == user_id - if is_repo_owner { return true } - return false } -fn (app App) has_user_repo_read_access_by_repo_name(user_id int, repo_owner_name string, repo_name string) bool { +fn (app &App) has_user_repo_read_access_by_repo_name(ctx Context, user_id int, repo_owner_name string, repo_name string) bool { user := app.get_user_by_username(repo_owner_name) or { return false } repo := app.find_repo_by_name_and_user_id(repo_name, user.id) or { return false } - - return app.has_user_repo_read_access(user_id, repo.id) + return app.has_user_repo_read_access(ctx, user_id, repo.id) } -fn (app App) check_repo_owner(username string, repo_name string) bool { +fn (app &App) check_repo_owner(username string, repo_name string) bool { user := app.get_user_by_username(username) or { return false } repo := app.find_repo_by_name_and_user_id(repo_name, user.id) or { return false } - return repo.user_id == user.id } diff --git a/src/repo_routes.v b/src/repo_routes.v index cf47dd4b..ca772755 100644 --- a/src/repo_routes.v +++ b/src/repo_routes.v @@ -1,6 +1,6 @@ module main -import vweb +import veb import crypto.sha1 import os import highlight @@ -9,58 +9,58 @@ import validation import git @['/:username/repos'] -pub fn (mut app App) user_repos(username string) vweb.Result { +pub fn (mut app App) user_repos(username string) veb.Result { exists, user := app.check_username(username) if !exists { - return app.not_found() + return ctx.not_found() } mut repos := app.find_user_public_repos(user.id) - if user.id == app.user.id { + if user.id == ctx.user.id { repos = app.find_user_repos(user.id) } - return $vweb.html() + return $veb.html() } @['/:username/stars'] -pub fn (mut app App) user_stars(username string) vweb.Result { +pub fn (mut app App) user_stars(username string) veb.Result { exists, user := app.check_username(username) if !exists { - return app.not_found() + return ctx.not_found() } - repos := app.find_user_starred_repos(app.user.id) + repos := app.find_user_starred_repos(ctx.user.id) - return $vweb.html() + return $veb.html() } @['/:username/:repo_name/settings'] -pub fn (mut app App) repo_settings(username string, repo_name string) vweb.Result { +pub fn (mut app App) repo_settings(username string, repo_name string) veb.Result { repo := app.find_repo_by_name_and_username(repo_name, username) or { - return app.redirect_to_repository(username, repo_name) + return ctx.redirect_to_repository(username, repo_name) } - is_owner := app.check_repo_owner(app.user.username, repo_name) + is_owner := app.check_repo_owner(ctx.user.username, repo_name) if !is_owner { - return app.redirect_to_repository(username, repo_name) + return ctx.redirect_to_repository(username, repo_name) } - return $vweb.html() + return $veb.html() } @['/:username/:repo_name/settings'; post] -pub fn (mut app App) handle_update_repo_settings(username string, repo_name string, webhook_secret string) vweb.Result { +pub fn (mut app App) handle_update_repo_settings(username string, repo_name string, webhook_secret string) veb.Result { repo := app.find_repo_by_name_and_username(repo_name, username) or { - return app.redirect_to_repository(username, repo_name) + return ctx.redirect_to_repository(username, repo_name) } - is_owner := app.check_repo_owner(app.user.username, repo_name) + is_owner := app.check_repo_owner(ctx.user.username, repo_name) if !is_owner { - return app.redirect_to_repository(username, repo_name) + return ctx.redirect_to_repository(username, repo_name) } if webhook_secret != '' && webhook_secret != repo.webhook_secret { @@ -68,81 +68,81 @@ pub fn (mut app App) handle_update_repo_settings(username string, repo_name stri app.set_repo_webhook_secret(repo.id, webhook) or { app.info(err.str()) } } - return app.redirect_to_repository(username, repo_name) + return ctx.redirect_to_repository(username, repo_name) } @['/:user/:repo_name/delete'; post] -pub fn (mut app App) handle_repo_delete(username string, repo_name string) vweb.Result { +pub fn (mut app App) handle_repo_delete(username string, repo_name string) veb.Result { repo := app.find_repo_by_name_and_username(repo_name, username) or { - return app.redirect_to_repository(username, repo_name) + return ctx.redirect_to_repository(username, repo_name) } - is_owner := app.check_repo_owner(app.user.username, repo_name) + is_owner := app.check_repo_owner(ctx.user.username, repo_name) if !is_owner { - return app.redirect_to_repository(username, repo_name) + return ctx.redirect_to_repository(username, repo_name) } - if app.form['verify'] == '${username}/${repo_name}' { + if ctx.form['verify'] == '${username}/${repo_name}' { spawn app.delete_repository(repo.id, repo.git_dir, repo.name) } else { - app.error('Verification failed') - return app.repo_settings(username, repo_name) + ctx.error('Verification failed') + return app.repo_settings(username, repo_name, mut ctx) } - return app.redirect_to_index() + return ctx.redirect_to_index() } @['/:username/:repo_name/move'; post] -pub fn (mut app App) handle_repo_move(username string, repo_name string, dest string, verify string) vweb.Result { +pub fn (mut app App) handle_repo_move(username string, repo_name string, dest string, verify string) veb.Result { repo := app.find_repo_by_name_and_username(repo_name, username) or { - return app.redirect_to_index() + return ctx.redirect_to_index() } - is_owner := app.check_repo_owner(app.user.username, repo_name) + is_owner := app.check_repo_owner(ctx.user.username, repo_name) if !is_owner { - return app.redirect_to_repository(username, repo_name) + return ctx.redirect_to_repository(username, repo_name) } if dest != '' && verify == '${username}/${repo_name}' { dest_user := app.get_user_by_username(dest) or { - app.error('Unknown user ${dest}') - return app.repo_settings(username, repo_name) + ctx.error('Unknown user ${dest}') + return app.repo_settings(username, repo_name, mut ctx) } if app.user_has_repo(dest_user.id, repo.name) { - app.error('User already owns repo ${repo.name}') - return app.repo_settings(username, repo_name) + ctx.error('User already owns repo ${repo.name}') + return app.repo_settings(username, repo_name, mut ctx) } if app.get_count_user_repos(dest_user.id) >= max_user_repos { - app.error('User already reached the repo limit') - return app.repo_settings(username, repo_name) + ctx.error('User already reached the repo limit') + return app.repo_settings(username, repo_name, mut ctx) } app.move_repo_to_user(repo.id, dest_user.id, dest_user.username) or { - app.error('There was an error while moving the repo') - return app.repo_settings(username, repo_name) + ctx.error('There was an error while moving the repo') + return app.repo_settings(username, repo_name, mut ctx) } - return app.redirect('/${dest_user.username}/${repo.name}') + return ctx.redirect('/${dest_user.username}/${repo.name}') } else { - app.error('Verification failed') + ctx.error('Verification failed') - return app.repo_settings(username, repo_name) + return app.repo_settings(username, repo_name, mut ctx) } - return app.redirect_to_index() + return ctx.redirect_to_index() } @['/:username/:repo_name'] -pub fn (mut app App) handle_tree(username string, repo_name string) vweb.Result { +pub fn (mut app App) handle_tree(username string, repo_name string) veb.Result { println('handle tree()') match repo_name { 'repos' { - return app.user_repos(username) + return app.user_repos(username, mut ctx) } 'issues' { - return app.handle_get_user_issues(username) + return app.handle_get_user_issues(username, mut ctx) } 'settings' { return app.user_settings(username) @@ -150,67 +150,67 @@ pub fn (mut app App) handle_tree(username string, repo_name string) vweb.Result else {} } - repo := app.find_repo_by_name_and_username(repo_name, username) or { return app.not_found() } + repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() } return app.tree(username, repo_name, repo.primary_branch, '') } @['/:username/:repo_name/tree/:branch_name'] -pub fn (mut app App) handle_branch_tree(username string, repo_name string, branch_name string) vweb.Result { - app.find_repo_by_name_and_username(repo_name, username) or { return app.not_found() } +pub fn (mut app App) handle_branch_tree(username string, repo_name string, branch_name string) veb.Result { + app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() } return app.tree(username, repo_name, branch_name, '') } @['/:username/:repo_name/update'] -pub fn (mut app App) handle_repo_update(username string, repo_name string) vweb.Result { +pub fn (mut app App) handle_repo_update(username string, repo_name string) veb.Result { mut repo := app.find_repo_by_name_and_username(repo_name, username) or { - return app.not_found() + return ctx.not_found() } - if app.user.is_admin { + if ctx.user.is_admin { app.update_repo_from_remote(mut repo) or { app.info(err.str()) } app.slow_fetch_files_info(mut repo, 'master', '.') or { app.info(err.str()) } } - return app.redirect_to_repository(username, repo_name) + return ctx.redirect_to_repository(username, repo_name) } @['/new'] -pub fn (mut app App) new() vweb.Result { - if !app.logged_in { - return app.redirect_to_login() +pub fn (mut app App) new() veb.Result { + if !ctx.logged_in { + return ctx.redirect_to_login() } - return $vweb.html() + return $veb.html() } @['/new'; post] -pub fn (mut app App) handle_new_repo(name string, clone_url string, description string, no_redirect string) vweb.Result { +pub fn (mut app App) handle_new_repo(name string, clone_url string, description string, no_redirect string) veb.Result { mut valid_clone_url := clone_url is_clone_url_empty := validation.is_string_empty(clone_url) - is_public := app.form['repo_visibility'] == 'public' - if !app.logged_in { - return app.redirect_to_login() + is_public := ctx.form['repo_visibility'] == 'public' + if !ctx.logged_in { + return ctx.redirect_to_login() } - if !app.is_admin() && app.get_count_user_repos(app.user.id) >= max_user_repos { - app.error('You have reached the limit for the number of repositories') + if !ctx.is_admin() && app.get_count_user_repos(ctx.user.id) >= max_user_repos { + ctx.error('You have reached the limit for the number of repositories') return app.new() } if name.len > max_repo_name_len { - app.error('The repository name is too long (should be fewer than ${max_repo_name_len} characters)') + ctx.error('The repository name is too long (should be fewer than ${max_repo_name_len} characters)') return app.new() } - if _ := app.find_repo_by_name_and_username(name, app.user.username) { - app.error('A repository with the name "${name}" already exists') + if _ := app.find_repo_by_name_and_username(name, ctx.user.username) { + ctx.error('A repository with the name "${name}" already exists') return app.new() } if name.contains(' ') { - app.error('Repository name cannot contain spaces') + ctx.error('Repository name cannot contain spaces') return app.new() } is_repo_name_valid := validation.is_repository_name_valid(name) if !is_repo_name_valid { - app.error('The repository name is not valid') + ctx.error('The repository name is not valid') return app.new() } has_clone_url_https_prefix := clone_url.starts_with('https://') @@ -220,21 +220,21 @@ pub fn (mut app App) handle_new_repo(name string, clone_url string, description } is_git_repo := git.check_git_repo_url(valid_clone_url) if !is_git_repo { - app.error('The repository URL does not contain any git repository or the server does not respond') + ctx.error('The repository URL does not contain any git repository or the server does not respond') return app.new() } } - repo_path := os.join_path(app.config.repo_storage_path, app.user.username, name) + repo_path := os.join_path(app.config.repo_storage_path, ctx.user.username, name) mut new_repo := &Repo{ - git_repo: git.new_repo(repo_path) - name: name - description: description - git_dir: repo_path - user_id: app.user.id + git_repo: git.new_repo(repo_path) + name: name + description: description + git_dir: repo_path + user_id: ctx.user.id primary_branch: 'master' - user_name: app.user.username - clone_url: valid_clone_url - is_public: is_public + user_name: ctx.user.username + clone_url: valid_clone_url + is_public: is_public } if is_clone_url_empty { os.mkdir(new_repo.git_dir) or { panic(err) } @@ -248,17 +248,17 @@ pub fn (mut app App) handle_new_repo(name string, clone_url string, description // println(time.since(t)) } app.add_repo(new_repo) or { - app.error('There was an error while adding the repo') + ctx.error('There was an error while adding the repo') return app.new() } - new_repo2 := app.find_repo_by_name_and_user_id(new_repo.name, app.user.id) or { + new_repo2 := app.find_repo_by_name_and_user_id(new_repo.name, ctx.user.id) or { app.info('Repo was not inserted') - return app.redirect('/new') + return ctx.redirect('/new') } repo_id := new_repo2.id primary_branch := git.get_repository_primary_branch(repo_path) app.update_repo_primary_branch(repo_id, primary_branch) or { - app.error('There was an error while adding the repo') + ctx.error('There was an error while adding the repo') return app.new() } app.find_repo_by_id(repo_id) or { return app.new() } @@ -266,19 +266,19 @@ pub fn (mut app App) handle_new_repo(name string, clone_url string, description /* if !is_clone_url_empty { app.update_repo_from_fs(mut new_repo) or { - app.error('There was an error while cloning the repo') + ctx.error('There was an error while cloning the repo') return app.new() } } */ if no_redirect == '1' { - return app.text('ok') + return ctx.text('ok') } - has_first_repo_activity := app.has_activity(app.user.id, 'first_repo') + has_first_repo_activity := app.has_activity(ctx.user.id, 'first_repo') if !has_first_repo_activity { - app.add_activity(app.user.id, 'first_repo') or { app.info(err.str()) } + app.add_activity(ctx.user.id, 'first_repo') or { app.info(err.str()) } } - return app.redirect('/${app.user.username}/repos') + return ctx.redirect('/${ctx.user.username}/repos') } pub fn (mut app App) foo(mut new_repo Repo) { @@ -289,15 +289,15 @@ pub fn (mut app App) foo(mut new_repo Repo) { } @['/:username/:repo_name/tree/:branch_name/:path...'] -pub fn (mut app App) tree(username string, repo_name string, branch_name string, path string) vweb.Result { +pub fn (mut app App) tree(username string, repo_name string, branch_name string, path string) veb.Result { mut repo := app.find_repo_by_name_and_username(repo_name, username) or { - return app.not_found() + return ctx.not_found() } _, user := app.check_username(username) if !repo.is_public { - if user.id != app.user.id { - return app.not_found() + if user.id != ctx.user.id { + return ctx.not_found() } } @@ -307,17 +307,17 @@ pub fn (mut app App) tree(username string, repo_name string, branch_name string, // XTODO // app.fetch_tags(repo) or { app.info(err.str()) } - app.current_path = '/${path}' - if app.current_path.contains('/favicon.svg') { - return vweb.not_found() + ctx.current_path = '/${path}' + if ctx.current_path.contains('/favicon.svg') { + return ctx.not_found() } path_parts := path.split('/') - app.path_split = [repo_name] - app.path_split << path_parts + ctx.path_split = [repo_name] + ctx.path_split << path_parts - app.is_tree = true + ctx.is_tree = true app.increment_repo_views(repo.id) or { app.info(err.str()) } @@ -327,15 +327,15 @@ pub fn (mut app App) tree(username string, repo_name string, branch_name string, if path.split('/').len == 1 { up = '../..' } else { - up = app.req.url.all_before_last('/') + up = ctx.req.url.all_before_last('/') } } - if app.current_path.starts_with('/') { - app.current_path = app.current_path[1..] + if ctx.current_path.starts_with('/') { + ctx.current_path = ctx.current_path[1..] } - mut items := app.find_repository_items(repo_id, branch_name, app.current_path) + mut items := app.find_repository_items(repo_id, branch_name, ctx.current_path) branch := app.find_repo_branch_by_name(repo.id, branch_name) app.info('${log_prefix}: ${items.len} items found in branch ${branch_name}') @@ -345,11 +345,11 @@ pub fn (mut app App) tree(username string, repo_name string, branch_name string, // No files in the db, fetch them from git and cache in db app.info('${log_prefix}: caching items in repository with ${repo_id}') - items = app.cache_repository_items(mut repo, branch_name, app.current_path) or { + items = app.cache_repository_items(mut repo, branch_name, ctx.current_path) or { app.info(err.str()) []File{} } - app.slow_fetch_files_info(mut repo, branch_name, app.current_path) or { + app.slow_fetch_files_info(mut repo, branch_name, ctx.current_path) or { app.info(err.str()) } } @@ -357,7 +357,7 @@ pub fn (mut app App) tree(username string, repo_name string, branch_name string, if items.any(it.last_msg == '') { // If any of the files has a missing `last_msg`, we need to refetch it. println('no last msg') - app.slow_fetch_files_info(mut repo, branch_name, app.current_path) or { + app.slow_fetch_files_info(mut repo, branch_name, ctx.current_path) or { app.info(err.str()) } } @@ -380,15 +380,15 @@ pub fn (mut app App) tree(username string, repo_name string, branch_name string, last_commit = app.find_repo_last_commit(repo.id, branch.id) } - diff := int(time.ticks() - app.page_gen_start) + diff := int(time.ticks() - ctx.page_gen_start) if diff == 0 { - app.page_gen_time = '<1ms' + ctx.page_gen_time = '<1ms' } else { - app.page_gen_time = '${diff}ms' + ctx.page_gen_time = '${diff}ms' } // Update items after fetching info - items = app.find_repository_items(repo_id, branch_name, app.current_path) + items = app.find_repository_items(repo_id, branch_name, ctx.current_path) println('new items') println(items) @@ -403,7 +403,7 @@ pub fn (mut app App) tree(username string, repo_name string, branch_name string, has_commits := commits_count > 0 // Get readme after updating repository - mut readme := vweb.RawHtml('') + mut readme := veb.RawHtml('') readme_file := find_readme_file(items) or { File{} } if readme_file.id != 0 { @@ -412,7 +412,7 @@ pub fn (mut app App) tree(username string, repo_name string, branch_name string, highlighted_readme, _, _ := highlight.highlight_text(readme_content, readme_path, false) - readme = vweb.RawHtml(highlighted_readme) + readme = veb.RawHtml(highlighted_readme) } license_file := find_license_file(items) or { File{} } @@ -423,94 +423,94 @@ pub fn (mut app App) tree(username string, repo_name string, branch_name string, } watcher_count := app.get_count_repo_watchers(repo_id) - is_repo_starred := app.check_repo_starred(repo_id, app.user.id) - is_repo_watcher := app.check_repo_watcher_status(repo_id, app.user.id) - is_top_directory := app.current_path == '' + is_repo_starred := app.check_repo_starred(repo_id, ctx.user.id) + is_repo_watcher := app.check_repo_watcher_status(repo_id, ctx.user.id) + is_top_directory := ctx.current_path == '' - return $vweb.html() + return $veb.html() } @['/api/v1/repos/:repo_id/star'; 'post'] -pub fn (mut app App) handle_api_repo_star(repo_id_str string) vweb.Result { +pub fn (mut app App) handle_api_repo_star(repo_id_str string) veb.Result { repo_id := repo_id_str.int() - has_access := app.has_user_repo_read_access(app.user.id, repo_id) + has_access := app.has_user_repo_read_access(ctx, ctx.user.id, repo_id) if !has_access { - return app.json_error('Not found') + return ctx.json_error('Not found') } - user_id := app.user.id + user_id := ctx.user.id app.toggle_repo_star(repo_id, user_id) or { - return app.json_error('There was an error while starring the repo') + return ctx.json_error('There was an error while starring the repo') } is_repo_starred := app.check_repo_starred(repo_id, user_id) - return app.json_success(is_repo_starred) + return ctx.json_success(is_repo_starred) } @['/api/v1/repos/:repo_id/watch'; 'post'] -pub fn (mut app App) handle_api_repo_watch(repo_id_str string) vweb.Result { +pub fn (mut app App) handle_api_repo_watch(repo_id_str string) veb.Result { repo_id := repo_id_str.int() - has_access := app.has_user_repo_read_access(app.user.id, repo_id) + has_access := app.has_user_repo_read_access(ctx, ctx.user.id, repo_id) if !has_access { - return app.json_error('Not found') + return ctx.json_error('Not found') } - user_id := app.user.id + user_id := ctx.user.id app.toggle_repo_watcher_status(repo_id, user_id) or { - return app.json_error('There was an error while toggling to watch') + return ctx.json_error('There was an error while toggling to watch') } is_watching := app.check_repo_watcher_status(repo_id, user_id) - return app.json_success(is_watching) + return ctx.json_success(is_watching) } @['/:username/:repo_name/contributors'] -pub fn (mut app App) contributors(username string, repo_name string) vweb.Result { - repo := app.find_repo_by_name_and_username(repo_name, username) or { return app.not_found() } +pub fn (mut app App) contributors(username string, repo_name string) veb.Result { + repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() } contributors := app.find_repo_registered_contributor(repo.id) - return $vweb.html() + return $veb.html() } @['/:username/:repo_name/blob/:branch_name/:path...'] -pub fn (mut app App) blob(username string, repo_name string, branch_name string, path string) vweb.Result { - repo := app.find_repo_by_name_and_username(repo_name, username) or { return app.not_found() } +pub fn (mut app App) blob(username string, repo_name string, branch_name string, path string) veb.Result { + repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() } mut path_parts := path.split('/') path_parts.pop() - app.current_path = path - app.path_split = [repo_name] - app.path_split << path_parts + ctx.current_path = path + ctx.path_split = [repo_name] + ctx.path_split << path_parts if !app.contains_repo_branch(repo.id, branch_name) && branch_name != repo.primary_branch { app.info('Branch ${branch_name} not found') - return app.not_found() + return ctx.not_found() } raw_url := '/${username}/${repo_name}/raw/${branch_name}/${path}' - file := app.find_repo_file_by_path(repo.id, branch_name, path) or { return app.not_found() } + file := app.find_repo_file_by_path(repo.id, branch_name, path) or { return ctx.not_found() } is_markdown := file.name.to_lower().ends_with('.md') plain_text := repo.read_file(branch_name, path) highlighted_source, _, _ := highlight.highlight_text(plain_text, file.name, false) - source := vweb.RawHtml(highlighted_source) + source := veb.RawHtml(highlighted_source) loc, sloc := calculate_lines_of_code(plain_text) - return $vweb.html() + return $veb.html() } @['/:user/:repository/raw/:branch_name/:path...'] -pub fn (mut app App) handle_raw(username string, repo_name string, branch_name string, path string) vweb.Result { - user := app.get_user_by_username(username) or { return app.not_found() } - repo := app.find_repo_by_name_and_user_id(repo_name, user.id) or { return app.not_found() } +pub fn (mut app App) handle_raw(username string, repo_name string, branch_name string, path string) veb.Result { + user := app.get_user_by_username(username) or { return ctx.not_found() } + repo := app.find_repo_by_name_and_user_id(repo_name, user.id) or { return ctx.not_found() } // TODO: throw error when git returns non-zero status file_source := repo.git('--no-pager show ${branch_name}:${path}') - return app.ok(file_source) + return ctx.ok(file_source) } diff --git a/src/repo_template.v b/src/repo_template.v index a5ec3fba..99c59200 100644 --- a/src/repo_template.v +++ b/src/repo_template.v @@ -1,6 +1,6 @@ module main -import vweb +import veb fn get_declension_form(count int, first_form string, second_form string) string { if count == 1 { @@ -10,37 +10,37 @@ fn get_declension_form(count int, first_form string, second_form string) string return '${count} ${second_form}' } -fn (mut app App) format_commits_count(repo Repo, branch_name string) vweb.RawHtml { +fn (mut app App) format_commits_count(repo Repo, branch_name string) veb.RawHtml { branch := app.find_repo_branch_by_name(repo.id, branch_name) nr_commits := app.get_repo_commit_count(repo.id, branch.id) return get_declension_form(nr_commits, 'Commit', 'Commits') } -fn (r &Repo) format_nr_branches() vweb.RawHtml { +fn (r &Repo) format_nr_branches() veb.RawHtml { return get_declension_form(r.nr_branches, 'Branch', 'Branches') } -fn (r &Repo) format_nr_tags() vweb.RawHtml { +fn (r &Repo) format_nr_tags() veb.RawHtml { return get_declension_form(r.nr_tags, 'Branch', 'Branches') } -fn (r &Repo) format_nr_open_prs() vweb.RawHtml { +fn (r &Repo) format_nr_open_prs() veb.RawHtml { return get_declension_form(r.nr_open_prs, 'Pull request', 'Pull requests') } -fn (r &Repo) format_nr_open_issues() vweb.RawHtml { +fn (r &Repo) format_nr_open_issues() veb.RawHtml { return get_declension_form(r.nr_open_issues, 'Issue', 'Issues') } -fn (r &Repo) format_nr_contributors() vweb.RawHtml { +fn (r &Repo) format_nr_contributors() veb.RawHtml { return get_declension_form(r.nr_contributors, 'Contributor', 'Contributors') } -fn (r &Repo) format_nr_topics() vweb.RawHtml { +fn (r &Repo) format_nr_topics() veb.RawHtml { return get_declension_form(r.nr_topics, 'Discussion', 'discussions') } -fn (r &Repo) format_nr_releases() vweb.RawHtml { +fn (r &Repo) format_nr_releases() veb.RawHtml { return get_declension_form(r.nr_releases, 'Release', 'Releases') } diff --git a/src/search_routes.v b/src/search_routes.v index fa7a8ee0..de2a6f91 100644 --- a/src/search_routes.v +++ b/src/search_routes.v @@ -1,12 +1,12 @@ module main -import vweb +import veb import regex @['/search'] -pub fn (mut app App) search() vweb.Result { - query := app.query['query'] - search_type := if 'type' in app.query { app.query['type'] } else { 'repos' } +pub fn (mut app App) search() veb.Result { + query := ctx.query['query'] + search_type := if 'type' in ctx.query { ctx.query['type'] } else { 'repos' } sanitize_query := r'[a-zA-z0-9]+' mut re := regex.regex_opt(sanitize_query) or { panic(err) } @@ -24,5 +24,5 @@ pub fn (mut app App) search() vweb.Result { []User{} } - return $vweb.html() + return $veb.html() } diff --git a/src/security_log.v b/src/security_log.v index ee4eab95..7d209b6f 100644 --- a/src/security_log.v +++ b/src/security_log.v @@ -14,7 +14,7 @@ enum SecurityLogKind { } struct SecurityLog { - id int @[primary; sql: serial] + id int @[primary; sql: serial] user_id int kind_id int ip string @@ -29,7 +29,7 @@ fn (mut app App) add_security_log(log SecurityLog) ! { new_log := SecurityLog{ ...log kind_id: int(log.kind) - ip: app.ip() + // ip: ip // ctx.ip() XTODO } sql app.db { diff --git a/src/security_log_routes.v b/src/security_log_routes.v index 29f8f567..f59566cd 100644 --- a/src/security_log_routes.v +++ b/src/security_log_routes.v @@ -1,10 +1,10 @@ module main -import vweb +import veb @['/settings/security'] -fn (mut app App) security() vweb.Result { - logs := app.get_all_user_security_logs(app.user.id) +fn (mut app App) security() veb.Result { + logs := app.get_all_user_security_logs(ctx.user.id) - return $vweb.html() + return $veb.html() } diff --git a/src/settings.v b/src/settings.v index cf90d1b0..7a4f098b 100644 --- a/src/settings.v +++ b/src/settings.v @@ -46,7 +46,7 @@ fn (mut app App) update_settings(oauth_client_id string, oauth_client_secret str if old_settings.id == 0 { new_settings := Settings{ - oauth_client_id: github_oauth_client_id + oauth_client_id: github_oauth_client_id oauth_client_secret: github_oauth_client_secret } diff --git a/src/ssh_key.v b/src/ssh_key.v index 6275db68..d4cd067c 100644 --- a/src/ssh_key.v +++ b/src/ssh_key.v @@ -3,9 +3,9 @@ module main import time struct SshKey { - id int @[primary; sql: serial] - user_id int @[unique: 'ssh_key'] - title string @[unique: 'ssh_key'] + id int @[primary; sql: serial] + user_id int @[unique: 'ssh_key'] + title string @[unique: 'ssh_key'] key string created_at time.Time } @@ -20,9 +20,9 @@ fn (mut app App) add_ssh_key(user_id int, title string, key string) ! { } new_ssh_key := SshKey{ - user_id: user_id - title: title - key: key + user_id: user_id + title: title + key: key created_at: time.now() } diff --git a/src/ssh_key_routes.v b/src/ssh_key_routes.v index 8b8cca53..619207a1 100644 --- a/src/ssh_key_routes.v +++ b/src/ssh_key_routes.v @@ -1,83 +1,83 @@ module main -import vweb +import veb import validation import api @['/:username/settings/ssh-keys'] -pub fn (mut app App) user_ssh_keys_list(username string) vweb.Result { - is_users_settings := username == app.user.username +pub fn (mut app App) user_ssh_keys_list(username string) veb.Result { + is_users_settings := username == ctx.user.username - if !app.logged_in || !is_users_settings { - return app.redirect_to_index() + if !ctx.logged_in || !is_users_settings { + return ctx.redirect_to_index() } - ssh_keys := app.find_ssh_keys(app.user.id) + ssh_keys := app.find_ssh_keys(ctx.user.id) - return $vweb.html() + return $veb.html() } @['/:username/settings/ssh-keys'; 'post'] -pub fn (mut app App) handle_add_ssh_key(username string) vweb.Result { - is_users_settings := username == app.user.username +pub fn (mut app App) handle_add_ssh_key(username string) veb.Result { + is_users_settings := username == ctx.user.username - if !app.logged_in || !is_users_settings { - return app.redirect_to_index() + if !ctx.logged_in || !is_users_settings { + return ctx.redirect_to_index() } - title := app.form['title'] - ssh_key := app.form['key'] + title := ctx.form['title'] + ssh_key := ctx.form['key'] is_title_empty := validation.is_string_empty(title) is_ssh_key_empty := validation.is_string_empty(ssh_key) if is_title_empty { - app.error('Title is empty') + ctx.error('Title is empty') return app.user_ssh_keys_new(username) } if is_ssh_key_empty { - app.error('SSH key is empty') + ctx.error('SSH key is empty') return app.user_ssh_keys_new(username) } - app.add_ssh_key(app.user.id, title, ssh_key) or { - app.error(err.str()) + app.add_ssh_key(ctx.user.id, title, ssh_key) or { + ctx.error(err.str()) return app.user_ssh_keys_new(username) } - return app.redirect('/${username}/settings/ssh-keys') + return ctx.redirect('/${username}/settings/ssh-keys') } @['/:username/settings/ssh-keys/:id'; 'delete'] -pub fn (mut app App) handle_remove_ssh_key(username string, id int) vweb.Result { - is_users_settings := username == app.user.username +pub fn (mut app App) handle_remove_ssh_key(username string, id int) veb.Result { + is_users_settings := username == ctx.user.username - if !app.logged_in || !is_users_settings { - return app.redirect_to_index() + if !ctx.logged_in || !is_users_settings { + return ctx.redirect_to_index() } - app.remove_ssh_key(app.user.id, id) or { + app.remove_ssh_key(ctx.user.id, id) or { response := api.ApiErrorResponse{ message: 'There was an error while deleting the SSH key' } - return app.json(response) + return ctx.json(response) } - return app.ok('') + return ctx.ok('') } @['/:username/settings/ssh-keys/new'] -pub fn (mut app App) user_ssh_keys_new(username string) vweb.Result { - is_users_settings := username == app.user.username +pub fn (mut app App) user_ssh_keys_new(username string) veb.Result { + is_users_settings := username == ctx.user.username - if !app.logged_in || !is_users_settings { - return app.redirect_to_index() + if !ctx.logged_in || !is_users_settings { + return ctx.redirect_to_index() } - return $vweb.html() + return $veb.html() } diff --git a/src/tag.v b/src/tag.v index 4b96e2ca..892b373e 100644 --- a/src/tag.v +++ b/src/tag.v @@ -50,11 +50,11 @@ fn (mut app App) insert_tag_into_db(repo_id int, tag_name string, commit_hash st } new_tag := Tag{ - repo_id: repo_id - name: tag_name - hash: commit_hash - message: commit_message - user_id: user_id + repo_id: repo_id + name: tag_name + hash: commit_hash + message: commit_message + user_id: user_id created_at: date } diff --git a/src/tag_routes.v b/src/tag_routes.v index 14c4de02..7a2416d4 100644 --- a/src/tag_routes.v +++ b/src/tag_routes.v @@ -1,13 +1,13 @@ module main -import vweb +import veb import os @['/:username/:repo_name/tag/:tag/:format'] -pub fn (mut app App) handle_download_tag_archive(username string, repo_name string, tag string, format string) vweb.Result { +pub fn (mut app App) handle_download_tag_archive(username string, repo_name string, tag string, format string) veb.Result { // access checking will be implemented in another module - user := app.get_user_by_username(username) or { return app.not_found() } - repo := app.find_repo_by_name_and_user_id(repo_name, user.id) or { return app.not_found() } + user := app.get_user_by_username(username) or { return ctx.not_found() } + repo := app.find_repo_by_name_and_user_id(repo_name, user.id) or { return ctx.not_found() } archive_abs_path := os.abs_path(app.config.archive_path) snapshot_format := if format == 'zip' { 'zip' } else { 'tar.gz' } @@ -20,7 +20,7 @@ pub fn (mut app App) handle_download_tag_archive(username string, repo_name stri repo.archive_tag(tag, archive_path, .tar) } - archive_content := os.read_file(archive_path) or { return app.not_found() } + archive_content := os.read_file(archive_path) or { return ctx.not_found() } return app.send_file(snapshot_name, archive_content) } diff --git a/src/templates/contributors.html b/src/templates/contributors.html index 8aa1d6eb..321658d3 100644 --- a/src/templates/contributors.html +++ b/src/templates/contributors.html @@ -17,7 +17,7 @@