From babf0a37f098dfdde4c4e769ccf4491b2a33b347 Mon Sep 17 00:00:00 2001 From: tomleb Date: Thu, 18 May 2017 22:55:59 -0400 Subject: [PATCH] Cleanups and fixes (#623) * Keep naming consistent * Remove execute bit from files * Default to DefaultLanguage (without passing it to the func) * Remove commented code * Use Content-Type to get language json * Lines of 400 characters is dumb * Update new repo in README * Remove useless script since we fallback to a defaultlang * Fix fallback language panic * Fix uninitialized MaxPerPage when not in querystr The issue was that the req.MaxPerPage was not set (default to 0) when the query string didn't include "max". This makes the server query the whole db since the resulting limit is 0. * Fix creating empty torrents (only worked once) * Lines of 400 characters is still dumb --- ...metainfoFetcher.go => metainfo_fetcher.go} | 0 deploy/README.md | 6 +- public/js/languages.js | 3 +- router/{apiHandler.go => api_handler.go} | 19 ++- ...umpHandler.go => database_dump_handler.go} | 0 router/{faqHandler.go => faq_handler.go} | 9 +- router/{homeHandler.go => home_handler.go} | 20 ++- ...LanguageHandler.go => language_handler.go} | 17 +- ...otFoundHandler.go => not_found_handler.go} | 12 +- router/router.go | 34 ---- router/{rssHandler.go => rss_handler.go} | 0 .../{searchHandler.go => search_handler.go} | 0 router/template.go | 28 +++- ...lateFunctions.go => template_functions.go} | 0 ...lateVariables.go => template_variables.go} | 0 ...rtHandler.go => torrent_report_handler.go} | 0 router/uploadHandler.go | 118 -------------- router/upload_handler.go | 134 ++++++++++++++++ router/{userHandler.go => user_handler.go} | 151 ++++++++++-------- ...rentHandler.go => view_torrent_handler.go} | 0 router/{wrapHandler.go => wrap_handler.go} | 0 service/api/api.go | 2 + ...metainfoFetcher.go => metainfo_fetcher.go} | 0 .../{formValidator.go => form_validator.go} | 0 .../user/{userHelper.go => user_helper.go} | 0 translations/add_translation.sh | 12 -- util/languages/translation.go | 37 ++--- .../{modelHelper.go => model_helper.go} | 0 .../{timeHelper.go => time_helper.go} | 0 29 files changed, 325 insertions(+), 277 deletions(-) rename config/{metainfoFetcher.go => metainfo_fetcher.go} (100%) rename router/{apiHandler.go => api_handler.go} (91%) rename router/{databaseDumpHandler.go => database_dump_handler.go} (100%) rename router/{faqHandler.go => faq_handler.go} (56%) rename router/{homeHandler.go => home_handler.go} (77%) rename router/{changeLanguageHandler.go => language_handler.go} (80%) rename router/{notFoundHandler.go => not_found_handler.go} (58%) mode change 100755 => 100644 router/router.go rename router/{rssHandler.go => rss_handler.go} (100%) rename router/{searchHandler.go => search_handler.go} (100%) rename router/{templateFunctions.go => template_functions.go} (100%) rename router/{templateVariables.go => template_variables.go} (100%) rename router/{torrentReportHandler.go => torrent_report_handler.go} (100%) delete mode 100644 router/uploadHandler.go create mode 100644 router/upload_handler.go rename router/{userHandler.go => user_handler.go} (72%) mode change 100755 => 100644 rename router/{viewTorrentHandler.go => view_torrent_handler.go} (100%) rename router/{wrapHandler.go => wrap_handler.go} (100%) rename service/torrent/metainfoFetcher/{metainfoFetcher.go => metainfo_fetcher.go} (100%) rename service/user/form/{formValidator.go => form_validator.go} (100%) rename service/user/{userHelper.go => user_helper.go} (100%) delete mode 100755 translations/add_translation.sh rename util/modelHelper/{modelHelper.go => model_helper.go} (100%) rename util/timeHelper/{timeHelper.go => time_helper.go} (100%) diff --git a/config/metainfoFetcher.go b/config/metainfo_fetcher.go similarity index 100% rename from config/metainfoFetcher.go rename to config/metainfo_fetcher.go diff --git a/deploy/README.md b/deploy/README.md index ca772e1f..4294b35e 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -25,9 +25,9 @@ You may now start the container as such. ``` $ export GOPATH=$HOME/.go -$ mkdir -p $HOME/.go/src/github.com/ewhal -$ cd $HOME/.go/src/github.com/ewhal -$ git clone https://github.com/ewhal/nyaa +$ mkdir -p $HOME/.go/src/github.com/NyaaPantsu +$ cd $HOME/.go/src/github.com/NyaaPantsu +$ git clone https://github.com/NyaaPantsu/nyaa $ cd nyaa/deploy $ docker-compose -f up ``` diff --git a/public/js/languages.js b/public/js/languages.js index 92c5d155..a7db5296 100644 --- a/public/js/languages.js +++ b/public/js/languages.js @@ -24,7 +24,8 @@ function loadLanguages() { } } } - xhr.open("GET", "/language?format=json", true) + xhr.open("GET", "/language", true) + xhr.setRequestHeader("Content-Type", "application/json") xhr.send() } diff --git a/router/apiHandler.go b/router/api_handler.go similarity index 91% rename from router/apiHandler.go rename to router/api_handler.go index a35cb234..52091933 100644 --- a/router/apiHandler.go +++ b/router/api_handler.go @@ -34,7 +34,7 @@ func ApiHandler(w http.ResponseWriter, r *http.Request) { } if req.MaxPerPage == 0 { - req.MaxPerPage = 50 + req.MaxPerPage = config.TorrentsPerPage } if req.Page == 0 { req.Page = 1 @@ -47,8 +47,10 @@ func ApiHandler(w http.ResponseWriter, r *http.Request) { if maxString != "" { req.MaxPerPage, err = strconv.Atoi(maxString) if !log.CheckError(err) { - req.MaxPerPage = 50 // default Value maxPerPage + req.MaxPerPage = config.TorrentsPerPage } + } else { + req.MaxPerPage = config.TorrentsPerPage } req.Page = 1 @@ -125,12 +127,12 @@ func ApiUploadHandler(w http.ResponseWriter, r *http.Request) { contentType := r.Header.Get("Content-Type") if contentType == "application/json" { - defer r.Body.Close() d := json.NewDecoder(r.Body) if err := d.Decode(&upload); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + decodeError := fmt.Errorf("Unable to decode upload data: %s", err).Error() + http.Error(w, decodeError, http.StatusInternalServerError) return } err, code := upload.ValidateUpload() @@ -139,7 +141,6 @@ func ApiUploadHandler(w http.ResponseWriter, r *http.Request) { return } } else if strings.HasPrefix(contentType, "multipart/form-data") { - upload.Name = r.FormValue("name") upload.Category, _ = strconv.Atoi(r.FormValue("category")) upload.SubCategory, _ = strconv.Atoi(r.FormValue("sub_category")) @@ -153,12 +154,17 @@ func ApiUploadHandler(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), code) return } + } else { + // TODO What should we do here ? upload is empty so we shouldn't + // create a torrent from it + err := fmt.Errorf("Please provide either of Content-Type: application/json header or multipart/form-data").Error() + http.Error(w, err, http.StatusInternalServerError) } var sameTorrents int + db.ORM.Model(&model.Torrent{}).Where("torrent_hash = ?", upload.Hash).Count(&sameTorrents) if sameTorrents == 0 { - torrent := model.Torrent{ Name: upload.Name, Category: upload.Category, @@ -183,6 +189,7 @@ func ApiUploadHandler(w http.ResponseWriter, r *http.Request) { } } +// FIXME Impossible to update a torrent uploaded by user 0 func ApiUpdateHandler(w http.ResponseWriter, r *http.Request) { token := r.Header.Get("Authorization") user := model.User{} diff --git a/router/databaseDumpHandler.go b/router/database_dump_handler.go similarity index 100% rename from router/databaseDumpHandler.go rename to router/database_dump_handler.go diff --git a/router/faqHandler.go b/router/faq_handler.go similarity index 56% rename from router/faqHandler.go rename to router/faq_handler.go index dd2d3e73..11269121 100644 --- a/router/faqHandler.go +++ b/router/faq_handler.go @@ -9,7 +9,14 @@ import ( func FaqHandler(w http.ResponseWriter, r *http.Request) { languages.SetTranslationFromRequest(faqTemplate, r) - err := faqTemplate.ExecuteTemplate(w, "index.html", FaqTemplateVariables{NewNavigation(), NewSearchForm(), GetUser(r), r.URL, mux.CurrentRoute(r)}) + ftv := FaqTemplateVariables{ + Navigation: NewNavigation(), + Search: NewSearchForm(), + User: GetUser(r), + URL: r.URL, + Route: mux.CurrentRoute(r), + } + err := faqTemplate.ExecuteTemplate(w, "index.html", ftv) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } diff --git a/router/homeHandler.go b/router/home_handler.go similarity index 77% rename from router/homeHandler.go rename to router/home_handler.go index 91acd94c..cdc56486 100644 --- a/router/homeHandler.go +++ b/router/home_handler.go @@ -52,12 +52,24 @@ func HomeHandler(w http.ResponseWriter, r *http.Request) { return torrents, nbTorrents, err }) - b := model.TorrentsToJSON(torrents) - - navigationTorrents := Navigation{nbTorrents, maxPerPage, pagenum, "search_page"} + navigationTorrents := Navigation{ + TotalItem: nbTorrents, + MaxItemPerPage: maxPerPage, + CurrentPage: pagenum, + Route: "search_page", + } languages.SetTranslationFromRequest(homeTemplate, r) - htv := HomeTemplateVariables{b, NewSearchForm(), navigationTorrents, GetUser(r), r.URL, mux.CurrentRoute(r)} + + torrentsJson := model.TorrentsToJSON(torrents) + htv := HomeTemplateVariables{ + ListTorrents: torrentsJson, + Search: NewSearchForm(), + Navigation: navigationTorrents, + User: GetUser(r), + URL: r.URL, + Route: mux.CurrentRoute(r), + } err = homeTemplate.ExecuteTemplate(w, "index.html", htv) if err != nil { diff --git a/router/changeLanguageHandler.go b/router/language_handler.go similarity index 80% rename from router/changeLanguageHandler.go rename to router/language_handler.go index b28fbd75..f7ff0da6 100644 --- a/router/changeLanguageHandler.go +++ b/router/language_handler.go @@ -18,8 +18,8 @@ func SeeLanguagesHandler(w http.ResponseWriter, r *http.Request) { _, Tlang := languages.GetTfuncAndLanguageFromRequest(r) availableLanguages := languages.GetAvailableLanguages() - format := r.URL.Query().Get("format") - if format == "json" { + contentType := r.Header.Get("Content-Type") + if contentType == "application/json" { w.Header().Set("Content-Type", "application/json") err := json.NewEncoder(w).Encode(LanguagesJSONResponse{Tlang.Tag, availableLanguages}) if err != nil { @@ -27,7 +27,15 @@ func SeeLanguagesHandler(w http.ResponseWriter, r *http.Request) { return } } else { - clv := ChangeLanguageVariables{NewSearchForm(), NewNavigation(), Tlang.Tag, availableLanguages, GetUser(r), r.URL, mux.CurrentRoute(r)} + clv := ChangeLanguageVariables{ + Search: NewSearchForm(), + Navigation: NewNavigation(), + Language: Tlang.Tag, + Languages: availableLanguages, + User: GetUser(r), + URL: r.URL, + Route: mux.CurrentRoute(r), + } languages.SetTranslationFromRequest(changeLanguageTemplate, r) err := changeLanguageTemplate.ExecuteTemplate(w, "index.html", clv) if err != nil { @@ -52,9 +60,8 @@ func ChangeLanguageHandler(w http.ResponseWriter, r *http.Request) { user.Language = lang // I don't know if I should use this... userService.UpdateUserCore(&user) - } else { - http.SetCookie(w, &http.Cookie{Name: "lang", Value: lang}) } + http.SetCookie(w, &http.Cookie{Name: "lang", Value: lang}) url, _ := Router.Get("home").URL() http.Redirect(w, r, url.String(), http.StatusSeeOther) diff --git a/router/notFoundHandler.go b/router/not_found_handler.go similarity index 58% rename from router/notFoundHandler.go rename to router/not_found_handler.go index 8bbfe6c5..0eee09fe 100644 --- a/router/notFoundHandler.go +++ b/router/not_found_handler.go @@ -8,10 +8,18 @@ import ( ) func NotFoundHandler(w http.ResponseWriter, r *http.Request) { + languages.SetTranslationFromRequest(notFoundTemplate, r) w.WriteHeader(http.StatusNotFound) - languages.SetTranslationFromRequest(notFoundTemplate, r) - err := notFoundTemplate.ExecuteTemplate(w, "index.html", NotFoundTemplateVariables{NewNavigation(), NewSearchForm(), GetUser(r), r.URL, mux.CurrentRoute(r)}) + nftv := NotFoundTemplateVariables{ + Navigation: NewNavigation(), + Search: NewSearchForm(), + User: GetUser(r), + URL: r.URL, + Route: mux.CurrentRoute(r), + } + + err := notFoundTemplate.ExecuteTemplate(w, "index.html", nftv) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } diff --git a/router/router.go b/router/router.go old mode 100755 new mode 100644 index ffcf1029..276ff759 --- a/router/router.go +++ b/router/router.go @@ -30,43 +30,9 @@ func init() { gzipUserProfileFormHandler := http.HandlerFunc(UserProfileFormHandler) gzipDumpsHandler := handlers.CompressHandler(dumpsHandler) gzipGpgKeyHandler := handlers.CompressHandler(gpgKeyHandler) - - /* - // Enable GZIP compression for all handlers except imgHandler and captcha - gzipCSSHandler := cssHandler) - gzipJSHandler:= jsHandler) - gzipSearchHandler:= http.HandlerFunc(SearchHandler) - gzipAPIUploadHandler := http.HandlerFunc(ApiUploadHandler) - gzipAPIUpdateHandler := http.HandlerFunc(ApiUpdateHandler) - gzipFaqHandler := http.HandlerFunc(FaqHandler) - gzipRSSHandler := http.HandlerFunc(RSSHandler) - gzipUploadHandler := http.HandlerFunc(UploadHandler) - gzipUserRegisterFormHandler := http.HandlerFunc(UserRegisterFormHandler) - gzipUserLoginFormHandler := http.HandlerFunc(UserLoginFormHandler) - gzipUserVerifyEmailHandler := http.HandlerFunc(UserVerifyEmailHandler) - gzipUserRegisterPostHandler := http.HandlerFunc(UserRegisterPostHandler) - gzipUserLoginPostHandler := http.HandlerFunc(UserLoginPostHandler) - gzipUserLogoutHandler := http.HandlerFunc(UserLogoutHandler) - gzipUserFollowHandler := http.HandlerFunc(UserFollowHandler) - - gzipIndexModPanel := http.HandlerFunc(IndexModPanel) - gzipTorrentsListPanel := http.HandlerFunc(TorrentsListPanel) - gzipTorrentReportListPanel := http.HandlerFunc(TorrentReportListPanel) - gzipUsersListPanel := http.HandlerFunc(UsersListPanel) - gzipCommentsListPanel := http.HandlerFunc(CommentsListPanel) - gzipTorrentEditModPanel := http.HandlerFunc(TorrentEditModPanel) - gzipTorrentPostEditModPanel := http.HandlerFunc(TorrentPostEditModPanel) - gzipCommentDeleteModPanel := http.HandlerFunc(CommentDeleteModPanel) - gzipTorrentDeleteModPanel := http.HandlerFunc(TorrentDeleteModPanel) - gzipTorrentReportDeleteModPanel := http.HandlerFunc(TorrentReportDeleteModPanel)*/ - //gzipTorrentReportCreateHandler := http.HandlerFunc(CreateTorrentReportHandler) - //gzipTorrentReportDeleteHandler := http.HandlerFunc(DeleteTorrentReportHandler) - //gzipTorrentDeleteHandler := http.HandlerFunc(DeleteTorrentHandler) gzipDatabaseDumpHandler := handlers.CompressHandler(http.HandlerFunc(DatabaseDumpHandler)) Router = mux.NewRouter() - - // Routes http.Handle("/css/", http.StripPrefix("/css/", cssHandler)) http.Handle("/js/", http.StripPrefix("/js/", jsHandler)) http.Handle("/img/", http.StripPrefix("/img/", imgHandler)) diff --git a/router/rssHandler.go b/router/rss_handler.go similarity index 100% rename from router/rssHandler.go rename to router/rss_handler.go diff --git a/router/searchHandler.go b/router/search_handler.go similarity index 100% rename from router/searchHandler.go rename to router/search_handler.go diff --git a/router/template.go b/router/template.go index 0a66df12..fb6eaa35 100644 --- a/router/template.go +++ b/router/template.go @@ -7,9 +7,29 @@ import ( var TemplateDir = "templates" -var homeTemplate, searchTemplate, faqTemplate, uploadTemplate, viewTemplate, viewRegisterTemplate, viewLoginTemplate, viewRegisterSuccessTemplate, viewVerifySuccessTemplate, viewProfileTemplate, viewProfileEditTemplate, viewUserDeleteTemplate, notFoundTemplate, changeLanguageTemplate, databaseDumpTemplate *template.Template +var homeTemplate, + searchTemplate, + faqTemplate, + uploadTemplate, + viewTemplate, + viewRegisterTemplate, + viewLoginTemplate, + viewRegisterSuccessTemplate, + viewVerifySuccessTemplate, + viewProfileTemplate, + viewProfileEditTemplate, + viewUserDeleteTemplate, + notFoundTemplate, + changeLanguageTemplate, + databaseDumpTemplate *template.Template -var panelIndex, panelTorrentList, panelUserList, panelCommentList, panelTorrentEd, panelTorrentReportList, panelTorrentReassign *template.Template +var panelIndex, + panelTorrentList, + panelUserList, + panelCommentList, + panelTorrentEd, + panelTorrentReportList, + panelTorrentReassign *template.Template type templateLoader struct { templ **template.Template @@ -93,8 +113,8 @@ func ReloadTemplates() { }, templateLoader{ templ: &changeLanguageTemplate, - name: "change_language", - file: "change_language.html", + name: "change_language", + file: "change_language.html", }, } for idx := range pubTempls { diff --git a/router/templateFunctions.go b/router/template_functions.go similarity index 100% rename from router/templateFunctions.go rename to router/template_functions.go diff --git a/router/templateVariables.go b/router/template_variables.go similarity index 100% rename from router/templateVariables.go rename to router/template_variables.go diff --git a/router/torrentReportHandler.go b/router/torrent_report_handler.go similarity index 100% rename from router/torrentReportHandler.go rename to router/torrent_report_handler.go diff --git a/router/uploadHandler.go b/router/uploadHandler.go deleted file mode 100644 index dbc0e333..00000000 --- a/router/uploadHandler.go +++ /dev/null @@ -1,118 +0,0 @@ -package router - -import ( - "fmt" - "net/http" - "strconv" - "time" - - "github.com/NyaaPantsu/nyaa/config" - "github.com/NyaaPantsu/nyaa/db" - "github.com/NyaaPantsu/nyaa/model" - "github.com/NyaaPantsu/nyaa/service/captcha" - "github.com/NyaaPantsu/nyaa/service/user/permission" - "github.com/NyaaPantsu/nyaa/util/languages" - "github.com/gorilla/mux" -) - -func UploadHandler(w http.ResponseWriter, r *http.Request) { - user := GetUser(r) - - if config.UploadsDisabled { - - if config.AdminsAreStillAllowedTo && user.Status != 2 && config.TrustedUsersAreStillAllowedTo && user.Status != 1 { - http.Error(w, "Error uploads are disabled", http.StatusInternalServerError) - return - } else if !config.AdminsAreStillAllowedTo && user.Status == 2 { - http.Error(w, "Error uploads are disabled", http.StatusInternalServerError) - return - } else if !config.TrustedUsersAreStillAllowedTo && user.Status == 1 { - http.Error(w, "Error uploads are disabled", http.StatusInternalServerError) - return - } - - } - - var uploadForm UploadForm - if r.Method == "POST" { - defer r.Body.Close() - if userPermission.NeedsCaptcha(user) { - userCaptcha := captcha.Extract(r) - if !captcha.Authenticate(userCaptcha) { - http.Error(w, captcha.ErrInvalidCaptcha.Error(), http.StatusInternalServerError) - return - } - } - - // validation is done in ExtractInfo() - err := uploadForm.ExtractInfo(r) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - status := 1 // normal - if uploadForm.Remake { // overrides trusted - status = 2 - } else if user.Status == 1 { - status = 3 // mark as trusted if user is trusted - } - - var sameTorrents int - db.ORM.Model(&model.Torrent{}).Table(config.TableName).Where("torrent_hash = ?", uploadForm.Infohash).Count(&sameTorrents) - if sameTorrents == 0 { - // add to db and redirect - torrent := model.Torrent{ - Name: uploadForm.Name, - Category: uploadForm.CategoryID, - SubCategory: uploadForm.SubCategoryID, - Status: status, - Hash: uploadForm.Infohash, - Date: time.Now(), - Filesize: uploadForm.Filesize, - Description: uploadForm.Description, - UploaderID: user.ID} - db.ORM.Table(config.TableName).Create(&torrent) - - // add filelist to files db, if we have one - if len(uploadForm.FileList) > 0 { - for _, uploadedFile := range uploadForm.FileList { - file := model.File{TorrentID: torrent.ID, Filesize: uploadedFile.Filesize} - err := file.SetPath(uploadedFile.Path) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - db.ORM.Create(&file) - } - } - - url, err := Router.Get("view_torrent").URL("id", strconv.FormatUint(uint64(torrent.ID), 10)) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - http.Redirect(w, r, url.String(), 302) - } else { - http.Error(w, fmt.Errorf("Torrent already in database!").Error(), http.StatusInternalServerError) - return - } - } else if r.Method == "GET" { - user := GetUser(r) - if userPermission.NeedsCaptcha(user) { - uploadForm.CaptchaID = captcha.GetID() - } else { - uploadForm.CaptchaID = "" - } - - htv := UploadTemplateVariables{uploadForm, NewSearchForm(), NewNavigation(), GetUser(r), r.URL, mux.CurrentRoute(r)} - languages.SetTranslationFromRequest(uploadTemplate, r) - err := uploadTemplate.ExecuteTemplate(w, "index.html", htv) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - } else { - w.WriteHeader(http.StatusMethodNotAllowed) - return - } -} diff --git a/router/upload_handler.go b/router/upload_handler.go new file mode 100644 index 00000000..0673829f --- /dev/null +++ b/router/upload_handler.go @@ -0,0 +1,134 @@ +package router + +import ( + "fmt" + "net/http" + "strconv" + "time" + + "github.com/NyaaPantsu/nyaa/config" + "github.com/NyaaPantsu/nyaa/db" + "github.com/NyaaPantsu/nyaa/model" + "github.com/NyaaPantsu/nyaa/service/captcha" + "github.com/NyaaPantsu/nyaa/service/user/permission" + "github.com/NyaaPantsu/nyaa/util/languages" + "github.com/gorilla/mux" +) + +func UploadHandler(w http.ResponseWriter, r *http.Request) { + if config.UploadsDisabled { + user := GetUser(r) + if config.AdminsAreStillAllowedTo && user.Status != 2 && config.TrustedUsersAreStillAllowedTo && user.Status != 1 { + http.Error(w, "Error uploads are disabled", http.StatusInternalServerError) + return + } else if !config.AdminsAreStillAllowedTo && user.Status == 2 { + http.Error(w, "Error uploads are disabled", http.StatusInternalServerError) + return + } else if !config.TrustedUsersAreStillAllowedTo && user.Status == 1 { + http.Error(w, "Error uploads are disabled", http.StatusInternalServerError) + return + } + } + + if r.Method == "POST" { + UploadPostHandler(w, r) + } else if r.Method == "GET" { + UploadGetHandler(w, r) + } else { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } +} + +func UploadPostHandler(w http.ResponseWriter, r *http.Request) { + var uploadForm UploadForm + defer r.Body.Close() + user := GetUser(r) + if userPermission.NeedsCaptcha(user) { + userCaptcha := captcha.Extract(r) + if !captcha.Authenticate(userCaptcha) { + http.Error(w, captcha.ErrInvalidCaptcha.Error(), http.StatusInternalServerError) + return + } + } + + // validation is done in ExtractInfo() + err := uploadForm.ExtractInfo(r) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + status := 1 // normal + if uploadForm.Remake { // overrides trusted + status = 2 + } else if user.Status == 1 { + status = 3 // mark as trusted if user is trusted + } + + var sameTorrents int + db.ORM.Model(&model.Torrent{}).Table(config.TableName).Where("torrent_hash = ?", uploadForm.Infohash).Count(&sameTorrents) + if sameTorrents == 0 { + // add to db and redirect + torrent := model.Torrent{ + Name: uploadForm.Name, + Category: uploadForm.CategoryID, + SubCategory: uploadForm.SubCategoryID, + Status: status, + Hash: uploadForm.Infohash, + Date: time.Now(), + Filesize: uploadForm.Filesize, + Description: uploadForm.Description, + UploaderID: user.ID} + db.ORM.Table(config.TableName).Create(&torrent) + + // add filelist to files db, if we have one + if len(uploadForm.FileList) > 0 { + for _, uploadedFile := range uploadForm.FileList { + file := model.File{TorrentID: torrent.ID, Filesize: uploadedFile.Filesize} + err := file.SetPath(uploadedFile.Path) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + db.ORM.Create(&file) + } + } + + url, err := Router.Get("view_torrent").URL("id", strconv.FormatUint(uint64(torrent.ID), 10)) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + http.Redirect(w, r, url.String(), 302) + } else { + err = fmt.Errorf("Torrent already in database!") + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } +} + +func UploadGetHandler(w http.ResponseWriter, r *http.Request) { + languages.SetTranslationFromRequest(uploadTemplate, r) + + var uploadForm UploadForm + user := GetUser(r) + if userPermission.NeedsCaptcha(user) { + uploadForm.CaptchaID = captcha.GetID() + } else { + uploadForm.CaptchaID = "" + } + + utv := UploadTemplateVariables{ + Upload: uploadForm, + Search: NewSearchForm(), + Navigation: NewNavigation(), + User: GetUser(r), + URL: r.URL, + Route: mux.CurrentRoute(r), + } + err := uploadTemplate.ExecuteTemplate(w, "index.html", utv) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } +} diff --git a/router/userHandler.go b/router/user_handler.go old mode 100755 new mode 100644 similarity index 72% rename from router/userHandler.go rename to router/user_handler.go index 6744559a..7264a078 --- a/router/userHandler.go +++ b/router/user_handler.go @@ -18,30 +18,47 @@ import ( // Getting View User Registration func UserRegisterFormHandler(w http.ResponseWriter, r *http.Request) { _, errorUser := userService.CurrentUser(r) - if errorUser != nil { - b := form.RegistrationForm{} - modelHelper.BindValueForm(&b, r) - b.CaptchaID = captcha.GetID() - languages.SetTranslationFromRequest(viewRegisterTemplate, r) - htv := UserRegisterTemplateVariables{b, form.NewErrors(), NewSearchForm(), NewNavigation(), GetUser(r), r.URL, mux.CurrentRoute(r)} - err := viewRegisterTemplate.ExecuteTemplate(w, "index.html", htv) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - } else { + // User is already connected, redirect to home + if errorUser == nil { HomeHandler(w, r) + return + } + registrationForm := form.RegistrationForm{} + modelHelper.BindValueForm(®istrationForm, r) + registrationForm.CaptchaID = captcha.GetID() + languages.SetTranslationFromRequest(viewRegisterTemplate, r) + urtv := UserRegisterTemplateVariables{ + RegistrationForm: registrationForm, + FormErrors: form.NewErrors(), + Search: NewSearchForm(), + Navigation: NewNavigation(), + User: GetUser(r), + URL: r.URL, + Route: mux.CurrentRoute(r), + } + err := viewRegisterTemplate.ExecuteTemplate(w, "index.html", urtv) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) } } // Getting View User Login func UserLoginFormHandler(w http.ResponseWriter, r *http.Request) { - b := form.LoginForm{} - modelHelper.BindValueForm(&b, r) + loginForm := form.LoginForm{} + modelHelper.BindValueForm(&loginForm, r) languages.SetTranslationFromRequest(viewLoginTemplate, r) - htv := UserLoginFormVariables{b, form.NewErrors(), NewSearchForm(), NewNavigation(), GetUser(r), r.URL, mux.CurrentRoute(r)} + ulfv := UserLoginFormVariables{ + LoginForm: loginForm, + FormErrors: form.NewErrors(), + Search: NewSearchForm(), + Navigation: NewNavigation(), + User: GetUser(r), + URL: r.URL, + Route: mux.CurrentRoute(r), + } - err := viewLoginTemplate.ExecuteTemplate(w, "index.html", htv) + err := viewLoginTemplate.ExecuteTemplate(w, "index.html", ulfv) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } @@ -128,64 +145,64 @@ func UserProfileFormHandler(w http.ResponseWriter, r *http.Request) { id := vars["id"] currentUser := GetUser(r) userProfile, _, errorUser := userService.RetrieveUserForAdmin(id) - if errorUser == nil { - if userPermission.CurrentOrAdmin(currentUser, userProfile.ID) { - b := form.UserForm{} - err := form.NewErrors() - infos := form.NewInfos() - T := languages.SetTranslationFromRequest(viewProfileEditTemplate, r) - if len(r.PostFormValue("email")) > 0 { - _, err = form.EmailValidation(r.PostFormValue("email"), err) - } - if len(r.PostFormValue("username")) > 0 { - _, err = form.ValidateUsername(r.PostFormValue("username"), err) - } + if errorUser != nil || !userPermission.CurrentOrAdmin(currentUser, userProfile.ID) { + NotFoundHandler(w, r) + return + } - if len(err) == 0 { - modelHelper.BindValueForm(&b, r) - if !userPermission.HasAdmin(currentUser) { - b.Username = userProfile.Username - b.Status = userProfile.Status - } else { - if userProfile.Status != b.Status && b.Status == 2 { - err["errors"] = append(err["errors"], "Elevating status to moderator is prohibited") - } - } - err = modelHelper.ValidateForm(&b, err) - if len(err) == 0 { - if b.Email != userProfile.Email { - userService.SendVerificationToUser(*currentUser, b.Email) - infos["infos"] = append(infos["infos"], fmt.Sprintf(T("email_changed"), b.Email)) - b.Email = userProfile.Email // reset, it will be set when user clicks verification - } - userProfile, _, errorUser = userService.UpdateUser(w, &b, currentUser, id) - if errorUser != nil { - err["errors"] = append(err["errors"], errorUser.Error()) - } else { - infos["infos"] = append(infos["infos"], T("profile_updated")) - } - } - } - availableLanguages := languages.GetAvailableLanguages() - htv := UserProfileEditVariables{&userProfile, b, err, infos, availableLanguages, NewSearchForm(), NewNavigation(), currentUser, r.URL, mux.CurrentRoute(r)} - errorTmpl := viewProfileEditTemplate.ExecuteTemplate(w, "index.html", htv) - if errorTmpl != nil { - http.Error(w, errorTmpl.Error(), http.StatusInternalServerError) - } + userForm := form.UserForm{} + err := form.NewErrors() + infos := form.NewInfos() + T := languages.SetTranslationFromRequest(viewProfileEditTemplate, r) + if len(r.PostFormValue("email")) > 0 { + _, err = form.EmailValidation(r.PostFormValue("email"), err) + } + if len(r.PostFormValue("username")) > 0 { + _, err = form.ValidateUsername(r.PostFormValue("username"), err) + } + + if len(err) == 0 { + modelHelper.BindValueForm(&userForm, r) + if !userPermission.HasAdmin(currentUser) { + userForm.Username = userProfile.Username + userForm.Status = userProfile.Status } else { - languages.SetTranslationFromRequest(notFoundTemplate, r) - err := notFoundTemplate.ExecuteTemplate(w, "index.html", NotFoundTemplateVariables{NewNavigation(), NewSearchForm(), GetUser(r), r.URL, mux.CurrentRoute(r)}) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + if userProfile.Status != userForm.Status && userForm.Status == 2 { + err["errors"] = append(err["errors"], "Elevating status to moderator is prohibited") } } - } else { - languages.SetTranslationFromRequest(notFoundTemplate, r) - err := notFoundTemplate.ExecuteTemplate(w, "index.html", NotFoundTemplateVariables{NewNavigation(), NewSearchForm(), GetUser(r), r.URL, mux.CurrentRoute(r)}) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + err = modelHelper.ValidateForm(&userForm, err) + if len(err) == 0 { + if userForm.Email != userProfile.Email { + userService.SendVerificationToUser(*currentUser, userForm.Email) + infos["infos"] = append(infos["infos"], fmt.Sprintf(T("email_changed"), userForm.Email)) + userForm.Email = userProfile.Email // reset, it will be set when user clicks verification + } + userProfile, _, errorUser = userService.UpdateUser(w, &userForm, currentUser, id) + if errorUser != nil { + err["errors"] = append(err["errors"], errorUser.Error()) + } else { + infos["infos"] = append(infos["infos"], T("profile_updated")) + } } } + availableLanguages := languages.GetAvailableLanguages() + upev := UserProfileEditVariables{ + UserProfile: &userProfile, + UserForm: userForm, + FormErrors: err, + FormInfos: infos, + Languages: availableLanguages, + Search: NewSearchForm(), + Navigation: NewNavigation(), + User: currentUser, + URL: r.URL, + Route: mux.CurrentRoute(r), + } + errorTmpl := viewProfileEditTemplate.ExecuteTemplate(w, "index.html", upev) + if errorTmpl != nil { + http.Error(w, errorTmpl.Error(), http.StatusInternalServerError) + } } // Post Registration controller, we do some check on the form here, the rest on user service diff --git a/router/viewTorrentHandler.go b/router/view_torrent_handler.go similarity index 100% rename from router/viewTorrentHandler.go rename to router/view_torrent_handler.go diff --git a/router/wrapHandler.go b/router/wrap_handler.go similarity index 100% rename from router/wrapHandler.go rename to router/wrap_handler.go diff --git a/service/api/api.go b/service/api/api.go index 3c789cb0..479945cd 100644 --- a/service/api/api.go +++ b/service/api/api.go @@ -74,6 +74,7 @@ func validateName(r *TorrentRequest) (error, int) { return nil, http.StatusOK } +// TODO Check category is within accepted range func validateCategory(r *TorrentRequest) (error, int) { if r.Category == 0 { return ErrCategory, http.StatusNotAcceptable @@ -81,6 +82,7 @@ func validateCategory(r *TorrentRequest) (error, int) { return nil, http.StatusOK } +// TODO Check subCategory is within accepted range func validateSubCategory(r *TorrentRequest) (error, int) { if r.SubCategory == 0 { return ErrSubCategory, http.StatusNotAcceptable diff --git a/service/torrent/metainfoFetcher/metainfoFetcher.go b/service/torrent/metainfoFetcher/metainfo_fetcher.go similarity index 100% rename from service/torrent/metainfoFetcher/metainfoFetcher.go rename to service/torrent/metainfoFetcher/metainfo_fetcher.go diff --git a/service/user/form/formValidator.go b/service/user/form/form_validator.go similarity index 100% rename from service/user/form/formValidator.go rename to service/user/form/form_validator.go diff --git a/service/user/userHelper.go b/service/user/user_helper.go similarity index 100% rename from service/user/userHelper.go rename to service/user/user_helper.go diff --git a/translations/add_translation.sh b/translations/add_translation.sh deleted file mode 100755 index 08614b16..00000000 --- a/translations/add_translation.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -id="$1" -translation="$2" - -for file in *.json; do - head -n -2 "${file}" > "${file}.tmp" - echo -e " },\n {\n \"id\": \"${id}\",\n \"translation\": \"${translation}\"\n }\n]" >> "${file}.tmp" - mv "${file}.tmp" "${file}" -done diff --git a/util/languages/translation.go b/util/languages/translation.go index d2bd5b6d..ec6c554a 100644 --- a/util/languages/translation.go +++ b/util/languages/translation.go @@ -29,7 +29,7 @@ func InitI18n(conf config.I18nConfig, retriever UserRetriever) error { defaultLanguage = conf.DefaultLanguage userRetriever = retriever - defaultFilepath := path.Join(conf.TranslationsDirectory, conf.DefaultLanguage+".all.json") + defaultFilepath := path.Join(conf.TranslationsDirectory, defaultLanguage+".all.json") err := i18n.LoadTranslationFile(defaultFilepath) if err != nil { panic(fmt.Sprintf("failed to load default translation file '%s': %v", defaultFilepath, err)) @@ -57,27 +57,26 @@ func GetDefaultLanguage() string { // When go-i18n finds a language with >0 translations, it uses it as the Tfunc // However, if said language has a missing translation, it won't fallback to the "main" language func TfuncAndLanguageWithFallback(language string, languages ...string) (i18n.TranslateFunc, *language.Language, error) { - // Use the last language on the args as the fallback one. - fallbackLanguage := language - if languages != nil { - fallbackLanguage = languages[len(languages)-1] - } + fallbackLanguage := GetDefaultLanguage() - T, Tlang, err1 := i18n.TfuncAndLanguage(language, languages...) - fallbackT, fallbackTlang, err2 := i18n.TfuncAndLanguage(fallbackLanguage) + tFunc, tLang, err1 := i18n.TfuncAndLanguage(language, languages...) + // If fallbackLanguage fails, it will give the "id" field so we don't + // care about the error + fallbackT, fallbackTlang, _ := i18n.TfuncAndLanguage(fallbackLanguage) - if err1 != nil && err2 != nil { - // fallbackT is still a valid function even with the error, it returns translationID. - return fallbackT, fallbackTlang, err2 - } - - return func(translationID string, args ...interface{}) string { - if translated := T(translationID, args...); translated != translationID { + translateFunction := func(translationID string, args ...interface{}) string { + if translated := tFunc(translationID, args...); translated != translationID { return translated } return fallbackT(translationID, args...) - }, Tlang, nil + } + + if err1 != nil { + tLang = fallbackTlang + } + + return translateFunction, tLang, err1 } func GetAvailableLanguages() (languages map[string]string) { @@ -112,8 +111,6 @@ func GetDefaultTfunc() (i18n.TranslateFunc, error) { } func GetTfuncAndLanguageFromRequest(r *http.Request) (T i18n.TranslateFunc, Tlang *language.Language) { - defaultLanguage := GetDefaultLanguage() - userLanguage := "" user, err := getCurrentUser(r) if err == nil { @@ -126,9 +123,9 @@ func GetTfuncAndLanguageFromRequest(r *http.Request) (T i18n.TranslateFunc, Tlan cookieLanguage = cookie.Value } - // go-i18n supports the format of the Accept-Language header, thankfully. + // go-i18n supports the format of the Accept-Language header headerLanguage := r.Header.Get("Accept-Language") - T, Tlang, _ = TfuncAndLanguageWithFallback(userLanguage, cookieLanguage, headerLanguage, defaultLanguage) + T, Tlang, _ = TfuncAndLanguageWithFallback(userLanguage, cookieLanguage, headerLanguage) return } diff --git a/util/modelHelper/modelHelper.go b/util/modelHelper/model_helper.go similarity index 100% rename from util/modelHelper/modelHelper.go rename to util/modelHelper/model_helper.go diff --git a/util/timeHelper/timeHelper.go b/util/timeHelper/time_helper.go similarity index 100% rename from util/timeHelper/timeHelper.go rename to util/timeHelper/time_helper.go