diff --git a/libdc/CMakeLists.txt b/libdc/CMakeLists.txt index 0cfae74..5f29e65 100644 --- a/libdc/CMakeLists.txt +++ b/libdc/CMakeLists.txt @@ -18,6 +18,7 @@ SET(SOURCES "include/dc/util.h" "src/account.c" "src/api.c" + "src/api-auth.c" "src/api-channel.c" "src/api-friends.c" "src/apisync.c" diff --git a/libdc/include/dc/api.h b/libdc/include/dc/api.h index cbb6665..3beb91b 100644 --- a/libdc/include/dc/api.h +++ b/libdc/include/dc/api.h @@ -27,6 +27,7 @@ void dc_api_signal(dc_api_t api, CURL *easy, int code); /* internal curl stuff */ +bool dc_api_error(json_t *j, int *code, char const **message); dc_api_sync_t dc_api_call(dc_api_t api, char const *token, char const *verb, char const *method, json_t *j); @@ -43,6 +44,12 @@ json_t *dc_api_call_sync(dc_api_t api, char const *token, */ bool dc_api_authenticate(dc_api_t api, dc_account_t account); +/** + * Inverse of dc_api_authenticate(). Logs the given user out, destroying the + * login token in the process. + */ +bool dc_api_logout(dc_api_t api, dc_account_t account); + /** * Retrieve basic user information for the given account. The first * parameter is the user account holding login info, while the second diff --git a/libdc/src/api-auth.c b/libdc/src/api-auth.c new file mode 100644 index 0000000..084d63a --- /dev/null +++ b/libdc/src/api-auth.c @@ -0,0 +1,71 @@ +#include +#include "internal.h" + +bool dc_api_logout(dc_api_t api, dc_account_t account) +{ + json_t *reply = NULL; + json_t *data = NULL; + + data = json_object(); + return_if_true(data == NULL, false); + + json_object_set_new(data, "provider", json_null()); + json_object_set_new(data, "voip_provider", json_null()); + + reply = dc_api_call_sync(api, "POST", dc_account_token(account), + "auth/logout", data + ); + json_decref(data); + + if (reply != NULL) { + /* TODO: parse error + */ + json_decref(reply); + return false; + } + + dc_account_set_token(account, NULL); + return true; +} + +bool dc_api_authenticate(dc_api_t api, dc_account_t account) +{ + json_t *j = json_object(), *reply = NULL, *token = NULL; + bool ret = false; + + json_object_set_new(j, "email", + json_string(dc_account_email(account)) + ); + json_object_set_new(j, "password", + json_string(dc_account_password(account)) + ); + + reply = dc_api_call_sync(api, "POST", NULL, "auth/login", j); + goto_if_true(reply == NULL, cleanup); + + if (dc_api_error(j, NULL, NULL)) { + return false; + } + + token = json_object_get(reply, "token"); + if (token == NULL || !json_is_string(token)) { + goto cleanup; + } + + dc_account_set_token(account, json_string_value(token)); + ret = true; + +cleanup: + + if (j != NULL) { + json_decref(j); + j = NULL; + } + + if (reply != NULL) { + json_decref(reply); + reply = NULL; + } + + return ret; +} diff --git a/libdc/src/api.c b/libdc/src/api.c index c7e6e1e..f5b4756 100644 --- a/libdc/src/api.c +++ b/libdc/src/api.c @@ -253,7 +253,7 @@ cleanup: return reply; } -static bool dc_api_error(json_t *j, int *code, char const **message) +bool dc_api_error(json_t *j, int *code, char const **message) { return_if_true(j == NULL, false); @@ -279,48 +279,6 @@ static bool dc_api_error(json_t *j, int *code, char const **message) return error; } -bool dc_api_authenticate(dc_api_t api, dc_account_t account) -{ - json_t *j = json_object(), *reply = NULL, *token = NULL; - bool ret = false; - - json_object_set_new(j, "email", - json_string(dc_account_email(account)) - ); - json_object_set_new(j, "password", - json_string(dc_account_password(account)) - ); - - reply = dc_api_call_sync(api, "POST", NULL, "auth/login", j); - goto_if_true(reply == NULL, cleanup); - - if (dc_api_error(j, NULL, NULL)) { - return false; - } - - token = json_object_get(reply, "token"); - if (token == NULL || !json_is_string(token)) { - goto cleanup; - } - - dc_account_set_token(account, json_string_value(token)); - ret = true; - -cleanup: - - if (j != NULL) { - json_decref(j); - j = NULL; - } - - if (reply != NULL) { - json_decref(reply); - reply = NULL; - } - - return ret; -} - bool dc_api_get_userinfo(dc_api_t api, dc_account_t login, dc_account_t user) { diff --git a/ncdc/CMakeLists.txt b/ncdc/CMakeLists.txt index d8b26ab..bc88a68 100644 --- a/ncdc/CMakeLists.txt +++ b/ncdc/CMakeLists.txt @@ -19,6 +19,7 @@ SET(SOURCES "src/input.c" "src/keycodes.c" "src/login.c" + "src/logout.c" "src/mainwindow.c" "src/msg.c" "src/ncdc.c" diff --git a/ncdc/include/ncdc/cmds.h b/ncdc/include/ncdc/cmds.h index 1b9967c..e8bec5f 100644 --- a/ncdc/include/ncdc/cmds.h +++ b/ncdc/include/ncdc/cmds.h @@ -26,7 +26,8 @@ ncdc_commands_t *ncdc_find_cmd(ncdc_commands_t *cmds, wchar_t const *name); bool ncdc_cmd_friends(ncdc_mainwindow_t n, size_t ac, wchar_t **av); bool ncdc_cmd_login(ncdc_mainwindow_t n, size_t ac, wchar_t **av); -bool ncdc_cmd_quit(ncdc_mainwindow_t n, size_t ac, wchar_t **av); +bool ncdc_cmd_logout(ncdc_mainwindow_t n, size_t ac, wchar_t **av); bool ncdc_cmd_msg(ncdc_mainwindow_t n, size_t ac, wchar_t **av); +bool ncdc_cmd_quit(ncdc_mainwindow_t n, size_t ac, wchar_t **av); #endif diff --git a/ncdc/src/cmds.c b/ncdc/src/cmds.c index 0ab83d3..46b803f 100644 --- a/ncdc/src/cmds.c +++ b/ncdc/src/cmds.c @@ -4,6 +4,7 @@ ncdc_commands_t cmds[] = { { L"/friend", ncdc_cmd_friends }, { L"/friends", ncdc_cmd_friends }, { L"/login", ncdc_cmd_login }, + { L"/logout", ncdc_cmd_logout }, { L"/msg", ncdc_cmd_msg }, { L"/quit", ncdc_cmd_quit }, { NULL, NULL } diff --git a/ncdc/src/login.c b/ncdc/src/login.c index debcdc4..37bc79d 100644 --- a/ncdc/src/login.c +++ b/ncdc/src/login.c @@ -39,7 +39,7 @@ bool ncdc_cmd_login(ncdc_mainwindow_t n, size_t ac, wchar_t **av) goto cleanup; } - current_account = acc; + current_account = dc_ref(acc); LOG(n, L"login: %ls: authentication successful", av[1]); ret = true; diff --git a/ncdc/src/logout.c b/ncdc/src/logout.c new file mode 100644 index 0000000..74e3c0d --- /dev/null +++ b/ncdc/src/logout.c @@ -0,0 +1,28 @@ +#include +#include +#include + +bool ncdc_cmd_logout(ncdc_mainwindow_t n, size_t ac, wchar_t **av) +{ + bool ret = false; + + goto_if_true(current_account == NULL || + !dc_account_has_token(current_account), error); + + ret = dc_api_logout(api, current_account); + if (!ret) { + LOG(n, L"logout: failed to log out the current account"); + goto error; + } + + g_hash_table_remove(accounts, dc_account_fullname(current_account)); + + dc_unref(current_account); + current_account = NULL; + + LOG(n, L"logout: successfully logged out"); + +error: + + return ret; +}