Skip to content
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

Wallet update passphrase integration tests #261

Merged
merged 3 commits into from
May 15, 2019
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
3 changes: 2 additions & 1 deletion lib/core/src/Cardano/Wallet/Api.hs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import Servant.API
, NoContent
, PostAccepted
, Put
, PutNoContent
, QueryParam
, ReqBody
)
Expand Down Expand Up @@ -96,7 +97,7 @@ type PutWalletPassphrase = "wallets"
:> Capture "walletId" (ApiT WalletId)
:> "passphrase"
:> ReqBody '[JSON] WalletPutPassphraseData
:> Put '[Any] NoContent
:> PutNoContent '[Any] NoContent

{-------------------------------------------------------------------------------
Transactions
Expand Down
254 changes: 253 additions & 1 deletion lib/http-bridge/test/integration/Test/Integration/Scenario/Wallets.hs
Original file line number Diff line number Diff line change
Expand Up @@ -687,7 +687,7 @@ spec = do
expectResponseCode @IO HTTP.status400 r

describe "WALLETS_CREATE_09, WALLETS_LIST_03 - v2/wallets - Methods Not Allowed" $ do
let matrix = ["PUT", "DELETE"]
let matrix = ["PUT", "DELETE", "CONNECT", "TRACE", "OPTIONS"]
forM_ matrix $ \method -> it (show method) $ \ctx -> do
r <- request @ApiWallet ctx (method, "v2/wallets") Default Empty
expectResponseCode @IO HTTP.status405 r
Expand Down Expand Up @@ -1020,6 +1020,252 @@ spec = do
ru <- request @ApiWallet ctx ("PUT", endpoint) headers newName
verify ru expectations

it "WALLETS_UPDATE_PASS_01 - passphaseLastUpdate gets updated" $ \ctx -> do
r <- request @ApiWallet ctx ("POST", "v2/wallets") Default simplePayload
let payload = updatePassPayload "Secure passphrase" "New passphrase"
let endpoint = "v2/wallets" </> (getFromResponse walletId r)
</> ("passphrase" :: Text)
rup <- request @ApiWallet ctx ("PUT", endpoint) Default payload
expectResponseCode @IO HTTP.status204 rup

let getEndpoint = "v2/wallets" </> (getFromResponse walletId r)
let originalPassUpdateDateTime = getFromResponse passphraseLastUpdate r
rg <- request @ApiWallet ctx ("GET", getEndpoint) Default Empty
expectFieldNotEqual passphraseLastUpdate originalPassUpdateDateTime rg

describe "WALLETS_UPDATE_PASS_02 - New passphrase values" $ do
let passphraseMax = T.pack (replicate passphraseMaxLength 'ą')
let matrix =
[ ( show passphraseMinLength ++ " char long"
, T.pack (replicate passphraseMinLength 'ź')
, [ expectResponseCode @IO HTTP.status204
]
)
, ( show (passphraseMinLength - 1) ++ " char long"
, T.pack (replicate (passphraseMinLength - 1) 'ż')
, [ expectResponseCode @IO HTTP.status400
, expectErrorMessage "passphrase is too short: expected at\
\ least 10 characters"
]
)
, ( show passphraseMaxLength ++ " char long", passphraseMax
, [ expectResponseCode @IO HTTP.status204 ]
)
, ( show (passphraseMaxLength + 1) ++ " char long"
, T.pack (replicate (passphraseMaxLength + 1) 'ę')
, [ expectResponseCode @IO HTTP.status400
, expectErrorMessage "passphrase is too long: expected at\
\ most 255 characters"
]
)
, ( "Empty passphrase", ""
, [ expectResponseCode @IO HTTP.status400
, expectErrorMessage "passphrase is too short: expected at\
\ least 10 characters"
]
)
, ( "Russian passphrase", russianWalletName
, [ expectResponseCode @IO HTTP.status204 ]
)
, ( "Polish passphrase", polishWalletName
, [ expectResponseCode @IO HTTP.status204 ]
)
, ( "Kanji passphrase", kanjiWalletName
, [ expectResponseCode @IO HTTP.status204 ]
)
, ( "Arabic passphrase", arabicWalletName
, [ expectResponseCode @IO HTTP.status204 ]
)
, ( "Wildcards passphrase", wildcardsWalletName
, [ expectResponseCode @IO HTTP.status204 ]
)
]
forM_ matrix $ \(title, passphrase, expectations) -> it title $ \ctx -> do
r <- request @ApiWallet ctx ("POST", "v2/wallets") Default simplePayload
let payload = updatePassPayload "Secure passphrase" passphrase
let endpoint = "v2/wallets" </> (getFromResponse walletId r)
</> ("passphrase" :: Text)
rup <- request @ApiWallet ctx ("PUT", endpoint) Default payload
verify rup expectations

describe "WALLETS_UPDATE_PASS_03 - Old passphrase invalid values" $ do
let matrix =
[ ( show (passphraseMinLength - 1) ++ " char long"
, T.pack (replicate (passphraseMinLength - 1) 'ż')
, [ expectResponseCode @IO HTTP.status400
, expectErrorMessage "passphrase is too short: expected at\
\ least 10 characters" ]
)
, ( show (passphraseMaxLength + 1) ++ " char long"
, T.pack (replicate (passphraseMaxLength + 1) 'ę')
, [ expectResponseCode @IO HTTP.status400
, expectErrorMessage "passphrase is too long: expected at\
\ most 255 characters" ]
)
, ( "Empty passphrase", ""
, [ expectResponseCode @IO HTTP.status400
, expectErrorMessage "passphrase is too short: expected at\
\ least 10 characters" ]
)
, ( "Incorrect old pass", "Incorrect passphrase"
, [ expectResponseCode @IO HTTP.status403 ]
)
]
forM_ matrix $ \(title, passphrase, expectations) -> it title $ \ctx -> do
r <- request @ApiWallet ctx ("POST", "v2/wallets") Default simplePayload
let payload = updatePassPayload passphrase "Secure passphrase 2"
let endpoint = "v2/wallets" </> (getFromResponse walletId r)
</> ("passphrase" :: Text)
rup <- request @ApiWallet ctx ("PUT", endpoint) Default payload
verify rup expectations

describe "WALLETS_UPDATE_PASS_03 - Can update pass from pass that's boundary\
\ value" $ do
let matrix =
[ ( show passphraseMinLength ++ " char long"
, T.pack (replicate passphraseMinLength 'ź') )
, ( show passphraseMaxLength ++ " char long"
, T.pack (replicate passphraseMaxLength 'ą') )
, ( "Russian passphrase", russianWalletName )
, ( "Polish passphrase", polishWalletName )
, ( "Kanji passphrase", kanjiWalletName )
, ( "Arabic passphrase", arabicWalletName )
, ( "Wildcards passphrase", wildcardsWalletName )
]
forM_ matrix $ \(title, oldPass) -> it title $ \ctx -> do
let createPayload = Json [json| {
"name": "Name of the wallet",
"mnemonic_sentence": #{mnemonics24},
"passphrase": #{oldPass}
} |]
r <- request @ApiWallet ctx ("POST", "v2/wallets") Default createPayload
let payload = updatePassPayload oldPass
(T.pack (replicate passphraseMaxLength '💘'))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love it.

let endpoint = "v2/wallets" </> (getFromResponse walletId r)
</> ("passphrase" :: Text)
rup <- request @ApiWallet ctx ("PUT", endpoint) Default payload
expectResponseCode @IO HTTP.status204 rup

describe "WALLETS_UPDATE_PASS_02,03 - invalid payloads" $ do
let matrix =
[ ( "[] as new passphrase"
, Json [json| {
"old_passphrase": "Secure passphrase",
"new_passphrase": []
} |]
, [ expectResponseCode @IO HTTP.status400
, expectErrorMessage "expected Text, encountered Array" ]
)
, ( "[] as old passphrase"
, Json [json| {
"old_passphrase": [],
"new_passphrase": "Secure passphrase"
} |]
, [ expectResponseCode @IO HTTP.status400
, expectErrorMessage "expected Text, encountered Array" ]
)
, ( "Num as old passphrase"
, Json [json| {
"old_passphrase": 12345678910,
"new_passphrase": "Secure passphrase"
} |]
, [ expectResponseCode @IO HTTP.status400
, expectErrorMessage "expected Text, encountered Number" ]
)
, ( "Num as new passphrase"
, Json [json| {
"old_passphrase": "Secure passphrase",
"new_passphrase": 12345678910
} |]
, [ expectResponseCode @IO HTTP.status400
, expectErrorMessage "expected Text, encountered Number" ]
)
, ( "Missing old passphrase"
, Json [json| {
"new_passphrase": "Secure passphrase"
} |]
, [ expectResponseCode @IO HTTP.status400
, expectErrorMessage "key \"old_passphrase\" not present" ]
)
, ( "Missing new passphrase"
, Json [json| {
"old_passphrase": "Secure passphrase"
} |]
, [ expectResponseCode @IO HTTP.status400
, expectErrorMessage "key \"new_passphrase\" not present" ]
)
]
forM_ matrix $ \(title, payload, expectations) -> it title $ \ctx -> do
r <- request @ApiWallet ctx ("POST", "v2/wallets") Default simplePayload
let endpoint = "v2/wallets" </> (getFromResponse walletId r)
</> ("passphrase" :: Text)
rup <- request @ApiWallet ctx ("PUT", endpoint) Default payload
verify rup expectations

it "WALLETS_UPDATE_PASS_04 - Deleted wallet is not available" $ \ctx -> do
r <- request @ApiWallet ctx ("POST", "v2/wallets") Default simplePayload
let payload = updatePassPayload "Secure passphrase" "Secure passphrase2"
let delEndp = "v2/wallets" </> (getFromResponse walletId r)
_ <- request @ApiWallet ctx ("DELETE", delEndp) Default Empty

let updEndp = delEndp </> ("passphrase" :: Text)
rup <- request @ApiWallet ctx ("PUT", updEndp) Default payload
expectResponseCode @IO HTTP.status403 rup

describe "WALLETS_UPDATE_PASS_04 - non-existing wallets" $ do
forM_ falseWalletIds $ \(title, walId) -> it title $ \ctx -> do
let payload = updatePassPayload "Secure passphrase" "Secure passphrase2"
let endpoint = "v2/wallets" </> T.pack walId </> ("passphrase" :: Text)
rup <- request @ApiWallet ctx ("PUT", endpoint) Default payload
if (title == "40 chars hex") then
expectResponseCode @IO HTTP.status403 rup
else
expectResponseCode @IO HTTP.status404 rup
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a slight inconsistency in the behavior: There is 403 being returned in case when {wallet-id} is a 40 char long hex encoded string (ofc, for the wallet that does not exist). For any other string it returns 404 (e.g. longer/shorter than 40 chars, 40 char length but not valid hex).

I think I'd be expecting either 404 for all. Or 400 for not valid IDs and 404 for valid and not existing (but this cannot be achieved now #252 (comment))

Not sure if this is something that can be addressed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm... Probably has to do with the way we map the error when a root private key can't be found. I'll have a look at it.


it "WALLETS_UPDATE_PASS_04 - 'almost' valid walletId" $ \ctx -> do
r <- request @ApiWallet ctx ("POST", "v2/wallets") Default simplePayload
let payload = updatePassPayload "Secure passphrase" "Secure passphrase2"
let endpoint =
"v2/wallets"
</> (T.append (getFromResponse walletId r) "0")
</> ("passphrase" :: Text)
rup <- request @ApiWallet ctx ("PUT", endpoint) Default payload
expectResponseCode @IO HTTP.status404 rup

describe "WALLETS_UPDATE_PASS_07 - HTTP headers" $ do
let matrix =
[ ( "No HTTP headers -> 415", None
, [expectResponseCode @IO HTTP.status415] )
, ( "Accept: text/plain -> 406"
, Headers
[ ("Content-Type", "application/json")
, ("Accept", "text/plain") ]
, [expectResponseCode @IO HTTP.status406]
)
, ( "No Accept -> 204"
, Headers [ ("Content-Type", "application/json") ]
, [expectResponseCode @IO HTTP.status204]
)
, ( "No Content-Type -> 415"
, Headers [ ("Accept", "application/json") ]
, [expectResponseCode @IO HTTP.status415]
)
, ( "Content-Type: text/plain -> 415"
, Headers [ ("Content-Type", "text/plain") ]
, [expectResponseCode @IO HTTP.status415]
)
]
forM_ matrix $ \(title, headers, expectations) -> it title $ \ctx -> do
r <- request @ApiWallet ctx ("POST", "v2/wallets") Default simplePayload
let payload =
updatePassPayload "Secure passphrase" "Secure passphrase2"
let endpoint =
"v2/wallets"
</> (getFromResponse walletId r)
</> ("passphrase" :: Text)
rup <- request @ApiWallet ctx ("PUT", endpoint) headers payload
verify rup expectations

where
falseWalletIds =
[ ("40 chars hex", replicate 40 '1')
Expand Down Expand Up @@ -1070,6 +1316,12 @@ spec = do
"name": #{name}
} |]

updatePassPayload :: Text -> Text -> Payload
updatePassPayload oldPass newPass = Json [json| {
"old_passphrase": #{oldPass},
"new_passphrase": #{newPass}
} |]

mnemonics3 :: [Text]
mnemonics3 = ["diamond", "flee", "window"]

Expand Down
2 changes: 0 additions & 2 deletions specifications/api/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,6 @@ responsesPutWallet: &responsesPutWallet
<<: *responsesErr400
<<: *responsesErr404
<<: *responsesErr406
<<: *responsesErr410
<<: *responsesErr415
200:
description: Ok
Expand All @@ -708,7 +707,6 @@ responsesPutWalletPassphrase: &responsesPutWalletPassphrase
<<: *responsesErr403
<<: *responsesErr404
<<: *responsesErr406
<<: *responsesErr410
<<: *responsesErr415
204:
description: No Content
Expand Down