From 85c936d94a0483ee0cee538306ca7b637204a3d1 Mon Sep 17 00:00:00 2001 From: Mikhail Chekan Date: Sat, 2 Oct 2021 01:12:16 +0800 Subject: [PATCH] Housekeeping with linter 'I do as the golint guides' --- README.md | 2 ++ flag.go | 1 + history/history.go | 3 ++- history/information.go | 8 ++++++-- history/operations.go | 41 +++++++++++++++++++++++++---------------- hyphae/backlinks.go | 6 ++++++ hyphae/count.go | 6 +++--- hyphae/hyphae.go | 4 ++++ hyphae/iteration.go | 1 + hyphae/iterators.go | 3 ++- l18n/util.go | 4 ++-- shroom/can.go | 15 ++++++++------- shroom/delete.go | 4 ++-- shroom/rename.go | 16 ++++++++-------- shroom/unattach.go | 7 +++---- shroom/upload.go | 12 +++++++----- shroom/view.go | 1 + tree/tree.go | 4 ++-- user/files.go | 1 + user/net.go | 6 +++--- user/user.go | 6 +++++- user/users.go | 17 +++++++++++++---- util/util.go | 7 +++++++ web/admin.go | 4 ++-- web/auth.go | 2 +- web/history.go | 2 +- web/mutators.go | 16 ++++++++-------- web/readers.go | 24 ++++++++++++------------ web/web.go | 1 + 29 files changed, 139 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index 2ef0936..1852580 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ A screenshot of mycorrhiza.wiki's home page in the Safari browser +[![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 {