feat: list visibility
parent
bb4edcecda
commit
c616ad3cb5
|
@ -1,5 +1,14 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
# 0.16.0
|
||||||
|
|
||||||
|
Allows instances to control the visibility of their endorsements, censures and hesitations by setting their visibility in PATCHing `api/b1/whitelist`
|
||||||
|
* OPEN: Public visibility (Default).
|
||||||
|
* ENDORSED: Only endorsed instances can see that list.
|
||||||
|
* PRIVATE: Only admins from their own instance can see that list.
|
||||||
|
|
||||||
|
When a list visibility is not OPEN, the reports will use `[REDACTED]` as the target domain. But this will not affect historical reports.
|
||||||
|
|
||||||
# 0.15.1
|
# 0.15.1
|
||||||
|
|
||||||
* Added some rate limits. Currently each instance is limited to 20 actions per minute
|
* Added some rate limits. Currently each instance is limited to 20 actions per minute
|
||||||
|
|
|
@ -88,12 +88,15 @@ class Models:
|
||||||
'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"),
|
'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_instance_modify = api.model('InstanceModify', {
|
||||||
'admin_username': fields.String(required=False, description="If a username is given, their API key will be reset. Otherwise the user's whose API key was provided will be reset. This allows can be initiated by other instance admins or the fediseer.", example="admin"),
|
'admin_username': fields.String(required=False, description="If a username is given, their API key will be reset. Otherwise the user's whose API key was provided will be reset. This allows can be initiated by other instance admins or the fediseer.", example="admin"),
|
||||||
'return_new_key': fields.Boolean(required=False, default=False, description="If True, the key will be returned as part of the response instead of PM'd. Fediseer will still PM a notification to the target admin account."),
|
'return_new_key': fields.Boolean(required=False, default=False, description="If True, the key will be returned as part of the response instead of PM'd. Fediseer will still PM a notification to the target admin account."),
|
||||||
'sysadmins': fields.Integer(required=False, default=None, min=0, max=100, description="Report how many system administrators this instance currently has."),
|
'sysadmins': fields.Integer(required=False, default=None, min=0, max=100, description="Report how many system administrators this instance currently has."),
|
||||||
'moderators': fields.Integer(required=False, default=None, min=0, max=1000, description="Report how many instance moderators this instance currently has."),
|
'moderators': fields.Integer(required=False, default=None, min=0, max=1000, description="Report how many instance moderators this instance currently has."),
|
||||||
'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."),
|
||||||
|
'visibility_endorsements': fields.String(required=False, enum=[e.name for e in enums.ListVisibility], description="Set this to OPEN, to allow anyone to read your endorsements. Set to ENDORSED to only allow endorsed instances to read your endorsements. Set to PRIVATE to only allow your own admins to read your endorsements."),
|
||||||
|
'visibility_censures': fields.String(required=False, enum=[e.name for e in enums.ListVisibility], description="Set this to OPEN, to allow anyone to read your censures. Set to ENDORSED to only allow endorsed instances to read your censures. Set to PRIVATE to only allow your own admins to read your censures."),
|
||||||
|
'visibility_hesitations': fields.String(required=False, enum=[e.name for e in enums.ListVisibility], description="Set this to OPEN, to allow anyone to read your hesitations. Set to ENDORSED to only allow endorsed instances to read your hesitations. Set to PRIVATE to only allow your own admins to read your hesitations."),
|
||||||
})
|
})
|
||||||
self.response_model_reports = api.model('ActivityReport', {
|
self.response_model_reports = api.model('ActivityReport', {
|
||||||
'source_domain': fields.String(description="The instance domain which initiated this activity", example="lemmy.dbzer0.com"),
|
'source_domain': fields.String(description="The instance domain which initiated this activity", example="lemmy.dbzer0.com"),
|
||||||
|
|
|
@ -6,6 +6,7 @@ from fediseer import enums
|
||||||
|
|
||||||
class CensuresGiven(Resource):
|
class CensuresGiven(Resource):
|
||||||
get_parser = reqparse.RequestParser()
|
get_parser = reqparse.RequestParser()
|
||||||
|
get_parser.add_argument("apikey", type=str, required=False, help="An instance's API key.", location='headers')
|
||||||
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("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("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")
|
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")
|
||||||
|
@ -16,17 +17,39 @@ class CensuresGiven(Resource):
|
||||||
@cache.cached(timeout=10, query_string=True)
|
@cache.cached(timeout=10, query_string=True)
|
||||||
@api.marshal_with(models.response_model_model_Censures_get, code=200, description='Instances', skip_none=True)
|
@api.marshal_with(models.response_model_model_Censures_get, code=200, description='Instances', skip_none=True)
|
||||||
@api.response(404, 'Instance not registered', models.response_model_error)
|
@api.response(404, 'Instance not registered', models.response_model_error)
|
||||||
|
@api.response(401, 'API key not found', models.response_model_error)
|
||||||
|
@api.response(403, 'Access Denied', models.response_model_error)
|
||||||
def get(self, domains_csv):
|
def get(self, domains_csv):
|
||||||
'''Display all censures given out by one or more domains
|
'''Display all censures given out by one or more domains
|
||||||
You can pass a comma-separated list of domain names
|
You can pass a comma-separated list of domain names
|
||||||
and the results will be a set of all their censures together.
|
and the results will be a set of all their censures together.
|
||||||
'''
|
'''
|
||||||
self.args = self.get_parser.parse_args()
|
self.args = self.get_parser.parse_args()
|
||||||
|
get_instance = None
|
||||||
|
if self.args.apikey:
|
||||||
|
get_instance = database.find_instance_by_api_key(self.args.apikey)
|
||||||
|
if not get_instance:
|
||||||
|
raise e.Unauthorized(f"No Instance found matching provided API key. Please ensure you've typed it correctly")
|
||||||
domains_list = domains_csv.split(',')
|
domains_list = domains_csv.split(',')
|
||||||
instances = database.find_multiple_instance_by_domains(domains_list)
|
precheck_instances = database.find_multiple_instance_by_domains(domains_list)
|
||||||
if not instances:
|
if not precheck_instances:
|
||||||
raise e.NotFound(f"No Instances found matching any of the provided domains. Have you remembered to register them?")
|
raise e.NotFound(f"No Instances found matching any of the provided domains. Have you remembered to register them?")
|
||||||
if self.args.min_censures > len(domains_list):
|
instances = []
|
||||||
|
for instance in precheck_instances:
|
||||||
|
if instance.visibility_censures == enums.ListVisibility.ENDORSED:
|
||||||
|
if get_instance is None:
|
||||||
|
continue
|
||||||
|
if instance != get_instance and not instance.is_endorsing(get_instance):
|
||||||
|
continue
|
||||||
|
if instance.visibility_censures == enums.ListVisibility.PRIVATE:
|
||||||
|
if get_instance is None:
|
||||||
|
continue
|
||||||
|
if instance != get_instance:
|
||||||
|
continue
|
||||||
|
instances.append(instance)
|
||||||
|
if len(instances) == 0:
|
||||||
|
raise e.Forbidden(f"You do not have access to see these censures")
|
||||||
|
if self.args.min_censures > len(instances):
|
||||||
raise e.BadRequest(f"You cannot request more censures than the amount of reference domains")
|
raise e.BadRequest(f"You cannot request more censures than the amount of reference domains")
|
||||||
instance_details = []
|
instance_details = []
|
||||||
for c_instance in database.get_all_censured_instances_by_censuring_id([instance.id for instance in instances]):
|
for c_instance in database.get_all_censured_instances_by_censuring_id([instance.id for instance in instances]):
|
||||||
|
@ -78,6 +101,7 @@ class CensuresGiven(Resource):
|
||||||
|
|
||||||
class Censures(Resource):
|
class Censures(Resource):
|
||||||
get_parser = reqparse.RequestParser()
|
get_parser = reqparse.RequestParser()
|
||||||
|
get_parser.add_argument("apikey", type=str, required=False, help="An instance's API key.", location='headers')
|
||||||
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("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("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")
|
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")
|
||||||
|
@ -90,11 +114,30 @@ class Censures(Resource):
|
||||||
'''Display all censures received by a specific domain
|
'''Display all censures received by a specific domain
|
||||||
'''
|
'''
|
||||||
self.args = self.get_parser.parse_args()
|
self.args = self.get_parser.parse_args()
|
||||||
|
get_instance = None
|
||||||
|
if self.args.apikey:
|
||||||
|
get_instance = database.find_instance_by_api_key(self.args.apikey)
|
||||||
|
if not get_instance:
|
||||||
|
raise e.Unauthorized(f"No Instance found matching provided API key. Please ensure you've typed it correctly")
|
||||||
instance = database.find_instance_by_domain(domain)
|
instance = database.find_instance_by_domain(domain)
|
||||||
if not instance:
|
if not instance:
|
||||||
raise e.NotFound(f"No Instance found matching provided domain. Have you remembered to register it?")
|
raise e.NotFound(f"No Instance found matching provided domain. Have you remembered to register it?")
|
||||||
instance_details = []
|
instance_details = []
|
||||||
for c_instance in database.get_all_censuring_instances_by_censured_id(instance.id):
|
precheck_instances = database.get_all_censuring_instances_by_censured_id(instance.id)
|
||||||
|
instances = []
|
||||||
|
for instance in precheck_instances:
|
||||||
|
if instance.visibility_censures == enums.ListVisibility.ENDORSED:
|
||||||
|
if get_instance is None:
|
||||||
|
continue
|
||||||
|
if not instance.is_endorsing(get_instance):
|
||||||
|
continue
|
||||||
|
if instance.visibility_censures == enums.ListVisibility.PRIVATE:
|
||||||
|
if get_instance is None:
|
||||||
|
continue
|
||||||
|
if not instance != get_instance:
|
||||||
|
continue
|
||||||
|
instances.append(instance)
|
||||||
|
for c_instance in instances:
|
||||||
censures = database.get_all_censure_reasons_for_censured_id(instance.id, [c_instance.id])
|
censures = database.get_all_censure_reasons_for_censured_id(instance.id, [c_instance.id])
|
||||||
censures = [c for c in censures if c.reason is not None]
|
censures = [c for c in censures if c.reason is not None]
|
||||||
c_instance_details = c_instance.get_details()
|
c_instance_details = c_instance.get_details()
|
||||||
|
@ -164,9 +207,12 @@ class Censures(Resource):
|
||||||
evidence=evidence,
|
evidence=evidence,
|
||||||
)
|
)
|
||||||
db.session.add(new_censure)
|
db.session.add(new_censure)
|
||||||
|
target_domain = target_instance.domain
|
||||||
|
if instance.visibility_censures != enums.ListVisibility.OPEN:
|
||||||
|
target_domain = '[REDACTED]'
|
||||||
new_report = Report(
|
new_report = Report(
|
||||||
source_domain=instance.domain,
|
source_domain=instance.domain,
|
||||||
target_domain=target_instance.domain,
|
target_domain=target_domain,
|
||||||
report_type=enums.ReportType.CENSURE,
|
report_type=enums.ReportType.CENSURE,
|
||||||
report_activity=enums.ReportActivity.ADDED,
|
report_activity=enums.ReportActivity.ADDED,
|
||||||
)
|
)
|
||||||
|
@ -222,9 +268,12 @@ class Censures(Resource):
|
||||||
changed = True
|
changed = True
|
||||||
if changed is False:
|
if changed is False:
|
||||||
return {"message":'OK'}, 200
|
return {"message":'OK'}, 200
|
||||||
|
target_domain = target_instance.domain
|
||||||
|
if instance.visibility_censures != enums.ListVisibility.OPEN:
|
||||||
|
target_domain = '[REDACTED]'
|
||||||
new_report = Report(
|
new_report = Report(
|
||||||
source_domain=instance.domain,
|
source_domain=instance.domain,
|
||||||
target_domain=target_instance.domain,
|
target_domain=target_domain,
|
||||||
report_type=enums.ReportType.CENSURE,
|
report_type=enums.ReportType.CENSURE,
|
||||||
report_activity=enums.ReportActivity.MODIFIED,
|
report_activity=enums.ReportActivity.MODIFIED,
|
||||||
)
|
)
|
||||||
|
@ -260,9 +309,12 @@ class Censures(Resource):
|
||||||
if not censure:
|
if not censure:
|
||||||
return {"message":'OK'}, 200
|
return {"message":'OK'}, 200
|
||||||
db.session.delete(censure)
|
db.session.delete(censure)
|
||||||
|
target_domain = target_instance.domain
|
||||||
|
if instance.visibility_censures != enums.ListVisibility.OPEN:
|
||||||
|
target_domain = '[REDACTED]'
|
||||||
new_report = Report(
|
new_report = Report(
|
||||||
source_domain=instance.domain,
|
source_domain=instance.domain,
|
||||||
target_domain=target_instance.domain,
|
target_domain=target_domain,
|
||||||
report_type=enums.ReportType.CENSURE,
|
report_type=enums.ReportType.CENSURE,
|
||||||
report_activity=enums.ReportActivity.DELETED,
|
report_activity=enums.ReportActivity.DELETED,
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,6 +6,7 @@ from fediseer.utils import sanitize_string
|
||||||
|
|
||||||
class Approvals(Resource):
|
class Approvals(Resource):
|
||||||
get_parser = reqparse.RequestParser()
|
get_parser = reqparse.RequestParser()
|
||||||
|
get_parser.add_argument("apikey", type=str, required=False, help="An instance's API key.", location='headers')
|
||||||
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("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("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")
|
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")
|
||||||
|
@ -16,6 +17,8 @@ class Approvals(Resource):
|
||||||
@cache.cached(timeout=10, query_string=True)
|
@cache.cached(timeout=10, query_string=True)
|
||||||
@api.marshal_with(models.response_model_model_Endorsed_get, code=200, description='Instances', skip_none=True)
|
@api.marshal_with(models.response_model_model_Endorsed_get, code=200, description='Instances', skip_none=True)
|
||||||
@api.response(404, 'Instance not registered', models.response_model_error)
|
@api.response(404, 'Instance not registered', models.response_model_error)
|
||||||
|
@api.response(401, 'API key not found', models.response_model_error)
|
||||||
|
@api.response(403, 'Access Denied', models.response_model_error)
|
||||||
def get(self, domains_csv):
|
def get(self, domains_csv):
|
||||||
'''Display all endorsements given out by one or more domains
|
'''Display all endorsements given out by one or more domains
|
||||||
You can pass a comma-separated list of domain names and the results will be a set of all their
|
You can pass a comma-separated list of domain names and the results will be a set of all their
|
||||||
|
@ -23,9 +26,29 @@ class Approvals(Resource):
|
||||||
'''
|
'''
|
||||||
domains_list = domains_csv.split(',')
|
domains_list = domains_csv.split(',')
|
||||||
self.args = self.get_parser.parse_args()
|
self.args = self.get_parser.parse_args()
|
||||||
instances = database.find_multiple_instance_by_domains(domains_list)
|
get_instance = None
|
||||||
if not instances:
|
if self.args.apikey:
|
||||||
|
get_instance = database.find_instance_by_api_key(self.args.apikey)
|
||||||
|
if not get_instance:
|
||||||
|
raise e.Unauthorized(f"No Instance found matching provided API key. Please ensure you've typed it correctly")
|
||||||
|
precheck_instances = database.find_multiple_instance_by_domains(domains_list)
|
||||||
|
if not precheck_instances:
|
||||||
raise e.NotFound(f"No Instances found matching any of the provided domains. Have you remembered to register them?")
|
raise e.NotFound(f"No Instances found matching any of the provided domains. Have you remembered to register them?")
|
||||||
|
instances = []
|
||||||
|
for instance in precheck_instances:
|
||||||
|
if instance.visibility_endorsements == enums.ListVisibility.ENDORSED:
|
||||||
|
if get_instance is None:
|
||||||
|
continue
|
||||||
|
if instance != get_instance and not instance.is_endorsing(get_instance):
|
||||||
|
continue
|
||||||
|
if instance.visibility_endorsements == enums.ListVisibility.PRIVATE:
|
||||||
|
if get_instance is None:
|
||||||
|
continue
|
||||||
|
if instance != get_instance:
|
||||||
|
continue
|
||||||
|
instances.append(instance)
|
||||||
|
if len(instances) == 0:
|
||||||
|
raise e.Forbidden(f"You do not have access to see these endorsements")
|
||||||
instance_details = []
|
instance_details = []
|
||||||
for e_instance in database.get_all_endorsed_instances_by_approving_id([instance.id for instance in instances]):
|
for e_instance in database.get_all_endorsed_instances_by_approving_id([instance.id for instance in instances]):
|
||||||
endorsements = database.get_all_endorsement_reasons_for_endorsed_id(e_instance.id, [instance.id for instance in instances])
|
endorsements = database.get_all_endorsement_reasons_for_endorsed_id(e_instance.id, [instance.id for instance in instances])
|
||||||
|
@ -58,6 +81,7 @@ class Approvals(Resource):
|
||||||
|
|
||||||
class Endorsements(Resource):
|
class Endorsements(Resource):
|
||||||
get_parser = reqparse.RequestParser()
|
get_parser = reqparse.RequestParser()
|
||||||
|
get_parser.add_argument("apikey", type=str, required=False, help="An instance's API key.", location='headers')
|
||||||
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("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("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")
|
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")
|
||||||
|
@ -70,11 +94,30 @@ class Endorsements(Resource):
|
||||||
'''Display all endorsements received by a specific domain
|
'''Display all endorsements received by a specific domain
|
||||||
'''
|
'''
|
||||||
self.args = self.get_parser.parse_args()
|
self.args = self.get_parser.parse_args()
|
||||||
|
get_instance = None
|
||||||
|
if self.args.apikey:
|
||||||
|
get_instance = database.find_instance_by_api_key(self.args.apikey)
|
||||||
|
if not get_instance:
|
||||||
|
raise e.Unauthorized(f"No Instance found matching provided API key. Please ensure you've typed it correctly")
|
||||||
instance = database.find_instance_by_domain(domain)
|
instance = database.find_instance_by_domain(domain)
|
||||||
if not instance:
|
if not instance:
|
||||||
raise e.NotFound(f"No Instance found matching provided domain. Have you remembered to register it?")
|
raise e.NotFound(f"No Instance found matching provided domain. Have you remembered to register it?")
|
||||||
instance_details = []
|
instance_details = []
|
||||||
for e_instance in database.get_all_approving_instances_by_endorsed_id(instance.id):
|
precheck_instances = database.get_all_approving_instances_by_endorsed_id(instance.id)
|
||||||
|
instances = []
|
||||||
|
for instance in precheck_instances:
|
||||||
|
if instance.visibility_endorsements == enums.ListVisibility.ENDORSED:
|
||||||
|
if get_instance is None:
|
||||||
|
continue
|
||||||
|
if not instance.is_endorsing(get_instance):
|
||||||
|
continue
|
||||||
|
if instance.visibility_endorsements == enums.ListVisibility.PRIVATE:
|
||||||
|
if get_instance is None:
|
||||||
|
continue
|
||||||
|
if not instance != get_instance:
|
||||||
|
continue
|
||||||
|
instances.append(instance)
|
||||||
|
for e_instance in instances:
|
||||||
endorsements = database.get_all_endorsement_reasons_for_endorsed_id(instance.id, [e_instance.id])
|
endorsements = database.get_all_endorsement_reasons_for_endorsed_id(instance.id, [e_instance.id])
|
||||||
endorsements = [e for e in endorsements if e.reason is not None]
|
endorsements = [e for e in endorsements if e.reason is not None]
|
||||||
e_instance_details = e_instance.get_details()
|
e_instance_details = e_instance.get_details()
|
||||||
|
@ -139,9 +182,12 @@ class Endorsements(Resource):
|
||||||
reason=reason,
|
reason=reason,
|
||||||
)
|
)
|
||||||
db.session.add(new_endorsement)
|
db.session.add(new_endorsement)
|
||||||
|
target_domain = target_instance.domain
|
||||||
|
if instance.visibility_endorsements != enums.ListVisibility.OPEN:
|
||||||
|
target_domain = '[REDACTED]'
|
||||||
new_report = Report(
|
new_report = Report(
|
||||||
source_domain=instance.domain,
|
source_domain=instance.domain,
|
||||||
target_domain=target_instance.domain,
|
target_domain=target_domain,
|
||||||
report_type=enums.ReportType.ENDORSEMENT,
|
report_type=enums.ReportType.ENDORSEMENT,
|
||||||
report_activity=enums.ReportActivity.ADDED,
|
report_activity=enums.ReportActivity.ADDED,
|
||||||
)
|
)
|
||||||
|
@ -202,9 +248,12 @@ class Endorsements(Resource):
|
||||||
changed = True
|
changed = True
|
||||||
if changed is False:
|
if changed is False:
|
||||||
return {"message":'OK'}, 200
|
return {"message":'OK'}, 200
|
||||||
|
target_domain = target_instance.domain
|
||||||
|
if instance.visibility_endorsements != enums.ListVisibility.OPEN:
|
||||||
|
target_domain = '[REDACTED]'
|
||||||
new_report = Report(
|
new_report = Report(
|
||||||
source_domain=instance.domain,
|
source_domain=instance.domain,
|
||||||
target_domain=target_instance.domain,
|
target_domain=target_domain,
|
||||||
report_type=enums.ReportType.ENDORSEMENT,
|
report_type=enums.ReportType.ENDORSEMENT,
|
||||||
report_activity=enums.ReportActivity.MODIFIED,
|
report_activity=enums.ReportActivity.MODIFIED,
|
||||||
)
|
)
|
||||||
|
@ -242,9 +291,12 @@ class Endorsements(Resource):
|
||||||
if not endorsement:
|
if not endorsement:
|
||||||
return {"message":'OK'}, 200
|
return {"message":'OK'}, 200
|
||||||
db.session.delete(endorsement)
|
db.session.delete(endorsement)
|
||||||
|
target_domain = target_instance.domain
|
||||||
|
if instance.visibility_endorsements != enums.ListVisibility.OPEN:
|
||||||
|
target_domain = '[REDACTED]'
|
||||||
new_report = Report(
|
new_report = Report(
|
||||||
source_domain=instance.domain,
|
source_domain=instance.domain,
|
||||||
target_domain=target_instance.domain,
|
target_domain=target_domain,
|
||||||
report_type=enums.ReportType.ENDORSEMENT,
|
report_type=enums.ReportType.ENDORSEMENT,
|
||||||
report_activity=enums.ReportActivity.DELETED,
|
report_activity=enums.ReportActivity.DELETED,
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,6 +6,7 @@ from fediseer import enums
|
||||||
|
|
||||||
class HesitationsGiven(Resource):
|
class HesitationsGiven(Resource):
|
||||||
get_parser = reqparse.RequestParser()
|
get_parser = reqparse.RequestParser()
|
||||||
|
get_parser.add_argument("apikey", type=str, required=False, help="An instance's API key.", location='headers')
|
||||||
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("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("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")
|
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")
|
||||||
|
@ -16,17 +17,40 @@ class HesitationsGiven(Resource):
|
||||||
@cache.cached(timeout=10, query_string=True)
|
@cache.cached(timeout=10, query_string=True)
|
||||||
@api.marshal_with(models.response_model_model_Hesitations_get, code=200, description='Instances', skip_none=True)
|
@api.marshal_with(models.response_model_model_Hesitations_get, code=200, description='Instances', skip_none=True)
|
||||||
@api.response(404, 'Instance not registered', models.response_model_error)
|
@api.response(404, 'Instance not registered', models.response_model_error)
|
||||||
|
@api.response(401, 'API key not found', models.response_model_error)
|
||||||
|
@api.response(403, 'Access Denied', models.response_model_error)
|
||||||
def get(self, domains_csv):
|
def get(self, domains_csv):
|
||||||
'''Display all hesitations given out by one or more domains
|
'''Display all hesitations given out by one or more domains
|
||||||
You can pass a comma-separated list of domain names
|
You can pass a comma-separated list of domain names
|
||||||
and the results will be a set of all their hesitations together.
|
and the results will be a set of all their hesitations together.
|
||||||
'''
|
'''
|
||||||
self.args = self.get_parser.parse_args()
|
self.args = self.get_parser.parse_args()
|
||||||
|
get_instance = None
|
||||||
|
if self.args.apikey:
|
||||||
|
get_instance = database.find_instance_by_api_key(self.args.apikey)
|
||||||
|
if not get_instance:
|
||||||
|
raise e.Unauthorized(f"No Instance found matching provided API key. Please ensure you've typed it correctly")
|
||||||
domains_list = domains_csv.split(',')
|
domains_list = domains_csv.split(',')
|
||||||
instances = database.find_multiple_instance_by_domains(domains_list)
|
precheck_instances = database.find_multiple_instance_by_domains(domains_list)
|
||||||
if not instances:
|
if not precheck_instances:
|
||||||
raise e.NotFound(f"No Instances found matching any of the provided domains. Have you remembered to register them?")
|
raise e.NotFound(f"No Instances found matching any of the provided domains. Have you remembered to register them?")
|
||||||
if self.args.min_hesitations > len(domains_list):
|
instances = []
|
||||||
|
for instance in precheck_instances:
|
||||||
|
if instance.visibility_hesitations == enums.ListVisibility.ENDORSED:
|
||||||
|
if get_instance is None:
|
||||||
|
continue
|
||||||
|
if instance != get_instance and not instance.is_endorsing(get_instance):
|
||||||
|
continue
|
||||||
|
if instance.visibility_hesitations == enums.ListVisibility.PRIVATE:
|
||||||
|
logger.debug([instance.visibility_hesitations,instance,get_instance,instance != get_instance])
|
||||||
|
if get_instance is None:
|
||||||
|
continue
|
||||||
|
if instance != get_instance:
|
||||||
|
continue
|
||||||
|
instances.append(instance)
|
||||||
|
if len(instances) == 0:
|
||||||
|
raise e.Forbidden(f"You do not have access to see these hesitations")
|
||||||
|
if self.args.min_hesitations > len(instances):
|
||||||
raise e.BadRequest(f"You cannot request more hesitations than the amount of reference domains")
|
raise e.BadRequest(f"You cannot request more hesitations than the amount of reference domains")
|
||||||
instance_details = []
|
instance_details = []
|
||||||
for c_instance in database.get_all_dubious_instances_by_hesitant_id([instance.id for instance in instances]):
|
for c_instance in database.get_all_dubious_instances_by_hesitant_id([instance.id for instance in instances]):
|
||||||
|
@ -63,6 +87,7 @@ class HesitationsGiven(Resource):
|
||||||
|
|
||||||
class Hesitations(Resource):
|
class Hesitations(Resource):
|
||||||
get_parser = reqparse.RequestParser()
|
get_parser = reqparse.RequestParser()
|
||||||
|
get_parser.add_argument("apikey", type=str, required=False, help="An instance's API key.", location='headers')
|
||||||
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("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("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")
|
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")
|
||||||
|
@ -75,11 +100,30 @@ class Hesitations(Resource):
|
||||||
'''Display all hesitations received by a specific domain
|
'''Display all hesitations received by a specific domain
|
||||||
'''
|
'''
|
||||||
self.args = self.get_parser.parse_args()
|
self.args = self.get_parser.parse_args()
|
||||||
|
get_instance = None
|
||||||
|
if self.args.apikey:
|
||||||
|
get_instance = database.find_instance_by_api_key(self.args.apikey)
|
||||||
|
if not get_instance:
|
||||||
|
raise e.Unauthorized(f"No Instance found matching provided API key. Please ensure you've typed it correctly")
|
||||||
instance = database.find_instance_by_domain(domain)
|
instance = database.find_instance_by_domain(domain)
|
||||||
if not instance:
|
if not instance:
|
||||||
raise e.NotFound(f"No Instance found matching provided domain. Have you remembered to register it?")
|
raise e.NotFound(f"No Instance found matching provided domain. Have you remembered to register it?")
|
||||||
|
precheck_instances = database.get_all_hesitant_instances_by_dubious_id(instance.id)
|
||||||
|
instances = []
|
||||||
|
for instance in precheck_instances:
|
||||||
|
if instance.visibility_endorsements == enums.ListVisibility.ENDORSED:
|
||||||
|
if get_instance is None:
|
||||||
|
continue
|
||||||
|
if not instance.is_endorsing(get_instance):
|
||||||
|
continue
|
||||||
|
if instance.visibility_endorsements == enums.ListVisibility.PRIVATE:
|
||||||
|
if get_instance is None:
|
||||||
|
continue
|
||||||
|
if not instance != get_instance:
|
||||||
|
continue
|
||||||
|
instances.append(instance)
|
||||||
instance_details = []
|
instance_details = []
|
||||||
for c_instance in database.get_all_hesitant_instances_by_dubious_id(instance.id):
|
for c_instance in instances:
|
||||||
hesitations = database.get_all_hesitation_reasons_for_dubious_id(instance.id, [c_instance.id])
|
hesitations = database.get_all_hesitation_reasons_for_dubious_id(instance.id, [c_instance.id])
|
||||||
hesitations = [c for c in hesitations if c.reason is not None]
|
hesitations = [c for c in hesitations if c.reason is not None]
|
||||||
c_instance_details = c_instance.get_details()
|
c_instance_details = c_instance.get_details()
|
||||||
|
@ -149,9 +193,12 @@ class Hesitations(Resource):
|
||||||
evidence=evidence,
|
evidence=evidence,
|
||||||
)
|
)
|
||||||
db.session.add(new_hesitation)
|
db.session.add(new_hesitation)
|
||||||
|
target_domain = target_instance.domain
|
||||||
|
if instance.visibility_hesitations != enums.ListVisibility.OPEN:
|
||||||
|
target_domain = '[REDACTED]'
|
||||||
new_report = Report(
|
new_report = Report(
|
||||||
source_domain=instance.domain,
|
source_domain=instance.domain,
|
||||||
target_domain=target_instance.domain,
|
target_domain=target_domain,
|
||||||
report_type=enums.ReportType.HESITATION,
|
report_type=enums.ReportType.HESITATION,
|
||||||
report_activity=enums.ReportActivity.ADDED,
|
report_activity=enums.ReportActivity.ADDED,
|
||||||
)
|
)
|
||||||
|
@ -206,9 +253,12 @@ class Hesitations(Resource):
|
||||||
changed = True
|
changed = True
|
||||||
if changed is False:
|
if changed is False:
|
||||||
return {"message":'OK'}, 200
|
return {"message":'OK'}, 200
|
||||||
|
target_domain = target_instance.domain
|
||||||
|
if instance.visibility_hesitations != enums.ListVisibility.OPEN:
|
||||||
|
target_domain = '[REDACTED]'
|
||||||
new_report = Report(
|
new_report = Report(
|
||||||
source_domain=instance.domain,
|
source_domain=instance.domain,
|
||||||
target_domain=target_instance.domain,
|
target_domain=target_domain,
|
||||||
report_type=enums.ReportType.HESITATION,
|
report_type=enums.ReportType.HESITATION,
|
||||||
report_activity=enums.ReportActivity.MODIFIED,
|
report_activity=enums.ReportActivity.MODIFIED,
|
||||||
)
|
)
|
||||||
|
@ -245,9 +295,12 @@ class Hesitations(Resource):
|
||||||
if not hesitation:
|
if not hesitation:
|
||||||
return {"message":'OK'}, 200
|
return {"message":'OK'}, 200
|
||||||
db.session.delete(hesitation)
|
db.session.delete(hesitation)
|
||||||
|
target_domain = target_instance.domain
|
||||||
|
if instance.visibility_hesitations != enums.ListVisibility.OPEN:
|
||||||
|
target_domain = '[REDACTED]'
|
||||||
new_report = Report(
|
new_report = Report(
|
||||||
source_domain=instance.domain,
|
source_domain=instance.domain,
|
||||||
target_domain=target_instance.domain,
|
target_domain=target_domain,
|
||||||
report_type=enums.ReportType.HESITATION,
|
report_type=enums.ReportType.HESITATION,
|
||||||
report_activity=enums.ReportActivity.DELETED,
|
report_activity=enums.ReportActivity.DELETED,
|
||||||
)
|
)
|
||||||
|
|
|
@ -145,9 +145,12 @@ class WhitelistDomain(Resource):
|
||||||
patch_parser.add_argument("sysadmins", default=None, required=False, type=int, help="How many sysadmins this instance has.", location="json")
|
patch_parser.add_argument("sysadmins", default=None, required=False, type=int, help="How many sysadmins this instance has.", location="json")
|
||||||
patch_parser.add_argument("moderators", default=None, required=False, type=int, help="How many moderators this instance has.", location="json")
|
patch_parser.add_argument("moderators", default=None, required=False, type=int, help="How many moderators this instance has.", location="json")
|
||||||
patch_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")
|
patch_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")
|
||||||
|
patch_parser.add_argument("visibility_endorsements", required=False, type=str, location="json")
|
||||||
|
patch_parser.add_argument("visibility_censures", required=False, type=str, location="json")
|
||||||
|
patch_parser.add_argument("visibility_hesitations", required=False, type=str, location="json")
|
||||||
|
|
||||||
|
|
||||||
@api.expect(patch_parser,models.input_api_key_reset, validate=True)
|
@api.expect(patch_parser,models.input_instance_modify, validate=True)
|
||||||
@api.marshal_with(models.response_model_api_key_reset, code=200, description='Instances', skip_none=True)
|
@api.marshal_with(models.response_model_api_key_reset, code=200, description='Instances', skip_none=True)
|
||||||
@api.response(401, 'Invalid API Key', models.response_model_error)
|
@api.response(401, 'Invalid API Key', models.response_model_error)
|
||||||
@api.response(403, 'Instance Not Registered', models.response_model_error)
|
@api.response(403, 'Instance Not Registered', models.response_model_error)
|
||||||
|
@ -171,12 +174,26 @@ class WhitelistDomain(Resource):
|
||||||
instance.moderators = self.args.moderators
|
instance.moderators = self.args.moderators
|
||||||
changed = True
|
changed = True
|
||||||
if self.args.pm_proxy is not None:
|
if self.args.pm_proxy is not None:
|
||||||
logger.debug(self.args.pm_proxy)
|
|
||||||
proxy = enums.PMProxy[self.args.pm_proxy]
|
proxy = enums.PMProxy[self.args.pm_proxy]
|
||||||
if instance.pm_proxy != proxy:
|
if instance.pm_proxy != proxy:
|
||||||
activitypub_pm.pm_new_proxy_switch(proxy,instance.pm_proxy,instance,user.username)
|
activitypub_pm.pm_new_proxy_switch(proxy,instance.pm_proxy,instance,user.username)
|
||||||
instance.pm_proxy = proxy
|
instance.pm_proxy = proxy
|
||||||
changed = True
|
changed = True
|
||||||
|
if self.args.visibility_endorsements is not None:
|
||||||
|
visibility = enums.ListVisibility[self.args.visibility_endorsements]
|
||||||
|
if instance.visibility_endorsements != visibility:
|
||||||
|
instance.visibility_endorsements = visibility
|
||||||
|
changed = True
|
||||||
|
if self.args.visibility_censures is not None:
|
||||||
|
visibility = enums.ListVisibility[self.args.visibility_censures]
|
||||||
|
if instance.visibility_censures != visibility:
|
||||||
|
instance.visibility_censures = visibility
|
||||||
|
changed = True
|
||||||
|
if self.args.visibility_hesitations is not None:
|
||||||
|
visibility = enums.ListVisibility[self.args.visibility_hesitations]
|
||||||
|
if instance.visibility_hesitations != visibility:
|
||||||
|
instance.visibility_hesitations = visibility
|
||||||
|
changed = True
|
||||||
if self.args.admin_username:
|
if self.args.admin_username:
|
||||||
requestor = None
|
requestor = None
|
||||||
if self.args.admin_username != user.username or user.username == "fediseer":
|
if self.args.admin_username != user.username or user.username == "fediseer":
|
||||||
|
|
|
@ -100,7 +100,9 @@ class Instance(db.Model):
|
||||||
sysadmins = db.Column(db.Integer, unique=False, nullable=True)
|
sysadmins = db.Column(db.Integer, unique=False, nullable=True)
|
||||||
moderators = db.Column(db.Integer, unique=False, nullable=True)
|
moderators = db.Column(db.Integer, unique=False, nullable=True)
|
||||||
pm_proxy = db.Column(Enum(enums.PMProxy), default=enums.PMProxy.NONE, nullable=False)
|
pm_proxy = db.Column(Enum(enums.PMProxy), default=enums.PMProxy.NONE, nullable=False)
|
||||||
|
visibility_endorsements = db.Column(Enum(enums.ListVisibility), default=enums.ListVisibility.OPEN, nullable=False)
|
||||||
|
visibility_censures = db.Column(Enum(enums.ListVisibility), default=enums.ListVisibility.OPEN, nullable=False)
|
||||||
|
visibility_hesitations = db.Column(Enum(enums.ListVisibility), default=enums.ListVisibility.OPEN, nullable=False)
|
||||||
|
|
||||||
approvals = db.relationship("Endorsement", back_populates="approving_instance", cascade="all, delete-orphan", foreign_keys=[Endorsement.approving_id])
|
approvals = db.relationship("Endorsement", back_populates="approving_instance", cascade="all, delete-orphan", foreign_keys=[Endorsement.approving_id])
|
||||||
endorsements = db.relationship("Endorsement", back_populates="endorsed_instance", cascade="all, delete-orphan", foreign_keys=[Endorsement.endorsed_id])
|
endorsements = db.relationship("Endorsement", back_populates="endorsed_instance", cascade="all, delete-orphan", foreign_keys=[Endorsement.endorsed_id])
|
||||||
|
@ -166,3 +168,12 @@ class Instance(db.Model):
|
||||||
|
|
||||||
def is_claimed(self):
|
def is_claimed(self):
|
||||||
return len(self.admins) > 0
|
return len(self.admins) > 0
|
||||||
|
|
||||||
|
def is_endorsing(self,instance):
|
||||||
|
return instance in self.approvals
|
||||||
|
|
||||||
|
def is_censuring(self,instance):
|
||||||
|
return instance in self.censures_given
|
||||||
|
|
||||||
|
def is_hesitating(self,instance):
|
||||||
|
return instance in self.hesitations_given
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FEDISEER_VERSION = "0.15.0"
|
FEDISEER_VERSION = "0.16.0"
|
||||||
SUPPORTED_SOFTWARE = {
|
SUPPORTED_SOFTWARE = {
|
||||||
"lemmy",
|
"lemmy",
|
||||||
"mastodon",
|
"mastodon",
|
||||||
|
|
|
@ -16,3 +16,8 @@ class ReportActivity(enum.Enum):
|
||||||
class PMProxy(enum.Enum):
|
class PMProxy(enum.Enum):
|
||||||
NONE = 0
|
NONE = 0
|
||||||
MASTODON = 1
|
MASTODON = 1
|
||||||
|
|
||||||
|
class ListVisibility(enum.Enum):
|
||||||
|
OPEN = 0
|
||||||
|
ENDORSED = 1
|
||||||
|
PRIVATE = 2
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
CREATE TYPE listvisibility AS ENUM ('OPEN','ENDORSED','PRIVATE');
|
||||||
|
ALTER TABLE instances ADD COLUMN visibility_endorsements listvisibility default 'OPEN';
|
||||||
|
ALTER TABLE instances ADD COLUMN visibility_censures listvisibility default 'OPEN';
|
||||||
|
ALTER TABLE instances ADD COLUMN visibility_hesitations listvisibility default 'OPEN';
|
Loading…
Reference in New Issue