diff --git a/CHANGELOG.md b/CHANGELOG.md index ebf1864..d82a525 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # 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 * Added some rate limits. Currently each instance is limited to 20 actions per minute diff --git a/fediseer/apis/models/v1.py b/fediseer/apis/models/v1.py index 26200d5..8b600a0 100644 --- a/fediseer/apis/models/v1.py +++ b/fediseer/apis/models/v1.py @@ -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"), '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"), '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."), '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."), + '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', { 'source_domain': fields.String(description="The instance domain which initiated this activity", example="lemmy.dbzer0.com"), diff --git a/fediseer/apis/v1/censures.py b/fediseer/apis/v1/censures.py index 82db97b..a0d9423 100644 --- a/fediseer/apis/v1/censures.py +++ b/fediseer/apis/v1/censures.py @@ -6,6 +6,7 @@ from fediseer import enums class CensuresGiven(Resource): 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("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") @@ -16,17 +17,39 @@ class CensuresGiven(Resource): @cache.cached(timeout=10, query_string=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(401, 'API key not found', models.response_model_error) + @api.response(403, 'Access Denied', models.response_model_error) def get(self, domains_csv): '''Display all censures 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 censures together. ''' 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(',') - instances = database.find_multiple_instance_by_domains(domains_list) - if not instances: + 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?") - 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") instance_details = [] 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): 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("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") @@ -90,11 +114,30 @@ class Censures(Resource): '''Display all censures received by a specific domain ''' 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) if not instance: raise e.NotFound(f"No Instance found matching provided domain. Have you remembered to register it?") 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 = [c for c in censures if c.reason is not None] c_instance_details = c_instance.get_details() @@ -164,9 +207,12 @@ class Censures(Resource): evidence=evidence, ) db.session.add(new_censure) + target_domain = target_instance.domain + if instance.visibility_censures != enums.ListVisibility.OPEN: + target_domain = '[REDACTED]' new_report = Report( source_domain=instance.domain, - target_domain=target_instance.domain, + target_domain=target_domain, report_type=enums.ReportType.CENSURE, report_activity=enums.ReportActivity.ADDED, ) @@ -222,9 +268,12 @@ class Censures(Resource): changed = True if changed is False: return {"message":'OK'}, 200 + target_domain = target_instance.domain + if instance.visibility_censures != enums.ListVisibility.OPEN: + target_domain = '[REDACTED]' new_report = Report( source_domain=instance.domain, - target_domain=target_instance.domain, + target_domain=target_domain, report_type=enums.ReportType.CENSURE, report_activity=enums.ReportActivity.MODIFIED, ) @@ -260,9 +309,12 @@ class Censures(Resource): if not censure: return {"message":'OK'}, 200 db.session.delete(censure) + target_domain = target_instance.domain + if instance.visibility_censures != enums.ListVisibility.OPEN: + target_domain = '[REDACTED]' new_report = Report( source_domain=instance.domain, - target_domain=target_instance.domain, + target_domain=target_domain, report_type=enums.ReportType.CENSURE, report_activity=enums.ReportActivity.DELETED, ) diff --git a/fediseer/apis/v1/endorsements.py b/fediseer/apis/v1/endorsements.py index 57aa4f5..d1db63a 100644 --- a/fediseer/apis/v1/endorsements.py +++ b/fediseer/apis/v1/endorsements.py @@ -6,6 +6,7 @@ from fediseer.utils import sanitize_string class Approvals(Resource): 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("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") @@ -16,6 +17,8 @@ class Approvals(Resource): @cache.cached(timeout=10, query_string=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(401, 'API key not found', models.response_model_error) + @api.response(403, 'Access Denied', models.response_model_error) def get(self, domains_csv): '''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 @@ -23,9 +26,29 @@ class Approvals(Resource): ''' domains_list = domains_csv.split(',') self.args = self.get_parser.parse_args() - instances = database.find_multiple_instance_by_domains(domains_list) - if not instances: + 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") + 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?") + 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 = [] 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]) @@ -58,6 +81,7 @@ class Approvals(Resource): class Endorsements(Resource): 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("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") @@ -70,11 +94,30 @@ class Endorsements(Resource): '''Display all endorsements received by a specific domain ''' 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) if not instance: raise e.NotFound(f"No Instance found matching provided domain. Have you remembered to register it?") 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 = [e for e in endorsements if e.reason is not None] e_instance_details = e_instance.get_details() @@ -139,9 +182,12 @@ class Endorsements(Resource): reason=reason, ) db.session.add(new_endorsement) + target_domain = target_instance.domain + if instance.visibility_endorsements != enums.ListVisibility.OPEN: + target_domain = '[REDACTED]' new_report = Report( source_domain=instance.domain, - target_domain=target_instance.domain, + target_domain=target_domain, report_type=enums.ReportType.ENDORSEMENT, report_activity=enums.ReportActivity.ADDED, ) @@ -202,9 +248,12 @@ class Endorsements(Resource): changed = True if changed is False: return {"message":'OK'}, 200 + target_domain = target_instance.domain + if instance.visibility_endorsements != enums.ListVisibility.OPEN: + target_domain = '[REDACTED]' new_report = Report( source_domain=instance.domain, - target_domain=target_instance.domain, + target_domain=target_domain, report_type=enums.ReportType.ENDORSEMENT, report_activity=enums.ReportActivity.MODIFIED, ) @@ -242,9 +291,12 @@ class Endorsements(Resource): if not endorsement: return {"message":'OK'}, 200 db.session.delete(endorsement) + target_domain = target_instance.domain + if instance.visibility_endorsements != enums.ListVisibility.OPEN: + target_domain = '[REDACTED]' new_report = Report( source_domain=instance.domain, - target_domain=target_instance.domain, + target_domain=target_domain, report_type=enums.ReportType.ENDORSEMENT, report_activity=enums.ReportActivity.DELETED, ) diff --git a/fediseer/apis/v1/hesitations.py b/fediseer/apis/v1/hesitations.py index e575094..cce6b8e 100644 --- a/fediseer/apis/v1/hesitations.py +++ b/fediseer/apis/v1/hesitations.py @@ -6,6 +6,7 @@ from fediseer import enums class HesitationsGiven(Resource): 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("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") @@ -16,17 +17,40 @@ class HesitationsGiven(Resource): @cache.cached(timeout=10, query_string=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(401, 'API key not found', models.response_model_error) + @api.response(403, 'Access Denied', models.response_model_error) def get(self, domains_csv): '''Display all hesitations 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 hesitations together. ''' 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(',') - instances = database.find_multiple_instance_by_domains(domains_list) - if not instances: + 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?") - 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") instance_details = [] 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): 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("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") @@ -75,11 +100,30 @@ class Hesitations(Resource): '''Display all hesitations received by a specific domain ''' 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) if not instance: 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 = [] - 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 = [c for c in hesitations if c.reason is not None] c_instance_details = c_instance.get_details() @@ -149,9 +193,12 @@ class Hesitations(Resource): evidence=evidence, ) db.session.add(new_hesitation) + target_domain = target_instance.domain + if instance.visibility_hesitations != enums.ListVisibility.OPEN: + target_domain = '[REDACTED]' new_report = Report( source_domain=instance.domain, - target_domain=target_instance.domain, + target_domain=target_domain, report_type=enums.ReportType.HESITATION, report_activity=enums.ReportActivity.ADDED, ) @@ -206,9 +253,12 @@ class Hesitations(Resource): changed = True if changed is False: return {"message":'OK'}, 200 + target_domain = target_instance.domain + if instance.visibility_hesitations != enums.ListVisibility.OPEN: + target_domain = '[REDACTED]' new_report = Report( source_domain=instance.domain, - target_domain=target_instance.domain, + target_domain=target_domain, report_type=enums.ReportType.HESITATION, report_activity=enums.ReportActivity.MODIFIED, ) @@ -245,9 +295,12 @@ class Hesitations(Resource): if not hesitation: return {"message":'OK'}, 200 db.session.delete(hesitation) + target_domain = target_instance.domain + if instance.visibility_hesitations != enums.ListVisibility.OPEN: + target_domain = '[REDACTED]' new_report = Report( source_domain=instance.domain, - target_domain=target_instance.domain, + target_domain=target_domain, report_type=enums.ReportType.HESITATION, report_activity=enums.ReportActivity.DELETED, ) diff --git a/fediseer/apis/v1/whitelist.py b/fediseer/apis/v1/whitelist.py index 6615991..c8cf29c 100644 --- a/fediseer/apis/v1/whitelist.py +++ b/fediseer/apis/v1/whitelist.py @@ -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("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("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.response(401, 'Invalid API Key', 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 changed = True if self.args.pm_proxy is not None: - logger.debug(self.args.pm_proxy) proxy = enums.PMProxy[self.args.pm_proxy] if instance.pm_proxy != proxy: activitypub_pm.pm_new_proxy_switch(proxy,instance.pm_proxy,instance,user.username) instance.pm_proxy = proxy 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: requestor = None if self.args.admin_username != user.username or user.username == "fediseer": diff --git a/fediseer/classes/instance.py b/fediseer/classes/instance.py index 1bdf88f..8f9a4c3 100644 --- a/fediseer/classes/instance.py +++ b/fediseer/classes/instance.py @@ -100,7 +100,9 @@ class Instance(db.Model): sysadmins = 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) - + 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]) endorsements = db.relationship("Endorsement", back_populates="endorsed_instance", cascade="all, delete-orphan", foreign_keys=[Endorsement.endorsed_id]) @@ -165,4 +167,13 @@ class Instance(db.Model): db.session.commit() def is_claimed(self): - return len(self.admins) > 0 \ No newline at end of file + 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 diff --git a/fediseer/consts.py b/fediseer/consts.py index 039ede2..c94b398 100644 --- a/fediseer/consts.py +++ b/fediseer/consts.py @@ -1,4 +1,4 @@ -FEDISEER_VERSION = "0.15.0" +FEDISEER_VERSION = "0.16.0" SUPPORTED_SOFTWARE = { "lemmy", "mastodon", diff --git a/fediseer/enums.py b/fediseer/enums.py index 76aebae..dd06d40 100644 --- a/fediseer/enums.py +++ b/fediseer/enums.py @@ -16,3 +16,8 @@ class ReportActivity(enum.Enum): class PMProxy(enum.Enum): NONE = 0 MASTODON = 1 + +class ListVisibility(enum.Enum): + OPEN = 0 + ENDORSED = 1 + PRIVATE = 2 diff --git a/sql_statements/0.16.0.txt b/sql_statements/0.16.0.txt new file mode 100644 index 0000000..913c247 --- /dev/null +++ b/sql_statements/0.16.0.txt @@ -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';