Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
varqox committed Sep 27, 2024
2 parents a752014 + 7c6c573 commit 889bcee
Show file tree
Hide file tree
Showing 14 changed files with 141 additions and 126 deletions.
8 changes: 4 additions & 4 deletions subprojects/sim/include/sim/sql/fields/datetime.hh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include "varbinary.hh"
#include "binary.hh"

#include <simlib/concat_tostr.hh>
#include <simlib/throw_assert.hh>
Expand All @@ -11,7 +11,7 @@
namespace sim::sql::fields {

// Format: YYYY-mm-dd HH:MM:SS
class Datetime : public Varbinary<std::char_traits<char>::length("YYYY-mm-dd HH:MM:SS")> {
class Datetime : public Binary<std::char_traits<char>::length("YYYY-mm-dd HH:MM:SS")> {
public:
Datetime() noexcept = default;
Datetime(const Datetime&) = default;
Expand All @@ -21,14 +21,14 @@ public:
~Datetime() = default;

explicit Datetime(std::string str)
: Varbinary{[&]() -> decltype(auto) {
: Binary{[&]() -> decltype(auto) {
throw_assert(is_datetime(str.c_str()));
return std::move(str);
}()} {}

Datetime& operator=(std::string str) {
throw_assert(is_datetime(str.c_str()));
Varbinary::operator=(std::move(str));
Binary::operator=(std::move(str));
return *this;
}

Expand Down
20 changes: 14 additions & 6 deletions subprojects/sim/include/sim/sql/fields/inf_datetime.hh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include "varbinary.hh"
#include "binary.hh"

#include <simlib/concat_tostr.hh>
#include <simlib/throw_assert.hh>
Expand All @@ -11,7 +11,7 @@
namespace sim::sql::fields {

// Format: YYYY-mm-dd HH:MM:SS | # | @
class InfDatetime : public Varbinary<std::char_traits<char>::length("YYYY-mm-dd HH:MM:SS")> {
class InfDatetime : public Binary<std::char_traits<char>::length("YYYY-mm-dd HH:MM:SS")> {
static constexpr const auto NEG_INF_STR = std::string_view{"#"};
static constexpr const auto INF_STR = std::string_view{"@"};

Expand All @@ -24,14 +24,22 @@ public:
~InfDatetime() = default;

explicit InfDatetime(std::string str)
: Varbinary{[&]() -> decltype(auto) {
throw_assert(is_datetime(str.c_str()));
: Binary{[&]() -> decltype(auto) {
// Database stores binary as bytes padded with '\0' at the end
while (!str.empty() && str.back() == '\0') {
str.pop_back();
}
throw_assert(str == NEG_INF_STR || str == INF_STR || is_datetime(str.c_str()));
return std::move(str);
}()} {}

InfDatetime& operator=(std::string str) {
throw_assert(is_datetime(str.c_str()));
Varbinary::operator=(std::move(str));
// Database stores binary as bytes padded with '\0' at the end
while (!str.empty() && str.back() == '\0') {
str.pop_back();
}
throw_assert(str == NEG_INF_STR || str == INF_STR || is_datetime(str.c_str()));
Binary::operator=(std::move(str));
return *this;
}

Expand Down
8 changes: 4 additions & 4 deletions subprojects/sim/src/sim/db/schema.cc
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,10 @@ const DbSchema& get_schema() {
" `contest_id` bigint(20) unsigned NOT NULL,"
" `name` varbinary(", decltype(ContestRound::name)::max_len, ") NOT NULL,"
" `item` bigint(20) unsigned NOT NULL,"
" `begins` binary(", decltype(ContestRound::begins)::max_len, ") NOT NULL,"
" `ends` binary(", decltype(ContestRound::ends)::max_len, ") NOT NULL,"
" `full_results` binary(", decltype(ContestRound::full_results)::max_len, ") NOT NULL,"
" `ranking_exposure` binary(", decltype(ContestRound::ranking_exposure)::max_len, ") NOT NULL,"
" `begins` binary(", decltype(ContestRound::begins)::len, ") NOT NULL,"
" `ends` binary(", decltype(ContestRound::ends)::len, ") NOT NULL,"
" `full_results` binary(", decltype(ContestRound::full_results)::len, ") NOT NULL,"
" `ranking_exposure` binary(", decltype(ContestRound::ranking_exposure)::len, ") NOT NULL,"
" PRIMARY KEY (`id`),"
" UNIQUE KEY `contest_id_3` (`contest_id`,`item`),"
" KEY `contest_id_2` (`contest_id`,`begins`),"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ ContestEntryToken contest_entry_token_for(
const Contest& caps_contest,
std::optional<decltype(sim::contest_users::ContestUser::mode)> contest_user_mode
) noexcept {
bool is_contest_moderator = caps_contest.node.view and
(is_admin(session) or
bool is_contest_moderator = caps_contest.node.view &&
(is_admin(session) ||
is_one_of(contest_user_mode, ContestUser::Mode::OWNER, ContestUser::Mode::MODERATOR));
switch (token_kind) {
case ContestEntryTokenKind::NORMAL:
Expand Down
2 changes: 1 addition & 1 deletion subprojects/sim/src/web_server/capabilities/contests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Contests contests_for(const decltype(web_worker::Context::session)& session) noe
.web_ui_view = true,
.view_all = is_admin(session),
.view_public = true,
.add_private = is_admin(session) or is_teacher(session),
.add_private = is_admin(session) || is_teacher(session),
.add_public = is_admin(session),
};
}
Expand Down
83 changes: 42 additions & 41 deletions subprojects/sim/src/web_server/capabilities/problems.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,38 +14,39 @@ namespace web_server::capabilities {
ProblemsCapabilities problems(const decltype(Context::session)& session) noexcept {
return {
.web_ui_view = true,
.add_problem = is_admin(session) or is_teacher(session),
.add_problem_with_type_private = is_admin(session) or is_teacher(session),
.add_problem_with_type_contest_only = is_admin(session) or is_teacher(session),
.add_problem_with_type_public = is_admin(session),
.add_problem = is_admin(session) || is_teacher(session),
.add_problem_with_visibility_private = is_admin(session) || is_teacher(session),
.add_problem_with_visibility_contest_only = is_admin(session) || is_teacher(session),
.add_problem_with_visibility_public = is_admin(session),
};
}

ProblemsListCapabilities list_problems(const decltype(Context::session)& session) noexcept {
return {
.query_all = true,
.query_with_type_public = true,
.query_with_type_contest_only = is_admin(session) or is_teacher(session) or
(session and list_user_problems(session, session->user_id).query_with_type_contest_only
.query_with_visibility_public = true,
.query_with_visibility_contest_only = is_admin(session) || is_teacher(session) ||
(session &&
list_user_problems(session, session->user_id).query_with_visibility_contest_only),
.query_with_visibility_private = is_admin(session) || is_teacher(session) ||
(session && list_user_problems(session, session->user_id).query_with_visibility_private
),
.query_with_type_private = is_admin(session) or is_teacher(session) or
(session and list_user_problems(session, session->user_id).query_with_type_private),
.view_all_with_type_public = true,
.view_all_with_type_contest_only = is_admin(session) or is_teacher(session),
.view_all_with_type_private = is_admin(session),
.view_all_with_visibility_public = true,
.view_all_with_visibility_contest_only = is_admin(session) || is_teacher(session),
.view_all_with_visibility_private = is_admin(session),
};
}

ProblemsListCapabilities
list_user_problems(const decltype(Context::session)& session, decltype(User::id) user_id) noexcept {
return {
.query_all = is_self(session, user_id) or is_admin(session),
.query_with_type_public = is_self(session, user_id) or is_admin(session),
.query_with_type_contest_only = is_self(session, user_id) or is_admin(session),
.query_with_type_private = is_self(session, user_id) or is_admin(session),
.view_all_with_type_public = is_self(session, user_id) or is_admin(session),
.view_all_with_type_contest_only = is_self(session, user_id) or is_admin(session),
.view_all_with_type_private = is_self(session, user_id) or is_admin(session),
.query_all = is_self(session, user_id) || is_admin(session),
.query_with_visibility_public = is_self(session, user_id) || is_admin(session),
.query_with_visibility_contest_only = is_self(session, user_id) || is_admin(session),
.query_with_visibility_private = is_self(session, user_id) || is_admin(session),
.view_all_with_visibility_public = is_self(session, user_id) || is_admin(session),
.view_all_with_visibility_contest_only = is_self(session, user_id) || is_admin(session),
.view_all_with_visibility_private = is_self(session, user_id) || is_admin(session),
};
}

Expand All @@ -54,35 +55,35 @@ ProblemCapabilities problem(
decltype(Problem::visibility) problem_visibility,
decltype(Problem::owner_id) problem_owner_id
) noexcept {
bool is_owned = problem_owner_id and is_self(session, *problem_owner_id);
bool is_owned = problem_owner_id && is_self(session, *problem_owner_id);
bool is_public = problem_visibility == sim::problems::Problem::Visibility::PUBLIC;
bool is_contest_only = problem_visibility == sim::problems::Problem::Visibility::CONTEST_ONLY;
bool view =
is_public or is_owned or is_admin(session) or (is_teacher(session) and is_contest_only);
is_public || is_owned || is_admin(session) || (is_teacher(session) && is_contest_only);
return {
.view = view,
.view_statement = view,
.view_public_tags = view,
.view_hidden_tags = view and (is_admin(session) or is_teacher(session) or is_owned),
.view_solutions = is_admin(session) or is_owned or (is_teacher(session) and is_public),
.view_simfile = is_admin(session) or is_owned or
(is_teacher(session) and (is_public or is_contest_only)),
.view_owner = is_admin(session) or is_owned or
(is_teacher(session) and (is_public or is_contest_only)),
.view_creation_time = is_admin(session) or is_owned or
(is_teacher(session) and (is_public or is_contest_only)),
.view_update_time = is_admin(session) or is_owned or
(is_teacher(session) and (is_public or is_contest_only)),
.view_final_submission_full_status = view and session,
.download = is_admin(session) or is_owned or (is_teacher(session) and is_public),
.create_submission = view and session,
.edit = is_admin(session) or is_owned,
.reupload = is_admin(session) or is_owned,
.rejudge_all_submissions = is_admin(session) or is_owned,
.reset_time_limits = is_admin(session) or is_owned,
.delete_ = is_admin(session) or is_owned,
.merge_into_another_problem = is_admin(session) or is_owned,
.merge_other_problem_into_this_problem = is_admin(session) or is_owned,
.view_hidden_tags = view && (is_admin(session) || is_teacher(session) || is_owned),
.view_solutions = is_admin(session) || is_owned || (is_teacher(session) && is_public),
.view_simfile = is_admin(session) || is_owned ||
(is_teacher(session) && (is_public || is_contest_only)),
.view_owner = is_admin(session) || is_owned ||
(is_teacher(session) && (is_public || is_contest_only)),
.view_creation_time = is_admin(session) || is_owned ||
(is_teacher(session) && (is_public || is_contest_only)),
.view_update_time = is_admin(session) || is_owned ||
(is_teacher(session) && (is_public || is_contest_only)),
.view_final_submission_full_status = view && session,
.download = is_admin(session) || is_owned || (is_teacher(session) && is_public),
.create_submission = view && session,
.edit = is_admin(session) || is_owned,
.reupload = is_admin(session) || is_owned,
.rejudge_all_submissions = is_admin(session) || is_owned,
.reset_time_limits = is_admin(session) || is_owned,
.delete_ = is_admin(session) || is_owned,
.merge_into_another_problem = is_admin(session) || is_owned,
.merge_other_problem_into_this_problem = is_admin(session) || is_owned,
};
}

Expand Down
18 changes: 9 additions & 9 deletions subprojects/sim/src/web_server/capabilities/problems.hh
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@ namespace web_server::capabilities {
struct ProblemsCapabilities {
bool web_ui_view : 1;
bool add_problem : 1;
bool add_problem_with_type_private : 1;
bool add_problem_with_type_contest_only : 1;
bool add_problem_with_type_public : 1;
bool add_problem_with_visibility_private : 1;
bool add_problem_with_visibility_contest_only : 1;
bool add_problem_with_visibility_public : 1;
};

ProblemsCapabilities problems(const decltype(web_worker::Context::session)& session) noexcept;

struct ProblemsListCapabilities {
bool query_all : 1;
bool query_with_type_public : 1;
bool query_with_type_contest_only : 1;
bool query_with_type_private : 1;
bool view_all_with_type_public : 1;
bool view_all_with_type_contest_only : 1;
bool view_all_with_type_private : 1;
bool query_with_visibility_public : 1;
bool query_with_visibility_contest_only : 1;
bool query_with_visibility_private : 1;
bool view_all_with_visibility_public : 1;
bool view_all_with_visibility_contest_only : 1;
bool view_all_with_visibility_private : 1;
};

ProblemsListCapabilities list_problems(const decltype(web_worker::Context::session)& session
Expand Down
33 changes: 16 additions & 17 deletions subprojects/sim/src/web_server/capabilities/users.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ UsersCapabilities users(const decltype(Context::session)& session) noexcept {
return {
.web_ui_view = is_admin(session),
.add_user = is_admin(session),
.add_admin = session and session->user_id == sim::users::SIM_ROOT_ID,
.add_admin = session && session->user_id == sim::users::SIM_ROOT_ID,
.add_teacher = is_admin(session),
.add_normal_user = is_admin(session),
.sign_in = true,
Expand Down Expand Up @@ -42,29 +42,28 @@ UserCapabilities user(
bool is_admin_ = is_admin(session);
bool is_teacher_ = is_teacher(session);
bool is_self_ = is_self(session, user_id);
bool edit = is_self_ or (is_admin_ and user_id != SIM_ROOT_ID);
bool edit = is_self_ || (is_admin_ && user_id != SIM_ROOT_ID);
bool make_admin =
(session and session->user_id == SIM_ROOT_ID) or (edit and user_type == User::Type::ADMIN);
(session && session->user_id == SIM_ROOT_ID) || (edit && user_type == User::Type::ADMIN);
bool make_teacher =
(user_id != SIM_ROOT_ID) and (is_admin_ or (edit and user_type == User::Type::TEACHER));
bool make_normal = (user_id != SIM_ROOT_ID) and
(is_admin_ or (is_teacher_ and is_self_) or (edit and user_type == User::Type::NORMAL));
(user_id != SIM_ROOT_ID) && (is_admin_ || (edit && user_type == User::Type::TEACHER));
bool make_normal = (user_id != SIM_ROOT_ID) &&
(is_admin_ || (is_teacher_ && is_self_) || (edit && user_type == User::Type::NORMAL));
return {
.view = is_self_ or is_admin_,
.view = is_self_ || is_admin_,
.edit = edit,
.edit_username = is_self_ or (is_admin_ and user_id != SIM_ROOT_ID),
.edit_first_name = is_self_ or (is_admin_ and user_id != SIM_ROOT_ID),
.edit_last_name = is_self_ or (is_admin_ and user_id != SIM_ROOT_ID),
.edit_email = is_self_ or (is_admin_ and user_id != SIM_ROOT_ID),
.change_password = is_self_ or (is_admin_ and user_id != SIM_ROOT_ID),
.change_password_without_old_password =
not is_self_ and is_admin_ and user_id != SIM_ROOT_ID,
.change_type = make_admin or make_teacher or make_normal,
.edit_username = is_self_ || (is_admin_ && user_id != SIM_ROOT_ID),
.edit_first_name = is_self_ || (is_admin_ && user_id != SIM_ROOT_ID),
.edit_last_name = is_self_ || (is_admin_ && user_id != SIM_ROOT_ID),
.edit_email = is_self_ || (is_admin_ && user_id != SIM_ROOT_ID),
.change_password = is_self_ || (is_admin_ && user_id != SIM_ROOT_ID),
.change_password_without_old_password = not is_self_ && is_admin_ && user_id != SIM_ROOT_ID,
.change_type = make_admin || make_teacher || make_normal,
.make_admin = make_admin,
.make_teacher = make_teacher,
.make_normal = make_normal,
.delete_ = user_id != SIM_ROOT_ID and (is_self_ or is_admin_),
.merge_into_another_user = user_id != SIM_ROOT_ID and is_admin_,
.delete_ = user_id != SIM_ROOT_ID && (is_self_ || is_admin_),
.merge_into_another_user = user_id != SIM_ROOT_ID && is_admin_,
.merge_someone_into_this_user = user_id != SIM_ROOT_ID
};
}
Expand Down
6 changes: 3 additions & 3 deletions subprojects/sim/src/web_server/capabilities/utils.hh
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@
namespace web_server::capabilities {

constexpr bool is_admin(const decltype(web_worker::Context::session)& session) noexcept {
return session and session->user_type == sim::users::User::Type::ADMIN;
return session && session->user_type == sim::users::User::Type::ADMIN;
}

constexpr bool is_teacher(const decltype(web_worker::Context::session)& session) noexcept {
return session and session->user_type == sim::users::User::Type::TEACHER;
return session && session->user_type == sim::users::User::Type::TEACHER;
}

constexpr bool is_self(
const decltype(web_worker::Context::session)& session, decltype(sim::users::User::id) user_id
) noexcept {
return session and session->user_id == user_id;
return session && session->user_id == user_id;
}

} // namespace web_server::capabilities
18 changes: 9 additions & 9 deletions subprojects/sim/src/web_server/problems/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,9 @@ constexpr bool is_query_allowed(
}
// NOLINTNEXTLINE(bugprone-switch-missing-default-case)
switch (*problem_visibility) {
case Problem::Visibility::PUBLIC: return caps.query_with_type_public;
case Problem::Visibility::CONTEST_ONLY: return caps.query_with_type_contest_only;
case Problem::Visibility::PRIVATE: return caps.query_with_type_private;
case Problem::Visibility::PUBLIC: return caps.query_with_visibility_public;
case Problem::Visibility::CONTEST_ONLY: return caps.query_with_visibility_contest_only;
case Problem::Visibility::PRIVATE: return caps.query_with_visibility_private;
}
THROW("unexpected problem visibility");
}
Expand All @@ -247,23 +247,23 @@ Condition<> caps_to_condition(
ProblemsListCapabilities caps, optional<decltype(Problem::visibility)> problem_visibility
) {
optional<Condition<>> res;
if (caps.view_all_with_type_public and
if (caps.view_all_with_visibility_public and
(!problem_visibility or problem_visibility == Problem::Visibility::PUBLIC))
{
res = std::move(res) ||
optional{Condition(
concat_tostr("p.visibility=", enum_to_underlying_type(Problem::Visibility::PUBLIC))
)};
}
if (caps.view_all_with_type_contest_only and
if (caps.view_all_with_visibility_contest_only and
(!problem_visibility or problem_visibility == Problem::Visibility::CONTEST_ONLY))
{
res = std::move(res) ||
optional{Condition(concat_tostr(
"p.visibility=", enum_to_underlying_type(Problem::Visibility::CONTEST_ONLY)
))};
}
if (caps.view_all_with_type_private and
if (caps.view_all_with_visibility_private and
(!problem_visibility or problem_visibility == Problem::Visibility::PRIVATE))
{
res = std::move(res) ||
Expand Down Expand Up @@ -629,9 +629,9 @@ http::Response add(web_worker::Context& ctx) {

VALIDATE(ctx.request.form_fields, ctx.response_400,
(visibility, params::visibility, REQUIRED_ENUM_CAPS(
(PRIVATE, caps.add_problem_with_type_private)
(CONTEST_ONLY, caps.add_problem_with_type_contest_only)
(PUBLIC, caps.add_problem_with_type_public)
(PRIVATE, caps.add_problem_with_visibility_private)
(CONTEST_ONLY, caps.add_problem_with_visibility_contest_only)
(PUBLIC, caps.add_problem_with_visibility_public)
))
);

Expand Down
Loading

0 comments on commit 889bcee

Please sign in to comment.