mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
PubSub: Cleanup tree requests, rename pubsub_node.type->pubsub_node.plugin
This commit is contained in:
parent
2531f37e5c
commit
44700d91ba
@ -203,7 +203,7 @@ CREATE TABLE pubsub_node (
|
|||||||
host text NOT NULL,
|
host text NOT NULL,
|
||||||
node text NOT NULL,
|
node text NOT NULL,
|
||||||
parent text NOT NULL DEFAULT '',
|
parent text NOT NULL DEFAULT '',
|
||||||
type text NOT NULL,
|
plugin text NOT NULL,
|
||||||
nodeid INTEGER PRIMARY KEY AUTOINCREMENT
|
nodeid INTEGER PRIMARY KEY AUTOINCREMENT
|
||||||
);
|
);
|
||||||
CREATE INDEX i_pubsub_node_parent ON pubsub_node (parent);
|
CREATE INDEX i_pubsub_node_parent ON pubsub_node (parent);
|
||||||
|
@ -279,7 +279,7 @@ CREATE TABLE [dbo].[pubsub_node] (
|
|||||||
[host] [varchar] (255) NOT NULL,
|
[host] [varchar] (255) NOT NULL,
|
||||||
[node] [varchar] (255) NOT NULL,
|
[node] [varchar] (255) NOT NULL,
|
||||||
[parent] [varchar] (255) NOT NULL DEFAULT '',
|
[parent] [varchar] (255) NOT NULL DEFAULT '',
|
||||||
[type] [text] NOT NULL,
|
[plugin] [text] NOT NULL,
|
||||||
[nodeid] [bigint] IDENTITY(1,1) NOT NULL,
|
[nodeid] [bigint] IDENTITY(1,1) NOT NULL,
|
||||||
CONSTRAINT [pubsub_node_PRIMARY] PRIMARY KEY CLUSTERED
|
CONSTRAINT [pubsub_node_PRIMARY] PRIMARY KEY CLUSTERED
|
||||||
(
|
(
|
||||||
|
@ -215,7 +215,7 @@ CREATE TABLE pubsub_node (
|
|||||||
host text NOT NULL,
|
host text NOT NULL,
|
||||||
node text NOT NULL,
|
node text NOT NULL,
|
||||||
parent VARCHAR(191) NOT NULL DEFAULT '',
|
parent VARCHAR(191) NOT NULL DEFAULT '',
|
||||||
type text NOT NULL,
|
plugin text NOT NULL,
|
||||||
nodeid bigint auto_increment primary key
|
nodeid bigint auto_increment primary key
|
||||||
) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
CREATE INDEX i_pubsub_node_parent ON pubsub_node(parent(120));
|
CREATE INDEX i_pubsub_node_parent ON pubsub_node(parent(120));
|
||||||
|
@ -396,7 +396,7 @@ CREATE TABLE pubsub_node (
|
|||||||
host text NOT NULL,
|
host text NOT NULL,
|
||||||
node text NOT NULL,
|
node text NOT NULL,
|
||||||
parent text NOT NULL DEFAULT '',
|
parent text NOT NULL DEFAULT '',
|
||||||
"type" text NOT NULL,
|
plugin text NOT NULL,
|
||||||
nodeid SERIAL UNIQUE
|
nodeid SERIAL UNIQUE
|
||||||
);
|
);
|
||||||
CREATE INDEX i_pubsub_node_parent ON pubsub_node USING btree (parent);
|
CREATE INDEX i_pubsub_node_parent ON pubsub_node USING btree (parent);
|
||||||
|
@ -221,7 +221,7 @@ CREATE TABLE pubsub_node (
|
|||||||
host text NOT NULL,
|
host text NOT NULL,
|
||||||
node text NOT NULL,
|
node text NOT NULL,
|
||||||
parent text NOT NULL DEFAULT '',
|
parent text NOT NULL DEFAULT '',
|
||||||
"type" text NOT NULL,
|
plugin text NOT NULL,
|
||||||
nodeid SERIAL UNIQUE
|
nodeid SERIAL UNIQUE
|
||||||
);
|
);
|
||||||
CREATE INDEX i_pubsub_node_parent ON pubsub_node USING btree (parent);
|
CREATE INDEX i_pubsub_node_parent ON pubsub_node USING btree (parent);
|
||||||
|
@ -337,7 +337,7 @@ get_entity_affiliations(Host, Owner) ->
|
|||||||
J = encode_jid(GenKey),
|
J = encode_jid(GenKey),
|
||||||
{result,
|
{result,
|
||||||
case ejabberd_sql:sql_query_t(
|
case ejabberd_sql:sql_query_t(
|
||||||
?SQL("select @(node)s, @(type)s, @(i.nodeid)d, @(affiliation)s "
|
?SQL("select @(node)s, @(plugin)s, @(i.nodeid)d, @(affiliation)s "
|
||||||
"from pubsub_state i, pubsub_node n where "
|
"from pubsub_state i, pubsub_node n where "
|
||||||
"i.nodeid = n.nodeid and jid=%(J)s and host=%(H)s")) of
|
"i.nodeid = n.nodeid and jid=%(J)s and host=%(H)s")) of
|
||||||
{selected, RItems} ->
|
{selected, RItems} ->
|
||||||
@ -389,13 +389,13 @@ get_entity_subscriptions(Host, Owner) ->
|
|||||||
Query = case SubKey of
|
Query = case SubKey of
|
||||||
GenKey ->
|
GenKey ->
|
||||||
GJLike = <<(encode_jid_like(GenKey))/binary, "/%">>,
|
GJLike = <<(encode_jid_like(GenKey))/binary, "/%">>,
|
||||||
?SQL("select @(node)s, @(type)s, @(i.nodeid)d, @(jid)s, @(subscriptions)s "
|
?SQL("select @(node)s, @(plugin)s, @(i.nodeid)d, @(jid)s, @(subscriptions)s "
|
||||||
"from pubsub_state i, pubsub_node n "
|
"from pubsub_state i, pubsub_node n "
|
||||||
"where i.nodeid = n.nodeid and "
|
"where i.nodeid = n.nodeid and "
|
||||||
"(jid=%(GJ)s or jid like %(GJLike)s escape '^') and host=%(H)s");
|
"(jid=%(GJ)s or jid like %(GJLike)s escape '^') and host=%(H)s");
|
||||||
_ ->
|
_ ->
|
||||||
SJ = encode_jid(SubKey),
|
SJ = encode_jid(SubKey),
|
||||||
?SQL("select @(node)s, @(type)s, @(i.nodeid)d, @(jid)s, @(subscriptions)s "
|
?SQL("select @(node)s, @(plugin)s, @(i.nodeid)d, @(jid)s, @(subscriptions)s "
|
||||||
"from pubsub_state i, pubsub_node n "
|
"from pubsub_state i, pubsub_node n "
|
||||||
"where i.nodeid = n.nodeid and "
|
"where i.nodeid = n.nodeid and "
|
||||||
"jid in (%(SJ)s, %(GJ)s) and host=%(H)s")
|
"jid in (%(SJ)s, %(GJ)s) and host=%(H)s")
|
||||||
@ -431,14 +431,14 @@ get_entity_subscriptions_for_send_last(Host, Owner) ->
|
|||||||
Query = case SubKey of
|
Query = case SubKey of
|
||||||
GenKey ->
|
GenKey ->
|
||||||
GJLike = <<(encode_jid_like(GenKey))/binary, "/%">>,
|
GJLike = <<(encode_jid_like(GenKey))/binary, "/%">>,
|
||||||
?SQL("select @(node)s, @(type)s, @(i.nodeid)d, @(jid)s, @(subscriptions)s "
|
?SQL("select @(node)s, @(plugin)s, @(i.nodeid)d, @(jid)s, @(subscriptions)s "
|
||||||
"from pubsub_state i, pubsub_node n, pubsub_node_option o "
|
"from pubsub_state i, pubsub_node n, pubsub_node_option o "
|
||||||
"where i.nodeid = n.nodeid and n.nodeid = o.nodeid and "
|
"where i.nodeid = n.nodeid and n.nodeid = o.nodeid and "
|
||||||
"name='send_last_published_item' and val='on_sub_and_presence' and "
|
"name='send_last_published_item' and val='on_sub_and_presence' and "
|
||||||
"(jid=%(GJ)s or jid like %(GJLike)s escape '^') and host=%(H)s");
|
"(jid=%(GJ)s or jid like %(GJLike)s escape '^') and host=%(H)s");
|
||||||
_ ->
|
_ ->
|
||||||
SJ = encode_jid(SubKey),
|
SJ = encode_jid(SubKey),
|
||||||
?SQL("select @(node)s, @(type)s, @(i.nodeid)d, @(jid)s, @(subscriptions)s "
|
?SQL("select @(node)s, @(plugin)s, @(i.nodeid)d, @(jid)s, @(subscriptions)s "
|
||||||
"from pubsub_state i, pubsub_node n, pubsub_node_option o "
|
"from pubsub_state i, pubsub_node n, pubsub_node_option o "
|
||||||
"where i.nodeid = n.nodeid and n.nodeid = o.nodeid and "
|
"where i.nodeid = n.nodeid and n.nodeid = o.nodeid and "
|
||||||
"name='send_last_published_item' and val='on_sub_and_presence' and "
|
"name='send_last_published_item' and val='on_sub_and_presence' and "
|
||||||
|
@ -123,13 +123,13 @@ get_entity_subscriptions(_Host, Owner) ->
|
|||||||
Query = case SubKey of
|
Query = case SubKey of
|
||||||
GenKey ->
|
GenKey ->
|
||||||
GJLike = <<(node_flat_sql:encode_jid_like(GenKey))/binary, "/%">>,
|
GJLike = <<(node_flat_sql:encode_jid_like(GenKey))/binary, "/%">>,
|
||||||
?SQL("select @(host)s, @(node)s, @(type)s, @(i.nodeid)d, @(jid)s, @(subscriptions)s "
|
?SQL("select @(host)s, @(node)s, @(plugin)s, @(i.nodeid)d, @(jid)s, @(subscriptions)s "
|
||||||
"from pubsub_state i, pubsub_node n "
|
"from pubsub_state i, pubsub_node n "
|
||||||
"where i.nodeid = n.nodeid and "
|
"where i.nodeid = n.nodeid and "
|
||||||
"(jid=%(GJ)s or jid like %(GJLike)s escape '^') and host like %(HLike)s escape '^'");
|
"(jid=%(GJ)s or jid like %(GJLike)s escape '^') and host like %(HLike)s escape '^'");
|
||||||
_ ->
|
_ ->
|
||||||
SJ = node_flat_sql:encode_jid(SubKey),
|
SJ = node_flat_sql:encode_jid(SubKey),
|
||||||
?SQL("select @(host)s, @(node)s, @(type)s, @(i.nodeid)d, @(jid)s, @(subscriptions)s "
|
?SQL("select @(host)s, @(node)s, @(plugin)s, @(i.nodeid)d, @(jid)s, @(subscriptions)s "
|
||||||
"from pubsub_state i, pubsub_node n "
|
"from pubsub_state i, pubsub_node n "
|
||||||
"where i.nodeid = n.nodeid and "
|
"where i.nodeid = n.nodeid and "
|
||||||
"jid in (%(SJ)s,%(GJ)s) and host like %(HLike)s escape '^'")
|
"jid in (%(SJ)s,%(GJ)s) and host like %(HLike)s escape '^'")
|
||||||
@ -159,14 +159,14 @@ get_entity_subscriptions_for_send_last(_Host, Owner) ->
|
|||||||
Query = case SubKey of
|
Query = case SubKey of
|
||||||
GenKey ->
|
GenKey ->
|
||||||
GJLike = <<(node_flat_sql:encode_jid_like(GenKey))/binary, "/%">>,
|
GJLike = <<(node_flat_sql:encode_jid_like(GenKey))/binary, "/%">>,
|
||||||
?SQL("select @(host)s, @(node)s, @(type)s, @(i.nodeid)d, @(jid)s, @(subscriptions)s "
|
?SQL("select @(host)s, @(node)s, @(plugin)s, @(i.nodeid)d, @(jid)s, @(subscriptions)s "
|
||||||
"from pubsub_state i, pubsub_node n, pubsub_node_option o "
|
"from pubsub_state i, pubsub_node n, pubsub_node_option o "
|
||||||
"where i.nodeid = n.nodeid and n.nodeid = o.nodeid and "
|
"where i.nodeid = n.nodeid and n.nodeid = o.nodeid and "
|
||||||
"name='send_last_published_item' and val='on_sub_and_presence' and "
|
"name='send_last_published_item' and val='on_sub_and_presence' and "
|
||||||
"(jid=%(GJ)s or jid like %(GJLike)s escape '^') and host like %(HLike)s escape '^'");
|
"(jid=%(GJ)s or jid like %(GJLike)s escape '^') and host like %(HLike)s escape '^'");
|
||||||
_ ->
|
_ ->
|
||||||
SJ = node_flat_sql:encode_jid(SubKey),
|
SJ = node_flat_sql:encode_jid(SubKey),
|
||||||
?SQL("select @(host)s, @(node)s, @(type)s, @(i.nodeid)d, @(jid)s, @(subscriptions)s "
|
?SQL("select @(host)s, @(node)s, @(plugin)s, @(i.nodeid)d, @(jid)s, @(subscriptions)s "
|
||||||
"from pubsub_state i, pubsub_node n, pubsub_node_option o "
|
"from pubsub_state i, pubsub_node n, pubsub_node_option o "
|
||||||
"where i.nodeid = n.nodeid and n.nodeid = o.nodeid and "
|
"where i.nodeid = n.nodeid and n.nodeid = o.nodeid and "
|
||||||
"name='send_last_published_item' and val='on_sub_and_presence' and "
|
"name='send_last_published_item' and val='on_sub_and_presence' and "
|
||||||
|
@ -72,23 +72,20 @@ set_node(Record) when is_record(Record, pubsub_node) ->
|
|||||||
{result, OldNidx} ->
|
{result, OldNidx} ->
|
||||||
catch
|
catch
|
||||||
ejabberd_sql:sql_query_t(
|
ejabberd_sql:sql_query_t(
|
||||||
?SQL("delete from pubsub_node_option where "
|
?SQL("delete from pubsub_node_option "
|
||||||
"nodeid=%(OldNidx)d")),
|
"where nodeid=%(OldNidx)d")),
|
||||||
catch
|
catch
|
||||||
ejabberd_sql:sql_query_t(
|
ejabberd_sql:sql_query_t(
|
||||||
?SQL("update pubsub_node set"
|
?SQL("update pubsub_node set"
|
||||||
" host=%(H)s,"
|
" host=%(H)s, node=%(Node)s,"
|
||||||
" node=%(Node)s,"
|
" parent=%(Parent)s, plugin=%(Type)s "
|
||||||
" parent=%(Parent)s,"
|
|
||||||
" type=%(Type)s "
|
|
||||||
"where nodeid=%(OldNidx)d")),
|
"where nodeid=%(OldNidx)d")),
|
||||||
OldNidx;
|
OldNidx;
|
||||||
_ ->
|
_ ->
|
||||||
catch
|
catch
|
||||||
ejabberd_sql:sql_query_t(
|
ejabberd_sql:sql_query_t(
|
||||||
?SQL("insert into pubsub_node(host, node, "
|
?SQL("insert into pubsub_node(host, node, parent, plugin) "
|
||||||
"parent, type) values("
|
"values(%(H)s, %(Node)s, %(Parent)s, %(Type)s)")),
|
||||||
"%(H)s, %(Node)s, %(Parent)s, %(Type)s)")),
|
|
||||||
case nodeidx(Host, Node) of
|
case nodeidx(Host, Node) of
|
||||||
{result, NewNidx} -> NewNidx;
|
{result, NewNidx} -> NewNidx;
|
||||||
_ -> none % this should not happen
|
_ -> none % this should not happen
|
||||||
@ -104,9 +101,8 @@ set_node(Record) when is_record(Record, pubsub_node) ->
|
|||||||
SValue = misc:term_to_expr(Value),
|
SValue = misc:term_to_expr(Value),
|
||||||
catch
|
catch
|
||||||
ejabberd_sql:sql_query_t(
|
ejabberd_sql:sql_query_t(
|
||||||
?SQL("insert into pubsub_node_option(nodeid, "
|
?SQL("insert into pubsub_node_option(nodeid, name, val) "
|
||||||
"name, val) values ("
|
"values (%(Nidx)d, %(SKey)s, %(SValue)s)"))
|
||||||
"%(Nidx)d, %(SKey)s, %(SValue)s)"))
|
|
||||||
end,
|
end,
|
||||||
Record#pubsub_node.options),
|
Record#pubsub_node.options),
|
||||||
{result, Nidx}
|
{result, Nidx}
|
||||||
@ -119,8 +115,8 @@ get_node(Host, Node) ->
|
|||||||
H = node_flat_sql:encode_host(Host),
|
H = node_flat_sql:encode_host(Host),
|
||||||
case catch
|
case catch
|
||||||
ejabberd_sql:sql_query_t(
|
ejabberd_sql:sql_query_t(
|
||||||
?SQL("select @(node)s, @(parent)s, @(type)s, @(nodeid)d from "
|
?SQL("select @(node)s, @(parent)s, @(plugin)s, @(nodeid)d from pubsub_node "
|
||||||
"pubsub_node where host=%(H)s and node=%(Node)s"))
|
"where host=%(H)s and node=%(Node)s"))
|
||||||
of
|
of
|
||||||
{selected, [RItem]} ->
|
{selected, [RItem]} ->
|
||||||
raw_to_node(Host, RItem);
|
raw_to_node(Host, RItem);
|
||||||
@ -133,8 +129,8 @@ get_node(Host, Node) ->
|
|||||||
get_node(Nidx) ->
|
get_node(Nidx) ->
|
||||||
case catch
|
case catch
|
||||||
ejabberd_sql:sql_query_t(
|
ejabberd_sql:sql_query_t(
|
||||||
?SQL("select @(host)s, @(node)s, @(parent)s, @(type)s from "
|
?SQL("select @(host)s, @(node)s, @(parent)s, @(plugin)s from pubsub_node "
|
||||||
"pubsub_node where nodeid=%(Nidx)d"))
|
"where nodeid=%(Nidx)d"))
|
||||||
of
|
of
|
||||||
{selected, [{Host, Node, Parent, Type}]} ->
|
{selected, [{Host, Node, Parent, Type}]} ->
|
||||||
raw_to_node(Host, {Node, Parent, Type, Nidx});
|
raw_to_node(Host, {Node, Parent, Type, Nidx});
|
||||||
@ -151,8 +147,8 @@ get_nodes(Host) ->
|
|||||||
H = node_flat_sql:encode_host(Host),
|
H = node_flat_sql:encode_host(Host),
|
||||||
case catch
|
case catch
|
||||||
ejabberd_sql:sql_query_t(
|
ejabberd_sql:sql_query_t(
|
||||||
?SQL("select @(node)s, @(parent)s, @(type)s, @(nodeid)d from "
|
?SQL("select @(node)s, @(parent)s, @(plugin)s, @(nodeid)d from pubsub_node "
|
||||||
"pubsub_node where host=%(H)s"))
|
"where host=%(H)s"))
|
||||||
of
|
of
|
||||||
{selected, RItems} ->
|
{selected, RItems} ->
|
||||||
[raw_to_node(Host, Item) || Item <- RItems];
|
[raw_to_node(Host, Item) || Item <- RItems];
|
||||||
@ -189,8 +185,8 @@ get_subnodes(Host, Node) ->
|
|||||||
H = node_flat_sql:encode_host(Host),
|
H = node_flat_sql:encode_host(Host),
|
||||||
case catch
|
case catch
|
||||||
ejabberd_sql:sql_query_t(
|
ejabberd_sql:sql_query_t(
|
||||||
?SQL("select @(node)s, @(parent)s, @(type)s, @(nodeid)d from "
|
?SQL("select @(node)s, @(parent)s, @(plugin)s, @(nodeid)d from pubsub_node "
|
||||||
"pubsub_node where host=%(H)s and parent=%(Node)s"))
|
"where host=%(H)s and parent=%(Node)s"))
|
||||||
of
|
of
|
||||||
{selected, RItems} ->
|
{selected, RItems} ->
|
||||||
[raw_to_node(Host, Item) || Item <- RItems];
|
[raw_to_node(Host, Item) || Item <- RItems];
|
||||||
@ -206,14 +202,14 @@ get_subnodes_tree(Host, Node) ->
|
|||||||
{error, _} ->
|
{error, _} ->
|
||||||
[];
|
[];
|
||||||
Rec ->
|
Rec ->
|
||||||
|
Type = Rec#pubsub_node.type,
|
||||||
H = node_flat_sql:encode_host(Host),
|
H = node_flat_sql:encode_host(Host),
|
||||||
N = <<(ejabberd_sql:escape_like_arg_circumflex(Node))/binary, "/%">>,
|
N = <<(ejabberd_sql:escape_like_arg_circumflex(Node))/binary, "/%">>,
|
||||||
Sub = case catch
|
Sub = case catch
|
||||||
ejabberd_sql:sql_query_t(
|
ejabberd_sql:sql_query_t(
|
||||||
?SQL("select @(node)s, @(parent)s, @(type)s, @(nodeid)d from "
|
?SQL("select @(node)s, @(parent)s, @(plugin)s, @(nodeid)d from pubsub_node "
|
||||||
"pubsub_node where host=%(H)s"
|
"where host=%(H)s and plugin=%(Type)s and"
|
||||||
" and node like %(N)s escape '^'"
|
" (parent=%(Node)s or parent like %(N)s escape '^')"))
|
||||||
" and \"type\"='hometree'"))
|
|
||||||
of
|
of
|
||||||
{selected, RItems} ->
|
{selected, RItems} ->
|
||||||
[raw_to_node(Host, Item) || Item <- RItems];
|
[raw_to_node(Host, Item) || Item <- RItems];
|
||||||
@ -269,14 +265,13 @@ create_node(Host, Node, Type, Owner, Options, Parents) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
delete_node(Host, Node) ->
|
delete_node(Host, Node) ->
|
||||||
H = node_flat_sql:encode_host(Host),
|
lists:map(
|
||||||
N = <<(ejabberd_sql:escape_like_arg_circumflex(Node))/binary, "/%">>,
|
fun(Rec) ->
|
||||||
Removed = get_subnodes_tree(Host, Node),
|
Nidx = Rec#pubsub_node.id,
|
||||||
catch ejabberd_sql:sql_query_t(
|
catch ejabberd_sql:sql_query_t(
|
||||||
?SQL("delete from pubsub_node where host=%(H)s"
|
?SQL("delete from pubsub_node where nodeid=%(Nidx)d")),
|
||||||
" and (node=%(Node)s"
|
Rec
|
||||||
" or (\"type\"='hometree' and node like %(N)s escape '^'))")),
|
end, get_subnodes_tree(Host, Node)).
|
||||||
Removed.
|
|
||||||
|
|
||||||
%% helpers
|
%% helpers
|
||||||
raw_to_node(Host, [Node, Parent, Type, Nidx]) ->
|
raw_to_node(Host, [Node, Parent, Type, Nidx]) ->
|
||||||
@ -308,16 +303,15 @@ raw_to_node(Host, {Node, Parent, Type, Nidx}) ->
|
|||||||
<<>> -> [];
|
<<>> -> [];
|
||||||
_ -> [Parent]
|
_ -> [Parent]
|
||||||
end,
|
end,
|
||||||
#pubsub_node{nodeid = {Host, Node},
|
#pubsub_node{nodeid = {Host, Node}, id = Nidx,
|
||||||
parents = Parents,
|
parents = Parents, type = Type, options = Options}.
|
||||||
id = Nidx, type = Type, options = Options}.
|
|
||||||
|
|
||||||
nodeidx(Host, Node) ->
|
nodeidx(Host, Node) ->
|
||||||
H = node_flat_sql:encode_host(Host),
|
H = node_flat_sql:encode_host(Host),
|
||||||
case catch
|
case catch
|
||||||
ejabberd_sql:sql_query_t(
|
ejabberd_sql:sql_query_t(
|
||||||
?SQL("select @(nodeid)d from pubsub_node where "
|
?SQL("select @(nodeid)d from pubsub_node "
|
||||||
"host=%(H)s and node=%(Node)s"))
|
"where host=%(H)s and node=%(Node)s"))
|
||||||
of
|
of
|
||||||
{selected, [{Nidx}]} ->
|
{selected, [{Nidx}]} ->
|
||||||
{result, Nidx};
|
{result, Nidx};
|
||||||
|
Loading…
Reference in New Issue
Block a user