From e2ff8dde3000a32f33761605a4277778f8260244 Mon Sep 17 00:00:00 2001 From: walking dev <104449470+walkingdevel@users.noreply.github.com> Date: Tue, 10 May 2022 04:53:05 +0000 Subject: [PATCH] username and repository name validation (#165) --- gitly.v | 4 +-- repo_routes.v | 11 ++++++- user_routes.v | 24 ++++++++++++-- validation/validation_service.v | 25 +++++++++++++++ validation/validation_service_test.v | 48 ++++++++++++++++++++++++++++ 5 files changed, 107 insertions(+), 5 deletions(-) create mode 100644 validation/validation_service.v create mode 100644 validation/validation_service_test.v diff --git a/gitly.v b/gitly.v index 4cf4398..747f9d0 100644 --- a/gitly.v +++ b/gitly.v @@ -13,10 +13,10 @@ const ( http_port = 8080 expire_length = 200 posts_per_day = 5 - max_username_len = 32 + max_username_len = 40 max_login_attempts = 5 max_user_repos = 10 - max_repo_name_len = 20 + max_repo_name_len = 100 max_namechanges = 3 namechange_period = time.hour * 24 ) diff --git a/repo_routes.v b/repo_routes.v index 102b038..38b0460 100644 --- a/repo_routes.v +++ b/repo_routes.v @@ -5,6 +5,7 @@ import crypto.sha1 import os import highlight import time +import validation ['/:username/repos'] pub fn (mut app App) user_repos(username string) vweb.Result { @@ -172,7 +173,15 @@ pub fn (mut app App) handle_new_repo(name string, clone_url string) vweb.Result } if name.contains(' ') { - app.error('Repo name cannot contain spaces') + app.error('Repository name cannot contain spaces') + return app.new() + } + + is_repository_name_valid := validation.is_repository_name_valid(name) + + if !is_repository_name_valid { + app.error('Repository name is not valid') + return app.new() } diff --git a/user_routes.v b/user_routes.v index 3d4168d..90dc6c3 100644 --- a/user_routes.v +++ b/user_routes.v @@ -4,6 +4,7 @@ import time import os import vweb import rand +import validation pub fn (mut app App) login() vweb.Result { csrf := rand.string(30) @@ -88,11 +89,13 @@ pub fn (mut app App) handle_update_user_settings(user string) vweb.Result { if !app.logged_in || !is_users_settings { return app.redirect_to_index() } - + // TODO: uneven parameters count (2) in `handle_update_user_settings`, compared to the vweb route `['/:user/settings', 'post']` (1) name := app.form['name'] - if name == '' { + is_username_empty := validation.is_string_empty(name) + + if is_username_empty { app.error('New name is empty') return app.user_settings(user) @@ -108,6 +111,14 @@ pub fn (mut app App) handle_update_user_settings(user string) vweb.Result { return app.user_settings(user) } + is_username_valid := validation.is_username_valid(name) + + if !is_username_valid { + app.error('New username is not valid') + + return app.user_settings(user) + } + if app.user.last_namechange_time == 0 || app.user.last_namechange_time + namechange_period <= time.now().unix { u := app.find_user_by_username(name) or { User{} } @@ -173,6 +184,15 @@ pub fn (mut app App) handle_register(username string, email string, password str return app.register() } } + + is_username_valid := validation.is_username_valid(username) + + if !is_username_valid { + app.error('Username is not valid') + + return app.register() + } + if password == '' { app.error('Password cannot be empty') diff --git a/validation/validation_service.v b/validation/validation_service.v new file mode 100644 index 0000000..fde995e --- /dev/null +++ b/validation/validation_service.v @@ -0,0 +1,25 @@ +module validation + +import regex + +pub fn is_username_valid(value string) bool { + query := r'^[A-Za-z][A-Za-z0-9_\.]{1,40}$' + + mut re := regex.regex_opt(query) or { panic(err) } + + return re.matches_string(value) +} + +pub fn is_repository_name_valid(value string) bool { + query := r'^[A-Za-z][A-Za-z0-9_\.\-]{1,100}$' + + mut re := regex.regex_opt(query) or { panic(err) } + + return re.matches_string(value) +} + +pub fn is_string_empty(value string) bool { + trimmed := value.trim(' ') + + return trimmed == '' +} diff --git a/validation/validation_service_test.v b/validation/validation_service_test.v new file mode 100644 index 0000000..b4ec7fc --- /dev/null +++ b/validation/validation_service_test.v @@ -0,0 +1,48 @@ +module validation + +fn test_is_username_valid() { + assert is_username_valid('gitly') + assert is_username_valid('Gitly') + assert is_username_valid('gitly1') + assert is_username_valid('git.ly') + assert is_username_valid('git3.ly') + assert is_username_valid('git3ly_') + + assert is_username_valid('_gitly') == false + assert is_username_valid('git-ly') == false + assert is_username_valid('1gitly') == false + assert is_username_valid('') == false + assert is_username_valid(' ') == false + assert is_username_valid(' 33') == false + assert is_username_valid(' gitly') == false + assert is_username_valid('#gitly') == false +} + +fn test_is_repository_name_valid() { + assert is_repository_name_valid('gitly') + assert is_repository_name_valid('Gitly') + assert is_repository_name_valid('gitly1') + assert is_repository_name_valid('git.ly') + assert is_repository_name_valid('git3.ly') + assert is_repository_name_valid('git3-ly') + assert is_repository_name_valid('git3ly_') + assert is_repository_name_valid('git-ly') + + assert is_repository_name_valid('_gitly') == false + assert is_repository_name_valid('1gitly') == false + assert is_repository_name_valid('') == false + assert is_repository_name_valid(' ') == false + assert is_repository_name_valid(' 33') == false + assert is_repository_name_valid(' gitly') == false + assert is_repository_name_valid('#gitly') == false +} + +fn test_is_string_empty() { + assert is_string_empty('') + + assert is_string_empty(' ') + + assert is_string_empty('g') == false + + assert is_string_empty(' g') == false +} -- 2.39.5