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