diff --git a/README.md b/README.md
index 2ef0936..1852580 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,8 @@
+[![Go Report Card](https://goreportcard.com/badge/github.com/bouncepaw/mycorrhiza)](https://goreportcard.com/report/github.com/bouncepaw/mycorrhiza)
+
**Mycorrhiza Wiki** is a lightweight file-system wiki engine that uses Git for keeping history.
[š Main wiki](https://mycorrhiza.wiki)
diff --git a/flag.go b/flag.go
index b1b44b0..fa0d4b2 100644
--- a/flag.go
+++ b/flag.go
@@ -28,6 +28,7 @@ func printHelp() {
flag.PrintDefaults()
}
+// CreateUserCommand is parameters for admin creation flag. Only a single parameter, though.
type CreateUserCommand struct {
name string
}
diff --git a/history/history.go b/history/history.go
index f0b524b..37ce429 100644
--- a/history/history.go
+++ b/history/history.go
@@ -33,6 +33,7 @@ func Start() {
gitpath = path
}
+// InitGitRepo checks a Git repository and initializes it if necessary.
func InitGitRepo() {
// Detect if the Git repo directory is a Git repository
isGitRepo := true
@@ -144,7 +145,7 @@ func (rev *Revision) textDiff() (diff string) {
for _, filename := range filenames {
text, err := PrimitiveDiffAtRevision(filename, rev.Hash)
if err != nil {
- diff += "\nAn error has occured with " + filename + "\n"
+ diff += "\nAn error has occurred with " + filename + "\n"
}
diff += text + "\n"
}
diff --git a/history/information.go b/history/information.go
index e27cf19..8237c1c 100644
--- a/history/information.go
+++ b/history/information.go
@@ -52,18 +52,22 @@ func recentChangesFeed() *feeds.Feed {
return feed
}
+// RecentChangesRSS creates recent changes feed in RSS format.
func RecentChangesRSS() (string, error) {
return recentChangesFeed().ToRss()
}
+// RecentChangesAtom creates recent changes feed in Atom format.
func RecentChangesAtom() (string, error) {
return recentChangesFeed().ToAtom()
}
+// RecentChangesJSON creates recent changes feed in JSON format.
func RecentChangesJSON() (string, error) {
return recentChangesFeed().ToJSON()
}
+// RecentChanges gathers an arbitrary number of latest changes in form of revisions slice.
func RecentChanges(n int) []Revision {
var (
out, err = silentGitsh(
@@ -110,8 +114,8 @@ func Revisions(hyphaName string) ([]Revision, error) {
return revs, err
}
-// HistoryWithRevisions returns an html representation of `revs` that is meant to be inserted in a history page.
-func HistoryWithRevisions(hyphaName string, revs []Revision) (html string) {
+// WithRevisions returns an html representation of `revs` that is meant to be inserted in a history page.
+func WithRevisions(hyphaName string, revs []Revision) (html string) {
var (
currentYear int
currentMonth time.Month
diff --git a/history/operations.go b/history/operations.go
index 9438538..2e23f82 100644
--- a/history/operations.go
+++ b/history/operations.go
@@ -19,16 +19,22 @@ var gitMutex = sync.Mutex{}
type OpType int
const (
+ // TypeNone represents an empty operation. Not to be used in practice.
TypeNone OpType = iota
+ // TypeEditText represents an edit of hypha text part.
TypeEditText
+ // TypeEditBinary represents an addition or replacement of hypha attachment.
TypeEditBinary
+ // TypeDeleteHypha represents a hypha deletion
TypeDeleteHypha
+ // TypeRenameHypha represents a hypha renaming
TypeRenameHypha
+ // TypeUnattachHypha represents a hypha attachment deletion
TypeUnattachHypha
)
-// HistoryOp is an object representing a history operation.
-type HistoryOp struct {
+// Op is an object representing a history operation.
+type Op struct {
// All errors are appended here.
Errs []error
Type OpType
@@ -38,9 +44,9 @@ type HistoryOp struct {
}
// Operation is a constructor of a history operation.
-func Operation(opType OpType) *HistoryOp {
+func Operation(opType OpType) *Op {
gitMutex.Lock()
- hop := &HistoryOp{
+ hop := &Op{
Errs: []error{},
name: "anon",
email: "anon@mycorrhiza",
@@ -50,7 +56,7 @@ func Operation(opType OpType) *HistoryOp {
}
// git operation maker helper
-func (hop *HistoryOp) gitop(args ...string) *HistoryOp {
+func (hop *Op) gitop(args ...string) *Op {
out, err := gitsh(args...)
if err != nil {
fmt.Println("out:", out.String())
@@ -60,17 +66,18 @@ func (hop *HistoryOp) gitop(args ...string) *HistoryOp {
}
// WithErr appends the `err` to the list of errors.
-func (hop *HistoryOp) WithErr(err error) *HistoryOp {
+func (hop *Op) WithErr(err error) *Op {
hop.Errs = append(hop.Errs, err)
return hop
}
-func (hop *HistoryOp) WithErrAbort(err error) *HistoryOp {
+// WithErrAbort appends the `err` to the list of errors and immediately aborts the operation.
+func (hop *Op) WithErrAbort(err error) *Op {
return hop.WithErr(err).Abort()
}
// WithFilesRemoved git-rm-s all passed `paths`. Paths can be rooted or not. Paths that are empty strings are ignored.
-func (hop *HistoryOp) WithFilesRemoved(paths ...string) *HistoryOp {
+func (hop *Op) WithFilesRemoved(paths ...string) *Op {
args := []string{"rm", "--quiet", "--"}
for _, path := range paths {
if path != "" {
@@ -81,7 +88,7 @@ func (hop *HistoryOp) WithFilesRemoved(paths ...string) *HistoryOp {
}
// WithFilesRenamed git-mv-s all passed keys of `pairs` to values of `pairs`. Paths can be rooted ot not. Empty keys are ignored.
-func (hop *HistoryOp) WithFilesRenamed(pairs map[string]string) *HistoryOp {
+func (hop *Op) WithFilesRenamed(pairs map[string]string) *Op {
for from, to := range pairs {
if from != "" {
if err := os.MkdirAll(filepath.Dir(to), 0777); err != nil {
@@ -97,7 +104,7 @@ func (hop *HistoryOp) WithFilesRenamed(pairs map[string]string) *HistoryOp {
}
// WithFiles stages all passed `paths`. Paths can be rooted or not.
-func (hop *HistoryOp) WithFiles(paths ...string) *HistoryOp {
+func (hop *Op) WithFiles(paths ...string) *Op {
for i, path := range paths {
paths[i] = util.ShorterPath(path)
}
@@ -106,7 +113,7 @@ func (hop *HistoryOp) WithFiles(paths ...string) *HistoryOp {
}
// Apply applies history operation by doing the commit.
-func (hop *HistoryOp) Apply() *HistoryOp {
+func (hop *Op) Apply() *Op {
hop.gitop(
"commit",
"--author='"+hop.name+" <"+hop.email+">'",
@@ -117,13 +124,13 @@ func (hop *HistoryOp) Apply() *HistoryOp {
}
// Abort aborts the history operation.
-func (hop *HistoryOp) Abort() *HistoryOp {
+func (hop *Op) Abort() *Op {
gitMutex.Unlock()
return hop
}
// WithMsg sets what message will be used for the future commit. If user message exceeds one line, it is stripped down.
-func (hop *HistoryOp) WithMsg(userMsg string) *HistoryOp {
+func (hop *Op) WithMsg(userMsg string) *Op {
for _, ch := range userMsg {
if ch == '\r' || ch == '\n' {
break
@@ -134,7 +141,7 @@ func (hop *HistoryOp) WithMsg(userMsg string) *HistoryOp {
}
// WithUser sets a user for the commit.
-func (hop *HistoryOp) WithUser(u *user.User) *HistoryOp {
+func (hop *Op) WithUser(u *user.User) *Op {
if u.Group != "anon" {
hop.name = u.Name
hop.email = u.Name + "@mycorrhiza"
@@ -142,10 +149,12 @@ func (hop *HistoryOp) WithUser(u *user.User) *HistoryOp {
return hop
}
-func (hop *HistoryOp) HasErrors() bool {
+// HasErrors checks whether operation has errors appended.
+func (hop *Op) HasErrors() bool {
return len(hop.Errs) > 0
}
-func (hop *HistoryOp) FirstErrorText() string {
+// FirstErrorText extracts first error appended to the operation.
+func (hop *Op) FirstErrorText() string {
return hop.Errs[0].Error()
}
diff --git a/hyphae/backlinks.go b/hyphae/backlinks.go
index 0923dc1..ec78ece 100644
--- a/hyphae/backlinks.go
+++ b/hyphae/backlinks.go
@@ -38,12 +38,14 @@ type BacklinkIndexOperation interface {
Apply()
}
+// BacklinkIndexEdit contains data for backlink index update after a hypha edit
type BacklinkIndexEdit struct {
Name string
OldLinks []string
NewLinks []string
}
+// Apply changes backlink index respective to the operation data
func (op BacklinkIndexEdit) Apply() {
oldLinks := toLinkSet(op.OldLinks)
newLinks := toLinkSet(op.NewLinks)
@@ -62,11 +64,13 @@ func (op BacklinkIndexEdit) Apply() {
}
}
+// BacklinkIndexDeletion contains data for backlink index update after a hypha deletion
type BacklinkIndexDeletion struct {
Name string
Links []string
}
+// Apply changes backlink index respective to the operation data
func (op BacklinkIndexDeletion) Apply() {
for _, link := range op.Links {
if lSet, exists := backlinkIndex[link]; exists {
@@ -75,12 +79,14 @@ func (op BacklinkIndexDeletion) Apply() {
}
}
+// BacklinkIndexRenaming contains data for backlink index update after a hypha renaming
type BacklinkIndexRenaming struct {
OldName string
NewName string
Links []string
}
+// Apply changes backlink index respective to the operation data
func (op BacklinkIndexRenaming) Apply() {
for _, link := range op.Links {
if lSet, exists := backlinkIndex[link]; exists {
diff --git a/hyphae/count.go b/hyphae/count.go
index 7d20f93..241f950 100644
--- a/hyphae/count.go
+++ b/hyphae/count.go
@@ -10,21 +10,21 @@ var count = struct {
sync.Mutex
}{}
-// Set the value of hyphae count to zero. Use when reloading hyphae.
+// ResetCount sets the value of hyphae count to zero. Use when reloading hyphae.
func ResetCount() {
count.Lock()
count.value = 0
count.Unlock()
}
-// Increment the value of the hyphae counter. Use when creating new hyphae or loading hyphae from disk.
+// IncrementCount increments the value of the hyphae counter. Use when creating new hyphae or loading hyphae from disk.
func IncrementCount() {
count.Lock()
count.value++
count.Unlock()
}
-// Decrement the value of the hyphae counter. Use when deleting existing hyphae.
+// DecrementCount decrements the value of the hyphae counter. Use when deleting existing hyphae.
func DecrementCount() {
count.Lock()
count.value--
diff --git a/hyphae/hyphae.go b/hyphae/hyphae.go
index 6729354..d7a1875 100644
--- a/hyphae/hyphae.go
+++ b/hyphae/hyphae.go
@@ -12,6 +12,7 @@ import (
// HyphaPattern is a pattern which all hyphae must match.
var HyphaPattern = regexp.MustCompile(`[^?!:#@><*|"'&%{}]+`)
+// Hypha keeps vital information about a hypha
type Hypha struct {
sync.RWMutex
@@ -79,6 +80,7 @@ func (h *Hypha) Insert() (justRecorded bool) {
return !recorded
}
+// InsertIfNew checks whether hypha exists and returns `true` if it didn't and has been created.
func (h *Hypha) InsertIfNew() (justRecorded bool) {
if !h.Exists {
return h.Insert()
@@ -86,6 +88,7 @@ func (h *Hypha) InsertIfNew() (justRecorded bool) {
return false
}
+// Delete removes a hypha from the storage.
func (h *Hypha) Delete() {
byNamesMutex.Lock()
h.Lock()
@@ -95,6 +98,7 @@ func (h *Hypha) Delete() {
h.Unlock()
}
+// RenameTo renames a hypha and performs respective changes in the storage.
func (h *Hypha) RenameTo(newName string) {
byNamesMutex.Lock()
h.Lock()
diff --git a/hyphae/iteration.go b/hyphae/iteration.go
index a33e9ac..1773977 100644
--- a/hyphae/iteration.go
+++ b/hyphae/iteration.go
@@ -11,6 +11,7 @@ type Iteration struct {
checks []func(h *Hypha) CheckResult
}
+// NewIteration constructs an iteration without checks.
func NewIteration() *Iteration {
return &Iteration{
iterator: YieldExistingHyphae,
diff --git a/hyphae/iterators.go b/hyphae/iterators.go
index 9fb494e..e2d6749 100644
--- a/hyphae/iterators.go
+++ b/hyphae/iterators.go
@@ -1,6 +1,7 @@
-// File `iterators.go` contains stuff that iterates over hyphae.
package hyphae
+// File `iterators.go` contains stuff that iterates over hyphae.
+
import (
"sort"
"strings"
diff --git a/l18n/util.go b/l18n/util.go
index 5701548..8bd27cb 100644
--- a/l18n/util.go
+++ b/l18n/util.go
@@ -14,7 +14,7 @@ var locales = language.NewMatcher([]language.Tag{
language.Make("ru"),
})
-// GetLocalizer takes a HTTP request and picks the most appropriate localizer (with English fallback)
+// FromRequest takes a HTTP request and picks the most appropriate localizer (with English fallback)
func FromRequest(r *http.Request) *Localizer {
t, _, _ := language.ParseAcceptLanguage(r.Header.Get("Accept-Language"))
tag, _, _ := locales.Match(t...)
@@ -91,7 +91,7 @@ func getLocalizationKey(locale string, key string) string {
/* chekoopa: Missing translation features:
- history records (they use Git description, the possible solution is to parse and translate)
-- history dates (HistoryWithRevisions doesn't consider locale, Monday package is bad idea)
+- history dates (history.WithRevisions doesn't consider locale, Monday package is bad idea)
- probably error messages (which are scattered across the code)
- default top bar (it is static from one-shot cfg.SetDefaultHeaderLinks, but it is possible to track default-ness in templates)
- alt solution is implementing "special" links
diff --git a/shroom/can.go b/shroom/can.go
index 3e0c67f..0cf61db 100644
--- a/shroom/can.go
+++ b/shroom/can.go
@@ -14,29 +14,30 @@ func canFactory(
noRightsMsg string,
notExistsMsg string,
careAboutExistence bool,
-) func(*user.User, *hyphae.Hypha) (error, string) {
- return func(u *user.User, h *hyphae.Hypha) (error, string) {
+) func(*user.User, *hyphae.Hypha) (string, error) {
+ return func(u *user.User, h *hyphae.Hypha) (string, error) {
if !u.CanProceed(action) {
rejectLogger(h, u, "no rights")
- return errors.New(noRightsMsg), "Not enough rights"
+ return "Not enough rights", errors.New(noRightsMsg)
}
if careAboutExistence && !h.Exists {
rejectLogger(h, u, "does not exist")
- return errors.New(notExistsMsg), "Does not exist"
+ return "Does not exist", errors.New(notExistsMsg)
}
if dispatcher == nil {
- return nil, ""
+ return "", nil
}
errmsg, errtitle := dispatcher(h, u)
if errtitle == "" {
- return nil, ""
+ return "", nil
}
- return errors.New(errmsg), errtitle
+ return errtitle, errors.New(errmsg)
}
}
+// CanDelete and etc are hyphae operation checkers based on user rights and hyphae existence.
var (
CanDelete = canFactory(
rejectDeleteLog,
diff --git a/shroom/delete.go b/shroom/delete.go
index 6f71146..05c5c68 100644
--- a/shroom/delete.go
+++ b/shroom/delete.go
@@ -9,10 +9,10 @@ import (
)
// DeleteHypha deletes hypha and makes a history record about that.
-func DeleteHypha(u *user.User, h *hyphae.Hypha) (hop *history.HistoryOp, errtitle string) {
+func DeleteHypha(u *user.User, h *hyphae.Hypha) (hop *history.Op, errtitle string) {
hop = history.Operation(history.TypeDeleteHypha)
- if err, errtitle := CanDelete(u, h); errtitle != "" {
+ if errtitle, err := CanDelete(u, h); errtitle != "" {
hop.WithErrAbort(err)
return hop, errtitle
}
diff --git a/shroom/rename.go b/shroom/rename.go
index e4d3fc2..aedf968 100644
--- a/shroom/rename.go
+++ b/shroom/rename.go
@@ -11,36 +11,36 @@ import (
"github.com/bouncepaw/mycorrhiza/util"
)
-func canRenameThisToThat(oh *hyphae.Hypha, nh *hyphae.Hypha, u *user.User) (err error, errtitle string) {
+func canRenameThisToThat(oh *hyphae.Hypha, nh *hyphae.Hypha, u *user.User) (errtitle string, err error) {
if nh.Exists {
rejectRenameLog(oh, u, fmt.Sprintf("name ā%sā taken already", nh.Name))
- return errors.New(fmt.Sprintf("Hypha named %[1]s already exists, cannot rename", nh.Name)), "Name taken"
+ return "Name taken", fmt.Errorf("Hypha named %[1]s already exists, cannot rename", nh.Name)
}
if nh.Name == "" {
rejectRenameLog(oh, u, "no new name given")
- return errors.New("No new name is given"), "No name given"
+ return "No name given", errors.New("No new name is given")
}
if !hyphae.HyphaPattern.MatchString(nh.Name) {
rejectRenameLog(oh, u, fmt.Sprintf("new name ā%sā invalid", nh.Name))
- return errors.New("Invalid new name. Names cannot contain characters ^?!:#@><*|\"\\'&%
"), "Invalid name"
+ return "Invalid name", errors.New("Invalid new name. Names cannot contain characters ^?!:#@><*|\"\\'&%
")
}
- return nil, ""
+ 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) (hop *history.HistoryOp, errtitle string) {
+func RenameHypha(h *hyphae.Hypha, newHypha *hyphae.Hypha, recursive bool, u *user.User) (hop *history.Op, errtitle string) {
newHypha.Lock()
defer newHypha.Unlock()
hop = history.Operation(history.TypeRenameHypha)
- if err, errtitle := CanRename(u, h); errtitle != "" {
+ if errtitle, err := CanRename(u, h); errtitle != "" {
hop.WithErrAbort(err)
return hop, errtitle
}
- if err, errtitle := canRenameThisToThat(h, newHypha, u); errtitle != "" {
+ if errtitle, err := canRenameThisToThat(h, newHypha, u); errtitle != "" {
hop.WithErrAbort(err)
return hop, errtitle
}
diff --git a/shroom/unattach.go b/shroom/unattach.go
index 60f31e6..4514e9b 100644
--- a/shroom/unattach.go
+++ b/shroom/unattach.go
@@ -1,7 +1,6 @@
package shroom
import (
- "errors"
"fmt"
"github.com/bouncepaw/mycorrhiza/history"
@@ -10,10 +9,10 @@ import (
)
// UnattachHypha unattaches hypha and makes a history record about that.
-func UnattachHypha(u *user.User, h *hyphae.Hypha) (hop *history.HistoryOp, errtitle string) {
+func UnattachHypha(u *user.User, h *hyphae.Hypha) (hop *history.Op, errtitle string) {
hop = history.Operation(history.TypeUnattachHypha)
- if err, errtitle := CanUnattach(u, h); errtitle != "" {
+ if errtitle, err := CanUnattach(u, h); errtitle != "" {
hop.WithErrAbort(err)
return hop, errtitle
}
@@ -27,7 +26,7 @@ func UnattachHypha(u *user.User, h *hyphae.Hypha) (hop *history.HistoryOp, errti
if len(hop.Errs) > 0 {
rejectUnattachLog(h, u, "fail")
// FIXME: something may be wrong here
- return hop.WithErrAbort(errors.New(fmt.Sprintf("Could not unattach this hypha due to internal server errors: %v
", hop.Errs))), "Error"
+ return hop.WithErrAbort(fmt.Errorf("Could not unattach this hypha due to internal server errors: %v
", hop.Errs)), "Error"
}
if h.BinaryPath != "" {
diff --git a/shroom/upload.go b/shroom/upload.go
index ecdff81..ed8b4f5 100644
--- a/shroom/upload.go
+++ b/shroom/upload.go
@@ -18,7 +18,8 @@ import (
"github.com/bouncepaw/mycorrhiza/user"
)
-func UploadText(h *hyphae.Hypha, data []byte, message string, u *user.User) (hop *history.HistoryOp, errtitle string) {
+// UploadText edits a hypha' text part and makes a history record about that.
+func UploadText(h *hyphae.Hypha, data []byte, message string, u *user.User) (hop *history.Op, errtitle string) {
hop = history.Operation(history.TypeEditText)
var action string
if h.Exists {
@@ -33,7 +34,7 @@ func UploadText(h *hyphae.Hypha, data []byte, message string, u *user.User) (hop
hop.WithMsg(fmt.Sprintf("%s ā%sā: %s", action, h.Name, message))
}
- if err, errtitle := CanEdit(u, h); err != nil {
+ if errtitle, err := CanEdit(u, h); err != nil {
return hop.WithErrAbort(err), errtitle
}
if len(bytes.TrimSpace(data)) == 0 && h.BinaryPath == "" {
@@ -43,7 +44,8 @@ func UploadText(h *hyphae.Hypha, data []byte, message string, u *user.User) (hop
return uploadHelp(h, hop, ".myco", data, u)
}
-func UploadBinary(h *hyphae.Hypha, mime string, file multipart.File, u *user.User) (*history.HistoryOp, string) {
+// UploadBinary edits a hypha' attachment and makes a history record about that.
+func UploadBinary(h *hyphae.Hypha, mime string, file multipart.File, u *user.User) (*history.Op, string) {
var (
hop = history.Operation(history.TypeEditBinary).WithMsg(fmt.Sprintf("Upload attachment for ā%sā with type ā%sā", h.Name, mime))
data, err = io.ReadAll(file)
@@ -52,7 +54,7 @@ func UploadBinary(h *hyphae.Hypha, mime string, file multipart.File, u *user.Use
if err != nil {
return hop.WithErrAbort(err), err.Error()
}
- if err, errtitle := CanAttach(u, h); err != nil {
+ if errtitle, err := CanAttach(u, h); err != nil {
return hop.WithErrAbort(err), errtitle
}
if len(data) == 0 {
@@ -63,7 +65,7 @@ func UploadBinary(h *hyphae.Hypha, mime string, file multipart.File, u *user.Use
}
// uploadHelp is a helper function for UploadText and UploadBinary
-func uploadHelp(h *hyphae.Hypha, hop *history.HistoryOp, ext string, data []byte, u *user.User) (*history.HistoryOp, string) {
+func uploadHelp(h *hyphae.Hypha, hop *history.Op, ext string, data []byte, u *user.User) (*history.Op, string) {
var (
fullPath = filepath.Join(files.HyphaeDir(), h.Name+ext)
originalFullPath = &h.TextPath
diff --git a/shroom/view.go b/shroom/view.go
index 486c479..1bd22db 100644
--- a/shroom/view.go
+++ b/shroom/view.go
@@ -21,6 +21,7 @@ func FetchTextPart(h *hyphae.Hypha) (string, error) {
return string(text), nil
}
+// SetHeaderLinks initializes header links by reading the configured hypha, if there is any, or resorting to default values.
func SetHeaderLinks() {
if userLinksHypha := hyphae.ByName(cfg.HeaderLinksHypha); !userLinksHypha.Exists {
cfg.SetDefaultHeaderLinks()
diff --git a/tree/tree.go b/tree/tree.go
index f5b2ce5..244d808 100644
--- a/tree/tree.go
+++ b/tree/tree.go
@@ -137,14 +137,14 @@ func figureOutChildren(hyphaName string, subhyphaePool map[string]bool, exists b
nestLevel = strings.Count(hyphaName, "/")
adopted = make([]child, 0)
)
- for subhyphaName, _ := range subhyphaePool {
+ for subhyphaName := range subhyphaePool {
subnestLevel := strings.Count(subhyphaName, "/")
if subnestLevel-1 == nestLevel && path.Dir(subhyphaName) == hyphaName {
delete(subhyphaePool, subhyphaName)
adopted = append(adopted, figureOutChildren(subhyphaName, subhyphaePool, true))
}
}
- for descName, _ := range subhyphaePool {
+ for descName := range subhyphaePool {
if strings.HasPrefix(descName, hyphaName) {
var (
rawSubPath = strings.TrimPrefix(descName, hyphaName)[1:]
diff --git a/user/files.go b/user/files.go
index 8b97bb0..2f98207 100644
--- a/user/files.go
+++ b/user/files.go
@@ -76,6 +76,7 @@ func readTokensToUsers() {
log.Println("Found", len(tmp), "active sessions")
}
+// SaveUserDatabase stores current user credentials into JSON file by configured path.
func SaveUserDatabase() error {
return dumpUserCredentials()
}
diff --git a/user/net.go b/user/net.go
index 48b70f1..b439cb9 100644
--- a/user/net.go
+++ b/user/net.go
@@ -27,7 +27,7 @@ func FromRequest(rq *http.Request) *User {
if err != nil {
return EmptyUser()
}
- return UserByToken(cookie.Value)
+ return ByToken(cookie.Value)
}
// LogoutFromRequest logs the user in `rq` out and rewrites the cookie in `w`.
@@ -108,9 +108,9 @@ func AddSession(username string) (string, error) {
}
// A handy cookie constructor
-func cookie(name_suffix, val string, t time.Time) *http.Cookie {
+func cookie(nameSuffix, val string, t time.Time) *http.Cookie {
return &http.Cookie{
- Name: "mycorrhiza_" + name_suffix,
+ Name: "mycorrhiza_" + nameSuffix,
Value: val,
Expires: t,
Path: "/",
diff --git a/user/user.go b/user/user.go
index 966916e..e0522bd 100644
--- a/user/user.go
+++ b/user/user.go
@@ -9,7 +9,7 @@ import (
"golang.org/x/crypto/bcrypt"
)
-// User is a user.
+// User is a user (duh).
type User struct {
// Name is a username. It must follow hypha naming rules.
Name string `json:"name"`
@@ -59,6 +59,7 @@ var groupRight = map[string]int{
"admin": 4,
}
+// ValidGroup checks whether provided user group name exists.
func ValidGroup(group string) bool {
for _, grp := range groups {
if grp == group {
@@ -68,10 +69,12 @@ func ValidGroup(group string) bool {
return false
}
+// ValidSource checks whether provided user source name exists.
func ValidSource(source string) bool {
return source == "local" || source == "telegram"
}
+// EmptyUser constructs an anonymous user.
func EmptyUser() *User {
return &User{
Name: "anon",
@@ -81,6 +84,7 @@ func EmptyUser() *User {
}
}
+// CanProceed checks whether user has rights to visit the provided path (and perform an action).
func (user *User) CanProceed(route string) bool {
if !cfg.UseAuth {
return true
diff --git a/user/users.go b/user/users.go
index 6daa301..07fe2a9 100644
--- a/user/users.go
+++ b/user/users.go
@@ -5,6 +5,7 @@ import "sync"
var users sync.Map
var tokens sync.Map
+// YieldUsers creates a channel which iterates existing users.
func YieldUsers() chan *User {
ch := make(chan *User)
go func(ch chan *User) {
@@ -17,6 +18,7 @@ func YieldUsers() chan *User {
return ch
}
+// ListUsersWithGroup returns a slice with users of desired group.
func ListUsersWithGroup(group string) []string {
filtered := []string{}
for u := range YieldUsers() {
@@ -27,6 +29,7 @@ func ListUsersWithGroup(group string) []string {
return filtered
}
+// Count returns total users count
func Count() (i uint64) {
users.Range(func(k, v interface{}) bool {
i++
@@ -35,24 +38,29 @@ func Count() (i uint64) {
return i
}
+// HasUsername checks whether the desired user exists
func HasUsername(username string) bool {
_, has := users.Load(username)
return has
}
+// CredentialsOK checks whether a correct user-password pair is provided
func CredentialsOK(username, password string) bool {
- return UserByName(username).isCorrectPassword(password)
+ return ByName(username).isCorrectPassword(password)
}
-func UserByToken(token string) *User {
+// ByToken finds a user by provided session token
+func ByToken(token string) *User {
+ // TODO: Needs more session data -- chekoopa
if usernameUntyped, ok := tokens.Load(token); ok {
username := usernameUntyped.(string)
- return UserByName(username)
+ return ByName(username)
}
return EmptyUser()
}
-func UserByName(username string) *User {
+// ByName finds a user by one's username
+func ByName(username string) *User {
if userUntyped, ok := users.Load(username); ok {
user := userUntyped.(*User)
return user
@@ -60,6 +68,7 @@ func UserByName(username string) *User {
return EmptyUser()
}
+// DeleteUser removes a user by one's name and saves user database.
func DeleteUser(name string) error {
user, loaded := users.LoadAndDelete(name)
if loaded {
diff --git a/util/util.go b/util/util.go
index 8e39b12..121e2da 100644
--- a/util/util.go
+++ b/util/util.go
@@ -111,6 +111,7 @@ type FormData struct {
fields map[string]string
}
+// NewFormData constructs empty form data instance.
func NewFormData() FormData {
return FormData{
err: nil,
@@ -118,6 +119,7 @@ func NewFormData() FormData {
}
}
+// FormDataFromRequest extracts a form data from request, using a set of keys.
func FormDataFromRequest(r *http.Request, keys []string) FormData {
formData := NewFormData()
for _, key := range keys {
@@ -126,10 +128,12 @@ func FormDataFromRequest(r *http.Request, keys []string) FormData {
return formData
}
+// HasError is true if there is indeed an error.
func (f FormData) HasError() bool {
return f.err != nil
}
+// Error returns an error text or empty string, if there are no errors in form data.
func (f FormData) Error() string {
if f.err == nil {
return ""
@@ -137,15 +141,18 @@ func (f FormData) Error() string {
return f.err.Error()
}
+// WithError puts an error into form data and returns itself.
func (f FormData) WithError(err error) FormData {
f.err = err
return f
}
+// Get accesses form data with a key
func (f FormData) Get(key string) string {
return f.fields[key]
}
+// Put writes a form value for provided key
func (f FormData) Put(key, value string) {
f.fields[key] = value
}
diff --git a/web/admin.go b/web/admin.go
index 5f84dac..876bbf6 100644
--- a/web/admin.go
+++ b/web/admin.go
@@ -79,7 +79,7 @@ func handlerAdminUsers(w http.ResponseWriter, rq *http.Request) {
func handlerAdminUserEdit(w http.ResponseWriter, rq *http.Request) {
vars := mux.Vars(rq)
- u := user.UserByName(vars["username"])
+ u := user.ByName(vars["username"])
if u == nil {
util.HTTP404Page(w, "404 page not found")
return
@@ -121,7 +121,7 @@ func handlerAdminUserEdit(w http.ResponseWriter, rq *http.Request) {
func handlerAdminUserDelete(w http.ResponseWriter, rq *http.Request) {
vars := mux.Vars(rq)
- u := user.UserByName(vars["username"])
+ u := user.ByName(vars["username"])
if u == nil {
util.HTTP404Page(w, "404 page not found")
return
diff --git a/web/auth.go b/web/auth.go
index 9cbe5d2..8b15ea0 100644
--- a/web/auth.go
+++ b/web/auth.go
@@ -143,7 +143,7 @@ func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) {
false,
)
)
- if user.HasUsername(username) && user.UserByName(username).Source == "telegram" {
+ if user.HasUsername(username) && user.ByName(username).Source == "telegram" {
// Problems is something we put blankets on.
err = nil
}
diff --git a/web/history.go b/web/history.go
index d6ae80e..595d19f 100644
--- a/web/history.go
+++ b/web/history.go
@@ -36,7 +36,7 @@ func handlerHistory(w http.ResponseWriter, rq *http.Request) {
// History can be found for files that do not exist anymore.
revs, err := history.Revisions(hyphaName)
if err == nil {
- list = history.HistoryWithRevisions(hyphaName, revs)
+ list = history.WithRevisions(hyphaName, revs)
}
log.Println("Found", len(revs), "revisions for", hyphaName)
diff --git a/web/mutators.go b/web/mutators.go
index f72091e..bbfb0cb 100644
--- a/web/mutators.go
+++ b/web/mutators.go
@@ -35,7 +35,7 @@ func initMutators(r *mux.Router) {
func factoryHandlerAsker(
actionPath string,
- asker func(*user.User, *hyphae.Hypha) (error, string),
+ asker func(*user.User, *hyphae.Hypha) (string, error),
succTitleKey string,
succPageTemplate func(*http.Request, string, bool) string,
) func(http.ResponseWriter, *http.Request) {
@@ -47,7 +47,7 @@ func factoryHandlerAsker(
u = user.FromRequest(rq)
lc = l18n.FromRequest(rq)
)
- if err, errtitle := asker(u, h); err != nil {
+ if errtitle, err := asker(u, h); err != nil {
httpErr(
w,
lc,
@@ -90,7 +90,7 @@ var handlerRenameAsk = factoryHandlerAsker(
func factoryHandlerConfirmer(
actionPath string,
- confirmer func(*hyphae.Hypha, *user.User, *http.Request) (*history.HistoryOp, string),
+ confirmer func(*hyphae.Hypha, *user.User, *http.Request) (*history.Op, string),
) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, rq *http.Request) {
util.PrepareRq(rq)
@@ -112,14 +112,14 @@ func factoryHandlerConfirmer(
var handlerUnattachConfirm = factoryHandlerConfirmer(
"unattach-confirm",
- func(h *hyphae.Hypha, u *user.User, _ *http.Request) (*history.HistoryOp, string) {
+ func(h *hyphae.Hypha, u *user.User, _ *http.Request) (*history.Op, string) {
return shroom.UnattachHypha(u, h)
},
)
var handlerDeleteConfirm = factoryHandlerConfirmer(
"delete-confirm",
- func(h *hyphae.Hypha, u *user.User, _ *http.Request) (*history.HistoryOp, string) {
+ func(h *hyphae.Hypha, u *user.User, _ *http.Request) (*history.Op, string) {
return shroom.DeleteHypha(u, h)
},
)
@@ -158,7 +158,7 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) {
u = user.FromRequest(rq)
lc = l18n.FromRequest(rq)
)
- if err, errtitle := shroom.CanEdit(u, h); err != nil {
+ if errtitle, err := shroom.CanEdit(u, h); err != nil {
httpErr(w, lc, http.StatusInternalServerError, hyphaName,
errtitle,
err.Error())
@@ -196,7 +196,7 @@ func handlerUploadText(w http.ResponseWriter, rq *http.Request) {
message = rq.PostFormValue("message")
u = user.FromRequest(rq)
lc = l18n.FromRequest(rq)
- hop *history.HistoryOp
+ hop *history.Op
errtitle string
)
@@ -247,7 +247,7 @@ func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) {
lc.Get("ui.error"),
err.Error())
}
- if err, errtitle := shroom.CanAttach(u, h); err != nil {
+ if errtitle, err := shroom.CanAttach(u, h); err != nil {
httpErr(w, lc, http.StatusInternalServerError, hyphaName,
errtitle,
err.Error())
diff --git a/web/readers.go b/web/readers.go
index 047fa24..68edb05 100644
--- a/web/readers.go
+++ b/web/readers.go
@@ -55,10 +55,10 @@ func handlerAttachment(w http.ResponseWriter, rq *http.Request) {
func handlerPrimitiveDiff(w http.ResponseWriter, rq *http.Request) {
util.PrepareRq(rq)
var (
- shorterUrl = strings.TrimPrefix(rq.URL.Path, "/primitive-diff/")
- firstSlashIndex = strings.IndexRune(shorterUrl, '/')
- revHash = shorterUrl[:firstSlashIndex]
- hyphaName = util.CanonicalName(shorterUrl[firstSlashIndex+1:])
+ shorterURL = strings.TrimPrefix(rq.URL.Path, "/primitive-diff/")
+ firstSlashIndex = strings.IndexRune(shorterURL, '/')
+ revHash = shorterURL[:firstSlashIndex]
+ hyphaName = util.CanonicalName(shorterURL[firstSlashIndex+1:])
h = hyphae.ByName(hyphaName)
u = user.FromRequest(rq)
lc = l18n.FromRequest(rq)
@@ -77,10 +77,10 @@ func handlerPrimitiveDiff(w http.ResponseWriter, rq *http.Request) {
func handlerRevisionText(w http.ResponseWriter, rq *http.Request) {
util.PrepareRq(rq)
var (
- shorterUrl = strings.TrimPrefix(rq.URL.Path, "/rev-text/")
- firstSlashIndex = strings.IndexRune(shorterUrl, '/')
- revHash = shorterUrl[:firstSlashIndex]
- hyphaName = util.CanonicalName(shorterUrl[firstSlashIndex+1:])
+ shorterURL = strings.TrimPrefix(rq.URL.Path, "/rev-text/")
+ firstSlashIndex = strings.IndexRune(shorterURL, '/')
+ revHash = shorterURL[:firstSlashIndex]
+ hyphaName = util.CanonicalName(shorterURL[firstSlashIndex+1:])
h = hyphae.ByName(hyphaName)
textContents, err = history.FileAtRevision(h.TextPartPath(), revHash)
)
@@ -101,10 +101,10 @@ func handlerRevision(w http.ResponseWriter, rq *http.Request) {
util.PrepareRq(rq)
var (
lc = l18n.FromRequest(rq)
- shorterUrl = strings.TrimPrefix(rq.URL.Path, "/rev/")
- firstSlashIndex = strings.IndexRune(shorterUrl, '/')
- revHash = shorterUrl[:firstSlashIndex]
- hyphaName = util.CanonicalName(shorterUrl[firstSlashIndex+1:])
+ shorterURL = strings.TrimPrefix(rq.URL.Path, "/rev/")
+ firstSlashIndex = strings.IndexRune(shorterURL, '/')
+ revHash = shorterURL[:firstSlashIndex]
+ hyphaName = util.CanonicalName(shorterURL[firstSlashIndex+1:])
h = hyphae.ByName(hyphaName)
contents = fmt.Sprintf(`
%s
`, lc.Get("ui.revision_no_text")) textContents, err = history.FileAtRevision(h.TextPartPath(), revHash) diff --git a/web/web.go b/web/web.go index 5e985fe..d19a0c5 100644 --- a/web/web.go +++ b/web/web.go @@ -74,6 +74,7 @@ func handlerRobotsTxt(w http.ResponseWriter, rq *http.Request) { file.Close() } +// Handler initializes func Handler() http.Handler { router := mux.NewRouter() router.Use(func(next http.Handler) http.Handler {