1 # Copyright (C) 2011-2023 by the Free Software Foundation, Inc.
3 # This file is part of GNU Mailman.
5 # GNU Mailman is free software: you can redistribute it and/or modify it under
6 # the terms of the GNU General Public License as published by the Free
7 # Software Foundation, either version 3 of the License, or (at your option)
10 # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 # You should have received a copy of the GNU General Public License along with
16 # GNU Mailman. If not, see <https://www.gnu.org/licenses/>.
20 from mailman
.database
.model
import Model
21 from mailman
.database
.transaction
import dbconnection
22 from mailman
.database
.types
import UUID
23 from public
import public
24 from sqlalchemy
import Column
, Integer
29 """Enforce uniqueness of uids through a database table.
31 This is used so that unique ids don't have to be tracked by each
32 individual model object that uses them. So for example, when a user is
33 deleted, we don't have to keep separate track of its uid to prevent it
34 from ever being used again. This class, hooked up to the `UIDFactory`
37 There is no interface for this class, because it's purely an internal
38 implementation detail.
43 id = Column(Integer
, primary_key
=True)
44 uid
= Column(UUID
, index
=True)
47 def __init__(self
, store
, uid
):
53 return '<UID {} at {}>'.format(self
.uid
, id(self
))
57 # Note that the parameter order is deliberately reversed here. Normally,
58 # `store` is the first parameter after `self`, but since this is a
59 # staticmethod and there is no self, the decorator will see the uid in
61 def record(uid
, store
):
62 """Record the uid in the database.
64 :param uid: The unique id.
66 :raises ValueError: if the id is not unique.
68 existing
= store
.query(UID
).filter_by(uid
=uid
)
69 if existing
.count() != 0:
75 def get_total_uid_count(store
):
76 return store
.query(UID
).count()
80 def cull_orphans(store
):
81 # Avoid circular imports.
82 from mailman
.model
.user
import User
84 # Delete all uids in this table that are not associated with user
86 results
= store
.query(UID
).filter(
87 ~UID
.uid
.in_(store
.query(User
._user
_id
)))
88 for uid
in results
.all():