Documentation ¶
Index ¶
- Constants
- Variables
- func CheckEmailVerificationToken(kms security.KMS, account Account, email string, token []byte) error
- func DecryptPayload(payload interface{}, auth *Authorization, level PrivilegeLevel) (interface{}, error)
- func EncryptMessage(msg *Message, keyID string, key *security.ManagedKey) error
- func LoadEmoji(path string) error
- func NormalizeNick(name string) (string, error)
- func PacketsByType() map[PacketType]string
- func ParsePasswordResetConfirmation(confirmation string) (snowflake.Snowflake, []byte, error)
- func ValidateAccountPassword(password string) (bool, string)
- func ValidateEmailTemplates(templater *templates.Templater) []error
- func ValidatePersonalIdentity(namespace, id string) (bool, string)
- type Account
- type AccountGrantable
- type AccountManager
- type AccountSecurity
- type AccountView
- type Agent
- type AgentTracker
- type AuthCommand
- type AuthOption
- type AuthReply
- type Authorization
- type AuthorizationResult
- type Backend
- type BackendFactory
- type Ban
- type BanCommand
- type BanReply
- type BounceEvent
- type CapabilityTable
- type ChangeEmailCommand
- type ChangeEmailReply
- type ChangeNameCommand
- type ChangeNameReply
- type ChangePasswordCommand
- type ChangePasswordReply
- type Client
- func (c *Client) AuthenticateWithAgent(ctx scope.Context, backend Backend, agent *Agent, ...) error
- func (c *Client) AuthenticateWithPasscode(ctx scope.Context, room ManagedRoom, passcode string) (string, error)
- func (c *Client) FromContext(ctx scope.Context) bool
- func (c *Client) FromRequest(ctx scope.Context, r *http.Request)
- func (c *Client) RoomAuthorize(ctx scope.Context, room Room) error
- func (c *Client) UserID() UserID
- type CommonEmailParams
- type DisconnectEvent
- type EditMessageCommand
- type EditMessageEvent
- type EditMessageReply
- type EmailTracker
- type ErrorReply
- type GetMessageCommand
- type GetMessageReply
- type GrantAccessCommand
- type GrantAccessReply
- type GrantManager
- func (gs *GrantManager) AccountCapability(ctx scope.Context, account Account) (*security.PublicKeyCapability, error)
- func (gs *GrantManager) Authority(ctx scope.Context, manager Account, managerKey *security.ManagedKey) (subjectKeyPair *security.ManagedKeyPair, public, private *json.RawMessage, ...)
- func (gs *GrantManager) GrantToAccount(ctx scope.Context, kms security.KMS, manager Account, ...) error
- func (gs *GrantManager) GrantToPasscode(ctx scope.Context, manager Account, managerKey *security.ManagedKey, ...) error
- func (gs *GrantManager) PasscodeCapability(ctx scope.Context, passcode string) (*security.SharedSecretCapability, error)
- func (gs *GrantManager) RevokeFromAccount(ctx scope.Context, account Account) error
- func (gs *GrantManager) RevokeFromPasscode(ctx scope.Context, passcode string) error
- func (gs *GrantManager) StaffGrantToAccount(ctx scope.Context, kms security.KMS, target Account) error
- type GrantManagerCommand
- type GrantManagerReply
- type Heim
- func (heim *Heim) MockDeliverer() emails.MockDeliverer
- func (heim *Heim) NewOTP(account Account) (*OTP, error)
- func (heim *Heim) OnAccountEmailChanged(ctx scope.Context, b Backend, account Account, clientKey *security.ManagedKey, ...) error
- func (heim *Heim) OnAccountPasswordChanged(ctx scope.Context, b Backend, account Account) error
- func (heim *Heim) OnAccountPasswordResetRequest(ctx scope.Context, b Backend, account Account, req *PasswordResetRequest) error
- func (heim *Heim) OnAccountRegistration(ctx scope.Context, b Backend, account Account, clientKey *security.ManagedKey) error
- func (heim *Heim) SendEmail(ctx scope.Context, b Backend, account Account, to, templateName string, ...) (*emails.EmailRef, error)
- type HelloEvent
- type Identity
- type IdentityView
- type Listing
- type LogCommand
- type LogReply
- type LoginCommand
- type LoginEvent
- type LoginReply
- type LogoutCommand
- type LogoutEvent
- type LogoutReply
- type ManagedRoom
- type Message
- type NetworkEvent
- type NickCommand
- type NickEvent
- type NickReply
- type OTP
- type PM
- type PMInitiateCommand
- type PMInitiateEvent
- type PMInitiateReply
- type PMTracker
- type Packet
- type PacketType
- type PasscodeGrantable
- type PasswordChangedEmailParams
- type PasswordResetEmailParams
- type PasswordResetRequest
- type PersonalAccountView
- type PersonalIdentity
- type PingCommand
- type PingEvent
- type PingReply
- type Presence
- type PresenceEvent
- type PrivilegeLevel
- type RegisterAccountCommand
- type RegisterAccountReply
- type ResendVerificationEmailCommand
- type ResendVerificationEmailReply
- type ResetPasswordCommand
- type ResetPasswordReply
- type RevokeAccessCommand
- type RevokeAccessReply
- type RevokeManagerCommand
- type RevokeManagerReply
- type Room
- type RoomInvitationEmailParams
- type RoomInvitationWelcomeEmailParams
- type RoomManagerKey
- type RoomMessageKey
- type RoomSecurity
- type SendCommand
- type SendEvent
- type SendReply
- type Session
- type SessionView
- type SnapshotEvent
- type StaffCreateRoomCommand
- type StaffCreateRoomReply
- type StaffEnrollOTPCommand
- type StaffEnrollOTPReply
- type StaffGrantManagerCommand
- type StaffGrantManagerReply
- type StaffInspectIPCommand
- type StaffInspectIPReply
- type StaffInvadeCommand
- type StaffInvadeReply
- type StaffLockRoomCommand
- type StaffLockRoomReply
- type StaffRevokeAccessCommand
- type StaffRevokeAccessReply
- type StaffRevokeManagerCommand
- type StaffRevokeManagerReply
- type StaffValidateOTPCommand
- type StaffValidateOTPReply
- type Time
- type UnbanCommand
- type UnbanReply
- type UnlockStaffCapabilityCommand
- type UnlockStaffCapabilityReply
- type UserID
- type VerificationEmailParams
- type WelcomeEmailParams
- type WhoCommand
- type WhoReply
Constants ¶
const ( MinPasswordLength = 6 ClientKeyType = security.AES128 PasswordResetRequestLifetime = time.Hour )
const ( AgentIDSize = 8 AgentKeyType = security.AES128 )
const ( PasswordChangedEmail = "password-changed" PasswordResetEmail = "password-reset" RoomInvitationEmail = "room-invitation" RoomInvitationWelcomeEmail = "room-invitation-welcome" VerificationEmail = "verification" WelcomeEmail = "welcome" )
const ( MaxMessageLength = 1 << 20 MaxMessageTransmissionLength = 4096 )
const ( RoomManagerKeyType = security.AES128 RoomMessageKeyType = security.AES128 )
const (
AuthPasscode = AuthOption("passcode")
)
const MaxNickLength = 36
Variables ¶
var ( DefaultCommonEmailParams = CommonEmailParams{ CommonData: emails.CommonData{ LocalDomain: "heim.invalid", }, SenderAddress: "noreply@heim.invalid", HelpAddress: "help@heim.invalid", SiteName: "heim", SiteURL: "https://heim.invalid", } EmailScenarios = map[string]map[string]templates.TemplateTest{ WelcomeEmail: map[string]templates.TemplateTest{ "default": templates.TemplateTest{ Data: &WelcomeEmailParams{ CommonEmailParams: DefaultCommonEmailParams, VerificationToken: "token", }, }, }, PasswordChangedEmail: map[string]templates.TemplateTest{ "default": templates.TemplateTest{ Data: &PasswordChangedEmailParams{ CommonEmailParams: DefaultCommonEmailParams, AccountName: "yourname", }, }, }, PasswordResetEmail: map[string]templates.TemplateTest{ "default": templates.TemplateTest{ Data: &PasswordResetEmailParams{ CommonEmailParams: DefaultCommonEmailParams, AccountName: "yourname", }, }, }, RoomInvitationEmail: map[string]templates.TemplateTest{ "default": templates.TemplateTest{ Data: &RoomInvitationEmailParams{ CommonEmailParams: DefaultCommonEmailParams, SenderName: "(‿|‿)", RoomName: "butts", SenderMessage: "hey, i heard you like butts", }, }, }, RoomInvitationWelcomeEmail: map[string]templates.TemplateTest{ "default": templates.TemplateTest{ Data: &RoomInvitationWelcomeEmailParams{ CommonEmailParams: DefaultCommonEmailParams, SenderName: "thatguy", RoomName: "cabal", RoomPrivacy: "private", SenderMessage: "let's move our machinations here", }, }, }, } )
var ( ErrAccessDenied = fmt.Errorf("access denied") ErrAccountIdentityInUse = fmt.Errorf("account identity already in use") ErrAccountNotFound = fmt.Errorf("account not found") ErrAgentAlreadyExists = fmt.Errorf("agent already exists") ErrAgentNotFound = fmt.Errorf("agent not found") ErrCapabilityNotFound = fmt.Errorf("capability not found") ErrClientKeyNotFound = fmt.Errorf("client key not found") ErrEditInconsistent = fmt.Errorf("edit inconsistent") ErrEmailNotFound = fmt.Errorf("email not found") ErrEmailAlreadyDelivered = fmt.Errorf("email already delivered") ErrInvalidConfirmationCode = fmt.Errorf("invalid confirmation code") ErrInvalidNick = fmt.Errorf("invalid nick") ErrInvalidParent = fmt.Errorf("invalid parent ID") ErrInvalidUserID = fmt.Errorf("invalid user ID") ErrInvalidVerificationToken = fmt.Errorf("invalid verification token") ErrLoggedIn = fmt.Errorf("logged in") ErrOTPAlreadyEnrolled = fmt.Errorf("otp already enrolled") ErrOTPNotEnrolled = fmt.Errorf("otp not enrolled") ErrManagerNotFound = fmt.Errorf("manager not found") ErrMessageNotFound = fmt.Errorf("message not found") ErrMessageTooLong = fmt.Errorf("message too long") ErrNotLoggedIn = fmt.Errorf("not logged in") ErrPMNotFound = fmt.Errorf("pm not found") ErrPersonalIdentityAlreadyVerified = fmt.Errorf("personal identity already verified") ErrPersonalIdentityInUse = fmt.Errorf("personal identity already in use") ErrRoomNotFound = fmt.Errorf("room not found") )
var ( AuthType = PacketType("auth") AuthReplyType = AuthType.Reply() BanType = PacketType("ban") BanReplyType = BanType.Reply() UnbanType = PacketType("unban") UnbanReplyType = UnbanType.Reply() SendType = PacketType("send") SendEventType = SendType.Event() SendReplyType = SendType.Reply() ChangeEmailType = PacketType("change-email") ChangeEmailReplyType = ChangeEmailType.Reply() ChangeNameType = PacketType("change-name") ChangeNameReplyType = ChangeNameType.Reply() ChangePasswordType = PacketType("change-password") ChangePasswordReplyType = ChangePasswordType.Reply() EditMessageType = PacketType("edit-message") EditMessageEventType = EditMessageType.Event() EditMessageReplyType = EditMessageType.Reply() GetMessageType = PacketType("get-message") GetMessageReplyType = GetMessageType.Reply() GrantAccessType = PacketType("grant-access") GrantAccessReplyType = GrantAccessType.Reply() GrantManagerType = PacketType("grant-manager") GrantManagerReplyType = GrantManagerType.Reply() JoinType = PacketType("join") JoinEventType = JoinType.Event() PartType = PacketType("part") PartEventType = PartType.Event() LogType = PacketType("log") LogReplyType = LogType.Reply() LoginType = PacketType("login") LoginEventType = LoginType.Event() LoginReplyType = LoginType.Reply() LogoutType = PacketType("logout") LogoutEventType = LogoutType.Event() LogoutReplyType = LogoutType.Reply() NickType = PacketType("nick") NickEventType = NickType.Event() NickReplyType = NickType.Reply() PingType = PacketType("ping") PingEventType = PingType.Event() PingReplyType = PingType.Reply() PMInitiateType = PacketType("pm-initiate") PMInitiateEventType = PacketType("pm-initiate-event") PMInitiateReplyType = PacketType("pm-initiate-reply") RegisterAccountType = PacketType("register-account") RegisterAccountReplyType = RegisterAccountType.Reply() ResendVerificationEmailType = PacketType("resend-verification-email") ResendVerificationEmailReplyType = ResendVerificationEmailType.Reply() ResetPasswordType = PacketType("reset-password") ResetPasswordReplyType = ResetPasswordType.Reply() RevokeAccessType = PacketType("revoke-access") RevokeAccessReplyType = RevokeAccessType.Reply() RevokeManagerType = PacketType("revoke-manager") RevokeManagerReplyType = RevokeManagerType.Reply() StaffCreateRoomType = PacketType("staff-create-room") StaffCreateRoomReplyType = StaffCreateRoomType.Reply() StaffEnrollOTPType = PacketType("staff-enroll-otp") StaffEnrollOTPReplyType = StaffEnrollOTPType.Reply() StaffValidateOTPType = PacketType("staff-validate-otp") StaffValidateOTPReplyType = StaffValidateOTPType.Reply() StaffGrantManagerType = PacketType("staff-grant-manager") StaffGrantManagerReplyType = StaffGrantManagerType.Reply() StaffInspectIPType = PacketType("staff-inspect-ip") StaffInspectIPReplyType = StaffInspectIPType.Reply() StaffInvadeType = PacketType("staff-invade") StaffInvadeReplyType = StaffInvadeType.Reply() StaffLockRoomType = PacketType("staff-lock-room") StaffLockRoomReplyType = StaffLockRoomType.Reply() StaffRevokeAccessType = PacketType("staff-revoke-access") StaffRevokeAccessReplyType = StaffRevokeAccessType.Reply() StaffRevokeManagerType = PacketType("staff-revoke-manager") StaffRevokeManagerReplyType = StaffRevokeManagerType.Reply() UnlockStaffCapabilityType = PacketType("unlock-staff-capability") UnlockStaffCapabilityReplyType = UnlockStaffCapabilityType.Reply() WhoType = PacketType("who") WhoReplyType = WhoType.Reply() BounceEventType = PacketType("bounce").Event() DisconnectEventType = PacketType("disconnect").Event() HelloEventType = PacketType("hello").Event() NetworkEventType = PacketType("network").Event() SnapshotEventType = PacketType("snapshot").Event() ErrorReplyType = PacketType("error").Reply() )
Functions ¶
func DecryptPayload ¶
func DecryptPayload(payload interface{}, auth *Authorization, level PrivilegeLevel) (interface{}, error)
func EncryptMessage ¶
func EncryptMessage(msg *Message, keyID string, key *security.ManagedKey) error
func LoadEmoji ¶
LoadEmoji takes a json key-value object stored in the file at path and unmarshals it into the global validEmoji map[string]string.
func NormalizeNick ¶
NormalizeNick validates and normalizes a proposed name from a user. If the proposed name is not valid, returns an error. Otherwise, returns the normalized form of the name. Normalization for a nick consists of:
1. Remove leading and trailing whitespace 2. Collapse all internal whitespace to single spaces 3. Replace all
func PacketsByType ¶
func PacketsByType() map[PacketType]string
func ValidateAccountPassword ¶
func ValidateEmailTemplates ¶
Types ¶
type Account ¶
type Account interface { ID() snowflake.Snowflake Name() string Email() (string, bool) KeyFromPassword(password string) *security.ManagedKey KeyPair() security.ManagedKeyPair Unlock(clientKey *security.ManagedKey) (*security.ManagedKeyPair, error) IsStaff() bool UnlockStaffKMS(clientKey *security.ManagedKey) (security.KMS, error) PersonalIdentities() []PersonalIdentity UserKey() security.ManagedKey SystemKey() security.ManagedKey View(roomName string) *AccountView }
type AccountGrantable ¶
type AccountGrantable interface { GrantToAccount( ctx scope.Context, kms security.KMS, manager Account, managerClientKey *security.ManagedKey, target Account) error StaffGrantToAccount(ctx scope.Context, kms security.KMS, target Account) error RevokeFromAccount(ctx scope.Context, account Account) error AccountCapability(ctx scope.Context, account Account) (*security.PublicKeyCapability, error) }
type AccountManager ¶
type AccountManager interface { // GetAccount returns the account with the given ID. Get(ctx scope.Context, id snowflake.Snowflake) (Account, error) // RegisterAccount creates and returns a new, unverified account, along with // its (unencrypted) client key. Register( ctx scope.Context, kms security.KMS, namespace, id, password string, agentID string, agentKey *security.ManagedKey) ( Account, *security.ManagedKey, error) // ResolveAccount returns any account registered under the given account identity. Resolve(ctx scope.Context, namespace, id string) (Account, error) // GrantStaff adds a StaffKMS capability to the identified account. GrantStaff(ctx scope.Context, accountID snowflake.Snowflake, kmsCred security.KMSCredential) error // RevokeStaff removes a StaffKMS capability from the identified account. RevokeStaff(ctx scope.Context, accountID snowflake.Snowflake) error // VerifyPersonalIdentity marks a personal identity as verified. VerifyPersonalIdentity(ctx scope.Context, namespace, id string) error // ChangeClientKey re-encrypts account keys with a new client key. // The correct former client key must also be given. ChangeClientKey( ctx scope.Context, accountID snowflake.Snowflake, oldClientKey, newClientKey *security.ManagedKey) error // RequestPasswordReset generates a temporary password-reset record. RequestPasswordReset( ctx scope.Context, kms security.KMS, namespace, id string) (Account, *PasswordResetRequest, error) // CheckPasswordResetRequest returns the account associated with // a password reset request, or an error if invalid or expired. GetPasswordResetAccount(ctx scope.Context, confirmation string) (Account, error) // ConfirmPasswordReset verifies a password reset confirmation code, // and applies the new password to the account referred to by the // confirmation code. ConfirmPasswordReset(ctx scope.Context, kms security.KMS, confirmation, password string) error // ChangeEmail changes an account's primary email address. It returns true if the email // address is verified for this account. If false is returned, then a verification // email will be sent out. ChangeEmail(ctx scope.Context, accountID snowflake.Snowflake, email string) (bool, error) // ChangeName changes an account's name. ChangeName(ctx scope.Context, accountID snowflake.Snowflake, name string) error // OTP unlocks and returns the user's enrolled OTP, or nil if one has never // been generated. OTP(ctx scope.Context, kms security.KMS, accountID snowflake.Snowflake) (*OTP, error) // GenerateOTP generates a new OTP secret for the user. If one has been generated // before, then it is replaced if it was never validated, or an error is returned. GenerateOTP(ctx scope.Context, heim *Heim, kms security.KMS, account Account) (*OTP, error) // ValidateOTP validates a one-time passcode according to the user's enrolled OTP. ValidateOTP(ctx scope.Context, kms security.KMS, accountID snowflake.Snowflake, passcode string) error }
type AccountSecurity ¶
type AccountSecurity struct { Nonce []byte MAC []byte SystemKey security.ManagedKey UserKey security.ManagedKey KeyPair security.ManagedKeyPair }
func NewAccountSecurity ¶
func NewAccountSecurity( kms security.KMS, password string) (*AccountSecurity, *security.ManagedKey, error)
NewAccountSecurity initializes the nonce and account secrets for a new account with the given password. Returns an encrypted key-encrypting-key, encrypted key-pair, nonce, and error.
func (*AccountSecurity) ChangeClientKey ¶
func (sec *AccountSecurity) ChangeClientKey(oldKey, newKey *security.ManagedKey) error
func (*AccountSecurity) ResetPassword ¶
func (sec *AccountSecurity) ResetPassword(kms security.KMS, password string) (*AccountSecurity, error)
func (*AccountSecurity) Unlock ¶
func (sec *AccountSecurity) Unlock(clientKey *security.ManagedKey) (*security.ManagedKeyPair, error)
type AccountView ¶
type AccountView struct { ID snowflake.Snowflake `json:"id"` // the id of the account Name string `json:"name"` // the name that the holder of the account goes by }
AccountView describes an account and its preferred names.
type Agent ¶
type Agent struct { ID []byte IV []byte MAC []byte EncryptedClientKey *security.ManagedKey AccountID string Created time.Time Blessed bool Bot bool }
func (*Agent) SetClientKey ¶
func (a *Agent) SetClientKey(accessKey, clientKey *security.ManagedKey) error
func (*Agent) Unlock ¶
func (a *Agent) Unlock(accessKey *security.ManagedKey) (*security.ManagedKey, error)
type AgentTracker ¶
type AgentTracker interface { // Register associates the given ID with the given unencrypted key. The key // is not stored, but will be required to access the agent. Register(ctx scope.Context, agent *Agent) error // Get returns details for the agent associated with the given ID. Get(ctx scope.Context, agentID string) (*Agent, error) // SetClientKey encrypts the given clientKey with accessKey and saves it // under the given agentID. Both keys must be unencrypted. SetClientKey( ctx scope.Context, agentID string, accessKey *security.ManagedKey, accountID snowflake.Snowflake, clientKey *security.ManagedKey) error // ClearClientKey logs the agent out. ClearClientKey(ctx scope.Context, agentID string) error }
type AuthCommand ¶
type AuthCommand struct { Type AuthOption `json:"type"` // the method of authentication Passcode string `json:"passcode,omitempty"` // use this field for `passcode` authentication }
The `auth` command attempts to join a private room. It should be sent in response to a `bounce-event` at the beginning of a session.
type AuthOption ¶
type AuthOption string
type AuthReply ¶
type AuthReply struct { Success bool `json:"success"` // true if authentication succeeded Reason string `json:"reason,omitempty"` // if `success` was false, the reason for failure }
The `auth-reply` packet reports whether the `auth` command succeeded.
type Authorization ¶
type Authorization struct { ClientKey *security.ManagedKey ManagerKeyEncryptingKey *security.ManagedKey ManagerKeyPair *security.ManagedKeyPair MessageKeys map[string]*security.ManagedKey CurrentMessageKeyID string }
func (*Authorization) AddMessageKey ¶
func (a *Authorization) AddMessageKey(keyID string, key *security.ManagedKey)
type AuthorizationResult ¶
type AuthorizationResult struct { Authorization FailureReason string }
type Backend ¶
type Backend interface { AccountManager() AccountManager AgentTracker() AgentTracker EmailTracker() EmailTracker Jobs() jobs.JobService PMTracker() PMTracker // Ban adds an entry to the global ban list. A zero value for until // indicates a permanent ban. Ban(ctx scope.Context, ban Ban, until time.Time) error // UnbanAgent removes a global ban. Unban(ctx scope.Context, ban Ban) error Close() // Create creates a new room. CreateRoom( ctx scope.Context, kms security.KMS, private bool, name string, managers ...Account) (ManagedRoom, error) // Gets an existing Room by name. GetRoom(ctx scope.Context, name string) (ManagedRoom, error) // Peers returns a snapshot of known peers in this backend's cluster. Peers() []cluster.PeerDesc // Version returns the implementation version string. Version() string // NotifyUser broadcasts a packet to all sessions associated with the given userID NotifyUser(ctx scope.Context, userID UserID, packetType PacketType, payload interface{}, excluding ...Session) error }
A Backend provides Rooms and an implementation version.
type BackendFactory ¶
type Ban ¶
type Ban struct { ID UserID `json:"id,omitempty"` // the id of an agent or account IP string `json:"ip,omitempty"` // an IP address Global bool `json:"global,omitempty"` // if true, the ban applies site-wide and not just to the current room }
`Ban` describes an entry in a ban list. When incoming sessions match one of these entries, they are rejected.
type BanCommand ¶
type BanCommand struct { Ban Seconds int `json:"seconds,omitempty"` // the duration of the ban; if not given, the ban is infinite }
The `ban` command adds an entry to the room's ban list. Any joined sessions that match this entry will be disconnected. New sessions matching the entry will be unable to join the room.
The command is a no-op if an identical entry already exists in the ban list.
type BanReply ¶
type BanReply BanCommand
The `ban-reply` packet indicates that the `ban` command succeeded.
type BounceEvent ¶
type BounceEvent struct { Reason string `json:"reason,omitempty"` // the reason why access was denied AuthOptions []AuthOption `json:"auth_options,omitempty"` // authentication options that may be used; see [auth](#auth) AgentID UserID `json:"agent_id,omitempty"` // internal use only IP string `json:"ip,omitempty"` // internal use only }
A `bounce-event` indicates that access to a room is denied.
type CapabilityTable ¶
type ChangeEmailCommand ¶
type ChangeEmailCommand struct { Email string `json:"email"` // the new primary email address for the account Password string `json:"password"` // the account's password }
The `change-email` command changes the primary email address associated with the signed in account. The email address may need to be verified before the change is fully applied.
type ChangeEmailReply ¶
type ChangeEmailReply struct { Success bool `json:"success"` // true if authentication succeeded and the email was changed Reason string `json:"reason,omitempty"` // if `success` was false, the reason for failure VerificationNeeded bool `json:"verification_needed"` // if true, a verification email will be sent out, and the user must verify the address before it becomes their primary address }
The `change-email-reply` packet indicates that the primary email address has been changed.
type ChangeNameCommand ¶
type ChangeNameCommand struct {
Name string `json:"name"` // the name to associate with the account
}
The `change-name` command changes the name associated with the signed in account.
type ChangeNameReply ¶
type ChangeNameReply struct {
Name string `json:"name"` // the new name associated with the account
}
The `change-name-reply` packet indicates a successful name change.
type ChangePasswordCommand ¶
type ChangePasswordCommand struct { OldPassword string `json:"old_password"` // the current (and soon-to-be former) password NewPassword string `json:"new_password"` // the new password }
The `change-password` command changes the password of the signed in account.
type ChangePasswordReply ¶
type ChangePasswordReply struct{}
The `change-password-reply` packet returns the outcome of changing the password.
type Client ¶
type Client struct { IP string UserAgent string Connected time.Time Agent *Agent Account Account Authorization Authorization }
func (*Client) AuthenticateWithAgent ¶
func (*Client) AuthenticateWithPasscode ¶
type CommonEmailParams ¶
type CommonEmailParams struct { emails.CommonData EmailDomain string `yaml:"email_domain"` SiteName string `yaml:"site_name"` SiteURL string `yaml:"site_url"` HelpAddress template.HTML `yaml:"help_address"` SenderAddress template.HTML `yaml:"sender_address"` }
func (*CommonEmailParams) EmailPreferencesURL ¶
func (p *CommonEmailParams) EmailPreferencesURL() template.HTML
func (*CommonEmailParams) SiteURLShort ¶
func (p *CommonEmailParams) SiteURLShort() template.HTML
type DisconnectEvent ¶
type DisconnectEvent struct {
Reason string `json:"reason"` // the reason for disconnection
}
A `disconnect-event` indicates that the session is being closed. The client will subsequently be disconnected.
If the disconnect reason is "authentication changed", the client should immediately reconnect.
type EditMessageCommand ¶
type EditMessageCommand struct { ID snowflake.Snowflake `json:"id"` // the id of the message to edit PreviousEditID snowflake.Snowflake `json:"previous_edit_id"` // the `previous_edit_id` of the message; if this does not match, the edit will fail (basic conflict resolution) Parent snowflake.Snowflake `json:"parent,omitempty"` // the new parent of the message (*not yet implemented*) Content string `json:"content,omitempty"` // the new content of the message (*not yet implemented*) Delete bool `json:"delete"` // the new deletion status of the message Announce bool `json:"announce"` // if true, broadcast an `edit-message-event` to the room }
The `edit-message` command can be used by active room managers to modify the content or display of a message.
A message deleted by this command is still stored in the database. Deleted messages may be undeleted by this command. (Messages that have expired from the database due to the room's retention policy are no longer available and cannot be restored by this or any command).
If the `announce` field is set to true, then an edit-message-event will be broadcast to the room.
TODO: support content editing TODO: support reparenting
type EditMessageEvent ¶
type EditMessageEvent struct { EditID snowflake.Snowflake `json:"edit_id"` // the id of the edit Message }
An `edit-message-event` indicates that a message in the room has been modified or deleted. If the client offers a user interface and the indicated message is currently displayed, it should update its display accordingly.
The event packet includes a snapshot of the message post-edit.
type EditMessageReply ¶
type EditMessageReply struct { EditID snowflake.Snowflake `json:"edit_id"` // the unique id of the edit that was applied Message }
`edit-message-reply` returns the id of a successful edit.
type EmailTracker ¶
type EmailTracker interface { Get(ctx scope.Context, accountID snowflake.Snowflake, id string) (*emails.EmailRef, error) List(ctx scope.Context, accountID snowflake.Snowflake, n int, before time.Time) ([]*emails.EmailRef, error) MarkDelivered(ctx scope.Context, accountID snowflake.Snowflake, id string) error Send( ctx scope.Context, js jobs.JobService, templater *templates.Templater, deliverer emails.Deliverer, account Account, to, templateName string, data interface{}) (*emails.EmailRef, error) }
type ErrorReply ¶
type ErrorReply struct {
Error string `json:"error"`
}
type GetMessageCommand ¶
type GetMessageCommand struct {
ID snowflake.Snowflake `json:"id"` // the id of the message to retrieve
}
The `get-message` command retrieves the full content of a single message in the room.
type GetMessageReply ¶
type GetMessageReply Message
`get-message-reply` returns the message retrieved by `get-message`.
type GrantAccessCommand ¶
type GrantAccessCommand struct { AccountID snowflake.Snowflake `json:"account_id,omitempty"` // the id of an account to grant access to Passcode string `json:"passcode,omitempty"` // a passcode to grant access to; anyone presenting the same passcode can access the room }
The `grant-access` command may be used by an active manager in a private room to create a new capability for access. Access may be granted to either a passcode or an account.
If the room is not private, or if the requested access grant already exists, an error will be returned.
type GrantAccessReply ¶
type GrantAccessReply struct{}
`grant-access-reply` confirms that access was granted.
type GrantManager ¶
type GrantManager struct { Capabilities CapabilityTable Managers AccountGrantable KeyEncryptingKey *security.ManagedKey SubjectKeyPair *security.ManagedKeyPair SubjectNonce []byte PayloadKey *security.ManagedKey }
func (*GrantManager) AccountCapability ¶
func (gs *GrantManager) AccountCapability( ctx scope.Context, account Account) (*security.PublicKeyCapability, error)
func (*GrantManager) Authority ¶
func (gs *GrantManager) Authority( ctx scope.Context, manager Account, managerKey *security.ManagedKey) ( subjectKeyPair *security.ManagedKeyPair, public, private *json.RawMessage, err error)
func (*GrantManager) GrantToAccount ¶
func (gs *GrantManager) GrantToAccount( ctx scope.Context, kms security.KMS, manager Account, managerKey *security.ManagedKey, target Account) error
func (*GrantManager) GrantToPasscode ¶
func (gs *GrantManager) GrantToPasscode( ctx scope.Context, manager Account, managerKey *security.ManagedKey, passcode string) error
func (*GrantManager) PasscodeCapability ¶
func (gs *GrantManager) PasscodeCapability( ctx scope.Context, passcode string) (*security.SharedSecretCapability, error)
func (*GrantManager) RevokeFromAccount ¶
func (gs *GrantManager) RevokeFromAccount(ctx scope.Context, account Account) error
func (*GrantManager) RevokeFromPasscode ¶
func (gs *GrantManager) RevokeFromPasscode(ctx scope.Context, passcode string) error
func (*GrantManager) StaffGrantToAccount ¶
type GrantManagerCommand ¶
type GrantManagerCommand struct {
AccountID snowflake.Snowflake `json:"account_id"` // the id of an account to grant manager status to
}
The `grant-manager` command may be used by an active room manager to make another account a manager in the same room.
An error is returned if the account can't be found.
type GrantManagerReply ¶
type GrantManagerReply struct{}
`grant-manager-reply` confirms that manager status was granted.
type Heim ¶
type Heim struct { Backend Backend Cluster cluster.Cluster PeerDesc *cluster.PeerDesc Context scope.Context KMS security.KMS SiteName string StaticPath string EmailDeliverer emails.Deliverer EmailTemplater *templates.Templater GeoIP *geoip2.Api PageTemplater *templates.Templater }
func (*Heim) MockDeliverer ¶
func (heim *Heim) MockDeliverer() emails.MockDeliverer
func (*Heim) OnAccountEmailChanged ¶
func (*Heim) OnAccountPasswordChanged ¶
func (*Heim) OnAccountPasswordResetRequest ¶
func (*Heim) OnAccountRegistration ¶
type HelloEvent ¶
type HelloEvent struct { ID UserID `json:"id"` // the id of the agent or account logged into this session AccountView *PersonalAccountView `json:"account,omitempty"` // details about the user's account, if the session is logged in SessionView SessionView `json:"session"` // details about the session AccountHasAccess bool `json:"account_has_access,omitempty"` // if true, then the account has an explicit access grant to the current room AccountEmailVerified bool `json:"account_email_verified,omitempty"` // whether the account's email address has been verified RoomIsPrivate bool `json:"room_is_private"` // if true, the session is connected to a private room Version string `json:"version"` // the version of the code being run and served by the server }
A `hello-event` is sent by the server to the client when a session is started. It includes information about the client's authentication and associated identity.
type Identity ¶
type Identity interface { ID() UserID Name() string ServerID() string View() IdentityView }
An Identity maps to a global persona. It may exist only in the context of a single Room. An Identity may be anonymous.
type IdentityView ¶
type IdentityView struct { ID UserID `json:"id"` // the id of an agent or account Name string `json:"name"` // the name-in-use at the time this view was captured ServerID string `json:"server_id"` // the id of the server that captured this view ServerEra string `json:"server_era"` // the era of the server that captured this view }
type Listing ¶
type Listing []SessionView
A Listing is a sortable list of Identitys present in a Room. TODO: these should be Sessions
type LogCommand ¶
type LogCommand struct { N int `json:"n"` // maximum number of messages to return (up to 1000) Before snowflake.Snowflake `json:"before,omitempty"` // return messages prior to this snowflake }
The `log` command requests messages from the room's message log. This can be used to supplement the log provided by `snapshot-event` (for example, when scrolling back further in history).
type LogReply ¶
type LogReply struct { Log []Message `json:"log"` // list of messages returned Before snowflake.Snowflake `json:"before,omitempty"` // messages prior to this snowflake were returned }
The `log-reply` packet returns a list of messages from the room's message log.
type LoginCommand ¶
type LoginCommand struct { Namespace string `json:"namespace"` // the namespace of a personal identifier ID string `json:"id"` // the id of a personal identifier Password string `json:"password"` // the password for unlocking the account }
The `login` command attempts to log an anonymous session into an account. It will return an error if the session is already logged in.
If the login succeeds, the client should expect to receive a `disconnect-event` shortly after. The next connection the client makes will be a logged in session.
type LoginEvent ¶
The `login-event` packet is sent to all sessions of an agent when that agent is logged in (except for the session that issued the login command).
type LoginReply ¶
type LoginReply struct { Success bool `json:"success"` // true if the session is now logged in Reason string `json:"reason,omitempty"` // if `success` was false, the reason why AccountID snowflake.Snowflake `json:"account_id,omitempty"` // if `success` was true, the id of the account the session logged into. }
The `login-reply` packet returns whether the session successfully logged into an account.
If this reply returns success, the client should expect to receive a `disconnect-event` shortly after. The next connection the client makes will be a logged in session.
type LogoutCommand ¶
type LogoutCommand struct{}
The `logout` command logs a session out of an account. It will return an error if the session is not logged in.
If the logout is successful, the client should expect to receive a `disconnect-event` shortly after. The next connection the client makes will be a logged out session.
type LogoutEvent ¶
type LogoutEvent struct{}
The `logout-event` packet is sent to all sessions of an agent when that agent is logged out (except for the session that issued the logout command).
type ManagedRoom ¶
type ManagedRoom interface { Room // Ban adds an entry to the room's ban list. A zero value for until // indicates a permanent ban. Ban(ctx scope.Context, ban Ban, until time.Time) error // UnbanAgent removes an agent ban from the room. Unban(ctx scope.Context, ban Ban) error // GenerateMessageKey generates and stores a new key and nonce // for encrypting messages in the room. This invalidates all grants made with // the previous key. GenerateMessageKey(ctx scope.Context, kms security.KMS) (RoomMessageKey, error) // MessageKey returns the room's current message key, or nil if the room is // unencrypted. MessageKey(ctx scope.Context) (RoomMessageKey, error) // ManagerKey returns a handle to the room's manager key. ManagerKey(ctx scope.Context) (RoomManagerKey, error) // Managers returns the list of accounts managing the room. Managers(ctx scope.Context) ([]Account, error) // AddManager adds an account as a manager of the room. An unencrypted // client key and corresponding account are needed from the user taking // this action. AddManager( ctx scope.Context, kms security.KMS, actor Account, actorKey *security.ManagedKey, newManager Account) error // RemoveManager removes an account as manager. An unencrypted client key // and corresponding account are needed from the user taking this action. RemoveManager( ctx scope.Context, actor Account, actorKey *security.ManagedKey, formerManager Account) error // ManagerCapability returns the manager capablity for the given account. ManagerCapability(ctx scope.Context, manager Account) (security.Capability, error) MinAgentAge() time.Duration }
type Message ¶
type Message struct { ID snowflake.Snowflake `json:"id"` // the id of the message (unique within a room) Parent snowflake.Snowflake `json:"parent,omitempty"` // the id of the message's parent, or null if top-level PreviousEditID snowflake.Snowflake `json:"previous_edit_id,omitempty"` // the edit id of the most recent edit of this message, or null if it's never been edited UnixTime Time `json:"time"` // the unix timestamp of when the message was posted Sender SessionView `json:"sender"` // the view of the sender's session Content string `json:"content"` // the content of the message (client-defined) EncryptionKeyID string `json:"encryption_key_id,omitempty"` // the id of the key that encrypts the message in storage Edited Time `json:"edited,omitempty"` // the unix timestamp of when the message was last edited Deleted Time `json:"deleted,omitempty"` // the unix timestamp of when the message was deleted Truncated bool `json:"truncated,omitempty"` // if true, then the full content of this message is not included (see `get-message` to obtain the message with full content) }
A Message is a node in a Room's Log. It corresponds to a chat message, or a post, or any broadcasted event in a room that should appear in the log.
func DecryptMessage ¶
func DecryptMessage(msg Message, auths map[string]*security.ManagedKey, level PrivilegeLevel) (Message, error)
type NetworkEvent ¶
type NetworkEvent struct { Type string `json:"type"` // the type of network event; for now, always `partition` ServerID string `json:"server_id"` // the id of the affected server ServerEra string `json:"server_era"` // the era of the affected server }
A `network-event` indicates some server-side event that impacts the presence of sessions in a room.
If the network event type is `partition`, then this should be treated as a [part-event](#part-event) for all sessions connected to the same server id/era combo.
type NickCommand ¶
type NickCommand struct {
Name string `json:"name"` // the requested name (maximum length 36 bytes)
}
The `nick` command sets the name you present to the room. This name applies to all messages sent during this session, until the `nick` command is called again.
type NickEvent ¶
type NickEvent NickReply
`nick-event` announces a nick change by another session in the room.
type NickReply ¶
type NickReply struct { SessionID string `json:"session_id"` // the id of the session this name applies to ID UserID `json:"id"` // the id of the agent or account logged into the session From string `json:"from"` // the previous name associated with the session To string `json:"to"` // the name associated with the session henceforth }
`nick-reply` confirms the `nick` command. It returns the session's former and new names (the server may modify the requested nick).
type PM ¶
type PM struct { ID snowflake.Snowflake Initiator snowflake.Snowflake InitiatorNick string Receiver UserID ReceiverNick string ReceiverMAC []byte IV []byte EncryptedSystemKey *security.ManagedKey EncryptedInitiatorKey *security.ManagedKey EncryptedReceiverKey *security.ManagedKey }
func InitiatePM ¶
type PMInitiateCommand ¶
type PMInitiateCommand struct {
UserID UserID `json:"user_id"` // the id of the user to invite to chat privately
}
The `pm-initiate` command constructs a virtual room for private messaging between the client and the given UserID(#userid).
type PMInitiateEvent ¶
type PMInitiateEvent struct { From UserID `json:"from"` // the id of the user inviting the client to chat privately FromNick string `json:"from_nick"` // the nick of the inviting user FromRoom string `json:"from_room"` // the room where the invitation was sent from PMID snowflake.Snowflake `json:"pm_id"` // the private chat can be accessed at /room/pm:*PMID* }
The `pm-initiate-event` informs the client that another user wants to chat with them privately.
type PMInitiateReply ¶
type PMInitiateReply struct { PMID snowflake.Snowflake `json:"pm_id"` // the private chat can be accessed at /room/pm:*PMID* ToNick string `json:"to_nick"` // the nickname of the recipient of the invitation }
The `pm-initiate-reply` provides the PMID for the requested private messaging room.
type Packet ¶
type Packet struct { ID string `json:"id,omitempty"` // client-generated id for associating replies with commands Type PacketType `json:"type"` // the name of the command, reply, or event Data json.RawMessage `json:"data,omitempty"` // the payload of the command, reply, or event Error string `json:"error,omitempty"` // this field appears in replies if a command fails Throttled bool `json:"throttled,omitempty"` // this field appears in replies to warn the client that it may be flooding; the client should slow down its command rate ThrottledReason string `json:"throttled_reason,omitempty"` // if throttled is true, this field describes why }
func MakeResponse ¶
func MakeResponse( refID string, msgType PacketType, payload interface{}, throttled bool) (*Packet, error)
func ParseRequest ¶
type PacketType ¶
type PacketType string
func (PacketType) Event ¶
func (c PacketType) Event() PacketType
func (PacketType) Reply ¶
func (c PacketType) Reply() PacketType
type PasscodeGrantable ¶
type PasscodeGrantable interface { GrantToPasscode( ctx scope.Context, manager Account, managerClientKey *security.ManagedKey, passcode string) error RevokeFromPasscode(ctx scope.Context, passcode string) error PasscodeCapability(ctx scope.Context, passcode string) (*security.SharedSecretCapability, error) }
type PasswordChangedEmailParams ¶
type PasswordChangedEmailParams struct { CommonEmailParams AccountName string }
func (PasswordChangedEmailParams) Subject ¶
func (p PasswordChangedEmailParams) Subject() template.HTML
type PasswordResetEmailParams ¶
type PasswordResetEmailParams struct { CommonEmailParams AccountName string Confirmation string }
func (PasswordResetEmailParams) ResetPasswordURL ¶
func (p PasswordResetEmailParams) ResetPasswordURL() template.HTML
func (PasswordResetEmailParams) Subject ¶
func (p PasswordResetEmailParams) Subject() template.HTML
type PasswordResetRequest ¶
type PasswordResetRequest struct { ID snowflake.Snowflake AccountID snowflake.Snowflake Key []byte Requested time.Time Expires time.Time }
func (*PasswordResetRequest) MAC ¶
func (req *PasswordResetRequest) MAC() []byte
func (*PasswordResetRequest) String ¶
func (req *PasswordResetRequest) String() string
func (*PasswordResetRequest) VerifyMAC ¶
func (req *PasswordResetRequest) VerifyMAC(mac []byte) bool
type PersonalAccountView ¶
type PersonalAccountView struct { AccountView Email string `json:"email"` // the account's email address }
PersonalAccountView describes an account to its owner.
type PersonalIdentity ¶
type PingCommand ¶
type PingCommand struct {
UnixTime Time `json:"time"` // an arbitrary value, intended to be a unix timestamp
}
The `ping` command initiates a client-to-server ping. The server will send back a `ping-reply` with the same timestamp as soon as possible.
type PingEvent ¶
type PingEvent struct { UnixTime Time `json:"time"` // a unix timestamp according to the server's clock NextUnixTime Time `json:"next"` // the expected time of the next ping-event, according to the server's clock }
A `ping-event` represents a server-to-client ping. The client should send back a `ping-reply` with the same value for the time field as soon as possible (or risk disconnection).
type PingReply ¶
type PingReply struct {
UnixTime Time `json:"time,omitempty"` // the timestamp of the ping being replied to
}
`ping-reply` is a response to a `ping` command or `ping-event`.
type PresenceEvent ¶
type PresenceEvent SessionView
A `presence-event` describes a session joining into or parting from a room.
type RegisterAccountCommand ¶
type RegisterAccountCommand LoginCommand
The `register-account` command creates a new account and logs into it. It will return an error if the session is already logged in.
If the account registration succeeds, the client should expect to receive a `disconnect-event` shortly after. The next connection the client makes will be a logged in session using the new account.
type RegisterAccountReply ¶
type RegisterAccountReply LoginReply
The `register-account-reply` packet returns whether the new account was registered.
If this reply returns success, the client should expect to receive a disconnect-event shortly after. The next connection the client makes will be a logged in session, using the newly created account.
type ResendVerificationEmailCommand ¶
type ResendVerificationEmailCommand struct{}
The `resend-verification-email` command forces a new email to be sent for verifying an accounts primary email address. An error will be returned if the account has no unverified email addresses associated with it.
type ResendVerificationEmailReply ¶
type ResendVerificationEmailReply struct{}
The `resend-verification-email-reply` packet indicates that a verification email has been sent.
type ResetPasswordCommand ¶
The `reset-password` command generates a password reset request. An email will be sent to the owner of the given personal identifier, with instructions and a confirmation code for resetting the password.
type ResetPasswordReply ¶
type ResetPasswordReply struct{}
`reset-password-reply` confirms that the password reset is in progress.
type RevokeAccessCommand ¶
type RevokeAccessCommand struct { AccountID snowflake.Snowflake `json:"account_id,omitempty"` // the id of the account to revoke access from Passcode string `json:"passcode",omitempty` // the passcode to revoke access from }
The `revoke-access` command disables an access grant to a private room. The grant may be to an account or to a passcode.
TODO: all live sessions using the revoked grant should be disconnected TODO: support revocation by capability_id, in case a manager doesn't know the passcode
type RevokeAccessReply ¶
type RevokeAccessReply struct{}
`revoke-access-reply` confirms that the access grant was revoked.
type RevokeManagerCommand ¶
type RevokeManagerCommand struct {
AccountID snowflake.Snowflake `json:"account_id"` // the id of the account to remove as manager
}
The `revoke-manager` command removes an account as manager of the room. This command can be applied to oneself, so be careful not to orphan your room!
type RevokeManagerReply ¶
type RevokeManagerReply struct{}
`revoke-manager-reply` confirms that the manager grant was revoked.
type Room ¶
type Room interface { ID() string Title() string GetMessage(scope.Context, snowflake.Snowflake) (*Message, error) Latest(scope.Context, int, snowflake.Snowflake) ([]Message, error) Snapshot(ctx scope.Context, session Session, level PrivilegeLevel, numMessages int) (*SnapshotEvent, error) // Join inserts a Session into the Room's global presence. Join(scope.Context, Session) (virtualClientAddr string, err error) // Part removes a Session from the Room's global presence. Part(scope.Context, Session) error // IsValidParent checks whether the message with the given ID is able to be replied to. IsValidParent(id snowflake.Snowflake) (bool, error) // Send broadcasts a Message from a Session to the Room. Send(scope.Context, Session, Message) (Message, error) // Edit modifies or deletes a message. EditMessage(scope.Context, Session, EditMessageCommand) (EditMessageReply, error) // Listing returns the current global list of connected sessions to this // Room. Listing(ctx scope.Context, level PrivilegeLevel, exclude ...Session) (Listing, error) // RenameUser updates the nickname of a Session in this Room. RenameUser(ctx scope.Context, session Session, formerName string) (*NickEvent, error) // Version returns the version of the server hosting this Room. Version() string WaitForPart(sessionID string) error MessageKeyID(scope.Context) (string, bool, error) ResolveClientAddress(ctx scope.Context, addr string) (net.IP, error) ResolveNick(ctx scope.Context, userID UserID) (string, bool, error) }
A Room is a nexus of communication. Users connect to a Room via Session and interact.
type RoomInvitationEmailParams ¶
type RoomInvitationEmailParams struct { CommonEmailParams AccountName string RoomName string SenderName string SenderMessage string }
func (RoomInvitationEmailParams) RoomURL ¶
func (p RoomInvitationEmailParams) RoomURL() template.HTML
func (RoomInvitationEmailParams) Subject ¶
func (p RoomInvitationEmailParams) Subject() template.HTML
type RoomInvitationWelcomeEmailParams ¶
type RoomInvitationWelcomeEmailParams struct { CommonEmailParams AccountName string RoomName string RoomPrivacy string SenderName string SenderMessage string }
func (RoomInvitationWelcomeEmailParams) RoomURL ¶
func (p RoomInvitationWelcomeEmailParams) RoomURL() template.HTML
func (RoomInvitationWelcomeEmailParams) Subject ¶
func (p RoomInvitationWelcomeEmailParams) Subject() template.HTML
type RoomManagerKey ¶
type RoomManagerKey interface { AccountGrantable // KeyPair returns the current encrypted ManagedKeyPair for the room. KeyPair() security.ManagedKeyPair // StaffUnlock uses the KMS to decrypt the room's ManagedKeyPair and returns it. StaffUnlock(kms security.KMS) (*security.ManagedKeyPair, error) // Unlock decrypts the room's ManagedKeyPair with the given key and returns it. Unlock(managerKey *security.ManagedKey) (*security.ManagedKeyPair, error) // Nonce returns the current 128-bit nonce for the room. Nonce() []byte }
type RoomMessageKey ¶
type RoomMessageKey interface { AccountGrantable PasscodeGrantable // ID returns a unique identifier for the key. KeyID() string // Timestamp returns when the key was generated. Timestamp() time.Time // Nonce returns the current 128-bit nonce for the room. Nonce() []byte // ManagedKey returns the current encrypted ManagedKey for the room. ManagedKey() security.ManagedKey }
type RoomSecurity ¶
type RoomSecurity struct { Nonce []byte MAC []byte KeyEncryptingKey security.ManagedKey KeyPair security.ManagedKeyPair }
func NewRoomSecurity ¶
func NewRoomSecurity(kms security.KMS, roomName string) (*RoomSecurity, error)
func (*RoomSecurity) Unlock ¶
func (sec *RoomSecurity) Unlock(managerKey *security.ManagedKey) (*security.ManagedKeyPair, error)
type SendCommand ¶
type SendCommand struct { Content string `json:"content"` // the content of the message (client-defined) Parent snowflake.Snowflake `json:"parent,omitempty"` // the id of the parent message, if any }
The `send` command sends a message to a room. The session must be successfully joined with the room. This message will be broadcast to all sessions joined with the room.
If the room is private, then the message content will be encrypted before it is stored and broadcast to the rest of the room.
The caller of this command will not receive the corresponding `send-event`, but will receive the same information in the `send-reply`.
type SendEvent ¶
type SendEvent Message
A `send-event` indicates a message received by the room from another session.
type SendReply ¶
type SendReply SendEvent
`send-reply` returns the message that was sent. This includes the message id, which was populated by the server.
type Session ¶
type Session interface { // ID returns the globally unique identifier for the Session. ID() string // ServerID returns the globally unique identifier of the server hosting // the Session. ServerID() string AgentID() string // Identity returns the Identity associated with the Session. Identity() Identity // SetName sets the acting nickname for the Session. SetName(name string) // Send sends a packet to the Session's client. Send(scope.Context, PacketType, interface{}) error // Close terminates the Session and disconnects the client. Close() // CheckAbandoned() issues an immediate ping to the session with a short // timeout. CheckAbandoned() error View(PrivilegeLevel) SessionView }
A Session is a connection between a client and a Room.
type SessionView ¶
type SessionView struct { IdentityView SessionID string `json:"session_id"` // id of the session, unique across all sessions globally IsStaff bool `json:"is_staff,omitempty"` // if true, this session belongs to a member of staff IsManager bool `json:"is_manager,omitempty"` // if true, this session belongs to a manager of the room ClientAddress string `json:"client_address,omitempty"` // for hosts and staff, the virtual address of the client RealClientAddress string `json:"real_client_address,omitempty"` // for staff, the real address of the client }
SessionView describes a session and its identity.
type SnapshotEvent ¶
type SnapshotEvent struct { Identity UserID `json:"identity"` // the id of the agent or account logged into this session SessionID string `json:"session_id"` // the globally unique id of this session Version string `json:"version"` // the server's version identifier Listing Listing `json:"listing"` // the list of all other sessions joined to the room (excluding this session) Log []Message `json:"log"` // the most recent messages posted to the room (currently up to 100) Nick string `json:"nick,omitempty"` // the acting nick of the session; if omitted, client set nick before speaking PMWithNick string `json:"pm_with_nick,omitempty"` // if given, this room is for private chat with the given nick PMWithUserID UserID `json:"pm_with_user_id,omitempty"` // if given, this room is for private chat with the given user }
A `snapshot-event` indicates that a session has successfully joined a room. It also offers a snapshot of the room's state and recent history.
type StaffCreateRoomCommand ¶
type StaffCreateRoomCommand struct { Name string `json:"name"` // the name of the new rom Managers []snowflake.Snowflake `json:"managers"` // ids of manager accounts for this room (there must be at least one) Private bool `json:"private,omitempty"` // if true, create a private room (all managers will be granted access) }
The `staff-create-room` command creates a new room.
type StaffCreateRoomReply ¶
type StaffCreateRoomReply struct { Success bool `json:"success"` // whether the room was created FailureReason string `json:"failure_reason,omitempty"` // if `success` was false, the reason why }
`staff-create-room-reply` returns the outcome of a room creation request.
type StaffEnrollOTPCommand ¶
type StaffEnrollOTPCommand struct{}
The `staff-enroll-otp` command generates a new OTP key for a staff user. The user must then validate the key by issuing a successful `staff-validate-otp` command. An error will be returned if the user already has a validated OTP key.
type StaffEnrollOTPReply ¶
type StaffEnrollOTPReply struct { URI string `json:"uri"` // the otpauth URI for the generated key (https://github.com/google/google-authenticator/wiki/Key-Uri-Format) QRImage string `json:"qr_uri"` // the data URI for a QR image encoding the otpauth URI }
`staff-enroll-otp-reply` returns the OTP key in several forms that a user can use to import into their personal authentication app.
type StaffGrantManagerCommand ¶
type StaffGrantManagerCommand GrantManagerCommand
The `staff-grant-manager` command is a version of the [grant-manager](#grant-manager) command that is available to staff. The staff account does not need to be a manager of the room to use this command.
type StaffGrantManagerReply ¶
type StaffGrantManagerReply GrantManagerReply
`staff-grant-manager-reply` confirms that requested manager change was granted.
type StaffInspectIPCommand ¶
type StaffInspectIPCommand struct {
IP string `json:"ip"` // the IP or virtual client address to inspect
}
The `staff-inspect-ip` command looks up details about a given IP address or virtual client address.
type StaffInspectIPReply ¶
type StaffInspectIPReply struct { IP string `json:"ip"` // the IP address resolved from the virtual address Details json.RawMessage `json:"details"` // details looked up about the IP address }
`staff-inspect-ip-reply` returns details about the requested address.
type StaffInvadeCommand ¶
type StaffInvadeCommand struct {
Password string `json:"password"` // the staff member's current one-time password
}
The `staff-invade` command can be used by staff to acquire temporary host and/or access capabilities in the current room.
type StaffInvadeReply ¶
type StaffInvadeReply struct{}
`staff-invade-reply` indicates that the current session now holds host and access capabilities in the room.
type StaffLockRoomCommand ¶
type StaffLockRoomCommand struct{}
The `staff-lock-room` command makes a room private. If the room is already private, then it generates a new message key (which currently invalidates all access grants).
type StaffLockRoomReply ¶
type StaffLockRoomReply struct{}
`staff-lock-room-reply` confirms that the room has been made newly private.
type StaffRevokeAccessCommand ¶
type StaffRevokeAccessCommand RevokeAccessCommand
The `staff-revoke-access` command is a version of the [revoke-access](#revoke-access) command that is available to staff. The staff account does not need to be a manager of the room to use this command.
type StaffRevokeAccessReply ¶
type StaffRevokeAccessReply RevokeAccessReply
`staff-revoke-access-reply` confirms that requested access capability was revoked.
type StaffRevokeManagerCommand ¶
type StaffRevokeManagerCommand RevokeManagerCommand
The `staff-revoke-manager` command is a version of the [revoke-manager](#revoke-access) command that is available to staff. The staff account does not need to be a manager of the room to use this command.
type StaffRevokeManagerReply ¶
type StaffRevokeManagerReply RevokeManagerReply
`staff-revoke-manager-reply` confirms that requested manager capability was revoked.
type StaffValidateOTPCommand ¶
type StaffValidateOTPCommand struct {
Password string `json:"password"`
}
The `staff-validate-otp` command validates a one-time password against the latest OTP key generated for the user by the `staff-enroll-otp` command.
type StaffValidateOTPReply ¶
type StaffValidateOTPReply struct{}
`staff-validate-otp-reply` indicates successful authentication with the given one-time password.
type UnbanCommand ¶
type UnbanCommand struct {
Ban
}
The `unban` command removes an entry from the room's ban list.
type UnbanReply ¶
type UnbanReply UnbanCommand
The `unban-reply` packet indicates that the `unban` command succeeded.
type UnlockStaffCapabilityCommand ¶
type UnlockStaffCapabilityCommand struct {
Password string `json:"password"` // the account's password
}
The `unlock-staff-capability` command may be called by a staff account to gain access to staff commands.
type UnlockStaffCapabilityReply ¶
type UnlockStaffCapabilityReply struct { Success bool `json:"success"` // whether staff capability was unlocked FailureReason string `json:"failure_reason,omitempty"` // if `success` was false, the reason why }
`unlock-staff-capability-reply` returns the outcome of unlocking the staff capability.
type VerificationEmailParams ¶
type VerificationEmailParams struct { CommonEmailParams VerificationToken string }
func (VerificationEmailParams) Subject ¶
func (p VerificationEmailParams) Subject() template.HTML
func (VerificationEmailParams) VerifyEmailURL ¶
func (p VerificationEmailParams) VerifyEmailURL() template.HTML
type WelcomeEmailParams ¶
type WelcomeEmailParams struct { CommonEmailParams VerificationToken string }
func (WelcomeEmailParams) Subject ¶
func (p WelcomeEmailParams) Subject() template.HTML
func (*WelcomeEmailParams) VerifyEmailURL ¶
func (p *WelcomeEmailParams) VerifyEmailURL() template.HTML
type WhoCommand ¶
type WhoCommand struct{}
The `who` command requests a list of sessions currently joined in the room.