request

package
v0.41.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 24, 2017 License: AGPL-3.0 Imports: 21 Imported by: 0

Documentation

Overview

Package request handles database requests for Documize, mostly from the endpoints package.

Index

Constants

View Source
const (
	// AuditGetDocument means someone viewed a document
	AuditGetDocument string = "get-document"
)

Variables

View Source
var Db *sqlx.DB

Db is the central connection to the database, used by all database requests.

Functions

func CheckDomain

func CheckDomain(domain string) string

CheckDomain makes sure there is an organisation with the correct domain

func ConfigSet

func ConfigSet(area, json string) error

ConfigSet writes a configuration JSON element to the config table.

func ConfigString

func ConfigString(area, path string) (ret string)

ConfigString fetches a configuration JSON element from the config table.

func GetRequestSubdomain

func GetRequestSubdomain(r *http.Request) string

GetRequestSubdomain extracts subdomain from referring URL.

func GetSubdomainFromHost

func GetSubdomainFromHost(r *http.Request) string

GetSubdomainFromHost extracts the subdomain from the requesting URL.

func SetContext

func SetContext(r *http.Request, c Context)

SetContext simply calls the Set method on the passed context, using the empty context stored in rc as an extra parameter.

func UserConfigGetJSON

func UserConfigGetJSON(orgid, userid, area, path string) (ret string)

UserConfigGetJSON fetches a configuration JSON element from the userconfig table for a given orgid/userid combination. Errors return the empty string. A blank path returns the whole JSON object, as JSON.

func UserConfigSetJSON

func UserConfigSetJSON(orgid, userid, area, json string) error

UserConfigSetJSON writes a configuration JSON element to the userconfig table for the current user.

Types

type Context

type Context struct {
	AllowAnonymousAccess bool
	Authenticated        bool
	Administrator        bool
	Guest                bool
	Editor               bool
	Global               bool
	UserID               string
	OrgID                string
	OrgName              string
	SSL                  bool
	AppURL               string // e.g. https://{url}.documize.com
	Subdomain            string
	Expires              time.Time
	Transaction          *sqlx.Tx
}

Context holds the context in which the client is dealing with Documize.

func NewContext

func NewContext() Context

NewContext simply returns a blank Context type.

func (*Context) GetAppURL

func (c *Context) GetAppURL(endpoint string) string

GetAppURL returns full HTTP url for the app

type Persister

type Persister struct {
	Context Context
	Base    baseManager
}

Persister stores the Context of the client along with a baseManager instance.

func GetPersister

func GetPersister(r *http.Request) Persister

GetPersister reurns a Persister which contains a Context which is based on the incoming request.

func SetupPersister

func SetupPersister() (*Persister, error)

SetupPersister prepares context for database activity.

func (*Persister) AddAccount

func (p *Persister) AddAccount(account entity.Account) (err error)

AddAccount inserts the given record into the datbase account table.

func (*Persister) AddAttachment

func (p *Persister) AddAttachment(a entity.Attachment) (err error)

AddAttachment inserts the given record into the database attachement table.

func (*Persister) AddBlock added in v0.40.0

func (p *Persister) AddBlock(b entity.Block) (err error)

AddBlock saves reusable content block.

func (p *Persister) AddContentLink(l entity.Link) (err error)

AddContentLink inserts wiki-link into the store. These links exist when content references another document or content.

func (*Persister) AddDocument

func (p *Persister) AddDocument(document entity.Document) (err error)

AddDocument inserts the given document record into the document table and audits that it has been done.

func (*Persister) AddLabel

func (p *Persister) AddLabel(l entity.Label) (err error)

AddLabel adds new folder into the store.

func (*Persister) AddLabelRole

func (p *Persister) AddLabelRole(l entity.LabelRole) (err error)

AddLabelRole inserts the given record into the labelrole database table.

func (*Persister) AddOrganization

func (p *Persister) AddOrganization(org entity.Organization) error

AddOrganization inserts the passed organization record into the organization table.

func (*Persister) AddPage

func (p *Persister) AddPage(model models.PageModel) (err error)

AddPage inserts the given page into the page table, adds that page to the queue of pages to index and audits that the page has been added.

func (*Persister) AddPin added in v0.34.0

func (p *Persister) AddPin(pin entity.Pin) (err error)

AddPin saves pinned item.

func (*Persister) AddUser

func (p *Persister) AddUser(user entity.User) (err error)

AddUser adds the given user record to the user table.

func (*Persister) CanChangeDocument

func (p *Persister) CanChangeDocument(documentID string) (hasPermission bool)

CanChangeDocument returns if the clinet has permission to change a given document.

func (*Persister) CanUploadDocument

func (p *Persister) CanUploadDocument(folderID string) (hasPermission bool)

CanUploadDocument returns if the client has permission to upload documents to the given folderID.

func (*Persister) CanViewDocument

func (p *Persister) CanViewDocument(documentID string) (hasPermission bool)

CanViewDocument returns if the clinet has permission to view a given document.

func (*Persister) CanViewDocumentInFolder

func (p *Persister) CanViewDocumentInFolder(labelID string) (hasPermission bool)

CanViewDocumentInFolder returns if the user has permission to view a document within the specified folder.

func (*Persister) CanViewFolder

func (p *Persister) CanViewFolder(folderID string) (hasPermission bool)

CanViewFolder returns if the user has permission to view the given folderID.

func (*Persister) ChangeDocumentLabel

func (p *Persister) ChangeDocumentLabel(document, label string) (err error)

ChangeDocumentLabel assigns the specified folder to the document.

func (*Persister) ChangeLabelOwner

func (p *Persister) ChangeLabelOwner(currentOwner, newOwner string) (err error)

ChangeLabelOwner transfer folder ownership.

func (*Persister) DeactiveUser

func (p *Persister) DeactiveUser(userID string) (err error)

DeactiveUser deletes the account record for the given userID and persister.Context.OrgID.

func (*Persister) DecrementBlockUsage added in v0.40.0

func (p *Persister) DecrementBlockUsage(id string) (err error)

DecrementBlockUsage decrements usage counter for content block.

func (*Persister) DeleteAccount

func (p *Persister) DeleteAccount(ID string) (rows int64, err error)

DeleteAccount deletes the database record in the account table for user ID.

func (*Persister) DeleteAttachment

func (p *Persister) DeleteAttachment(id string) (rows int64, err error)

DeleteAttachment deletes the id record from the database attachment table.

func (*Persister) DeleteBlock added in v0.40.0

func (p *Persister) DeleteBlock(id string) (rows int64, err error)

DeleteBlock removes reusable content block from database.

func (*Persister) DeleteDocument

func (p *Persister) DeleteDocument(documentID string) (rows int64, err error)

DeleteDocument delete the document pages in the database, updates the search subsystem, deletes the associated revisions and attachments, audits the deletion, then finally deletes the document itself.

func (*Persister) DeleteLabel

func (p *Persister) DeleteLabel(labelID string) (rows int64, err error)

DeleteLabel removes folder from the store.

func (*Persister) DeleteLabelRole

func (p *Persister) DeleteLabelRole(labelRoleID string) (rows int64, err error)

DeleteLabelRole deletes the labelRoleID record from the labelrole table.

func (*Persister) DeleteLabelRoles

func (p *Persister) DeleteLabelRoles(labelID string) (rows int64, err error)

DeleteLabelRoles deletes records from the labelrole table which have the given labelID.

func (p *Persister) DeleteLink(id string) (rows int64, err error)

DeleteLink removes saved link from the store.

func (*Persister) DeleteOrganization

func (p *Persister) DeleteOrganization(orgID string) (rows int64, err error)

DeleteOrganization deletes the orgID organization from the organization table.

func (*Persister) DeletePage

func (p *Persister) DeletePage(documentID, pageID string) (rows int64, err error)

DeletePage deletes the pageID page in the document. It then propagates that change into the search table, adds a delete the page revisions history, and audits that the page has been removed.

func (*Persister) DeletePageRevisions added in v0.35.0

func (p *Persister) DeletePageRevisions(pageID string) (rows int64, err error)

DeletePageRevisions deletes all of the page revision records for a given pageID.

func (*Persister) DeletePin added in v0.34.0

func (p *Persister) DeletePin(id string) (rows int64, err error)

DeletePin removes folder from the store.

func (*Persister) DeletePinnedDocument added in v0.34.0

func (p *Persister) DeletePinnedDocument(documentID string) (rows int64, err error)

DeletePinnedDocument removes any pins for specified document.

func (*Persister) DeletePinnedSpace added in v0.34.0

func (p *Persister) DeletePinnedSpace(spaceID string) (rows int64, err error)

DeletePinnedSpace removes any pins for specified space.

func (p *Persister) DeleteSourceDocumentLinks(documentID string) (rows int64, err error)

DeleteSourceDocumentLinks removes saved links for given document.

func (p *Persister) DeleteSourcePageLinks(pageID string) (rows int64, err error)

DeleteSourcePageLinks removes saved links for given source.

func (*Persister) DeleteUserFolderRoles

func (p *Persister) DeleteUserFolderRoles(labelID, userID string) (rows int64, err error)

DeleteUserFolderRoles removes all roles for the specified user, for the specified folder.

func (*Persister) ForgotUserPassword

func (p *Persister) ForgotUserPassword(email, token string) (err error)

ForgotUserPassword sets the password to ” and the reset field to token, for a user identified by email.

func (*Persister) GetAccountsByOrg

func (p *Persister) GetAccountsByOrg() (t []entity.Account, err error)

GetAccountsByOrg returns a slice of database account records, for all users in the client's organization.

func (*Persister) GetAttachment added in v0.28.0

func (p *Persister) GetAttachment(orgID, attachmentID string) (attachment entity.Attachment, err error)

GetAttachment returns the database attachment record specified by the parameters.

func (*Persister) GetAttachments

func (p *Persister) GetAttachments(docID string) (attachments []entity.Attachment, err error)

GetAttachments returns a slice containing the attachement records (excluding their data) for document docID, ordered by filename.

func (*Persister) GetAttachmentsWithData

func (p *Persister) GetAttachmentsWithData(docID string) (attachments []entity.Attachment, err error)

GetAttachmentsWithData returns a slice containing the attachement records (including their data) for document docID, ordered by filename.

func (*Persister) GetBlock added in v0.40.0

func (p *Persister) GetBlock(id string) (b entity.Block, err error)

GetBlock returns requested reusable content block.

func (*Persister) GetBlocksForSpace added in v0.40.0

func (p *Persister) GetBlocksForSpace(labelID string) (b []entity.Block, err error)

GetBlocksForSpace returns all reusable content scoped to given space.

func (*Persister) GetDocument

func (p *Persister) GetDocument(id string) (document entity.Document, err error)

GetDocument fetches the document record with the given id fromt the document table and audits that it has been got.

func (*Persister) GetDocumentList added in v0.40.0

func (p *Persister) GetDocumentList() (documents []entity.Document, err error)

GetDocumentList returns a slice containing the documents available as templates to the client's organisation, in title order.

func (*Persister) GetDocumentMeta

func (p *Persister) GetDocumentMeta(id string) (meta entity.DocumentMeta, err error)

GetDocumentMeta returns the metadata for a specified document.

func (p *Persister) GetDocumentOutboundLinks(documentID string) (links []entity.Link, err error)

GetDocumentOutboundLinks returns outbound links for specified document.

func (*Persister) GetDocumentPageMeta

func (p *Persister) GetDocumentPageMeta(documentID string, externalSourceOnly bool) (meta []entity.PageMeta, err error)

GetDocumentPageMeta returns the meta information associated with a document.

func (*Persister) GetDocumentRevisions added in v0.35.0

func (p *Persister) GetDocumentRevisions(documentID string) (revisions []entity.Revision, err error)

GetDocumentRevisions returns a slice of page revision records for a given document, in the order they were created. Then audits that the get-page-revisions action has occurred.

func (*Persister) GetDocumentTemplates

func (p *Persister) GetDocumentTemplates() (documents []entity.Document, err error)

GetDocumentTemplates returns a slice containing the documents available as templates to the client's organisation, in title order.

func (*Persister) GetDocuments

func (p *Persister) GetDocuments() (documents []entity.Document, err error)

GetDocuments returns a slice containg all of the the documents for the client's organisation, with the most recient first.

func (*Persister) GetDocumentsByFolder

func (p *Persister) GetDocumentsByFolder(folderID string) (documents []entity.Document, err error)

GetDocumentsByFolder returns a slice containing the documents for a given folder, most recient first.

func (*Persister) GetDocumentsByTag

func (p *Persister) GetDocumentsByTag(tag string) (documents []entity.Document, err error)

GetDocumentsByTag returns a slice containing the documents with the specified tag, in title order.

func (*Persister) GetFolderUsers

func (p *Persister) GetFolderUsers(folderID string) (users []entity.User, err error)

GetFolderUsers returns a slice containing all user records for given folder.

func (*Persister) GetFolderVisibility

func (p *Persister) GetFolderVisibility() (visibleTo []entity.FolderVisibility, err error)

GetFolderVisibility returns the list of people who can see shared folders.

func (*Persister) GetLabel

func (p *Persister) GetLabel(id string) (label entity.Label, err error)

GetLabel returns a folder from the store.

func (*Persister) GetLabelRoles

func (p *Persister) GetLabelRoles(labelID string) (roles []entity.LabelRole, err error)

GetLabelRoles returns a slice of labelrole records, for the given labelID in the client's organization, grouped by user.

func (*Persister) GetLabels

func (p *Persister) GetLabels() (labels []entity.Label, err error)

GetLabels returns folders that the user can see. Also handles which folders can be seen by anonymous users.

func (*Persister) GetNextPageSequence added in v0.40.0

func (p *Persister) GetNextPageSequence(documentID string) (maxSeq float64, err error)

GetNextPageSequence returns the next sequence numbner to use for a page in given document.

func (*Persister) GetOrganization

func (p *Persister) GetOrganization(id string) (org entity.Organization, err error)

GetOrganization returns the Organization reocrod from the organization database table with the given id.

func (*Persister) GetOrganizationByDomain

func (p *Persister) GetOrganizationByDomain(subdomain string) (org entity.Organization, err error)

GetOrganizationByDomain returns the organization matching a given URL subdomain.

func (*Persister) GetPage

func (p *Persister) GetPage(pageID string) (page entity.Page, err error)

GetPage returns the pageID page record from the page table.

func (p *Persister) GetPageLinks(documentID, pageID string) (links []entity.Link, err error)

GetPageLinks returns outbound links for specified page in document.

func (*Persister) GetPageMeta

func (p *Persister) GetPageMeta(pageID string) (meta entity.PageMeta, err error)

GetPageMeta returns the meta information associated with the page.

func (*Persister) GetPageRevision added in v0.35.0

func (p *Persister) GetPageRevision(revisionID string) (revision entity.Revision, err error)

GetPageRevision returns the revisionID page revision record.

func (*Persister) GetPageRevisions added in v0.35.0

func (p *Persister) GetPageRevisions(pageID string) (revisions []entity.Revision, err error)

GetPageRevisions returns a slice of page revision records for a given pageID, in the order they were created. Then audits that the get-page-revisions action has occurred.

func (*Persister) GetPages

func (p *Persister) GetPages(documentID string) (pages []entity.Page, err error)

GetPages returns a slice containing all the page records for a given documentID, in presentation sequence.

func (*Persister) GetPagesWhereIn

func (p *Persister) GetPagesWhereIn(documentID, inPages string) (pages []entity.Page, err error)

GetPagesWhereIn returns a slice, in presentation sequence, containing those page records for a given documentID where their refid is in the comma-separated list passed as inPages.

func (*Persister) GetPagesWithoutContent

func (p *Persister) GetPagesWithoutContent(documentID string) (pages []entity.Page, err error)

GetPagesWithoutContent returns a slice containing all the page records for a given documentID, in presentation sequence, but without the body field (which holds the HTML content).

func (*Persister) GetPin added in v0.34.0

func (p *Persister) GetPin(id string) (pin entity.Pin, err error)

GetPin returns requested pinned item.

func (*Persister) GetPublicDocuments

func (p *Persister) GetPublicDocuments(orgID string) (documents []entity.SitemapDocument, err error)

GetPublicDocuments returns a slice of SitemapDocument records, holding documents in folders of type 1 (entity.TemplateTypePublic).

func (*Persister) GetPublicFolders

func (p *Persister) GetPublicFolders(orgID string) (labels []entity.Label, err error)

GetPublicFolders returns folders that anyone can see.

func (*Persister) GetUser

func (p *Persister) GetUser(id string) (user entity.User, err error)

GetUser returns the user record for the given id.

func (*Persister) GetUserAccount

func (p *Persister) GetUserAccount(userID string) (account entity.Account, err error)

GetUserAccount returns the databse account record corresponding to the given userID, using the client's current organizaion.

func (*Persister) GetUserAccounts

func (p *Persister) GetUserAccounts(userID string) (t []entity.Account, err error)

GetUserAccounts returns a slice of database account records, for all organizations that the userID is a member of, in organization title order.

func (*Persister) GetUserByDomain

func (p *Persister) GetUserByDomain(domain, email string) (user entity.User, err error)

GetUserByDomain matches user by email and domain.

func (*Persister) GetUserByEmail

func (p *Persister) GetUserByEmail(email string) (user entity.User, err error)

GetUserByEmail returns a single row match on email.

func (*Persister) GetUserBySerial

func (p *Persister) GetUserBySerial(serial string) (user entity.User, err error)

GetUserBySerial is used to retrieve a user via their temporary password salt value! This occurs when we you share a folder with a new user and they have to complete the onboarding process.

func (*Persister) GetUserByToken

func (p *Persister) GetUserByToken(token string) (user entity.User, err error)

GetUserByToken returns a user record given a reset token value.

func (*Persister) GetUserLabelRoles

func (p *Persister) GetUserLabelRoles() (roles []entity.LabelRole, err error)

GetUserLabelRoles returns a slice of labelrole records, for both the client's user and organization, and those label roles that exist for all users in the client's organization.

func (*Persister) GetUserPins added in v0.34.0

func (p *Persister) GetUserPins(userID string) (pins []entity.Pin, err error)

GetUserPins returns pinned items for specified user.

func (*Persister) GetUsersForOrganization

func (p *Persister) GetUsersForOrganization() (users []entity.User, err error)

GetUsersForOrganization returns a slice containing all of the user records for the organizaiton identified in the Persister.

func (*Persister) HasOrgAccount

func (p *Persister) HasOrgAccount(orgID, userID string) bool

HasOrgAccount returns if the given orgID has valid userID.

func (*Persister) IncrementBlockUsage added in v0.40.0

func (p *Persister) IncrementBlockUsage(id string) (err error)

IncrementBlockUsage increments usage counter for content block.

func (p *Persister) MarkOrphanAttachmentLink(attachmentID string) (err error)

MarkOrphanAttachmentLink marks all link records referencing specified attachment.

func (p *Persister) MarkOrphanDocumentLink(documentID string) (err error)

MarkOrphanDocumentLink marks all link records referencing specified document.

func (p *Persister) MarkOrphanPageLink(pageID string) (err error)

MarkOrphanPageLink marks all link records referencing specified page.

func (*Persister) MoveDocumentLabel

func (p *Persister) MoveDocumentLabel(id, move string) (err error)

MoveDocumentLabel changes the label for client's organization's documents which have label "id", to "move". Then audits that move.

func (*Persister) MoveLabelRoles

func (p *Persister) MoveLabelRoles(previousLabel, newLabel string) (err error)

MoveLabelRoles changes the labelid for an organization's labelrole records from previousLabel to newLabel.

func (*Persister) RemoveBlockReference added in v0.40.0

func (p *Persister) RemoveBlockReference(id string) (err error)

RemoveBlockReference clears page.blockid for given blockID.

func (*Persister) RemoveOrganization

func (p *Persister) RemoveOrganization(orgID string) (err error)

RemoveOrganization sets the orgID organization to be inactive, thus executing a "soft delete" operation.

func (*Persister) SearchDocument

func (p *Persister) SearchDocument(keywords string) (results []entity.DocumentSearch, err error)

SearchDocument searches the documents that the client is allowed to see, using the keywords search string, then audits that search. Visible documents include both those in the client's own organisation and those that are public, or whose visibility includes the client.

func (*Persister) SearchLinkCandidates added in v0.28.0

func (p *Persister) SearchLinkCandidates(keywords string) (docs []entity.LinkCandidate,
	pages []entity.LinkCandidate, attachments []entity.LinkCandidate, err error)

SearchLinkCandidates returns matching documents, sections and attachments using keywords.

func (*Persister) SetupOrganization

func (p *Persister) SetupOrganization(company, title, message, domain, email string) (entity.Organization, error)

SetupOrganization creates "tenant" record in database.

func (*Persister) UpdateAccount

func (p *Persister) UpdateAccount(account entity.Account) (err error)

UpdateAccount updates the database record for the given account to the given values.

func (*Persister) UpdateBlock added in v0.40.0

func (p *Persister) UpdateBlock(b entity.Block) (err error)

UpdateBlock updates existing reusable content block item.

func (*Persister) UpdateDocument

func (p *Persister) UpdateDocument(document entity.Document) (err error)

UpdateDocument changes the given document record to the new values, updates search information and audits the action.

func (*Persister) UpdateLabel

func (p *Persister) UpdateLabel(label entity.Label) (err error)

UpdateLabel saves folder changes.

func (*Persister) UpdateOrganization

func (p *Persister) UpdateOrganization(org entity.Organization) (err error)

UpdateOrganization updates the given organization record in the database to the values supplied.

func (*Persister) UpdatePage

func (p *Persister) UpdatePage(page entity.Page, refID, userID string, skipRevision bool) (err error)

UpdatePage saves changes to the database and handles recording of revisions. Not all updates result in a revision being recorded hence the parameter.

func (*Persister) UpdatePageLevel

func (p *Persister) UpdatePageLevel(documentID, pageID string, level int) (err error)

UpdatePageLevel changes the heading level of the pageID page in the document. It then propagates that change into the search table and audits that it has occurred.

func (*Persister) UpdatePageMeta

func (p *Persister) UpdatePageMeta(meta entity.PageMeta, updateUserID bool) (err error)

UpdatePageMeta persists meta information associated with a document page.

func (*Persister) UpdatePageSequence

func (p *Persister) UpdatePageSequence(documentID, pageID string, sequence float64) (err error)

UpdatePageSequence changes the presentation sequence of the pageID page in the document. It then propagates that change into the search table and audits that it has occurred.

func (*Persister) UpdatePin added in v0.34.0

func (p *Persister) UpdatePin(pin entity.Pin) (err error)

UpdatePin updates existing pinned item.

func (*Persister) UpdatePinSequence added in v0.34.0

func (p *Persister) UpdatePinSequence(pinID string, sequence int) (err error)

UpdatePinSequence updates existing pinned item sequence number

func (*Persister) UpdateUser

func (p *Persister) UpdateUser(user entity.User) (err error)

UpdateUser updates the user table using the given replacement user record.

func (*Persister) UpdateUserPassword

func (p *Persister) UpdateUserPassword(userID, salt, password string) (err error)

UpdateUserPassword updates a user record with new password and salt values.

type SearchManager

type SearchManager struct {
	// contains filtered or unexported fields
}

SearchManager type provides the datastructure for the queues of activity to be serialized through a single background goroutine. NOTE if the queue becomes full, the system will trigger the rebuilding entire files in order to clear the backlog.

func (*SearchManager) Add

func (m *SearchManager) Add(request *databaseRequest, page entity.Page, id string) (err error)

Add should be called when a new page is added to a document.

func (*SearchManager) Delete

func (m *SearchManager) Delete(request *databaseRequest, documentID, pageID string) (rows int64, err error)

Delete should be called after a page has been deleted.

func (*SearchManager) DeleteDocument

func (m *SearchManager) DeleteDocument(request *databaseRequest, documentID string) (err error)

DeleteDocument should be called after a document record has been deleted.

func (*SearchManager) GetPageContext

func (m *SearchManager) GetPageContext(request *databaseRequest, pageID string, existingContext []string) ([]string, error)

GetPageContext is called to get the context of a page in terms of an headings hierarchy.

func (*SearchManager) Update

func (m *SearchManager) Update(request *databaseRequest, page entity.Page) (err error)

Update should be called after a page record has been updated.

func (*SearchManager) UpdateDocument

func (m *SearchManager) UpdateDocument(request *databaseRequest, document entity.Document) (err error)

UpdateDocument should be called after a document record has been updated.

func (*SearchManager) UpdateLevel

func (m *SearchManager) UpdateLevel(request *databaseRequest, documentID, pageID string, level int) (err error)

UpdateLevel should be called after the level of a page has been changed.

func (*SearchManager) UpdateSequence

func (m *SearchManager) UpdateSequence(request *databaseRequest, documentID, pageID string, sequence float64) (err error)

UpdateSequence should be called after a page record has been resequenced.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL