More self-review

This commit is contained in:
binwiederhier 2023-05-17 10:58:28 -04:00
parent ac029c389e
commit 92c384374a
11 changed files with 62 additions and 44 deletions

2
go.sum
View File

@ -2,8 +2,6 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.110.2 h1:sdFPBr6xG9/wkBbfhmUz/JmZC7X6LavQgcrVINrKiVA= cloud.google.com/go v0.110.2 h1:sdFPBr6xG9/wkBbfhmUz/JmZC7X6LavQgcrVINrKiVA=
cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw=
cloud.google.com/go/compute v1.19.2 h1:GbJtPo8OKVHbVep8jvM57KidbYHxeE68LOVqouNLrDY=
cloud.google.com/go/compute v1.19.2/go.mod h1:5f5a+iC1IriXYauaQ0EyQmEAEq9CGRnV5xJSQSlTV08=
cloud.google.com/go/compute v1.19.3 h1:DcTwsFgGev/wV5+q8o2fzgcHOaac+DKGC91ZlvpsQds= cloud.google.com/go/compute v1.19.3 h1:DcTwsFgGev/wV5+q8o2fzgcHOaac+DKGC91ZlvpsQds=
cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=

View File

@ -550,6 +550,7 @@ func (s *Server) handleWebConfig(w http.ResponseWriter, _ *http.Request, _ *visi
EnableSignup: s.config.EnableSignup, EnableSignup: s.config.EnableSignup,
EnablePayments: s.config.StripeSecretKey != "", EnablePayments: s.config.StripeSecretKey != "",
EnableCalls: s.config.TwilioAccount != "", EnableCalls: s.config.TwilioAccount != "",
EnableEmails: s.config.SMTPSenderFrom != "",
EnableReservations: s.config.EnableReservations, EnableReservations: s.config.EnableReservations,
BillingContact: s.config.BillingContact, BillingContact: s.config.BillingContact,
DisallowedTopics: s.config.DisallowedTopics, DisallowedTopics: s.config.DisallowedTopics,
@ -911,7 +912,7 @@ func (s *Server) parsePublishParams(r *http.Request, m *message) (cache bool, fi
return false, false, "", "", false, errHTTPBadRequestEmailDisabled return false, false, "", "", false, errHTTPBadRequestEmailDisabled
} }
call = readParam(r, "x-call", "call") call = readParam(r, "x-call", "call")
if call != "" && s.config.TwilioAccount == "" && s.userManager == nil { if call != "" && (s.config.TwilioAccount == "" || s.userManager == nil) {
return false, false, "", "", false, errHTTPBadRequestPhoneCallsDisabled return false, false, "", "", false, errHTTPBadRequestPhoneCallsDisabled
} else if call != "" && !isBoolValue(call) && !phoneNumberRegex.MatchString(call) { } else if call != "" && !isBoolValue(call) && !phoneNumberRegex.MatchString(call) {
return false, false, "", "", false, errHTTPBadRequestPhoneNumberInvalid return false, false, "", "", false, errHTTPBadRequestPhoneNumberInvalid

View File

@ -146,6 +146,11 @@
# If enabled, ntfy can perform voice calls via Twilio via the "X-Call" header. # If enabled, ntfy can perform voice calls via Twilio via the "X-Call" header.
# #
# - twilio-account is the Twilio account SID, e.g. AC12345beefbeef67890beefbeef122586
# - twilio-auth-token is the Twilio auth token, e.g. affebeef258625862586258625862586
# - twilio-from-number is the outgoing phone number you purchased, e.g. +18775132586
# - twilio-verify-service is the Twilio Verify service SID, e.g. VA12345beefbeef67890beefbeef122586
#
# twilio-account: # twilio-account:
# twilio-auth-token: # twilio-auth-token:
# twilio-from-number: # twilio-from-number:

View File

@ -108,17 +108,19 @@ func (s *Server) handleAccountGet(w http.ResponseWriter, r *http.Request, v *vis
CancelAt: u.Billing.StripeSubscriptionCancelAt.Unix(), CancelAt: u.Billing.StripeSubscriptionCancelAt.Unix(),
} }
} }
reservations, err := s.userManager.Reservations(u.Name) if s.config.EnableReservations {
if err != nil { reservations, err := s.userManager.Reservations(u.Name)
return err if err != nil {
} return err
if len(reservations) > 0 { }
response.Reservations = make([]*apiAccountReservation, 0) if len(reservations) > 0 {
for _, r := range reservations { response.Reservations = make([]*apiAccountReservation, 0)
response.Reservations = append(response.Reservations, &apiAccountReservation{ for _, r := range reservations {
Topic: r.Topic, response.Reservations = append(response.Reservations, &apiAccountReservation{
Everyone: r.Everyone.String(), Topic: r.Topic,
}) Everyone: r.Everyone.String(),
})
}
} }
} }
tokens, err := s.userManager.Tokens(u.ID) tokens, err := s.userManager.Tokens(u.ID)
@ -141,12 +143,14 @@ func (s *Server) handleAccountGet(w http.ResponseWriter, r *http.Request, v *vis
}) })
} }
} }
phoneNumbers, err := s.userManager.PhoneNumbers(u.ID) if s.config.TwilioAccount != "" {
if err != nil { phoneNumbers, err := s.userManager.PhoneNumbers(u.ID)
return err if err != nil {
} return err
if len(phoneNumbers) > 0 { }
response.PhoneNumbers = phoneNumbers if len(phoneNumbers) > 0 {
response.PhoneNumbers = phoneNumbers
}
} }
} else { } else {
response.Username = user.Everyone response.Username = user.Everyone

View File

@ -151,6 +151,8 @@ func TestAccount_Get_Anonymous(t *testing.T) {
require.Equal(t, int64(1004), account.Stats.MessagesRemaining) require.Equal(t, int64(1004), account.Stats.MessagesRemaining)
require.Equal(t, int64(0), account.Stats.Emails) require.Equal(t, int64(0), account.Stats.Emails)
require.Equal(t, int64(24), account.Stats.EmailsRemaining) require.Equal(t, int64(24), account.Stats.EmailsRemaining)
require.Equal(t, int64(0), account.Stats.Calls)
require.Equal(t, int64(0), account.Stats.CallsRemaining)
rr = request(t, s, "POST", "/mytopic", "", nil) rr = request(t, s, "POST", "/mytopic", "", nil)
require.Equal(t, 200, rr.Code) require.Equal(t, 200, rr.Code)
@ -498,6 +500,8 @@ func TestAccount_Reservation_AddAdminSuccess(t *testing.T) {
func TestAccount_Reservation_AddRemoveUserWithTierSuccess(t *testing.T) { func TestAccount_Reservation_AddRemoveUserWithTierSuccess(t *testing.T) {
conf := newTestConfigWithAuthFile(t) conf := newTestConfigWithAuthFile(t)
conf.EnableSignup = true conf.EnableSignup = true
conf.EnableReservations = true
conf.TwilioAccount = "dummy"
s := newTestServer(t, conf) s := newTestServer(t, conf)
// Create user // Create user
@ -510,6 +514,7 @@ func TestAccount_Reservation_AddRemoveUserWithTierSuccess(t *testing.T) {
MessageLimit: 123, MessageLimit: 123,
MessageExpiryDuration: 86400 * time.Second, MessageExpiryDuration: 86400 * time.Second,
EmailLimit: 32, EmailLimit: 32,
CallLimit: 10,
ReservationLimit: 2, ReservationLimit: 2,
AttachmentFileSizeLimit: 1231231, AttachmentFileSizeLimit: 1231231,
AttachmentTotalSizeLimit: 123123, AttachmentTotalSizeLimit: 123123,
@ -551,6 +556,7 @@ func TestAccount_Reservation_AddRemoveUserWithTierSuccess(t *testing.T) {
require.Equal(t, int64(123), account.Limits.Messages) require.Equal(t, int64(123), account.Limits.Messages)
require.Equal(t, int64(86400), account.Limits.MessagesExpiryDuration) require.Equal(t, int64(86400), account.Limits.MessagesExpiryDuration)
require.Equal(t, int64(32), account.Limits.Emails) require.Equal(t, int64(32), account.Limits.Emails)
require.Equal(t, int64(10), account.Limits.Calls)
require.Equal(t, int64(2), account.Limits.Reservations) require.Equal(t, int64(2), account.Limits.Reservations)
require.Equal(t, int64(1231231), account.Limits.AttachmentFileSize) require.Equal(t, int64(1231231), account.Limits.AttachmentFileSize)
require.Equal(t, int64(123123), account.Limits.AttachmentTotalSize) require.Equal(t, int64(123123), account.Limits.AttachmentTotalSize)

View File

@ -1194,7 +1194,7 @@ func TestServer_PublishDelayedEmail_Fail(t *testing.T) {
} }
func TestServer_PublishDelayedCall_Fail(t *testing.T) { func TestServer_PublishDelayedCall_Fail(t *testing.T) {
c := newTestConfig(t) c := newTestConfigWithAuthFile(t)
c.TwilioAccount = "AC1234567890" c.TwilioAccount = "AC1234567890"
c.TwilioAuthToken = "AAEAA1234567890" c.TwilioAuthToken = "AAEAA1234567890"
c.TwilioFromNumber = "+1234567890" c.TwilioFromNumber = "+1234567890"

View File

@ -228,7 +228,7 @@ func TestServer_Twilio_Call_UnverifiedNumber(t *testing.T) {
} }
func TestServer_Twilio_Call_InvalidNumber(t *testing.T) { func TestServer_Twilio_Call_InvalidNumber(t *testing.T) {
c := newTestConfig(t) c := newTestConfigWithAuthFile(t)
c.TwilioCallsBaseURL = "https://127.0.0.1" c.TwilioCallsBaseURL = "https://127.0.0.1"
c.TwilioAccount = "AC1234567890" c.TwilioAccount = "AC1234567890"
c.TwilioAuthToken = "AAEAA1234567890" c.TwilioAuthToken = "AAEAA1234567890"
@ -242,7 +242,7 @@ func TestServer_Twilio_Call_InvalidNumber(t *testing.T) {
} }
func TestServer_Twilio_Call_Anonymous(t *testing.T) { func TestServer_Twilio_Call_Anonymous(t *testing.T) {
c := newTestConfig(t) c := newTestConfigWithAuthFile(t)
c.TwilioCallsBaseURL = "https://127.0.0.1" c.TwilioCallsBaseURL = "https://127.0.0.1"
c.TwilioAccount = "AC1234567890" c.TwilioAccount = "AC1234567890"
c.TwilioAuthToken = "AAEAA1234567890" c.TwilioAuthToken = "AAEAA1234567890"

View File

@ -394,6 +394,7 @@ type apiConfigResponse struct {
EnableSignup bool `json:"enable_signup"` EnableSignup bool `json:"enable_signup"`
EnablePayments bool `json:"enable_payments"` EnablePayments bool `json:"enable_payments"`
EnableCalls bool `json:"enable_calls"` EnableCalls bool `json:"enable_calls"`
EnableEmails bool `json:"enable_emails"`
EnableReservations bool `json:"enable_reservations"` EnableReservations bool `json:"enable_reservations"`
BillingContact string `json:"billing_contact"` BillingContact string `json:"billing_contact"`
DisallowedTopics []string `json:"disallowed_topics"` DisallowedTopics []string `json:"disallowed_topics"`

8
web/package-lock.json generated
View File

@ -16262,16 +16262,16 @@
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.0.4", "version": "4.9.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
"integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
"peer": true, "peer": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
}, },
"engines": { "engines": {
"node": ">=12.20" "node": ">=4.2.0"
} }
}, },
"node_modules/unbox-primitive": { "node_modules/unbox-primitive": {

View File

@ -6,12 +6,13 @@
// During web development, you may change values here for rapid testing. // During web development, you may change values here for rapid testing.
var config = { var config = {
base_url: "http://127.0.0.1:2586",// FIXME window.location.origin, // Change to test against a different server base_url: window.location.origin, // Change to test against a different server
app_root: "/app", app_root: "/app",
enable_login: true, enable_login: true,
enable_signup: true, enable_signup: true,
enable_payments: true, enable_payments: true,
enable_reservations: true, enable_reservations: true,
enable_emails: true,
enable_calls: true, enable_calls: true,
billing_contact: "", billing_contact: "",
disallowed_topics: ["docs", "static", "file", "app", "account", "settings", "signup", "login", "v1"] disallowed_topics: ["docs", "static", "file", "app", "account", "settings", "signup", "login", "v1"]

View File

@ -571,22 +571,24 @@ const Stats = () => {
value={account.role === Role.USER ? normalize(account.stats.messages, account.limits.messages) : 100} value={account.role === Role.USER ? normalize(account.stats.messages, account.limits.messages) : 100}
/> />
</Pref> </Pref>
<Pref title={ {config.enable_emails &&
<> <Pref title={
{t("account_usage_emails_title")} <>
<Tooltip title={t("account_usage_limits_reset_daily")}><span><InfoIcon/></span></Tooltip> {t("account_usage_emails_title")}
</> <Tooltip title={t("account_usage_limits_reset_daily")}><span><InfoIcon/></span></Tooltip>
}> </>
<div> }>
<Typography variant="body2" sx={{float: "left"}}>{account.stats.emails.toLocaleString()}</Typography> <div>
<Typography variant="body2" sx={{float: "right"}}>{account.role === Role.USER ? t("account_usage_of_limit", { limit: account.limits.emails.toLocaleString() }) : t("account_usage_unlimited")}</Typography> <Typography variant="body2" sx={{float: "left"}}>{account.stats.emails.toLocaleString()}</Typography>
</div> <Typography variant="body2" sx={{float: "right"}}>{account.role === Role.USER ? t("account_usage_of_limit", { limit: account.limits.emails.toLocaleString() }) : t("account_usage_unlimited")}</Typography>
<LinearProgress </div>
variant="determinate" <LinearProgress
value={account.role === Role.USER ? normalize(account.stats.emails, account.limits.emails) : 100} variant="determinate"
/> value={account.role === Role.USER ? normalize(account.stats.emails, account.limits.emails) : 100}
</Pref> />
{(account.role === Role.ADMIN || account.limits.calls > 0) && </Pref>
}
{config.enable_calls && (account.role === Role.ADMIN || account.limits.calls > 0) &&
<Pref title={ <Pref title={
<> <>
{t("account_usage_calls_title")} {t("account_usage_calls_title")}