app

package
v3.7.0 Latest Latest
Warning

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

Go to latest
Published: Mar 14, 2017 License: AGPL-3.0, Apache-2.0 Imports: 57 Imported by: 0

Documentation

Index

Constants

View Source
const (
	DAY_MILLISECONDS   = 24 * 60 * 60 * 1000
	MONTH_MILLISECONDS = 31 * DAY_MILLISECONDS
)
View Source
const (
	SEGMENT_KEY = "fwb7VPbFeQ7SKp3wHm1RzFUuXZudqVok"

	TRACK_CONFIG_SERVICE      = "config_service"
	TRACK_CONFIG_TEAM         = "config_team"
	TRACK_CONFIG_SQL          = "config_sql"
	TRACK_CONFIG_LOG          = "config_log"
	TRACK_CONFIG_FILE         = "config_file"
	TRACK_CONFIG_RATE         = "config_rate"
	TRACK_CONFIG_EMAIL        = "config_email"
	TRACK_CONFIG_PRIVACY      = "config_privacy"
	TRACK_CONFIG_OAUTH        = "config_oauth"
	TRACK_CONFIG_LDAP         = "config_ldap"
	TRACK_CONFIG_COMPLIANCE   = "config_compliance"
	TRACK_CONFIG_LOCALIZATION = "config_localization"
	TRACK_CONFIG_SAML         = "config_saml"
	TRACK_CONFIG_PASSWORD     = "config_password"
	TRACK_CONFIG_CLUSTER      = "config_cluster"
	TRACK_CONFIG_METRICS      = "config_metrics"
	TRACK_CONFIG_WEBRTC       = "config_webrtc"
	TRACK_CONFIG_SUPPORT      = "config_support"
	TRACK_CONFIG_NATIVEAPP    = "config_nativeapp"
	TRACK_CONFIG_ANALYTICS    = "config_analytics"

	TRACK_ACTIVITY = "activity"
	TRACK_LICENSE  = "license"
	TRACK_SERVER   = "server"
)
View Source
const (
	/*
	  EXIF Image Orientations
	  1        2       3      4         5            6           7          8

	  888888  888888      88  88      8888888888  88                  88  8888888888
	  88          88      88  88      88  88      88  88          88  88      88  88
	  8888      8888    8888  8888    88          8888888888  8888888888          88
	  88          88      88  88
	  88          88  888888  888888
	*/
	Upright            = 1
	UprightMirrored    = 2
	UpsideDown         = 3
	UpsideDownMirrored = 4
	RotatedCWMirrored  = 5
	RotatedCCW         = 6
	RotatedCCWMirrored = 7
	RotatedCW          = 8

	MaxImageSize = 6048 * 4032 // 24 megapixels, roughly 36MB as a raw image
)
View Source
const (
	SECURITY_URL           = "https://d7zmvsa9e04kk.cloudfront.net"
	SECURITY_UPDATE_PERIOD = 86400000 // 24 hours in milliseconds.

	PROP_SECURITY_ID                = "id"
	PROP_SECURITY_CATEGORY          = "c"
	VAL_SECURITY_CATEGORY_DEFAULT   = "d"
	PROP_SECURITY_BUILD             = "b"
	PROP_SECURITY_ENTERPRISE_READY  = "be"
	PROP_SECURITY_DATABASE          = "db"
	PROP_SECURITY_OS                = "os"
	PROP_SECURITY_USER_COUNT        = "uc"
	PROP_SECURITY_TEAM_COUNT        = "tc"
	PROP_SECURITY_ACTIVE_USER_COUNT = "auc"
	PROP_SECURITY_UNIT_TESTS        = "ut"
)
View Source
const (
	WRITE_WAIT                = 30 * time.Second
	PONG_WAIT                 = 100 * time.Second
	PING_PERIOD               = (PONG_WAIT * 6) / 10
	AUTH_TIMEOUT              = 5 * time.Second
	WEBCONN_MEMBER_CACHE_TIME = 1000 * 60 * 30 // 30 minutes
)
View Source
const (
	TRIGGERWORDS_FULL       = 0
	TRIGGERWORDS_STARTSWITH = 1
)
View Source
const (
	EMAIL_BATCHING_TASK_NAME = "Email Batching"
)
View Source
const TIME_TO_WAIT_FOR_CONNECTIONS_TO_CLOSE_ON_SERVER_SHUTDOWN = time.Second

Variables

This section is empty.

Functions

func ActivateMfa

func ActivateMfa(userId, token string) *model.AppError

func AddDirectChannels

func AddDirectChannels(teamId string, user *model.User) *model.AppError

func AddNotificationEmailToBatch

func AddNotificationEmailToBatch(user *model.User, post *model.Post, team *model.Team) *model.AppError

func AddSamlCertificate

func AddSamlCertificate(fileData *multipart.FileHeader) *model.AppError

func AddSessionToCache

func AddSessionToCache(session *model.Session)

func AddStatusCache

func AddStatusCache(status *model.Status)

func AddStatusCacheSkipClusterSend

func AddStatusCacheSkipClusterSend(status *model.Status)

func AddUserToChannel

func AddUserToChannel(user *model.User, channel *model.Channel) (*model.ChannelMember, *model.AppError)

func AddUserToTeam

func AddUserToTeam(teamId string, userId string, siteURL string) (*model.Team, *model.AppError)

func AddUserToTeamByHash

func AddUserToTeamByHash(userId string, hash string, data string, siteURL string) (*model.Team, *model.AppError)

func AddUserToTeamByInviteId

func AddUserToTeamByInviteId(inviteId string, userId string, siteURL string) (*model.Team, *model.AppError)

func AddUserToTeamByTeamId

func AddUserToTeamByTeamId(teamId string, user *model.User, siteURL string) *model.AppError

func AttachDeviceId

func AttachDeviceId(sessionId string, deviceId string, expiresAt int64) *model.AppError

func AuthenticateUserForLogin

func AuthenticateUserForLogin(id, loginId, password, mfaToken, deviceId string, ldapOnly bool) (*model.User, *model.AppError)

func AutocompleteUsersInChannel

func AutocompleteUsersInChannel(teamId string, channelId string, term string, searchOptions map[string]bool) (*model.UserAutocompleteInChannel, *model.AppError)

func AutocompleteUsersInTeam

func AutocompleteUsersInTeam(teamId string, term string, searchOptions map[string]bool) (*model.UserAutocompleteInTeam, *model.AppError)

func BulkImport

func BulkImport(fileReader io.Reader, dryRun bool) (*model.AppError, int)

func CheckIfRolesGrantPermission

func CheckIfRolesGrantPermission(roles []string, permissionId string) bool

func CheckPasswordAndAllCriteria

func CheckPasswordAndAllCriteria(user *model.User, password string, mfaToken string) *model.AppError

func CheckUserAdditionalAuthenticationCriteria

func CheckUserAdditionalAuthenticationCriteria(user *model.User, mfaToken string) *model.AppError

func CheckUserDomain

func CheckUserDomain(user *model.User, domains string) bool

Check that a user's email domain matches a list of space-delimited domains as a string.

func CheckUserMfa

func CheckUserMfa(user *model.User, token string) *model.AppError

func ClearPushNotification

func ClearPushNotification(userId string, channelId string) *model.AppError

func ClearSessionCacheForUser

func ClearSessionCacheForUser(userId string)

func ClearSessionCacheForUserSkipClusterSend

func ClearSessionCacheForUserSkipClusterSend(userId string)

func ClearStatusCache

func ClearStatusCache()

func CloseBody

func CloseBody(r *http.Response)

func CreateChannel

func CreateChannel(channel *model.Channel, addMember bool) (*model.Channel, *model.AppError)

func CreateChannelWithUser

func CreateChannelWithUser(channel *model.Channel, userId string) (*model.Channel, *model.AppError)

func CreateCommandPost

func CreateCommandPost(post *model.Post, teamId string, response *model.CommandResponse, siteURL string) (*model.Post, *model.AppError)

func CreateDefaultChannels

func CreateDefaultChannels(teamId string) ([]*model.Channel, *model.AppError)

func CreateDirectChannel

func CreateDirectChannel(userId string, otherUserId string) (*model.Channel, *model.AppError)

func CreateGroupChannel

func CreateGroupChannel(userIds []string) (*model.Channel, *model.AppError)

func CreateIncomingWebhookForChannel

func CreateIncomingWebhookForChannel(creatorId string, channel *model.Channel, hook *model.IncomingWebhook) (*model.IncomingWebhook, *model.AppError)

func CreateOAuthUser

func CreateOAuthUser(service string, userData io.Reader, teamId string, siteURL string) (*model.User, *model.AppError)

func CreateOutgoingWebhook

func CreateOutgoingWebhook(hook *model.OutgoingWebhook) (*model.OutgoingWebhook, *model.AppError)

func CreatePasswordRecovery

func CreatePasswordRecovery(userId string) (*model.PasswordRecovery, *model.AppError)

func CreatePost

func CreatePost(post *model.Post, teamId string, triggerWebhooks bool, siteURL string) (*model.Post, *model.AppError)

func CreatePostAsUser

func CreatePostAsUser(post *model.Post, siteURL string) (*model.Post, *model.AppError)

func CreateProfileImage

func CreateProfileImage(username string, userId string) ([]byte, *model.AppError)

func CreateSession

func CreateSession(session *model.Session) (*model.Session, *model.AppError)

func CreateTeam

func CreateTeam(team *model.Team) (*model.Team, *model.AppError)

func CreateTeamWithUser

func CreateTeamWithUser(team *model.Team, userId string, siteURL string) (*model.Team, *model.AppError)

func CreateUser

func CreateUser(user *model.User) (*model.User, *model.AppError)

func CreateUserFromSignup

func CreateUserFromSignup(user *model.User, siteURL string) (*model.User, *model.AppError)

func CreateUserWithHash

func CreateUserWithHash(user *model.User, hash string, data string, siteURL string) (*model.User, *model.AppError)

func CreateUserWithInviteId

func CreateUserWithInviteId(user *model.User, inviteId string, siteURL string) (*model.User, *model.AppError)

func CreateWebhookPost

func CreateWebhookPost(userId, teamId, channelId, text, overrideUsername, overrideIconUrl string, props model.StringInterface, postType string, siteURL string) (*model.Post, *model.AppError)

func DeactivateMfa

func DeactivateMfa(userId string) *model.AppError

func DeleteChannel

func DeleteChannel(channel *model.Channel, userId string, siteURL string) *model.AppError

func DeleteFlaggedPosts

func DeleteFlaggedPosts(postId string)

func DeleteIncomingWebhook

func DeleteIncomingWebhook(hookId string) *model.AppError

func DeleteOutgoingWebhook

func DeleteOutgoingWebhook(hookId string) *model.AppError

func DeletePasswordRecoveryForUser

func DeletePasswordRecoveryForUser(userId string) *model.AppError

func DeletePost

func DeletePost(postId string) (*model.Post, *model.AppError)

func DeletePostFiles

func DeletePostFiles(post *model.Post)

func DeletePreferences

func DeletePreferences(userId string, preferences model.Preferences) (bool, *model.AppError)

func DoLogin

func DoLogin(w http.ResponseWriter, r *http.Request, user *model.User, deviceId string) (*model.Session, *model.AppError)

func DoSecurityUpdateCheck

func DoSecurityUpdateCheck()

func DoUploadFile

func DoUploadFile(teamId string, channelId string, userId string, rawFilename string, data []byte) (*model.FileInfo, *model.AppError)

func DoesNotifyPropsAllowPushNotification

func DoesNotifyPropsAllowPushNotification(user *model.User, channelNotifyProps model.StringMap, post *model.Post, wasMentioned bool) bool

func DoesStatusAllowPushNotification

func DoesStatusAllowPushNotification(userNotifyProps model.StringMap, status *model.Status, channelId string) bool

func FindTeamByName

func FindTeamByName(name string) bool

func FindTeamIdForFilename

func FindTeamIdForFilename(post *model.Post, filename string) string
func GeneratePublicLink(siteURL string, info *model.FileInfo) string

func GeneratePublicLinkHash

func GeneratePublicLinkHash(fileId, salt string) string

func GetAllOpenTeams

func GetAllOpenTeams() ([]*model.Team, *model.AppError)

func GetAllOpenTeamsPage

func GetAllOpenTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError)

func GetAllStatuses

func GetAllStatuses() map[string]*model.Status

func GetAllTeams

func GetAllTeams() ([]*model.Team, *model.AppError)

func GetAllTeamsPage

func GetAllTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError)

func GetAnalytics

func GetAnalytics(name string, teamId string) (model.AnalyticsRows, *model.AppError)

func GetAudits

func GetAudits(userId string, limit int) (model.Audits, *model.AppError)

func GetAuditsPage

func GetAuditsPage(userId string, page int, perPage int) (model.Audits, *model.AppError)

func GetBrandImage

func GetBrandImage() ([]byte, *model.AppError)

func GetChannel

func GetChannel(channelId string) (*model.Channel, *model.AppError)

func GetChannelByName

func GetChannelByName(channelName, teamId string) (*model.Channel, *model.AppError)

func GetChannelByNameForTeamName

func GetChannelByNameForTeamName(channelName, teamName string) (*model.Channel, *model.AppError)

func GetChannelCounts

func GetChannelCounts(teamId string, userId string) (*model.ChannelCounts, *model.AppError)

func GetChannelMember

func GetChannelMember(channelId string, userId string) (*model.ChannelMember, *model.AppError)

func GetChannelMemberCount

func GetChannelMemberCount(channelId string) (int64, *model.AppError)

func GetChannelMembersByIds

func GetChannelMembersByIds(channelId string, userIds []string) (*model.ChannelMembers, *model.AppError)

func GetChannelMembersForUser

func GetChannelMembersForUser(teamId string, userId string) (*model.ChannelMembers, *model.AppError)

func GetChannelMembersPage

func GetChannelMembersPage(channelId string, page, perPage int) (*model.ChannelMembers, *model.AppError)

func GetChannelsForUser

func GetChannelsForUser(teamId string, userId string) (*model.ChannelList, *model.AppError)

func GetChannelsUserNotIn

func GetChannelsUserNotIn(teamId string, userId string, offset int, limit int) (*model.ChannelList, *model.AppError)

func GetClusterStatus

func GetClusterStatus() []*model.ClusterInfo

func GetComplianceFile

func GetComplianceFile(job *model.Compliance) ([]byte, *model.AppError)

func GetComplianceReport

func GetComplianceReport(reportId string) (*model.Compliance, *model.AppError)

func GetComplianceReports

func GetComplianceReports() (model.Compliances, *model.AppError)

func GetConfig

func GetConfig() *model.Config

func GetExplicitMentions

func GetExplicitMentions(message string, keywords map[string][]string) (map[string]bool, []string, bool, bool, bool)

Given a message and a map mapping mention keywords to the users who use them, returns a map of mentioned users and a slice of potential mention users not in the channel and whether or not @here was mentioned.

func GetFileInfo

func GetFileInfo(fileId string) (*model.FileInfo, *model.AppError)

func GetFileInfosForPost

func GetFileInfosForPost(postId string, readFromMaster bool) ([]*model.FileInfo, *model.AppError)

func GetFlaggedPosts

func GetFlaggedPosts(userId string, offset int, limit int) (*model.PostList, *model.AppError)

func GetIncomingWebhook

func GetIncomingWebhook(hookId string) (*model.IncomingWebhook, *model.AppError)

func GetIncomingWebhooksForTeamPage

func GetIncomingWebhooksForTeamPage(teamId string, page, perPage int) ([]*model.IncomingWebhook, *model.AppError)

func GetIncomingWebhooksPage

func GetIncomingWebhooksPage(page, perPage int) ([]*model.IncomingWebhook, *model.AppError)

func GetInfoForFilename

func GetInfoForFilename(post *model.Post, teamId string, filename string) *model.FileInfo

func GetLogs

func GetLogs() ([]string, *model.AppError)

func GetLogsSkipSend

func GetLogsSkipSend() ([]string, *model.AppError)

func GetMentionKeywordsInChannel

func GetMentionKeywordsInChannel(profiles map[string]*model.User) map[string][]string

Given a map of user IDs to profiles, returns a list of mention keywords for all users in the channel.

func GetMessageForNotification

func GetMessageForNotification(post *model.Post, translateFunc i18n.TranslateFunc) string

func GetNumberOfChannelsOnTeam

func GetNumberOfChannelsOnTeam(teamId string) (int, *model.AppError)

func GetOpenGraphMetadata

func GetOpenGraphMetadata(url string) *opengraph.OpenGraph

func GetOutgoingWebhook

func GetOutgoingWebhook(hookId string) (*model.OutgoingWebhook, *model.AppError)

func GetOutgoingWebhooksForTeamPage

func GetOutgoingWebhooksForTeamPage(teamId string, page, perPage int) ([]*model.OutgoingWebhook, *model.AppError)

func GetPasswordRecovery

func GetPasswordRecovery(code string) (*model.PasswordRecovery, *model.AppError)

func GetPermalinkPost

func GetPermalinkPost(postId string, userId string, siteURL string) (*model.PostList, *model.AppError)

func GetPostThread

func GetPostThread(postId string) (*model.PostList, *model.AppError)

func GetPosts

func GetPosts(channelId string, offset int, limit int) (*model.PostList, *model.AppError)

func GetPostsAroundPost

func GetPostsAroundPost(postId, channelId string, offset, limit int, before bool) (*model.PostList, *model.AppError)

func GetPostsEtag

func GetPostsEtag(channelId string) string

func GetPostsPage

func GetPostsPage(channelId string, page int, perPage int) (*model.PostList, *model.AppError)

func GetPostsSince

func GetPostsSince(channelId string, time int64) (*model.PostList, *model.AppError)

func GetPreferenceByCategoryAndNameForUser

func GetPreferenceByCategoryAndNameForUser(userId string, category string, preferenceName string) (*model.Preference, *model.AppError)

func GetPreferenceByCategoryForUser

func GetPreferenceByCategoryForUser(userId string, category string) (model.Preferences, *model.AppError)

func GetPreferencesForUser

func GetPreferencesForUser(userId string) (model.Preferences, *model.AppError)

func GetProfileImage

func GetProfileImage(user *model.User) ([]byte, bool, *model.AppError)

func GetProtocol

func GetProtocol(r *http.Request) string

func GetRecentlyActiveUsersForTeam

func GetRecentlyActiveUsersForTeam(teamId string) (map[string]*model.User, *model.AppError)

func GetSamlCertificateStatus

func GetSamlCertificateStatus() map[string]interface{}

func GetSamlMetadata

func GetSamlMetadata() (string, *model.AppError)

func GetSession

func GetSession(token string) (*model.Session, *model.AppError)

func GetSessions

func GetSessions(userId string) ([]*model.Session, *model.AppError)

func GetSinglePost

func GetSinglePost(postId string) (*model.Post, *model.AppError)

func GetStatus

func GetStatus(userId string) (*model.Status, *model.AppError)

func GetStatusFromCache

func GetStatusFromCache(userId string) *model.Status

func GetStatusesByIds

func GetStatusesByIds(userIds []string) (map[string]interface{}, *model.AppError)

func GetTeam

func GetTeam(teamId string) (*model.Team, *model.AppError)

func GetTeamByInviteId

func GetTeamByInviteId(inviteId string) (*model.Team, *model.AppError)

func GetTeamByName

func GetTeamByName(name string) (*model.Team, *model.AppError)

func GetTeamMember

func GetTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError)

func GetTeamMembers

func GetTeamMembers(teamId string, offset int, limit int) ([]*model.TeamMember, *model.AppError)

func GetTeamMembersByIds

func GetTeamMembersByIds(teamId string, userIds []string) ([]*model.TeamMember, *model.AppError)

func GetTeamMembersForUser

func GetTeamMembersForUser(userId string) ([]*model.TeamMember, *model.AppError)

func GetTeamStats

func GetTeamStats(teamId string) (*model.TeamStats, *model.AppError)

func GetTeamsForUser

func GetTeamsForUser(userId string) ([]*model.Team, *model.AppError)

func GetTeamsUnreadForUser

func GetTeamsUnreadForUser(teamId string, userId string) ([]*model.TeamUnread, *model.AppError)

func GetUser

func GetUser(userId string) (*model.User, *model.AppError)

func GetUserByAuth

func GetUserByAuth(authData *string, authService string) (*model.User, *model.AppError)

func GetUserByEmail

func GetUserByEmail(email string) (*model.User, *model.AppError)

func GetUserByUsername

func GetUserByUsername(username string) (*model.User, *model.AppError)

func GetUserForLogin

func GetUserForLogin(loginId string, onlyLdap bool) (*model.User, *model.AppError)

func GetUsers

func GetUsers(offset int, limit int) ([]*model.User, *model.AppError)

func GetUsersByIds

func GetUsersByIds(userIds []string, asAdmin bool) ([]*model.User, *model.AppError)

func GetUsersEtag

func GetUsersEtag() string

func GetUsersInChannel

func GetUsersInChannel(channelId string, offset int, limit int) ([]*model.User, *model.AppError)

func GetUsersInChannelMap

func GetUsersInChannelMap(channelId string, offset int, limit int, asAdmin bool) (map[string]*model.User, *model.AppError)

func GetUsersInChannelPage

func GetUsersInChannelPage(channelId string, page int, perPage int, asAdmin bool) ([]*model.User, *model.AppError)

func GetUsersInTeam

func GetUsersInTeam(teamId string, offset int, limit int) ([]*model.User, *model.AppError)

func GetUsersInTeamEtag

func GetUsersInTeamEtag(teamId string) string

func GetUsersInTeamMap

func GetUsersInTeamMap(teamId string, offset int, limit int, asAdmin bool) (map[string]*model.User, *model.AppError)

func GetUsersInTeamPage

func GetUsersInTeamPage(teamId string, page int, perPage int, asAdmin bool) ([]*model.User, *model.AppError)

func GetUsersMap

func GetUsersMap(offset int, limit int, asAdmin bool) (map[string]*model.User, *model.AppError)

func GetUsersNotInChannel

func GetUsersNotInChannel(teamId string, channelId string, offset int, limit int) ([]*model.User, *model.AppError)

func GetUsersNotInChannelMap

func GetUsersNotInChannelMap(teamId string, channelId string, offset int, limit int, asAdmin bool) (map[string]*model.User, *model.AppError)

func GetUsersNotInChannelPage

func GetUsersNotInChannelPage(teamId string, channelId string, page int, perPage int, asAdmin bool) ([]*model.User, *model.AppError)

func GetUsersPage

func GetUsersPage(page int, perPage int, asAdmin bool) ([]*model.User, *model.AppError)

func HandleImages

func HandleImages(previewPathList []string, thumbnailPathList []string, fileData [][]byte)

func HandleIncomingWebhook

func HandleIncomingWebhook(hookId string, req *model.IncomingWebhookRequest, siteURL string) *model.AppError

func HasPermissionTo

func HasPermissionTo(askingUserId string, permission *model.Permission) bool

func HasPermissionToChannel

func HasPermissionToChannel(askingUserId string, channelId string, permission *model.Permission) bool

func HasPermissionToChannelByPost

func HasPermissionToChannelByPost(askingUserId string, postId string, permission *model.Permission) bool

func HasPermissionToTeam

func HasPermissionToTeam(askingUserId string, teamId string, permission *model.Permission) bool

func HasPermissionToUser

func HasPermissionToUser(askingUserId string, userId string) bool

func HubRegister

func HubRegister(webConn *WebConn)

func HubStart

func HubStart()

func HubStop

func HubStop()

func HubUnregister

func HubUnregister(webConn *WebConn)

func ImportChannel

func ImportChannel(data *ChannelImportData, dryRun bool) *model.AppError

func ImportLine

func ImportLine(line LineImportData, dryRun bool) *model.AppError

func ImportPost

func ImportPost(data *PostImportData, dryRun bool) *model.AppError

func ImportTeam

func ImportTeam(data *TeamImportData, dryRun bool) *model.AppError

func ImportUser

func ImportUser(data *UserImportData, dryRun bool) *model.AppError

func ImportUserChannels

func ImportUserChannels(user *model.User, team *model.Team, data *[]UserChannelImportData) *model.AppError

func ImportUserTeams

func ImportUserTeams(username string, data *[]UserTeamImportData) *model.AppError

func InitEmailBatching

func InitEmailBatching()

func InitStores

func InitStores()

func InvalidateAllCaches

func InvalidateAllCaches() *model.AppError

func InvalidateAllCachesSkipSend

func InvalidateAllCachesSkipSend()

func InvalidateCacheForChannel

func InvalidateCacheForChannel(channel *model.Channel)

func InvalidateCacheForChannelByNameSkipClusterSend

func InvalidateCacheForChannelByNameSkipClusterSend(teamId, name string)

func InvalidateCacheForChannelMembers

func InvalidateCacheForChannelMembers(channelId string)

func InvalidateCacheForChannelMembersNotifyProps

func InvalidateCacheForChannelMembersNotifyProps(channelId string)

func InvalidateCacheForChannelMembersNotifyPropsSkipClusterSend

func InvalidateCacheForChannelMembersNotifyPropsSkipClusterSend(channelId string)

func InvalidateCacheForChannelMembersSkipClusterSend

func InvalidateCacheForChannelMembersSkipClusterSend(channelId string)

func InvalidateCacheForChannelPosts

func InvalidateCacheForChannelPosts(channelId string)

func InvalidateCacheForChannelPostsSkipClusterSend

func InvalidateCacheForChannelPostsSkipClusterSend(channelId string)

func InvalidateCacheForChannelSkipClusterSend

func InvalidateCacheForChannelSkipClusterSend(channelId string)

func InvalidateCacheForReactions

func InvalidateCacheForReactions(postId string)

func InvalidateCacheForReactionsSkipClusterSend

func InvalidateCacheForReactionsSkipClusterSend(postId string)

func InvalidateCacheForUser

func InvalidateCacheForUser(userId string)

func InvalidateCacheForUserSkipClusterSend

func InvalidateCacheForUserSkipClusterSend(userId string)

func InvalidateCacheForWebhook

func InvalidateCacheForWebhook(webhookId string)

func InvalidateCacheForWebhookSkipClusterSend

func InvalidateCacheForWebhookSkipClusterSend(webhookId string)

func InvalidateWebConnSessionCacheForUser

func InvalidateWebConnSessionCacheForUser(userId string)

func InviteNewUsersToTeam

func InviteNewUsersToTeam(emailList []string, teamId, senderId, siteURL string) *model.AppError

func IsFirstUserAccount

func IsFirstUserAccount() bool

func IsUserAway

func IsUserAway(lastActivityAt int64) bool

func IsUserSignUpAllowed

func IsUserSignUpAllowed() *model.AppError

func IsUsernameTaken

func IsUsernameTaken(name string) bool

Check if the username is already used by another user. Return false if the username is invalid.

func JoinChannel

func JoinChannel(channel *model.Channel, userId string, siteURL string) *model.AppError

func JoinDefaultChannels

func JoinDefaultChannels(teamId string, user *model.User, channelRole string, siteURL string) *model.AppError

func JoinUserToTeam

func JoinUserToTeam(team *model.Team, user *model.User, siteURL string) *model.AppError

func LeaveChannel

func LeaveChannel(channelId string, userId string, siteURL string) *model.AppError

func LeaveTeam

func LeaveTeam(team *model.Team, user *model.User) *model.AppError

func LinkUserToTeam

func LinkUserToTeam(user *model.User, team *model.Team)

func LoadLicense

func LoadLicense()

func MigrateFilenamesToFileInfos

func MigrateFilenamesToFileInfos(post *model.Post) []*model.FileInfo

Creates and stores FileInfos for a post created before the FileInfos table existed.

func MoveFile

func MoveFile(oldPath, newPath string) *model.AppError

func NewServer

func NewServer()

func OldImportChannel

func OldImportChannel(channel *model.Channel) *model.Channel

func OldImportFile

func OldImportFile(file io.Reader, teamId string, channelId string, userId string, fileName string) (*model.FileInfo, error)

func OldImportIncomingWebhookPost

func OldImportIncomingWebhookPost(post *model.Post, props model.StringInterface)

func OldImportPost

func OldImportPost(post *model.Post)

func OldImportUser

func OldImportUser(team *model.Team, user *model.User) *model.User

func PatchUser

func PatchUser(userId string, patch *model.UserPatch, siteURL string, asAdmin bool) (*model.User, *model.AppError)

func PermanentDeleteAllUsers

func PermanentDeleteAllUsers() *model.AppError

func PermanentDeleteChannel

func PermanentDeleteChannel(channel *model.Channel) *model.AppError

func PermanentDeleteTeam

func PermanentDeleteTeam(team *model.Team) *model.AppError

func PermanentDeleteUser

func PermanentDeleteUser(user *model.User) *model.AppError

func PostAddToChannelMessage

func PostAddToChannelMessage(user *model.User, addedUser *model.User, channel *model.Channel, siteURL string) *model.AppError

func PostRemoveFromChannelMessage

func PostRemoveFromChannelMessage(removerUserId string, removedUser *model.User, channel *model.Channel, siteURL string) *model.AppError

func PostUpdateChannelDisplayNameMessage

func PostUpdateChannelDisplayNameMessage(userId string, channelId string, teamId string, oldChannelDisplayName, newChannelDisplayName string, siteURL string) *model.AppError

func PostUpdateChannelHeaderMessage

func PostUpdateChannelHeaderMessage(userId string, channelId string, teamId string, oldChannelHeader, newChannelHeader string, siteURL string) *model.AppError

func PostUpdateChannelPurposeMessage

func PostUpdateChannelPurposeMessage(userId string, channelId string, teamId string, oldChannelPurpose string, newChannelPurpose string, siteURL string) *model.AppError

func Publish

func Publish(message *model.WebSocketEvent)

func PublishSkipClusterSend

func PublishSkipClusterSend(message *model.WebSocketEvent)

func ReadFile

func ReadFile(path string) ([]byte, *model.AppError)

func RecycleDatabaseConnection

func RecycleDatabaseConnection()

func RegenOutgoingWebhookToken

func RegenOutgoingWebhookToken(hook *model.OutgoingWebhook) (*model.OutgoingWebhook, *model.AppError)

func ReloadConfig

func ReloadConfig()

func RemoveLicense

func RemoveLicense() *model.AppError

func RemoveSamlCertificate

func RemoveSamlCertificate(filename string) *model.AppError

func RemoveUserFromChannel

func RemoveUserFromChannel(userIdToRemove string, removerUserId string, channel *model.Channel, siteURL string) *model.AppError

func RemoveUserFromTeam

func RemoveUserFromTeam(teamId string, userId string) *model.AppError

func ResetPasswordFromCode

func ResetPasswordFromCode(code, newPassword, siteURL string) *model.AppError

func ReturnWebSocketError

func ReturnWebSocketError(conn *WebConn, r *model.WebSocketRequest, err *model.AppError)

func RevokeAccessToken

func RevokeAccessToken(token string) *model.AppError

func RevokeAllSessions

func RevokeAllSessions(userId string) *model.AppError

func RevokeSession

func RevokeSession(session *model.Session) *model.AppError

func RevokeSessionById

func RevokeSessionById(sessionId string) *model.AppError

func RevokeSessionsForDeviceId

func RevokeSessionsForDeviceId(userId string, deviceId string, currentSessionId string) *model.AppError

func RevokeWebrtcToken

func RevokeWebrtcToken(sessionId string)

func SanitizeProfile

func SanitizeProfile(user *model.User, asAdmin bool)

func SaveBrandImage

func SaveBrandImage(imageData *multipart.FileHeader) *model.AppError

func SaveComplianceReport

func SaveComplianceReport(job *model.Compliance) (*model.Compliance, *model.AppError)

func SaveConfig

func SaveConfig(cfg *model.Config) *model.AppError

func SaveLicense

func SaveLicense(licenseBytes []byte) (*model.License, *model.AppError)

func SearchChannels

func SearchChannels(teamId string, term string) (*model.ChannelList, *model.AppError)

func SearchChannelsUserNotIn

func SearchChannelsUserNotIn(teamId string, userId string, term string) (*model.ChannelList, *model.AppError)

func SearchPostsInTeam

func SearchPostsInTeam(terms string, userId string, teamId string, isOrSearch bool) (*model.PostList, *model.AppError)

func SearchUsersInChannel

func SearchUsersInChannel(channelId string, term string, searchOptions map[string]bool) ([]*model.User, *model.AppError)

func SearchUsersInTeam

func SearchUsersInTeam(teamId string, term string, searchOptions map[string]bool) ([]*model.User, *model.AppError)

func SearchUsersNotInChannel

func SearchUsersNotInChannel(teamId string, channelId string, term string, searchOptions map[string]bool) ([]*model.User, *model.AppError)

func SendChangeUsernameEmail

func SendChangeUsernameEmail(oldUsername, newUsername, email, locale, siteURL string) *model.AppError

func SendDailyDiagnostics

func SendDailyDiagnostics()

func SendDiagnostic

func SendDiagnostic(event string, properties map[string]interface{})

func SendEmailChangeEmail

func SendEmailChangeEmail(oldEmail, newEmail, locale, siteURL string) *model.AppError

func SendEmailChangeVerifyEmail

func SendEmailChangeVerifyEmail(userId, newUserEmail, locale, siteURL string) *model.AppError

func SendEphemeralPost

func SendEphemeralPost(teamId, userId string, post *model.Post) *model.Post

func SendInviteEmails

func SendInviteEmails(team *model.Team, senderName string, invites []string, siteURL string)

func SendMfaChangeEmail

func SendMfaChangeEmail(email string, activated bool, locale, siteURL string) *model.AppError

func SendNotifications

func SendNotifications(post *model.Post, team *model.Team, channel *model.Channel, sender *model.User, siteURL string) ([]string, *model.AppError)

func SendPasswordChangeEmail

func SendPasswordChangeEmail(email, method, locale, siteURL string) *model.AppError

func SendPasswordReset

func SendPasswordReset(email string, siteURL string) (bool, *model.AppError)

func SendPasswordResetEmail

func SendPasswordResetEmail(email string, recovery *model.PasswordRecovery, locale, siteURL string) (bool, *model.AppError)

func SendSignInChangeEmail

func SendSignInChangeEmail(email, method, locale, siteURL string) *model.AppError

func SendVerifyEmail

func SendVerifyEmail(userId, userEmail, locale, siteURL string) *model.AppError

func SendWelcomeEmail

func SendWelcomeEmail(userId string, email string, verified bool, locale, siteURL string) *model.AppError

func SessionCacheLength

func SessionCacheLength() int

func SessionHasPermissionTo

func SessionHasPermissionTo(session model.Session, permission *model.Permission) bool

func SessionHasPermissionToChannel

func SessionHasPermissionToChannel(session model.Session, channelId string, permission *model.Permission) bool

func SessionHasPermissionToChannelByPost

func SessionHasPermissionToChannelByPost(session model.Session, postId string, permission *model.Permission) bool

func SessionHasPermissionToPost

func SessionHasPermissionToPost(session model.Session, postId string, permission *model.Permission) bool

func SessionHasPermissionToTeam

func SessionHasPermissionToTeam(session model.Session, teamId string, permission *model.Permission) bool

func SessionHasPermissionToUser

func SessionHasPermissionToUser(session model.Session, userId string) bool

func SetActiveChannel

func SetActiveChannel(userId string, channelId string) *model.AppError

func SetProfileImage

func SetProfileImage(userId string, imageData *multipart.FileHeader) *model.AppError

func SetStatusAwayIfNeeded

func SetStatusAwayIfNeeded(userId string, manual bool)

func SetStatusOffline

func SetStatusOffline(userId string, manual bool)

func SetStatusOnline

func SetStatusOnline(userId string, sessionId string, manual bool)

func ShouldSendPushNotification

func ShouldSendPushNotification(user *model.User, channelNotifyProps model.StringMap, wasMentioned bool, status *model.Status, post *model.Post) bool

func SlackAddBotUser

func SlackAddBotUser(teamId string, log *bytes.Buffer) *model.User

func SlackAddChannels

func SlackAddChannels(teamId string, slackchannels []SlackChannel, posts map[string][]SlackPost, users map[string]*model.User, uploads map[string]*zip.File, botUser *model.User, log *bytes.Buffer) map[string]*model.Channel

func SlackAddPosts

func SlackAddPosts(teamId string, channel *model.Channel, posts []SlackPost, users map[string]*model.User, uploads map[string]*zip.File, botUser *model.User)

func SlackAddUsers

func SlackAddUsers(teamId string, slackusers []SlackUser, log *bytes.Buffer) map[string]*model.User

func SlackConvertChannelMentions

func SlackConvertChannelMentions(channels []SlackChannel, posts map[string][]SlackPost) map[string][]SlackPost

func SlackConvertChannelName

func SlackConvertChannelName(channelName string) string

func SlackConvertPostsMarkup

func SlackConvertPostsMarkup(posts map[string][]SlackPost) map[string][]SlackPost

func SlackConvertTimeStamp

func SlackConvertTimeStamp(ts string) int64

func SlackConvertUserMentions

func SlackConvertUserMentions(users []SlackUser, posts map[string][]SlackPost) map[string][]SlackPost

func SlackImport

func SlackImport(fileData multipart.File, fileSize int64, teamID string) (*model.AppError, *bytes.Buffer)

func SlackSanitiseChannelProperties

func SlackSanitiseChannelProperties(channel model.Channel) model.Channel

func SlackUploadFile

func SlackUploadFile(sPost SlackPost, uploads map[string]*zip.File, teamId string, channelId string, userId string) (*model.FileInfo, bool)

func StartServer

func StartServer()

func StopServer

func StopServer()

func SyncLdap

func SyncLdap()

func TearDown

func TearDown()

func TestEmail

func TestEmail(userId string, cfg *model.Config) *model.AppError

func TestLdap

func TestLdap() *model.AppError

func TotalWebsocketConnections

func TotalWebsocketConnections() int

func UpdateActive

func UpdateActive(user *model.User, active bool) (*model.User, *model.AppError)

func UpdateActiveNoLdap

func UpdateActiveNoLdap(userId string, active bool) (*model.User, *model.AppError)

func UpdateChannel

func UpdateChannel(channel *model.Channel) (*model.Channel, *model.AppError)

func UpdateChannelLastViewedAt

func UpdateChannelLastViewedAt(channelIds []string, userId string) *model.AppError

func UpdateChannelMemberNotifyProps

func UpdateChannelMemberNotifyProps(data map[string]string, channelId string, userId string) (*model.ChannelMember, *model.AppError)

func UpdateChannelMemberRoles

func UpdateChannelMemberRoles(channelId string, userId string, newRoles string) (*model.ChannelMember, *model.AppError)

func UpdateIncomingWebhook

func UpdateIncomingWebhook(oldHook, updatedHook *model.IncomingWebhook) (*model.IncomingWebhook, *model.AppError)

func UpdateOAuthUserAttrs

func UpdateOAuthUserAttrs(userData io.Reader, user *model.User, provider einterfaces.OauthProvider, service string, siteURL string) *model.AppError

func UpdateOutgoingWebhook

func UpdateOutgoingWebhook(oldHook, updatedHook *model.OutgoingWebhook) (*model.OutgoingWebhook, *model.AppError)

func UpdatePassword

func UpdatePassword(user *model.User, newPassword string) *model.AppError

func UpdatePasswordAsUser

func UpdatePasswordAsUser(userId, currentPassword, newPassword, siteURL string) *model.AppError

func UpdatePasswordByUserIdSendEmail

func UpdatePasswordByUserIdSendEmail(userId, newPassword, method, siteURL string) *model.AppError

func UpdatePasswordSendEmail

func UpdatePasswordSendEmail(user *model.User, newPassword, method, siteURL string) *model.AppError

func UpdatePost

func UpdatePost(post *model.Post) (*model.Post, *model.AppError)

func UpdatePreferences

func UpdatePreferences(preferences model.Preferences) (bool, *model.AppError)

func UpdateTeam

func UpdateTeam(team *model.Team) (*model.Team, *model.AppError)

func UpdateTeamMemberRoles

func UpdateTeamMemberRoles(teamId string, userId string, newRoles string) (*model.TeamMember, *model.AppError)

func UpdateUser

func UpdateUser(user *model.User, siteURL string, sendNotifications bool) (*model.User, *model.AppError)

func UpdateUserAsUser

func UpdateUserAsUser(user *model.User, siteURL string, asAdmin bool) (*model.User, *model.AppError)

func UpdateUserNotifyProps

func UpdateUserNotifyProps(userId string, props map[string]string, siteURL string) (*model.User, *model.AppError)

func UpdateUserRoles

func UpdateUserRoles(userId string, newRoles string) (*model.User, *model.AppError)

func UploadFiles

func UploadFiles(teamId string, channelId string, userId string, fileHeaders []*multipart.FileHeader, clientIds []string) (*model.FileUploadResponse, *model.AppError)

func VerifyUserEmail

func VerifyUserEmail(userId string) *model.AppError

func ViewChannel

func ViewChannel(view *model.ChannelView, userId string, clearPushNotifications bool) *model.AppError

func WaitForChannelMembership

func WaitForChannelMembership(channelId string, userId string)

func WriteFile

func WriteFile(f []byte, path string) *model.AppError

Types

type ChannelImportData

type ChannelImportData struct {
	Team        *string `json:"team"`
	Name        *string `json:"name"`
	DisplayName *string `json:"display_name"`
	Type        *string `json:"type"`
	Header      *string `json:"header"`
	Purpose     *string `json:"purpose"`
}

type CorsWrapper

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

func (*CorsWrapper) ServeHTTP

func (cw *CorsWrapper) ServeHTTP(w http.ResponseWriter, r *http.Request)

type EmailBatchingJob

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

func MakeEmailBatchingJob

func MakeEmailBatchingJob(bufferSize int) *EmailBatchingJob

func (*EmailBatchingJob) Add

func (job *EmailBatchingJob) Add(user *model.User, post *model.Post, team *model.Team) bool

func (*EmailBatchingJob) CheckPendingEmails

func (job *EmailBatchingJob) CheckPendingEmails()

func (*EmailBatchingJob) Start

func (job *EmailBatchingJob) Start()

type Hub

type Hub struct {
	ExplicitStop bool
	// contains filtered or unexported fields
}

func GetHubForUserId

func GetHubForUserId(userId string) *Hub

func NewWebHub

func NewWebHub() *Hub

func (*Hub) Broadcast

func (h *Hub) Broadcast(message *model.WebSocketEvent)

func (*Hub) InvalidateUser

func (h *Hub) InvalidateUser(userId string)

func (*Hub) Register

func (h *Hub) Register(webConn *WebConn)

func (*Hub) Start

func (h *Hub) Start()

func (*Hub) Stop

func (h *Hub) Stop()

func (*Hub) Unregister

func (h *Hub) Unregister(webConn *WebConn)

type LineImportData

type LineImportData struct {
	Type    string             `json:"type"`
	Team    *TeamImportData    `json:"team"`
	Channel *ChannelImportData `json:"channel"`
	User    *UserImportData    `json:"user"`
	Post    *PostImportData    `json:"post"`
	Version *int               `json:"version"`
}

type PostImportData

type PostImportData struct {
	Team    *string `json:"team"`
	Channel *string `json:"channel"`
	User    *string `json:"user"`

	Message  *string `json:"message"`
	CreateAt *int64  `json:"create_at"`
}

type Server

type Server struct {
	Store           store.Store
	WebSocketRouter *WebSocketRouter
	Router          *mux.Router
	GracefulServer  *graceful.Server
}
var Srv *Server

type SlackChannel

type SlackChannel struct {
	Id      string            `json:"id"`
	Name    string            `json:"name"`
	Members []string          `json:"members"`
	Topic   map[string]string `json:"topic"`
	Purpose map[string]string `json:"purpose"`
}

func SlackParseChannels

func SlackParseChannels(data io.Reader) ([]SlackChannel, error)

type SlackComment

type SlackComment struct {
	User    string `json:"user"`
	Comment string `json:"comment"`
}

type SlackFile

type SlackFile struct {
	Id    string `json:"id"`
	Title string `json:"title"`
}

type SlackPost

type SlackPost struct {
	User        string                   `json:"user"`
	BotId       string                   `json:"bot_id"`
	BotUsername string                   `json:"username"`
	Text        string                   `json:"text"`
	TimeStamp   string                   `json:"ts"`
	Type        string                   `json:"type"`
	SubType     string                   `json:"subtype"`
	Comment     *SlackComment            `json:"comment"`
	Upload      bool                     `json:"upload"`
	File        *SlackFile               `json:"file"`
	Attachments []*model.SlackAttachment `json:"attachments"`
}

func SlackParsePosts

func SlackParsePosts(data io.Reader) ([]SlackPost, error)

type SlackUser

type SlackUser struct {
	Id       string            `json:"id"`
	Username string            `json:"name"`
	Profile  map[string]string `json:"profile"`
}

func SlackParseUsers

func SlackParseUsers(data io.Reader) ([]SlackUser, error)

type TeamImportData

type TeamImportData struct {
	Name            *string `json:"name"`
	DisplayName     *string `json:"display_name"`
	Type            *string `json:"type"`
	Description     *string `json:"description"`
	AllowOpenInvite *bool   `json:"allow_open_invite"`
}

type TestHelper

type TestHelper struct {
	BasicTeam    *model.Team
	BasicUser    *model.User
	BasicUser2   *model.User
	BasicChannel *model.Channel
	BasicPost    *model.Post
}

func Setup

func Setup() *TestHelper

func SetupEnterprise

func SetupEnterprise() *TestHelper

func (*TestHelper) CreateChannel

func (me *TestHelper) CreateChannel(team *model.Team) *model.Channel

func (*TestHelper) CreatePost

func (me *TestHelper) CreatePost(channel *model.Channel) *model.Post

func (*TestHelper) CreatePrivateChannel

func (me *TestHelper) CreatePrivateChannel(team *model.Team) *model.Channel

func (*TestHelper) CreateTeam

func (me *TestHelper) CreateTeam() *model.Team

func (*TestHelper) CreateUser

func (me *TestHelper) CreateUser() *model.User

func (*TestHelper) InitBasic

func (me *TestHelper) InitBasic() *TestHelper

type UserChannelImportData

type UserChannelImportData struct {
	Name        *string                           `json:"name"`
	Roles       *string                           `json:"roles"`
	NotifyProps *UserChannelNotifyPropsImportData `json:"notify_props"`
}

type UserChannelNotifyPropsImportData

type UserChannelNotifyPropsImportData struct {
	Desktop    *string `json:"desktop"`
	MarkUnread *string `json:"mark_unread"`
}

type UserImportData

type UserImportData struct {
	Username    *string `json:"username"`
	Email       *string `json:"email"`
	AuthService *string `json:"auth_service"`
	AuthData    *string `json:"auth_data"`
	Nickname    *string `json:"nickname"`
	FirstName   *string `json:"first_name"`
	LastName    *string `json:"last_name"`
	Position    *string `json:"position"`
	Roles       *string `json:"roles"`
	Locale      *string `json:"locale"`

	Teams *[]UserTeamImportData `json:"teams"`

	Theme              *string `json:"theme"`
	SelectedFont       *string `json:"display_font"`
	UseMilitaryTime    *string `json:"military_time"`
	NameFormat         *string `json:"teammate_name_display"`
	CollapsePreviews   *string `json:"link_previews"`
	MessageDisplay     *string `json:"message_display"`
	ChannelDisplayMode *string `json:"channel_display_mode"`
}

type UserTeamImportData

type UserTeamImportData struct {
	Name     *string                  `json:"name"`
	Roles    *string                  `json:"roles"`
	Channels *[]UserChannelImportData `json:"channels"`
}

type VaryBy

type VaryBy struct{}

func (*VaryBy) Key

func (m *VaryBy) Key(r *http.Request) string

type WebConn

type WebConn struct {
	WebSocket                 *websocket.Conn
	Send                      chan model.WebSocketMessage
	SessionToken              string
	SessionExpiresAt          int64
	Session                   *model.Session
	UserId                    string
	T                         goi18n.TranslateFunc
	Locale                    string
	AllChannelMembers         map[string]string
	LastAllChannelMembersTime int64
}

func NewWebConn

func NewWebConn(ws *websocket.Conn, session model.Session, t goi18n.TranslateFunc, locale string) *WebConn

func (*WebConn) InvalidateCache

func (webCon *WebConn) InvalidateCache()

func (*WebConn) IsAuthenticated

func (webCon *WebConn) IsAuthenticated() bool

func (*WebConn) IsMemberOfTeam

func (webCon *WebConn) IsMemberOfTeam(teamId string) bool

func (*WebConn) ReadPump

func (c *WebConn) ReadPump()

func (*WebConn) SendHello

func (webCon *WebConn) SendHello()

func (*WebConn) ShouldSendEvent

func (webCon *WebConn) ShouldSendEvent(msg *model.WebSocketEvent) bool

func (*WebConn) WritePump

func (c *WebConn) WritePump()

type WebSocketRouter

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

func NewWebSocketRouter

func NewWebSocketRouter() *WebSocketRouter

func (*WebSocketRouter) Handle

func (wr *WebSocketRouter) Handle(action string, handler webSocketHandler)

func (*WebSocketRouter) ServeWebSocket

func (wr *WebSocketRouter) ServeWebSocket(conn *WebConn, r *model.WebSocketRequest)

Jump to

Keyboard shortcuts

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