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")
}