feat: geo risk scores

This commit is contained in:
Iain Learmonth 2023-10-29 15:45:10 +00:00
parent 315dae7f06
commit 0e0d499428
17 changed files with 558 additions and 54 deletions

View file

@ -1,7 +1,7 @@
import logging
from abc import abstractmethod
from datetime import datetime
from typing import Union, List, Optional, Any
from typing import Union, List, Optional, Any, Dict
from app.brm.brn import BRN
from app.extensions import db
@ -37,6 +37,21 @@ class AbstractConfiguration(db.Model): # type: ignore
]
class Deprecation(db.Model): # type: ignore[name-defined,misc]
id = db.Column(db.Integer, primary_key=True)
resource_type = db.Column(db.String(50))
resource_id = db.Column(db.Integer)
deprecated_at = db.Column(db.DateTime(), default=datetime.utcnow, nullable=False)
meta = db.Column(db.JSON())
reason = db.Column(db.String(), nullable=False)
@property
def resource(self) -> "AbstractResource":
from app.models.mirrors import Proxy
model = {'Proxy': Proxy}[self.resource_type]
return model.query.get(self.resource_id) # type: ignore[no-any-return]
class AbstractResource(db.Model): # type: ignore
__abstract__ = True
@ -72,12 +87,14 @@ class AbstractResource(db.Model): # type: ignore
def brn(self) -> BRN:
raise NotImplementedError()
def deprecate(self, *, reason: str) -> bool:
def deprecate(self, *, reason: str, meta: Optional[Dict[str, Any]] = None) -> bool:
"""
Marks the resource as deprecated. In the event that the resource was already
deprecated, no change will be recorded and the function will return False.
:param reason: an opaque string that records the deprecation reason
:param meta: metadata associated with the deprecation reason, such as the circumstances in which censorship was
detected
:return: if the proxy was deprecated
"""
if self.deprecated is None:
@ -85,10 +102,26 @@ class AbstractResource(db.Model): # type: ignore
self.deprecated = datetime.utcnow()
self.deprecation_reason = reason
self.updated = datetime.utcnow()
if reason not in [d.reason for d in self.deprecations]:
new_deprecation = Deprecation(
resource_type=type(self).__name__,
resource_id=self.id,
reason=reason,
meta=meta
)
db.session.add(new_deprecation)
return True
logging.info("Not deprecating %s (reason=%s) because it's already deprecated", self.brn, reason)
logging.info("Not deprecating %s (reason=%s) because it's already deprecated with that reason.",
self.brn, reason)
return False
@property
def deprecations(self) -> List[Deprecation]:
return Deprecation.query.filter_by( # type: ignore[no-any-return]
resource_type='Proxy',
resource_id=self.id
).all()
def destroy(self) -> None:
"""
Marks the resource for destruction.