diff --git a/api.v b/api.v index de768dee..9b897209 100644 --- a/api.v +++ b/api.v @@ -7,7 +7,7 @@ import json ['/api/:user/:repo/issues'] pub fn (mut app App) api_issues(user, repo string) vweb.Result { - if !app.find_repo(user, repo) { + if !app.exists_user_repo(user, repo) { return app.vweb.json('{}') } issues := app.find_repo_issues(app.repo.id) @@ -16,7 +16,7 @@ pub fn (mut app App) api_issues(user, repo string) vweb.Result { ['/api/:user/:repo/commits'] pub fn (mut app App) api_commits(user, repo string) vweb.Result { - if !app.find_repo(user, repo) { + if !app.exists_user_repo(user, repo) { return app.vweb.json('{}') } commits := app.find_repo_commits(app.repo.id) diff --git a/branch.v b/branch.v index c79672f5..2b123b22 100644 --- a/branch.v +++ b/branch.v @@ -123,3 +123,9 @@ fn (mut app App) contains_repo_branch(name string, repo_id int) bool { } return nr == 1 } + +fn (mut app App) delete_repo_branches(repo_id int) { + sql app.db { + delete from Branch where repo_id == repo_id + } +} diff --git a/file.v b/file.v index a0b88fbe..88e03798 100644 --- a/file.v +++ b/file.v @@ -73,3 +73,13 @@ fn (mut app App) find_repo_file_by_path(repo_id int, branch, path string) ?File } return file } + +fn (mut app App) delete_repo_files(repo_id int) { + sql app.db { + delete from File where repo_id == repo_id + } +} + +fn (mut app App) delete_repo_folder(path string) { + os.rmdir_all(os.real_path(path)) +} diff --git a/gitly.v b/gitly.v index eb496c10..71ec4d66 100644 --- a/gitly.v +++ b/gitly.v @@ -19,7 +19,9 @@ const ( max_login_attempts = 5 repo_storage_path = './repos' max_user_repos = 5 - max_repo_name_len = 20 + max_repo_name_len = 20 + max_namechanges = 3 + namechange_period = time.hour * 24 ) struct App { @@ -139,6 +141,7 @@ pub fn (mut app App) init_once() { pub fn (mut app App) init() { url := app.vweb.req.url + app.show_menu = false app.page_gen_time = '' app.info('\n\ninit() url=$url') app.path = '' @@ -212,7 +215,7 @@ pub fn (mut app App) repo_settings(user, repo string) vweb.Result { if !app.logged_in { return app.vweb.redirect('/$user/$repo') } - if !app.find_repo(user, repo) { + if !app.exists_user_repo(user, repo) { return app.vweb.redirect('/$user/$repo') } if app.repo.user_id != app.user.id { @@ -223,18 +226,16 @@ pub fn (mut app App) repo_settings(user, repo string) vweb.Result { return $vweb.html() } +// Helper function +fn (mut app App) repo_belongs_to(user, repo string) bool { + return app.logged_in && app.exists_user_repo(user, repo) && app.repo.user_id == app.user.id +} + ['/:user/:repo/repo_settings_post'] pub fn (mut app App) repo_settings_post(user, repo string) vweb.Result { - if !app.logged_in { - return app.r_repo() - } - if !app.find_repo(user, repo) { + if !app.repo_belongs_to(user, repo) { return app.r_repo() } - if app.repo.user_id != app.user.id { - return app.r_repo() - } - if 'webhook_secret' in app.vweb.form && app.vweb.form['webhook_secret'] != app.repo.webhook_secret && app.vweb.form['webhook_secret'] != '' { webhook := sha1.hexhash(app.vweb.form['webhook_secret']) app.update_repo_webhook(app.repo.id, webhook) @@ -243,9 +244,52 @@ pub fn (mut app App) repo_settings_post(user, repo string) vweb.Result { return app.r_repo() } +['/:user/:repo/delete_repo_post'] +pub fn (mut app App) repo_delete_post(user, repo string) vweb.Result { + if !app.repo_belongs_to(user, repo) { + return app.r_repo() + } + if 'verify' in app.vweb.form && app.vweb.form['verify'] == '$user/$repo' { + go app.delete_repo(app.repo.id, app.repo.git_dir, app.repo.name) + } else { + app.vweb.error('Verification failed') + return app.repo_settings(user, repo) + } + + return app.r_home() +} + +['/:user/:repo/move_repo_post'] +pub fn (mut app App) repo_move_post(user, repo string) vweb.Result { + if !app.repo_belongs_to(user, repo) { + return app.r_repo() + } + if 'verify' in app.vweb.form && 'dest' in app.vweb.form && app.vweb.form['verify'] == '$user/$repo' { + uname := app.vweb.form['dest'] + dest_user := app.find_user_by_username(uname) or { + app.vweb.error('Unknown user $uname') + return app.repo_settings(user, repo) + } + if app.user_has_repo(dest_user.id, app.repo.name) { + app.vweb.error('User already owns repo $app.repo.name') + return app.repo_settings(user, repo) + } + if app.nr_user_repos(dest_user.id) >= max_user_repos { + app.vweb.error('User already reached the repo limit') + return app.repo_settings(user, repo) + } + app.move_repo_to_user(app.repo.id, dest_user.id, dest_user.username) + return app.vweb.redirect('/$dest_user.username/$app.repo.name') + } else { + app.vweb.error('Verification failed') + return app.repo_settings(user, repo) + } + return app.r_home() +} + ['/:user/:repo'] pub fn (mut app App) tree2(user, repo string) vweb.Result { - if !app.find_repo(user, repo) { + if !app.exists_user_repo(user, repo) { return app.vweb.not_found() } return app.tree(user, repo, app.repo.primary_branch, '') @@ -254,7 +298,7 @@ pub fn (mut app App) tree2(user, repo string) vweb.Result { // pub fn (mut app App) tree(path string) { ['/:user/:repo/tree/:branch/:path...'] pub fn (mut app App) tree(user, repo, branch, path string) vweb.Result { - if !app.find_repo(user, repo) { + if !app.exists_user_repo(user, repo) { return app.vweb.not_found() } println('\n\n\ntree() user="$user" repo="' + repo + '"') @@ -335,7 +379,7 @@ pub fn (mut app App) index() vweb.Result { ['/:user/:repo/update'] pub fn (mut app App) update(user, repo string) vweb.Result { - if !app.find_repo(user, repo) { + if !app.exists_user_repo(user, repo) { return app.vweb.not_found() } /*secret := if 'X-Hub-Signature' in app.vweb.req.headers { app.vweb.req.headers['X-Hub-Signature'][5..] } else { '' } @@ -348,7 +392,7 @@ pub fn (mut app App) update(user, repo string) vweb.Result { if app.user.is_admin { go app.update_repo_data(app.repo) } - return app.r_home() + return app.r_repo() } pub fn (mut app App) new() vweb.Result { @@ -398,27 +442,7 @@ pub fn (mut app App) new_post() vweb.Result { } go app.update_repo() println('end go') - return app.vweb.redirect('/$app.user.username') -} - -['/:username'] -pub fn (mut app App) user(username string) vweb.Result { - println('user() name=$username') - app.show_menu = false - mut user := User{} - if username.len != 0 { - user = app.find_user_by_username(username) or { - return app.vweb.not_found() - } - } else { - return app.vweb.not_found() - } - user.b_avatar = user.avatar != '' - if !user.b_avatar { - user.avatar = user.username.bytes()[0].str() - } - repos := app.find_user_repos(user.id) - return $vweb.html() + return app.vweb.redirect('/$app.user.username/repos') } ['/:user/:repo/commits'] @@ -428,7 +452,7 @@ pub fn (mut app App) commits2(user, repo string) vweb.Result { ['/:user/:repo/commits/:page_str'] pub fn (mut app App) commits(user, repo, page_str string) vweb.Result { - if !app.find_repo(user, repo) { + if !app.exists_user_repo(user, repo) { return app.vweb.not_found() } app.show_menu = true @@ -501,7 +525,7 @@ pub fn (mut app App) commits(user, repo, page_str string) vweb.Result { ['/:user/:repo/commit/:hash'] pub fn (mut app App) commit(user, repo, hash string) vweb.Result { - if !app.find_repo(user, repo) { + if !app.exists_user_repo(user, repo) { return app.vweb.not_found() } commit := app.find_repo_commit_by_hash(app.repo.id, hash) @@ -525,7 +549,7 @@ pub fn (mut app App) issues2(user, repo string) vweb.Result { ['/:user/:repo/issues/:page_str'] pub fn (mut app App) issues(user, repo, page_str string) vweb.Result { - if !app.find_repo(user, repo) { + if !app.exists_user_repo(user, repo) { app.vweb.not_found() } app.show_menu = true @@ -560,7 +584,7 @@ pub fn (mut app App) issues(user, repo, page_str string) vweb.Result { ['/:user/:repo/issue/:id'] pub fn (mut app App) issue(user, repo, id_str string) vweb.Result { - if !app.find_repo(user, repo) { + if !app.exists_user_repo(user, repo) { return app.vweb.not_found() } app.show_menu = true @@ -579,7 +603,7 @@ pub fn (mut app App) issue(user, repo, id_str string) vweb.Result { ['/:user/:repo/pull/:id'] pub fn (mut app App) pull(user, repo, id_str string) vweb.Result { - if !app.find_repo(user, repo) { + if !app.exists_user_repo(user, repo) { return app.vweb.not_found() } _ := app.path.split('/') @@ -599,7 +623,7 @@ pub fn (mut app App) pulls() vweb.Result { ['/:user/:repo/contributors'] pub fn (mut app App) contributors(user, repo string) vweb.Result { - if !app.find_repo(user, repo) { + if !app.exists_user_repo(user, repo) { return app.vweb.not_found() } contributors := app.find_repo_registered_contributor(app.repo.id) @@ -608,7 +632,7 @@ pub fn (mut app App) contributors(user, repo string) vweb.Result { ['/:user/:repo/branches'] pub fn (mut app App) branches(user, repo string) vweb.Result { - if !app.find_repo(user, repo) { + if !app.exists_user_repo(user, repo) { return app.vweb.not_found() } app.show_menu = true @@ -618,7 +642,7 @@ pub fn (mut app App) branches(user, repo string) vweb.Result { ['/:user/:repo/releases'] pub fn (mut app App) releases(user_str, repo string) vweb.Result { - if !app.find_repo(user_str, repo) { + if !app.exists_user_repo(user_str, repo) { return app.vweb.not_found() } app.show_menu = true @@ -652,7 +676,7 @@ pub fn (mut app App) releases(user_str, repo string) vweb.Result { ['/:user/:repo/blob/:branch/:path...'] pub fn (mut app App) blob(user, repo, branch, path string) vweb.Result { - if !app.find_repo(user, repo) { + if !app.exists_user_repo(user, repo) { return app.vweb.not_found() } app.path = path @@ -696,7 +720,7 @@ pub fn (mut app App) blob(user, repo, branch, path string) vweb.Result { ['/:user/:repo/issues/new'] pub fn (mut app App) new_issue(user, repo string) vweb.Result { - if !app.find_repo(user, repo) { + if !app.exists_user_repo(user, repo) { return app.vweb.not_found() } if !app.logged_in { @@ -707,7 +731,7 @@ pub fn (mut app App) new_issue(user, repo string) vweb.Result { ['/:user/:repo/new_issue_post'] pub fn (mut app App) new_issue_post(user, repo string) vweb.Result { - if !app.find_repo(user, repo) { + if !app.exists_user_repo(user, repo) { return app.vweb.not_found() } if !app.logged_in || (app.logged_in && app.user.nr_posts >= posts_per_day) { @@ -733,7 +757,7 @@ pub fn (mut app App) new_issue_post(user, repo string) vweb.Result { ['/:user/:repo/comment_post'] pub fn (mut app App) comment_post(user, repo string) vweb.Result { - if !app.find_repo(user, repo) { + if !app.exists_user_repo(user, repo) { return app.vweb.not_found() } text := app.vweb.form['text'] diff --git a/hl/hl.v b/hl/hl.v index bdfc00c2..65124250 100644 --- a/hl/hl.v +++ b/hl/hl.v @@ -33,7 +33,7 @@ pub fn highlight_text(st, ext string, commit bool) (string, int, int) { res << '
1 | '.bytes() + res << ' |
1 | '.bytes() lines++ } mut in_comment := false @@ -52,9 +52,9 @@ pub fn highlight_text(st, ext string, commit bool) (string, int, int) { class = 'class="d"' } res << - ' |
$lines | '.bytes() + ' |
$lines | '.bytes() } else { - res << ' |
$lines | '.bytes() + res << ' |
$lines | '.bytes()
}
if in_line_comment {
in_line_comment = false
diff --git a/issue.v b/issue.v
index 4bb2675f..27af1fbe 100644
--- a/issue.v
+++ b/issue.v
@@ -19,6 +19,8 @@ mut:
status IssueStatus [skip]
linked_issues []int [skip]
author_name string [skip]
+ repo_author string [skip]
+ repo_name string [skip]
}
enum IssueStatus {
@@ -81,6 +83,18 @@ fn (mut app App) find_repo_prs(repo_id int) []Issue {
return issues
}
+fn (mut app App) find_user_issues(user_id int) []Issue {
+ return sql app.db {
+ select from Issue where author_id == user_id && is_pr == false
+ }
+}
+
+fn (mut app App) delete_repo_issues(repo_id int) {
+ sql app.db {
+ delete from Issue where repo_id == repo_id
+ }
+}
+
fn (mut app App) inc_issue_comments(id int) {
sql app.db {
update Issue set nr_comments = nr_comments + 1 where id == id
diff --git a/lang_stat.v b/lang_stat.v
index 4daddbff..40783170 100644
--- a/lang_stat.v
+++ b/lang_stat.v
@@ -36,7 +36,7 @@ pub fn (l &LangStat) pct_html() vweb.RawHtml {
pub fn (mut app App) find_repo_lang_stats(repo_id int) []LangStat {
lang_stats := sql app.db {
- select from LangStat where repo_id == repo_id
+ select from LangStat where repo_id == repo_id order by pct desc
}
return lang_stats
}
diff --git a/login.v b/login.v
index 89f7453b..2deaa395 100644
--- a/login.v
+++ b/login.v
@@ -6,7 +6,6 @@ import vweb
import time
import rand
import math
-import strings
//['/login']
pub fn (mut app App) login() vweb.Result {
@@ -58,8 +57,9 @@ pub fn (mut app App) auth_user(user User, ip string) {
token := app.add_token(user.id, ip)
app.update_user_login_attempts(user.id, 0)
//println('cookie: setting token=$token id=$user.id')
- app.vweb.set_cookie(name: 'id', value:user.id.str())
- app.vweb.set_cookie(name:'token', value:token)
+ expire_date := time.now().add_days(200)
+ app.vweb.set_cookie(name: 'id', value:user.id.str(), expires: expire_date)
+ app.vweb.set_cookie(name:'token', value:token, expires: expire_date)
//app.vweb.set_cookie_with_expire_date('id', user.id.str(), expires)
//app.vweb.set_cookie_with_expire_date('token', token, expires)
}
diff --git a/release.v b/release.v
index 42bc9c24..cec0264a 100644
--- a/release.v
+++ b/release.v
@@ -25,3 +25,10 @@ pub fn (mut app App) find_repo_releases(repo_id int) []Release {
select from Release where repo_id == repo_id
}
}
+
+pub fn (mut app App) delete_repo_releases(repo_id int) {
+ sql app.db {
+ delete from Release where repo_id == repo_id
+ }
+}
+
diff --git a/repo_db.v b/repo_db.v
index 6da9c9dd..39e85aea 100644
--- a/repo_db.v
+++ b/repo_db.v
@@ -82,6 +82,8 @@ fn (mut app App) create_tables() {
'avatar text default ""'
'nr_posts integer default 0'
'last_post_time integer default 0'
+ 'nr_namechanges integer default 0'
+ 'last_namechange_time integer default 0'
'is_github int default 0'
'is_blocked int default 0'
'is_registered int default 0'
@@ -216,7 +218,13 @@ fn (app &App) find_user_repos(user_id int) []Repo {
}
}
-fn (app &App) find_repo(user, name string) bool {
+fn (app &App) find_repo_by_id(repo_id int) Repo {
+ return sql app.db {
+ select from Repo where id == repo_id
+ }
+}
+
+fn (app &App) exists_user_repo(user, name string) bool {
if user.len == 0 || name.len == 0 {
app.info('User or repo was not found')
return false
@@ -282,3 +290,50 @@ fn (mut app App) insert_repo(repo Repo) {
insert repo into Repo
}
}
+
+fn (mut app App) delete_repo(id int, path, name string) {
+ // Remove repo
+ sql app.db {
+ delete from Repo where id == id
+ }
+ app.info('Removed repo entry ($id, $name)')
+
+ // Remove all commits
+ sql app.db {
+ delete from Commit where repo_id == id
+ }
+ app.info('Removed repo commits ($id, $name)')
+
+ // Remove all issues & prs
+ app.delete_repo_issues(id)
+ app.info('Removed repo issues ($id, $name)')
+
+ // Remove all branches
+ app.delete_repo_branches(id)
+ app.info('Removed repo branches ($id, $name)')
+
+ // Remove all releases
+ app.delete_repo_releases(id)
+ app.info('Removed repo releases ($id, $name)')
+
+ // Remove all files
+ app.delete_repo_files(id)
+ app.info('Removed repo files ($id, $name)')
+
+ // Remove physical files
+ app.delete_repo_folder(path)
+ app.info('Removed repo folder ($id, $name)')
+}
+
+fn (mut app App) move_repo_to_user(repo_id, user_id int, user_name string) {
+ sql app.db {
+ update Repo set user_id = user_id, user_name = user_name where id == repo_id
+ }
+}
+
+fn (mut app App) user_has_repo(user_id int, repo_name string) bool {
+ count := sql app.db {
+ select count from Repo where user_id == user_id && name == repo_name
+ }
+ return count >= 0
+}
diff --git a/security_log.v b/security_log.v
index dad37a4f..eafc4b15 100644
--- a/security_log.v
+++ b/security_log.v
@@ -3,8 +3,6 @@
module main
import vweb
-import json
-import net.http
enum SecurityLogKind {
registered
diff --git a/static/css/gitly.scss b/static/css/gitly.scss
index 0a087146..7ddbd6ed 100644
--- a/static/css/gitly.scss
+++ b/static/css/gitly.scss
@@ -49,6 +49,14 @@ pre > code {
background-color: #eff0f1;
display: block;
}
+.no_select {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
.content {
max-width: $mob-max;
margin: 0 auto;
@@ -147,6 +155,16 @@ pre > code {
width: 40px;
margin: 0;
}
+
+.new {
+ display: flex;
+ position: absolute;
+ top: 0;
+ right: 0;
+ padding-right: 150px;
+}
+
+
#header .login-button {
color: $white;
line-height: 50px;
diff --git a/templates/header.html b/templates/header.html
index dd9a8747..a00eb2ae 100644
--- a/templates/header.html
+++ b/templates/header.html
@@ -42,6 +42,11 @@
@app.repo.name
@end
}
+ @if app.logged_in
+
+ New repo
+
+ @end
@if app.logged_in
.avatar {
@@ -57,10 +62,16 @@
@app.user.username
}
.links {
- Repositories
+ Repositories
Issues
Pull requests
}
+ .links {
+ Settings
+ }
+ @if app.user.is_admin
+ Admin Panel
+ @end
.links {
Sign out
}
diff --git a/templates/repo/settings.html b/templates/repo/settings.html
index b63823af..27014fb8 100644
--- a/templates/repo/settings.html
+++ b/templates/repo/settings.html
@@ -1,8 +1,24 @@
@header
+.div-center {
+ .form-error {
+ @app.vweb.form_error
+ }
-
+
+
+
+
+
+}
@footer
diff --git a/templates/security.html b/templates/security.html
index 7fbd6d37..bd2d65a9 100644
--- a/templates/security.html
+++ b/templates/security.html
@@ -7,7 +7,7 @@ Security log@for log in logs
-
+ @log
@end
diff --git a/templates/user.html b/templates/user.html
index 15a13cda..9a2aa40d 100644
--- a/templates/user.html
+++ b/templates/user.html
@@ -1,6 +1,5 @@
@header
-
@if user.b_avatar
@user.username@user.name-@if app.logged_in -New repository-@end - -@if repos.len > 0 -@for repo in repos - - @repo.name-@repo.description - -@end -@else -No repositories-@end - - @footer diff --git a/templates/user/issues.html b/templates/user/issues.html new file mode 100644 index 00000000..b8d25f1b --- /dev/null +++ b/templates/user/issues.html @@ -0,0 +1,55 @@ +@header + +
+@if user.b_avatar
+
+@user.username s issues+ +.commit-day { +} + +.clog-block { + @for issue in issues + .clog { + .clog-msg { + @issue.title + } + span.clog-author { + #@issue.id opened @issue.relative_time() + by @issue.author_name + } + @if issue.nr_comments > 0 + .comments { + @if issue.nr_comments == 1 + @issue.nr_comments comment + @else + @issue.nr_comments comments + @end + } + @end + } + @end +} + + + + + +@footer diff --git a/templates/user/repos.html b/templates/user/repos.html new file mode 100644 index 00000000..178df3c0 --- /dev/null +++ b/templates/user/repos.html @@ -0,0 +1,23 @@ +@header + +
+@if user.b_avatar
+
+@user.username s repositories+ +@if repos.len > 0 +@for repo in repos + +@repo.name+@repo.description + +@end +@else +No repositories+@end + +@footer diff --git a/templates/user/settings.html b/templates/user/settings.html new file mode 100644 index 00000000..8486968f --- /dev/null +++ b/templates/user/settings.html @@ -0,0 +1,16 @@ +@header + +User settings+ +.div-center { + .form-error { + @app.vweb.form_error + } + + +} + +@footer diff --git a/user.v b/user.v index 0b803174..4d24ad18 100644 --- a/user.v +++ b/user.v @@ -18,6 +18,8 @@ struct User { is_admin bool oauth_state string [skip] // for github oauth XSRF protection mut: + nr_namechanges int + last_namechange_time int nr_posts int last_post_time int avatar string @@ -351,3 +353,19 @@ pub fn (mut app App) client_ip(username string) ?string { ip := app.vweb.conn.peer_ip() or { return none } return make_password(ip, '${username}token') } + +fn (mut app App) change_username(user_id int, username string) { + sql app.db { + update User set username = username where id == user_id + } + sql app.db { + update Repo set user_name = username where user_id == user_id + } +} + +fn (mut app App) inc_namechanges(user_id int) { + now := int(time.now().unix) + sql app.db { + update User set nr_namechanges = nr_namechanges + 1, last_namechange_time = now where id == user_id + } +} diff --git a/usersite.v b/usersite.v new file mode 100644 index 00000000..6337006a --- /dev/null +++ b/usersite.v @@ -0,0 +1,132 @@ +module main + +import time +import vweb + +fn (mut app App) check_username(user string) (bool, User) { + if user.len == 0 { + return false, User{} + } + mut u := app.find_user_by_username(user) or { + return false, User{} + } + u.b_avatar = u.avatar != '' + if !u.b_avatar { + u.avatar = u.username.bytes()[0].str() + } + return u.is_registered, u +} + +['/:username'] +pub fn (mut app App) user(username string) vweb.Result { + println('user() name=$username') + app.show_menu = false + exists, u := app.check_username(username) + if !exists { + return app.vweb.not_found() + } + user := u + return $vweb.html() +} + + +['/:username/repos'] +pub fn (mut app App) user_repos(username string) vweb.Result { + exists, u := app.check_username(username) + if !exists { + return app.vweb.not_found() + } + user := u + repos := app.find_user_repos(user.id) + return $vweb.html() +} + +['/:username/issues'] +pub fn (mut app App) user_issues2(username string) vweb.Result { + return app.user_issues(username, '0') +} + +['/:username/issues/:page_str'] +pub fn (mut app App) user_issues(username, page_str string) vweb.Result { + if !app.logged_in { + return app.vweb.not_found() + } + if app.user.username != username { + return app.vweb.not_found() + } + exists, u := app.check_username(username) + if !exists { + return app.vweb.not_found() + } + user := u + page := if page_str.len >= 1 { page_str.int() } else { 0 } + mut issues := app.find_user_issues(user.id) + mut first := false + mut last := false + for i, issue in issues { + issues[i].author_name = username + repo := app.find_repo_by_id(issue.repo_id) + issues[i].repo_author = repo.user_name + issues[i].repo_name = repo.name + } + if issues.len > commits_per_page { + offset := page * commits_per_page + delta := issues.len - offset + if delta > 0 { + if delta == issues.len && page == 0 { + first = true + } else { + last = true + } + } + } else { + last = true + first = true + } + mut last_site := 0 + if page > 0 { + last_site = page - 1 + } + next_site := page + 1 + return $vweb.html() +} + +/* +['/:user/prs'] +pub fn (mut app App) user_pullrequests(user string) vweb.Result {} +*/ +['/:user/settings'] +pub fn (mut app App) user_settings(user string) vweb.Result { + return $vweb.html() +} + +['/:user/settings_post'] +pub fn (mut app App) user_settings_post(user string) vweb.Result { + if !app.logged_in || user != app.user.username { + return app.r_home() + } + name := if 'name' in app.vweb.form { app.vweb.form['name'] } else { '' } + if name == '' { + app.vweb.error('New name is empty') + return app.user_settings(user) + } + if name == user { + return app.user_settings(user) + } + if app.user.nr_namechanges > max_namechanges { + app.vweb.error('You can not change your username, limit reached') + 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{} } + if u.id != 0 { + app.vweb.error('Name already exists') + return app.user_settings(user) + } + app.change_username(app.user.id, name) + app.inc_namechanges(app.user.id) + return app.vweb.redirect('/$name') + } + app.vweb.error('You need to wait until you can change the name again') + return app.user_settings(user) +} |