mirror of
https://github.com/osmarks/mycorrhiza.git
synced 2024-10-30 03:36:16 +00:00
Break a lot of stuff
Starring: * Broken error localization for now (got in the way) * The title for error pages is the same for all errors (who cares anyway) * New bugs * The brand new /rename/ handler
This commit is contained in:
parent
dd3f2c698a
commit
eb9acb718e
@ -2,6 +2,7 @@ package hyphae
|
||||
|
||||
import "sync"
|
||||
|
||||
// EmptyHypha is a hypha that does not exist and is not stored anywhere. You get one when querying for a hypha that was not created before.
|
||||
type EmptyHypha struct {
|
||||
sync.RWMutex
|
||||
|
||||
@ -12,6 +13,7 @@ func (e *EmptyHypha) CanonicalName() string {
|
||||
return e.canonicalName
|
||||
}
|
||||
|
||||
// ExtendEmptyToTextual returns a new textual hypha with the same name as the given empty hypha. The created hypha is not stored yet.
|
||||
func ExtendEmptyToTextual(e *EmptyHypha, mycoFilePath string) *TextualHypha {
|
||||
return &TextualHypha{
|
||||
canonicalName: e.CanonicalName(),
|
||||
@ -19,6 +21,7 @@ func ExtendEmptyToTextual(e *EmptyHypha, mycoFilePath string) *TextualHypha {
|
||||
}
|
||||
}
|
||||
|
||||
// ExtendEmptyToMedia returns a new media hypha with the same name as the given empty hypha. The created hypha is not stored yet.
|
||||
func ExtendEmptyToMedia(e *EmptyHypha, mediaFilePath string) *MediaHypha {
|
||||
return &MediaHypha{
|
||||
canonicalName: e.CanonicalName(),
|
||||
|
@ -4,20 +4,17 @@ import (
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
)
|
||||
|
||||
// ExistingHypha is not EmptyHypha.
|
||||
// ExistingHypha is not EmptyHypha. *MediaHypha and *TextualHypha implement this interface.
|
||||
type ExistingHypha interface {
|
||||
Hypha
|
||||
|
||||
// DoesExist does nothing except marks that the type is an ExistingHypha.
|
||||
DoesExist()
|
||||
|
||||
HasTextFile() bool
|
||||
TextFilePath() string
|
||||
}
|
||||
|
||||
// RenameHyphaTo renames a hypha and renames stored filepaths as needed. The actual files are not moved, move them yourself.
|
||||
func RenameHyphaTo(h ExistingHypha, newName string, replaceName func(string) string) {
|
||||
// TODO: that replaceName is suspicious.
|
||||
// TODO: that replaceName is suspicious, get rid of it.
|
||||
newName = util.CanonicalName(newName)
|
||||
byNamesMutex.Lock()
|
||||
h.Lock()
|
||||
@ -37,3 +34,28 @@ func RenameHyphaTo(h ExistingHypha, newName string, replaceName func(string) str
|
||||
byNamesMutex.Unlock()
|
||||
h.Unlock()
|
||||
}
|
||||
|
||||
// DeleteHypha deletes the hypha from the storage.
|
||||
func DeleteHypha(h ExistingHypha) {
|
||||
byNamesMutex.Lock()
|
||||
h.Lock()
|
||||
delete(byNames, h.CanonicalName())
|
||||
decrementCount()
|
||||
byNamesMutex.Unlock()
|
||||
h.Unlock()
|
||||
}
|
||||
|
||||
// Insert inserts the hypha into the storage, possibly overwriting the previous hypha with the same name. Count incrementation is done if needed. You cannot insert an empty hypha.
|
||||
func Insert(h ExistingHypha) (madeNewRecord bool) {
|
||||
_, recorded := byNames[h.CanonicalName()]
|
||||
|
||||
byNamesMutex.Lock()
|
||||
byNames[h.CanonicalName()] = h
|
||||
byNamesMutex.Unlock()
|
||||
|
||||
if !recorded {
|
||||
incrementCount()
|
||||
}
|
||||
|
||||
return !recorded
|
||||
}
|
||||
|
@ -6,12 +6,12 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// HyphaPattern is a pattern which all hyphae names must match.
|
||||
var HyphaPattern = regexp.MustCompile(`[^?!:#@><*|"'&%{}]+`)
|
||||
// hyphaNamePattern is a pattern which all hyphae names must match.
|
||||
var hyphaNamePattern = regexp.MustCompile(`[^?!:#@><*|"'&%{}]+`)
|
||||
|
||||
// IsValidName checks for invalid characters and path traversals.
|
||||
func IsValidName(hyphaName string) bool {
|
||||
if !HyphaPattern.MatchString(hyphaName) {
|
||||
if !hyphaNamePattern.MatchString(hyphaName) {
|
||||
return false
|
||||
}
|
||||
for _, segment := range strings.Split(hyphaName, "/") {
|
||||
@ -22,38 +22,16 @@ func IsValidName(hyphaName string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Hypha is a hypha you know and love.
|
||||
// Hypha is the hypha you know and love.
|
||||
type Hypha interface {
|
||||
sync.Locker
|
||||
|
||||
// CanonicalName returns the canonical name of the hypha.
|
||||
//
|
||||
// util.CanonicalName(h.CanonicalName()) == h.CanonicalName()
|
||||
CanonicalName() string
|
||||
}
|
||||
|
||||
// DeleteHypha deletes the hypha from the storage.
|
||||
func DeleteHypha(h ExistingHypha) {
|
||||
byNamesMutex.Lock()
|
||||
h.Lock()
|
||||
delete(byNames, h.CanonicalName())
|
||||
decrementCount()
|
||||
byNamesMutex.Unlock()
|
||||
h.Unlock()
|
||||
}
|
||||
|
||||
// Insert inserts the hypha into the storage, possibly overwriting the previous hypha with the same name. Count incrementation is done if needed. You cannot insert an empty hypha.
|
||||
func Insert(h ExistingHypha) (madeNewRecord bool) {
|
||||
_, recorded := byNames[h.CanonicalName()]
|
||||
|
||||
byNamesMutex.Lock()
|
||||
byNames[h.CanonicalName()] = h
|
||||
byNamesMutex.Unlock()
|
||||
|
||||
if !recorded {
|
||||
incrementCount()
|
||||
}
|
||||
|
||||
return !recorded
|
||||
}
|
||||
|
||||
// ByName returns a hypha by name. It returns an *EmptyHypha if there is no such hypha. This function is the only source of empty hyphae.
|
||||
func ByName(hyphaName string) (h Hypha) {
|
||||
byNamesMutex.Lock()
|
||||
|
@ -14,9 +14,6 @@ type MediaHypha struct {
|
||||
mediaFilePath string
|
||||
}
|
||||
|
||||
func (m *MediaHypha) DoesExist() {
|
||||
}
|
||||
|
||||
func (m *MediaHypha) CanonicalName() string {
|
||||
return m.canonicalName
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// TextualHypha is a hypha with text, and nothing else. An article, a note, a poem, whatnot.
|
||||
type TextualHypha struct {
|
||||
sync.RWMutex
|
||||
|
||||
@ -11,9 +12,6 @@ type TextualHypha struct {
|
||||
mycoFilePath string
|
||||
}
|
||||
|
||||
func (t *TextualHypha) DoesExist() {
|
||||
}
|
||||
|
||||
func (t *TextualHypha) CanonicalName() string {
|
||||
return t.canonicalName
|
||||
}
|
||||
@ -26,6 +24,7 @@ func (t *TextualHypha) TextFilePath() string {
|
||||
return t.mycoFilePath
|
||||
}
|
||||
|
||||
// ExtendTextualToMedia returns a new media hypha with the same name and text file as the given textual hypha. The new hypha is not stored yet.
|
||||
func ExtendTextualToMedia(t *TextualHypha, mediaFilePath string) *MediaHypha {
|
||||
return &MediaHypha{
|
||||
canonicalName: t.CanonicalName(),
|
||||
|
@ -17,29 +17,29 @@ func canFactory(
|
||||
noRightsMsg string,
|
||||
notExistsMsg string,
|
||||
mustExist bool,
|
||||
) func(*user.User, hyphae.Hypha, *l18n.Localizer) (string, error) {
|
||||
return func(u *user.User, h hyphae.Hypha, lc *l18n.Localizer) (string, error) {
|
||||
) func(*user.User, hyphae.Hypha, *l18n.Localizer) error {
|
||||
return func(u *user.User, h hyphae.Hypha, lc *l18n.Localizer) error {
|
||||
if !u.CanProceed(action) {
|
||||
rejectLogger(h, u, "no rights")
|
||||
return lc.Get("ui.act_no_rights"), errors.New(lc.Get(noRightsMsg))
|
||||
return errors.New(noRightsMsg)
|
||||
}
|
||||
|
||||
if mustExist {
|
||||
switch h.(type) {
|
||||
case *hyphae.EmptyHypha:
|
||||
rejectLogger(h, u, "does not exist")
|
||||
return lc.Get("ui.act_notexist"), errors.New(lc.Get(notExistsMsg))
|
||||
return errors.New(notExistsMsg)
|
||||
}
|
||||
}
|
||||
|
||||
if dispatcher == nil {
|
||||
return "", nil
|
||||
return nil
|
||||
}
|
||||
errmsg, errtitle := dispatcher(h, u, lc)
|
||||
if errtitle == "" {
|
||||
return "", nil
|
||||
return nil
|
||||
}
|
||||
return errtitle, errors.New(errmsg)
|
||||
return errors.New(errmsg)
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,22 +54,12 @@ var (
|
||||
true,
|
||||
)
|
||||
|
||||
CanRename = canFactory(
|
||||
rejectRenameLog,
|
||||
"rename-confirm",
|
||||
nil,
|
||||
"ui.act_norights_rename",
|
||||
"ui.act_notexist_rename",
|
||||
true,
|
||||
)
|
||||
|
||||
CanUnattach = canFactory(
|
||||
rejectUnattachLog,
|
||||
"unattach-confirm",
|
||||
func(h hyphae.Hypha, u *user.User, lc *l18n.Localizer) (errmsg, errtitle string) {
|
||||
switch h := h.(type) {
|
||||
case *hyphae.EmptyHypha:
|
||||
case *hyphae.TextualHypha:
|
||||
case *hyphae.EmptyHypha, *hyphae.TextualHypha:
|
||||
rejectUnattachLog(h, u, "no amnt")
|
||||
return lc.Get("ui.act_noattachment_tip"), lc.Get("ui.act_noattachment")
|
||||
}
|
||||
|
@ -11,17 +11,16 @@ import (
|
||||
)
|
||||
|
||||
// DeleteHypha deletes hypha and makes a history record about that.
|
||||
func DeleteHypha(u *user.User, h hyphae.Hypha, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
|
||||
hop = history.
|
||||
func DeleteHypha(u *user.User, h hyphae.Hypha, lc *l18n.Localizer) error {
|
||||
if err := CanDelete(u, h, lc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hop := history.
|
||||
Operation(history.TypeDeleteHypha).
|
||||
WithMsg(fmt.Sprintf("Delete ‘%s’", h.CanonicalName())).
|
||||
WithUser(u)
|
||||
|
||||
if errtitle, err := CanDelete(u, h, lc); errtitle != "" {
|
||||
hop.WithErrAbort(err)
|
||||
return hop, errtitle
|
||||
}
|
||||
|
||||
switch h := h.(type) {
|
||||
case *hyphae.MediaHypha:
|
||||
hop.WithFilesRemoved(h.MediaFilePath(), h.TextFilePath())
|
||||
@ -36,5 +35,5 @@ func DeleteHypha(u *user.User, h hyphae.Hypha, lc *l18n.Localizer) (hop *history
|
||||
backlinks.UpdateBacklinksAfterDelete(h, originalText)
|
||||
hyphae.DeleteHypha(h.(hyphae.ExistingHypha)) // we panicked before, so it's safe
|
||||
}
|
||||
return hop, ""
|
||||
return nil
|
||||
}
|
||||
|
@ -8,76 +8,68 @@ import (
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/history"
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae"
|
||||
"github.com/bouncepaw/mycorrhiza/l18n"
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
)
|
||||
|
||||
func canRenameThisToThat(oh hyphae.Hypha, nh hyphae.Hypha, u *user.User, lc *l18n.Localizer) (errtitle string, err error) {
|
||||
switch nh.(type) {
|
||||
case *hyphae.EmptyHypha:
|
||||
default:
|
||||
rejectRenameLog(oh, u, fmt.Sprintf("name ‘%s’ taken already", nh.CanonicalName()))
|
||||
return lc.Get("ui.rename_taken"), fmt.Errorf(lc.Get("ui.rename_taken_tip", &l18n.Replacements{"name": "<a href='/hypha/%[1]s'>%[1]s</a>"}), nh.CanonicalName())
|
||||
// Rename renames the old hypha to the new name. Call if and only if the user has the permission to rename.
|
||||
func Rename(oldHypha hyphae.ExistingHypha, newName string, recursive bool, u *user.User) error {
|
||||
if newName == "" {
|
||||
rejectRenameLog(oldHypha, u, "no new name given")
|
||||
return errors.New("ui.rename_noname_tip")
|
||||
}
|
||||
|
||||
if nh.CanonicalName() == "" {
|
||||
rejectRenameLog(oh, u, "no new name given")
|
||||
return lc.Get("ui.rename_noname"), errors.New(lc.Get("ui.rename_noname_tip"))
|
||||
if !hyphae.IsValidName(newName) {
|
||||
rejectRenameLog(oldHypha, u, fmt.Sprintf("new name ‘%s’ invalid", newName))
|
||||
return errors.New("ui.rename_badname_tip") // FIXME: There is a bug related to this.
|
||||
}
|
||||
|
||||
if !hyphae.IsValidName(nh.CanonicalName()) {
|
||||
rejectRenameLog(oh, u, fmt.Sprintf("new name ‘%s’ invalid", nh.CanonicalName()))
|
||||
return lc.Get("ui.rename_badname"), errors.New(lc.Get("ui.rename_badname_tip", &l18n.Replacements{"chars": "<code>^?!:#@><*|\"\\'&%</code>"}))
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// RenameHypha renames hypha from old name `hyphaName` to `newName` and makes a history record about that. If `recursive` is `true`, its subhyphae will be renamed the same way.
|
||||
func RenameHypha(h hyphae.Hypha, newHypha hyphae.Hypha, recursive bool, u *user.User, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
|
||||
newHypha.Lock()
|
||||
defer newHypha.Unlock()
|
||||
hop = history.Operation(history.TypeRenameHypha)
|
||||
|
||||
if errtitle, err := CanRename(u, h, lc); errtitle != "" {
|
||||
hop.WithErrAbort(err)
|
||||
return hop, errtitle
|
||||
}
|
||||
if errtitle, err := canRenameThisToThat(h, newHypha, u, lc); errtitle != "" {
|
||||
hop.WithErrAbort(err)
|
||||
return hop, errtitle
|
||||
switch targetHypha := hyphae.ByName(newName); targetHypha.(type) {
|
||||
case hyphae.ExistingHypha:
|
||||
rejectRenameLog(oldHypha, u, fmt.Sprintf("name ‘%s’ taken already", newName))
|
||||
return errors.New("ui.rename_taken_tip") // FIXME: There is a bug related to this.
|
||||
}
|
||||
|
||||
var (
|
||||
re = regexp.MustCompile(`(?i)` + h.CanonicalName())
|
||||
re = regexp.MustCompile(`(?i)` + oldHypha.CanonicalName())
|
||||
replaceName = func(str string) string {
|
||||
return re.ReplaceAllString(util.CanonicalName(str), newHypha.CanonicalName())
|
||||
return re.ReplaceAllString(util.CanonicalName(str), newName)
|
||||
}
|
||||
hyphaeToRename = findHyphaeToRename(h.(hyphae.ExistingHypha), recursive)
|
||||
hyphaeToRename = findHyphaeToRename(oldHypha, recursive)
|
||||
renameMap, err = renamingPairs(hyphaeToRename, replaceName)
|
||||
renameMsg = "Rename ‘%s’ to ‘%s’"
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
hop.Errs = append(hop.Errs, err)
|
||||
return hop, hop.FirstErrorText()
|
||||
return err
|
||||
}
|
||||
if recursive && len(hyphaeToRename) > 0 {
|
||||
renameMsg += " recursively"
|
||||
|
||||
hop := history.Operation(history.TypeRenameHypha).WithUser(u)
|
||||
|
||||
if len(hyphaeToRename) > 0 {
|
||||
hop.WithMsg(fmt.Sprintf(
|
||||
"Rename ‘%s’ to ‘%s’ recursively",
|
||||
oldHypha.CanonicalName(),
|
||||
newName))
|
||||
} else {
|
||||
hop.WithMsg(fmt.Sprintf(
|
||||
"Rename ‘%s’ to ‘%s’",
|
||||
oldHypha.CanonicalName(),
|
||||
newName))
|
||||
}
|
||||
hop.WithFilesRenamed(renameMap).
|
||||
WithMsg(fmt.Sprintf(renameMsg, h.CanonicalName(), newHypha.CanonicalName())).
|
||||
WithUser(u).
|
||||
Apply()
|
||||
if len(hop.Errs) == 0 {
|
||||
for _, H := range hyphaeToRename {
|
||||
h := H.(hyphae.ExistingHypha) // ontology think
|
||||
oldName := h.CanonicalName()
|
||||
hyphae.RenameHyphaTo(h, replaceName(h.CanonicalName()), replaceName)
|
||||
backlinks.UpdateBacklinksAfterRename(h, oldName)
|
||||
}
|
||||
|
||||
hop.WithFilesRenamed(renameMap).Apply()
|
||||
|
||||
if len(hop.Errs) != 0 {
|
||||
return hop.Errs[0]
|
||||
}
|
||||
return hop, ""
|
||||
|
||||
for _, h := range hyphaeToRename {
|
||||
oldName := h.CanonicalName()
|
||||
hyphae.RenameHyphaTo(h, replaceName(h.CanonicalName()), replaceName)
|
||||
backlinks.UpdateBacklinksAfterRename(h, oldName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func findHyphaeToRename(superhypha hyphae.ExistingHypha, recursive bool) []hyphae.ExistingHypha {
|
||||
|
@ -10,16 +10,15 @@ import (
|
||||
)
|
||||
|
||||
// UnattachHypha unattaches hypha and makes a history record about that.
|
||||
func UnattachHypha(u *user.User, h hyphae.Hypha, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
|
||||
hop = history.Operation(history.TypeUnattachHypha)
|
||||
func UnattachHypha(u *user.User, h hyphae.Hypha, lc *l18n.Localizer) error {
|
||||
|
||||
if errtitle, err := CanUnattach(u, h, lc); errtitle != "" {
|
||||
hop.WithErrAbort(err)
|
||||
return hop, errtitle
|
||||
if err := CanUnattach(u, h, lc); err != nil {
|
||||
return err
|
||||
}
|
||||
H := h.(*hyphae.MediaHypha)
|
||||
|
||||
hop.
|
||||
hop := history.
|
||||
Operation(history.TypeUnattachHypha).
|
||||
WithFilesRemoved(H.MediaFilePath()).
|
||||
WithMsg(fmt.Sprintf("Unattach ‘%s’", h.CanonicalName())).
|
||||
WithUser(u).
|
||||
@ -28,7 +27,7 @@ func UnattachHypha(u *user.User, h hyphae.Hypha, lc *l18n.Localizer) (hop *histo
|
||||
if len(hop.Errs) > 0 {
|
||||
rejectUnattachLog(h, u, "fail")
|
||||
// FIXME: something may be wrong here
|
||||
return hop.WithErrAbort(fmt.Errorf("Could not unattach this hypha due to internal server errors: <code>%v</code>", hop.Errs)), "Error"
|
||||
return fmt.Errorf("Could not unattach this hypha due to internal server errors: <code>%v</code>", hop.Errs)
|
||||
}
|
||||
|
||||
if H.HasTextFile() {
|
||||
@ -36,5 +35,5 @@ func UnattachHypha(u *user.User, h hyphae.Hypha, lc *l18n.Localizer) (hop *histo
|
||||
} else {
|
||||
hyphae.DeleteHypha(H)
|
||||
}
|
||||
return hop, ""
|
||||
return nil
|
||||
}
|
||||
|
@ -47,8 +47,8 @@ func writeTextToDisk(h hyphae.ExistingHypha, data []byte, hop *history.Op) error
|
||||
}
|
||||
|
||||
// UploadText edits the hypha's text part and makes a history record about that.
|
||||
func UploadText(h hyphae.Hypha, data []byte, userMessage string, u *user.User, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
|
||||
hop = history.
|
||||
func UploadText(h hyphae.Hypha, data []byte, userMessage string, u *user.User, lc *l18n.Localizer) error {
|
||||
hop := history.
|
||||
Operation(history.TypeEditText).
|
||||
WithMsg(historyMessageForTextUpload(h, userMessage)).
|
||||
WithUser(u)
|
||||
@ -56,28 +56,27 @@ func UploadText(h hyphae.Hypha, data []byte, userMessage string, u *user.User, l
|
||||
// Privilege check
|
||||
if !u.CanProceed("upload-text") {
|
||||
rejectEditLog(h, u, "no rights")
|
||||
return hop.WithErrAbort(errors.New(lc.Get("ui.act_norights_edit"))), lc.Get("ui.act_no_rights")
|
||||
hop.Abort()
|
||||
return errors.New("ui.act_no_rights")
|
||||
}
|
||||
|
||||
// Hypha name exploit check
|
||||
if !hyphae.IsValidName(h.CanonicalName()) {
|
||||
// We check for the name only. I suppose the filepath would be valid as well.
|
||||
err := errors.New("invalid hypha name")
|
||||
return hop.WithErrAbort(err), err.Error()
|
||||
hop.Abort()
|
||||
return errors.New("invalid hypha name")
|
||||
}
|
||||
|
||||
// Empty data check
|
||||
if len(bytes.TrimSpace(data)) == 0 { // if nothing but whitespace
|
||||
switch h.(type) {
|
||||
case *hyphae.EmptyHypha:
|
||||
// It's ok, just like cancel button.
|
||||
return hop.Abort(), ""
|
||||
case *hyphae.MediaHypha:
|
||||
case *hyphae.EmptyHypha, *hyphae.MediaHypha:
|
||||
// Writing no description, it's ok, just like cancel button.
|
||||
return hop.Abort(), ""
|
||||
hop.Abort()
|
||||
return nil
|
||||
case *hyphae.TextualHypha:
|
||||
// What do you want passing nothing for a textual hypha?
|
||||
return hop.WithErrAbort(errors.New("No data passed")), "Empty"
|
||||
return errors.New("No data passed")
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,49 +88,57 @@ func UploadText(h hyphae.Hypha, data []byte, userMessage string, u *user.User, l
|
||||
|
||||
err := writeTextToDisk(H, data, hop)
|
||||
if err != nil {
|
||||
return hop.WithErrAbort(err), err.Error()
|
||||
hop.Abort()
|
||||
return err
|
||||
}
|
||||
|
||||
hyphae.Insert(H)
|
||||
case *hyphae.MediaHypha:
|
||||
oldText, err := FetchTextFile(h)
|
||||
if err != nil {
|
||||
return hop.WithErrAbort(err), err.Error()
|
||||
hop.Abort()
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: that []byte(...) part should be removed
|
||||
if bytes.Compare(data, []byte(oldText)) == 0 {
|
||||
// No changes! Just like cancel button
|
||||
return hop.Abort(), ""
|
||||
hop.Abort()
|
||||
return nil
|
||||
}
|
||||
|
||||
err = writeTextToDisk(h, data, hop)
|
||||
if err != nil {
|
||||
return hop.WithErrAbort(err), err.Error()
|
||||
hop.Abort()
|
||||
return err
|
||||
}
|
||||
|
||||
backlinks.UpdateBacklinksAfterEdit(h, oldText)
|
||||
case *hyphae.TextualHypha:
|
||||
oldText, err := FetchTextFile(h)
|
||||
if err != nil {
|
||||
return hop.WithErrAbort(err), err.Error()
|
||||
hop.Abort()
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: that []byte(...) part should be removed
|
||||
if bytes.Compare(data, []byte(oldText)) == 0 {
|
||||
// No changes! Just like cancel button
|
||||
return hop.Abort(), ""
|
||||
hop.Abort()
|
||||
return nil
|
||||
}
|
||||
|
||||
err = writeTextToDisk(h, data, hop)
|
||||
if err != nil {
|
||||
return hop.WithErrAbort(err), err.Error()
|
||||
hop.Abort()
|
||||
return err
|
||||
}
|
||||
|
||||
backlinks.UpdateBacklinksAfterEdit(h, oldText)
|
||||
}
|
||||
|
||||
return hop.Apply(), ""
|
||||
hop.Apply()
|
||||
return nil
|
||||
}
|
||||
|
||||
func historyMessageForMediaUpload(h hyphae.Hypha, mime string) string {
|
||||
@ -157,40 +164,35 @@ func writeMediaToDisk(h hyphae.Hypha, mime string, data []byte) (string, error)
|
||||
}
|
||||
|
||||
// UploadBinary edits the hypha's media part and makes a history record about that.
|
||||
func UploadBinary(h hyphae.Hypha, mime string, file multipart.File, u *user.User, lc *l18n.Localizer) (*history.Op, string) {
|
||||
hop := history.
|
||||
Operation(history.TypeEditBinary).
|
||||
WithMsg(historyMessageForMediaUpload(h, mime)).
|
||||
WithUser(u)
|
||||
func UploadBinary(h hyphae.Hypha, mime string, file multipart.File, u *user.User, lc *l18n.Localizer) error {
|
||||
|
||||
// Privilege check
|
||||
if !u.CanProceed("upload-binary") {
|
||||
rejectAttachLog(h, u, "no rights")
|
||||
return hop.WithErrAbort(errors.New(lc.Get("ui.act_norights_attach"))), lc.Get("ui.act_no_rights")
|
||||
return errors.New("ui.act_no_rights")
|
||||
}
|
||||
|
||||
// Hypha name exploit check
|
||||
if !hyphae.IsValidName(h.CanonicalName()) {
|
||||
// We check for the name only. I suppose the filepath would be valid as well.
|
||||
err := errors.New("invalid hypha name")
|
||||
return hop.WithErrAbort(err), err.Error()
|
||||
return errors.New("invalid hypha name")
|
||||
}
|
||||
|
||||
data, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return hop.WithErrAbort(err), err.Error()
|
||||
return err
|
||||
}
|
||||
|
||||
// Empty data check
|
||||
if len(data) == 0 {
|
||||
return hop.WithErrAbort(errors.New("No data passed")), "Empty"
|
||||
return errors.New("No data passed")
|
||||
}
|
||||
|
||||
// At this point, we have a savable media document. Gotta save it.
|
||||
|
||||
uploadedFilePath, err := writeMediaToDisk(h, mime, data)
|
||||
if err != nil {
|
||||
return hop.WithErrAbort(err), err.Error()
|
||||
return err
|
||||
}
|
||||
|
||||
switch h := h.(type) {
|
||||
@ -203,12 +205,18 @@ func UploadBinary(h hyphae.Hypha, mime string, file multipart.File, u *user.User
|
||||
prevFilePath := h.MediaFilePath()
|
||||
if prevFilePath != uploadedFilePath {
|
||||
if err := history.Rename(prevFilePath, uploadedFilePath); err != nil {
|
||||
return hop.WithErrAbort(err), err.Error()
|
||||
return err
|
||||
}
|
||||
log.Printf("Move ‘%s’ to ‘%s’\n", prevFilePath, uploadedFilePath)
|
||||
h.SetMediaFilePath(uploadedFilePath)
|
||||
}
|
||||
}
|
||||
|
||||
return hop.WithFiles(uploadedFilePath).Apply(), ""
|
||||
history.
|
||||
Operation(history.TypeEditBinary).
|
||||
WithMsg(historyMessageForMediaUpload(h, mime)).
|
||||
WithUser(u).
|
||||
WithFiles(uploadedFilePath).
|
||||
Apply()
|
||||
return nil
|
||||
}
|
||||
|
@ -34,11 +34,14 @@ var minimalRights = map[string]int{
|
||||
"edit": 1,
|
||||
"upload-binary": 1,
|
||||
"upload-text": 1,
|
||||
"rename": 2,
|
||||
"rename-ask": 2,
|
||||
"rename-confirm": 2,
|
||||
"remove-media": 2,
|
||||
"unattach-ask": 2,
|
||||
"unattach-confirm": 2,
|
||||
"update-header-links": 3,
|
||||
"delete": 3,
|
||||
"delete-ask": 3,
|
||||
"delete-confirm": 3,
|
||||
"reindex": 4,
|
||||
|
@ -2,7 +2,7 @@
|
||||
{% import "net/http" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/l18n" %}
|
||||
|
||||
{% func DeleteAskHTML(rq *http.Request, hyphaName string, isOld bool) %}
|
||||
{% func DeleteAskHTML(rq *http.Request, hyphaName string) %}
|
||||
{% code
|
||||
lc := l18n.FromRequest(rq)
|
||||
%}
|
||||
@ -16,7 +16,7 @@
|
||||
{%= modalEnd(hyphaName, true, lc) %}
|
||||
{% endfunc %}
|
||||
|
||||
{% func UnattachAskHTML(rq *http.Request, hyphaName string, isOld bool) %}
|
||||
{% func UnattachAskHTML(rq *http.Request, hyphaName string) %}
|
||||
{% code
|
||||
lc := l18n.FromRequest(rq)
|
||||
%}
|
||||
@ -29,7 +29,7 @@
|
||||
{%= modalEnd(hyphaName, true, lc) %}
|
||||
{% endfunc %}
|
||||
|
||||
{% func RenameAskHTML(rq *http.Request, hyphaName string, isOld bool) %}
|
||||
{% func RenameAskHTML(rq *http.Request, hyphaName string) %}
|
||||
{% code
|
||||
lc := l18n.FromRequest(rq)
|
||||
%}
|
||||
|
@ -27,7 +27,7 @@ var (
|
||||
)
|
||||
|
||||
//line views/modal.qtpl:5
|
||||
func StreamDeleteAskHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName string, isOld bool) {
|
||||
func StreamDeleteAskHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName string) {
|
||||
//line views/modal.qtpl:5
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
@ -65,22 +65,22 @@ func StreamDeleteAskHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName
|
||||
}
|
||||
|
||||
//line views/modal.qtpl:17
|
||||
func WriteDeleteAskHTML(qq422016 qtio422016.Writer, rq *http.Request, hyphaName string, isOld bool) {
|
||||
func WriteDeleteAskHTML(qq422016 qtio422016.Writer, rq *http.Request, hyphaName string) {
|
||||
//line views/modal.qtpl:17
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/modal.qtpl:17
|
||||
StreamDeleteAskHTML(qw422016, rq, hyphaName, isOld)
|
||||
StreamDeleteAskHTML(qw422016, rq, hyphaName)
|
||||
//line views/modal.qtpl:17
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/modal.qtpl:17
|
||||
}
|
||||
|
||||
//line views/modal.qtpl:17
|
||||
func DeleteAskHTML(rq *http.Request, hyphaName string, isOld bool) string {
|
||||
func DeleteAskHTML(rq *http.Request, hyphaName string) string {
|
||||
//line views/modal.qtpl:17
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/modal.qtpl:17
|
||||
WriteDeleteAskHTML(qb422016, rq, hyphaName, isOld)
|
||||
WriteDeleteAskHTML(qb422016, rq, hyphaName)
|
||||
//line views/modal.qtpl:17
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/modal.qtpl:17
|
||||
@ -91,7 +91,7 @@ func DeleteAskHTML(rq *http.Request, hyphaName string, isOld bool) string {
|
||||
}
|
||||
|
||||
//line views/modal.qtpl:19
|
||||
func StreamUnattachAskHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName string, isOld bool) {
|
||||
func StreamUnattachAskHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName string) {
|
||||
//line views/modal.qtpl:19
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
@ -124,22 +124,22 @@ func StreamUnattachAskHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaNam
|
||||
}
|
||||
|
||||
//line views/modal.qtpl:30
|
||||
func WriteUnattachAskHTML(qq422016 qtio422016.Writer, rq *http.Request, hyphaName string, isOld bool) {
|
||||
func WriteUnattachAskHTML(qq422016 qtio422016.Writer, rq *http.Request, hyphaName string) {
|
||||
//line views/modal.qtpl:30
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/modal.qtpl:30
|
||||
StreamUnattachAskHTML(qw422016, rq, hyphaName, isOld)
|
||||
StreamUnattachAskHTML(qw422016, rq, hyphaName)
|
||||
//line views/modal.qtpl:30
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/modal.qtpl:30
|
||||
}
|
||||
|
||||
//line views/modal.qtpl:30
|
||||
func UnattachAskHTML(rq *http.Request, hyphaName string, isOld bool) string {
|
||||
func UnattachAskHTML(rq *http.Request, hyphaName string) string {
|
||||
//line views/modal.qtpl:30
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/modal.qtpl:30
|
||||
WriteUnattachAskHTML(qb422016, rq, hyphaName, isOld)
|
||||
WriteUnattachAskHTML(qb422016, rq, hyphaName)
|
||||
//line views/modal.qtpl:30
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/modal.qtpl:30
|
||||
@ -150,7 +150,7 @@ func UnattachAskHTML(rq *http.Request, hyphaName string, isOld bool) string {
|
||||
}
|
||||
|
||||
//line views/modal.qtpl:32
|
||||
func StreamRenameAskHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName string, isOld bool) {
|
||||
func StreamRenameAskHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName string) {
|
||||
//line views/modal.qtpl:32
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
@ -201,22 +201,22 @@ func StreamRenameAskHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName
|
||||
}
|
||||
|
||||
//line views/modal.qtpl:49
|
||||
func WriteRenameAskHTML(qq422016 qtio422016.Writer, rq *http.Request, hyphaName string, isOld bool) {
|
||||
func WriteRenameAskHTML(qq422016 qtio422016.Writer, rq *http.Request, hyphaName string) {
|
||||
//line views/modal.qtpl:49
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/modal.qtpl:49
|
||||
StreamRenameAskHTML(qw422016, rq, hyphaName, isOld)
|
||||
StreamRenameAskHTML(qw422016, rq, hyphaName)
|
||||
//line views/modal.qtpl:49
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/modal.qtpl:49
|
||||
}
|
||||
|
||||
//line views/modal.qtpl:49
|
||||
func RenameAskHTML(rq *http.Request, hyphaName string, isOld bool) string {
|
||||
func RenameAskHTML(rq *http.Request, hyphaName string) string {
|
||||
//line views/modal.qtpl:49
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/modal.qtpl:49
|
||||
WriteRenameAskHTML(qb422016, rq, hyphaName, isOld)
|
||||
WriteRenameAskHTML(qb422016, rq, hyphaName)
|
||||
//line views/modal.qtpl:49
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/modal.qtpl:49
|
||||
|
@ -23,7 +23,7 @@
|
||||
<nav class="hypha-info">
|
||||
<ul class="hypha-info__list">
|
||||
{%= hyphaInfoEntry(h, u, "history", lc.Get("ui.history_link")) %}
|
||||
{%= hyphaInfoEntry(h, u, "rename-ask", lc.Get("ui.rename_link")) %}
|
||||
{%= hyphaInfoEntry(h, u, "rename", lc.Get("ui.rename_link")) %}
|
||||
{%= hyphaInfoEntry(h, u, "delete-ask", lc.Get("ui.delete_link")) %}
|
||||
{%= hyphaInfoEntry(h, u, "text", lc.Get("ui.text_link")) %}
|
||||
{%= hyphaInfoEntry(h, u, "attachment", lc.Get("ui.attachment_link")) %}
|
||||
|
@ -122,7 +122,7 @@ func streamhyphaInfo(qw422016 *qt422016.Writer, rq *http.Request, h hyphae.Hypha
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/nav.qtpl:26
|
||||
streamhyphaInfoEntry(qw422016, h, u, "rename-ask", lc.Get("ui.rename_link"))
|
||||
streamhyphaInfoEntry(qw422016, h, u, "rename", lc.Get("ui.rename_link"))
|
||||
//line views/nav.qtpl:26
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
|
104
web/mutators.go
104
web/mutators.go
@ -10,7 +10,6 @@ import (
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/history"
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae"
|
||||
"github.com/bouncepaw/mycorrhiza/l18n"
|
||||
"github.com/bouncepaw/mycorrhiza/shroom"
|
||||
@ -22,14 +21,13 @@ import (
|
||||
func initMutators(r *mux.Router) {
|
||||
// Those that do not actually mutate anything:
|
||||
r.PathPrefix("/edit/").HandlerFunc(handlerEdit)
|
||||
r.PathPrefix("/rename/").HandlerFunc(handlerRename).Methods("GET", "POST")
|
||||
r.PathPrefix("/delete-ask/").HandlerFunc(handlerDeleteAsk)
|
||||
r.PathPrefix("/rename-ask/").HandlerFunc(handlerRenameAsk)
|
||||
r.PathPrefix("/unattach-ask/").HandlerFunc(handlerUnattachAsk)
|
||||
// And those that do mutate something:
|
||||
r.PathPrefix("/upload-binary/").HandlerFunc(handlerUploadBinary)
|
||||
r.PathPrefix("/upload-text/").HandlerFunc(handlerUploadText)
|
||||
r.PathPrefix("/delete-confirm/").HandlerFunc(handlerDeleteConfirm)
|
||||
r.PathPrefix("/rename-confirm/").HandlerFunc(handlerRenameConfirm)
|
||||
r.PathPrefix("/unattach-confirm/").HandlerFunc(handlerUnattachConfirm)
|
||||
}
|
||||
|
||||
@ -37,9 +35,9 @@ func initMutators(r *mux.Router) {
|
||||
|
||||
func factoryHandlerAsker(
|
||||
actionPath string,
|
||||
asker func(*user.User, hyphae.Hypha, *l18n.Localizer) (string, error),
|
||||
asker func(*user.User, hyphae.Hypha, *l18n.Localizer) error,
|
||||
succTitleKey string,
|
||||
succPageTemplate func(*http.Request, string, bool) string,
|
||||
succPageTemplate func(*http.Request, string) string,
|
||||
) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
@ -49,13 +47,12 @@ func factoryHandlerAsker(
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
)
|
||||
if errtitle, err := asker(u, h, lc); err != nil {
|
||||
if err := asker(u, h, lc); err != nil {
|
||||
httpErr(
|
||||
w,
|
||||
lc,
|
||||
http.StatusInternalServerError,
|
||||
hyphaName,
|
||||
errtitle,
|
||||
err.Error())
|
||||
return
|
||||
}
|
||||
@ -63,14 +60,7 @@ func factoryHandlerAsker(
|
||||
w,
|
||||
views.BaseHTML(
|
||||
fmt.Sprintf(lc.Get(succTitleKey), util.BeautifulName(hyphaName)),
|
||||
succPageTemplate(rq, hyphaName, func(h hyphae.Hypha) bool {
|
||||
switch h.(type) {
|
||||
case *hyphae.EmptyHypha:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}(h)),
|
||||
succPageTemplate(rq, hyphaName),
|
||||
lc,
|
||||
u))
|
||||
}
|
||||
@ -90,16 +80,9 @@ var handlerDeleteAsk = factoryHandlerAsker(
|
||||
views.DeleteAskHTML,
|
||||
)
|
||||
|
||||
var handlerRenameAsk = factoryHandlerAsker(
|
||||
"rename-ask",
|
||||
shroom.CanRename,
|
||||
"ui.ask_rename",
|
||||
views.RenameAskHTML,
|
||||
)
|
||||
|
||||
func factoryHandlerConfirmer(
|
||||
actionPath string,
|
||||
confirmer func(hyphae.Hypha, *user.User, *http.Request) (*history.Op, string),
|
||||
confirmer func(hyphae.Hypha, *user.User, *http.Request) error,
|
||||
) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
@ -109,10 +92,9 @@ func factoryHandlerConfirmer(
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
)
|
||||
if hop, errtitle := confirmer(h, u, rq); hop.HasErrors() {
|
||||
if err := confirmer(h, u, rq); err != nil {
|
||||
httpErr(w, lc, http.StatusInternalServerError, hyphaName,
|
||||
errtitle,
|
||||
hop.FirstErrorText())
|
||||
err.Error())
|
||||
return
|
||||
}
|
||||
http.Redirect(w, rq, "/hypha/"+hyphaName, http.StatusSeeOther)
|
||||
@ -121,35 +103,52 @@ func factoryHandlerConfirmer(
|
||||
|
||||
var handlerUnattachConfirm = factoryHandlerConfirmer(
|
||||
"unattach-confirm",
|
||||
func(h hyphae.Hypha, u *user.User, rq *http.Request) (*history.Op, string) {
|
||||
func(h hyphae.Hypha, u *user.User, rq *http.Request) error {
|
||||
return shroom.UnattachHypha(u, h, l18n.FromRequest(rq))
|
||||
},
|
||||
)
|
||||
|
||||
var handlerDeleteConfirm = factoryHandlerConfirmer(
|
||||
"delete-confirm",
|
||||
func(h hyphae.Hypha, u *user.User, rq *http.Request) (*history.Op, string) {
|
||||
func(h hyphae.Hypha, u *user.User, rq *http.Request) error {
|
||||
return shroom.DeleteHypha(u, h, l18n.FromRequest(rq))
|
||||
},
|
||||
)
|
||||
|
||||
// handlerRenameConfirm should redirect to the new hypha, thus it's out of factory
|
||||
func handlerRenameConfirm(w http.ResponseWriter, rq *http.Request) {
|
||||
func handlerRename(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
var (
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
hyphaName = util.HyphaNameFromRq(rq, "rename-confirm")
|
||||
oldHypha = hyphae.ByName(hyphaName)
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
h = hyphae.ByName(util.HyphaNameFromRq(rq, "rename-confirm"))
|
||||
)
|
||||
|
||||
switch h.(type) {
|
||||
case *hyphae.EmptyHypha:
|
||||
log.Printf("%s tries to rename empty hypha ‘%s’", u.Name, h.CanonicalName())
|
||||
httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "Cannot rename an empty hypha") // TODO: localize
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
oldHypha = h.(hyphae.ExistingHypha)
|
||||
newName = util.CanonicalName(rq.PostFormValue("new-name"))
|
||||
newHypha = hyphae.ByName(newName)
|
||||
recursive = rq.PostFormValue("recursive") == "true"
|
||||
)
|
||||
hop, errtitle := shroom.RenameHypha(oldHypha, newHypha, recursive, u, lc)
|
||||
if hop.HasErrors() {
|
||||
httpErr(w, lc, http.StatusInternalServerError, hyphaName,
|
||||
errtitle,
|
||||
hop.FirstErrorText())
|
||||
|
||||
if rq.Method == "GET" {
|
||||
util.HTTP200Page(
|
||||
w,
|
||||
views.BaseHTML(
|
||||
fmt.Sprintf(lc.Get("ui.ask_rename"), util.BeautifulName(oldHypha.CanonicalName())),
|
||||
views.RenameAskHTML(rq, oldHypha.CanonicalName()),
|
||||
lc,
|
||||
u))
|
||||
}
|
||||
|
||||
if err := shroom.Rename(oldHypha, newName, recursive, u); err != nil {
|
||||
log.Printf("%s tries to rename ‘%s’: %s", u.Name, oldHypha.CanonicalName(), err.Error())
|
||||
httpErr(w, lc, http.StatusForbidden, oldHypha.CanonicalName(), lc.Get(err.Error())) // TODO: localize
|
||||
return
|
||||
}
|
||||
http.Redirect(w, rq, "/hypha/"+newName, http.StatusSeeOther)
|
||||
@ -167,9 +166,8 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) {
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
)
|
||||
if errtitle, err := shroom.CanEdit(u, h, lc); err != nil {
|
||||
if err := shroom.CanEdit(u, h, lc); err != nil {
|
||||
httpErr(w, lc, http.StatusInternalServerError, hyphaName,
|
||||
errtitle,
|
||||
err.Error())
|
||||
return
|
||||
}
|
||||
@ -181,7 +179,6 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) {
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
httpErr(w, lc, http.StatusInternalServerError, hyphaName,
|
||||
lc.Get("ui.error"),
|
||||
lc.Get("ui.error_text_fetch"))
|
||||
return
|
||||
}
|
||||
@ -206,16 +203,11 @@ func handlerUploadText(w http.ResponseWriter, rq *http.Request) {
|
||||
message = rq.PostFormValue("message")
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
hop *history.Op
|
||||
errtitle string
|
||||
)
|
||||
|
||||
if action != "Preview" {
|
||||
hop, errtitle = shroom.UploadText(h, []byte(textData), message, u, lc)
|
||||
if hop.HasErrors() {
|
||||
httpErr(w, lc, http.StatusForbidden, hyphaName,
|
||||
errtitle,
|
||||
hop.FirstErrorText())
|
||||
if err := shroom.UploadText(h, []byte(textData), message, u, lc); err != nil {
|
||||
httpErr(w, lc, http.StatusForbidden, hyphaName, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -254,12 +246,10 @@ func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) {
|
||||
)
|
||||
if err != nil {
|
||||
httpErr(w, lc, http.StatusInternalServerError, hyphaName,
|
||||
lc.Get("ui.error"),
|
||||
err.Error())
|
||||
}
|
||||
if errtitle, err := shroom.CanAttach(u, h, lc); err != nil {
|
||||
if err := shroom.CanAttach(u, h, lc); err != nil {
|
||||
httpErr(w, lc, http.StatusInternalServerError, hyphaName,
|
||||
errtitle,
|
||||
err.Error())
|
||||
}
|
||||
|
||||
@ -272,13 +262,13 @@ func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) {
|
||||
if file != nil {
|
||||
defer file.Close()
|
||||
}
|
||||
|
||||
var (
|
||||
mime = handler.Header.Get("Content-Type")
|
||||
hop, errtitle = shroom.UploadBinary(h, mime, file, u, lc)
|
||||
mime = handler.Header.Get("Content-Type")
|
||||
)
|
||||
|
||||
if hop.HasErrors() {
|
||||
httpErr(w, lc, http.StatusInternalServerError, hyphaName, errtitle, hop.FirstErrorText())
|
||||
if err := shroom.UploadBinary(h, mime, file, u, lc); err != nil {
|
||||
httpErr(w, lc, http.StatusInternalServerError, hyphaName, err.Error())
|
||||
return
|
||||
}
|
||||
http.Redirect(w, rq, "/hypha/"+hyphaName, http.StatusSeeOther)
|
||||
|
@ -104,7 +104,7 @@ func handlerReindex(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
if ok := user.CanProceed(rq, "reindex"); !ok {
|
||||
var lc = l18n.FromRequest(rq)
|
||||
httpErr(w, lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.no_rights"), lc.Get("ui.reindex_no_rights"))
|
||||
httpErr(w, lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.reindex_no_rights"))
|
||||
log.Println("Rejected", rq.URL)
|
||||
return
|
||||
}
|
||||
@ -122,7 +122,7 @@ func handlerUpdateHeaderLinks(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
if ok := user.CanProceed(rq, "update-header-links"); !ok {
|
||||
var lc = l18n.FromRequest(rq)
|
||||
httpErr(w, lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.no_rights"), lc.Get("ui.header_no_rights"))
|
||||
httpErr(w, lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.header_no_rights"))
|
||||
log.Println("Rejected", rq.URL)
|
||||
return
|
||||
}
|
||||
@ -139,7 +139,7 @@ func handlerRandom(w http.ResponseWriter, rq *http.Request) {
|
||||
)
|
||||
if amountOfHyphae == 0 {
|
||||
var lc = l18n.FromRequest(rq)
|
||||
httpErr(w, lc, http.StatusNotFound, cfg.HomeHypha, lc.Get("ui.random_no_hyphae"), lc.Get("ui.random_no_hyphae_tip"))
|
||||
httpErr(w, lc, http.StatusNotFound, cfg.HomeHypha, lc.Get("ui.random_no_hyphae_tip"))
|
||||
return
|
||||
}
|
||||
i := rand.Intn(amountOfHyphae)
|
||||
|
@ -6,7 +6,6 @@ package web
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"mime"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@ -24,14 +23,13 @@ import (
|
||||
var stylesheets = []string{"default.css", "custom.css"}
|
||||
|
||||
// httpErr is used by many handlers to signal errors in a compact way.
|
||||
func httpErr(w http.ResponseWriter, lc *l18n.Localizer, status int, name, title, errMsg string) {
|
||||
log.Println(errMsg, "for", name)
|
||||
func httpErr(w http.ResponseWriter, lc *l18n.Localizer, status int, name, errMsg string) {
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
|
||||
w.WriteHeader(status)
|
||||
fmt.Fprint(
|
||||
w,
|
||||
views.BaseHTML(
|
||||
title,
|
||||
"Error",
|
||||
fmt.Sprintf(
|
||||
`<main class="main-width"><p>%s. <a href="/hypha/%s">%s<a></p></main>`,
|
||||
errMsg,
|
||||
|
Loading…
Reference in New Issue
Block a user