auth
parent
b6e4c3dd22
commit
9160d6a330
|
@ -10,6 +10,9 @@ set(CROW_FEATURES compression)
|
||||||
|
|
||||||
find_package(Crow)
|
find_package(Crow)
|
||||||
find_package(CURL)
|
find_package(CURL)
|
||||||
|
find_package(OpenSSL)
|
||||||
|
|
||||||
|
message("SSL ${OPENSSL_INCLUDE_DIR}")
|
||||||
|
|
||||||
if (NOT CURL_FOUND)
|
if (NOT CURL_FOUND)
|
||||||
message("libcurl is required!")
|
message("libcurl is required!")
|
||||||
|
@ -28,6 +31,7 @@ add_executable(crowsite ${source_files})
|
||||||
target_link_libraries(crowsite BLT)
|
target_link_libraries(crowsite BLT)
|
||||||
target_link_libraries(crowsite Crow::Crow)
|
target_link_libraries(crowsite Crow::Crow)
|
||||||
target_link_libraries(crowsite ${CURL_LIBRARIES})
|
target_link_libraries(crowsite ${CURL_LIBRARIES})
|
||||||
|
target_link_libraries(crowsite OpenSSL::SSL OpenSSL::Crypto)
|
||||||
target_compile_options(crowsite PRIVATE -Wall -Wextra -Wpedantic)
|
target_compile_options(crowsite PRIVATE -Wall -Wextra -Wpedantic)
|
||||||
|
|
||||||
if (${ENABLE_ADDRSAN} MATCHES ON)
|
if (${ENABLE_ADDRSAN} MATCHES ON)
|
||||||
|
|
|
@ -27,13 +27,20 @@ namespace cs
|
||||||
request();
|
request();
|
||||||
|
|
||||||
static const std::string& getResponse(const std::string& domain);
|
static const std::string& getResponse(const std::string& domain);
|
||||||
|
static std::string getResponseAndClear(const std::string& domain);
|
||||||
|
static void clearResponse(const std::string& domain);
|
||||||
|
|
||||||
|
void setContentHeaderJson();
|
||||||
|
void setContentHeaderXForm();
|
||||||
|
void setContentHeader(const std::string& header);
|
||||||
void setAuthHeader(const std::string& header);
|
void setAuthHeader(const std::string& header);
|
||||||
|
|
||||||
void get(const std::string& domain, const std::string& data = "");
|
void get(const std::string& domain, const std::string& data = "");
|
||||||
|
|
||||||
void post(const std::string& domain, const std::string& data = "");
|
void post(const std::string& domain, const std::string& data = "");
|
||||||
|
|
||||||
|
long status();
|
||||||
|
|
||||||
~request();
|
~request();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,31 @@
|
||||||
#define CROWSITE_JELLYFIN_H
|
#define CROWSITE_JELLYFIN_H
|
||||||
|
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace cs::jellyfin
|
namespace cs::jellyfin
|
||||||
{
|
{
|
||||||
|
enum class auth_response {
|
||||||
|
AUTHORIZED,
|
||||||
|
USERNAME,
|
||||||
|
ERROR
|
||||||
|
};
|
||||||
|
|
||||||
|
struct client_data {
|
||||||
|
struct {
|
||||||
|
std::string name;
|
||||||
|
std::string serverId;
|
||||||
|
std::string Id;
|
||||||
|
std::string primaryImageTag;
|
||||||
|
bool hasPassword;
|
||||||
|
bool hasConfiguredPassword;
|
||||||
|
bool hasConfiguredEasyPassword;
|
||||||
|
bool enableAutoLogin;
|
||||||
|
std::string lastLoginDate;
|
||||||
|
std::string lastActivityDate;
|
||||||
|
} user;
|
||||||
|
std::string accessToken;
|
||||||
|
};
|
||||||
|
|
||||||
void setToken(std::string_view token);
|
void setToken(std::string_view token);
|
||||||
|
|
||||||
|
@ -18,6 +40,7 @@ namespace cs::jellyfin
|
||||||
std::string getUserData();
|
std::string getUserData();
|
||||||
|
|
||||||
bool hasUser(std::string_view username);
|
bool hasUser(std::string_view username);
|
||||||
|
auth_response authenticateUser(std::string_view username, std::string_view password);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
libs/BLT
2
libs/BLT
|
@ -1 +1 @@
|
||||||
Subproject commit a3f67571460d23fe819a3a3a572344e7030fba4a
|
Subproject commit 1e8f431f9eb06582083efde6489b59380f3e19ac
|
|
@ -58,8 +58,6 @@ namespace cs
|
||||||
|
|
||||||
void request::setAuthHeader(const std::string& header)
|
void request::setAuthHeader(const std::string& header)
|
||||||
{
|
{
|
||||||
curl_slist_free_all(headers);
|
|
||||||
headers = curl_slist_append(headers, "Content-Type: application/json");
|
|
||||||
headers = curl_slist_append(headers, ("Authorization: " + header).c_str());
|
headers = curl_slist_append(headers, ("Authorization: " + header).c_str());
|
||||||
|
|
||||||
curl_easy_setopt(handler, CURLOPT_HTTPHEADER, headers);
|
curl_easy_setopt(handler, CURLOPT_HTTPHEADER, headers);
|
||||||
|
@ -97,4 +95,38 @@ namespace cs
|
||||||
{
|
{
|
||||||
return responses[domain];
|
return responses[domain];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void request::clearResponse(const std::string& domain)
|
||||||
|
{
|
||||||
|
responses.erase(domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string request::getResponseAndClear(const std::string& domain)
|
||||||
|
{
|
||||||
|
std::string res = getResponse(domain);
|
||||||
|
clearResponse(domain);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void request::setContentHeaderJson()
|
||||||
|
{
|
||||||
|
setContentHeader("application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
void request::setContentHeaderXForm()
|
||||||
|
{
|
||||||
|
setContentHeader("application/x-www-form-urlencoded");
|
||||||
|
}
|
||||||
|
|
||||||
|
void request::setContentHeader(const std::string& header)
|
||||||
|
{
|
||||||
|
headers = curl_slist_append(headers, ("Content-Type: " + header).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
long request::status()
|
||||||
|
{
|
||||||
|
long code = 0;
|
||||||
|
curl_easy_getinfo(handler, CURLINFO_RESPONSE_CODE, &code);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -6,50 +6,106 @@
|
||||||
#include <crow/json.h>
|
#include <crow/json.h>
|
||||||
#include <blt/std/hashmap.h>
|
#include <blt/std/hashmap.h>
|
||||||
#include <blt/std/logging.h>
|
#include <blt/std/logging.h>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
struct
|
namespace cs::jellyfin
|
||||||
{
|
{
|
||||||
std::string token;
|
|
||||||
HASHMAP<std::string, std::string> user_ids;
|
|
||||||
} GLOBALS;
|
|
||||||
|
|
||||||
void cs::jellyfin::setToken(std::string_view token)
|
|
||||||
{
|
|
||||||
GLOBALS.token = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cs::jellyfin::processUserData()
|
|
||||||
{
|
|
||||||
auto data = getUserData();
|
|
||||||
|
|
||||||
auto json = crow::json::load(data);
|
|
||||||
|
|
||||||
for (const auto& user : json){
|
struct
|
||||||
auto username = user["Name"].s();
|
{
|
||||||
auto userid = user["Id"].s();
|
std::string token;
|
||||||
//BLT_TRACE("Processing %s = %s", username.operator std::string().c_str(), userid.operator std::string().c_str());
|
HASHMAP<std::string, std::string> user_ids;
|
||||||
GLOBALS.user_ids[username] = userid;
|
HASHMAP<std::string, client_data> logged_in_users;
|
||||||
|
} GLOBALS;
|
||||||
|
|
||||||
|
void setToken(std::string_view token)
|
||||||
|
{
|
||||||
|
GLOBALS.token = token;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
void processUserData()
|
||||||
std::string cs::jellyfin::getUserData()
|
{
|
||||||
{
|
auto data = getUserData();
|
||||||
|
|
||||||
|
auto json = crow::json::load(data);
|
||||||
|
|
||||||
|
for (const auto& user : json)
|
||||||
|
{
|
||||||
|
auto username = user["Name"].s();
|
||||||
|
auto userid = user["Id"].s();
|
||||||
|
//BLT_TRACE("Processing %s = %s", username.operator std::string().c_str(), userid.operator std::string().c_str());
|
||||||
|
GLOBALS.user_ids[username] = userid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getUserData()
|
||||||
|
{
|
||||||
#define url "https://media.tpgc.me/Users"
|
#define url "https://media.tpgc.me/Users"
|
||||||
|
|
||||||
|
cs::request request;
|
||||||
|
request.setContentHeaderJson();
|
||||||
|
request.setAuthHeader(generateAuthHeader());
|
||||||
|
request.get(url);
|
||||||
|
|
||||||
|
return cs::request::getResponse(url);
|
||||||
|
}
|
||||||
|
|
||||||
cs::request request;
|
std::string generateAuthHeader()
|
||||||
request.setAuthHeader(generateAuthHeader());
|
{
|
||||||
request.get(url);
|
return "MediaBrowser Client=Crowsite, Device=YourMom, Token=" + GLOBALS.token;
|
||||||
|
}
|
||||||
|
|
||||||
return cs::request::getResponse(url);
|
bool hasUser(std::string_view username)
|
||||||
}
|
{
|
||||||
|
return GLOBALS.user_ids.find(std::string(username)) != GLOBALS.user_ids.end();
|
||||||
std::string cs::jellyfin::generateAuthHeader()
|
}
|
||||||
{
|
|
||||||
return "MediaBrowser Client=Crowsite, Device=YourMom, Token=" + GLOBALS.token;
|
auth_response authenticateUser(std::string_view username, std::string_view password)
|
||||||
}
|
{
|
||||||
|
if (!hasUser(username))
|
||||||
bool cs::jellyfin::hasUser(std::string_view username)
|
processUserData();
|
||||||
{
|
if (!hasUser(username))
|
||||||
return GLOBALS.user_ids.find(std::string(username)) != GLOBALS.user_ids.end();
|
{
|
||||||
}
|
BLT_ERROR("User not found!");
|
||||||
|
return auth_response::USERNAME;
|
||||||
|
}
|
||||||
|
auto l_url = "https://media.tpgc.me/Users/AuthenticateByName";
|
||||||
|
|
||||||
|
cs::request post;
|
||||||
|
post.setContentHeaderJson();
|
||||||
|
post.setAuthHeader(generateAuthHeader());
|
||||||
|
crow::json::wvalue json;
|
||||||
|
json["Username"] = std::string(username);
|
||||||
|
json["Pw"] = std::string(password);
|
||||||
|
post.post(l_url, json.dump());
|
||||||
|
|
||||||
|
auto response = cs::request::getResponseAndClear(l_url);
|
||||||
|
|
||||||
|
if (post.status() == 200)
|
||||||
|
{
|
||||||
|
crow::json::rvalue read = crow::json::load(response);
|
||||||
|
|
||||||
|
const auto& users = read["User"];
|
||||||
|
|
||||||
|
client_data data;
|
||||||
|
data.accessToken = read["AccessToken"].s();
|
||||||
|
auto& user = data.user;
|
||||||
|
user.name = users["Name"].s();
|
||||||
|
user.serverId = users["ServerId"].s();
|
||||||
|
user.Id = users["Id"].s();
|
||||||
|
user.primaryImageTag = users["PrimaryImageTag"].s();
|
||||||
|
user.hasPassword = users["HasPassword"].b();
|
||||||
|
user.hasConfiguredPassword = users["HasConfiguredPassword"].b();
|
||||||
|
user.hasConfiguredEasyPassword = users["HasConfiguredEasyPassword"].b();
|
||||||
|
user.enableAutoLogin = users["EnableAutoLogin"].b();
|
||||||
|
user.lastLoginDate = users["LastLoginDate"].s();
|
||||||
|
user.lastActivityDate = users["LastActivityDate"].s();
|
||||||
|
|
||||||
|
GLOBALS.logged_in_users[std::string(username)] = data;
|
||||||
|
|
||||||
|
return auth_response::AUTHORIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return auth_response::ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -48,10 +48,14 @@ int main(int argc, const char** argv)
|
||||||
|
|
||||||
blt::arg_parse parser;
|
blt::arg_parse parser;
|
||||||
parser.addArgument(blt::arg_builder("token").build());
|
parser.addArgument(blt::arg_builder("token").build());
|
||||||
|
parser.addArgument(blt::arg_builder("user").build());
|
||||||
|
parser.addArgument(blt::arg_builder("pass").build());
|
||||||
auto args = parser.parse_args(argc, argv);
|
auto args = parser.parse_args(argc, argv);
|
||||||
cs::jellyfin::setToken(blt::arg_parse::get<std::string>(args["token"]));
|
cs::jellyfin::setToken(blt::arg_parse::get<std::string>(args["token"]));
|
||||||
cs::jellyfin::processUserData();
|
cs::jellyfin::processUserData();
|
||||||
|
|
||||||
|
cs::jellyfin::authenticateUser(blt::arg_parse::get<std::string>(args["user"]), blt::arg_parse::get<std::string>(args["pass"]));
|
||||||
|
|
||||||
// blt::string::StringBuffer buffer;
|
// blt::string::StringBuffer buffer;
|
||||||
// std::stringstream stream;
|
// std::stringstream stream;
|
||||||
// std::string normalString;
|
// std::string normalString;
|
||||||
|
|
Loading…
Reference in New Issue