Rename plan->tier, topics->reservations, more tests, more todos
This commit is contained in:
parent
df512d0ba2
commit
1f54adad71
14 changed files with 298 additions and 134 deletions
|
@ -502,7 +502,7 @@ func (c *messageCache) AttachmentsExpired() ([]string, error) {
|
|||
return ids, nil
|
||||
}
|
||||
|
||||
func (c *messageCache) MarkAttachmentsDeleted(ids []string) error {
|
||||
func (c *messageCache) MarkAttachmentsDeleted(ids ...string) error {
|
||||
tx, err := c.db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -57,8 +57,9 @@ import (
|
|||
- visitor with/without user
|
||||
- plan-based message expiry
|
||||
- plan-based attachment expiry
|
||||
Docs:
|
||||
- "expires" field in message
|
||||
Refactor:
|
||||
- rename TopicsLimit -> ReservationsLimit
|
||||
- rename /access -> /reservation
|
||||
Later:
|
||||
- Password reset
|
||||
|
@ -544,8 +545,8 @@ func (s *Server) handlePublishWithoutResponse(r *http.Request, v *visitor) (*mes
|
|||
if v.user != nil {
|
||||
m.User = v.user.Name
|
||||
}
|
||||
if v.user != nil && v.user.Plan != nil {
|
||||
m.Expires = time.Now().Unix() + v.user.Plan.MessagesExpiryDuration
|
||||
if v.user != nil && v.user.Tier != nil {
|
||||
m.Expires = time.Now().Unix() + v.user.Tier.MessagesExpiryDuration
|
||||
} else {
|
||||
m.Expires = time.Now().Add(s.config.CacheDuration).Unix()
|
||||
}
|
||||
|
@ -822,8 +823,8 @@ func (s *Server) handleBodyAsAttachment(r *http.Request, v *visitor, m *message,
|
|||
return errHTTPBadRequestAttachmentsDisallowed
|
||||
}
|
||||
var attachmentExpiryDuration time.Duration
|
||||
if v.user != nil && v.user.Plan != nil {
|
||||
attachmentExpiryDuration = time.Duration(v.user.Plan.AttachmentExpiryDuration) * time.Second
|
||||
if v.user != nil && v.user.Tier != nil {
|
||||
attachmentExpiryDuration = time.Duration(v.user.Tier.AttachmentExpiryDuration) * time.Second
|
||||
} else {
|
||||
attachmentExpiryDuration = s.config.AttachmentExpiryDuration
|
||||
}
|
||||
|
@ -1240,13 +1241,16 @@ func (s *Server) execManager() {
|
|||
if s.fileCache != nil {
|
||||
ids, err := s.messageCache.AttachmentsExpired()
|
||||
if err != nil {
|
||||
log.Warn("Error retrieving expired attachments: %s", err.Error())
|
||||
log.Warn("Manager: Error retrieving expired attachments: %s", err.Error())
|
||||
} else if len(ids) > 0 {
|
||||
if err := s.fileCache.Remove(ids...); err != nil {
|
||||
log.Warn("Error deleting attachments: %s", err.Error())
|
||||
if log.IsDebug() {
|
||||
log.Debug("Manager: Deleting attachments %s", strings.Join(ids, ", "))
|
||||
}
|
||||
if err := s.messageCache.MarkAttachmentsDeleted(ids); err != nil {
|
||||
log.Warn("Error marking attachments deleted: %s", err.Error())
|
||||
if err := s.fileCache.Remove(ids...); err != nil {
|
||||
log.Warn("Manager: Error deleting attachments: %s", err.Error())
|
||||
}
|
||||
if err := s.messageCache.MarkAttachmentsDeleted(ids...); err != nil {
|
||||
log.Warn("Manager: Error marking attachments deleted: %s", err.Error())
|
||||
}
|
||||
} else {
|
||||
log.Debug("Manager: No expired attachments to delete")
|
||||
|
|
|
@ -50,8 +50,8 @@ func (s *Server) handleAccountGet(w http.ResponseWriter, _ *http.Request, v *vis
|
|||
MessagesRemaining: stats.MessagesRemaining,
|
||||
Emails: stats.Emails,
|
||||
EmailsRemaining: stats.EmailsRemaining,
|
||||
Topics: stats.Topics,
|
||||
TopicsRemaining: stats.TopicsRemaining,
|
||||
Reservations: stats.Reservations,
|
||||
ReservationsRemaining: stats.ReservationsRemaining,
|
||||
AttachmentTotalSize: stats.AttachmentTotalSize,
|
||||
AttachmentTotalSizeRemaining: stats.AttachmentTotalSizeRemaining,
|
||||
},
|
||||
|
@ -60,7 +60,7 @@ func (s *Server) handleAccountGet(w http.ResponseWriter, _ *http.Request, v *vis
|
|||
Messages: stats.MessagesLimit,
|
||||
MessagesExpiryDuration: stats.MessagesExpiryDuration,
|
||||
Emails: stats.EmailsLimit,
|
||||
Topics: stats.TopicsLimit,
|
||||
Reservations: stats.ReservationsLimit,
|
||||
AttachmentTotalSize: stats.AttachmentTotalSizeLimit,
|
||||
AttachmentFileSize: stats.AttachmentFileSizeLimit,
|
||||
AttachmentExpiryDuration: stats.AttachmentExpiryDuration,
|
||||
|
@ -80,19 +80,19 @@ func (s *Server) handleAccountGet(w http.ResponseWriter, _ *http.Request, v *vis
|
|||
response.Subscriptions = v.user.Prefs.Subscriptions
|
||||
}
|
||||
}
|
||||
if v.user.Plan != nil {
|
||||
response.Plan = &apiAccountPlan{
|
||||
Code: v.user.Plan.Code,
|
||||
Upgradeable: v.user.Plan.Upgradeable,
|
||||
if v.user.Tier != nil {
|
||||
response.Tier = &apiAccountTier{
|
||||
Code: v.user.Tier.Code,
|
||||
Upgradeable: v.user.Tier.Upgradeable,
|
||||
}
|
||||
} else if v.user.Role == user.RoleAdmin {
|
||||
response.Plan = &apiAccountPlan{
|
||||
Code: string(user.PlanUnlimited),
|
||||
response.Tier = &apiAccountTier{
|
||||
Code: string(user.TierUnlimited),
|
||||
Upgradeable: false,
|
||||
}
|
||||
} else {
|
||||
response.Plan = &apiAccountPlan{
|
||||
Code: string(user.PlanDefault),
|
||||
response.Tier = &apiAccountTier{
|
||||
Code: string(user.TierDefault),
|
||||
Upgradeable: true,
|
||||
}
|
||||
}
|
||||
|
@ -112,8 +112,8 @@ func (s *Server) handleAccountGet(w http.ResponseWriter, _ *http.Request, v *vis
|
|||
} else {
|
||||
response.Username = user.Everyone
|
||||
response.Role = string(user.RoleAnonymous)
|
||||
response.Plan = &apiAccountPlan{
|
||||
Code: string(user.PlanNone),
|
||||
response.Tier = &apiAccountTier{
|
||||
Code: string(user.TierNone),
|
||||
Upgradeable: true,
|
||||
}
|
||||
}
|
||||
|
@ -340,7 +340,7 @@ func (s *Server) handleAccountAccessAdd(w http.ResponseWriter, r *http.Request,
|
|||
if err != nil {
|
||||
return errHTTPBadRequestPermissionInvalid
|
||||
}
|
||||
if v.user.Plan == nil {
|
||||
if v.user.Tier == nil {
|
||||
return errHTTPUnauthorized // FIXME there should always be a plan!
|
||||
}
|
||||
if err := s.userManager.CheckAllowAccess(v.user.Name, req.Topic); err != nil {
|
||||
|
@ -354,7 +354,7 @@ func (s *Server) handleAccountAccessAdd(w http.ResponseWriter, r *http.Request,
|
|||
reservations, err := s.userManager.ReservationsCount(v.user.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if reservations >= v.user.Plan.TopicsLimit {
|
||||
} else if reservations >= v.user.Tier.ReservationsLimit {
|
||||
return errHTTPTooManyRequestsLimitReservations
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/require"
|
||||
"heckel.io/ntfy/user"
|
||||
|
@ -343,7 +342,7 @@ func TestAccount_Delete_Not_Allowed(t *testing.T) {
|
|||
require.Equal(t, 401, rr.Code)
|
||||
}
|
||||
|
||||
func TestAccount_Reservation_Add_User_No_Plan_Failure(t *testing.T) {
|
||||
func TestAccount_Reservation_AddWithoutTierFails(t *testing.T) {
|
||||
conf := newTestConfigWithAuthFile(t)
|
||||
conf.EnableSignup = true
|
||||
s := newTestServer(t, conf)
|
||||
|
@ -357,7 +356,7 @@ func TestAccount_Reservation_Add_User_No_Plan_Failure(t *testing.T) {
|
|||
require.Equal(t, 401, rr.Code)
|
||||
}
|
||||
|
||||
func TestAccount_Reservation_Add_Admin_Success(t *testing.T) {
|
||||
func TestAccount_Reservation_AddAdminSuccess(t *testing.T) {
|
||||
conf := newTestConfigWithAuthFile(t)
|
||||
conf.EnableSignup = true
|
||||
s := newTestServer(t, conf)
|
||||
|
@ -370,7 +369,7 @@ func TestAccount_Reservation_Add_Admin_Success(t *testing.T) {
|
|||
require.Equal(t, 40026, toHTTPError(t, rr.Body.String()).Code)
|
||||
}
|
||||
|
||||
func TestAccount_Reservation_Add_Remove_User_With_Plan_Success(t *testing.T) {
|
||||
func TestAccount_Reservation_AddRemoveUserWithTierSuccess(t *testing.T) {
|
||||
conf := newTestConfigWithAuthFile(t)
|
||||
conf.EnableSignup = true
|
||||
s := newTestServer(t, conf)
|
||||
|
@ -379,17 +378,19 @@ func TestAccount_Reservation_Add_Remove_User_With_Plan_Success(t *testing.T) {
|
|||
rr := request(t, s, "POST", "/v1/account", `{"username":"phil", "password":"mypass"}`, nil)
|
||||
require.Equal(t, 200, rr.Code)
|
||||
|
||||
// Create a plan (hack!)
|
||||
db, err := sql.Open("sqlite3", conf.AuthFile)
|
||||
require.Nil(t, err)
|
||||
|
||||
_, err = db.Exec(`
|
||||
INSERT INTO plan (id, code, messages_limit, messages_expiry_duration, emails_limit, attachment_file_size_limit, attachment_total_size_limit, attachment_expiry_duration, topics_limit)
|
||||
VALUES (1, 'testplan', 10, 86400, 10, 10, 10, 10800, 2);
|
||||
|
||||
UPDATE user SET plan_id = 1 WHERE user = 'phil';
|
||||
`)
|
||||
require.Nil(t, err)
|
||||
// Create a tier
|
||||
require.Nil(t, s.userManager.CreateTier(&user.Tier{
|
||||
Code: "pro",
|
||||
Upgradeable: false,
|
||||
MessagesLimit: 123,
|
||||
MessagesExpiryDuration: 86400,
|
||||
EmailsLimit: 32,
|
||||
ReservationsLimit: 2,
|
||||
AttachmentFileSizeLimit: 1231231,
|
||||
AttachmentTotalSizeLimit: 123123,
|
||||
AttachmentExpiryDuration: 10800,
|
||||
}))
|
||||
require.Nil(t, s.userManager.ChangeTier("phil", "pro"))
|
||||
|
||||
// Reserve two topics
|
||||
rr = request(t, s, "POST", "/v1/account/access", `{"topic": "mytopic", "everyone":"deny-all"}`, map[string]string{
|
||||
|
@ -420,6 +421,14 @@ func TestAccount_Reservation_Add_Remove_User_With_Plan_Success(t *testing.T) {
|
|||
})
|
||||
require.Equal(t, 200, rr.Code)
|
||||
account, _ := util.UnmarshalJSON[apiAccountResponse](io.NopCloser(rr.Body))
|
||||
require.Equal(t, "pro", account.Tier.Code)
|
||||
require.Equal(t, int64(123), account.Limits.Messages)
|
||||
require.Equal(t, int64(86400), account.Limits.MessagesExpiryDuration)
|
||||
require.Equal(t, int64(32), account.Limits.Emails)
|
||||
require.Equal(t, int64(2), account.Limits.Reservations)
|
||||
require.Equal(t, int64(1231231), account.Limits.AttachmentFileSize)
|
||||
require.Equal(t, int64(123123), account.Limits.AttachmentTotalSize)
|
||||
require.Equal(t, int64(10800), account.Limits.AttachmentExpiryDuration)
|
||||
require.Equal(t, 2, len(account.Reservations))
|
||||
require.Equal(t, "another", account.Reservations[0].Topic)
|
||||
require.Equal(t, "write-only", account.Reservations[0].Everyone)
|
||||
|
@ -441,27 +450,21 @@ func TestAccount_Reservation_Add_Remove_User_With_Plan_Success(t *testing.T) {
|
|||
require.Equal(t, "mytopic", account.Reservations[0].Topic)
|
||||
}
|
||||
|
||||
func TestAccount_Reservation_Add_Access_By_Anonymous_Fails(t *testing.T) {
|
||||
func TestAccount_Reservation_PublishByAnonymousFails(t *testing.T) {
|
||||
conf := newTestConfigWithAuthFile(t)
|
||||
conf.AuthDefault = user.PermissionReadWrite
|
||||
conf.EnableSignup = true
|
||||
s := newTestServer(t, conf)
|
||||
|
||||
// Create user
|
||||
// Create user with tier
|
||||
rr := request(t, s, "POST", "/v1/account", `{"username":"phil", "password":"mypass"}`, nil)
|
||||
require.Equal(t, 200, rr.Code)
|
||||
|
||||
// Create a plan (hack!)
|
||||
db, err := sql.Open("sqlite3", conf.AuthFile)
|
||||
require.Nil(t, err)
|
||||
|
||||
_, err = db.Exec(`
|
||||
INSERT INTO plan (id, code, messages_limit, messages_expiry_duration, emails_limit, attachment_file_size_limit, attachment_total_size_limit, attachment_expiry_duration, topics_limit)
|
||||
VALUES (1, 'testplan', 10, 86400, 10, 10, 10, 10800, 2);
|
||||
|
||||
UPDATE user SET plan_id = 1 WHERE user = 'phil';
|
||||
`)
|
||||
require.Nil(t, err)
|
||||
require.Nil(t, s.userManager.CreateTier(&user.Tier{
|
||||
Code: "pro",
|
||||
ReservationsLimit: 2,
|
||||
}))
|
||||
require.Nil(t, s.userManager.ChangeTier("phil", "pro"))
|
||||
|
||||
// Reserve a topic
|
||||
rr = request(t, s, "POST", "/v1/account/access", `{"topic": "mytopic", "everyone":"deny-all"}`, map[string]string{
|
||||
|
|
|
@ -1090,6 +1090,34 @@ func TestServer_PublishAsJSON_Invalid(t *testing.T) {
|
|||
require.Equal(t, 400, response.Code)
|
||||
}
|
||||
|
||||
func TestServer_PublishWithTierBasedMessageLimitAndExpiry(t *testing.T) {
|
||||
c := newTestConfigWithAuthFile(t)
|
||||
s := newTestServer(t, c)
|
||||
|
||||
// Create tier with certain limits
|
||||
require.Nil(t, s.userManager.CreateTier(&user.Tier{
|
||||
Code: "test",
|
||||
MessagesLimit: 5,
|
||||
MessagesExpiryDuration: 1, // Second
|
||||
}))
|
||||
require.Nil(t, s.userManager.AddUser("phil", "phil", user.RoleUser))
|
||||
require.Nil(t, s.userManager.ChangeTier("phil", "test"))
|
||||
|
||||
// Publish to reach message limit
|
||||
for i := 0; i < 5; i++ {
|
||||
response := request(t, s, "PUT", "/mytopic", fmt.Sprintf("this is message %d", i+1), map[string]string{
|
||||
"Authorization": util.BasicAuth("phil", "phil"),
|
||||
})
|
||||
require.Equal(t, 200, response.Code)
|
||||
msg := toMessage(t, response.Body.String())
|
||||
require.True(t, msg.Expires < time.Now().Unix()+5)
|
||||
}
|
||||
response := request(t, s, "PUT", "/mytopic", "this is too much", map[string]string{
|
||||
"Authorization": util.BasicAuth("phil", "phil"),
|
||||
})
|
||||
require.Equal(t, 413, response.Code)
|
||||
}
|
||||
|
||||
func TestServer_PublishAttachment(t *testing.T) {
|
||||
content := util.RandomString(5000) // > 4096
|
||||
s := newTestServer(t, newTestConfig(t))
|
||||
|
@ -1271,7 +1299,7 @@ func TestServer_PublishAttachmentAndPrune(t *testing.T) {
|
|||
require.Equal(t, 200, response.Code)
|
||||
require.Equal(t, content, response.Body.String())
|
||||
|
||||
// DeleteMessages and makes sure it's gone
|
||||
// Prune and makes sure it's gone
|
||||
time.Sleep(time.Second) // Sigh ...
|
||||
s.execManager()
|
||||
require.NoFileExists(t, file)
|
||||
|
@ -1279,6 +1307,99 @@ func TestServer_PublishAttachmentAndPrune(t *testing.T) {
|
|||
require.Equal(t, 404, response.Code)
|
||||
}
|
||||
|
||||
func TestServer_PublishAttachmentWithTierBasedExpiry(t *testing.T) {
|
||||
content := util.RandomString(5000) // > 4096
|
||||
|
||||
c := newTestConfigWithAuthFile(t)
|
||||
c.AttachmentExpiryDuration = time.Millisecond // Hack
|
||||
s := newTestServer(t, c)
|
||||
|
||||
// Create tier with certain limits
|
||||
sevenDaysInSeconds := int64(604800)
|
||||
require.Nil(t, s.userManager.CreateTier(&user.Tier{
|
||||
Code: "test",
|
||||
MessagesExpiryDuration: sevenDaysInSeconds,
|
||||
AttachmentFileSizeLimit: 50_000,
|
||||
AttachmentTotalSizeLimit: 200_000,
|
||||
AttachmentExpiryDuration: sevenDaysInSeconds, // 7 days
|
||||
}))
|
||||
require.Nil(t, s.userManager.AddUser("phil", "phil", user.RoleUser))
|
||||
require.Nil(t, s.userManager.ChangeTier("phil", "test"))
|
||||
|
||||
// Publish and make sure we can retrieve it
|
||||
response := request(t, s, "PUT", "/mytopic", content, map[string]string{
|
||||
"Authorization": util.BasicAuth("phil", "phil"),
|
||||
})
|
||||
msg := toMessage(t, response.Body.String())
|
||||
require.Contains(t, msg.Attachment.URL, "http://127.0.0.1:12345/file/")
|
||||
require.True(t, msg.Attachment.Expires > time.Now().Unix()+sevenDaysInSeconds-30)
|
||||
require.True(t, msg.Expires > time.Now().Unix()+sevenDaysInSeconds-30)
|
||||
file := filepath.Join(s.config.AttachmentCacheDir, msg.ID)
|
||||
require.FileExists(t, file)
|
||||
|
||||
path := strings.TrimPrefix(msg.Attachment.URL, "http://127.0.0.1:12345")
|
||||
response = request(t, s, "GET", path, "", nil)
|
||||
require.Equal(t, 200, response.Code)
|
||||
require.Equal(t, content, response.Body.String())
|
||||
|
||||
// Prune and makes sure it's still there
|
||||
time.Sleep(time.Second) // Sigh ...
|
||||
s.execManager()
|
||||
require.FileExists(t, file)
|
||||
response = request(t, s, "GET", path, "", nil)
|
||||
require.Equal(t, 200, response.Code)
|
||||
}
|
||||
|
||||
func TestServer_PublishAttachmentWithTierBasedLimits(t *testing.T) {
|
||||
smallFile := util.RandomString(20_000)
|
||||
largeFile := util.RandomString(50_000)
|
||||
|
||||
c := newTestConfigWithAuthFile(t)
|
||||
c.AttachmentFileSizeLimit = 20_000
|
||||
c.VisitorAttachmentTotalSizeLimit = 40_000
|
||||
s := newTestServer(t, c)
|
||||
|
||||
// Create tier with certain limits
|
||||
require.Nil(t, s.userManager.CreateTier(&user.Tier{
|
||||
Code: "test",
|
||||
AttachmentFileSizeLimit: 50_000,
|
||||
AttachmentTotalSizeLimit: 200_000,
|
||||
}))
|
||||
require.Nil(t, s.userManager.AddUser("phil", "phil", user.RoleUser))
|
||||
require.Nil(t, s.userManager.ChangeTier("phil", "test"))
|
||||
|
||||
// Publish small file as anonymous
|
||||
response := request(t, s, "PUT", "/mytopic", smallFile, nil)
|
||||
msg := toMessage(t, response.Body.String())
|
||||
require.Contains(t, msg.Attachment.URL, "http://127.0.0.1:12345/file/")
|
||||
require.FileExists(t, filepath.Join(s.config.AttachmentCacheDir, msg.ID))
|
||||
|
||||
// Publish large file as anonymous
|
||||
response = request(t, s, "PUT", "/mytopic", largeFile, nil)
|
||||
require.Equal(t, 413, response.Code)
|
||||
|
||||
// Publish too large file as phil
|
||||
response = request(t, s, "PUT", "/mytopic", largeFile+" a few more bytes", map[string]string{
|
||||
"Authorization": util.BasicAuth("phil", "phil"),
|
||||
})
|
||||
require.Equal(t, 413, response.Code)
|
||||
|
||||
// Publish large file as phil (4x)
|
||||
for i := 0; i < 4; i++ {
|
||||
response = request(t, s, "PUT", "/mytopic", largeFile, map[string]string{
|
||||
"Authorization": util.BasicAuth("phil", "phil"),
|
||||
})
|
||||
require.Equal(t, 200, response.Code)
|
||||
msg = toMessage(t, response.Body.String())
|
||||
require.Contains(t, msg.Attachment.URL, "http://127.0.0.1:12345/file/")
|
||||
require.FileExists(t, filepath.Join(s.config.AttachmentCacheDir, msg.ID))
|
||||
}
|
||||
response = request(t, s, "PUT", "/mytopic", largeFile, map[string]string{
|
||||
"Authorization": util.BasicAuth("phil", "phil"),
|
||||
})
|
||||
require.Equal(t, 413, response.Code)
|
||||
}
|
||||
|
||||
func TestServer_PublishAttachmentBandwidthLimit(t *testing.T) {
|
||||
content := util.RandomString(5000) // > 4096
|
||||
|
||||
|
|
|
@ -235,17 +235,17 @@ type apiAccountTokenResponse struct {
|
|||
Expires int64 `json:"expires"`
|
||||
}
|
||||
|
||||
type apiAccountPlan struct {
|
||||
type apiAccountTier struct {
|
||||
Code string `json:"code"`
|
||||
Upgradeable bool `json:"upgradeable"`
|
||||
}
|
||||
|
||||
type apiAccountLimits struct {
|
||||
Basis string `json:"basis"` // "ip", "role" or "plan"
|
||||
Basis string `json:"basis"` // "ip", "role" or "tier"
|
||||
Messages int64 `json:"messages"`
|
||||
MessagesExpiryDuration int64 `json:"messages_expiry_duration"`
|
||||
Emails int64 `json:"emails"`
|
||||
Topics int64 `json:"topics"`
|
||||
Reservations int64 `json:"reservations"`
|
||||
AttachmentTotalSize int64 `json:"attachment_total_size"`
|
||||
AttachmentFileSize int64 `json:"attachment_file_size"`
|
||||
AttachmentExpiryDuration int64 `json:"attachment_expiry_duration"`
|
||||
|
@ -256,8 +256,8 @@ type apiAccountStats struct {
|
|||
MessagesRemaining int64 `json:"messages_remaining"`
|
||||
Emails int64 `json:"emails"`
|
||||
EmailsRemaining int64 `json:"emails_remaining"`
|
||||
Topics int64 `json:"topics"`
|
||||
TopicsRemaining int64 `json:"topics_remaining"`
|
||||
Reservations int64 `json:"reservations"`
|
||||
ReservationsRemaining int64 `json:"reservations_remaining"`
|
||||
AttachmentTotalSize int64 `json:"attachment_total_size"`
|
||||
AttachmentTotalSizeRemaining int64 `json:"attachment_total_size_remaining"`
|
||||
}
|
||||
|
@ -274,7 +274,7 @@ type apiAccountResponse struct {
|
|||
Notification *user.NotificationPrefs `json:"notification,omitempty"`
|
||||
Subscriptions []*user.Subscription `json:"subscriptions,omitempty"`
|
||||
Reservations []*apiAccountReservation `json:"reservations,omitempty"`
|
||||
Plan *apiAccountPlan `json:"plan,omitempty"`
|
||||
Tier *apiAccountTier `json:"tier,omitempty"`
|
||||
Limits *apiAccountLimits `json:"limits,omitempty"`
|
||||
Stats *apiAccountStats `json:"stats,omitempty"`
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ type visitor struct {
|
|||
}
|
||||
|
||||
type visitorInfo struct {
|
||||
Basis string // "ip", "role" or "plan"
|
||||
Basis string // "ip", "role" or "tier"
|
||||
Messages int64
|
||||
MessagesLimit int64
|
||||
MessagesRemaining int64
|
||||
|
@ -50,9 +50,9 @@ type visitorInfo struct {
|
|||
Emails int64
|
||||
EmailsLimit int64
|
||||
EmailsRemaining int64
|
||||
Topics int64
|
||||
TopicsLimit int64
|
||||
TopicsRemaining int64
|
||||
Reservations int64
|
||||
ReservationsLimit int64
|
||||
ReservationsRemaining int64
|
||||
AttachmentTotalSize int64
|
||||
AttachmentTotalSizeLimit int64
|
||||
AttachmentTotalSizeRemaining int64
|
||||
|
@ -69,9 +69,9 @@ func newVisitor(conf *Config, messageCache *messageCache, userManager *user.Mana
|
|||
} else {
|
||||
accountLimiter = rate.NewLimiter(rate.Every(conf.VisitorAccountCreateLimitReplenish), conf.VisitorAccountCreateLimitBurst)
|
||||
}
|
||||
if user != nil && user.Plan != nil {
|
||||
requestLimiter = rate.NewLimiter(dailyLimitToRate(user.Plan.MessagesLimit), conf.VisitorRequestLimitBurst)
|
||||
emailsLimiter = rate.NewLimiter(dailyLimitToRate(user.Plan.EmailsLimit), conf.VisitorEmailLimitBurst)
|
||||
if user != nil && user.Tier != nil {
|
||||
requestLimiter = rate.NewLimiter(dailyLimitToRate(user.Tier.MessagesLimit), conf.VisitorRequestLimitBurst)
|
||||
emailsLimiter = rate.NewLimiter(dailyLimitToRate(user.Tier.EmailsLimit), conf.VisitorEmailLimitBurst)
|
||||
} else {
|
||||
requestLimiter = rate.NewLimiter(rate.Every(conf.VisitorRequestLimitReplenish), conf.VisitorRequestLimitBurst)
|
||||
emailsLimiter = rate.NewLimiter(rate.Every(conf.VisitorEmailLimitReplenish), conf.VisitorEmailLimitBurst)
|
||||
|
@ -183,21 +183,21 @@ func (v *visitor) Info() (*visitorInfo, error) {
|
|||
// All limits are zero!
|
||||
info.MessagesExpiryDuration = 24 * 3600 // FIXME this is awful. Should be from the Unlimited plan
|
||||
info.AttachmentExpiryDuration = 24 * 3600 // FIXME this is awful. Should be from the Unlimited plan
|
||||
} else if v.user != nil && v.user.Plan != nil {
|
||||
info.Basis = "plan"
|
||||
info.MessagesLimit = v.user.Plan.MessagesLimit
|
||||
info.MessagesExpiryDuration = v.user.Plan.MessagesExpiryDuration
|
||||
info.EmailsLimit = v.user.Plan.EmailsLimit
|
||||
info.TopicsLimit = v.user.Plan.TopicsLimit
|
||||
info.AttachmentTotalSizeLimit = v.user.Plan.AttachmentTotalSizeLimit
|
||||
info.AttachmentFileSizeLimit = v.user.Plan.AttachmentFileSizeLimit
|
||||
info.AttachmentExpiryDuration = v.user.Plan.AttachmentExpiryDuration
|
||||
} else if v.user != nil && v.user.Tier != nil {
|
||||
info.Basis = "tier"
|
||||
info.MessagesLimit = v.user.Tier.MessagesLimit
|
||||
info.MessagesExpiryDuration = v.user.Tier.MessagesExpiryDuration
|
||||
info.EmailsLimit = v.user.Tier.EmailsLimit
|
||||
info.ReservationsLimit = v.user.Tier.ReservationsLimit
|
||||
info.AttachmentTotalSizeLimit = v.user.Tier.AttachmentTotalSizeLimit
|
||||
info.AttachmentFileSizeLimit = v.user.Tier.AttachmentFileSizeLimit
|
||||
info.AttachmentExpiryDuration = v.user.Tier.AttachmentExpiryDuration
|
||||
} else {
|
||||
info.Basis = "ip"
|
||||
info.MessagesLimit = replenishDurationToDailyLimit(v.config.VisitorRequestLimitReplenish)
|
||||
info.MessagesExpiryDuration = int64(v.config.CacheDuration.Seconds())
|
||||
info.EmailsLimit = replenishDurationToDailyLimit(v.config.VisitorEmailLimitReplenish)
|
||||
info.TopicsLimit = 0 // FIXME
|
||||
info.ReservationsLimit = 0 // FIXME
|
||||
info.AttachmentTotalSizeLimit = v.config.VisitorAttachmentTotalSizeLimit
|
||||
info.AttachmentFileSizeLimit = v.config.AttachmentFileSizeLimit
|
||||
info.AttachmentExpiryDuration = int64(v.config.AttachmentExpiryDuration.Seconds())
|
||||
|
@ -212,20 +212,19 @@ func (v *visitor) Info() (*visitorInfo, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var topics int64
|
||||
var reservations int64
|
||||
if v.user != nil && v.userManager != nil {
|
||||
reservations, err := v.userManager.Reservations(v.user.Name) // FIXME dup call, move this to endpoint?
|
||||
reservations, err = v.userManager.ReservationsCount(v.user.Name) // FIXME dup call, move this to endpoint?
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
topics = int64(len(reservations))
|
||||
}
|
||||
info.Messages = messages
|
||||
info.MessagesRemaining = zeroIfNegative(info.MessagesLimit - info.Messages)
|
||||
info.Emails = emails
|
||||
info.EmailsRemaining = zeroIfNegative(info.EmailsLimit - info.Emails)
|
||||
info.Topics = topics
|
||||
info.TopicsRemaining = zeroIfNegative(info.TopicsLimit - info.Topics)
|
||||
info.Reservations = reservations
|
||||
info.ReservationsRemaining = zeroIfNegative(info.ReservationsLimit - info.Reservations)
|
||||
info.AttachmentTotalSize = attachmentsBytesUsed
|
||||
info.AttachmentTotalSizeRemaining = zeroIfNegative(info.AttachmentTotalSizeLimit - info.AttachmentTotalSize)
|
||||
return info, nil
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue