-
Notifications
You must be signed in to change notification settings - Fork 332
[Polysemy] Effects Around the User Query Effect #2450
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7969711
b943d47
c28c6eb
2a3055d
866dcc5
b9d94af
e2271c1
8775800
f5cbebf
e0547e2
c7c7f57
41835f0
24dc4ef
21b2822
708fde4
9b79b8d
142e740
980342d
011b2c3
419a63e
3b95148
8930372
69da294
1153327
08adb08
3f0b894
975d3ef
7b31840
556b850
7212fa9
3ee9aac
19df7e1
48c289b
be904d9
dc55d2e
f105822
eef87c2
1428418
b462175
d29eefd
6a1379f
f5e9ed0
0f69444
b23a3f6
a41b0fb
fd08303
a3b9a93
995ac55
fa52ece
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Add the UserQuery and supporting effects |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,6 +29,15 @@ module Brig.Types.Common | |
| isValidPhonePrefix, | ||
| allPrefixes, | ||
| ExcludedPrefix (..), | ||
|
|
||
| -- * misc | ||
| foldKey, | ||
| keyText, | ||
| mkPhoneKey, | ||
| mkEmailKey, | ||
| EmailKey (..), | ||
| PhoneKey (..), | ||
| UserKey (..), | ||
| ) | ||
| where | ||
|
|
||
|
|
@@ -39,6 +48,7 @@ import Data.ByteString.Conversion | |
| import qualified Data.Text as Text | ||
| import Data.Time.Clock (NominalDiffTime) | ||
| import Imports | ||
| import Wire.API.User.Identity | ||
|
|
||
| ------------------------------------------------------------------------------ | ||
| --- PhoneBudgetTimeout | ||
|
|
@@ -111,3 +121,74 @@ instance FromJSON ExcludedPrefix where | |
|
|
||
| instance ToJSON ExcludedPrefix where | ||
| toJSON (ExcludedPrefix p c) = object ["phone_prefix" .= p, "comment" .= c] | ||
|
|
||
| ------------------------------------------------------------------------------- | ||
| -- Unique Keys | ||
|
|
||
| -- | An 'EmailKey' is an 'Email' in a form that serves as a unique lookup key. | ||
| data EmailKey = EmailKey | ||
| { emailKeyUniq :: !Text, | ||
| emailKeyOrig :: !Email | ||
| } | ||
|
|
||
| instance Show EmailKey where | ||
| showsPrec _ = shows . emailKeyUniq | ||
|
|
||
| instance Eq EmailKey where | ||
| (EmailKey k _) == (EmailKey k' _) = k == k' | ||
|
|
||
| -- | Turn an 'Email' into an 'EmailKey'. | ||
| -- | ||
| -- The following transformations are performed: | ||
| -- | ||
| -- * Both local and domain parts are forced to lowercase to make | ||
| -- e-mail addresses fully case-insensitive. | ||
| -- * "+" suffixes on the local part are stripped unless the domain | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is also far from universal. If we are modeling off of GMail we would also need to strip all
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not new code added by me in this PR; rather, it's old code I moved around. |
||
| -- part is contained in a trusted whitelist. | ||
| mkEmailKey :: Email -> EmailKey | ||
| mkEmailKey orig@(Email localPart domain) = | ||
| let uniq = Text.toLower localPart' <> "@" <> Text.toLower domain | ||
| in EmailKey uniq orig | ||
| where | ||
| localPart' | ||
| | domain `notElem` trusted = Text.takeWhile (/= '+') localPart | ||
| | otherwise = localPart | ||
| trusted = ["wearezeta.com", "wire.com", "simulator.amazonses.com"] | ||
|
|
||
| data PhoneKey = PhoneKey | ||
| { -- | canonical form of 'phoneKeyOrig', without whitespace. | ||
| phoneKeyUniq :: !Text, | ||
| -- | phone number with whitespace. | ||
| phoneKeyOrig :: !Phone | ||
| } | ||
|
|
||
| instance Show PhoneKey where | ||
| showsPrec _ = shows . phoneKeyUniq | ||
|
|
||
| instance Eq PhoneKey where | ||
| (PhoneKey k _) == (PhoneKey k' _) = k == k' | ||
|
|
||
| mkPhoneKey :: Phone -> PhoneKey | ||
| mkPhoneKey orig = | ||
| let uniq = Text.filter (not . isSpace) (fromPhone orig) | ||
| in PhoneKey uniq orig | ||
|
|
||
| -- | A natural identifier (i.e. unique key) of a user. | ||
| data UserKey | ||
| = UserEmailKey !EmailKey | ||
| | UserPhoneKey !PhoneKey | ||
|
|
||
| instance Eq UserKey where | ||
| (UserEmailKey k) == (UserEmailKey k') = k == k' | ||
| (UserPhoneKey k) == (UserPhoneKey k') = k == k' | ||
| _ == _ = False | ||
|
|
||
| -- | Get the normalised text of a 'UserKey'. | ||
| keyText :: UserKey -> Text | ||
| keyText (UserEmailKey k) = emailKeyUniq k | ||
| keyText (UserPhoneKey k) = phoneKeyUniq k | ||
|
|
||
| foldKey :: (Email -> a) -> (Phone -> a) -> UserKey -> a | ||
| foldKey f g k = case k of | ||
| UserEmailKey ek -> f (emailKeyOrig ek) | ||
| UserPhoneKey pk -> g (phoneKeyOrig pk) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| -- This file is part of the Wire Server implementation. | ||
| -- | ||
| -- Copyright (C) 2022 Wire Swiss GmbH <opensource@wire.com> | ||
| -- | ||
| -- This program is free software: you can redistribute it and/or modify it under | ||
| -- the terms of the GNU Affero General Public License as published by the Free | ||
| -- Software Foundation, either version 3 of the License, or (at your option) any | ||
| -- later version. | ||
| -- | ||
| -- This program is distributed in the hope that it will be useful, but WITHOUT | ||
| -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
| -- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more | ||
| -- details. | ||
| -- | ||
| -- You should have received a copy of the GNU Affero General Public License along | ||
| -- with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
|
||
| module Wire.Sem.Error where | ||
|
|
||
| import Imports | ||
| import Polysemy | ||
| import Polysemy.Error | ||
| import qualified UnliftIO.Exception as UnliftIO | ||
| import Wire.API.Error | ||
|
|
||
| interpretErrorToException :: | ||
| (Exception exc, Member (Embed IO) r) => | ||
| (err -> exc) -> | ||
| Sem (Error err ': r) a -> | ||
| Sem r a | ||
| interpretErrorToException f = either (embed @IO . UnliftIO.throwIO . f) pure <=< runError | ||
|
|
||
| interpretWaiErrorToException :: | ||
| (APIError e, Member (Embed IO) r) => | ||
| Sem (Error e ': r) a -> | ||
| Sem r a | ||
| interpretWaiErrorToException = interpretErrorToException toWai |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| {-# LANGUAGE TemplateHaskell #-} | ||
|
|
||
| -- This file is part of the Wire Server implementation. | ||
| -- | ||
| -- Copyright (C) 2022 Wire Swiss GmbH <opensource@wire.com> | ||
| -- | ||
| -- This program is free software: you can redistribute it and/or modify it under | ||
| -- the terms of the GNU Affero General Public License as published by the Free | ||
| -- Software Foundation, either version 3 of the License, or (at your option) any | ||
| -- later version. | ||
| -- | ||
| -- This program is distributed in the hope that it will be useful, but WITHOUT | ||
| -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
| -- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more | ||
| -- details. | ||
| -- | ||
| -- You should have received a copy of the GNU Affero General Public License along | ||
| -- with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
|
||
| module Wire.Sem.FireAndForget where | ||
|
|
||
| import Polysemy | ||
|
|
||
| data FireAndForget m a where | ||
| FireAndForgetOne :: m () -> FireAndForget m () | ||
| SpawnMany :: [m ()] -> FireAndForget m () | ||
|
|
||
| makeSem ''FireAndForget | ||
|
|
||
| fireAndForget :: Member FireAndForget r => Sem r () -> Sem r () | ||
| fireAndForget = fireAndForgetOne |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While it isn't common, the local part is "domain dependent" and can be case-sensitive. We probably shouldn't case fold it by default, though we can if we know the domain does handle the local part case-insensitively.
Case-folding by default will make for some very hard to trace issues if the domain does use case-sensitive local parts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just like the rest in this module, this is not new code added by me in the PR; rather, it's just being reorganised and moved from other modules. That said, I don't think this PR should be about addressing your concern and I believe you should open a ticket and bring it to the team's attention.