Skip to content

Commit cf35a77

Browse files
committed
Add option to delete announcement
1 parent 27ecde2 commit cf35a77

File tree

3 files changed

+230
-7
lines changed

3 files changed

+230
-7
lines changed

js/ff.js

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,8 @@ function get_announcements() {
10671067

10681068
w.appendChild(title);
10691069

1070+
const is_admin = get_cookie('user_type') === '1';
1071+
10701072
get_json().then(data => {
10711073
if (!data || !data.announcements || data.announcements.length === 0) {
10721074
const description = document.createElement('description');
@@ -1082,15 +1084,17 @@ function get_announcements() {
10821084
throw new Error('Invalid response from server: ' + JSON.stringify(data));
10831085
}
10841086

1085-
const announcements = data.announcements;
1086-
1087-
// sort by publish_timestamp
1088-
announcements.sort((a, b) => b.publish_timestamp - a.publish_timestamp);
1087+
let announcements = data.announcements;
1088+
announcements = announcements.map((announcement, index) => ({
1089+
...announcement,
1090+
index,
1091+
}));
10891092

1090-
announcements.forEach(announcement => {
1093+
announcements.sort((a, b) => b.publish_timestamp - a.publish_timestamp);
1094+
announcements.forEach(announcement => {
10911095
const div = document.createElement('div');
10921096
div.className = 'announcement_div';
1093-
div.id = "announcement-" + announcement.id;
1097+
div.id = "announcement-" + announcement.index;
10941098
div.style.marginBottom = '10px';
10951099
div.style.padding = '10px';
10961100
div.style.borderRadius = '10px';
@@ -1108,6 +1112,34 @@ function get_announcements() {
11081112
return;
11091113
}
11101114

1115+
if (is_admin) {
1116+
const delete_button = document.createElement('button');
1117+
delete_button.innerHTML = 'Delete';
1118+
delete_button.className = 'delete-announcement-button';
1119+
delete_button.onclick = (event) => {
1120+
play_click();
1121+
event.stopPropagation(); // prevent the announcement from being clicked
1122+
fetch('/api/delete_announcement', {
1123+
method: 'POST',
1124+
headers: {
1125+
'Content-Type': 'application/json',
1126+
},
1127+
body: JSON.stringify({ announcement_id: announcement.index }),
1128+
})
1129+
.then(() => {
1130+
const announcement_div = document.getElementById('announcement-' + announcement.index);
1131+
if (announcement_div) {
1132+
announcement_div.remove();
1133+
}
1134+
})
1135+
.catch((error) => {
1136+
console.error('Error:', error);
1137+
});
1138+
}
1139+
1140+
div.appendChild(delete_button);
1141+
}
1142+
11111143
if (announcement.title) {
11121144
const title = document.createElement('h1');
11131145
title.innerHTML = announcement.title;
@@ -1122,6 +1154,21 @@ function get_announcements() {
11221154
div.appendChild(title);
11231155

11241156
let shortened_text = announcement.text_html;
1157+
1158+
// remove any non p tags
1159+
const parser = new DOMParser();
1160+
const doc = parser.parseFromString(shortened_text, 'text/html');
1161+
const paragraphs = doc.querySelectorAll('p');
1162+
1163+
if (paragraphs.length > 0) {
1164+
shortened_text = '';
1165+
paragraphs.forEach((p, index) => {
1166+
if (index > 0) {
1167+
shortened_text += '<br/>';
1168+
}
1169+
shortened_text += p.innerHTML;
1170+
});
1171+
}
11251172
if (shortened_text.length > 100) {
11261173
shortened_text = shortened_text.substring(0, 100) + '...';
11271174
}

src/ff.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ void ff::start_server() {
282282
{"/api/get_profile", ff::handle_api_get_profile},
283283
{"/api/create_announcement", ff::handle_api_create_announcement},
284284
{"/api/get_announcements", ff::handle_api_get_announcements},
285-
//{"/api/delete_announcements", ff::handle_api_delete_announcements},
285+
{"/api/delete_announcement", ff::handle_api_delete_announcements},
286286
{"/api/stay_logged_in", ff::handle_api_stay_logged_in},
287287
{"/api/try_logout", ff::handle_api_try_logout_endpoint},
288288
};

src/path_handlers.cpp

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1801,6 +1801,182 @@ limhamn::http::server::response ff::handle_api_get_announcements(const limhamn::
18011801
return response;
18021802
}
18031803

1804+
limhamn::http::server::response ff::handle_api_delete_announcements(const limhamn::http::server::request& request, database& db) {
1805+
limhamn::http::server::response response{};
1806+
response.content_type = "application/json";
1807+
1808+
const auto get_username = [&request]() -> std::string {
1809+
if (request.session.find("username") != request.session.end()) {
1810+
return request.session.at("username");
1811+
}
1812+
1813+
try {
1814+
const auto json = nlohmann::json::parse(request.body);
1815+
if (json.find("username") != json.end() && json.at("username").is_string()) {
1816+
return json.at("username").get<std::string>();
1817+
}
1818+
} catch (const std::exception&) {
1819+
// ignore
1820+
}
1821+
1822+
return "";
1823+
};
1824+
1825+
const auto get_key = [&request]() -> std::string {
1826+
if (request.session.find("key") != request.session.end()) {
1827+
return request.session.at("key");
1828+
}
1829+
1830+
try {
1831+
const auto json = nlohmann::json::parse(request.body);
1832+
if (json.find("key") != json.end() && json.at("key").is_string()) {
1833+
return json.at("key").get<std::string>();
1834+
}
1835+
} catch (const std::exception&) {
1836+
// ignore
1837+
}
1838+
1839+
return "";
1840+
};
1841+
1842+
const std::string username{get_username()};
1843+
const std::string key{get_key()};
1844+
1845+
if (username.empty() || key.empty()) {
1846+
#ifdef FF_DEBUG
1847+
logger.write_to_log(limhamn::logger::type::notice, "Username or key is empty.\n");
1848+
#endif
1849+
nlohmann::json json;
1850+
json["error_str"] = "Username or key is empty.";
1851+
json["error"] = "FF_INVALID_CREDENTIALS";
1852+
response.http_status = 400;
1853+
response.body = json.dump();
1854+
return response;
1855+
}
1856+
1857+
if (!ff::verify_key(db, username, key)) {
1858+
#ifdef FF_DEBUG
1859+
logger.write_to_log(limhamn::logger::type::notice, "Invalid credentials.\n");
1860+
#endif
1861+
nlohmann::json json;
1862+
json["error_str"] = "Invalid credentials.";
1863+
json["error"] = "FF_INVALID_CREDENTIALS";
1864+
response.http_status = 400;
1865+
response.body = json.dump();
1866+
return response;
1867+
}
1868+
1869+
if (ff::get_user_type(db, username) != ff::UserType::Administrator) {
1870+
nlohmann::json json;
1871+
json["error"] = "FF_NOT_AUTHORIZED";
1872+
json["error_str"] = "You are not authorized to access this endpoint.";
1873+
response.http_status = 403;
1874+
response.body = json.dump();
1875+
return response;
1876+
}
1877+
1878+
if (request.body.empty()) {
1879+
#ifdef FF_DEBUG
1880+
logger.write_to_log(limhamn::logger::type::notice, "No body.\n");
1881+
#endif
1882+
nlohmann::json json;
1883+
json["error_str"] = "No body.";
1884+
json["error"] = "FF_NO_BODY";
1885+
response.http_status = 400;
1886+
response.body = json.dump();
1887+
return response;
1888+
}
1889+
if (request.method != "POST") {
1890+
#ifdef FF_DEBUG
1891+
logger.write_to_log(limhamn::logger::type::notice, "Not a POST request.\n");
1892+
#endif
1893+
nlohmann::json json;
1894+
json["error_str"] = "Not a POST request.";
1895+
json["error"] = "FF_INVALID_METHOD";
1896+
response.http_status = 400;
1897+
response.body = json.dump();
1898+
return response;
1899+
}
1900+
1901+
nlohmann::json input;
1902+
try {
1903+
input = nlohmann::json::parse(request.body);
1904+
} catch (const std::exception&) {
1905+
#ifdef FF_DEBUG
1906+
logger.write_to_log(limhamn::logger::type::notice, "Failed to parse JSON.\n");
1907+
#endif
1908+
nlohmann::json json;
1909+
json["error_str"] = "Invalid JSON received";
1910+
json["error"] = "FF_INVALID_JSON";
1911+
response.http_status = 400;
1912+
response.body = json.dump();
1913+
return response;
1914+
}
1915+
1916+
if (input.find("announcement_id") == input.end() || !input.at("announcement_id").is_number_integer()) {
1917+
nlohmann::json json;
1918+
json["error"] = "FF_INVALID_JSON";
1919+
json["error_str"] = "Invalid JSON received";
1920+
response.http_status = 400;
1921+
response.body = json.dump();
1922+
return response;
1923+
}
1924+
1925+
const auto query = db.query("SELECT * FROM general WHERE id=1;");
1926+
if (query.empty()) {
1927+
nlohmann::json ret;
1928+
ret["error"] = "FF_SERVER_ERROR";
1929+
ret["error_str"] = "Server failed, no idea why. general is empty";
1930+
1931+
response.content_type = "application/json";
1932+
response.http_status = 400;
1933+
response.body = ret.dump();
1934+
return response;
1935+
}
1936+
1937+
if (query.at(0).find("json") == query.at(0).end()) {
1938+
nlohmann::json ret;
1939+
ret["error"] = "FF_SERVER_ERROR";
1940+
ret["error_str"] = "Server failed, no idea why.";
1941+
1942+
response.content_type = "application/json";
1943+
response.http_status = 400;
1944+
response.body = ret.dump();
1945+
return response;
1946+
}
1947+
1948+
try {
1949+
auto json = nlohmann::json::parse(query.at(0).at("json"));
1950+
if (json.contains("announcements") && json.at("announcements").is_array()) {
1951+
auto& announcements = json["announcements"];
1952+
const int announcement_id = input.at("announcement_id").get<int>();
1953+
if (announcement_id < 0 || announcement_id >= static_cast<int>(announcements.size())) {
1954+
nlohmann::json ret;
1955+
ret["error"] = "FF_INVALID_JSON";
1956+
ret["error_str"] = "Invalid announcement_id.";
1957+
response.http_status = 400;
1958+
response.body = ret.dump();
1959+
return response;
1960+
}
1961+
announcements.erase(announcements.begin() + announcement_id);
1962+
}
1963+
db.exec("UPDATE general SET json = ? WHERE id = 1", json.dump());
1964+
response.http_status = 204;
1965+
return response;
1966+
} catch (const std::exception&) {
1967+
nlohmann::json ret;
1968+
ret["error"] = "FF_SERVER_ERROR";
1969+
ret["error_str"] = "Server failed, no idea why.";
1970+
1971+
response.content_type = "application/json";
1972+
response.http_status = 400;
1973+
response.body = ret.dump();
1974+
1975+
return response;
1976+
}
1977+
}
1978+
1979+
18041980
limhamn::http::server::response ff::handle_api_rate_file_endpoint(const limhamn::http::server::request& request, database& db) {
18051981
limhamn::http::server::response response{};
18061982
response.content_type = "application/json";

0 commit comments

Comments
 (0)