types.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // Package user deals with authentication and authorization against topics
  2. package user
  3. import (
  4. "errors"
  5. "regexp"
  6. "time"
  7. )
  8. // User is a struct that represents a user
  9. type User struct {
  10. Name string
  11. Hash string // password hash (bcrypt)
  12. Token string // Only set if token was used to log in
  13. Role Role
  14. Grants []Grant
  15. Prefs *Prefs
  16. Plan *Plan
  17. Stats *Stats
  18. }
  19. // Auther is an interface for authentication and authorization
  20. type Auther interface {
  21. // Authenticate checks username and password and returns a user if correct. The method
  22. // returns in constant-ish time, regardless of whether the user exists or the password is
  23. // correct or incorrect.
  24. Authenticate(username, password string) (*User, error)
  25. // Authorize returns nil if the given user has access to the given topic using the desired
  26. // permission. The user param may be nil to signal an anonymous user.
  27. Authorize(user *User, topic string, perm Permission) error
  28. }
  29. // Token represents a user token, including expiry date
  30. type Token struct {
  31. Value string
  32. Expires time.Time
  33. }
  34. // Prefs represents a user's configuration settings
  35. type Prefs struct {
  36. Language string `json:"language,omitempty"`
  37. Notification *NotificationPrefs `json:"notification,omitempty"`
  38. Subscriptions []*Subscription `json:"subscriptions,omitempty"`
  39. }
  40. // PlanCode is code identifying a user's plan
  41. type PlanCode string
  42. // Default plan codes
  43. const (
  44. PlanUnlimited = PlanCode("unlimited")
  45. PlanDefault = PlanCode("default")
  46. PlanNone = PlanCode("none")
  47. )
  48. // Plan represents a user's account type, including its account limits
  49. type Plan struct {
  50. Code string `json:"name"`
  51. Upgradable bool `json:"upgradable"`
  52. MessagesLimit int64 `json:"messages_limit"`
  53. EmailsLimit int64 `json:"emails_limit"`
  54. AttachmentFileSizeLimit int64 `json:"attachment_file_size_limit"`
  55. AttachmentTotalSizeLimit int64 `json:"attachment_total_size_limit"`
  56. }
  57. // Subscription represents a user's topic subscription
  58. type Subscription struct {
  59. ID string `json:"id"`
  60. BaseURL string `json:"base_url"`
  61. Topic string `json:"topic"`
  62. DisplayName string `json:"display_name"`
  63. }
  64. // NotificationPrefs represents the user's notification settings
  65. type NotificationPrefs struct {
  66. Sound string `json:"sound,omitempty"`
  67. MinPriority int `json:"min_priority,omitempty"`
  68. DeleteAfter int `json:"delete_after,omitempty"`
  69. }
  70. // Stats is a struct holding daily user statistics
  71. type Stats struct {
  72. Messages int64
  73. Emails int64
  74. }
  75. // Grant is a struct that represents an access control entry to a topic
  76. type Grant struct {
  77. TopicPattern string // May include wildcard (*)
  78. AllowRead bool
  79. AllowWrite bool
  80. }
  81. // Permission represents a read or write permission to a topic
  82. type Permission int
  83. // Permissions to a topic
  84. const (
  85. PermissionRead = Permission(1)
  86. PermissionWrite = Permission(2)
  87. )
  88. // Role represents a user's role, either admin or regular user
  89. type Role string
  90. // User roles
  91. const (
  92. RoleAdmin = Role("admin") // Some queries have these values hardcoded!
  93. RoleUser = Role("user")
  94. RoleAnonymous = Role("anonymous")
  95. )
  96. // Everyone is a special username representing anonymous users
  97. const (
  98. Everyone = "*"
  99. )
  100. var (
  101. allowedUsernameRegex = regexp.MustCompile(`^[-_.@a-zA-Z0-9]+$`) // Does not include Everyone (*)
  102. allowedTopicPatternRegex = regexp.MustCompile(`^[-_*A-Za-z0-9]{1,64}$`) // Adds '*' for wildcards!
  103. )
  104. // AllowedRole returns true if the given role can be used for new users
  105. func AllowedRole(role Role) bool {
  106. return role == RoleUser || role == RoleAdmin
  107. }
  108. // AllowedUsername returns true if the given username is valid
  109. func AllowedUsername(username string) bool {
  110. return allowedUsernameRegex.MatchString(username)
  111. }
  112. // AllowedTopicPattern returns true if the given topic pattern is valid; this includes the wildcard character (*)
  113. func AllowedTopicPattern(username string) bool {
  114. return allowedTopicPatternRegex.MatchString(username)
  115. }
  116. // Error constants used by the package
  117. var (
  118. ErrUnauthenticated = errors.New("unauthenticated")
  119. ErrUnauthorized = errors.New("unauthorized")
  120. ErrInvalidArgument = errors.New("invalid argument")
  121. ErrNotFound = errors.New("not found")
  122. )