mirror of
https://github.com/osmarks/mycorrhiza.git
synced 2025-02-01 11:59:08 +00:00
Delete uploadHelp, refactor UploadText
This commit is contained in:
parent
ae13fdab43
commit
002e9f7a93
@ -12,10 +12,6 @@ func (e *EmptyHypha) CanonicalName() string {
|
|||||||
return e.canonicalName
|
return e.canonicalName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EmptyHypha) DoesExist() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *EmptyHypha) HasTextPart() bool {
|
func (e *EmptyHypha) HasTextPart() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -31,10 +27,9 @@ func NewEmptyHypha(hyphaName string) *EmptyHypha {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func FillEmptyHyphaUpToMediaHypha(e *EmptyHypha) *MediaHypha { // sic!
|
func FillEmptyHyphaUpToTextualHypha(e *EmptyHypha, textPath string) *MediaHypha { // sic!
|
||||||
return &MediaHypha{
|
return &MediaHypha{
|
||||||
name: e.CanonicalName(),
|
name: e.CanonicalName(),
|
||||||
TextPath: "",
|
TextPath: textPath,
|
||||||
binaryPath: "",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ func InsertIfNew(h Hypher) (madeNewRecord bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ByName returns a hypha by name. It may have been recorded to the storage.
|
// 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 Hypher) {
|
func ByName(hyphaName string) (h Hypher) {
|
||||||
byNamesMutex.Lock()
|
byNamesMutex.Lock()
|
||||||
defer byNamesMutex.Unlock()
|
defer byNamesMutex.Unlock()
|
||||||
|
@ -8,6 +8,8 @@ import (
|
|||||||
"github.com/bouncepaw/mycorrhiza/user"
|
"github.com/bouncepaw/mycorrhiza/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO: get rid of this abomination
|
||||||
|
|
||||||
func canFactory(
|
func canFactory(
|
||||||
rejectLogger func(hyphae.Hypher, *user.User, string),
|
rejectLogger func(hyphae.Hypher, *user.User, string),
|
||||||
action string,
|
action string,
|
||||||
|
127
shroom/upload.go
127
shroom/upload.go
@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/bouncepaw/mycorrhiza/hyphae/backlinks"
|
"github.com/bouncepaw/mycorrhiza/hyphae/backlinks"
|
||||||
|
"github.com/bouncepaw/mycorrhiza/mimetype"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
@ -16,44 +17,115 @@ import (
|
|||||||
"github.com/bouncepaw/mycorrhiza/history"
|
"github.com/bouncepaw/mycorrhiza/history"
|
||||||
"github.com/bouncepaw/mycorrhiza/hyphae"
|
"github.com/bouncepaw/mycorrhiza/hyphae"
|
||||||
"github.com/bouncepaw/mycorrhiza/l18n"
|
"github.com/bouncepaw/mycorrhiza/l18n"
|
||||||
"github.com/bouncepaw/mycorrhiza/mimetype"
|
|
||||||
"github.com/bouncepaw/mycorrhiza/user"
|
"github.com/bouncepaw/mycorrhiza/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UploadText edits a hypha' text part and makes a history record about that.
|
func historyMessageForTextUpload(h hyphae.Hypher, userMessage string) string {
|
||||||
func UploadText(h hyphae.Hypher, data []byte, message string, u *user.User, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
|
var verb string
|
||||||
hop = history.Operation(history.TypeEditText)
|
|
||||||
|
|
||||||
var action string
|
|
||||||
switch h.(type) {
|
switch h.(type) {
|
||||||
case *hyphae.EmptyHypha:
|
case *hyphae.EmptyHypha:
|
||||||
action = "Create"
|
verb = "Create"
|
||||||
default:
|
default:
|
||||||
action = "Edit"
|
verb = "Edit"
|
||||||
}
|
}
|
||||||
|
|
||||||
if message == "" {
|
if userMessage == "" {
|
||||||
hop.WithMsg(fmt.Sprintf("%s ‘%s’", action, h.CanonicalName()))
|
return fmt.Sprintf("%s ‘%s’", verb, h.CanonicalName())
|
||||||
} else {
|
}
|
||||||
hop.WithMsg(fmt.Sprintf("%s ‘%s’: %s", action, h.CanonicalName(), message))
|
return fmt.Sprintf("%s ‘%s’: %s", verb, h.CanonicalName(), userMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeTextToDiskForEmptyHypha(eh *hyphae.EmptyHypha, data []byte) error {
|
||||||
|
h := hyphae.FillEmptyHyphaUpToTextualHypha(eh, filepath.Join(files.HyphaeDir(), eh.CanonicalName()+".myco"))
|
||||||
|
|
||||||
|
return writeTextToDiskForNonEmptyHypha(h, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeTextToDiskForNonEmptyHypha(h *hyphae.MediaHypha, data []byte) error {
|
||||||
|
if err := os.MkdirAll(filepath.Dir(h.TextPartPath()), 0777); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if errtitle, err := CanEdit(u, h, lc); err != nil {
|
if err := os.WriteFile(h.TextPartPath(), data, 0666); err != nil {
|
||||||
return hop.WithErrAbort(err), errtitle
|
return err
|
||||||
}
|
}
|
||||||
if len(bytes.TrimSpace(data)) == 0 {
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UploadText edits the hypha's text part and makes a history record about that.
|
||||||
|
func UploadText(h hyphae.Hypher, data []byte, userMessage string, u *user.User, lc *l18n.Localizer) (hop *history.Op, errtitle string) {
|
||||||
|
hop = history.
|
||||||
|
Operation(history.TypeEditText).
|
||||||
|
WithMsg(historyMessageForTextUpload(h, userMessage))
|
||||||
|
|
||||||
|
// 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")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty data check
|
||||||
|
if len(bytes.TrimSpace(data)) == 0 { // if nothing but whitespace
|
||||||
switch h := h.(type) {
|
switch h := h.(type) {
|
||||||
|
case *hyphae.EmptyHypha:
|
||||||
|
// It's ok, just like cancel button.
|
||||||
|
return hop.Abort(), ""
|
||||||
case *hyphae.MediaHypha:
|
case *hyphae.MediaHypha:
|
||||||
if h.Kind() != hyphae.HyphaMedia {
|
switch h.Kind() {
|
||||||
|
case hyphae.HyphaMedia:
|
||||||
|
// Writing no description, it's ok, just like cancel button.
|
||||||
|
return hop.Abort(), ""
|
||||||
|
case hyphae.HyphaText:
|
||||||
|
// What do you want passing nothing for a textual hypha?
|
||||||
return hop.WithErrAbort(errors.New("No data passed")), "Empty"
|
return hop.WithErrAbort(errors.New("No data passed")), "Empty"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return uploadHelp(h, hop, ".myco", data, u)
|
// At this point, we have a savable user-generated Mycomarkup document. Gotta save it.
|
||||||
|
|
||||||
|
switch h := h.(type) {
|
||||||
|
case *hyphae.EmptyHypha:
|
||||||
|
err := writeTextToDiskForEmptyHypha(h, data)
|
||||||
|
if err != nil {
|
||||||
|
return hop.WithErrAbort(err), err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
hyphae.InsertIfNew(h)
|
||||||
|
case *hyphae.MediaHypha:
|
||||||
|
oldText, err := FetchTextPart(h)
|
||||||
|
if err != nil {
|
||||||
|
return hop.WithErrAbort(err), err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: that []byte(...) part should be removed
|
||||||
|
if bytes.Compare(data, []byte(oldText)) == 0 {
|
||||||
|
// No changes! Just like cancel button
|
||||||
|
return hop.Abort(), ""
|
||||||
|
}
|
||||||
|
|
||||||
|
err = writeTextToDiskForNonEmptyHypha(h, data)
|
||||||
|
if err != nil {
|
||||||
|
return hop.WithErrAbort(err), err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
backlinks.UpdateBacklinksAfterEdit(h, oldText)
|
||||||
|
}
|
||||||
|
|
||||||
|
return hop.
|
||||||
|
WithFiles(h.TextPartPath()).
|
||||||
|
WithUser(u).
|
||||||
|
Apply(), ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// UploadBinary edits a hypha' attachment and makes a history record about that.
|
// UploadBinary edits the hypha's media part and makes a history record about that.
|
||||||
func UploadBinary(h hyphae.Hypher, mime string, file multipart.File, u *user.User, lc *l18n.Localizer) (*history.Op, string) {
|
func UploadBinary(h hyphae.Hypher, mime string, file multipart.File, u *user.User, lc *l18n.Localizer) (*history.Op, string) {
|
||||||
var (
|
var (
|
||||||
hop = history.Operation(history.TypeEditBinary).WithMsg(fmt.Sprintf("Upload attachment for ‘%s’ with type ‘%s’", h.CanonicalName(), mime))
|
hop = history.Operation(history.TypeEditBinary).WithMsg(fmt.Sprintf("Upload attachment for ‘%s’ with type ‘%s’", h.CanonicalName(), mime))
|
||||||
@ -70,15 +142,11 @@ func UploadBinary(h hyphae.Hypher, mime string, file multipart.File, u *user.Use
|
|||||||
return hop.WithErrAbort(errors.New("No data passed")), "Empty"
|
return hop.WithErrAbort(errors.New("No data passed")), "Empty"
|
||||||
}
|
}
|
||||||
|
|
||||||
return uploadHelp(h, hop, mimetype.ToExtension(mime), data, u)
|
ext := mimetype.ToExtension(mime)
|
||||||
}
|
|
||||||
|
|
||||||
// uploadHelp is a helper function for UploadText and UploadBinary
|
|
||||||
func uploadHelp(h hyphae.Hypher, hop *history.Op, ext string, data []byte, u *user.User) (*history.Op, string) {
|
|
||||||
var (
|
var (
|
||||||
fullPath = filepath.Join(files.HyphaeDir(), h.CanonicalName()+ext)
|
fullPath = filepath.Join(files.HyphaeDir(), h.CanonicalName()+ext)
|
||||||
sourceFullPath = h.TextPartPath()
|
sourceFullPath = h.TextPartPath()
|
||||||
originalText = "" // for backlink update
|
|
||||||
)
|
)
|
||||||
if !isValidPath(fullPath) || !hyphae.IsValidName(h.CanonicalName()) {
|
if !isValidPath(fullPath) || !hyphae.IsValidName(h.CanonicalName()) {
|
||||||
err := errors.New("bad path")
|
err := errors.New("bad path")
|
||||||
@ -92,10 +160,6 @@ func uploadHelp(h hyphae.Hypher, hop *history.Op, ext string, data []byte, u *us
|
|||||||
return hop.WithErrAbort(err), err.Error()
|
return hop.WithErrAbort(err), err.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
if hop.Type == history.TypeEditText {
|
|
||||||
originalText, _ = FetchTextPart(h)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := os.WriteFile(fullPath, data, 0666); err != nil {
|
if err := os.WriteFile(fullPath, data, 0666); err != nil {
|
||||||
return hop.WithErrAbort(err), err.Error()
|
return hop.WithErrAbort(err), err.Error()
|
||||||
}
|
}
|
||||||
@ -122,14 +186,7 @@ func uploadHelp(h hyphae.Hypher, hop *history.Op, ext string, data []byte, u *us
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sic!
|
// sic!
|
||||||
if h := h.(*hyphae.MediaHypha); hop.Type == history.TypeEditBinary {
|
h.(*hyphae.MediaHypha).SetBinaryPath(fullPath)
|
||||||
h.SetBinaryPath(fullPath)
|
|
||||||
} else {
|
|
||||||
h.TextPath = fullPath
|
|
||||||
}
|
|
||||||
if hop.Type == history.TypeEditText {
|
|
||||||
backlinks.UpdateBacklinksAfterEdit(h, originalText)
|
|
||||||
}
|
|
||||||
return hop.WithFiles(fullPath).WithUser(u).Apply(), ""
|
return hop.WithFiles(fullPath).WithUser(u).Apply(), ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package shroom
|
package shroom
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||||
@ -9,6 +10,10 @@ import (
|
|||||||
|
|
||||||
// FetchTextPart tries to read text file of the given hypha. If there is no file, empty string is returned.
|
// FetchTextPart tries to read text file of the given hypha. If there is no file, empty string is returned.
|
||||||
func FetchTextPart(h hyphae.Hypher) (string, error) {
|
func FetchTextPart(h hyphae.Hypher) (string, error) {
|
||||||
|
switch h.(type) {
|
||||||
|
case *hyphae.EmptyHypha:
|
||||||
|
return "", errors.New("empty hyphae have no text")
|
||||||
|
}
|
||||||
if !h.HasTextPart() {
|
if !h.HasTextPart() {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user