Skip to content

Commit

Permalink
feat: Notify if exceeding clients limit with Pass (#4124)
Browse files Browse the repository at this point in the history
The Cozy Pass mobile app and web extension use OAuth clients to
connect to the Cozy so we want to include these in the OAuth clients
number limitation.
However, they do not go through our classic OAuth flow and use their
own so they would not see the blocking modal we added before the
permissions modal when connecting the client would exceed the limit
set on the Cozy.

For this reason, the connection of these app and extension will always
go through but, if this leads to exceeding the clients limit, the user
will see the blocking modal when trying to navigate on their Cozy.
This is why we'll send an e-mail notification to raise attention on
the limit being exceeded and ways to solve this issue in an effort to
anticipate future navigation that could be a bit annoying and
disorientating.
  • Loading branch information
taratatach authored Sep 14, 2023
2 parents f95d8f3 + 0374c31 commit 96f4e5e
Show file tree
Hide file tree
Showing 18 changed files with 1,316 additions and 891 deletions.
24 changes: 24 additions & 0 deletions assets/locales/de.po
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,30 @@ msgstr ""
msgid "Notifications Disk Quota free text"
msgstr "Speicherplatz freiräumen"

msgid "Notifications OAuth Clients Subject"
msgstr "You've exceeded the maximum number of devices allowed in your plan"

msgid "Notifications OAuth Clients Title"
msgstr "Important information: maximum number of devices exceeded"

msgid "Notifications OAuth Clients Greeting"
msgstr "Hello,"

msgid "Notifications OAuth Clients Reason Device"
msgstr "**You've exceeded the maximum number of devices allowed** when connecting **%s** to your Cozy."

msgid "Notifications OAuth Clients Reason Limit"
msgstr "Your plan allows you to connect up to **%.0f devices**."

msgid "Notifications OAuth Clients Increase Limit"
msgstr "To upgrade your Cozy, or simply support us, you can change your Cozy plan."

msgid "Notifications OAuth Clients Offers Text"
msgstr "Check our plans"

msgid "Notifications OAuth Clients Devices Text"
msgstr "Manage my devices"

msgid "Terms of services have been updated"
msgstr ""
"Um DSGVO-konform zu sein hat Cozy Cloud seine Nutzungsbedingungen zum 25. "
Expand Down
24 changes: 24 additions & 0 deletions assets/locales/en.po
Original file line number Diff line number Diff line change
Expand Up @@ -1146,6 +1146,30 @@ msgstr "Option 2:\n"
msgid "Notifications Disk Quota free text"
msgstr "Free up storage space"

msgid "Notifications OAuth Clients Subject"
msgstr "You've exceeded the maximum number of devices allowed in your plan"

msgid "Notifications OAuth Clients Title"
msgstr "Important information: maximum number of devices exceeded"

msgid "Notifications OAuth Clients Greeting"
msgstr "Hello,"

msgid "Notifications OAuth Clients Reason Device"
msgstr "**You've exceeded the maximum number of devices allowed** when connecting **%s** to your Cozy."

msgid "Notifications OAuth Clients Reason Limit"
msgstr "Your plan allows you to connect up to **%.0f devices**."

msgid "Notifications OAuth Clients Increase Limit"
msgstr "To upgrade your Cozy, or simply support us, you can change your Cozy plan."

msgid "Notifications OAuth Clients Offers Text"
msgstr "Check our plans"

msgid "Notifications OAuth Clients Devices Text"
msgstr "Manage my devices"

msgid "Terms of services have been updated"
msgstr "To comply with the GDPR, Cozy Cloud has updated its Terms of Services that have taken effect on May 25, 2018"

Expand Down
24 changes: 24 additions & 0 deletions assets/locales/es.po
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,30 @@ msgstr ""
msgid "Notifications Disk Quota free text"
msgstr "Liberar espacio de almacenamiento"

msgid "Notifications OAuth Clients Subject"
msgstr "You've exceeded the maximum number of devices allowed in your plan"

msgid "Notifications OAuth Clients Title"
msgstr "Important information: maximum number of devices exceeded"

msgid "Notifications OAuth Clients Greeting"
msgstr "Hello,"

msgid "Notifications OAuth Clients Reason Device"
msgstr "**You've exceeded the maximum number of devices allowed** when connecting **%s** to your Cozy."

msgid "Notifications OAuth Clients Reason Limit"
msgstr "Your plan allows you to connect up to **%.0f devices**."

msgid "Notifications OAuth Clients Increase Limit"
msgstr "To upgrade your Cozy, or simply support us, you can change your Cozy plan."

msgid "Notifications OAuth Clients Offers Text"
msgstr "Check our plans"

msgid "Notifications OAuth Clients Devices Text"
msgstr "Manage my devices"

msgid "Terms of services have been updated"
msgstr ""
"Para cumplir con la GDPR que estará vigente a partir del 25 de mayo de 2018,"
Expand Down
24 changes: 24 additions & 0 deletions assets/locales/fr.po
Original file line number Diff line number Diff line change
Expand Up @@ -1251,6 +1251,30 @@ msgstr ""
msgid "Notifications Disk Quota free text"
msgstr "Libérer de l'espace"

msgid "Notifications OAuth Clients Subject"
msgstr "Vous avez dépassé le nombre maximum d'appareils connectés inclus dans votre offre"

msgid "Notifications OAuth Clients Title"
msgstr "Information importante : nombre maximum d'appareils dépassé"

msgid "Notifications OAuth Clients Greeting"
msgstr "Bonjour,"

msgid "Notifications OAuth Clients Reason Device"
msgstr "**Vous avez dépassé le nombre d'appareils autorisés** en connectant **%s** à votre Cozy."

msgid "Notifications OAuth Clients Reason Limit"
msgstr "Votre offre vous permet de connecter jusqu'à **%.0f appareils** simultanément."

msgid "Notifications OAuth Clients Increase Limit"
msgstr "Pour augmenter cette limite, ou simplement nous soutenir, vous pouvez modifier l'offre de votre Cozy."

msgid "Notifications OAuth Clients Offers Text"
msgstr "Voir les offres"

msgid "Notifications OAuth Clients Devices Text"
msgstr "Gérer mes appareils"

msgid "Terms of services have been updated"
msgstr ""
"Dans le cadre du RGPD, Cozy Cloud met à jour ses Conditions Générales "
Expand Down
24 changes: 24 additions & 0 deletions assets/locales/ja.po
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,30 @@ msgstr ""
msgid "Notifications Disk Quota free text"
msgstr "記憶容量を解放する"

msgid "Notifications OAuth Clients Subject"
msgstr "You've exceeded the maximum number of devices allowed in your plan"

msgid "Notifications OAuth Clients Title"
msgstr "Important information: maximum number of devices exceeded"

msgid "Notifications OAuth Clients Greeting"
msgstr "Hello,"

msgid "Notifications OAuth Clients Reason Device"
msgstr "**You've exceeded the maximum number of devices allowed** when connecting **%s** to your Cozy."

msgid "Notifications OAuth Clients Reason Limit"
msgstr "Your plan allows you to connect up to **%.0f devices**."

msgid "Notifications OAuth Clients Increase Limit"
msgstr "To upgrade your Cozy, or simply support us, you can change your Cozy plan."

msgid "Notifications OAuth Clients Offers Text"
msgstr "Check our plans"

msgid "Notifications OAuth Clients Devices Text"
msgstr "Manage my devices"

msgid "Terms of services have been updated"
msgstr "GDPR を遵守するため、Cozy Cloud は2018年5月25日に施行された利用規約を更新しました"

Expand Down
24 changes: 24 additions & 0 deletions assets/locales/nl_NL.po
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,30 @@ msgstr ""
msgid "Notifications Disk Quota free text"
msgstr "Opslagruimte vrijmaken"

msgid "Notifications OAuth Clients Subject"
msgstr "You've exceeded the maximum number of devices allowed in your plan"

msgid "Notifications OAuth Clients Title"
msgstr "Important information: maximum number of devices exceeded"

msgid "Notifications OAuth Clients Greeting"
msgstr "Hello,"

msgid "Notifications OAuth Clients Reason Device"
msgstr "**You've exceeded the maximum number of devices allowed** when connecting **%s** to your Cozy."

msgid "Notifications OAuth Clients Reason Limit"
msgstr "Your plan allows you to connect up to **%.0f devices**."

msgid "Notifications OAuth Clients Increase Limit"
msgstr "To upgrade your Cozy, or simply support us, you can change your Cozy plan."

msgid "Notifications OAuth Clients Offers Text"
msgstr "Check our plans"

msgid "Notifications OAuth Clients Devices Text"
msgstr "Manage my devices"

msgid "Terms of services have been updated"
msgstr ""
"Om te voldoen aan de GDPR heeft Cozy Cloud zijn algemene voorwaarden "
Expand Down
24 changes: 24 additions & 0 deletions assets/mails/notifications_oauthclients.mjml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{{define "content"}}
<mj-text mj-class="title content-medium">
<img src="https://files.cozycloud.cc/email-assets/stack/icon-archive.png" width="16" height="16" style="vertical-align:sub;"/>&nbsp;
{{t "Notifications OAuth Clients Title"}}
</mj-text>
<mj-text mj-class="content-medium">
{{t "Notifications OAuth Clients Greeting"}}
</mj-text>
<mj-text mj-class="content-medium">
{{tHTML "Notifications OAuth Clients Reason Device" .ClientName}}<br />
{{tHTML "Notifications OAuth Clients Reason Limit" .ClientsLimit}}
</mj-text>
{{if .OffersLink}}
<mj-text mj-class="content-medium">
{{t "Notifications OAuth Clients Increase Limit"}}
</mj-text>
<mj-button href="{{.OffersLink}}" align="left" mj-class="primary-button content-large">
{{t "Notifications OAuth Clients Offers Text"}}
</mj-button>
{{end}}
<mj-button href="{{.DevicesLink}}" align="left" mj-class="primary-button content-large">
{{t "Notifications OAuth Clients Devices Text"}}
</mj-button>
{{end}}
14 changes: 14 additions & 0 deletions assets/mails/notifications_oauthclients.text
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{{t "Notifications OAuth Clients Title"}}
---

{{t "Notifications OAuth Clients Greeting"}}

{{t "Notifications OAuth Clients Reason Device" .ClientName}}
{{t "Notifications OAuth Clients Reason Limit" .ClientsLimit}}

{{if .OffersLink}}
{{t "Notifications OAuth Clients Increase Limit"}}

{{t "Notifications OAuth Clients Offers Text"}}: {{.OffersLink}}
{{end}}
{{t "Notifications OAuth Clients Devices Text"}}: {{.DevicesLink}}
5 changes: 3 additions & 2 deletions docs/assets.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ with given parameter. For example:
* http://cozy.localhost:8080/dev/mails/move_success
* http://cozy.localhost:8080/dev/mails/new_connection
* http://cozy.localhost:8080/dev/mails/new_registration
* http://cozy.localhost:8080/dev/mails/notification_diskquota
* http://cozy.localhost:8080/dev/mails/notification_sharing
* http://cozy.localhost:8080/dev/mails/notifications_diskquota
* http://cozy.localhost:8080/dev/mails/notifications_oauthclients
* http://cozy.localhost:8080/dev/mails/notifications_sharing
* http://cozy.localhost:8080/dev/mails/passphrase_hint
* http://cozy.localhost:8080/dev/mails/passphrase_reset
* http://cozy.localhost:8080/dev/mails/sharing_request
Expand Down
36 changes: 36 additions & 0 deletions model/notification/center/notification_center.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ const (
// NotificationDiskQuota category for sending alert when reaching 90% of disk
// usage quota.
NotificationDiskQuota = "disk-quota"
// NotificationOAuthClients category for sending alert when exceeding the
// connected OAuth clients limit.
NotificationOAuthClients = "oauth-clients"
)

var (
Expand All @@ -36,6 +39,12 @@ var (
MailTemplate: "notifications_diskquota",
MinInterval: 7 * 24 * time.Hour,
},
NotificationOAuthClients: {
Description: "Warn about the connected OAuth clients count exceeding the offer limit",
Collapsible: false,
Stateful: false,
MailTemplate: "notifications_oauthclients",
},
}
)

Expand Down Expand Up @@ -73,6 +82,33 @@ func init() {
}
_ = PushStack(domain, NotificationDiskQuota, n)
})

oauth.RegisterClientsLimitAlertCallback(func(i *instance.Instance, clientName string, clientsLimit int, enablePremiumLinks bool) {
devicesLink := i.SubDomain(consts.SettingsSlug)
devicesLink.Fragment = "/connectedDevices"

var offersLink string
if enablePremiumLinks {
var err error
offersLink, err = i.ManagerURL(instance.ManagerPremiumURL)
if err != nil {
return
}
}

n := &notification.Notification{
Title: i.Translate("Notifications OAuth Clients Subject"),
Slug: consts.SettingsSlug,
Data: map[string]interface{}{
"ClientName": clientName,
"ClientsLimit": clientsLimit,
"OffersLink": offersLink,
"DevicesLink": devicesLink.String(),
},
PreferredChannels: []string{"mail"},
}
PushStack(i.DomainName(), NotificationOAuthClients, n)
})
}

// PushStack creates and sends a new notification where the source is the stack.
Expand Down
36 changes: 36 additions & 0 deletions model/oauth/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"time"

"github.com/cozy/cozy-stack/model/bitwarden/settings"
"github.com/cozy/cozy-stack/model/feature"
"github.com/cozy/cozy-stack/model/instance"
"github.com/cozy/cozy-stack/model/job"
"github.com/cozy/cozy-stack/model/notification"
Expand Down Expand Up @@ -515,6 +516,25 @@ func (c *Client) Create(i *instance.Instance, opts ...CreateOptions) *ClientRegi
}

c.TransformIDAndRev()

if !c.Pending {
flags, err := feature.GetFlags(i)
if err != nil {
i.Logger().WithNamespace("oauth").
Errorf("Failed to get the OAuth clients limit: %s", err)
return nil
}
limit := -1
if clientsLimit, ok := flags.M["cozy.oauthclients.max"].(float64); ok && clientsLimit >= 0 {
limit = int(clientsLimit)
}
_, exceeded := CheckOAuthClientsLimitReached(i, limit)
if exceeded {
enablePremiumLinks, _ := flags.M["enable_premium_links"].(bool)
PushClientsLimitAlert(i, c.ClientName, limit, enablePremiumLinks)
}
return nil
}
return nil
}

Expand Down Expand Up @@ -831,4 +851,20 @@ func CheckOAuthClientsLimitReached(i *instance.Instance, limit int) (reached, ex
return
}

var cbClientsLimitAlert func(i *instance.Instance, clientName string, clientsLimit int, enablePremiumLinks bool)

// RegisterClientsLimitAlertCallback allows to register a callback function
// called when the connected OAuth clients limit (if present) is exceeded.
func RegisterClientsLimitAlertCallback(cb func(i *instance.Instance, clientName string, clientsLimit int, enablePremiumLinks bool)) {
cbClientsLimitAlert = cb
}

// PushClientsLimitAlert can be used to notify when the connected OAuth clients
// limit (if present) is exceeded.
func PushClientsLimitAlert(i *instance.Instance, clientName string, clientsLimit int, enablePremiumLinks bool) {
if cbClientsLimitAlert != nil {
cbClientsLimitAlert(i, clientName, clientsLimit, enablePremiumLinks)
}
}

var _ couchdb.Doc = &Client{}
Loading

0 comments on commit 96f4e5e

Please sign in to comment.