Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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/5-internal/servantification
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Servantify /self/* endpoints in brig.
1 change: 1 addition & 0 deletions libs/wire-api/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ library:
- currency-codes >=2.0
- deriving-aeson >=0.2
- deriving-swagger2
- either
- email-validate >=2.0
- errors
- extended
Expand Down
20 changes: 20 additions & 0 deletions libs/wire-api/src/Wire/API/ErrorDescription.hs
Original file line number Diff line number Diff line change
Expand Up @@ -334,3 +334,23 @@ type AssetTooLarge = ErrorDescription 413 "client-error" "Asset too large"
type InvalidLength = ErrorDescription 400 "invalid-length" "Invalid content length"

type AssetNotFound = ErrorDescription 404 "not-found" "Asset not found"

type NameManagedByScim = ErrorDescription 403 "managed-by-scim" "Updating name is not allowed, because it is managed by SCIM"

type HandleManagedByScim = ErrorDescription 403 "managed-by-scim" "Updating handle is not allowed, because it is managed by SCIM"

type InvalidPhone = ErrorDescription 400 "invalid-phone" "Invalid mobile phone number"

type UserKeyExists = ErrorDescription 409 "key-exists" "The give e-mail address or phone number is in use."

type BlacklistedPhone = ErrorDescription 403 "blacklisted-phone" "The given phone number has been blacklisted due to suspected abuse or a complaint."

type LastIdentity = ErrorDescription 403 "last-identity" "The last user identity (email or phone number) cannot be removed."

type NoPassword = ErrorDescription 403 "no-password" "The user has no password."

type ChangePasswordMustDiffer = ErrorDescription 409 "password-must-differ" "For password change, new and old password must be different."

type HandleExists = ErrorDescription 409 "handle-exists" "The given handle is already taken."

type InvalidHandle = ErrorDescription 400 "invalid-handle" "The given handle is invalid."
35 changes: 35 additions & 0 deletions libs/wire-api/src/Wire/API/Routes/MultiVerb.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ module Wire.API.Routes.MultiVerb
AsUnion (..),
eitherToUnion,
eitherFromUnion,
maybeToUnion,
maybeFromUnion,
AsConstructor (..),
GenericAsConstructor (..),
GenericAsUnion (..),
Expand All @@ -50,6 +52,7 @@ import Data.ByteString.Builder
import qualified Data.ByteString.Lazy as LBS
import qualified Data.CaseInsensitive as CI
import Data.Containers.ListUtils
import Data.Either.Combinators (leftToMaybe)
import Data.HashMap.Strict.InsOrd (InsOrdHashMap)
import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap
import Data.Metrics.Servant
Expand Down Expand Up @@ -529,6 +532,21 @@ instance EitherFromUnion as bs => EitherFromUnion (a ': as) bs where
eitherFromUnion f _ (Z x) = Left (f (Z x))
eitherFromUnion f g (S x) = eitherFromUnion @as @bs (f . S) g x

maybeToUnion ::
forall as a.
(InjectAfter as '[()], InjectBefore as '[()]) =>
(a -> Union as) ->
(Maybe a -> Union (as .++ '[()]))
maybeToUnion f (Just a) = injectBefore @as @'[()] (f a)
maybeToUnion _ Nothing = injectAfter @as @'[()] (Z (I ()))

maybeFromUnion ::
forall as a.
EitherFromUnion as '[()] =>
(Union as -> a) ->
(Union (as .++ '[()]) -> Maybe a)
maybeFromUnion f = leftToMaybe . eitherFromUnion @as @'[()] f (const (Z (I ())))

-- | This class can be instantiated to get automatic derivation of 'AsUnion'
-- instances via 'GenericAsUnion'. The idea is that one has to make sure that for
-- each response @r@ in a 'MultiVerb' endpoint, there is an instance of
Expand Down Expand Up @@ -607,6 +625,23 @@ instance
toUnion (GenericAsUnion x) = fromSOP @xss @rs (GSOP.from x)
fromUnion = GenericAsUnion . GSOP.to . toSOP @xss @rs

-- | A handler for a pair of empty responses can be implemented simply by
-- returning a boolean value. The convention is that the "failure" case, normally
-- represented by 'False', corresponds to the /first/ response.
instance
AsUnion
'[ RespondEmpty s1 desc1,
RespondEmpty s2 desc2
]
Bool
where
toUnion False = Z (I ())
toUnion True = S (Z (I ()))

fromUnion (Z (I ())) = False
fromUnion (S (Z (I ()))) = True
fromUnion (S (S x)) = case x of

-- | A handler for a pair of responses where the first is empty can be
-- implemented simply by returning a 'Maybe' value. The convention is that the
-- "failure" case, normally represented by 'Nothing', corresponds to the /first/
Expand Down
84 changes: 84 additions & 0 deletions libs/wire-api/src/Wire/API/Routes/Public/Brig.hs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,90 @@ data Api routes = Api
:> "self"
:> ReqBody '[JSON] DeleteUser
:> MultiVerb 'DELETE '[JSON] DeleteSelfResponses (Maybe Timeout),
-- This endpoint can lead to the following events being sent:
-- - UserUpdated event to contacts of self
putSelf ::
routes
:- Summary "Update your profile."
:> ZUser
:> ZConn
:> "self"
:> ReqBody '[JSON] UserUpdate
:> MultiVerb 'PUT '[JSON] PutSelfResponses (Maybe UpdateProfileError),
changePhone ::
routes
:- Summary "Change your phone number."
:> ZUser
:> ZConn
:> "self"
:> "phone"
:> ReqBody '[JSON] PhoneUpdate
:> MultiVerb 'PUT '[JSON] ChangePhoneResponses (Maybe ChangePhoneError),
-- This endpoint can lead to the following events being sent:
-- - UserIdentityRemoved event to self
removePhone ::
routes
:- Summary "Remove your phone number."
:> Description
"Your phone number can only be removed if you also have an \
\email address and a password."
:> ZUser
:> ZConn
:> "self"
:> "phone"
:> MultiVerb 'DELETE '[JSON] RemoveIdentityResponses (Maybe RemoveIdentityError),
-- This endpoint can lead to the following events being sent:
-- - UserIdentityRemoved event to self
removeEmail ::
routes
:- Summary "Remove your email address."
:> Description
"Your email address can only be removed if you also have a \
\phone number."
:> ZUser
:> ZConn
:> "self"
:> "email"
:> MultiVerb 'DELETE '[JSON] RemoveIdentityResponses (Maybe RemoveIdentityError),
checkPasswordExists ::
routes
:- Summary "Check that your password is set."
:> ZUser
:> "self"
:> "password"
:> MultiVerb
'HEAD
'()
'[ RespondEmpty 404 "Password is not set",
RespondEmpty 200 "Password is set"
]
Bool,
changePassword ::
routes
:- Summary "Change your password."
:> ZUser
:> "self"
:> "password"
:> ReqBody '[JSON] PasswordChange
:> MultiVerb 'PUT '[JSON] ChangePasswordResponses (Maybe ChangePasswordError),
changeLocale ::
routes
:- Summary "Change your locale."
:> ZUser
:> ZConn
:> "self"
:> "locale"
:> ReqBody '[JSON] LocaleUpdate
:> MultiVerb 'PUT '[JSON] '[RespondEmpty 200 "Local Changed"] (),
changeHandle ::
routes
:- Summary "Change your handle."
:> ZUser
:> ZConn
:> "self"
:> "handle"
:> ReqBody '[JSON] HandleUpdate
:> MultiVerb 'PUT '[JSON] ChangeHandleResponses (Maybe ChangeHandleError),
updateUserEmail ::
routes
:- Summary "Resend email address validation email."
Expand Down
5 changes: 0 additions & 5 deletions libs/wire-api/src/Wire/API/Swagger.hs
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,7 @@ models =
User.modelUserIdList,
User.modelUser,
User.modelNewUser,
User.modelUserUpdate,
User.modelChangePassword,
User.modelChangeLocale,
User.modelEmailUpdate,
User.modelPhoneUpdate,
User.modelChangeHandle,
User.modelDelete,
User.modelVerifyDelete,
User.Activation.modelActivate,
Expand Down
Loading