1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2025-01-19 07:02:51 +00:00

Merge pull request #100 from chekoopa/tidy-up

Housekeeping with linter
This commit is contained in:
Timur Ismagilov 2021-10-01 20:19:58 +03:00 committed by GitHub
commit 54fdb29ddf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 139 additions and 85 deletions

View File

@ -2,6 +2,8 @@
<img src="https://mycorrhiza.wiki/binary/release/1.4/screenshot" alt="A screenshot of mycorrhiza.wiki's home page in the Safari browser" width="600">
[![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)

View File

@ -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
}

View File

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

View File

@ -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

View File

@ -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()
}

View File

@ -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 {

View File

@ -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--

View File

@ -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()

View File

@ -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,

View File

@ -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"

View File

@ -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

View File

@ -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,

View File

@ -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
}

View File

@ -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 <a href='/hypha/%[1]s'>%[1]s</a> already exists, cannot rename", nh.Name)), "Name taken"
return "Name taken", fmt.Errorf("Hypha named <a href='/hypha/%[1]s'>%[1]s</a> 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 <code>^?!:#@&gt;&lt;*|\"\\'&amp;%</code>"), "Invalid name"
return "Invalid name", errors.New("Invalid new name. Names cannot contain characters <code>^?!:#@&gt;&lt;*|\"\\'&amp;%</code>")
}
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
}

View File

@ -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: <code>%v</code>", hop.Errs))), "Error"
return hop.WithErrAbort(fmt.Errorf("Could not unattach this hypha due to internal server errors: <code>%v</code>", hop.Errs)), "Error"
}
if h.BinaryPath != "" {

View File

@ -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

View File

@ -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()

View File

@ -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:]

View File

@ -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()
}

View File

@ -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: "/",

View File

@ -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

View File

@ -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 {

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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)

View File

@ -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())

View File

@ -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(`<p>%s</p>`, lc.Get("ui.revision_no_text"))
textContents, err = history.FileAtRevision(h.TextPartPath(), revHash)

View File

@ -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 {