Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/2-features/WPB-1436
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The lifetime of conversation guest links is now configurable
3 changes: 3 additions & 0 deletions charts/galley/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ data:
disabledAPIVersions: {{ .settings.disabledAPIVersions }}
{{- end }}
{{- if .settings.featureFlags }}
{{- if .settings.guestLinkTTLDays }}
guestLinkTTLDays: {{ .settings.guestLinkTTLDays }}
{{- end }}
featureFlags:
sso: {{ .settings.featureFlags.sso }}
legalhold: {{ .settings.featureFlags.legalhold }}
Expand Down
5 changes: 4 additions & 1 deletion charts/galley/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,16 @@ config:
# Use this only if you want to expose the instance on multiple ingresses.
# If set it must a map from `Z-Host` to URI prefix
# Example:
# multiIngress:
# multiIngress:
# wire.example: https://accounts.wire.example/conversation-join/
# example.net: https://accounts.example.net/conversation-join/
multiIngress: null
# Disable one ore more API versions. Please make sure the configuration value is the same in all these charts:
# brig, cannon, cargohold, galley, gundeck, proxy, spar.
# disabledAPIVersions: [ v3 ]
# The lifetime of a conversation guest link in days (x, x ∈ (0, 365] and x ∈ R)
# Default is 365 days if not set
guestLinkTTLDays: 365
featureFlags: # see #RefConfigOptions in `/docs/reference` (https://github.com/wireapp/wire-server/)
appLock:
defaults:
Expand Down
13 changes: 12 additions & 1 deletion docs/src/developer/reference/config-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ federator:
clientPrivateKey: client-key.pem
```

## Outlook calalendar integration
### Outlook calalendar integration

This feature setting only applies to the Outlook Calendar extension for Wire. As it is an external service, it should only be configured through this feature flag and otherwise ignored by the backend.

Expand All @@ -439,6 +439,17 @@ outlookCalIntegration:
lockStatus: locked
```

### Guest Link Lifetime

To set the validity duration of conversation guest links set `guestLinkTTLDays` to the desired number of days, a value x, x ∈ (0, 365] and x ∈ R. E.g.

```yaml
# galley.yaml
config:
settings:
guestLinkTTLDays: 7
```

## Settings in brig

Some features (as of the time of writing this: only
Expand Down
5 changes: 5 additions & 0 deletions integration/test/API/Galley.hs
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,11 @@ getConversationCode user conv mbZHost = do
& maybe id zHost mbZHost
)

getJoinCodeConv :: (HasCallStack, MakesValue user) => user -> String -> String -> App Response
getJoinCodeConv u k v = do
req <- baseRequest u Galley Versioned (joinHttpPath ["conversations", "join"])
submit "GET" (req & addQueryParams [("key", k), ("code", v)])

-- https://staging-nginz-https.zinfra.io/v5/api/swagger-ui/#/default/put_conversations__cnv_domain___cnv__name
changeConversationName ::
(HasCallStack, MakesValue user, MakesValue conv, MakesValue name) =>
Expand Down
31 changes: 31 additions & 0 deletions integration/test/Test/Conversation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -764,3 +764,34 @@ testGuestCreatesConversation = do
bindResponse (postConversation alice defProteus) $ \resp -> do
resp.status `shouldMatchInt` 403
resp.json %. "label" `shouldMatch` "operation-denied"

testGuestLinksSuccess :: HasCallStack => App ()
testGuestLinksSuccess = do
(user, _, tm : _) <- createTeam OwnDomain 2
conv <- postConversation user (allowGuests defProteus) >>= getJSON 201
(k, v) <- bindResponse (postConversationCode user conv Nothing Nothing) $ \resp -> do
res <- getJSON 201 resp
k <- res %. "data.key" & asString
v <- res %. "data.code" & asString
pure (k, v)
bindResponse (getJoinCodeConv tm k v) $ \resp -> do
resp.status `shouldMatchInt` 200
resp.json %. "id" `shouldMatch` objId conv

testGuestLinksExpired :: HasCallStack => App ()
testGuestLinksExpired = do
withModifiedBackend
-- 0.0000116 days is a little more than 1 second and will be rounded to 1 second
def {galleyCfg = setField "settings.guestLinkTTLDays" (0.0000116 :: Double)}
$ \domain -> do
(user, _, tm : _) <- createTeam domain 2
conv <- postConversation user (allowGuests defProteus) >>= getJSON 201
(k, v) <- bindResponse (postConversationCode user conv Nothing Nothing) $ \resp -> do
res <- getJSON 201 resp
k <- res %. "data.key" & asString
v <- res %. "data.code" & asString
pure (k, v)
-- let's wait a little longer than 1 second for the guest link to expire
liftIO $ threadDelay (1_100_000)
bindResponse (getJoinCodeConv tm k v) $ \resp -> do
resp.status `shouldMatchInt` 404
1 change: 1 addition & 0 deletions services/galley/galley.integration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ settings:
mlsPrivateKeyPaths:
removal:
ed25519: test/resources/ed25519.pem
guestLinkTTLDays: 7

featureFlags: # see #RefConfigOptions in `/docs/reference`
sso: disabled-by-default
Expand Down
3 changes: 2 additions & 1 deletion services/galley/src/Galley/API/Update.hs
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,8 @@ addCode lusr mbZHost mZcon lcnv mReq = do
key <- E.makeKey (tUnqualified lcnv)
E.getCode key ReusableCode >>= \case
Nothing -> do
code <- E.generateCode (tUnqualified lcnv) ReusableCode (Timeout 3600 * 24 * 365) -- one year FUTUREWORK: configurable
ttl <- realToFrac . (\days -> 60 * 60 * 24 * days) . unGuestLinkTTLDays . fromMaybe defGuestLinkTTLDays . view (settings . guestLinkTTLDays) <$> input
code <- E.generateCode (tUnqualified lcnv) ReusableCode (Timeout ttl)
mPw <- for (mReq >>= (.password)) mkSafePassword
E.createCode code mPw
now <- input
Expand Down
25 changes: 24 additions & 1 deletion services/galley/src/Galley/Options.hs
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,15 @@ module Galley.Options
logLevel,
logNetStrings,
logFormat,
guestLinkTTLDays,
defGuestLinkTTLDays,
GuestLinkTTLDays (..),
)
where

import Control.Lens hiding (Level, (.=))
import Data.Aeson (FromJSON (..))
import Data.Aeson qualified as Aeson
import Data.Aeson.TH (deriveFromJSON)
import Data.Domain (Domain)
import Data.Id (TeamId)
Expand All @@ -72,6 +77,17 @@ import Util.Options.Common
import Wire.API.Routes.Version
import Wire.API.Team.Member

newtype GuestLinkTTLDays = GuestLinkTTLDays
{ unGuestLinkTTLDays :: Double
}
deriving (Show, Generic)

instance FromJSON GuestLinkTTLDays where
parseJSON (Aeson.Number n) = case realToFrac n of
d | d > 0 && d <= 365 -> pure $ GuestLinkTTLDays d
_ -> fail "GuestLinkTTLDays must be a number in (0, 365]"
parseJSON _ = fail "GuestLinkTTLDays must be a number"

data Settings = Settings
{ -- | Number of connections for the HTTP client pool
_httpPoolSize :: !Int,
Expand Down Expand Up @@ -129,7 +145,10 @@ data Settings = Settings
_mlsPrivateKeyPaths :: !(Maybe MLSPrivateKeyPaths),
-- | FUTUREWORK: 'setFeatureFlags' should be renamed to 'setFeatureConfigs' in all types.
_featureFlags :: !FeatureFlags,
_disabledAPIVersions :: Maybe (Set Version)
_disabledAPIVersions :: Maybe (Set Version),
-- | The lifetime of a conversation guest link in days (x, x ∈ (0, 365] and x ∈ R)
-- If not set it use the default `defGuestLinkTTLDays`
_guestLinkTTLDays :: !(Maybe GuestLinkTTLDays)
}
deriving (Show, Generic)

Expand All @@ -146,6 +165,10 @@ defDeleteConvThrottleMillis = 20
defFanoutLimit :: Range 1 HardTruncationLimit Int32
defFanoutLimit = unsafeRange hardTruncationLimit

-- | Default guest link TTL in days. 365 days if not set.
defGuestLinkTTLDays :: GuestLinkTTLDays
defGuestLinkTTLDays = GuestLinkTTLDays 365.0 -- 1 year

data JournalOpts = JournalOpts
{ -- | SQS queue name to send team events
_queueName :: !Text,
Expand Down