0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-25 23:14:13 +01:00

ircd:Ⓜ️:room: Reorg / slim the class member function interface.

ircd:Ⓜ️:room: Rename interface function.
This commit is contained in:
Jason Volk 2019-08-14 01:01:46 -07:00
parent 67f6a36b3f
commit fca330e1c1
29 changed files with 250 additions and 244 deletions

View file

@ -25,19 +25,27 @@ namespace ircd::m
bool operator!=(const room &, const room &); // room_id inequality
bool operator==(const room &, const room &); // room_id equality
// [GET] Util
// [GET] Convenience boolean suite
bool exists(const room &);
bool exists(const id::room &);
bool exists(const id::room_alias &, const bool &remote = false);
bool internal(const id::room &);
bool federate(const id::room &);
id::user::buf creator(const id::room &);
bool federated(const id::room &);
bool creator(const id::room &, const id::user &);
bool membership(const room &, const id::user &, const string_view & = "join");
bool join_rule(const room &, const string_view &rule);
bool visible(const room &, const string_view &mxid, const m::event *const & = nullptr);
bool local_only(const room &);
// [GET] Convenience and tools
id::user::buf creator(const id::room &);
string_view type(const mutable_buffer &, const room &);
string_view version(const mutable_buffer &, const room &, std::nothrow_t);
string_view version(const mutable_buffer &, const room &);
string_view join_rule(const mutable_buffer &out, const room &);
string_view membership(const mutable_buffer &out, const room &, const m::id::user &);
id::user::buf any_user(const room &, const string_view &host, const string_view &memshp = "join");
// [GET]
id::room room_id(const mutable_buffer &, const id::room_alias &);
id::room room_id(const mutable_buffer &, const string_view &id_or_alias);
id::room::buf room_id(const id::room_alias &);
@ -149,15 +157,6 @@ struct ircd::m::room
event::idx get(std::nothrow_t, const string_view &type) const;
event::idx get(const string_view &type) const;
// misc / convenience utils
bool membership(const m::id::user &, const string_view &membership = "join") const;
string_view membership(const mutable_buffer &out, const m::id::user &) const;
bool visible(const string_view &mxid, const m::event *const & = nullptr) const;
string_view join_rule(const mutable_buffer &out) const;
id::user::buf any_user(const string_view &host, const string_view &membership = "join") const;
bool join_rule(const string_view &rule) const;
bool lonly() const;
room(const id &room_id,
const string_view &event_id,
const vm::copts *const &copts = nullptr,

View file

@ -1623,13 +1623,13 @@ ircd::m::v1::fetch_head(const id::room &room_id,
// generate a random one from our host as well.
m::user::id::buf user_id
{
room.any_user(my_host(), "join")
any_user(room, my_host(), "join")
};
// Make another attempt to find an invited user because that carries some
// value (this query is not as fast as querying join memberships).
if(!user_id)
user_id = room.any_user(my_host(), "invite");
user_id = any_user(room, my_host(), "invite");
return fetch_head(room_id, remote, user_id);
}

View file

@ -985,6 +985,99 @@ ircd::m::top(std::nothrow_t,
return ret;
}
ircd::m::id::user::buf
ircd::m::any_user(const room &room,
const string_view &host,
const string_view &membership)
{
user::id::buf ret;
const room::members members{room};
members.for_each(membership, [&host, &ret]
(const auto &user_id, const auto &event_idx)
{
if(host && user_id.host() != host)
return true;
ret = user_id;
return false;
});
return ret;
}
ircd::string_view
ircd::m::membership(const mutable_buffer &out,
const room &room,
const user::id &user_id)
{
const room::state state
{
room
};
const auto event_idx
{
state.get(std::nothrow, "m.room.member", user_id)
};
return room::members::membership(out, event_idx);
}
/// Receive the join_rule of the room into buffer of sufficient size.
/// The protocol does not specify a join_rule string longer than 7
/// characters but do be considerate of the future. This function
/// properly defaults the string as per the protocol spec.
ircd::string_view
ircd::m::join_rule(const mutable_buffer &out,
const room &room)
{
static const string_view default_join_rule
{
"invite"
};
string_view ret
{
default_join_rule
};
const event::keys::include keys
{
"content"
};
const m::event::fetch::opts fopts
{
keys, room.fopts? room.fopts->gopts : db::gopts{}
};
const room::state state
{
room, &fopts
};
state.get(std::nothrow, "m.room.join_rules", "", [&ret, &out]
(const m::event &event)
{
const auto &content
{
json::get<"content"_>(event)
};
const json::string &rule
{
content.get("join_rule", default_join_rule)
};
ret = string_view
{
data(out), copy(out, rule)
};
});
return ret;
}
ircd::string_view
ircd::m::version(const mutable_buffer &buf,
const room &room)
@ -1019,20 +1112,19 @@ ircd::m::version(const mutable_buffer &buf,
strlcpy{buf, "1"_sv}
};
if(event_idx)
m::get(std::nothrow, event_idx, "content", [&buf, &ret]
(const json::object &content)
m::get(std::nothrow, event_idx, "content", [&buf, &ret]
(const json::object &content)
{
const json::string &version
{
const json::string &version
{
content.get("room_version", "1")
};
content.get("room_version", "1")
};
ret = strlcpy
{
buf, version
};
});
ret = strlcpy
{
buf, version
};
});
return ret;
}
@ -1047,36 +1139,23 @@ ircd::m::type(const mutable_buffer &buf,
room.get(std::nothrow, "m.room.create", "")
};
if(event_idx)
m::get(std::nothrow, event_idx, "content", [&buf, &ret]
(const json::object &content)
m::get(std::nothrow, event_idx, "content", [&buf, &ret]
(const json::object &content)
{
const json::string &type
{
const json::string &type
{
content.get("type")
};
content.get("type")
};
ret = strlcpy
{
buf, type
};
});
ret = strlcpy
{
buf, type
};
});
return ret;
}
bool
ircd::m::creator(const id::room &room_id,
const id::user &user_id)
{
const auto creator_user_id
{
creator(room_id)
};
return creator_user_id == user_id;
}
ircd::m::id::user::buf
ircd::m::creator(const id::room &room_id)
{
@ -1084,10 +1163,7 @@ ircd::m::creator(const id::room &room_id)
// future compatibility if the content.creator field gets eliminated.
static const event::fetch::opts fopts
{
event::keys::include
{
"sender",
}
event::keys::include {"sender"}
};
const room::state state
@ -1108,15 +1184,91 @@ ircd::m::creator(const id::room &room_id)
return ret;
}
//
// boolean suite
//
/// The only joined members are from our origin (local only). This indicates
/// we won't have any other federation servers to query for room data, nor do
/// we need to broadcast events to the federation. This is not an authority
/// about a room's type or ability to federate. Returned value changes to false
/// when another origin joins.
bool
ircd::m::federate(const id::room &room_id)
ircd::m::local_only(const room &room)
{
const room::origins origins
{
room
};
return origins.empty() || origins.only(my_host());
}
bool
ircd::m::visible(const room &room,
const string_view &mxid,
const event *const &event)
{
if(event)
return m::visible(*event, mxid);
const m::event event_
{
json::members
{
{ "event_id", room.event_id },
{ "room_id", room.room_id },
}
};
return m::visible(event_, mxid);
}
/// Test of the join_rule of the room is the argument.
bool
ircd::m::join_rule(const room &room,
const string_view &rule)
{
char buf[32];
return join_rule(buf, room) == rule;
}
bool
ircd::m::membership(const room &room,
const user::id &user_id,
const string_view &membership)
{
const room::state state
{
room
};
const auto event_idx
{
state.get(std::nothrow, "m.room.member", user_id)
};
return room::members::membership(event_idx, membership);
}
bool
ircd::m::creator(const room::id &room_id,
const user::id &user_id)
{
const auto creator_user_id
{
creator(room_id)
};
return creator_user_id == user_id;
}
bool
ircd::m::federated(const id::room &room_id)
{
static const m::event::fetch::opts fopts
{
event::keys::include
{
"content",
}
event::keys::include { "content" },
};
const m::room::state state
@ -1172,6 +1324,10 @@ ircd::m::exists(const room &room)
return exists(room.room_id);
}
//
// util
//
bool
ircd::m::operator==(const room &a, const room &b)
{
@ -1236,155 +1392,6 @@ ircd::m::room::index(const room::id &room_id,
// room::room
//
ircd::m::id::user::buf
ircd::m::room::any_user(const string_view &host,
const string_view &membership)
const
{
user::id::buf ret;
const members members{*this};
members.for_each(membership, [&host, &ret]
(const auto &user_id, const auto &event_idx)
{
if(host && user_id.host() != host)
return true;
ret = user_id;
return false;
});
return ret;
}
/// Test of the join_rule of the room is the argument.
bool
ircd::m::room::join_rule(const string_view &rule)
const
{
char buf[32];
return join_rule(mutable_buffer{buf}) == rule;
}
/// Receive the join_rule of the room into buffer of sufficient size.
/// The protocol does not specify a join_rule string longer than 7
/// characters but do be considerate of the future. This function
/// properly defaults the string as per the protocol spec.
ircd::string_view
ircd::m::room::join_rule(const mutable_buffer &out)
const
{
static const string_view default_join_rule
{
"invite"
};
string_view ret
{
default_join_rule
};
const event::keys::include keys
{
"content"
};
const m::event::fetch::opts fopts
{
keys, this->fopts? this->fopts->gopts : db::gopts{}
};
const room::state state
{
*this, &fopts
};
state.get(std::nothrow, "m.room.join_rules", "", [&ret, &out]
(const m::event &event)
{
const auto &content
{
json::get<"content"_>(event)
};
const string_view &rule
{
content.get("join_rule", default_join_rule)
};
ret = string_view
{
data(out), copy(out, unquote(rule))
};
});
return ret;
}
/// The only joined members are from our origin (local only). This indicates
/// we won't have any other federation servers to query for room data, nor do
/// we need to broadcast events to the federation. This is not an authority
/// about a room's type or ability to federate. Returned value changes to false
/// when another origin joins.
bool
ircd::m::room::lonly()
const
{
const origins origins(*this);
return origins.empty() || origins.only(my_host());
}
bool
ircd::m::room::visible(const string_view &mxid,
const event *const &event)
const
{
if(event)
return m::visible(*event, mxid);
const m::event event_
{
json::members
{
{ "event_id", event_id },
{ "room_id", room_id },
}
};
return m::visible(event_, mxid);
}
bool
ircd::m::room::membership(const m::id::user &user_id,
const string_view &membership)
const
{
char buf[64];
return this->membership(buf, user_id) == membership;
}
ircd::string_view
ircd::m::room::membership(const mutable_buffer &out,
const m::id::user &user_id)
const
{
string_view ret;
const room::state state{*this};
state.get(std::nothrow, "m.room.member", user_id, [&out, &ret]
(const event::idx &event_idx)
{
m::get(std::nothrow, event_idx, "content", [&out, &ret]
(const json::object &content)
{
ret =
{
data(out), copy(out, unquote(content.get("membership")))
};
});
});
return ret;
}
bool
ircd::m::room::has(const string_view &type)
const

View file

@ -132,7 +132,7 @@ get__events(client &client,
room_id, event_id
};
if(!room.visible(request.user_id))
if(!visible(room, request.user_id))
throw m::ACCESS_DENIED
{
"You are not able to view the room at this event."

View file

@ -74,7 +74,7 @@ get__context(client &client,
room_id, event_id
};
if(!room.visible(request.user_id))
if(!visible(room, request.user_id))
throw m::ACCESS_DENIED
{
"You are not permitted to view the room at this event"

View file

@ -33,7 +33,7 @@ get__event(client &client,
room_id, event_id
};
if(!room.visible(request.user_id))
if(!visible(room, request.user_id))
throw m::ACCESS_DENIED
{
"You are not permitted to view the room at this event"

View file

@ -42,7 +42,7 @@ post__forget(client &client,
char room_membuf[m::room::MEMBERSHIP_MAX_SIZE];
const string_view &room_membership
{
room.membership(room_membuf, request.user_id)
membership(room_membuf, room, request.user_id)
};
char user_membuf[m::room::MEMBERSHIP_MAX_SIZE];

View file

@ -103,7 +103,7 @@ get__initialsync_local(client &client,
char membership_buf[m::room::MEMBERSHIP_MAX_SIZE];
json::stack::member
{
out, "membership", room.membership(membership_buf, request.user_id)
out, "membership", membership(membership_buf, room, request.user_id)
};
json::stack::member

View file

@ -70,7 +70,7 @@ ircd::m::join(const room &room,
return ret;
}
if(room.membership(user_id, "join"))
if(membership(room, user_id, "join"))
{
const auto &event_idx
{

View file

@ -67,7 +67,7 @@ get__members(client &client,
string_view{room_id}
};
if(!room.visible(request.user_id))
if(!visible(room, request.user_id))
throw m::ACCESS_DENIED
{
"You do not have permission to view %s members.",
@ -137,7 +137,7 @@ get__joined_members(client &client,
string_view{room_id}
};
if(!room.visible(request.user_id))
if(!visible(room, request.user_id))
throw m::ACCESS_DENIED
{
"You do not have permission to view %s joined members.",

View file

@ -79,7 +79,7 @@ get__messages(client &client,
room_id, page.from
};
if(!room.visible(request.user_id))
if(!visible(room, request.user_id))
throw m::ACCESS_DENIED
{
"You are not permitted to view the room at this event"

View file

@ -101,7 +101,7 @@ get__state(client &client,
string_view{room_id}
};
if(!room.visible(request.user_id))
if(!visible(room, request.user_id))
throw m::ACCESS_DENIED
{
"You are not permitted to view %s",

View file

@ -46,7 +46,7 @@ post__unban(client &client,
power.level("ban")
};
if(!room.membership(user_id, "ban"))
if(!membership(room, user_id, "ban"))
throw m::error
{
http::OK, "M_BAD_STATE",

View file

@ -57,7 +57,7 @@ ircd::m::sync::rooms_linear(data &data)
const string_view &membership
{
data.room?
room.membership(membuf, data.user):
m::membership(membuf, room, data.user):
string_view{}
};

View file

@ -91,7 +91,7 @@ ircd::m::sync::room_account_data_linear_events(data &data,
char membuf[room::MEMBERSHIP_MAX_SIZE];
const auto membership
{
room.membership(membuf, data.user)
m::membership(membuf, room, data.user)
};
if(!membership)
@ -153,7 +153,7 @@ ircd::m::sync::room_account_data_linear_tags(data &data,
char membuf[room::MEMBERSHIP_MAX_SIZE];
const auto membership
{
room.membership(membuf, data.user)
m::membership(membuf, room, data.user)
};
if(!membership)

View file

@ -55,7 +55,7 @@ ircd::m::sync::room_ephemeral_m_receipt_m_read_linear(data &data)
json::get<"state_key"_>(*data.event)
};
if(!room.membership(data.user, "join"))
if(!membership(room, data.user, "join"))
return false;
json::stack::object rooms

View file

@ -41,7 +41,7 @@ ircd::m::sync::room_ephemeral_m_typing_linear(data &data)
};
// Check if our user is a member of the room targetted by the typing notif
if(!target_room.membership(data.user, "join"))
if(!membership(target_room, data.user, "join"))
return false;
const m::user::id &sender

View file

@ -7729,7 +7729,7 @@ console_cmd__room__top(opt &out, const string_view &line)
char version_buf[32];
out << "index: " << m::room::index(room_id) << std::endl;
out << "version: " << m::version(version_buf, room_id) << std::endl;
out << "federate: " << std::boolalpha << m::federate(room_id) << std::endl;
out << "federated: " << std::boolalpha << m::federated(room_id) << std::endl;
out << "top index: " << std::get<m::event::idx>(top) << std::endl;
out << "top depth: " << std::get<int64_t>(top) << std::endl;
out << "top event: " << std::get<m::event::id::buf>(top) << std::endl;
@ -8123,7 +8123,7 @@ console_cmd__room__visible(opt &out, const string_view &line)
const bool visible
{
room.visible(mxid)
m::visible(room, mxid)
};
out << room_id << " is "
@ -11949,12 +11949,12 @@ console_cmd__fed__head(opt &out, const string_view &line)
user_id = param["user_id"];
if(!user_id)
user_id = room.any_user(my_host(), "join");
user_id = any_user(room, my_host(), "join");
// Make another attempt to find an invited user because that carries some
// value (this query is not as fast as querying join memberships).
if(!user_id)
user_id = room.any_user(my_host(), "invite");
user_id = any_user(room, my_host(), "invite");
thread_local char buf[16_KiB];
m::v1::make_join::opts opts;

View file

@ -92,7 +92,7 @@ get__backfill_ids(client &client,
room_id, event_id
};
if(!room.visible(request.node_id))
if(!visible(room, request.node_id))
throw m::ACCESS_DENIED
{
"You are not permitted to view the room at this event"

View file

@ -72,7 +72,7 @@ get__event_auth(client &client,
bool visible
{
room.visible(request.node_id)
m::visible(room, request.node_id)
};
// make an exception to the visibility for invitee cases.

View file

@ -85,7 +85,7 @@ get__make_join(client &client,
"You are not permitted by the room's server access control list."
};
if(!room.visible(user_id))
if(!visible(room, user_id))
throw m::ACCESS_DENIED
{
"You are not permitted to view the room at this event."

View file

@ -81,7 +81,7 @@ get__make_leave(client &client,
char membuf[m::room::MEMBERSHIP_MAX_SIZE];
const string_view membership
{
room.membership(membuf, user_id)
m::membership(membuf, room, user_id)
};
if(membership != "join" && membership != "invite")

View file

@ -63,7 +63,7 @@ get__state(client &client,
room_id, event_id
};
if(!room.visible(request.node_id))
if(!visible(room, request.node_id))
throw m::ACCESS_DENIED
{
"You are not permitted to view the room at this event"

View file

@ -56,7 +56,7 @@ get__state_ids(client &client,
room_id, event_id
};
if(!room.visible(request.node_id))
if(!visible(room, request.node_id))
throw m::ACCESS_DENIED
{
"You are not permitted to view the room at this event"

View file

@ -41,7 +41,7 @@ try
if(!exists(my_room))
create(my_room, me.user_id, "internal");
if(!my_room.membership(me.user_id, "join"))
if(!membership(my_room, me, "join"))
join(my_room, me.user_id);
if(!my_room.has("m.room.name", ""))

View file

@ -499,7 +499,7 @@ try
return;
// Only broadcast if the user is joined to the room.
if(!m::room(room_id).membership(user, "join"))
if(!membership(m::room(room_id), user, "join"))
return;
const m::user::room user_room

View file

@ -25,7 +25,7 @@ _visible_to_user(const m::event &event,
char membership_buf[m::room::MEMBERSHIP_MAX_SIZE];
string_view membership
{
room.membership(membership_buf, user_id)
m::membership(membership_buf, room, user_id)
};
if(membership == "join")
@ -46,7 +46,7 @@ _visible_to_user(const m::event &event,
if(room.event_id)
{
const m::room present{room.room_id};
membership = present.membership(membership_buf, user_id);
membership = m::membership(membership_buf, present, user_id);
return membership == "join" || membership == "invite";
}

View file

@ -71,11 +71,11 @@ ircd::m::rooms::for_each(const opts &opts,
return;
if(opts.remote_joined_only)
if(room(room_id).lonly())
if(local_only(room(room_id)))
return;
if(opts.local_only)
if(!room(room_id).lonly())
if(!local_only(room(room_id)))
return;
if(opts.server && !opts.summary)
@ -91,7 +91,7 @@ ircd::m::rooms::for_each(const opts &opts,
return;
if(opts.join_rule)
if(!room(room_id).join_rule(opts.join_rule))
if(!join_rule(room(room_id), opts.join_rule))
return;
ret = closure(room_id);

View file

@ -75,7 +75,7 @@ commit(const m::typing &edu)
{
// Check if the user is actually in the room.
const m::room room{at<"room_id"_>(edu)};
if(!room.membership(at<"user_id"_>(edu), "join"))
if(!membership(room, at<"user_id"_>(edu), "join"))
throw m::FORBIDDEN
{
"Cannot type in a room %s to which you are not joined",
@ -217,7 +217,7 @@ _handle_edu_m_typing(const m::event &event,
// branch for remote servers only because our committer above did this
// already for our client.
const m::room room{room_id};
if(!room.membership(user_id, "join"))
if(!membership(room, user_id, "join"))
{
log::dwarning
{