slidge 0.2.5__py3-none-any.whl → 0.2.6__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- slidge/__version__.py +1 -1
- slidge/command/adhoc.py +8 -0
- slidge/command/user.py +5 -0
- slidge/contact/contact.py +1 -7
- slidge/core/config.py +0 -4
- slidge/core/gateway.py +4 -2
- slidge/core/mixins/message.py +6 -9
- slidge/core/session.py +11 -3
- slidge/db/alembic/versions/04cf35e3cf85_add_participant_nickname_no_illegal.py +33 -0
- slidge/db/alembic/versions/aa9d82a7f6ef_db_creation.py +0 -51
- slidge/db/models.py +1 -0
- slidge/db/store.py +3 -0
- slidge/group/participant.py +4 -1
- slidge/group/room.py +1 -1
- slidge/slixfix/__init__.py +0 -2
- slidge/slixfix/xep_0100/gateway.py +1 -4
- slidge/util/util.py +5 -1
- {slidge-0.2.5.dist-info → slidge-0.2.6.dist-info}/METADATA +9 -10
- {slidge-0.2.5.dist-info → slidge-0.2.6.dist-info}/RECORD +22 -26
- slidge/db/alembic/old_user_store.py +0 -183
- slidge/slixfix/xep_0356_old/__init__.py +0 -7
- slidge/slixfix/xep_0356_old/privilege.py +0 -167
- slidge/slixfix/xep_0356_old/stanza.py +0 -44
- slidge/util/db.py +0 -5
- {slidge-0.2.5.dist-info → slidge-0.2.6.dist-info}/WHEEL +0 -0
- {slidge-0.2.5.dist-info → slidge-0.2.6.dist-info}/entry_points.txt +0 -0
- {slidge-0.2.5.dist-info → slidge-0.2.6.dist-info}/top_level.txt +0 -0
slidge/__version__.py
CHANGED
slidge/command/adhoc.py
CHANGED
@@ -240,6 +240,14 @@ class AdhocProvider:
|
|
240
240
|
:param iq: the disco query IQ
|
241
241
|
:return: commands accessible to the given JID will be listed
|
242
242
|
"""
|
243
|
+
if not self.xmpp.jid_validator.match(str(jid)) and jid not in config.ADMINS:
|
244
|
+
raise XMPPError(
|
245
|
+
"forbidden",
|
246
|
+
"You are not authorized to execute adhoc commands on this gateway. "
|
247
|
+
"If this is unexpected, ask your administrator to verify that "
|
248
|
+
"'user-jid-validator' is correctly set in slidge's configuration.",
|
249
|
+
)
|
250
|
+
|
243
251
|
all_items = self.xmpp.plugin["xep_0030"].static.get_items(jid, node, None, None)
|
244
252
|
log.debug("Static items: %r", all_items)
|
245
253
|
if not all_items:
|
slidge/command/user.py
CHANGED
@@ -172,6 +172,9 @@ class Login(Command):
|
|
172
172
|
|
173
173
|
async def run(self, session: Optional[AnyBaseSession], _ifrom, *_):
|
174
174
|
assert session is not None
|
175
|
+
if session.is_logging_in:
|
176
|
+
raise XMPPError("bad-request", "You are already logging in.")
|
177
|
+
session.is_logging_in = True
|
175
178
|
try:
|
176
179
|
msg = await session.login()
|
177
180
|
except Exception as e:
|
@@ -179,6 +182,8 @@ class Login(Command):
|
|
179
182
|
raise XMPPError(
|
180
183
|
"internal-server-error", etype="wait", text=f"Could not login: {e}"
|
181
184
|
)
|
185
|
+
finally:
|
186
|
+
session.is_logging_in = False
|
182
187
|
session.logged = True
|
183
188
|
session.send_gateway_status(msg or "Re-connected", show="chat")
|
184
189
|
session.send_gateway_message(msg or "Re-connected")
|
slidge/contact/contact.py
CHANGED
@@ -448,7 +448,7 @@ class LegacyContact(
|
|
448
448
|
log.debug("Roster push request by plugin ignored (--no-roster-push)")
|
449
449
|
return
|
450
450
|
try:
|
451
|
-
await self.
|
451
|
+
await self.xmpp["xep_0356"].set_roster(
|
452
452
|
jid=self.user_jid, roster_items=self.get_roster_item()
|
453
453
|
)
|
454
454
|
except PermissionError:
|
@@ -490,12 +490,6 @@ class LegacyContact(
|
|
490
490
|
nick,
|
491
491
|
)
|
492
492
|
|
493
|
-
async def _set_roster(self, **kw):
|
494
|
-
try:
|
495
|
-
await self.xmpp["xep_0356"].set_roster(**kw)
|
496
|
-
except PermissionError:
|
497
|
-
await self.xmpp["xep_0356_old"].set_roster(**kw)
|
498
|
-
|
499
493
|
def send_friend_request(self, text: Optional[str] = None):
|
500
494
|
presence = self._make_presence(ptype="subscribe", pstatus=text, bare=True)
|
501
495
|
self._send(presence, nick=True)
|
slidge/core/config.py
CHANGED
@@ -68,7 +68,6 @@ USER_JID_VALIDATOR__DYNAMIC_DEFAULT = True
|
|
68
68
|
ADMINS: tuple[JIDType, ...] = ()
|
69
69
|
ADMINS__DOC = "JIDs of the gateway admins"
|
70
70
|
|
71
|
-
|
72
71
|
UPLOAD_SERVICE: Optional[str] = None
|
73
72
|
UPLOAD_SERVICE__DOC = (
|
74
73
|
"JID of an HTTP upload service the gateway can use. "
|
@@ -76,9 +75,6 @@ UPLOAD_SERVICE__DOC = (
|
|
76
75
|
"discovery."
|
77
76
|
)
|
78
77
|
|
79
|
-
SECRET_KEY: Optional[str] = None
|
80
|
-
SECRET_KEY__DOC = "Encryption for disk storage. Deprecated."
|
81
|
-
|
82
78
|
NO_ROSTER_PUSH = False
|
83
79
|
NO_ROSTER_PUSH__DOC = "Do not fill users' rosters with legacy contacts automatically"
|
84
80
|
|
slidge/core/gateway.py
CHANGED
@@ -515,6 +515,7 @@ class BaseGateway(
|
|
515
515
|
@timeit
|
516
516
|
async def login_wrap(self, session: "BaseSession"):
|
517
517
|
session.send_gateway_status("Logging in…", show="dnd")
|
518
|
+
session.is_logging_in = True
|
518
519
|
try:
|
519
520
|
status = await session.login()
|
520
521
|
except Exception as e:
|
@@ -808,7 +809,9 @@ class BaseGateway(
|
|
808
809
|
|
809
810
|
async def unregister_user(self, user: GatewayUser):
|
810
811
|
self.send_presence(
|
811
|
-
pshow="
|
812
|
+
pshow="dnd",
|
813
|
+
pstatus="You unregistered from this gateway.",
|
814
|
+
pto=user.jid,
|
812
815
|
)
|
813
816
|
await self.xmpp.plugin["xep_0077"].api["user_remove"](None, None, user.jid)
|
814
817
|
await self.xmpp.session_cls.kill_by_jid(user.jid)
|
@@ -913,7 +916,6 @@ SLIXMPP_PLUGINS = [
|
|
913
916
|
"xep_0333", # Chat markers
|
914
917
|
"xep_0334", # Message Processing Hints
|
915
918
|
"xep_0356", # Privileged Entity
|
916
|
-
"xep_0356_old", # Privileged Entity (old namespace)
|
917
919
|
"xep_0363", # HTTP file upload
|
918
920
|
"xep_0385", # Stateless in-line media sharing
|
919
921
|
"xep_0402", # PEP Native Bookmarks
|
slidge/core/mixins/message.py
CHANGED
@@ -177,15 +177,12 @@ class CarbonMessageMixin(ContentMessageMixin, MarkerMixin):
|
|
177
177
|
try:
|
178
178
|
self.xmpp["xep_0356"].send_privileged_message(msg)
|
179
179
|
except PermissionError:
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
" https://slidge.im/docs/slidge/main/admin/privilege.html"
|
187
|
-
" for more info."
|
188
|
-
)
|
180
|
+
warnings.warn(
|
181
|
+
"Slidge does not have privileges to send message on behalf of"
|
182
|
+
" user.Refer to"
|
183
|
+
" https://slidge.im/docs/slidge/main/admin/privilege.html"
|
184
|
+
" for more info."
|
185
|
+
)
|
189
186
|
|
190
187
|
|
191
188
|
class InviteMixin(MessageMaker):
|
slidge/core/session.py
CHANGED
@@ -33,7 +33,7 @@ from ..util.types import (
|
|
33
33
|
ResourceDict,
|
34
34
|
Sticker,
|
35
35
|
)
|
36
|
-
from ..util.util import deprecated
|
36
|
+
from ..util.util import deprecated, noop_coro
|
37
37
|
|
38
38
|
if TYPE_CHECKING:
|
39
39
|
from ..group.participant import LegacyParticipant
|
@@ -98,6 +98,7 @@ class BaseSession(
|
|
98
98
|
self.ignore_messages = set[str]()
|
99
99
|
|
100
100
|
self.contacts: LegacyRoster = LegacyRoster.get_self_or_unique_subclass()(self)
|
101
|
+
self.is_logging_in = False
|
101
102
|
self._logged = False
|
102
103
|
self.__reset_ready()
|
103
104
|
|
@@ -527,11 +528,13 @@ class BaseSession(
|
|
527
528
|
|
528
529
|
@logged.setter
|
529
530
|
def logged(self, v: bool):
|
531
|
+
self.is_logging_in = False
|
530
532
|
self._logged = v
|
531
533
|
if self.ready.done():
|
532
534
|
if v:
|
533
535
|
return
|
534
536
|
self.__reset_ready()
|
537
|
+
self.shutdown(logout=False)
|
535
538
|
else:
|
536
539
|
if v:
|
537
540
|
self.ready.set_result(True)
|
@@ -539,12 +542,15 @@ class BaseSession(
|
|
539
542
|
def __repr__(self):
|
540
543
|
return f"<Session of {self.user_jid}>"
|
541
544
|
|
542
|
-
def shutdown(self) -> asyncio.Task:
|
545
|
+
def shutdown(self, logout=True) -> asyncio.Task:
|
543
546
|
for c in self.contacts:
|
544
547
|
c.offline()
|
545
548
|
for m in self.bookmarks:
|
546
549
|
m.shutdown()
|
547
|
-
|
550
|
+
if logout:
|
551
|
+
return self.xmpp.loop.create_task(self.logout())
|
552
|
+
else:
|
553
|
+
return self.xmpp.loop.create_task(noop_coro())
|
548
554
|
|
549
555
|
@staticmethod
|
550
556
|
def legacy_to_xmpp_msg_id(legacy_msg_id: LegacyMessageType) -> str:
|
@@ -657,6 +663,8 @@ class BaseSession(
|
|
657
663
|
return
|
658
664
|
for c in session.contacts:
|
659
665
|
c.unsubscribe()
|
666
|
+
for m in session.bookmarks:
|
667
|
+
m.shutdown()
|
660
668
|
user = cls.xmpp.store.users.get(jid)
|
661
669
|
if user is None:
|
662
670
|
log.warning("User not found during unregistration")
|
@@ -0,0 +1,33 @@
|
|
1
|
+
"""Add Participant.nickname_no_illegal
|
2
|
+
|
3
|
+
Revision ID: 04cf35e3cf85
|
4
|
+
Revises: 15b0bd83407a
|
5
|
+
Create Date: 2025-02-22 06:57:45.491326
|
6
|
+
|
7
|
+
"""
|
8
|
+
|
9
|
+
from typing import Sequence, Union
|
10
|
+
|
11
|
+
import sqlalchemy as sa
|
12
|
+
from alembic import op
|
13
|
+
|
14
|
+
# revision identifiers, used by Alembic.
|
15
|
+
revision: str = "04cf35e3cf85"
|
16
|
+
down_revision: Union[str, None] = "15b0bd83407a"
|
17
|
+
branch_labels: Union[str, Sequence[str], None] = None
|
18
|
+
depends_on: Union[str, Sequence[str], None] = None
|
19
|
+
|
20
|
+
|
21
|
+
def upgrade() -> None:
|
22
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
23
|
+
with op.batch_alter_table("participant", schema=None) as batch_op:
|
24
|
+
batch_op.add_column(
|
25
|
+
sa.Column("nickname_no_illegal", sa.String(), nullable=True)
|
26
|
+
)
|
27
|
+
|
28
|
+
# ### end Alembic commands ###
|
29
|
+
|
30
|
+
|
31
|
+
def downgrade() -> None:
|
32
|
+
with op.batch_alter_table("participant", schema=None) as batch_op:
|
33
|
+
batch_op.drop_column("nickname_no_illegal")
|
@@ -8,8 +8,6 @@ Create Date: 2024-04-17 20:57:01.357041
|
|
8
8
|
|
9
9
|
"""
|
10
10
|
|
11
|
-
import logging
|
12
|
-
from datetime import datetime
|
13
11
|
from typing import Sequence, Union
|
14
12
|
|
15
13
|
import sqlalchemy as sa
|
@@ -44,58 +42,9 @@ def upgrade() -> None:
|
|
44
42
|
sa.UniqueConstraint("jid"),
|
45
43
|
)
|
46
44
|
# ### end Alembic commands ###
|
47
|
-
try:
|
48
|
-
migrate_from_shelf(accounts)
|
49
|
-
except Exception:
|
50
|
-
downgrade()
|
51
|
-
raise
|
52
45
|
|
53
46
|
|
54
47
|
def downgrade() -> None:
|
55
48
|
# ### commands auto generated by Alembic - please adjust! ###
|
56
49
|
op.drop_table("user_account")
|
57
50
|
# ### end Alembic commands ###
|
58
|
-
|
59
|
-
|
60
|
-
def migrate_from_shelf(accounts: sa.Table) -> None:
|
61
|
-
from slidge import global_config
|
62
|
-
|
63
|
-
home = getattr(global_config, "HOME_DIR", None)
|
64
|
-
if home is None:
|
65
|
-
return
|
66
|
-
|
67
|
-
db_file = home / "slidge.db"
|
68
|
-
if not db_file.exists():
|
69
|
-
return
|
70
|
-
|
71
|
-
try:
|
72
|
-
from slidge.db.alembic.old_user_store import user_store
|
73
|
-
except ImportError:
|
74
|
-
return
|
75
|
-
|
76
|
-
user_store.set_file(db_file, global_config.SECRET_KEY)
|
77
|
-
|
78
|
-
try:
|
79
|
-
users = list(user_store.get_all())
|
80
|
-
except AttributeError:
|
81
|
-
return
|
82
|
-
logging.info("Migrating %s users from the deprecated user_store shelf", len(users))
|
83
|
-
op.bulk_insert(
|
84
|
-
accounts,
|
85
|
-
[
|
86
|
-
{
|
87
|
-
"jid": user.jid,
|
88
|
-
"registration_date": (
|
89
|
-
user.registration_date
|
90
|
-
if user.registration_date is not None
|
91
|
-
else datetime.now()
|
92
|
-
),
|
93
|
-
"legacy_module_data": user.registration_form,
|
94
|
-
"preferences": {},
|
95
|
-
}
|
96
|
-
for user in users
|
97
|
-
],
|
98
|
-
)
|
99
|
-
|
100
|
-
user_store.close()
|
101
|
-
db_file.unlink()
|
slidge/db/models.py
CHANGED
@@ -388,6 +388,7 @@ class Participant(Base):
|
|
388
388
|
|
389
389
|
resource: Mapped[Optional[str]] = mapped_column(default=None)
|
390
390
|
nickname: Mapped[str] = mapped_column(nullable=True, default=None)
|
391
|
+
nickname_no_illegal: Mapped[str] = mapped_column(nullable=True, default=None)
|
391
392
|
|
392
393
|
hats: Mapped[list["Hat"]] = relationship(
|
393
394
|
secondary=participant_hats, back_populates="participants"
|
slidge/db/store.py
CHANGED
@@ -698,6 +698,8 @@ class MultiStore(EngineMixin):
|
|
698
698
|
).scalar()
|
699
699
|
if multi is None:
|
700
700
|
return []
|
701
|
+
if multi.legacy_ids_multi is None:
|
702
|
+
return []
|
701
703
|
return [m.xmpp_id for m in multi.legacy_ids_multi.xmpp_ids]
|
702
704
|
|
703
705
|
def set_xmpp_ids(
|
@@ -1072,6 +1074,7 @@ class ParticipantStore(EngineMixin):
|
|
1072
1074
|
.where(Participant.id == participant.pk)
|
1073
1075
|
.values(
|
1074
1076
|
resource=participant.jid.resource,
|
1077
|
+
nickname_no_illegal=participant._nickname_no_illegal,
|
1075
1078
|
affiliation=participant.affiliation,
|
1076
1079
|
role=participant.role,
|
1077
1080
|
presence_sent=participant._presence_sent, # type:ignore
|
slidge/group/participant.py
CHANGED
@@ -71,6 +71,7 @@ class LegacyParticipant(
|
|
71
71
|
role: MucRole = "participant",
|
72
72
|
affiliation: MucAffiliation = "member",
|
73
73
|
resource: str | None = None,
|
74
|
+
nickname_no_illegal: str | None = None,
|
74
75
|
):
|
75
76
|
self.session = session = muc.session
|
76
77
|
self.xmpp = session.xmpp
|
@@ -87,7 +88,8 @@ class LegacyParticipant(
|
|
87
88
|
if resource is None:
|
88
89
|
self.__update_jid(nickname)
|
89
90
|
else:
|
90
|
-
|
91
|
+
assert nickname_no_illegal is not None
|
92
|
+
self._nickname_no_illegal = nickname_no_illegal
|
91
93
|
self.jid = JID(self.muc.jid)
|
92
94
|
self.jid.resource = resource
|
93
95
|
|
@@ -518,6 +520,7 @@ class LegacyParticipant(
|
|
518
520
|
role=stored.role,
|
519
521
|
affiliation=stored.affiliation,
|
520
522
|
resource=stored.resource,
|
523
|
+
nickname_no_illegal=stored.nickname_no_illegal,
|
521
524
|
)
|
522
525
|
part.pk = stored.id
|
523
526
|
if contact is not None:
|
slidge/group/room.py
CHANGED
@@ -423,7 +423,7 @@ class LegacyMUC(
|
|
423
423
|
|
424
424
|
if subject_setter == self._subject_setter:
|
425
425
|
return
|
426
|
-
assert isinstance(subject_setter, str)
|
426
|
+
assert isinstance(subject_setter, str | None)
|
427
427
|
self._subject_setter = subject_setter
|
428
428
|
if self._updating_info:
|
429
429
|
return
|
slidge/slixfix/__init__.py
CHANGED
@@ -20,7 +20,6 @@ from . import (
|
|
20
20
|
xep_0100,
|
21
21
|
xep_0153,
|
22
22
|
xep_0292,
|
23
|
-
xep_0356_old,
|
24
23
|
xep_0492,
|
25
24
|
)
|
26
25
|
|
@@ -148,7 +147,6 @@ slixmpp.plugins.PLUGINS.extend(
|
|
148
147
|
[
|
149
148
|
"link_preview",
|
150
149
|
"xep_0292_provider",
|
151
|
-
"xep_0356_old",
|
152
150
|
"xep_0492",
|
153
151
|
]
|
154
152
|
)
|
@@ -93,10 +93,7 @@ class XEP_0100(BasePlugin):
|
|
93
93
|
self.xmpp.send_presence(ptype="subscribe", pto=jid.bare)
|
94
94
|
|
95
95
|
async def _set_roster(self, jid, items):
|
96
|
-
|
97
|
-
await self.xmpp["xep_0356"].set_roster(jid=jid.bare, roster_items=items)
|
98
|
-
except PermissionError:
|
99
|
-
await self.xmpp["xep_0356_old"].set_roster(jid=jid.bare, roster_items=items)
|
96
|
+
await self.xmpp["xep_0356"].set_roster(jid=jid.bare, roster_items=items)
|
100
97
|
|
101
98
|
def on_presence_unsubscribe(self, p: Presence):
|
102
99
|
if p.get_to() == self.xmpp.boundjid.bare:
|
slidge/util/util.py
CHANGED
@@ -321,7 +321,7 @@ def timeit(func):
|
|
321
321
|
async def wrapped(self, *args, **kwargs):
|
322
322
|
start = time()
|
323
323
|
r = await func(self, *args, **kwargs)
|
324
|
-
self.log.
|
324
|
+
self.log.debug("%s took %s ms", func.__name__, round((time() - start) * 1000))
|
325
325
|
return r
|
326
326
|
|
327
327
|
return wrapped
|
@@ -336,3 +336,7 @@ def strip_leading_emoji(text: str) -> str:
|
|
336
336
|
if len(words) > 1 and emoji.purely_emoji(words[0]):
|
337
337
|
return " ".join(words[1:])
|
338
338
|
return text
|
339
|
+
|
340
|
+
|
341
|
+
async def noop_coro():
|
342
|
+
pass
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: slidge
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.6
|
4
4
|
Summary: XMPP bridging framework
|
5
5
|
Author-email: Nicolas Cedilnik <nicoco@nicoco.fr>
|
6
6
|
License: GNU AFFERO GENERAL PUBLIC LICENSE
|
@@ -676,16 +676,15 @@ Classifier: Topic :: Internet :: XMPP
|
|
676
676
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
677
677
|
Requires-Python: >=3.11
|
678
678
|
Description-Content-Type: text/markdown
|
679
|
-
Requires-Dist: aiohttp[speedups]
|
680
|
-
Requires-Dist: alembic
|
681
|
-
Requires-Dist: configargparse
|
679
|
+
Requires-Dist: aiohttp[speedups]<4,>=3.11.11
|
680
|
+
Requires-Dist: alembic<2,>=1.14.0
|
681
|
+
Requires-Dist: configargparse<2,>=1.7
|
682
682
|
Requires-Dist: defusedxml>=0.7.1
|
683
|
-
Requires-Dist:
|
684
|
-
Requires-Dist:
|
685
|
-
Requires-Dist:
|
686
|
-
Requires-Dist:
|
687
|
-
Requires-Dist:
|
688
|
-
Requires-Dist: sqlalchemy>=2.0.36
|
683
|
+
Requires-Dist: pillow<12,>=11.0.0
|
684
|
+
Requires-Dist: python-magic<0.5,>=0.4.27
|
685
|
+
Requires-Dist: qrcode<9,>=8.0
|
686
|
+
Requires-Dist: slixmpp<2,>=1.8.6
|
687
|
+
Requires-Dist: sqlalchemy<3,>=2
|
689
688
|
Requires-Dist: thumbhash>=0.1.2
|
690
689
|
|
691
690
|

|
@@ -1,25 +1,25 @@
|
|
1
1
|
slidge/__init__.py,sha256=S0tUjqpZlzsr8G4Y_1Xt-KCYB07qaknTB0OwHU8k29U,1587
|
2
2
|
slidge/__main__.py,sha256=ydjUklOoavS4YlGfjRX_8BQN2DaSbaXPMi47RkOgcFI,37
|
3
|
-
slidge/__version__.py,sha256=
|
3
|
+
slidge/__version__.py,sha256=LukT7r82VsYYhRUhnpDW_6t1xNzuYY3v380h-wU8KCg,165
|
4
4
|
slidge/main.py,sha256=vMJzhvUxbeuIXuHxXXs6lm_ShBjXiS9B5Li5Ge4vWPo,6238
|
5
5
|
slidge/migration.py,sha256=4BJmPIRB56_WIhRTqBFIIBXuvnhhBjjOMl4CE7jY6oc,1541
|
6
6
|
slidge/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
7
|
slidge/command/__init__.py,sha256=UYf1mjCYbZ5G7PIgaFTWSQRAzEJkQ6dTH8Fu_e_XnO0,613
|
8
|
-
slidge/command/adhoc.py,sha256
|
8
|
+
slidge/command/adhoc.py,sha256=FEkE5UapIP_yrmrzGn5yIHCubOZijoI_muu1AtCqGOM,10472
|
9
9
|
slidge/command/admin.py,sha256=TYrzgCIhjcTIwl1IUaFlUd3D98SPyao10gB20zo8b3Q,6187
|
10
10
|
slidge/command/base.py,sha256=EDcEl5dJcooSmLarXI2fmBq6QtU7h-7MOM3DDsxXmTU,13447
|
11
11
|
slidge/command/categories.py,sha256=vF0KGDV9sEn8TNkcMoDRw-u3gEyNHSXghOU2JRHQtKs,351
|
12
12
|
slidge/command/chat_command.py,sha256=z-4qp03rK7kCh3_kEozDViwkDg_hVjHvRCiYYJxedBQ,11153
|
13
13
|
slidge/command/register.py,sha256=BduDI31Kx8CbWWEdjybimTA5Wcfhn-Jkt8sSPsySCpo,6724
|
14
|
-
slidge/command/user.py,sha256=
|
14
|
+
slidge/command/user.py,sha256=fLh5d7XTSXicj6g0I80F5n6BFaA20PaYoXFkfDOR4zA,12303
|
15
15
|
slidge/contact/__init__.py,sha256=WMMaHk7UW7YT9EH2LtPdkU0bHQaOp4ikBhbBQskmoc8,191
|
16
|
-
slidge/contact/contact.py,sha256=
|
16
|
+
slidge/contact/contact.py,sha256=ITcjW_3VMdVEHQfqxscpIULnofZBJ841wvnYwOvk1Tc,22934
|
17
17
|
slidge/contact/roster.py,sha256=x3speGdHbZ-VTLoQLQW4s53rBeBvW87W8ZibCCZSLDA,10300
|
18
18
|
slidge/core/__init__.py,sha256=RG7Jj5JCJERjhqJ31lOLYV-7bH_oblClQD1KF9LsTXo,68
|
19
|
-
slidge/core/config.py,sha256=
|
20
|
-
slidge/core/gateway.py,sha256=
|
19
|
+
slidge/core/config.py,sha256=OjJfpXJaDhMxRB-vYA0cqkSf0fwMt-HMThM8GS1htCg,7964
|
20
|
+
slidge/core/gateway.py,sha256=qdvLGh5GF823mACVw5j1WLYMzsSmeGpmQFuWvz5Z9AU,37028
|
21
21
|
slidge/core/pubsub.py,sha256=BoeYE__ptmRAn4x55Hn_6JWRA4nM-XJgDemG5Cy5kN4,11959
|
22
|
-
slidge/core/session.py,sha256=
|
22
|
+
slidge/core/session.py,sha256=Y6psOKm_lv4q7yXARiLuijvSebuS64NjqSNF1WARtHM,28439
|
23
23
|
slidge/core/dispatcher/__init__.py,sha256=1EXcjXietUKlxEqdrCWCV3xZ3q_DSsjHoqWrPMbtYao,84
|
24
24
|
slidge/core/dispatcher/caps.py,sha256=vzCAXo_bhALuLEpJWtyJTzVfWx96g1AsWD8_wkoDl0Y,2028
|
25
25
|
slidge/core/dispatcher/disco.py,sha256=j56VY9NIFzwPEWFKQQZ7YIqS9GdD-ZaF_K8a2L-JvRk,2006
|
@@ -46,7 +46,7 @@ slidge/core/mixins/base.py,sha256=MOd-pas38_52VawQVlxWtBtmTKC6My9G0ZaCeQxOJbs,74
|
|
46
46
|
slidge/core/mixins/db.py,sha256=5Qpegd7D8e5TLXLLINYcf_DuVdN-7wNmsfztUuFYPcU,442
|
47
47
|
slidge/core/mixins/disco.py,sha256=jk3Z1B6zTuisHv8VKNRJodIo0ee5btYHh2ZrlflPj_Q,3670
|
48
48
|
slidge/core/mixins/lock.py,sha256=Vf1rrkbyNbSprr38WGfZiMgTB7AdbqH8ppFHY8N2yXE,975
|
49
|
-
slidge/core/mixins/message.py,sha256=
|
49
|
+
slidge/core/mixins/message.py,sha256=X8Ka8j0nOnBcecYE_YuK8_J7MeO5-R0TIZw4X8c7R3Y,7846
|
50
50
|
slidge/core/mixins/message_maker.py,sha256=TcCutHi0sIwL6beJNkN7XyR0aDIbA0xZyxd2Gc9ulG4,6022
|
51
51
|
slidge/core/mixins/message_text.py,sha256=pCY4tezEuwB2ZuUyUi72i4v9AJkxp_SWF1jrFsn94Ns,8096
|
52
52
|
slidge/core/mixins/presence.py,sha256=yywo6KAw8C7GaZSMrSMuioNfhW08MrnobHt8XbHd0q8,7891
|
@@ -54,12 +54,12 @@ slidge/core/mixins/recipient.py,sha256=b0uFnpym-hOFgYxGjXT1xQcZ4YRbDSBftPcNWLzSw
|
|
54
54
|
slidge/db/__init__.py,sha256=EBDH1JSEhgqYcli2Bw11CRC749wJk8AOucgBzmhDSvU,105
|
55
55
|
slidge/db/avatar.py,sha256=z5e72STv8PdN6zkNyKlLqF7NFxHwCa6IjwgFpzu5ghE,8033
|
56
56
|
slidge/db/meta.py,sha256=v1Jf-npZ28QwdGpsLQWLBHEbEP3-jnPrygRg05tJ_Iw,1831
|
57
|
-
slidge/db/models.py,sha256=
|
58
|
-
slidge/db/store.py,sha256=
|
57
|
+
slidge/db/models.py,sha256=MSVNW04x05qfxahvjCYRDFjfFP-XXp-lOHnK5IqFCXw,14046
|
58
|
+
slidge/db/store.py,sha256=ETk6oUUEz8-YUFGCh7nspSJH7dFOj8qeIWLQhX4nOH8,47051
|
59
59
|
slidge/db/alembic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
60
60
|
slidge/db/alembic/env.py,sha256=hsBlRNs0zF5diSHGRSa8Fi3qRVQDA2rJdR41AEIdvxc,1642
|
61
|
-
slidge/db/alembic/old_user_store.py,sha256=zFOv0JEWQQK0_TMRlU4Z0G5Mc9pxvEErLyOzXmRAe5Q,5209
|
62
61
|
slidge/db/alembic/script.py.mako,sha256=MEqL-2qATlST9TAOeYgscMn1uy6HUS9NFvDgl93dMj8,635
|
62
|
+
slidge/db/alembic/versions/04cf35e3cf85_add_participant_nickname_no_illegal.py,sha256=Dwz_azOXr7Tsw7Wnj0L8mknITIPXO9ewEsRn169EUNA,904
|
63
63
|
slidge/db/alembic/versions/09f27f098baa_add_missing_attributes_in_room.py,sha256=mUL-0Io6ZPd_QbnKfwGYyjdMcM2uxQ0Wg72H23-2t_E,1033
|
64
64
|
slidge/db/alembic/versions/15b0bd83407a_remove_bogus_unique_constraints_on_room_.py,sha256=kzHuHGhzey5CY0p_OsKf5a-3zSk2649wqg2ToLiSD1I,2927
|
65
65
|
slidge/db/alembic/versions/2461390c0af2_store_contacts_caps_verstring_in_db.py,sha256=CLB-kOP9Rc0FJIKDLef912L5sYkjpTIPC8fhrIdrC7k,1084
|
@@ -71,7 +71,7 @@ slidge/db/alembic/versions/5bd48bfdffa2_lift_room_legacy_id_constraint.py,sha256
|
|
71
71
|
slidge/db/alembic/versions/82a4af84b679_add_muc_history_filled.py,sha256=g37po0ydp8ZmzJrE5oFV7GscnploxjCtPDpw28SqVGk,1429
|
72
72
|
slidge/db/alembic/versions/8b993243a536_add_vcard_content_to_contact_table.py,sha256=18tG8B03Kq8Qz_-mMd28Beed6jow8XNTtrz7gT5QY3g,1210
|
73
73
|
slidge/db/alembic/versions/8d2ced764698_rely_on_db_to_store_contacts_rooms_and_.py,sha256=ikoAlRV3_BJcDcFRANF-9HTB--0xpY0C5XdGuMuW9c0,4866
|
74
|
-
slidge/db/alembic/versions/aa9d82a7f6ef_db_creation.py,sha256=
|
74
|
+
slidge/db/alembic/versions/aa9d82a7f6ef_db_creation.py,sha256=eFlfn-LiDph05yyCc8gmtJwVKzgrSHwyWJ6nuVfEpQA,1391
|
75
75
|
slidge/db/alembic/versions/abba1ae0edb3_store_avatar_legacy_id_in_the_contact_.py,sha256=VprqEVHipYuM-ea-CIM4_ubOD5zJ9inLTbhXc869n3A,2779
|
76
76
|
slidge/db/alembic/versions/b33993e87db3_move_everything_to_persistent_db.py,sha256=2tiRxoC9PYOQn6XQrwK0JTEsb45Pzp2PsKoZSS4rcIA,7564
|
77
77
|
slidge/db/alembic/versions/b64b1a793483_add_source_and_legacy_id_for_archived_.py,sha256=r2sOgR5HcfueJyc3cWNDRmlZzdHOSX6nl2gef54wDbk,1559
|
@@ -80,9 +80,9 @@ slidge/db/alembic/versions/e91195719c2c_store_users_avatars_persistently.py,sha2
|
|
80
80
|
slidge/group/__init__.py,sha256=yFt7cHqeaKIMN6f9ZyhhspOcJJvBtLedGv-iICG7lto,258
|
81
81
|
slidge/group/archive.py,sha256=IPqklzo0UN3lPHckfsKW9c4nl3m_9XGY4u0eehrhe8k,5281
|
82
82
|
slidge/group/bookmarks.py,sha256=AvFL34bEX6n3OP1Np309T5hrLK9GnjkjdyLJ3uiLZyc,6616
|
83
|
-
slidge/group/participant.py,sha256=
|
84
|
-
slidge/group/room.py,sha256=
|
85
|
-
slidge/slixfix/__init__.py,sha256=
|
83
|
+
slidge/group/participant.py,sha256=cUuyJRGq8AIHrwtubje5cyb5hHY2hGLtGboBju4SI0c,17781
|
84
|
+
slidge/group/room.py,sha256=Ar7mSSZRqjDPaXtRuq1da-ZqdJ-fibVtEZDcfpZtpXY,46856
|
85
|
+
slidge/slixfix/__init__.py,sha256=Og6_EAuWst6paWmDiGqeqQH6Iof6V8Vkr5pyYisgjsw,4282
|
86
86
|
slidge/slixfix/delivery_receipt.py,sha256=3bWdZH3-X3CZJXmnI_TpjkTUUK-EY4Ktm78lW0-40fc,1366
|
87
87
|
slidge/slixfix/roster.py,sha256=KvDjh9q7pqaZf69H93okfib13cc95uVZUJ6rzpqmDaU,1704
|
88
88
|
slidge/slixfix/link_preview/__init__.py,sha256=TDPTSEH5FQxgGpQpQIde-D72AHg-6YVWG-tOj4KpKmU,290
|
@@ -92,27 +92,23 @@ slidge/slixfix/xep_0077/__init__.py,sha256=0lY1YXdgAsfrfxI_Woxaf1etHCJXe35Xtntq_
|
|
92
92
|
slidge/slixfix/xep_0077/register.py,sha256=6nwTfHNL7Z9-1wUhpAF743TNbjQLCMP7Rflkdad8d60,10431
|
93
93
|
slidge/slixfix/xep_0077/stanza.py,sha256=Lngly7F1ChCkNKn7yl1QmN838fO-KqkAhkazxzDsz80,2410
|
94
94
|
slidge/slixfix/xep_0100/__init__.py,sha256=AtEXDQOrEWodkN3fgKR0W3Ezsz_Zza6cgO5ZaZS-JOo,107
|
95
|
-
slidge/slixfix/xep_0100/gateway.py,sha256=
|
95
|
+
slidge/slixfix/xep_0100/gateway.py,sha256=aSR18605MWVqgucNd_zd1SdYlXry7k5uoqDzsvVqQyM,4363
|
96
96
|
slidge/slixfix/xep_0100/stanza.py,sha256=7vCzej9VFQupsTpGGl0cJWuGNH4I6oVcckBu_-fE55c,232
|
97
97
|
slidge/slixfix/xep_0153/__init__.py,sha256=hsEldnLuzvcp0NqSscxPV7FJl-6GFP372vlDg1G3S3I,283
|
98
98
|
slidge/slixfix/xep_0153/vcard_avatar.py,sha256=py-qzj1jmmzsM4GCTKLRW7cAdAmSVjodp6q0r5B0RqQ,458
|
99
99
|
slidge/slixfix/xep_0292/__init__.py,sha256=_MvS9wGra6ig3P_dPAVlCPDJkiOFvUWGjaRsHj1woUg,98
|
100
100
|
slidge/slixfix/xep_0292/vcard4.py,sha256=jL-TOW3eG2QXLduSLNq03L8HoUNmvy8kTZI5ojvo6GE,358
|
101
|
-
slidge/slixfix/xep_0356_old/__init__.py,sha256=3jGWJX2m5gWgDCxcVqCsCCVPRTcfmU96yenwvAJtOKE,180
|
102
|
-
slidge/slixfix/xep_0356_old/privilege.py,sha256=kcJzFbzhOHtQMtzOJpvvwm1pghSpealWnqhC0zc8dGo,5338
|
103
|
-
slidge/slixfix/xep_0356_old/stanza.py,sha256=i7aqcaTg6PBhVwbHToLtlrwxBj7uO-M7VrYSyElyEKI,1229
|
104
101
|
slidge/slixfix/xep_0492/__init__.py,sha256=kjWVeX3SG_2ohHx0fuMh1gmM2G57Bl6SRo7Mfv6sglA,161
|
105
102
|
slidge/slixfix/xep_0492/notify.py,sha256=8EPSdU3rTzWkHNm8oFr0tK2PmMJ6hBAIr88GoOmHTuQ,340
|
106
103
|
slidge/slixfix/xep_0492/stanza.py,sha256=gL0ixpV07Q9eqTXIOjdLVPtim45izuwaLk0iCoZ8e7c,2649
|
107
104
|
slidge/util/__init__.py,sha256=BELovoTMPcPPGz3D48esBr8A4BRRHXTvavfgnArBgEc,301
|
108
105
|
slidge/util/archive_msg.py,sha256=xXAR0BI5r3d6KKWjae9594izCOv6iI03z2WLuTecNw8,1724
|
109
106
|
slidge/util/conf.py,sha256=1j2OnOsCBar1tOObErhXR5RC3Vl3faliOZ1U8J3My58,6613
|
110
|
-
slidge/util/db.py,sha256=4LxZj8oBYgiSnyBUnF_ALjr0TblkfNQq_p28sCfkHMY,242
|
111
107
|
slidge/util/test.py,sha256=l1VHBsw5Uzk2t7wtkfb9kWvtehcYhw1t_d567JAJFKA,14135
|
112
108
|
slidge/util/types.py,sha256=R_xfS5mRL0XUJIoDpnaAkZlTOoLPerduXBFftaVwIAI,5489
|
113
|
-
slidge/util/util.py,sha256=
|
114
|
-
slidge-0.2.
|
115
|
-
slidge-0.2.
|
116
|
-
slidge-0.2.
|
117
|
-
slidge-0.2.
|
118
|
-
slidge-0.2.
|
109
|
+
slidge/util/util.py,sha256=4GdRZwHYUPkteEi8oux--qLwMiXnVLl_ojMDaKbEQCE,9629
|
110
|
+
slidge-0.2.6.dist-info/METADATA,sha256=ShWfovgJtP9yPJYaEZqHg0Rd62blhfP78go2AsRfeoM,44841
|
111
|
+
slidge-0.2.6.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
112
|
+
slidge-0.2.6.dist-info/entry_points.txt,sha256=py3_x834fFJ2TEzPd18Wt2DnysdAfuVqJ5zzBrXbAZs,44
|
113
|
+
slidge-0.2.6.dist-info/top_level.txt,sha256=2LRjDYHaGZ5ieCMF8xy58JIiabRMzX-MGMbCZwfE17c,7
|
114
|
+
slidge-0.2.6.dist-info/RECORD,,
|
@@ -1,183 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
This module covers a backend for storing user data persistently and managing a
|
3
|
-
pseudo-roster for the gateway component.
|
4
|
-
"""
|
5
|
-
|
6
|
-
import dataclasses
|
7
|
-
import datetime
|
8
|
-
import logging
|
9
|
-
import os.path
|
10
|
-
import shelve
|
11
|
-
from io import BytesIO
|
12
|
-
from os import PathLike
|
13
|
-
from typing import Iterable, Optional, Union
|
14
|
-
|
15
|
-
from pickle_secure import Pickler, Unpickler
|
16
|
-
from slixmpp import JID, Iq, Message, Presence
|
17
|
-
|
18
|
-
|
19
|
-
# noinspection PyUnresolvedReferences
|
20
|
-
class EncryptedShelf(shelve.DbfilenameShelf):
|
21
|
-
cache: dict
|
22
|
-
dict: dict
|
23
|
-
writeback: bool
|
24
|
-
keyencoding: str
|
25
|
-
_protocol: int
|
26
|
-
|
27
|
-
def __init__(
|
28
|
-
self, filename: PathLike, key: str, flag="c", protocol=None, writeback=False
|
29
|
-
):
|
30
|
-
super().__init__(str(filename), flag, protocol, writeback)
|
31
|
-
self.secret_key = key
|
32
|
-
|
33
|
-
def __getitem__(self, key):
|
34
|
-
try:
|
35
|
-
value = self.cache[key]
|
36
|
-
except KeyError:
|
37
|
-
f = BytesIO(self.dict[key.encode(self.keyencoding)])
|
38
|
-
value = Unpickler(f, key=self.secret_key).load() # type:ignore
|
39
|
-
if self.writeback:
|
40
|
-
self.cache[key] = value
|
41
|
-
return value
|
42
|
-
|
43
|
-
def __setitem__(self, key, value):
|
44
|
-
if self.writeback:
|
45
|
-
self.cache[key] = value
|
46
|
-
f = BytesIO()
|
47
|
-
p = Pickler(f, self._protocol, key=self.secret_key) # type:ignore
|
48
|
-
p.dump(value)
|
49
|
-
self.dict[key.encode(self.keyencoding)] = f.getvalue()
|
50
|
-
|
51
|
-
|
52
|
-
@dataclasses.dataclass
|
53
|
-
class GatewayUser:
|
54
|
-
"""
|
55
|
-
A gateway user
|
56
|
-
"""
|
57
|
-
|
58
|
-
bare_jid: str
|
59
|
-
"""Bare JID of the user"""
|
60
|
-
registration_form: dict[str, Optional[str]]
|
61
|
-
"""Content of the registration form, as a dict"""
|
62
|
-
plugin_data: Optional[dict] = None
|
63
|
-
registration_date: Optional[datetime.datetime] = None
|
64
|
-
|
65
|
-
def __hash__(self):
|
66
|
-
return hash(self.bare_jid)
|
67
|
-
|
68
|
-
def __repr__(self):
|
69
|
-
return f"<User {self.bare_jid}>"
|
70
|
-
|
71
|
-
def __post_init__(self):
|
72
|
-
if self.registration_date is None:
|
73
|
-
self.registration_date = datetime.datetime.now()
|
74
|
-
|
75
|
-
@property
|
76
|
-
def jid(self) -> JID:
|
77
|
-
"""
|
78
|
-
The user's (bare) JID
|
79
|
-
|
80
|
-
:return:
|
81
|
-
"""
|
82
|
-
return JID(self.bare_jid)
|
83
|
-
|
84
|
-
def get(self, field: str, default: str = "") -> Optional[str]:
|
85
|
-
# """
|
86
|
-
# Get fields from the registration form (required to comply with slixmpp backend protocol)
|
87
|
-
#
|
88
|
-
# :param field: Name of the field
|
89
|
-
# :param default: Default value to return if the field is not present
|
90
|
-
#
|
91
|
-
# :return: Value of the field
|
92
|
-
# """
|
93
|
-
return self.registration_form.get(field, default)
|
94
|
-
|
95
|
-
|
96
|
-
class UserStore:
|
97
|
-
"""
|
98
|
-
Basic user store implementation using shelve from the python standard library
|
99
|
-
|
100
|
-
Set_file must be called before it is usable
|
101
|
-
"""
|
102
|
-
|
103
|
-
def __init__(self):
|
104
|
-
self._users: shelve.Shelf[GatewayUser] = None # type: ignore
|
105
|
-
|
106
|
-
def set_file(self, filename: PathLike, secret_key: Optional[str] = None):
|
107
|
-
"""
|
108
|
-
Set the file to use to store user data
|
109
|
-
|
110
|
-
:param filename: Path to the shelf file
|
111
|
-
:param secret_key: Secret key to store files encrypted on disk
|
112
|
-
"""
|
113
|
-
if self._users is not None:
|
114
|
-
raise RuntimeError("Shelf file already set!")
|
115
|
-
if os.path.exists(filename):
|
116
|
-
log.info("Using existing slidge DB: %s", filename)
|
117
|
-
else:
|
118
|
-
log.info("Creating a new slidge DB: %s", filename)
|
119
|
-
if secret_key:
|
120
|
-
self._users = EncryptedShelf(filename, key=secret_key)
|
121
|
-
else:
|
122
|
-
self._users = shelve.open(str(filename))
|
123
|
-
log.info("Registered users in the DB: %s", list(self._users.keys()))
|
124
|
-
|
125
|
-
def get_all(self) -> Iterable[GatewayUser]:
|
126
|
-
"""
|
127
|
-
Get all users in the store
|
128
|
-
|
129
|
-
:return: An iterable of GatewayUsers
|
130
|
-
"""
|
131
|
-
return self._users.values()
|
132
|
-
|
133
|
-
def commit(self, user: GatewayUser):
|
134
|
-
self._users[user.jid.bare] = user
|
135
|
-
self._users.sync()
|
136
|
-
|
137
|
-
def get(self, _gateway_jid, _node, ifrom: JID, iq) -> Optional[GatewayUser]:
|
138
|
-
"""
|
139
|
-
Get a user from the store
|
140
|
-
|
141
|
-
NB: there is no reason to call this, it is used by SliXMPP internal API
|
142
|
-
|
143
|
-
:param _gateway_jid:
|
144
|
-
:param _node:
|
145
|
-
:param ifrom:
|
146
|
-
:param iq:
|
147
|
-
:return:
|
148
|
-
"""
|
149
|
-
if ifrom is None: # bug in SliXMPP's XEP_0100 plugin
|
150
|
-
ifrom = iq["from"]
|
151
|
-
log.debug("Getting user %s", ifrom.bare)
|
152
|
-
return self._users.get(ifrom.bare)
|
153
|
-
|
154
|
-
def get_by_jid(self, jid: JID) -> Optional[GatewayUser]:
|
155
|
-
"""
|
156
|
-
Convenience function to get a user from their JID.
|
157
|
-
|
158
|
-
:param jid: JID of the gateway user
|
159
|
-
:return:
|
160
|
-
"""
|
161
|
-
return self._users.get(jid.bare)
|
162
|
-
|
163
|
-
def get_by_stanza(self, s: Union[Presence, Message, Iq]) -> Optional[GatewayUser]:
|
164
|
-
"""
|
165
|
-
Convenience function to get a user from a stanza they sent.
|
166
|
-
|
167
|
-
:param s: A stanza sent by the gateway user
|
168
|
-
:return:
|
169
|
-
"""
|
170
|
-
return self.get_by_jid(s.get_from())
|
171
|
-
|
172
|
-
def close(self):
|
173
|
-
self._users.sync()
|
174
|
-
self._users.close()
|
175
|
-
|
176
|
-
|
177
|
-
user_store = UserStore()
|
178
|
-
"""
|
179
|
-
A persistent store for slidge users. Not public, but I didn't find how to hide
|
180
|
-
it from the docs!
|
181
|
-
"""
|
182
|
-
|
183
|
-
log = logging.getLogger(__name__)
|
@@ -1,167 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
import typing
|
3
|
-
from collections import defaultdict
|
4
|
-
|
5
|
-
from slixmpp import JID, Iq, Message
|
6
|
-
from slixmpp.plugins.base import BasePlugin
|
7
|
-
from slixmpp.plugins.xep_0356.permissions import (
|
8
|
-
MessagePermission,
|
9
|
-
Permissions,
|
10
|
-
RosterAccess,
|
11
|
-
)
|
12
|
-
from slixmpp.types import JidStr
|
13
|
-
from slixmpp.xmlstream import StanzaBase
|
14
|
-
from slixmpp.xmlstream.handler import Callback
|
15
|
-
from slixmpp.xmlstream.matcher import StanzaPath
|
16
|
-
|
17
|
-
from . import stanza
|
18
|
-
|
19
|
-
log = logging.getLogger(__name__)
|
20
|
-
|
21
|
-
|
22
|
-
# noinspection PyPep8Naming
|
23
|
-
class XEP_0356_OLD(BasePlugin):
|
24
|
-
"""
|
25
|
-
XEP-0356: Privileged Entity
|
26
|
-
|
27
|
-
Events:
|
28
|
-
|
29
|
-
::
|
30
|
-
|
31
|
-
privileges_advertised_old -- Received message/privilege from the server
|
32
|
-
"""
|
33
|
-
|
34
|
-
name = "xep_0356_old"
|
35
|
-
description = "XEP-0356: Privileged Entity (slidge - old namespace)"
|
36
|
-
dependencies = {"xep_0297"}
|
37
|
-
stanza = stanza
|
38
|
-
|
39
|
-
granted_privileges: defaultdict[JidStr, Permissions] = defaultdict(Permissions)
|
40
|
-
|
41
|
-
def plugin_init(self):
|
42
|
-
if not self.xmpp.is_component:
|
43
|
-
log.error("XEP 0356 is only available for components")
|
44
|
-
return
|
45
|
-
|
46
|
-
stanza.register()
|
47
|
-
|
48
|
-
self.xmpp.register_handler(
|
49
|
-
Callback(
|
50
|
-
"Privileges_old",
|
51
|
-
StanzaPath("message/privilege_old"),
|
52
|
-
self._handle_privilege,
|
53
|
-
)
|
54
|
-
)
|
55
|
-
|
56
|
-
def plugin_end(self):
|
57
|
-
self.xmpp.remove_handler("Privileges_old")
|
58
|
-
|
59
|
-
def _handle_privilege(self, msg: StanzaBase):
|
60
|
-
"""
|
61
|
-
Called when the XMPP server advertise the component's privileges.
|
62
|
-
|
63
|
-
Stores the privileges in this instance's granted_privileges attribute (a dict)
|
64
|
-
and raises the privileges_advertised event
|
65
|
-
"""
|
66
|
-
for perm in msg["privilege_old"]["perms"]:
|
67
|
-
setattr(
|
68
|
-
self.granted_privileges[msg.get_from()], perm["access"], perm["type"]
|
69
|
-
)
|
70
|
-
log.debug(f"Privileges (old): {self.granted_privileges}")
|
71
|
-
self.xmpp.event("privileges_advertised_old")
|
72
|
-
|
73
|
-
def send_privileged_message(self, msg: Message):
|
74
|
-
if (
|
75
|
-
self.granted_privileges[msg.get_from().domain].message
|
76
|
-
!= MessagePermission.OUTGOING
|
77
|
-
):
|
78
|
-
raise PermissionError(
|
79
|
-
"The server hasn't authorized us to send messages on behalf of other users"
|
80
|
-
)
|
81
|
-
else:
|
82
|
-
self._make_privileged_message(msg).send()
|
83
|
-
|
84
|
-
def _make_privileged_message(self, msg: Message):
|
85
|
-
server = msg.get_from().domain
|
86
|
-
wrapped = self.xmpp.make_message(mto=server, mfrom=self.xmpp.boundjid.bare)
|
87
|
-
wrapped["privilege_old"]["forwarded"].append(msg)
|
88
|
-
return wrapped
|
89
|
-
|
90
|
-
def _make_get_roster(self, jid: typing.Union[JID, str], **iq_kwargs):
|
91
|
-
return self.xmpp.make_iq_get(
|
92
|
-
queryxmlns="jabber:iq:roster",
|
93
|
-
ifrom=self.xmpp.boundjid.bare,
|
94
|
-
ito=jid,
|
95
|
-
**iq_kwargs,
|
96
|
-
)
|
97
|
-
|
98
|
-
def _make_set_roster(
|
99
|
-
self,
|
100
|
-
jid: typing.Union[JID, str],
|
101
|
-
roster_items: dict,
|
102
|
-
**iq_kwargs,
|
103
|
-
):
|
104
|
-
iq = self.xmpp.make_iq_set(
|
105
|
-
ifrom=self.xmpp.boundjid.bare,
|
106
|
-
ito=jid,
|
107
|
-
**iq_kwargs,
|
108
|
-
)
|
109
|
-
iq["roster"]["items"] = roster_items
|
110
|
-
return iq
|
111
|
-
|
112
|
-
async def get_roster(self, jid: typing.Union[JID, str], **send_kwargs) -> Iq:
|
113
|
-
"""
|
114
|
-
Return the roster of user on the server the component has privileged access to.
|
115
|
-
|
116
|
-
Raises ValueError if the server did not advertise the corresponding privileges
|
117
|
-
|
118
|
-
:param jid: user we want to fetch the roster from
|
119
|
-
"""
|
120
|
-
if isinstance(jid, str):
|
121
|
-
jid = JID(jid)
|
122
|
-
if self.granted_privileges[jid.domain].roster not in (
|
123
|
-
RosterAccess.GET,
|
124
|
-
RosterAccess.BOTH,
|
125
|
-
):
|
126
|
-
raise PermissionError(
|
127
|
-
"The server did not grant us privileges to get rosters"
|
128
|
-
)
|
129
|
-
else:
|
130
|
-
return await self._make_get_roster(jid).send(**send_kwargs)
|
131
|
-
|
132
|
-
async def set_roster(
|
133
|
-
self, jid: typing.Union[JID, str], roster_items: dict, **send_kwargs
|
134
|
-
) -> Iq:
|
135
|
-
"""
|
136
|
-
Return the roster of user on the server the component has privileged access to.
|
137
|
-
|
138
|
-
Raises ValueError if the server did not advertise the corresponding privileges
|
139
|
-
|
140
|
-
:param jid: user we want to add or modify roster items
|
141
|
-
:param roster_items: a dict containing the roster items' JIDs as keys and
|
142
|
-
nested dicts containing names, subscriptions and groups.
|
143
|
-
Example:
|
144
|
-
{
|
145
|
-
"friend1@example.com": {
|
146
|
-
"name": "Friend 1",
|
147
|
-
"subscription": "both",
|
148
|
-
"groups": ["group1", "group2"],
|
149
|
-
},
|
150
|
-
"friend2@example.com": {
|
151
|
-
"name": "Friend 2",
|
152
|
-
"subscription": "from",
|
153
|
-
"groups": ["group3"],
|
154
|
-
},
|
155
|
-
}
|
156
|
-
"""
|
157
|
-
if isinstance(jid, str):
|
158
|
-
jid = JID(jid)
|
159
|
-
if self.granted_privileges[jid.domain].roster not in (
|
160
|
-
RosterAccess.GET,
|
161
|
-
RosterAccess.BOTH,
|
162
|
-
):
|
163
|
-
raise PermissionError(
|
164
|
-
"The server did not grant us privileges to set rosters"
|
165
|
-
)
|
166
|
-
else:
|
167
|
-
return await self._make_set_roster(jid, roster_items).send(**send_kwargs)
|
@@ -1,44 +0,0 @@
|
|
1
|
-
from slixmpp.plugins.xep_0297 import Forwarded
|
2
|
-
from slixmpp.stanza import Message
|
3
|
-
from slixmpp.xmlstream import ElementBase, register_stanza_plugin
|
4
|
-
|
5
|
-
|
6
|
-
class PrivilegeOld(ElementBase):
|
7
|
-
namespace = "urn:xmpp:privilege:1"
|
8
|
-
name = "privilege"
|
9
|
-
plugin_attrib = "privilege_old"
|
10
|
-
|
11
|
-
def permission(self, access):
|
12
|
-
for perm in self["perms"]:
|
13
|
-
if perm["access"] == access:
|
14
|
-
return perm["type"]
|
15
|
-
|
16
|
-
def roster(self):
|
17
|
-
return self.permission("roster")
|
18
|
-
|
19
|
-
def message(self):
|
20
|
-
return self.permission("message")
|
21
|
-
|
22
|
-
def presence(self):
|
23
|
-
return self.permission("presence")
|
24
|
-
|
25
|
-
def add_perm(self, access, type):
|
26
|
-
# This should only be needed for servers, so maybe out of scope for slixmpp
|
27
|
-
perm = PermOld()
|
28
|
-
perm["type"] = type
|
29
|
-
perm["access"] = access
|
30
|
-
self.append(perm)
|
31
|
-
|
32
|
-
|
33
|
-
class PermOld(ElementBase):
|
34
|
-
namespace = "urn:xmpp:privilege:1"
|
35
|
-
name = "perm"
|
36
|
-
plugin_attrib = "perm"
|
37
|
-
plugin_multi_attrib = "perms"
|
38
|
-
interfaces = {"type", "access"}
|
39
|
-
|
40
|
-
|
41
|
-
def register():
|
42
|
-
register_stanza_plugin(Message, PrivilegeOld)
|
43
|
-
register_stanza_plugin(PrivilegeOld, Forwarded)
|
44
|
-
register_stanza_plugin(PrivilegeOld, PermOld, iterable=True)
|
slidge/util/db.py
DELETED
File without changes
|
File without changes
|
File without changes
|