From f45c132b41de86305b26bcbfe34df3953fbb1ba6 Mon Sep 17 00:00:00 2001 From: Daan Sprenkels Date: Sat, 21 Sep 2019 21:03:31 +0200 Subject: [PATCH] Make deleteTokens strings --- .../html/newRedirectPasteSuccess.html.tmpl | 3 + .../txt/newRedirectPasteSuccess.txt.tmpl | 1 + handlers/handlers.go | 75 ++++++------------- 3 files changed, 28 insertions(+), 51 deletions(-) create mode 100644 assets/templates/html/newRedirectPasteSuccess.html.tmpl create mode 100644 assets/templates/txt/newRedirectPasteSuccess.txt.tmpl diff --git a/assets/templates/html/newRedirectPasteSuccess.html.tmpl b/assets/templates/html/newRedirectPasteSuccess.html.tmpl new file mode 100644 index 0000000..334f2cb --- /dev/null +++ b/assets/templates/html/newRedirectPasteSuccess.html.tmpl @@ -0,0 +1,3 @@ +{{define "title"}} +Success - rushlink +{{end}} \ No newline at end of file diff --git a/assets/templates/txt/newRedirectPasteSuccess.txt.tmpl b/assets/templates/txt/newRedirectPasteSuccess.txt.tmpl new file mode 100644 index 0000000..bc3e192 --- /dev/null +++ b/assets/templates/txt/newRedirectPasteSuccess.txt.tmpl @@ -0,0 +1 @@ +{{.Request.Host}}/{{.Paste.Key}}?deleteToken={{.Paste.DeleteToken}} diff --git a/handlers/handlers.go b/handlers/handlers.go index 5815a5c..a9d241c 100644 --- a/handlers/handlers.go +++ b/handlers/handlers.go @@ -28,7 +28,7 @@ type storedPaste struct { State pasteState Content []byte Key string - DeleteToken [16]byte + DeleteToken string TimeCreated time.Time } @@ -126,13 +126,11 @@ func viewPasteHandlerInner(w http.ResponseWriter, r *http.Request, flags viewPas Bool bool String string }{Bool: false} - deleteToken, err := getDeleteTokenFromRequest(r) - if err != nil { - canDelete.String = "invalid" - } else if deleteToken == nil { + deleteToken := getDeleteTokenFromRequest(r) + if deleteToken == "" { canDelete.String = "undefined" } else { - if subtle.ConstantTimeCompare(deleteToken[:], storedPaste.DeleteToken[:]) == 1 { + if subtle.ConstantTimeCompare([]byte(deleteToken), []byte(storedPaste.DeleteToken)) == 1 { canDelete.Bool = true canDelete.String = "correct" } else { @@ -162,7 +160,7 @@ func viewPasteHandlerInner(w http.ResponseWriter, r *http.Request, flags viewPas } w.Write(storedPaste.Content) case stateDeleted: - renderError(w, r, http.StatusGone, "key has been deleted") + renderError(w, r, http.StatusGone, "paste has been deleted") default: log.Printf("error: invalid storedPaste.State (%v) for key '%v'\n", storedPaste.State, storedPaste.Key) msg := fmt.Sprintf("internal server error: invalid storedPaste.State (%v\n)", storedPaste.State) @@ -215,33 +213,16 @@ func newRedirectPasteHandler(w http.ResponseWriter, r *http.Request) { var storedPaste *storedPaste if err := db.DB.Update(func(tx *bolt.Tx) error { // Generate a new delete token for this paste - deleteToken, err := generateDeleteToken() - if err != nil { - return errors.Wrap(err, "generating delete token") - } - - sp, err := shortenURL(tx, userURL, deleteToken) - storedPaste = sp + var err error + storedPaste, err = shortenURL(tx, userURL) return err }); err != nil { log.Printf("error: %v\n", err) renderInternalServerError(w, r, err) return } - - deleteToken := hex.EncodeToString(storedPaste.DeleteToken[:]) - saveRawurl := fmt.Sprintf("%v/%v?deleteToken=%v", r.Host, string(storedPaste.Key), deleteToken) - saveURL, err := r.URL.Parse(saveRawurl) - if err != nil { - err = errors.Wrap(err, "parsing url") - log.Printf("error: %v\n", err) - renderInternalServerError(w, r, err) - return - } - - // TODO(dsprenkels) Put this into a template - w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, "%v\n", saveURL) + data := map[string]interface{}{"Paste": storedPaste} + render(w, r, "newRedirectPasteSuccess", data) } // Delete a URL from the database @@ -250,11 +231,8 @@ func deletePasteHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) key := vars["key"] - deleteToken, err := getDeleteTokenFromRequest(r) - if err != nil { - renderError(w, r, http.StatusBadRequest, "invalid delete token") - return - } else if deleteToken == nil { + deleteToken := getDeleteTokenFromRequest(r) + if deleteToken == "" { renderError(w, r, http.StatusBadRequest, "no delete token provided") return } @@ -266,7 +244,7 @@ func deletePasteHandler(w http.ResponseWriter, r *http.Request) { errorCode = http.StatusNotFound return err } - if subtle.ConstantTimeCompare(deleteToken[:], paste.DeleteToken[:]) == 1 { + if subtle.ConstantTimeCompare([]byte(deleteToken), []byte(paste.DeleteToken)) == 1 { // Replace the old paste with a new empty paste return savePaste(tx, key, storedPaste{ Key: paste.Key, @@ -301,7 +279,7 @@ func getURL(tx *bolt.Tx, key string) (*storedPaste, error) { // Add a new URL to the database // // Returns the new ID if the url was successfully shortened -func shortenURL(tx *bolt.Tx, userURL *url.URL, deleteToken [16]byte) (*storedPaste, error) { +func shortenURL(tx *bolt.Tx, userURL *url.URL) (*storedPaste, error) { pastesBucket := tx.Bucket([]byte(db.BUCKET_PASTES)) if pastesBucket == nil { return nil, errors.Errorf("bucket %v does not exist", db.BUCKET_PASTES) @@ -337,6 +315,12 @@ func shortenURL(tx *bolt.Tx, userURL *url.URL, deleteToken [16]byte) (*storedPas epoch++ } + // Also generate a deleteToken + deleteToken, err := generateDeleteToken() + if err != nil { + return nil, errors.Wrap(err, "generating delete token") + } + // Store the new key storedPaste := storedPaste{ Type: typeRedirect, @@ -403,26 +387,15 @@ func generateURLKey(epoch int) (string, error) { return string(urlKey), nil } -func generateDeleteToken() ([16]byte, error) { +func generateDeleteToken() (string, error) { var deleteToken [16]byte _, err := rand.Read(deleteToken[:]) if err != nil { - return deleteToken, err + return "", err } - return deleteToken, nil + return hex.EncodeToString(deleteToken[:]), nil } -func getDeleteTokenFromRequest(r *http.Request) (*[16]byte, error) { - deleteTokenQuery := r.URL.Query().Get("deleteToken") - if deleteTokenQuery == "" { - return nil, nil - } - var deleteToken [16]byte - n, err := hex.Decode(deleteToken[:], []byte(deleteTokenQuery)) - if err != nil { - return nil, errors.Wrap(err, "decoding hex") - } else if n != 16 { - return nil, errors.Errorf("invalid deleteToken length (%v bytes)", n) - } - return &deleteToken, nil +func getDeleteTokenFromRequest(r *http.Request) string { + return r.URL.Query().Get("deleteToken") }