feat: Added solicitations (#23)
* feat: Added solicitations * feat: working solicitationspull/26/head
parent
2a50a686df
commit
f8b4eeee51
|
@ -1,5 +1,10 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
# 0.15.0
|
||||||
|
|
||||||
|
* Added solicitation. Now you can see which instances are requesting guarantees
|
||||||
|
* Orphaned instances will automatically receive an open solicitation
|
||||||
|
|
||||||
# 0.14.1
|
# 0.14.1
|
||||||
|
|
||||||
* Fixed a bug with returning the reset API key on response
|
* Fixed a bug with returning the reset API key on response
|
||||||
|
|
|
@ -85,7 +85,7 @@ class Models:
|
||||||
})
|
})
|
||||||
self.input_instance_claim = api.model('ClaimInstanceInput', {
|
self.input_instance_claim = api.model('ClaimInstanceInput', {
|
||||||
'admin': fields.String(required=True, min_length=1, description="The username of the admin who wants to register this domain", example="admin"),
|
'admin': fields.String(required=True, min_length=1, description="The username of the admin who wants to register this domain", example="admin"),
|
||||||
'guarantor': fields.String(required=False, description="(Optional) The domain of the guaranteeing instance. They will receive a PM to validate you", example="admin"),
|
'guarantor': fields.String(required=False, description="(Optional) The domain of the guaranteeing instance. They will receive a PM to validate you", example="lemmy.dbzer0.com"),
|
||||||
'pm_proxy': fields.String(required=False, enum=[e.name for e in enums.PMProxy], description="(Optional) If you do receive the PM from @fediseer@fediseer.com, set this to 'MASTODON' to make the Fediseer PM your your API key via @fediseer@botsin.space. For this to work, ensure that botsin.space is not blocked in your instance and optimally follow @fediseer@botsin.space as well. If set, this will be used permanently for communication to your instance."),
|
'pm_proxy': fields.String(required=False, enum=[e.name for e in enums.PMProxy], description="(Optional) If you do receive the PM from @fediseer@fediseer.com, set this to 'MASTODON' to make the Fediseer PM your your API key via @fediseer@botsin.space. For this to work, ensure that botsin.space is not blocked in your instance and optimally follow @fediseer@botsin.space as well. If set, this will be used permanently for communication to your instance."),
|
||||||
})
|
})
|
||||||
self.input_api_key_reset = api.model('ApiKeyResetInput', {
|
self.input_api_key_reset = api.model('ApiKeyResetInput', {
|
||||||
|
@ -102,3 +102,16 @@ class Models:
|
||||||
'report_activity': fields.String(description="The activity reported", enum=[e.name for e in enums.ReportActivity]),
|
'report_activity': fields.String(description="The activity reported", enum=[e.name for e in enums.ReportActivity]),
|
||||||
'created': fields.DateTime(description="The date this record was added"),
|
'created': fields.DateTime(description="The date this record was added"),
|
||||||
})
|
})
|
||||||
|
self.input_solicit = api.model('SolicitInput', {
|
||||||
|
'guarantor': fields.String(required=False, description="The domain of the instance to solicit for a guarantee. They will receive a PM to guarantee for you", example="lemmy.dbzer0.com", min_length=1, max_length=255),
|
||||||
|
'comment': fields.String(required=False, description="You can provide some info about your instance here.", example="Me No Spam!", min_length=1, max_length=1000),
|
||||||
|
})
|
||||||
|
|
||||||
|
self.response_model_instances_soliciting = api.inherit('SolicitingInstanceDetails', self.response_model_instances, {
|
||||||
|
'comment': fields.String(description="The optional comment explaining why this instance deserves a guarantee"),
|
||||||
|
})
|
||||||
|
self.response_model_model_Solicitation_get = api.model('SolicitedInstances', {
|
||||||
|
'instances': fields.List(fields.Nested(self.response_model_instances_soliciting)),
|
||||||
|
'domains': fields.List(fields.String(description="The instance domains as a list.")),
|
||||||
|
'csv': fields.String(description="The instance domains as a csv."),
|
||||||
|
})
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import fediseer.apis.v1.base as base
|
import fediseer.apis.v1.base as base
|
||||||
import fediseer.apis.v1.whitelist as whitelist
|
import fediseer.apis.v1.whitelist as whitelist
|
||||||
|
import fediseer.apis.v1.solicitations as solicitations
|
||||||
import fediseer.apis.v1.endorsements as endorsements
|
import fediseer.apis.v1.endorsements as endorsements
|
||||||
import fediseer.apis.v1.censures as censures
|
import fediseer.apis.v1.censures as censures
|
||||||
import fediseer.apis.v1.hesitations as hesitations
|
import fediseer.apis.v1.hesitations as hesitations
|
||||||
|
@ -15,6 +16,7 @@ api.add_resource(find.FindInstance, "/find_instance")
|
||||||
api.add_resource(activitypub.User, "/user/<string:username>")
|
api.add_resource(activitypub.User, "/user/<string:username>")
|
||||||
api.add_resource(activitypub.Inbox, "/inbox/<string:username>")
|
api.add_resource(activitypub.Inbox, "/inbox/<string:username>")
|
||||||
api.add_resource(whitelist.Whitelist, "/whitelist")
|
api.add_resource(whitelist.Whitelist, "/whitelist")
|
||||||
|
api.add_resource(solicitations.Solicitations, "/solicitations")
|
||||||
api.add_resource(whitelist.WhitelistDomain, "/whitelist/<string:domain>")
|
api.add_resource(whitelist.WhitelistDomain, "/whitelist/<string:domain>")
|
||||||
api.add_resource(endorsements.Endorsements, "/endorsements/<string:domain>")
|
api.add_resource(endorsements.Endorsements, "/endorsements/<string:domain>")
|
||||||
api.add_resource(endorsements.Approvals, "/approvals/<string:domains_csv>")
|
api.add_resource(endorsements.Approvals, "/approvals/<string:domains_csv>")
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from fediseer.apis.v1.base import *
|
from fediseer.apis.v1.base import *
|
||||||
from fediseer.classes.instance import Guarantee, Endorsement, RejectionRecord
|
from fediseer.classes.instance import Guarantee, RejectionRecord, Solicitation
|
||||||
from fediseer.classes.reports import Report
|
from fediseer.classes.reports import Report
|
||||||
from fediseer import enums
|
from fediseer import enums
|
||||||
|
|
||||||
|
@ -99,12 +99,7 @@ class Guarantees(Resource):
|
||||||
guarantor_id=instance.id,
|
guarantor_id=instance.id,
|
||||||
)
|
)
|
||||||
db.session.add(new_guarantee)
|
db.session.add(new_guarantee)
|
||||||
# # Guaranteed instances get their automatic first endorsement
|
database.delete_all_solicitation_by_source(target_instance.id)
|
||||||
# new_endorsement = Endorsement(
|
|
||||||
# approving_id=instance.id,
|
|
||||||
# endorsed_id=target_instance.id,
|
|
||||||
# )
|
|
||||||
# db.session.add(new_endorsement)
|
|
||||||
new_report = Report(
|
new_report = Report(
|
||||||
source_domain=instance.domain,
|
source_domain=instance.domain,
|
||||||
target_domain=target_instance.domain,
|
target_domain=target_instance.domain,
|
||||||
|
@ -172,6 +167,22 @@ class Guarantees(Resource):
|
||||||
endorsement = database.get_endorsement(target_instance.id,instance.id)
|
endorsement = database.get_endorsement(target_instance.id,instance.id)
|
||||||
if endorsement:
|
if endorsement:
|
||||||
db.session.delete(endorsement)
|
db.session.delete(endorsement)
|
||||||
|
# Orphaned instances are automatically put into the solicitation list
|
||||||
|
new_solicitation = Solicitation(
|
||||||
|
comment="Orphaned instance!",
|
||||||
|
source_id=target_instance.id,
|
||||||
|
target_id=None,
|
||||||
|
created=guarantee.created,
|
||||||
|
)
|
||||||
|
db.session.add(new_solicitation)
|
||||||
|
solicitation_report = Report(
|
||||||
|
source_domain=instance.domain,
|
||||||
|
target_domain=instance.domain,
|
||||||
|
report_type=enums.ReportType.SOLICITATION,
|
||||||
|
report_activity=enums.ReportActivity.ADDED,
|
||||||
|
)
|
||||||
|
db.session.add(solicitation_report)
|
||||||
|
|
||||||
db.session.delete(guarantee)
|
db.session.delete(guarantee)
|
||||||
rejection_record = database.get_rejection_record(instance.id,target_instance.id)
|
rejection_record = database.get_rejection_record(instance.id,target_instance.id)
|
||||||
if rejection_record:
|
if rejection_record:
|
||||||
|
@ -188,6 +199,7 @@ class Guarantees(Resource):
|
||||||
report_type=enums.ReportType.GUARANTEE,
|
report_type=enums.ReportType.GUARANTEE,
|
||||||
report_activity=enums.ReportActivity.DELETED,
|
report_activity=enums.ReportActivity.DELETED,
|
||||||
)
|
)
|
||||||
|
|
||||||
db.session.add(new_report)
|
db.session.add(new_report)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
from fediseer.apis.v1.base import *
|
||||||
|
from fediseer.messaging import activitypub_pm
|
||||||
|
from fediseer import enums
|
||||||
|
from fediseer.classes.instance import Solicitation
|
||||||
|
from fediseer.classes.reports import Report
|
||||||
|
|
||||||
|
class Solicitations(Resource):
|
||||||
|
get_parser = reqparse.RequestParser()
|
||||||
|
get_parser.add_argument("Client-Agent", default="unknown:0:unknown", type=str, required=False, help="The client name and version.", location="headers")
|
||||||
|
get_parser.add_argument("csv", required=False, type=bool, help="Set to true to return just the domains as a csv. Mutually exclusive with domains", location="args")
|
||||||
|
get_parser.add_argument("domains", required=False, type=bool, help="Set to true to return just the domains as a list. Mutually exclusive with csv", location="args")
|
||||||
|
|
||||||
|
@api.expect(get_parser, query_string=True)
|
||||||
|
@cache.cached(timeout=10)
|
||||||
|
@api.marshal_with(models.response_model_model_Solicitation_get, code=200, description='Soliciting Instances', skip_none=True)
|
||||||
|
def get(self):
|
||||||
|
'''A List with all the currently open solicitations for guarantees.
|
||||||
|
'''
|
||||||
|
self.args = self.get_parser.parse_args()
|
||||||
|
instance_details = []
|
||||||
|
for instance in database.get_all_solicitations():
|
||||||
|
instance_detail = instance.get_details()
|
||||||
|
instance_detail["comment"] = database.find_latest_solicitation_by_source(instance.id).comment
|
||||||
|
instance_details.append(instance_detail)
|
||||||
|
if self.args.csv:
|
||||||
|
return {"csv": ",".join([instance["domain"] for instance in instance_details])},200
|
||||||
|
if self.args.domains:
|
||||||
|
return {"domains": [instance["domain"] for instance in instance_details]},200
|
||||||
|
return {"instances": instance_details},200
|
||||||
|
|
||||||
|
post_parser = reqparse.RequestParser()
|
||||||
|
post_parser.add_argument("Client-Agent", default="unknown:0:unknown", type=str, required=False, help="The client name and version.", location="headers")
|
||||||
|
post_parser.add_argument("apikey", type=str, required=True, help="The sending instance's API key.", location='headers')
|
||||||
|
post_parser.add_argument("guarantor", required=False, type=str, help="(Optional) The domain of a guaranteeing instance. They will receive a PM to validate you", location="json")
|
||||||
|
post_parser.add_argument("comment", required=False, type=str, location="json")
|
||||||
|
|
||||||
|
@api.expect(post_parser,models.input_solicit, validate=True)
|
||||||
|
@api.marshal_with(models.response_model_simple_response, code=200, description='Instances')
|
||||||
|
@api.response(400, 'Bad Request', models.response_model_error)
|
||||||
|
@api.response(401, 'Invalid API Key', models.response_model_error)
|
||||||
|
@api.response(403, 'Recent solicitation exists', models.response_model_error)
|
||||||
|
@api.response(404, 'Instance not claimed', models.response_model_error)
|
||||||
|
def post(self):
|
||||||
|
'''Solicit a guarantee
|
||||||
|
This will add your instance to the list of requested guarantees,
|
||||||
|
Other guaranteeed instances can review your application and decide to guarantee for you.
|
||||||
|
You can optionally provide the domain of an instance to receive a PM requesting for your guarantee
|
||||||
|
'''
|
||||||
|
self.args = self.post_parser.parse_args()
|
||||||
|
if not self.args.apikey:
|
||||||
|
raise e.Unauthorized("You must provide the API key that was PM'd to your admin account")
|
||||||
|
instance = database.find_instance_by_api_key(self.args.apikey)
|
||||||
|
if not instance:
|
||||||
|
raise e.NotFound(f"No Instance found matching provided API key and domain. Have you remembered to claim it?")
|
||||||
|
if instance.is_guaranteed():
|
||||||
|
raise e.BadRequest(f"Your instance is already guaranteed by {instance.get_guarantor().domain}")
|
||||||
|
guarantor_instance = None
|
||||||
|
if self.args.guarantor:
|
||||||
|
guarantor_instance = database.find_instance_by_domain(self.args.guarantor)
|
||||||
|
if not guarantor_instance:
|
||||||
|
raise e.BadRequest(f"Requested guarantor domain {self.args.guarantor} is not registered with the Fediseer yet!")
|
||||||
|
existing_solicitation = database.find_solicitation_by_target(instance.id,guarantor_instance.id)
|
||||||
|
if existing_solicitation:
|
||||||
|
raise e.Forbidden(f"You have already solicited this instance for a guarantee. Please solicit a different guarantor instead.")
|
||||||
|
else:
|
||||||
|
existing_solicitation = database.find_solicitation_by_target(instance.id,None)
|
||||||
|
if existing_solicitation:
|
||||||
|
raise e.Forbidden(f"You have already solicited an open-ended guarantee. Please try to solicit from a specific instance next.")
|
||||||
|
if database.has_recent_solicitations(instance.id):
|
||||||
|
raise e.Forbidden(f"You can only solicit one guarantee per day.")
|
||||||
|
new_solicitation = Solicitation(
|
||||||
|
comment=self.args.comment,
|
||||||
|
source_id=instance.id,
|
||||||
|
target_id=guarantor_instance.id if guarantor_instance else None,
|
||||||
|
)
|
||||||
|
db.session.add(new_solicitation)
|
||||||
|
new_report = Report(
|
||||||
|
source_domain=instance.domain,
|
||||||
|
target_domain=guarantor_instance.domain if guarantor_instance else instance.domain,
|
||||||
|
report_type=enums.ReportType.SOLICITATION,
|
||||||
|
report_activity=enums.ReportActivity.ADDED,
|
||||||
|
)
|
||||||
|
db.session.add(new_report)
|
||||||
|
db.session.commit()
|
||||||
|
if guarantor_instance:
|
||||||
|
try:
|
||||||
|
activitypub_pm.pm_admins(
|
||||||
|
message=f"New instance {instance.domain} was just registered with the Fediseer and have solicited [your guarantee](https://gui.fediseer.com/guarantees/guarantee)!",
|
||||||
|
domain=guarantor_instance.domain,
|
||||||
|
software=guarantor_instance.software,
|
||||||
|
instance=guarantor_instance,
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return {"message":'Changed'}, 200
|
|
@ -2,6 +2,8 @@ from fediseer.apis.v1.base import *
|
||||||
from fediseer.messaging import activitypub_pm
|
from fediseer.messaging import activitypub_pm
|
||||||
from fediseer.classes.user import User, Claim
|
from fediseer.classes.user import User, Claim
|
||||||
from fediseer import enums
|
from fediseer import enums
|
||||||
|
from fediseer.classes.instance import Solicitation
|
||||||
|
from fediseer.classes.reports import Report
|
||||||
|
|
||||||
class Whitelist(Resource):
|
class Whitelist(Resource):
|
||||||
get_parser = reqparse.RequestParser()
|
get_parser = reqparse.RequestParser()
|
||||||
|
@ -9,7 +11,7 @@ class Whitelist(Resource):
|
||||||
get_parser.add_argument("endorsements", required=False, default=0, type=int, help="Limit to this amount of endorsements of more", location="args")
|
get_parser.add_argument("endorsements", required=False, default=0, type=int, help="Limit to this amount of endorsements of more", location="args")
|
||||||
get_parser.add_argument("guarantors", required=False, default=1, type=int, help="Limit to this amount of guarantors of more", location="args")
|
get_parser.add_argument("guarantors", required=False, default=1, type=int, help="Limit to this amount of guarantors of more", location="args")
|
||||||
get_parser.add_argument("csv", required=False, type=bool, help="Set to true to return just the domains as a csv. Mutually exclusive with domains", location="args")
|
get_parser.add_argument("csv", required=False, type=bool, help="Set to true to return just the domains as a csv. Mutually exclusive with domains", location="args")
|
||||||
get_parser.add_argument("domains", required=False, type=str, help="Set to true to return just the domains as a list. Mutually exclusive with csv", location="args")
|
get_parser.add_argument("domains", required=False, type=bool, help="Set to true to return just the domains as a list. Mutually exclusive with csv", location="args")
|
||||||
|
|
||||||
@api.expect(get_parser)
|
@api.expect(get_parser)
|
||||||
@cache.cached(timeout=10, query_string=True)
|
@cache.cached(timeout=10, query_string=True)
|
||||||
|
@ -49,7 +51,7 @@ class WhitelistDomain(Resource):
|
||||||
put_parser = reqparse.RequestParser()
|
put_parser = reqparse.RequestParser()
|
||||||
put_parser.add_argument("Client-Agent", default="unknown:0:unknown", type=str, required=False, help="The client name and version.", location="headers")
|
put_parser.add_argument("Client-Agent", default="unknown:0:unknown", type=str, required=False, help="The client name and version.", location="headers")
|
||||||
put_parser.add_argument("admin", required=True, type=str, help="The username of the admin who wants to register this domain", location="json")
|
put_parser.add_argument("admin", required=True, type=str, help="The username of the admin who wants to register this domain", location="json")
|
||||||
put_parser.add_argument("guarantor", required=False, type=str, help="(Optional) The domain of the guaranteeing instance. They will receive a PM to validate you", location="json")
|
put_parser.add_argument("guarantor", required=False, type=str, help="(Optional) The domain of another guaranteed instance. They will receive a PM to validate you and you will be added to the solicitations list.", location="json")
|
||||||
put_parser.add_argument("pm_proxy", required=False, type=str, help="(Optional) If you do receive the PM from @fediseer@fediseer.com, set this to true to make the Fediseer PM your your API key via @fediseer@botsin.space. For this to work, ensure that botsin.space is not blocked in your instance and optimally follow @fediseer@botsin.space as well. If set, this will be used permanently for communication to your instance.", location="json")
|
put_parser.add_argument("pm_proxy", required=False, type=str, help="(Optional) If you do receive the PM from @fediseer@fediseer.com, set this to true to make the Fediseer PM your your API key via @fediseer@botsin.space. For this to work, ensure that botsin.space is not blocked in your instance and optimally follow @fediseer@botsin.space as well. If set, this will be used permanently for communication to your instance.", location="json")
|
||||||
|
|
||||||
|
|
||||||
|
@ -102,11 +104,31 @@ class WhitelistDomain(Resource):
|
||||||
instance_id = instance.id,
|
instance_id = instance.id,
|
||||||
)
|
)
|
||||||
db.session.add(new_claim)
|
db.session.add(new_claim)
|
||||||
|
new_report = Report(
|
||||||
|
source_domain=instance.domain,
|
||||||
|
target_domain=instance.domain,
|
||||||
|
report_type=enums.ReportType.CLAIM,
|
||||||
|
report_activity=enums.ReportActivity.ADDED,
|
||||||
|
)
|
||||||
|
db.session.add(new_report)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
if guarantor_instance:
|
if guarantor_instance and not instance.is_guaranteed():
|
||||||
|
new_solicitation = Solicitation(
|
||||||
|
source_id=instance.id,
|
||||||
|
target_id=guarantor_instance.id,
|
||||||
|
)
|
||||||
|
db.session.add(new_solicitation)
|
||||||
|
solicitation_report = Report(
|
||||||
|
source_domain=instance.domain,
|
||||||
|
target_domain=guarantor_instance.domain,
|
||||||
|
report_type=enums.ReportType.SOLICITATION,
|
||||||
|
report_activity=enums.ReportActivity.ADDED,
|
||||||
|
)
|
||||||
|
db.session.add(solicitation_report)
|
||||||
|
db.session.commit()
|
||||||
try:
|
try:
|
||||||
activitypub_pm.pm_admins(
|
activitypub_pm.pm_admins(
|
||||||
message=f"New instance {domain} was just registered with the Fediseer and have asked you to guarantee for them!",
|
message=f"New instance {instance.domain} was just registered with the Fediseer and have solicited [your guarantee](https://gui.fediseer.com/guarantees/guarantee)!",
|
||||||
domain=guarantor_instance.domain,
|
domain=guarantor_instance.domain,
|
||||||
software=guarantor_instance.software,
|
software=guarantor_instance.software,
|
||||||
instance=guarantor_instance,
|
instance=guarantor_instance,
|
||||||
|
|
|
@ -18,9 +18,9 @@ class RejectionRecord(db.Model):
|
||||||
__tablename__ = "rejection_records"
|
__tablename__ = "rejection_records"
|
||||||
__table_args__ = (UniqueConstraint('rejector_id', 'rejected_id', name='endoresements_rejector_id_rejected_id'),)
|
__table_args__ = (UniqueConstraint('rejector_id', 'rejected_id', name='endoresements_rejector_id_rejected_id'),)
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
rejector_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False)
|
rejector_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False, index=True)
|
||||||
rejector_instance = db.relationship("Instance", back_populates="rejections", foreign_keys=[rejector_id])
|
rejector_instance = db.relationship("Instance", back_populates="rejections", foreign_keys=[rejector_id])
|
||||||
rejected_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False)
|
rejected_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False, index=True)
|
||||||
rejected_instance = db.relationship("Instance", back_populates="rejectors", foreign_keys=[rejected_id])
|
rejected_instance = db.relationship("Instance", back_populates="rejectors", foreign_keys=[rejected_id])
|
||||||
created = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
created = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
||||||
performed = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
performed = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
||||||
|
@ -32,9 +32,9 @@ class RejectionRecord(db.Model):
|
||||||
class Guarantee(db.Model):
|
class Guarantee(db.Model):
|
||||||
__tablename__ = "guarantees"
|
__tablename__ = "guarantees"
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
guarantor_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False)
|
guarantor_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False, index=True)
|
||||||
guarantor_instance = db.relationship("Instance", back_populates="guarantees", foreign_keys=[guarantor_id])
|
guarantor_instance = db.relationship("Instance", back_populates="guarantees", foreign_keys=[guarantor_id])
|
||||||
guaranteed_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), unique=True, nullable=False)
|
guaranteed_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), unique=True, nullable=False, index=True)
|
||||||
guaranteed_instance = db.relationship("Instance", back_populates="guarantors", foreign_keys=[guaranteed_id])
|
guaranteed_instance = db.relationship("Instance", back_populates="guarantors", foreign_keys=[guaranteed_id])
|
||||||
created = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
created = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
||||||
|
|
||||||
|
@ -44,9 +44,9 @@ class Endorsement(db.Model):
|
||||||
__table_args__ = (UniqueConstraint('approving_id', 'endorsed_id', name='endoresements_approving_id_endorsed_id'),)
|
__table_args__ = (UniqueConstraint('approving_id', 'endorsed_id', name='endoresements_approving_id_endorsed_id'),)
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
reason = db.Column(db.String(255), unique=False, nullable=True, index=False)
|
reason = db.Column(db.String(255), unique=False, nullable=True, index=False)
|
||||||
approving_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False)
|
approving_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False, index=True)
|
||||||
approving_instance = db.relationship("Instance", back_populates="approvals", foreign_keys=[approving_id])
|
approving_instance = db.relationship("Instance", back_populates="approvals", foreign_keys=[approving_id])
|
||||||
endorsed_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False)
|
endorsed_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False, index=True)
|
||||||
endorsed_instance = db.relationship("Instance", back_populates="endorsements", foreign_keys=[endorsed_id])
|
endorsed_instance = db.relationship("Instance", back_populates="endorsements", foreign_keys=[endorsed_id])
|
||||||
created = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
created = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
||||||
|
|
||||||
|
@ -56,9 +56,9 @@ class Censure(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
reason = db.Column(db.String(255), unique=False, nullable=True, index=False)
|
reason = db.Column(db.String(255), unique=False, nullable=True, index=False)
|
||||||
evidence = db.Column(db.Text, unique=False, nullable=True, index=False)
|
evidence = db.Column(db.Text, unique=False, nullable=True, index=False)
|
||||||
censuring_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False)
|
censuring_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False, index=True)
|
||||||
censuring_instance = db.relationship("Instance", back_populates="censures_given", foreign_keys=[censuring_id])
|
censuring_instance = db.relationship("Instance", back_populates="censures_given", foreign_keys=[censuring_id])
|
||||||
censured_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False)
|
censured_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False, index=True)
|
||||||
censured_instance = db.relationship("Instance", back_populates="censures_received", foreign_keys=[censured_id])
|
censured_instance = db.relationship("Instance", back_populates="censures_received", foreign_keys=[censured_id])
|
||||||
created = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
created = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
||||||
|
|
||||||
|
@ -68,12 +68,22 @@ class Hesitation(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
reason = db.Column(db.String(255), unique=False, nullable=True, index=False)
|
reason = db.Column(db.String(255), unique=False, nullable=True, index=False)
|
||||||
evidence = db.Column(db.Text, unique=False, nullable=True, index=False)
|
evidence = db.Column(db.Text, unique=False, nullable=True, index=False)
|
||||||
hesitant_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False)
|
hesitant_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False, index=True)
|
||||||
hesitating_instance = db.relationship("Instance", back_populates="hesitations_given", foreign_keys=[hesitant_id])
|
hesitating_instance = db.relationship("Instance", back_populates="hesitations_given", foreign_keys=[hesitant_id])
|
||||||
dubious_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False)
|
dubious_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False, index=True)
|
||||||
dubious_instance = db.relationship("Instance", back_populates="hesitations_received", foreign_keys=[dubious_id])
|
dubious_instance = db.relationship("Instance", back_populates="hesitations_received", foreign_keys=[dubious_id])
|
||||||
created = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
created = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
||||||
|
|
||||||
|
class Solicitation(db.Model):
|
||||||
|
__tablename__ = "solicitations"
|
||||||
|
__table_args__ = (UniqueConstraint('source_id', 'target_id', name='solicitations_source_id_target_id'),)
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
comment = db.Column(db.Text, unique=False, nullable=True, index=False)
|
||||||
|
source_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=False, index=True)
|
||||||
|
source_instance = db.relationship("Instance", back_populates="solicitations_requested", foreign_keys=[source_id])
|
||||||
|
target_id = db.Column(db.Integer, db.ForeignKey("instances.id", ondelete="CASCADE"), nullable=True, index=True)
|
||||||
|
target_instance = db.relationship("Instance", back_populates="solicitations_received", foreign_keys=[target_id])
|
||||||
|
created = db.Column(db.DateTime, default=datetime.utcnow, nullable=False, index=True)
|
||||||
|
|
||||||
class Instance(db.Model):
|
class Instance(db.Model):
|
||||||
__tablename__ = "instances"
|
__tablename__ = "instances"
|
||||||
|
@ -98,6 +108,8 @@ class Instance(db.Model):
|
||||||
censures_received = db.relationship("Censure", back_populates="censured_instance", cascade="all, delete-orphan", foreign_keys=[Censure.censured_id])
|
censures_received = db.relationship("Censure", back_populates="censured_instance", cascade="all, delete-orphan", foreign_keys=[Censure.censured_id])
|
||||||
hesitations_given = db.relationship("Hesitation", back_populates="hesitating_instance", cascade="all, delete-orphan", foreign_keys=[Hesitation.hesitant_id])
|
hesitations_given = db.relationship("Hesitation", back_populates="hesitating_instance", cascade="all, delete-orphan", foreign_keys=[Hesitation.hesitant_id])
|
||||||
hesitations_received = db.relationship("Hesitation", back_populates="dubious_instance", cascade="all, delete-orphan", foreign_keys=[Hesitation.dubious_id])
|
hesitations_received = db.relationship("Hesitation", back_populates="dubious_instance", cascade="all, delete-orphan", foreign_keys=[Hesitation.dubious_id])
|
||||||
|
solicitations_requested = db.relationship("Solicitation", back_populates="source_instance", cascade="all, delete-orphan", foreign_keys=[Solicitation.source_id])
|
||||||
|
solicitations_received = db.relationship("Solicitation", back_populates="target_instance", cascade="all, delete-orphan", foreign_keys=[Solicitation.target_id])
|
||||||
guarantees = db.relationship("Guarantee", back_populates="guarantor_instance", cascade="all, delete-orphan", foreign_keys=[Guarantee.guarantor_id])
|
guarantees = db.relationship("Guarantee", back_populates="guarantor_instance", cascade="all, delete-orphan", foreign_keys=[Guarantee.guarantor_id])
|
||||||
guarantors = db.relationship("Guarantee", back_populates="guaranteed_instance", cascade="all, delete-orphan", foreign_keys=[Guarantee.guaranteed_id])
|
guarantors = db.relationship("Guarantee", back_populates="guaranteed_instance", cascade="all, delete-orphan", foreign_keys=[Guarantee.guaranteed_id])
|
||||||
rejections = db.relationship("RejectionRecord", back_populates="rejector_instance", cascade="all, delete-orphan", foreign_keys=[RejectionRecord.rejector_id])
|
rejections = db.relationship("RejectionRecord", back_populates="rejector_instance", cascade="all, delete-orphan", foreign_keys=[RejectionRecord.rejector_id])
|
||||||
|
@ -130,6 +142,9 @@ class Instance(db.Model):
|
||||||
return None
|
return None
|
||||||
return self.guarantors[0]
|
return self.guarantors[0]
|
||||||
|
|
||||||
|
def is_guaranteed(self):
|
||||||
|
return len(self.guarantors) > 0
|
||||||
|
|
||||||
def get_guarantor(self):
|
def get_guarantor(self):
|
||||||
guarantee = self.get_guarantee()
|
guarantee = self.get_guarantee()
|
||||||
if not guarantee:
|
if not guarantee:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FEDISEER_VERSION = "0.14.1"
|
FEDISEER_VERSION = "0.15.0"
|
||||||
SUPPORTED_SOFTWARE = {
|
SUPPORTED_SOFTWARE = {
|
||||||
"lemmy",
|
"lemmy",
|
||||||
"mastodon",
|
"mastodon",
|
||||||
|
|
|
@ -8,7 +8,7 @@ from sqlalchemy.orm import noload
|
||||||
from fediseer.flask import db, SQLITE_MODE
|
from fediseer.flask import db, SQLITE_MODE
|
||||||
from fediseer.utils import hash_api_key
|
from fediseer.utils import hash_api_key
|
||||||
from sqlalchemy.orm import joinedload
|
from sqlalchemy.orm import joinedload
|
||||||
from fediseer.classes.instance import Instance, Endorsement, Guarantee, RejectionRecord, Censure, Hesitation
|
from fediseer.classes.instance import Instance, Endorsement, Guarantee, RejectionRecord, Censure, Hesitation, Solicitation
|
||||||
from fediseer.classes.user import Claim, User
|
from fediseer.classes.user import Claim, User
|
||||||
from fediseer.classes.reports import Report
|
from fediseer.classes.reports import Report
|
||||||
from fediseer import enums
|
from fediseer import enums
|
||||||
|
@ -391,3 +391,59 @@ def get_reports(
|
||||||
if page < 0:
|
if page < 0:
|
||||||
page = 0
|
page = 0
|
||||||
return query.order_by(Report.created.desc()).offset(10 * page).limit(10).all()
|
return query.order_by(Report.created.desc()).offset(10 * page).limit(10).all()
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_solicitations():
|
||||||
|
# Subquery to find the minimum created date for each source_instance
|
||||||
|
subq = db.session.query(
|
||||||
|
Solicitation.source_id,
|
||||||
|
func.min(Solicitation.created).label('oldest_solicitation_date')
|
||||||
|
).group_by(
|
||||||
|
Solicitation.source_id
|
||||||
|
).subquery()
|
||||||
|
|
||||||
|
# Query to retrieve instances with at least one solicitation
|
||||||
|
query = db.session.query(
|
||||||
|
Instance,
|
||||||
|
).join(
|
||||||
|
subq,
|
||||||
|
Instance.id == subq.c.source_id
|
||||||
|
).order_by(
|
||||||
|
subq.c.oldest_solicitation_date
|
||||||
|
)
|
||||||
|
|
||||||
|
return query.all()
|
||||||
|
|
||||||
|
def find_solicitation_by_target(source_id, target_id):
|
||||||
|
query = db.session.query(
|
||||||
|
Solicitation
|
||||||
|
).filter(
|
||||||
|
Solicitation.source_id == source_id,
|
||||||
|
Solicitation.target_id == target_id,
|
||||||
|
)
|
||||||
|
return query.first()
|
||||||
|
|
||||||
|
def delete_all_solicitation_by_source(source_id):
|
||||||
|
query = db.session.query(
|
||||||
|
Solicitation
|
||||||
|
).filter(
|
||||||
|
Solicitation.source_id == source_id,
|
||||||
|
)
|
||||||
|
query.delete()
|
||||||
|
|
||||||
|
def has_recent_solicitations(source_id):
|
||||||
|
query = db.session.query(
|
||||||
|
Solicitation
|
||||||
|
).filter(
|
||||||
|
Solicitation.source_id == source_id,
|
||||||
|
Solicitation.created > datetime.utcnow() - timedelta(hours=24),
|
||||||
|
)
|
||||||
|
return query.count() > 0
|
||||||
|
|
||||||
|
def find_latest_solicitation_by_source(source_id):
|
||||||
|
query = db.session.query(
|
||||||
|
Solicitation
|
||||||
|
).filter(
|
||||||
|
Solicitation.source_id == source_id,
|
||||||
|
)
|
||||||
|
return query.order_by(Solicitation.created.desc()).first()
|
|
@ -5,6 +5,8 @@ class ReportType(enum.Enum):
|
||||||
ENDORSEMENT = 1
|
ENDORSEMENT = 1
|
||||||
CENSURE = 2
|
CENSURE = 2
|
||||||
HESITATION = 3
|
HESITATION = 3
|
||||||
|
CLAIM = 4
|
||||||
|
SOLICITATION = 5
|
||||||
|
|
||||||
class ReportActivity(enum.Enum):
|
class ReportActivity(enum.Enum):
|
||||||
ADDED = 0
|
ADDED = 0
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TYPE reporttype ADD VALUE 'CLAIM';
|
||||||
|
ALTER TYPE reporttype ADD VALUE 'SOLICITATION';
|
Loading…
Reference in New Issue