123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- // Copyright (C) 2019 Nicola Murino
- //
- // This program is free software: you can redistribute it and/or modify
- // it under the terms of the GNU Affero General Public License as published
- // by the Free Software Foundation, version 3.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU Affero General Public License for more details.
- //
- // You should have received a copy of the GNU Affero General Public License
- // along with this program. If not, see <https://www.gnu.org/licenses/>.
- package httpd
- import (
- "errors"
- "net/http"
- "strings"
- "github.com/go-chi/render"
- "github.com/unrolled/secure"
- "github.com/drakkan/sftpgo/v2/internal/util"
- "github.com/drakkan/sftpgo/v2/internal/version"
- )
- const (
- pageMFATitle = "Two-factor authentication"
- pageTwoFactorTitle = "Two-Factor authentication"
- pageTwoFactorRecoveryTitle = "Two-Factor recovery"
- webDateTimeFormat = "2006-01-02 15:04:05" // YYYY-MM-DD HH:MM:SS
- redactedSecret = "[**redacted**]"
- csrfFormToken = "_form_token"
- csrfHeaderToken = "X-CSRF-TOKEN"
- templateCommonDir = "common"
- templateTwoFactor = "twofactor.html"
- templateTwoFactorRecovery = "twofactor-recovery.html"
- templateForgotPassword = "forgot-password.html"
- templateResetPassword = "reset-password.html"
- templateChangePwd = "changepassword.html"
- templateMessage = "message.html"
- templateCommonBase = "base.html"
- templateCommonBaseLogin = "baselogin.html"
- templateCommonLogin = "login.html"
- )
- var (
- errInvalidTokenClaims = errors.New("invalid token claims")
- )
- type commonBasePage struct {
- CSPNonce string
- StaticURL string
- Version string
- }
- type loginPage struct {
- commonBasePage
- CurrentURL string
- Error *util.I18nError
- CSRFToken string
- AltLoginURL string
- AltLoginName string
- ForgotPwdURL string
- OpenIDLoginURL string
- Title string
- Branding UIBranding
- FormDisabled bool
- CheckRedirect bool
- }
- type twoFactorPage struct {
- commonBasePage
- CurrentURL string
- Error *util.I18nError
- CSRFToken string
- RecoveryURL string
- Title string
- Branding UIBranding
- }
- type forgotPwdPage struct {
- commonBasePage
- CurrentURL string
- Error *util.I18nError
- CSRFToken string
- LoginURL string
- Title string
- Branding UIBranding
- }
- type resetPwdPage struct {
- commonBasePage
- CurrentURL string
- Error *util.I18nError
- CSRFToken string
- LoginURL string
- Title string
- Branding UIBranding
- }
- func getSliceFromDelimitedValues(values, delimiter string) []string {
- result := []string{}
- for _, v := range strings.Split(values, delimiter) {
- cleaned := strings.TrimSpace(v)
- if cleaned != "" {
- result = append(result, cleaned)
- }
- }
- return result
- }
- func hasPrefixAndSuffix(key, prefix, suffix string) bool {
- return strings.HasPrefix(key, prefix) && strings.HasSuffix(key, suffix)
- }
- func getCommonBasePage(r *http.Request) commonBasePage {
- return commonBasePage{
- CSPNonce: secure.CSPNonce(r.Context()),
- StaticURL: webStaticFilesPath,
- Version: version.GetServerVersion(" ", true),
- }
- }
- func i18nListDirMsg(status int) string {
- if status == http.StatusForbidden {
- return util.I18nErrorDirList403
- }
- return util.I18nErrorDirListGeneric
- }
- func i18nFsMsg(status int) string {
- if status == http.StatusForbidden {
- return util.I18nError403Message
- }
- return util.I18nErrorFsGeneric
- }
- func getI18NErrorString(err error, fallback string) string {
- var errI18n *util.I18nError
- if errors.As(err, &errI18n) {
- return errI18n.Message
- }
- return fallback
- }
- func getI18nError(err error) *util.I18nError {
- var errI18n *util.I18nError
- if err != nil {
- errI18n = util.NewI18nError(err, util.I18nError500Message)
- }
- return errI18n
- }
- func handlePingRequest(w http.ResponseWriter, r *http.Request) {
- r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
- render.PlainText(w, r, "PONG")
- }
|