From f30e7a54d8f40cfe2d6d6f48c9a4f630d11bc2ed Mon Sep 17 00:00:00 2001 From: pattarawut Date: Wed, 24 Jul 2019 12:42:20 +0700 Subject: [PATCH] Modified odin to trim leading/trailing whitespace --- Cpp/odin-views/app.mint.cpp | 4 +- Cpp/odin-views/registration.cpp | 8 +- tests/registration-self.fg | 14 +++ views/app.register.fg | 57 +++++++++- views/app.register.test.json | 189 ++++++++++++++++++++++++++++++++ 5 files changed, 261 insertions(+), 11 deletions(-) diff --git a/Cpp/odin-views/app.mint.cpp b/Cpp/odin-views/app.mint.cpp index d10445b..febb3ad 100644 --- a/Cpp/odin-views/app.mint.cpp +++ b/Cpp/odin-views/app.mint.cpp @@ -65,12 +65,12 @@ namespace { "Must pass both username and password fields"); } const auto username = - fostlib::coerce(body["username"]); + fostlib::trim(fostlib::coerce(body["username"])); const auto password = fostlib::coerce(body["password"]); auto user = odin::credentials( - cnx, username, password, req.remote_address()); + cnx, username.value(), password, req.remote_address()); if (user.isnull()) { throw fostlib::exceptions::not_implemented( __PRETTY_FUNCTION__, "User not found"); diff --git a/Cpp/odin-views/registration.cpp b/Cpp/odin-views/registration.cpp index c751aaf..1d99811 100644 --- a/Cpp/odin-views/registration.cpp +++ b/Cpp/odin-views/registration.cpp @@ -50,9 +50,11 @@ namespace { auto body_str = fostlib::coerce( fostlib::coerce(req.data()->data())); fostlib::json body = fostlib::json::parse(body_str); - const auto username = - fostlib::coerce>( - body["username"]); + const auto username = (config["trim"] != fostlib::json(false)) ? + fostlib::trim(fostlib::coerce>( + body["username"])) : + fostlib::coerce>( + body["username"]); if (not username || username.value().empty()) { throw fostlib::exceptions::not_implemented( diff --git a/tests/registration-self.fg b/tests/registration-self.fg index debb710..94d6543 100644 --- a/tests/registration-self.fg +++ b/tests/registration-self.fg @@ -33,6 +33,20 @@ odin.user test-user test-user pw1234 odin.jwt.authorization test-user pw1234 GET odin /api/ 200 {"odin": {"user": "./user/:user-id/"}, "user": {"id": "test-user"}} +setting webserver views/odin/register-trim-false { + "view": "odin.register", + "configuration": { + "trim": false + } +} + +# Any leading/trailing whitespace in username will be trimmed +POST odin/register / {"username": "\u0020user\u2008", "password": "password1234"} 201 +POST odin/login / {"username": "user", "password": "password1234"} 200 + +# However, if set "trim" config to false, it won't trim +POST odin/register-trim-false / {"username": "\u0020user2\u2008", "password": "password1234"} 201 +POST odin/login / {"username": "\u0020user2\u2008", "password": "password1234"} 200 # Put the user PUT odin /api/user/test-user {"password": "1234"} 200 diff --git a/views/app.register.fg b/views/app.register.fg index 474ba4e..47b061c 100644 --- a/views/app.register.fg +++ b/views/app.register.fg @@ -117,6 +117,15 @@ POST odin/app/register / { "email": "brian@bowling.com" } 500 +# Check database validity, the identity_id should be the identity that installation API generated +GET odin/test/validate-register /fred 200 { + "id": "installation_ref", + "email": "fred@bowling.com", + "full_name": "Fred", + "login": "fred", + "app_id": "bowling-app" +} + # Existing username register twice should failed sql.insert odin.identity {"id": "installation_ref2"} @@ -136,11 +145,47 @@ POST odin/app/register / { "email": "fred2@bowling.com" } 500 -# Check database validity, the identity_id should be the identity that installation API generated -GET odin/test/validate-register /fred 200 { - "id": "installation_ref", - "email": "fred@bowling.com", - "full_name": "Fred", - "login": "fred", +# Register with leading/trailing username should be trimmed by default +POST odin/app/register / { + "username": "\uFEFF\n\u3000broski\u1680\u180E", + "password": "mercury2", + "password2": "mercury2", + "full-name": "Broski", + "email": "broski@bowling.com" +} 200 + +# The data should already be trimmed after registration +GET odin/test/validate-register /broski 200 { + "id": "installation_ref2", + "email": "broski@bowling.com", + "full_name": "Broski", + "login": "broski", "app_id": "bowling-app" } + +# Register new account with "trim": false config +sql.insert odin.identity {"id": "installation_ref3"} +sql.insert odin.app_user_installation_id_ledger { + "reference": "reference3", + "app_id": "bowling-app", + "identity_id": "installation_ref3", + "installation_id": "fred-mobile3" +} + +set app_jwt (odin.jwt.mint {"sub": "installation_ref3", "iss": "http://odin.felspar.com/app/bowling-app"} bowling-app) +set-path testserver.headers ["Authorization"] (cat "Bearer " (lookup app_jwt)) +POST odin/app/register-test-trim-false / { + "username": "ciao", + "password": "mercury2", + "password2": "mercury2", + "full-name": "\u2002Ciao\u2001", + "email": "\u2000ciao@bowling.com\t" +} 200 + +GET odin/test/validate-register /ciao 200 { + "id": "installation_ref3", + "email": "\u2000ciao@bowling.com\t", + "full_name": "\u2002Ciao\u2001", + "login": "ciao", + "app_id": "bowling-app" +} \ No newline at end of file diff --git a/views/app.register.test.json b/views/app.register.test.json index 68bea34..58f9002 100644 --- a/views/app.register.test.json +++ b/views/app.register.test.json @@ -23,6 +23,195 @@ } }] } + }, + "views/odin/app/register-test-trim-false": { + "view": "odin.app.secure", + "configuration": { + "unsecure": { + "view": "fost.response.403" + }, + "secure": { + "view": "fost.schema.validate", + "configuration": { + "schema": { + "type": "object", + "properties": { + "username": { + "type": "string", + "minLength": 1 + }, + "password": { + "type": "string", + "minLength": 8 + }, + "password2": { + "type": "string", + "minLength": 8 + }, + "full_name": { + "type": "string" + }, + "email": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "username", + "password", + "password2", + "full-name", + "email" + ] + }, + "valid": { + "view": "odin.password.hash", + "configuration": { + "hash": [ + "body", + "password" + ], + "verify": [ + "body", + "password2" + ], + "then": { + "view": "odin.middleware.reference", + "configuration": { + "then": { + "view": "fost.control.status-condition", + "configuration": { + "if": { + "view": "fostgres.control.pg-error", + "configuration": { + "execute": { + "view": "fostgres.sql", + "configuration": { + "sql": [ + { + "path": [], + "return": "object", + "POST": [ + { + "table": "odin.credentials_password_ledger", + "columns": { + "reference": { + "source": [ + "request", + "headers", + "__odin_reference" + ] + }, + "identity_id": { + "source": [ + "request", + "headers", + "__user" + ] + }, + "login": { + "source": ["body", "username"] + }, + "password": { + "source": ["request", "headers", "__hash"] + }, + "process": { + "source": ["request", "headers", "__hash_process"] + } + } + }, + { + "table": "odin.identity_full_name_ledger", + "columns": { + "reference": { + "source": [ + "request", + "headers", + "__odin_reference" + ] + }, + "identity_id": { + "source": [ + "request", + "headers", + "__user" + ] + }, + "full_name": { + "source": ["body", "full-name"], + "trim": false + } + } + }, + { + "table": "odin.identity_email_ledger", + "columns": { + "reference": { + "source": [ + "request", + "headers", + "__odin_reference" + ] + }, + "identity_id": { + "source": [ + "request", + "headers", + "__user" + ] + }, + "email": { + "source": ["body", "email"], + "trim": false + } + } + }, + { + "table": "odin.app_user_ledger", + "columns": { + "reference": { + "source": [ + "request", + "headers", + "__odin_reference" + ] + }, + "app_id": { + "source": ["request", "headers", "__app"] + }, + "identity_id": { + "source": [ + "request", + "headers", + "__user" + ] + } + } + } + ] + } + ] + } + }, + "": "fost.response.500" + } + }, + "then": { + "view": "odin.app.mint", + "configuration": { + "expires": {"hours": 72} + } + }, + "else": "fost.response.500" + } + } + } + } + } + } + } + } + } } } }