slidge 0.2.0a2__py3-none-any.whl → 0.2.0a4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -58,10 +58,19 @@ def downgrade() -> None:
58
58
 
59
59
 
60
60
  def migrate_from_shelf(accounts: sa.Table) -> None:
61
+ from slidge import global_config
62
+
63
+ db_file = global_config.HOME_DIR / "slidge.db"
64
+ if not db_file.exists():
65
+ return
66
+
61
67
  try:
62
- from slidge.util.db import user_store
68
+ from slidge.db.alembic.old_user_store import user_store
63
69
  except ImportError:
64
70
  return
71
+
72
+ user_store.set_file(db_file, global_config.SECRET_KEY)
73
+
65
74
  try:
66
75
  users = list(user_store.get_all())
67
76
  except AttributeError:
@@ -83,3 +92,6 @@ def migrate_from_shelf(accounts: sa.Table) -> None:
83
92
  for user in users
84
93
  ],
85
94
  )
95
+
96
+ user_store.close()
97
+ db_file.unlink()
slidge/db/avatar.py CHANGED
@@ -206,6 +206,11 @@ class AvatarCache:
206
206
  stored = orm.execute(select(Avatar).where(Avatar.hash == hash_)).scalar()
207
207
 
208
208
  if stored is not None:
209
+ if unique_id is not None:
210
+ log.warning("Updating 'unique' IDs of a known avatar.")
211
+ stored.legacy_id = str(unique_id)
212
+ orm.add(stored)
213
+ orm.commit()
209
214
  return CachedAvatar.from_store(stored, self.dir)
210
215
 
211
216
  stored = Avatar(
slidge/db/meta.py CHANGED
@@ -58,6 +58,13 @@ JSONSerializable = dict[str, JSONSerializableTypes]
58
58
 
59
59
  class Base(sa.orm.DeclarativeBase):
60
60
  type_annotation_map = {JSONSerializable: JSONEncodedDict, JID: JIDType}
61
+ naming_convention = {
62
+ "ix": "ix_%(column_0_label)s",
63
+ "uq": "uq_%(table_name)s_%(column_0_name)s",
64
+ "ck": "ck_%(table_name)s_`%(constraint_name)s`",
65
+ "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
66
+ "pk": "pk_%(table_name)s",
67
+ }
61
68
 
62
69
 
63
70
  def get_engine(path: str) -> sa.Engine:
slidge/db/models.py CHANGED
@@ -166,6 +166,9 @@ class Contact(Base):
166
166
  )
167
167
  updated: Mapped[bool] = mapped_column(default=False)
168
168
 
169
+ vcard: Mapped[Optional[str]] = mapped_column()
170
+ vcard_fetched: Mapped[bool] = mapped_column(default=False)
171
+
169
172
  participants: Mapped[list["Participant"]] = relationship(back_populates="contact")
170
173
 
171
174
 
@@ -191,13 +194,20 @@ class Room(Base):
191
194
  Legacy room
192
195
  """
193
196
 
197
+ __table_args__ = (
198
+ UniqueConstraint(
199
+ "user_account_id", "legacy_id", name="uq_room_user_account_id_legacy_id"
200
+ ),
201
+ UniqueConstraint("user_account_id", "jid", name="uq_room_user_account_id_jid"),
202
+ )
203
+
194
204
  __tablename__ = "room"
195
205
  id: Mapped[int] = mapped_column(primary_key=True)
196
206
  user_account_id: Mapped[int] = mapped_column(ForeignKey("user_account.id"))
197
207
  user: Mapped[GatewayUser] = relationship(back_populates="rooms")
198
- legacy_id: Mapped[str] = mapped_column(unique=True, nullable=False)
208
+ legacy_id: Mapped[str] = mapped_column(nullable=False)
199
209
 
200
- jid: Mapped[JID] = mapped_column(unique=True)
210
+ jid: Mapped[JID] = mapped_column(nullable=False)
201
211
 
202
212
  avatar_id: Mapped[int] = mapped_column(ForeignKey("avatar.id"), nullable=True)
203
213
  avatar: Mapped[Avatar] = relationship(back_populates="rooms")
slidge/db/store.py CHANGED
@@ -162,12 +162,20 @@ class AvatarStore(EngineMixin):
162
162
  class SentStore(EngineMixin):
163
163
  def set_message(self, user_pk: int, legacy_id: str, xmpp_id: str) -> None:
164
164
  with self.session() as session:
165
- msg = XmppToLegacyIds(
166
- user_account_id=user_pk,
167
- legacy_id=legacy_id,
168
- xmpp_id=xmpp_id,
169
- type=XmppToLegacyEnum.DM,
165
+ msg = (
166
+ session.query(XmppToLegacyIds)
167
+ .filter(XmppToLegacyIds.user_account_id == user_pk)
168
+ .filter(XmppToLegacyIds.legacy_id == legacy_id)
169
+ .filter(XmppToLegacyIds.xmpp_id == xmpp_id)
170
+ .scalar()
170
171
  )
172
+ if msg is None:
173
+ msg = XmppToLegacyIds(user_account_id=user_pk)
174
+ else:
175
+ log.debug("Resetting a DM from sent store")
176
+ msg.legacy_id = legacy_id
177
+ msg.xmpp_id = xmpp_id
178
+ msg.type = XmppToLegacyEnum.DM
171
179
  session.add(msg)
172
180
  session.commit()
173
181
 
@@ -380,11 +388,22 @@ class ContactStore(UpdatedMixin):
380
388
  row.updated = True
381
389
  row.extra_attributes = contact.serialize_extra_attributes()
382
390
  row.caps_ver = contact._caps_ver
391
+ row.vcard = contact._vcard
392
+ row.vcard_fetched = contact._vcard_fetched
383
393
  session.add(row)
384
394
  if commit:
385
395
  session.commit()
386
396
  return row.id
387
397
 
398
+ def set_vcard(self, contact_pk: int, vcard: str | None) -> None:
399
+ with self.session() as session:
400
+ session.execute(
401
+ update(Contact)
402
+ .where(Contact.id == contact_pk)
403
+ .values(vcard=vcard, vcard_fetched=True)
404
+ )
405
+ session.commit()
406
+
388
407
  def add_to_sent(self, contact_pk: int, msg_id: str) -> None:
389
408
  with self.session() as session:
390
409
  new = ContactSent(contact_id=contact_pk, msg_id=msg_id)
@@ -614,6 +633,7 @@ class MAMStore(EngineMixin):
614
633
  with self.session() as session:
615
634
  after_timestamp = (
616
635
  session.query(ArchivedMessage.timestamp)
636
+ .filter(ArchivedMessage.room_id == room_pk)
617
637
  .filter(ArchivedMessage.legacy_id == after_id)
618
638
  .scalar()
619
639
  )
@@ -660,7 +680,7 @@ class MultiStore(EngineMixin):
660
680
  if existing is not None:
661
681
  if fail:
662
682
  raise
663
- log.warning("Resetting multi for %s", legacy_msg_id)
683
+ log.debug("Resetting multi for %s", legacy_msg_id)
664
684
  session.execute(
665
685
  delete(LegacyIdsMulti)
666
686
  .where(LegacyIdsMulti.user_account_id == user_pk)
@@ -767,7 +787,10 @@ class RoomStore(UpdatedMixin):
767
787
  with self.session() as session:
768
788
  session.execute(
769
789
  update(Room).values(
770
- subject_setter=None, user_resources=None, history_filled=False
790
+ subject_setter=None,
791
+ user_resources=None,
792
+ history_filled=False,
793
+ participants_filled=False,
771
794
  )
772
795
  )
773
796
  session.commit()
@@ -879,6 +902,13 @@ class RoomStore(UpdatedMixin):
879
902
  )
880
903
  session.commit()
881
904
 
905
+ def update_user_nick(self, room_pk, nick: str) -> None:
906
+ with self.session() as session:
907
+ session.execute(
908
+ update(Room).where(Room.id == room_pk).values(user_nick=nick)
909
+ )
910
+ session.commit()
911
+
882
912
  def delete(self, room_pk: int) -> None:
883
913
  with self.session() as session:
884
914
  session.execute(delete(Room).where(Room.id == room_pk))
slidge/group/bookmarks.py CHANGED
@@ -8,6 +8,7 @@ from slixmpp.jid import _unescape_node
8
8
 
9
9
  from ..contact.roster import ESCAPE_TABLE
10
10
  from ..core.mixins.lock import NamedLockMixin
11
+ from ..db.models import Room
11
12
  from ..util import SubclassableOnce
12
13
  from ..util.types import LegacyGroupIdType, LegacyMUCType
13
14
  from .archive import MessageArchive
@@ -57,29 +58,6 @@ class LegacyBookmarks(
57
58
  def __repr__(self):
58
59
  return f"<Bookmarks of {self.user_jid}>"
59
60
 
60
- async def __finish_init_muc(self, legacy_id: LegacyGroupIdType, jid: JID):
61
- with self.__store.session():
62
- stored = self.__store.get_by_legacy_id(self.session.user_pk, str(legacy_id))
63
- if stored is not None:
64
- if stored.updated:
65
- return self._muc_class.from_store(self.session, stored)
66
- muc = self._muc_class(self.session, legacy_id=legacy_id, jid=jid)
67
- muc.pk = stored.id
68
- else:
69
- muc = self._muc_class(self.session, legacy_id=legacy_id, jid=jid)
70
-
71
- try:
72
- with muc.updating_info():
73
- await muc.avatar_wrap_update_info()
74
- except Exception as e:
75
- raise XMPPError("internal-server-error", str(e))
76
- if not muc.user_nick:
77
- muc.user_nick = self._user_nick
78
- self.log.debug("MUC created: %r", muc)
79
- muc.pk = self.__store.update(muc)
80
- muc.archive = MessageArchive(muc.pk, self.xmpp.store.mam)
81
- return muc
82
-
83
61
  async def legacy_id_to_jid_local_part(self, legacy_id: LegacyGroupIdType):
84
62
  return await self.legacy_id_to_jid_username(legacy_id)
85
63
 
@@ -110,24 +88,16 @@ class LegacyBookmarks(
110
88
  async def by_jid(self, jid: JID) -> LegacyMUCType:
111
89
  if jid.resource:
112
90
  jid = JID(jid.bare)
113
- bare = jid.bare
114
- async with self.lock(("bare", bare)):
115
- assert isinstance(jid.username, str)
116
- legacy_id = await self.jid_local_part_to_legacy_id(jid.username)
91
+ async with self.lock(("bare", jid.bare)):
92
+ assert isinstance(jid.local, str)
93
+ legacy_id = await self.jid_local_part_to_legacy_id(jid.local)
117
94
  if self.get_lock(("legacy_id", legacy_id)):
118
95
  self.log.debug("Not instantiating %s after all", jid)
119
96
  return await self.by_legacy_id(legacy_id)
120
97
 
121
98
  with self.__store.session():
122
99
  stored = self.__store.get_by_jid(self.session.user_pk, jid)
123
- if stored is not None and stored.updated:
124
- return self._muc_class.from_store(self.session, stored)
125
-
126
- self.log.debug("Attempting to instantiate a new MUC for JID %s", jid)
127
- local_part = jid.node
128
-
129
- self.log.debug("%r is group %r", local_part, legacy_id)
130
- return await self.__finish_init_muc(legacy_id, JID(bare))
100
+ return await self.__update_muc(stored, legacy_id, jid)
131
101
 
132
102
  def by_jid_only_if_exists(self, jid: JID) -> Optional[LegacyMUCType]:
133
103
  with self.__store.session():
@@ -138,22 +108,39 @@ class LegacyBookmarks(
138
108
 
139
109
  async def by_legacy_id(self, legacy_id: LegacyGroupIdType) -> LegacyMUCType:
140
110
  async with self.lock(("legacy_id", legacy_id)):
141
- with self.__store.session():
142
- stored = self.__store.get_by_legacy_id(
143
- self.session.user_pk, str(legacy_id)
144
- )
145
- if stored is not None and stored.updated:
146
- return self._muc_class.from_store(self.session, stored)
147
- self.log.debug("Create new MUC instance for legacy ID %s", legacy_id)
148
111
  local = await self.legacy_id_to_jid_local_part(legacy_id)
149
- bare = f"{local}@{self.xmpp.boundjid}"
150
- jid = JID(bare)
151
- if self.get_lock(("bare", bare)):
112
+ jid = JID(f"{local}@{self.xmpp.boundjid}")
113
+ if self.get_lock(("bare", jid.bare)):
152
114
  self.log.debug("Not instantiating %s after all", legacy_id)
153
115
  return await self.by_jid(jid)
154
- muc = await self.__finish_init_muc(legacy_id, jid)
155
116
 
156
- return muc
117
+ with self.__store.session():
118
+ stored = self.__store.get_by_legacy_id(
119
+ self.session.user_pk, str(legacy_id)
120
+ )
121
+ return await self.__update_muc(stored, legacy_id, jid)
122
+
123
+ async def __update_muc(
124
+ self, stored: Room | None, legacy_id: LegacyGroupIdType, jid: JID
125
+ ):
126
+ if stored is None:
127
+ muc = self._muc_class(self.session, legacy_id=legacy_id, jid=jid)
128
+ else:
129
+ muc = self._muc_class.from_store(self.session, stored)
130
+ if stored.updated:
131
+ return muc
132
+
133
+ try:
134
+ with muc.updating_info():
135
+ await muc.avatar_wrap_update_info()
136
+ except Exception as e:
137
+ raise XMPPError("internal-server-error", str(e))
138
+ if not muc.user_nick:
139
+ muc.user_nick = self._user_nick
140
+ self.log.debug("MUC created: %r", muc)
141
+ muc.pk = self.__store.update(muc)
142
+ muc.archive = MessageArchive(muc.pk, self.xmpp.store.mam)
143
+ return muc
157
144
 
158
145
  @abc.abstractmethod
159
146
  async def fill(self):
@@ -450,13 +450,21 @@ class LegacyParticipant(
450
450
  return super().get_disco_info()
451
451
 
452
452
  def moderate(self, legacy_msg_id: LegacyMessageType, reason: Optional[str] = None):
453
- m = self.muc.get_system_participant()._make_message()
454
- m["apply_to"]["id"] = self._legacy_to_xmpp(legacy_msg_id)
455
- m["apply_to"]["moderated"].enable("retract")
456
- m["apply_to"]["moderated"]["by"] = self.jid
457
- if reason:
458
- m["apply_to"]["moderated"]["reason"] = reason
459
- self._send(m)
453
+ xmpp_id = self._legacy_to_xmpp(legacy_msg_id)
454
+ multi = self.xmpp.store.multi.get_xmpp_ids(self.session.user_pk, xmpp_id)
455
+ if multi is None:
456
+ msg_ids = [xmpp_id]
457
+ else:
458
+ msg_ids = multi + [xmpp_id]
459
+
460
+ for i in msg_ids:
461
+ m = self.muc.get_system_participant()._make_message()
462
+ m["apply_to"]["id"] = i
463
+ m["apply_to"]["moderated"].enable("retract")
464
+ m["apply_to"]["moderated"]["by"] = self.jid
465
+ if reason:
466
+ m["apply_to"]["moderated"]["reason"] = reason
467
+ self._send(m)
460
468
 
461
469
  def set_room_subject(
462
470
  self,
slidge/group/room.py CHANGED
@@ -206,6 +206,8 @@ class LegacyMUC(
206
206
  @user_nick.setter
207
207
  def user_nick(self, nick: str):
208
208
  self._user_nick = nick
209
+ if not self._updating_info:
210
+ self.__store.update_user_nick(self.pk, nick)
209
211
 
210
212
  def add_user_resource(self, resource: str) -> None:
211
213
  self._user_resources.add(resource)
@@ -1195,7 +1197,7 @@ class LegacyMUC(
1195
1197
  )
1196
1198
  muc.pk = stored.id
1197
1199
  muc.type = stored.muc_type # type: ignore
1198
- muc.user_nick = stored.user_nick
1200
+ muc._user_nick = stored.user_nick
1199
1201
  if stored.name:
1200
1202
  muc.DISCO_NAME = stored.name
1201
1203
  if stored.description:
slidge/main.py CHANGED
@@ -32,7 +32,6 @@ from slidge.db.avatar import avatar_cache
32
32
  from slidge.db.meta import get_engine
33
33
  from slidge.migration import migrate
34
34
  from slidge.util.conf import ConfigModule
35
- from slidge.util.db import user_store
36
35
 
37
36
 
38
37
  class MainConfig(ConfigModule):
@@ -114,9 +113,6 @@ def configure():
114
113
  logging.info("Creating directory '%s'", h)
115
114
  h.mkdir()
116
115
 
117
- db_file = config.HOME_DIR / "slidge.db"
118
- user_store.set_file(db_file, args.secret_key)
119
-
120
116
  config.UPLOAD_REQUESTER = config.UPLOAD_REQUESTER or config.JID.bare
121
117
 
122
118
  return unknown_argv
slidge/slixfix/roster.py CHANGED
@@ -1,9 +1,8 @@
1
+ import logging
1
2
  from typing import TYPE_CHECKING
2
3
 
3
4
  from slixmpp import JID
4
5
 
5
- from ..util.db import log
6
-
7
6
  if TYPE_CHECKING:
8
7
  from .. import BaseGateway
9
8
 
@@ -65,3 +64,6 @@ class RosterBackend:
65
64
  "whitelisted": False,
66
65
  "subscription": "none",
67
66
  }
67
+
68
+
69
+ log = logging.getLogger(__name__)
@@ -1,103 +1,14 @@
1
- import logging
2
- from typing import TYPE_CHECKING, NamedTuple, Optional
3
-
4
- from slixmpp import JID, CoroutineCallback, Iq, StanzaPath
5
1
  from slixmpp.plugins.base import BasePlugin, register_plugin
6
- from slixmpp.plugins.xep_0292.stanza import NS, VCard4
7
- from slixmpp.types import JidStr
8
-
9
- from slidge.contact import LegacyContact
10
-
11
- if TYPE_CHECKING:
12
- from slidge.core.gateway import BaseGateway
13
-
14
-
15
- class StoredVCard(NamedTuple):
16
- content: VCard4
17
- authorized_jids: set[JidStr]
2
+ from slixmpp.plugins.xep_0292.stanza import NS
18
3
 
19
4
 
20
5
  class VCard4Provider(BasePlugin):
21
- xmpp: "BaseGateway"
22
-
23
6
  name = "xep_0292_provider"
24
7
  description = "VCard4 Provider"
25
8
  dependencies = {"xep_0030"}
26
9
 
27
- def __init__(self, *a, **k):
28
- super(VCard4Provider, self).__init__(*a, **k)
29
- # TODO: store that in DB and not in RAM
30
- self._vcards = dict[JidStr, StoredVCard]()
31
-
32
10
  def plugin_init(self):
33
- self.xmpp.register_handler(
34
- CoroutineCallback(
35
- "get_vcard",
36
- StanzaPath(f"iq@type=get/vcard"),
37
- self.handle_vcard_get, # type:ignore
38
- )
39
- )
40
-
41
11
  self.xmpp.plugin["xep_0030"].add_feature(NS)
42
12
 
43
- def _get_cached_vcard(self, jid: JidStr, requested_by: JidStr) -> Optional[VCard4]:
44
- vcard = self._vcards.get(JID(jid).bare)
45
- if vcard:
46
- if auth := vcard.authorized_jids:
47
- if JID(requested_by).bare in auth:
48
- return vcard.content
49
- else:
50
- return vcard.content
51
- return None
52
-
53
- async def get_vcard(self, jid: JidStr, requested_by: JidStr) -> Optional[VCard4]:
54
- if vcard := self._get_cached_vcard(jid, requested_by):
55
- log.debug("Found a cached vcard")
56
- return vcard
57
- if not hasattr(self.xmpp, "get_session_from_jid"):
58
- return None
59
- jid = JID(jid)
60
- if not jid.local:
61
- return None
62
- requested_by = JID(requested_by)
63
- session = self.xmpp.get_session_from_jid(requested_by)
64
- if session is None:
65
- return
66
- entity = await session.get_contact_or_group_or_participant(jid)
67
- if isinstance(entity, LegacyContact):
68
- log.debug("Fetching vcard")
69
- await entity.fetch_vcard()
70
- return self._get_cached_vcard(jid, requested_by)
71
- return None
72
-
73
- async def handle_vcard_get(self, iq: Iq):
74
- r = iq.reply()
75
- if vcard := await self.get_vcard(iq.get_to().bare, iq.get_from().bare):
76
- r.append(vcard)
77
- else:
78
- r.enable("vcard")
79
- r.send()
80
-
81
- def set_vcard(
82
- self,
83
- jid: JidStr,
84
- vcard: VCard4,
85
- /,
86
- authorized_jids: Optional[set[JidStr]] = None,
87
- ):
88
- cache = self._vcards.get(jid)
89
- new = StoredVCard(
90
- vcard, authorized_jids if authorized_jids is not None else set()
91
- )
92
- self._vcards[jid] = new
93
- if cache == new:
94
- return
95
- if self.xmpp["pubsub"] and authorized_jids:
96
- for to in authorized_jids:
97
- self.xmpp.loop.create_task(
98
- self.xmpp["pubsub"].broadcast_vcard_event(jid, to)
99
- )
100
-
101
13
 
102
14
  register_plugin(VCard4Provider)
103
- log = logging.getLogger(__name__)
slidge/util/db.py CHANGED
@@ -1,183 +1,5 @@
1
- """
2
- This module covers a backend for storing user data persistently and managing a
3
- pseudo-roster for the gateway component.
4
- """
1
+ # here to allow migration of the user store from v0.1
2
+ # since it relies on shelf, which relies on pickle, we need to keep objects
3
+ # importable where they were when the shelf was written
5
4
 
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__)
5
+ from ..db.alembic.old_user_store import * # noqa:F403
slidge/util/test.py CHANGED
@@ -287,7 +287,7 @@ class SlidgeTest(SlixTestPlus):
287
287
  stanza = self.next_sent()
288
288
  assert "yup" in stanza["status"].lower(), stanza
289
289
 
290
- self.romeo = BaseSession.get_self_or_unique_subclass().from_jid(
290
+ self.romeo: BaseSession = BaseSession.get_self_or_unique_subclass().from_jid(
291
291
  JID("romeo@montague.lit")
292
292
  )
293
293
  self.juliet: LegacyContact = self.run_coro(