Skip to content

Commit 9ef12e2

Browse files
committed
Add delete forwarder/file
1 parent 20215a5 commit 9ef12e2

File tree

4 files changed

+333
-0
lines changed

4 files changed

+333
-0
lines changed

include/ff.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,8 @@ namespace ff {
399399
limhamn::http::server::response handle_api_try_login_endpoint(const limhamn::http::server::request& request, database& db);
400400
limhamn::http::server::response handle_try_upload_forwarder_endpoint(const limhamn::http::server::request& request, database& db);
401401
limhamn::http::server::response handle_try_upload_file_endpoint(const limhamn::http::server::request& request, database& db);
402+
limhamn::http::server::response handle_api_delete_forwarder_endpoint(const limhamn::http::server::request& request, database& db);
403+
limhamn::http::server::response handle_api_delete_file_endpoint(const limhamn::http::server::request& request, database& db);
402404
limhamn::http::server::response handle_api_get_forwarders_endpoint(const limhamn::http::server::request& request, database& db);
403405
limhamn::http::server::response handle_api_get_files_endpoint(const limhamn::http::server::request& request, database& db);
404406
limhamn::http::server::response handle_api_set_approval_for_uploads_endpoint(const limhamn::http::server::request& request, database& db);

js/ff.js

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3200,6 +3200,50 @@ function update_stars_for_file(id, stars) {
32003200
});
32013201
}
32023202

3203+
function delete_forwarder(id) {
3204+
const json = {
3205+
forwarder_identifier: id
3206+
};
3207+
3208+
fetch('/api/delete_forwarder', {
3209+
method: 'POST',
3210+
headers: {
3211+
'Content-Type': 'application/json',
3212+
},
3213+
body: JSON.stringify(json),
3214+
})
3215+
.then(response => {
3216+
if (response.status === 204) {
3217+
show_browse();
3218+
}
3219+
})
3220+
.catch((error) => {
3221+
console.error('Error:', error);
3222+
});
3223+
}
3224+
3225+
function delete_file(id) {
3226+
const json = {
3227+
file_identifier: id
3228+
};
3229+
3230+
fetch('/api/delete_file', {
3231+
method: 'POST',
3232+
headers: {
3233+
'Content-Type': 'application/json',
3234+
},
3235+
body: JSON.stringify(json),
3236+
})
3237+
.then(response => {
3238+
if (response.status === 204) {
3239+
show_sandbox();
3240+
}
3241+
})
3242+
.catch((error) => {
3243+
console.error('Error:', error);
3244+
});
3245+
}
3246+
32033247
function update_stars_for_forwarder(id, stars) {
32043248
const json = {
32053249
forwarder_identifier: id,
@@ -3722,6 +3766,59 @@ async function draw_article(type, forwarder, id) {
37223766
view_window.appendChild(accept_button);
37233767
view_window.appendChild(reject_button);
37243768
}
3769+
if (get_cookie('username') === forwarder.uploader || get_cookie('user_type') === '1') {
3770+
const delete_button = document.createElement('button');
3771+
delete_button.innerHTML = 'Delete';
3772+
delete_button.className = 'view_floating_window_delete';
3773+
delete_button.onclick = () => {
3774+
play_click();
3775+
3776+
const confirmation = create_window('confirmation-window');
3777+
3778+
const confirmation_title = document.createElement('h1');
3779+
confirmation_title.innerHTML = 'Are you sure?';
3780+
confirmation_title.className = 'confirmation_window_title';
3781+
confirmation_title.id = 'confirmation-window-title';
3782+
3783+
const confirmation_text = document.createElement('p');
3784+
confirmation_text.innerHTML = 'Are you sure you want to delete this? This action cannot be undone.';
3785+
confirmation_text.className = 'confirmation_window_text';
3786+
confirmation_text.id = 'confirmation-window-text';
3787+
3788+
const yes_button = document.createElement('button');
3789+
yes_button.innerHTML = 'Yes';
3790+
yes_button.className = 'confirmation_window_yes';
3791+
yes_button.id = 'confirmation-window-yes';
3792+
yes_button.style.marginRight = '10px';
3793+
yes_button.onclick = () => {
3794+
play_click();
3795+
3796+
confirmation.remove();
3797+
3798+
if (type === Forwarder) {
3799+
delete_forwarder(id);
3800+
} else {
3801+
delete_file(id);
3802+
}
3803+
}
3804+
3805+
const no_button = document.createElement('button');
3806+
no_button.innerHTML = 'No';
3807+
no_button.className = 'confirmation_window_no';
3808+
no_button.id = 'confirmation-window-no';
3809+
no_button.onclick = () => {
3810+
play_click();
3811+
draw_article(type, forwarder, id);
3812+
}
3813+
3814+
confirmation.appendChild(confirmation_title);
3815+
confirmation.appendChild(confirmation_text);
3816+
confirmation.appendChild(yes_button);
3817+
confirmation.appendChild(no_button);
3818+
}
3819+
3820+
view_window.appendChild(delete_button);
3821+
}
37253822

37263823
const post_comment = document.createElement('div');
37273824
post_comment.className = 'view_floating_window_post_comment';

src/ff.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,8 @@ void ff::start_server() {
288288
{"/api/edit_announcement", ff::handle_api_edit_announcement},
289289
{"/api/stay_logged_in", ff::handle_api_stay_logged_in},
290290
{"/api/try_logout", ff::handle_api_try_logout_endpoint},
291+
{"/api/delete_forwarder", ff::handle_api_delete_forwarder_endpoint},
292+
{"/api/delete_file", ff::handle_api_delete_file_endpoint},
291293
};
292294
const std::unordered_map<std::string, std::function<limhamn::http::server::response(const limhamn::http::server::request&, ff::database&)>> setup_handlers{
293295
{virtual_favicon_path, ff::handle_virtual_favicon_endpoint},

src/path_handlers.cpp

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3083,6 +3083,238 @@ limhamn::http::server::response ff::handle_api_delete_comment_file_endpoint(cons
30833083
return response;
30843084
}
30853085

3086+
limhamn::http::server::response ff::handle_api_delete_file_endpoint(const limhamn::http::server::request& request, database& db) {
3087+
limhamn::http::server::response response{};
3088+
response.content_type = "application/json";
3089+
3090+
const auto get_username = [&request]() -> std::string {
3091+
if (request.session.find("username") != request.session.end()) {
3092+
return request.session.at("username");
3093+
}
3094+
3095+
try {
3096+
const auto json = nlohmann::json::parse(request.body);
3097+
if (json.find("username") != json.end() && json.at("username").is_string()) {
3098+
return json.at("username").get<std::string>();
3099+
}
3100+
} catch (const std::exception&) {
3101+
// ignore
3102+
}
3103+
3104+
return "";
3105+
};
3106+
3107+
const auto get_key = [&request]() -> std::string {
3108+
if (request.session.find("key") != request.session.end()) {
3109+
return request.session.at("key");
3110+
}
3111+
3112+
try {
3113+
const auto json = nlohmann::json::parse(request.body);
3114+
if (json.find("key") != json.end() && json.at("key").is_string()) {
3115+
return json.at("key").get<std::string>();
3116+
}
3117+
} catch (const std::exception&) {
3118+
// ignore
3119+
}
3120+
3121+
return "";
3122+
};
3123+
3124+
const std::string username{get_username()};
3125+
const std::string key{get_key()};
3126+
3127+
if (username.empty() || key.empty()) {
3128+
#ifdef FF_DEBUG
3129+
logger.write_to_log(limhamn::logger::type::notice, "Username or key is empty.\n");
3130+
#endif
3131+
nlohmann::json json;
3132+
json["error_str"] = "Username or key is empty.";
3133+
json["error"] = "FF_INVALID_CREDENTIALS";
3134+
response.http_status = 400;
3135+
response.body = json.dump();
3136+
return response;
3137+
}
3138+
3139+
if (!ff::verify_key(db, username, key)) {
3140+
#ifdef FF_DEBUG
3141+
logger.write_to_log(limhamn::logger::type::notice, "Invalid credentials.\n");
3142+
#endif
3143+
nlohmann::json json;
3144+
json["error_str"] = "Invalid credentials.";
3145+
json["error"] = "FF_INVALID_CREDENTIALS";
3146+
response.http_status = 400;
3147+
response.body = json.dump();
3148+
return response;
3149+
}
3150+
3151+
nlohmann::json json;
3152+
try {
3153+
json = nlohmann::json::parse(request.body);
3154+
} catch (const std::exception&) {
3155+
nlohmann::json ret;
3156+
ret["error_str"] = "Invalid JSON";
3157+
ret["error"] = "FF_INVALID_JSON";
3158+
response.http_status = 400;
3159+
response.body = ret.dump();
3160+
return response;
3161+
}
3162+
3163+
if (!json.contains("file_identifier") || !json.at("file_identifier").is_string()) {
3164+
nlohmann::json ret;
3165+
ret["error_str"] = "file_identifier is required";
3166+
ret["error"] = "FF_INVALID_JSON";
3167+
response.http_status = 400;
3168+
response.body = ret.dump();
3169+
return response;
3170+
}
3171+
3172+
const std::string& file_identifier = json.at("file_identifier").get<std::string>();
3173+
3174+
nlohmann::json db_json;
3175+
try {
3176+
db_json = nlohmann::json::parse(ff::get_json_from_table(db, "sandbox", "identifier", file_identifier));
3177+
const auto& uploader = db_json.at("uploader").get<std::string>();
3178+
if (username != uploader && get_user_type(db, username) != ff::UserType::Administrator) {
3179+
nlohmann::json ret;
3180+
ret["error_str"] = "You can only delete your own files";
3181+
ret["error"] = "FF_NOT_AUTHORIZED";
3182+
response.http_status = 403;
3183+
response.body = ret.dump();
3184+
return response;
3185+
}
3186+
3187+
db.exec("DELETE FROM sandbox WHERE identifier = ?", file_identifier);
3188+
} catch (const std::exception&) {
3189+
nlohmann::json ret;
3190+
ret["error_str"] = "File not found";
3191+
ret["error"] = "FF_FILE_NOT_FOUND";
3192+
response.http_status = 404;
3193+
response.body = ret.dump();
3194+
return response;
3195+
}
3196+
3197+
response.http_status = 204;
3198+
response.body = "";
3199+
return response;
3200+
}
3201+
3202+
limhamn::http::server::response ff::handle_api_delete_forwarder_endpoint(const limhamn::http::server::request& request, database& db) {
3203+
limhamn::http::server::response response{};
3204+
response.content_type = "application/json";
3205+
3206+
const auto get_username = [&request]() -> std::string {
3207+
if (request.session.find("username") != request.session.end()) {
3208+
return request.session.at("username");
3209+
}
3210+
3211+
try {
3212+
const auto json = nlohmann::json::parse(request.body);
3213+
if (json.find("username") != json.end() && json.at("username").is_string()) {
3214+
return json.at("username").get<std::string>();
3215+
}
3216+
} catch (const std::exception&) {
3217+
// ignore
3218+
}
3219+
3220+
return "";
3221+
};
3222+
3223+
const auto get_key = [&request]() -> std::string {
3224+
if (request.session.find("key") != request.session.end()) {
3225+
return request.session.at("key");
3226+
}
3227+
3228+
try {
3229+
const auto json = nlohmann::json::parse(request.body);
3230+
if (json.find("key") != json.end() && json.at("key").is_string()) {
3231+
return json.at("key").get<std::string>();
3232+
}
3233+
} catch (const std::exception&) {
3234+
// ignore
3235+
}
3236+
3237+
return "";
3238+
};
3239+
3240+
const std::string username{get_username()};
3241+
const std::string key{get_key()};
3242+
3243+
if (username.empty() || key.empty()) {
3244+
#ifdef FF_DEBUG
3245+
logger.write_to_log(limhamn::logger::type::notice, "Username or key is empty.\n");
3246+
#endif
3247+
nlohmann::json json;
3248+
json["error_str"] = "Username or key is empty.";
3249+
json["error"] = "FF_INVALID_CREDENTIALS";
3250+
response.http_status = 400;
3251+
response.body = json.dump();
3252+
return response;
3253+
}
3254+
3255+
if (!ff::verify_key(db, username, key)) {
3256+
#ifdef FF_DEBUG
3257+
logger.write_to_log(limhamn::logger::type::notice, "Invalid credentials.\n");
3258+
#endif
3259+
nlohmann::json json;
3260+
json["error_str"] = "Invalid credentials.";
3261+
json["error"] = "FF_INVALID_CREDENTIALS";
3262+
response.http_status = 400;
3263+
response.body = json.dump();
3264+
return response;
3265+
}
3266+
3267+
nlohmann::json json;
3268+
try {
3269+
json = nlohmann::json::parse(request.body);
3270+
} catch (const std::exception&) {
3271+
nlohmann::json ret;
3272+
ret["error_str"] = "Invalid JSON";
3273+
ret["error"] = "FF_INVALID_JSON";
3274+
response.http_status = 400;
3275+
response.body = ret.dump();
3276+
return response;
3277+
}
3278+
3279+
if (!json.contains("forwarder_identifier") || !json.at("forwarder_identifier").is_string()) {
3280+
nlohmann::json ret;
3281+
ret["error_str"] = "forwarder_identifier is required";
3282+
ret["error"] = "FF_INVALID_JSON";
3283+
response.http_status = 400;
3284+
response.body = ret.dump();
3285+
return response;
3286+
}
3287+
3288+
const std::string& forwarder_identifier = json.at("forwarder_identifier").get<std::string>();
3289+
3290+
nlohmann::json db_json;
3291+
try {
3292+
db_json = nlohmann::json::parse(ff::get_json_from_table(db, "forwarders", "identifier", forwarder_identifier));
3293+
const auto& uploader = db_json.at("uploader").get<std::string>();
3294+
if (username != uploader && get_user_type(db, username) != ff::UserType::Administrator) {
3295+
nlohmann::json ret;
3296+
ret["error_str"] = "You can only delete your own files";
3297+
ret["error"] = "FF_NOT_AUTHORIZED";
3298+
response.http_status = 403;
3299+
response.body = ret.dump();
3300+
return response;
3301+
}
3302+
3303+
db.exec("DELETE FROM forwarders WHERE identifier = ?", forwarder_identifier);
3304+
} catch (const std::exception&) {
3305+
nlohmann::json ret;
3306+
ret["error_str"] = "File not found";
3307+
ret["error"] = "FF_FILE_NOT_FOUND";
3308+
response.http_status = 404;
3309+
response.body = ret.dump();
3310+
return response;
3311+
}
3312+
3313+
response.http_status = 204;
3314+
response.body = "";
3315+
return response;
3316+
}
3317+
30863318
limhamn::http::server::response ff::handle_api_stay_logged_in(const limhamn::http::server::request& request, database& db) {
30873319
limhamn::http::server::response response{};
30883320

0 commit comments

Comments
 (0)