types.go 3.7 KB

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