Skip to content

Commit

Permalink
Add the notion of sponsorships and their logos (#4223)
Browse files Browse the repository at this point in the history
  • Loading branch information
nono authored Dec 18, 2023
2 parents 7632dbb + 5d5139b commit a4914b3
Show file tree
Hide file tree
Showing 18 changed files with 371 additions and 16 deletions.
8 changes: 8 additions & 0 deletions client/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type Instance struct {
UUID string `json:"uuid,omitempty"`
OIDCID string `json:"oidc_id,omitempty"`
ContextName string `json:"context,omitempty"`
Sponsorships []string `json:"sponsorships,omitempty"`
TOSSigned string `json:"tos,omitempty"`
TOSLatest string `json:"tos_latest,omitempty"`
AuthMode int `json:"auth_mode,omitempty"`
Expand Down Expand Up @@ -65,6 +66,7 @@ type InstanceOptions struct {
TOSLatest string
Timezone string
ContextName string
Sponsorships []string
Email string
PublicName string
Settings string
Expand Down Expand Up @@ -164,6 +166,9 @@ func (ac *AdminClient) CreateInstance(opts *InstanceOptions) (*Instance, error)
if opts.DomainAliases != nil {
q.Add("DomainAliases", strings.Join(opts.DomainAliases, ","))
}
if opts.Sponsorships != nil {
q.Add("Sponsorships", strings.Join(opts.Sponsorships, ","))
}
if opts.MagicLink != nil && *opts.MagicLink {
q.Add("MagicLink", "true")
}
Expand Down Expand Up @@ -237,6 +242,9 @@ func (ac *AdminClient) ModifyInstance(opts *InstanceOptions) (*Instance, error)
if opts.DomainAliases != nil {
q.Add("DomainAliases", strings.Join(opts.DomainAliases, ","))
}
if opts.Sponsorships != nil {
q.Add("Sponsorships", strings.Join(opts.Sponsorships, ","))
}
if opts.MagicLink != nil {
q.Add("MagicLink", strconv.FormatBool(*opts.MagicLink))
}
Expand Down
5 changes: 5 additions & 0 deletions cmd/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ var flagTOSSigned string
var flagTOS string
var flagTOSLatest string
var flagContextName string
var flagSponsorships []string
var flagOnboardingFinished bool
var flagTTL time.Duration
var flagExpire time.Duration
Expand Down Expand Up @@ -188,6 +189,7 @@ be used as the error message.
TOSSigned: flagTOSSigned,
Timezone: flagTimezone,
ContextName: flagContextName,
Sponsorships: flagSponsorships,
Email: flagEmail,
PublicName: flagPublicName,
Settings: flagSettings,
Expand Down Expand Up @@ -276,6 +278,7 @@ settings for a specified domain.
TOSLatest: flagTOSLatest,
Timezone: flagTimezone,
ContextName: flagContextName,
Sponsorships: flagSponsorships,
Email: flagEmail,
PublicName: flagPublicName,
Settings: flagSettings,
Expand Down Expand Up @@ -1085,6 +1088,7 @@ func init() {
addInstanceCmd.Flags().StringVar(&flagTOS, "tos", "", "The TOS version signed")
addInstanceCmd.Flags().StringVar(&flagTimezone, "tz", "", "The timezone for the user")
addInstanceCmd.Flags().StringVar(&flagContextName, "context-name", "", "Context name of the instance")
addInstanceCmd.Flags().StringSliceVar(&flagSponsorships, "sponsorships", nil, "Sponsorships of the instance (comma separated list)")
addInstanceCmd.Flags().StringVar(&flagEmail, "email", "", "The email of the owner")
addInstanceCmd.Flags().StringVar(&flagPublicName, "public-name", "", "The public name of the owner")
addInstanceCmd.Flags().StringVar(&flagSettings, "settings", "", "A list of settings (eg context:foo,offer:premium)")
Expand All @@ -1105,6 +1109,7 @@ func init() {
modifyInstanceCmd.Flags().StringVar(&flagTOSLatest, "tos-latest", "", "Update the latest TOS version")
modifyInstanceCmd.Flags().StringVar(&flagTimezone, "tz", "", "New timezone")
modifyInstanceCmd.Flags().StringVar(&flagContextName, "context-name", "", "New context name")
modifyInstanceCmd.Flags().StringSliceVar(&flagSponsorships, "sponsorships", nil, "Sponsorships of the instance (comma separated list)")
modifyInstanceCmd.Flags().StringVar(&flagEmail, "email", "", "New email")
modifyInstanceCmd.Flags().StringVar(&flagPublicName, "public-name", "", "New public name")
modifyInstanceCmd.Flags().StringVar(&flagSettings, "settings", "", "New list of settings (eg offer:premium)")
Expand Down
2 changes: 1 addition & 1 deletion cozy.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ contexts:
# Change the limit on the number of members for a sharing
max_members_per_sharing: 50
# Use a different wizard for moving a Cozy
move_url: htts://move.cozy.beta/
move_url: https://move.cozy.beta/
# Feature flags
features:
- hide_konnector_errors
Expand Down
1 change: 1 addition & 0 deletions docs/cli/cozy-stack_instances_add.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ $ cozy-stack instances add --passphrase cozy --apps drive,photos,settings,home,s
--passphrase string Register the instance with this passphrase (useful for tests)
--public-name string The public name of the owner
--settings string A list of settings (eg context:foo,offer:premium)
--sponsorships strings Sponsorships of the instance (comma separated list)
--swift-layout int Specify the layout to use for Swift (from 0 for layout V1 to 2 for layout V3, -1 means the default) (default -1)
--tos string The TOS version signed
--trace Show where time is spent
Expand Down
1 change: 1 addition & 0 deletions docs/cli/cozy-stack_instances_modify.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ cozy-stack instances modify <domain> [flags]
--onboarding-finished Force the finishing of the onboarding
--public-name string New public name
--settings string New list of settings (eg offer:premium)
--sponsorships strings Sponsorships of the instance (comma separated list)
--tos string Update the TOS version signed
--tos-latest string Update the latest TOS version
--tz string New timezone
Expand Down
3 changes: 2 additions & 1 deletion docs/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,8 @@ Cookie: sessionid=xxxx
"public_name": "Alice Martin",
"auth_mode": "basic",
"default_redirection": "drive/#/folder",
"context": "dev"
"context": "dev",
"sponsorships": ["springfield"]
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions model/instance/instance.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Package instance is for the instance model, with domain, locale, settings,
// etc.
package instance

import (
Expand Down Expand Up @@ -52,6 +54,7 @@ type Instance struct {
OIDCID string `json:"oidc_id,omitempty"` // An identifier to check authentication from OIDC
FranceConnectID string `json:"franceconnect_id,omitempty"` // An identifier to check authentication from FranceConnect
ContextName string `json:"context,omitempty"` // The context attached to the instance
Sponsorships []string `json:"sponsorships,omitempty"` // The list of sponsorships for the instance
TOSSigned string `json:"tos,omitempty"` // Terms of Service signed version
TOSLatest string `json:"tos_latest,omitempty"` // Terms of Service latest version
AuthMode AuthMode `json:"auth_mode,omitempty"` // 2 factor authentication
Expand Down
127 changes: 127 additions & 0 deletions model/instance/instance_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package instance_test

import (
"encoding/json"
"testing"

"github.com/cozy/cozy-stack/model/instance"
"github.com/cozy/cozy-stack/pkg/config/config"
"github.com/cozy/cozy-stack/pkg/crypto"
jwt "github.com/golang-jwt/jwt/v5"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestInstance(t *testing.T) {
Expand Down Expand Up @@ -51,4 +53,129 @@ func TestInstance(t *testing.T) {
assert.Equal(t, "test-ctx-token.example.com", claims["iss"])
assert.Equal(t, "my-app", claims["sub"])
})

t.Run("GetContextWithSponsorships", func(t *testing.T) {
cfg := config.GetConfig()
was := cfg.Contexts
defer func() { cfg.Contexts = was }()

cfg.Contexts = map[string]interface{}{
"context": map[string]interface{}{
"manager_url": "http://manager.example.org",
"logos": map[string]interface{}{
"coachco2": map[string]interface{}{
"light": []interface{}{
map[string]interface{}{"src": "/logos/main_cozy.png", "alt": "Cozy Cloud"},
},
},
"home": map[string]interface{}{
"light": []interface{}{
map[string]interface{}{"src": "/logos/main_cozy.png", "alt": "Cozy Cloud", "type": "main"},
map[string]interface{}{"src": "/logos/partner1.png", "alt": "Partner1", "type": "secondary"},
},
"dark": []interface{}{
// no main
map[string]interface{}{"src": "/logos/partner1.png", "alt": "Partner1", "type": "secondary"},
},
},
},
},
"sponsor1": map[string]interface{}{
"move_url": "http://move.cozy.beta/",
"logos": map[string]interface{}{
"coachco2": map[string]interface{}{
"dark": []interface{}{
map[string]interface{}{"src": "/logos/main_cozy.png", "alt": "Cozy Cloud"},
},
},
"home": map[string]interface{}{
"light": []interface{}{
map[string]interface{}{"src": "/logos/main_cozy.png", "alt": "Cozy Cloud", "type": "main"},
map[string]interface{}{"src": "/logos/partner1.png", "alt": "Partner1", "type": "secondary"},
map[string]interface{}{"src": "/logos/partner2.png", "alt": "Partner2", "type": "secondary"},
},
"dark": []interface{}{
map[string]interface{}{"src": "/logos/main_cozy.png", "alt": "Cozy Cloud", "type": "main"},
map[string]interface{}{"src": "/logos/partner2.png", "alt": "Partner2"},
map[string]interface{}{"src": "/logos/partner1.png", "alt": "Partner1"},
},
},
},
},
"sponsor2": map[string]interface{}{
"logos": map[string]interface{}{
"mespapiers": map[string]interface{}{
"dark": []interface{}{
map[string]interface{}{"src": "/logos/main_cozy.png", "alt": "Cozy Cloud"},
},
},
"home": map[string]interface{}{
"light": []interface{}{
map[string]interface{}{"src": "/logos/main_cozy.png", "alt": "Cozy Cloud", "type": "main"},
map[string]interface{}{"src": "/logos/partner3.png", "alt": "Partner3", "type": "secondary"},
map[string]interface{}{"src": "/logos/partner2.png", "alt": "Partner2", "type": "secondary"},
},
},
},
},
}

inst := &instance.Instance{
Domain: "foo.example.com",
ContextName: "context",
Sponsorships: []string{"sponsor1", "sponsor2"},
}
result := inst.GetContextWithSponsorships()
bytes, err := json.MarshalIndent(result, "", " ")
require.NoError(t, err)
expected := `{
"logos": {
"coachco2": {
"light": [
{
"src": "/logos/main_cozy.png",
"alt": "Cozy Cloud"
}
]
},
"home": {
"light": [
{
"src": "/logos/main_cozy.png",
"alt": "Cozy Cloud",
"type": "main"
},
{
"src": "/logos/partner1.png",
"alt": "Partner1",
"type": "secondary"
},
{
"src": "/ext/sponsor1/logos/partner2.png",
"alt": "Partner2",
"type": "secondary"
},
{
"src": "/ext/sponsor2/logos/partner3.png",
"alt": "Partner3",
"type": "secondary"
}
],
"dark": [
{
"src": "/logos/partner1.png",
"alt": "Partner1",
"type": "secondary"
},
{
"src": "/ext/sponsor1/logos/partner2.png",
"alt": "Partner2"
}
]
}
},
"manager_url": "http://manager.example.org"
}`
assert.Equal(t, expected, string(bytes))
})
}
6 changes: 6 additions & 0 deletions model/instance/lifecycle/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type Options struct {
TOSLatest string
Timezone string
ContextName string
Sponsorships []string
Email string
PublicName string
Settings string
Expand Down Expand Up @@ -119,6 +120,7 @@ func Create(opts *Options) (*instance.Instance, error) {
i.TOSSigned = opts.TOSSigned
i.TOSLatest = opts.TOSLatest
i.ContextName = opts.ContextName
i.Sponsorships = opts.Sponsorships
i.BytesDiskQuota = opts.DiskQuota
i.IndexViewsVersion = couchdb.IndexViewsVersion
opts.trace("generate secrets", func() {
Expand Down Expand Up @@ -311,6 +313,10 @@ func buildSettings(inst *instance.Instance, opts *Options) (*couchdb.JSONDoc, er
opts.ContextName = contextName
delete(settings.M, "context")
}
if sponsorships, ok := settings.M["sponsorships"].([]string); ok {
opts.Sponsorships = sponsorships
delete(settings.M, "sponsorships")
}
if locale, ok := settings.M["locale"].(string); ok {
opts.Locale = locale
delete(settings.M, "locale")
Expand Down
5 changes: 5 additions & 0 deletions model/instance/lifecycle/patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ func Patch(i *instance.Instance, opts *Options) error {
needUpdate = true
}

if len(opts.Sponsorships) != 0 {
i.Sponsorships = opts.Sponsorships
needUpdate = true
}

if opts.AuthMode != "" {
var authMode instance.AuthMode
authMode, err = instance.StringToAuthMode(opts.AuthMode)
Expand Down
Loading

0 comments on commit a4914b3

Please sign in to comment.