From 2742f827aa6f0908e5184294cd4c4c2ce935f96d Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Tue, 14 Jan 2020 20:35:21 -0500 Subject: [PATCH] The user is now prevented from proceeding forward if their credentials are incorrect --- app/src/main/cpp/Demo.hpp | 125 +++--------------- app/src/main/cpp/manager/Tok.h | 14 ++ app/src/main/cpp/model/APIInfo.h | 2 + app/src/main/cpp/model/CoverArt.h | 2 + app/src/main/cpp/model/User.h | 2 +- .../main/cpp/utility/JNIObjectConversion.h | 112 ++++++++++++++-- .../example/mear/activities/LoginActivity.kt | 5 + 7 files changed, 145 insertions(+), 117 deletions(-) diff --git a/app/src/main/cpp/Demo.hpp b/app/src/main/cpp/Demo.hpp index a40af80..3ce411b 100644 --- a/app/src/main/cpp/Demo.hpp +++ b/app/src/main/cpp/Demo.hpp @@ -33,6 +33,7 @@ #include "repository/SongRepository.h" #include "repository/TokenRepository.h" #include "repository/UserRepository.h" +#include "utility/JNIObjectConversion.h" template @@ -365,13 +366,9 @@ Java_com_example_mear_repositories_TrackRepository_retrieveSongs( jobject token, jstring baseUri ) { - jclass tokenClass = env->FindClass("com/example/mear/models/Token"); jclass songClass = env->FindClass( "com/example/mear/models/Song"); - auto tokField = env->GetFieldID(tokenClass, "accessToken", "Ljava/lang/String;"); - auto tokObj = env->GetObjectField(token, tokField); - std::string tokStr = env->GetStringUTFChars((jstring)tokObj, nullptr); - model::Token tk(tokStr); + auto tk = utility::JNIObjectConversion::ObjToToken(env, token); const std::string uri = env->GetStringUTFChars(baseUri, nullptr); env->DeleteLocalRef(baseUri); @@ -401,14 +398,10 @@ Java_com_example_mear_repositories_TrackRepository_retrieveSongsIncludingDownloa jstring baseUri, jstring appPathStr ) { - jclass tokenClass = env->FindClass("com/example/mear/models/Token"); jclass songClass = env->FindClass( "com/example/mear/models/Song"); - auto tokField = env->GetFieldID(tokenClass, "accessToken", "Ljava/lang/String;"); - auto tokObj = env->GetObjectField(token, tokField); - std::string tokStr = env->GetStringUTFChars((jstring)tokObj, nullptr); std::string appPath = env->GetStringUTFChars((jstring)appPathStr, nullptr); - model::Token tk(tokStr); + auto tk = utility::JNIObjectConversion::ObjToToken(env, token); const std::string uri = env->GetStringUTFChars(baseUri, nullptr); env->DeleteLocalRef(baseUri); @@ -465,20 +458,11 @@ Java_com_example_mear_repositories_CoverArtRepository_retrieveCoverArtImage( jobject coverArt, jstring apiUri ) { - jclass coverArtClass = env->GetObjectClass(coverArt); - auto idField = env->GetFieldID(coverArtClass, "id", "I"); - auto titleField = env->GetFieldID(coverArtClass, "title", "Ljava/lang/String;"); - auto id = env->GetIntField(coverArt, idField); - auto title = (jstring)env->GetObjectField(coverArt, titleField); + auto token = utility::JNIObjectConversion::ObjToToken(env, tokenObj); - jclass tokenClass = env->GetObjectClass(tokenObj); - auto accessTokenId = env->GetFieldID(tokenClass, "accessToken", "Ljava/lang/String;"); - auto accessTokenVal = (jstring) env->GetObjectField(tokenObj, accessTokenId); + auto cover = utility::JNIObjectConversion:: + ObjToCoverArt(env, coverArt); - model::Token token; - token.accessToken = env->GetStringUTFChars(accessTokenVal, nullptr); - - model::CoverArt cover(id, env->GetStringUTFChars(title, nullptr)); repository::CoverArtRepository coverArtRepo; auto data = coverArtRepo.retrieveCoverArtData(token, cover, env->GetStringUTFChars(apiUri, nullptr)); @@ -500,18 +484,8 @@ Java_com_example_mear_repositories_APIRepository_retrieveAPIInfoRecord( auto apiInfo = retrieveAPIInfo(path); - jclass apiInfoClass = env->FindClass( "com/example/mear/models/APIInfo"); - jmethodID jconstructor = env->GetMethodID( apiInfoClass, "", "()V" ); - jobject apiInfoObj = env->NewObject( apiInfoClass, jconstructor ); - - jmethodID uriId = env->GetMethodID( apiInfoClass, "setUri", "(Ljava/lang/String;)V" ); - jmethodID versionId = env->GetMethodID( apiInfoClass, "setVersion", "(I)V" ); - - jint versionVal = apiInfo.version; - jstring uriVal = env->NewStringUTF(apiInfo.uri.c_str()); - - env->CallVoidMethod(apiInfoObj, uriId, uriVal); - env->CallVoidMethod( apiInfoObj, versionId, versionVal); + auto apiInfoObj = utility::JNIObjectConversion:: + APIInfoToObj(env, apiInfo); return apiInfoObj; } @@ -527,15 +501,7 @@ Java_com_example_mear_repositories_TokenRepository_retrieveTokenRecord( const auto path = env->GetStringUTFChars(pathStr, nullptr); auto token = retrieveSavedToken(path); - auto tokenClass = env->FindClass("com/example/mear/models/Token"); - auto jConstructor = env->GetMethodID(tokenClass, "", "()V"); - auto tokenObj = env->NewObject(tokenClass, jConstructor); - - auto accessTokenId = env->GetMethodID(tokenClass, "setAccessToken", "(Ljava/lang/String;)V"); - - auto accessTokenStr = env->NewStringUTF(token.accessToken.c_str()); - - env->CallVoidMethod(tokenObj, accessTokenId, accessTokenStr); + auto tokenObj = utility::JNIObjectConversion::TokenToObj(env, token); return tokenObj; } @@ -550,10 +516,7 @@ Java_com_example_mear_repositories_TrackRepository_downloadSong( jobject songObj, jstring pathStr ) { - auto tokenClass = env->GetObjectClass(tokenObj); - auto accessTokenId = env->GetFieldID(tokenClass, "accessToken", "Ljava/lang/String;"); - auto accessTokenVal = (jstring) env->GetObjectField(tokenObj, accessTokenId); - model::Token token(env->GetStringUTFChars(accessTokenVal, nullptr)); + auto token = utility::JNIObjectConversion::ObjToToken(env, tokenObj); auto song = ObjToSong(env, songObj); auto path = env->GetStringUTFChars(pathStr, nullptr); @@ -572,17 +535,15 @@ Java_com_example_mear_repositories_TrackRepository_retrieveSong( jobject songObj, jstring uriStr ) { - auto tokenClass = env->GetObjectClass(tokenObj); auto songClass = env->GetObjectClass(songObj); - auto accessTokenField = env->GetFieldID(tokenClass, "accessToken", "Ljava/lang/String;"); auto idField = env->GetFieldID(songClass, "id", "I"); - auto accessTokenStr = (jstring)env->GetObjectField(tokenObj, accessTokenField); auto idInt = env->GetIntField(songObj, idField); auto uri = env->GetStringUTFChars(uriStr, nullptr); - model::Token token(env->GetStringUTFChars(accessTokenStr, nullptr)); + auto token = utility::JNIObjectConversion::ObjToToken(env, tokenObj); + model::Song song(idInt); song = retrieveSong(token, song, uri); @@ -599,21 +560,10 @@ Java_com_example_mear_repositories_UserRepository_retrieveUserCredentials( jobject thisObj, jstring dataPath ) { - jclass userClass = env->FindClass("com/example/mear/models/User"); - jmethodID userContructor = env->GetMethodID(userClass, "", "()V"); - jobject userObj = env->NewObject(userClass, userContructor); - const std::string dataPathStr = env->GetStringUTFChars(dataPath, nullptr); auto user = retrieveCredentials(dataPathStr); - jmethodID usernameId = env->GetMethodID(userClass, "setUsername", "(Ljava/lang/String;)V"); - jmethodID passwordId = env->GetMethodID(userClass, "setPassword", "(Ljava/lang/String;)V"); - - jstring username = env->NewStringUTF(user.username.c_str()); - jstring password = env->NewStringUTF(user.password.c_str()); - - env->CallVoidMethod(userObj, usernameId, username); - env->CallVoidMethod(userObj, passwordId, password); + auto userObj = utility::JNIObjectConversion::UserToObj(env, user); return userObj; } @@ -626,28 +576,13 @@ Java_com_example_mear_repositories_UserRepository_logUser( jobject thisObj, jobject user, jstring apiUri ) { - jclass userClass = env->GetObjectClass(user); - auto passwordField = env->GetFieldID(userClass, "password", "Ljava/lang/String;"); - auto usernameField = env->GetFieldID(userClass, "username", "Ljava/lang/String;"); - - auto password = (jstring)env->GetObjectField(user, passwordField); - auto username = (jstring)env->GetObjectField(user, usernameField); - const std::string api = env->GetStringUTFChars(apiUri, nullptr); - model::User us(env->GetStringUTFChars(username, nullptr), - env->GetStringUTFChars(password, nullptr)); + + auto us = utility::JNIObjectConversion::ObjToUser(env, user); auto token = fetchToken(us, api); - jclass tokenClass = env->FindClass( "com/example/mear/models/Token"); - jmethodID jconstructor = env->GetMethodID( tokenClass, "", "()V" ); - jobject tokenObj = env->NewObject( tokenClass, jconstructor ); - - jmethodID tokenAccess = env->GetMethodID( tokenClass, "setAccessToken", "(Ljava/lang/String;)V" ); - - jstring title = env->NewStringUTF(token.accessToken.c_str()); - - env->CallVoidMethod(tokenObj, tokenAccess, title); + auto tokenObj = utility::JNIObjectConversion::TokenToObj(env, token); return tokenObj; } @@ -763,14 +698,8 @@ Java_com_example_mear_repositories_APIRepository_saveAPIInfoRecord( jobject apiInfoObj, jstring pathStr ) { - auto apiInfoClass = env->GetObjectClass(apiInfoObj); - auto uriId = env->GetFieldID(apiInfoClass, "uri", "Ljava/lang/String;"); - auto versionId = env->GetFieldID(apiInfoClass, "version", "I"); - - auto uriStr = (jstring) env->GetObjectField(apiInfoObj, uriId); - auto versionInt = env->GetIntField(apiInfoObj, versionId); - - model::APIInfo apiInfo(env->GetStringUTFChars(uriStr, nullptr), versionInt); + auto apiInfo = utility::JNIObjectConversion:: + ObjToAPIInfo(env, apiInfoObj); auto path = env->GetStringUTFChars(pathStr, nullptr); saveAPIInfo(apiInfo, path); @@ -809,12 +738,7 @@ Java_com_example_mear_repositories_TokenRepository_saveTokenRecord( jobject tokenObj, jstring pathStr ) { - auto tokenClass = env->GetObjectClass(tokenObj); - auto accessTokenId = env->GetFieldID(tokenClass, "accessToken", "Ljava/lang/String;"); - - auto accessTokenVal = (jstring) env->GetObjectField(tokenObj, accessTokenId); - - model::Token token(env->GetStringUTFChars(accessTokenVal, nullptr)); + auto token = utility::JNIObjectConversion::ObjToToken(env, tokenObj); auto path = env->GetStringUTFChars(pathStr, nullptr); saveToken(token, path); @@ -829,18 +753,9 @@ Java_com_example_mear_repositories_UserRepository_saveUserCredentials( jobject user, jstring appDirectory ) { - jclass userClass = env->GetObjectClass(user); - auto usernameId = env->GetFieldID(userClass, "username", "Ljava/lang/String;"); - auto passwordId = env->GetFieldID(userClass, "password", "Ljava/lang/String;"); - - auto usernameStr = (jstring) env->GetObjectField(user, usernameId); - auto passwordStr = (jstring) env->GetObjectField(user, passwordId); - - const std::string username = env->GetStringUTFChars(usernameStr, nullptr); - const std::string password = env->GetStringUTFChars(passwordStr, nullptr); const std::string appDirectoryStr = env->GetStringUTFChars(appDirectory, nullptr); - model::User usr(username, password); + auto usr = utility::JNIObjectConversion::ObjToUser(env, user); saveCredentials(usr, appDirectoryStr); } diff --git a/app/src/main/cpp/manager/Tok.h b/app/src/main/cpp/manager/Tok.h index 5d5d002..2bed905 100644 --- a/app/src/main/cpp/manager/Tok.h +++ b/app/src/main/cpp/manager/Tok.h @@ -45,11 +45,19 @@ namespace manager { curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, respBodyRetriever); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeOut()); res = curl_easy_perform(curl); curl_easy_cleanup(curl); if (res == CURLE_OK) { + long respCode; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &respCode); + + if (respCode != 200) { + return Token(std::move("failure")); + } + auto s = nlohmann::json::parse(resp); const auto tokenStr = std::move(s["token"].get()); @@ -78,6 +86,12 @@ namespace manager { } + template + constexpr L timeOut() noexcept { + return 15L; + } + + constexpr auto loginEndpoint() noexcept { return "api/v1/login"; } diff --git a/app/src/main/cpp/model/APIInfo.h b/app/src/main/cpp/model/APIInfo.h index 502e09a..0b8db00 100644 --- a/app/src/main/cpp/model/APIInfo.h +++ b/app/src/main/cpp/model/APIInfo.h @@ -16,6 +16,8 @@ namespace model { uri(uri) { } APIInfo(const std::string& uri, const int version) : uri(uri), version(version) { } + APIInfo(const std::string&& uri, const int version) : + uri(uri), version(version) { } APIInfo(const std::string& uri, const std::string& endpoint, const int version) : uri(uri), endpoint(endpoint), version(version) { } diff --git a/app/src/main/cpp/model/CoverArt.h b/app/src/main/cpp/model/CoverArt.h index e5657f4..5c7cbb8 100644 --- a/app/src/main/cpp/model/CoverArt.h +++ b/app/src/main/cpp/model/CoverArt.h @@ -13,6 +13,8 @@ namespace model { CoverArt() = default; CoverArt(const int id, const std::string& title) : id(id), title(title) { } + CoverArt(const int id, const std::string&& title) : + id(id), title(title) { } int id; std::string title; diff --git a/app/src/main/cpp/model/User.h b/app/src/main/cpp/model/User.h index 8ed1a30..59dc371 100644 --- a/app/src/main/cpp/model/User.h +++ b/app/src/main/cpp/model/User.h @@ -16,7 +16,7 @@ public: User(const std::string& user, const std::string& pass) : username(user), password(pass) { } User(const std::string&& user, const std::string&& pass) : - username(std::move(user)), password(std::move(pass)) {} + username(user), password(pass) {} std::string username; std::string password; diff --git a/app/src/main/cpp/utility/JNIObjectConversion.h b/app/src/main/cpp/utility/JNIObjectConversion.h index b8e336b..ad1ca10 100644 --- a/app/src/main/cpp/utility/JNIObjectConversion.h +++ b/app/src/main/cpp/utility/JNIObjectConversion.h @@ -13,36 +13,126 @@ #include "../model/User.h" namespace utility { - template + template class JNIObjectConversion { public: // jobject to classes - template - static Token ObjToToken(JE *env, Obj tokenObj) { + template + static SomeClass ObjToToken(JE *env, Obj tokenObj) { auto tokenClass = env->GetObjectClass(tokenObj); - auto accessTokenId = env->GetFieldId(tokenClass, "accessToken", "Ljava/lang/String;"); + auto accessTokenId = env->GetFieldID(tokenClass, "accessToken", "Ljava/lang/String;"); - auto accessTokenVal = env->GetObjectField(tokenObj, accessTokenId); + auto accessTokenVal = static_cast( + env->GetObjectField(tokenObj, accessTokenId)); - Token token(std::move(env->GetStringUTFChars(accessTokenVal, nullptr))); + SomeClass token(std::move(env->GetStringUTFChars(accessTokenVal, nullptr))); return token; } + template + static SomeClass ObjToUser(JE *env, Obj userObj) { + auto userClass = env->GetObjectClass(userObj); + + auto usernameId = env->GetFieldID(userClass, "username", "Ljava/lang/String;"); + auto passwordId = env->GetFieldID(userClass, "password", "Ljava/lang/String;"); + + auto usernameVal = static_cast(env->GetObjectField(userObj, usernameId)); + auto passwordVal = static_cast(env->GetObjectField(userObj, passwordId)); + + SomeClass user(std::move(env->GetStringUTFChars(usernameVal, nullptr)), + std::move(env->GetStringUTFChars(passwordVal, nullptr))); + + return user; + } + + template + static SomeClass ObjToAPIInfo(JE *env, Obj apiObj) { + auto apiClass = env->GetObjectClass(apiObj); + + auto uriId = env->GetFieldID(apiClass, "uri", "Ljava/lang/String;"); + auto versionId = env->GetFieldID(apiClass, "version", "I"); + + auto uriVal = static_cast(env->GetObjectField(apiObj, uriId)); + auto versionVal = env->GetIntField(apiObj, versionId); + + SomeClass apiInfo(std::move(env->GetStringUTFChars(uriVal, nullptr)), versionVal); + + return apiInfo; + } + + template + static SomeClass ObjToCoverArt(JE *env, Obj covObj) { + auto coverClass = env->GetObjectClass(covObj); + + auto idField = env->GetFieldID(coverClass, "id", "I"); + auto titleField = env->GetFieldID(coverClass, "title", "Ljava/lang/String;"); + + auto id = env->GetIntField(covObj, idField); + auto title = static_cast(env->GetObjectField(covObj, titleField)); + + SomeClass cover(id, std::move(env->GetStringUTFChars(title, nullptr))); + + return cover; + } + // classes to jobject - template - static Obj TokenToObj(JE *env, const Token& token) { - auto tokenClass = env->FindClass("com/example/mear/models/Token"); + template + static Obj TokenToObj(JE *env, const SomeClass& token) { + auto tokenClass = env->FindClass(classBasePath("models/Token").c_str()); auto tokenConstructor = env->GetMethodID(tokenClass, "", "()V"); auto tokenObj = env->NewObject(tokenClass, tokenConstructor); auto accessTokenId = env->GetFieldID(tokenClass, "accessToken", "Ljava/lang/String;"); - // TODO: left off here + env->SetObjectField(tokenObj, + accessTokenId, env->NewStringUTF(token.accessToken.c_str())); + + return tokenObj; + } + + template + static Obj UserToObj(JE *env, const SomeClass& user) { + auto userClass = env->FindClass(classBasePath("models/User").c_str()); + auto classConstructor = env->GetMethodID(userClass, "", "()V"); + auto userObj = env->NewObject(userClass, classConstructor); + + auto usernameId = env->GetFieldID(userClass, "username", "Ljava/lang/String;"); + auto passwordId = env->GetFieldID(userClass, "password", "Ljava/lang/String;"); + + env->SetObjectField(userObj, usernameId, env->NewStringUTF(user.username.c_str())); + env->SetObjectField(userObj, passwordId, env->NewStringUTF(user.password.c_str())); + + return userObj; + } + + template + static Obj APIInfoToObj(JE *env, const SomeClass& apiInfo) { + auto apiClass = env->FindClass(classBasePath("models/APIInfo").c_str()); + auto apiConstructor = env->GetMethodID(apiClass, "", "()V"); + auto apiObj = env->NewObject(apiClass, apiConstructor); + + auto uriId = env->GetFieldID(apiClass, "uri", "Ljava/lang/String;"); + auto versionId = env->GetFieldID(apiClass, "version", "I"); + + env->SetObjectField(apiObj, uriId, env->NewStringUTF(apiInfo.uri.c_str())); + env->SetIntField(apiObj, versionId, apiInfo.version); + + return apiObj; + } + + + template + static Str classBasePath(const Str& classPath = std::string()) noexcept { + Str basePath("com/example/mear/"); + if (!classPath.empty()) { + basePath.append(classPath); + } + + return basePath; } - private: }; } diff --git a/app/src/main/java/com/example/mear/activities/LoginActivity.kt b/app/src/main/java/com/example/mear/activities/LoginActivity.kt index 78b844b..0b03660 100644 --- a/app/src/main/java/com/example/mear/activities/LoginActivity.kt +++ b/app/src/main/java/com/example/mear/activities/LoginActivity.kt @@ -5,6 +5,7 @@ import kotlinx.android.synthetic.main.content_login.* import android.content.Intent import android.os.Bundle +import android.widget.Toast import org.jetbrains.anko.toast import com.example.mear.models.* @@ -40,6 +41,10 @@ class LoginActivity : BaseServiceActivity() { val usrRepo = UserRepository() val tokenRepo = TokenRepository() val myToken = usrRepo.fetchToken(usr, apiInfo.uri) + if (myToken.accessToken == "failure") { + Toast.makeText(this, "login failed, try again", Toast.LENGTH_SHORT).show() + return + } try { val pa = appDirectory()