def canBeUnsubscribedByUser(self, user): """See `ISpecificationSubscription`.""" if user is None: return False if not IPersonRoles.providedBy(user): user = IPersonRoles(user) if ( user.inTeam(self.specification.owner) or user.inTeam(self.person) or user.in_admin): return True # XXX Abel Deuring 2012-11-21, bug=1081677 # People who subscribed users should be able to unsubscribe # them again, similar to branch subscriptions. This is # essential if somebody was erroneuosly subscribed to a # proprietary or embargoed specification. Unfortunately, # SpecificationSubscription does not record who subscribed # somebody else, but if the specification is private, we can # check who issued the artifact grant. artifacts = getUtility(IAccessArtifactSource).find( [self.specification]) wanted = [(artifact, self.person) for artifact in artifacts] if len(wanted) == 0: return False for grant in getUtility(IAccessArtifactGrantSource).find(wanted): if user.inTeam(grant.grantor): return True return False
def test_isOneOfDrivers(self): # The person can be one of multiple drivers of if an object # implements IHasDrivers. productseries = self.factory.makeProductSeries() productseries.product.driver = self.person productseries.driver = self.factory.makePerson() roles = IPersonRoles(self.person) self.assertTrue(roles.isOneOfDrivers(productseries))
def test_isOneOf_None(self): # Objects may have multiple roles that a person can fulfill. # Specifications are such a case. Some roles may be None. spec = removeSecurityProxy(self.factory.makeSpecification()) spec.owner = self.factory.makePerson() spec.drafter = None spec.assignee = None spec.approver = self.person roles = IPersonRoles(self.person) self.assertTrue(roles.isOneOf( spec, ['owner', 'drafter', 'assignee', 'approver']))
def test_members_of_parent_teams_get_limited_view(self): team_owner = self.factory.makePerson() private_team = self.factory.makeTeam( owner=team_owner, visibility=PersonVisibility.PRIVATE) public_team = self.factory.makeTeam(owner=team_owner) team_user = self.factory.makePerson() other_user = self.factory.makePerson() with person_logged_in(team_owner): public_team.addMember(team_user, team_owner) public_team.addMember(private_team, team_owner) checker = PublicOrPrivateTeamsExistence( removeSecurityProxy(private_team)) self.assertTrue(checker.checkAuthenticated(IPersonRoles(team_user))) self.assertFalse(checker.checkAuthenticated(IPersonRoles(other_user)))
def test_in_teams(self): # Test all celebrity teams are available. for name, team in self._get_person_celebrities(is_team=True): roles_attribute = self.prefix + name roles = IPersonRoles(self.person) self.assertFalse( getattr(roles, roles_attribute), "%s should be False" % roles_attribute) team.addMember(self.person, team.teamowner) roles = IPersonRoles(self.person) self.assertTrue( getattr(roles, roles_attribute), "%s should be True" % roles_attribute) self.person.leave(team)
def get_specification_privacy_filter(user): # Circular imports. from lp.registry.model.accesspolicy import AccessPolicyGrant public_spec_filter = ( Specification.information_type.is_in(PUBLIC_INFORMATION_TYPES)) if user is None: return [public_spec_filter] elif IPersonRoles.providedBy(user): user = user.person artifact_grant_query = Coalesce( ArrayIntersects( SQL('Specification.access_grants'), Select( ArrayAgg(TeamParticipation.teamID), tables=TeamParticipation, where=(TeamParticipation.person == user) )), False) policy_grant_query = Coalesce( ArrayIntersects( Array(SQL('Specification.access_policy')), Select( ArrayAgg(AccessPolicyGrant.policy_id), tables=(AccessPolicyGrant, Join(TeamParticipation, TeamParticipation.teamID == AccessPolicyGrant.grantee_id)), where=(TeamParticipation.person == user) )), False) return [Or(public_spec_filter, artifact_grant_query, policy_grant_query)]
def get_specification_privacy_filter(user): # Circular imports. from lp.registry.model.accesspolicy import AccessPolicyGrant public_spec_filter = ( Specification.information_type.is_in(PUBLIC_INFORMATION_TYPES)) if user is None: return [public_spec_filter] elif IPersonRoles.providedBy(user): user = user.person artifact_grant_query = Coalesce( ArrayIntersects( SQL('Specification.access_grants'), Select(ArrayAgg(TeamParticipation.teamID), tables=TeamParticipation, where=(TeamParticipation.person == user))), False) policy_grant_query = Coalesce( ArrayIntersects( Array(SQL('Specification.access_policy')), Select(ArrayAgg(AccessPolicyGrant.policy_id), tables=(AccessPolicyGrant, Join( TeamParticipation, TeamParticipation.teamID == AccessPolicyGrant.grantee_id)), where=(TeamParticipation.person == user))), False) return [Or(public_spec_filter, artifact_grant_query, policy_grant_query)]
def _getTemplateParams(self, email, recipient): params = BaseMailer._getTemplateParams(self, email, recipient) reason, rationale = self._recipients.getReason(email) branch = reason.branch params['unique_name'] = branch.unique_name params['branch_identity'] = branch.identity params['branch_url'] = canonical_url(branch) if reason.recipient in branch.subscribers: # Give subscribers a link to unsubscribe. # XXX cjwatson 2015-04-15: Perhaps GitRef:+edit-subscription # should be made to work? if IGitRef.providedBy(branch): unsubscribe_url = canonical_url(branch.repository) else: unsubscribe_url = canonical_url(branch) params['unsubscribe'] = ("\nTo unsubscribe from this branch go to " "%s/+edit-subscription" % unsubscribe_url) else: params['unsubscribe'] = '' params['diff'] = self.contents or '' if not self._includeDiff(email): params['diff'] += self._explainNotPresentDiff(email) if self.delta_for_editors_text is not None: authz = getAdapter(branch, IAuthorization, 'launchpad.Edit') if authz.checkAuthenticated(IPersonRoles(recipient)): params['delta'] = self.delta_for_editors_text else: params['delta'] = self.delta_text or '' else: params['delta'] = self.delta_text or '' params.update(self.extra_template_params) return params
def test_is_person(self): # All celebrity persons are available. for name, celeb in self._get_person_celebrities(is_team=False): roles_attribute = self.prefix + name roles = IPersonRoles(celeb) self.assertTrue( getattr(roles, roles_attribute), "%s should be True" % roles_attribute)
def getSharedProjects(self, person, user): """See `ISharingService`.""" commercial_filter = None if user and IPersonRoles(user).in_commercial_admin: commercial_filter = Exists(Select( 1, tables=CommercialSubscription, where=CommercialSubscription.product == Product.id)) return self._getSharedPillars(person, user, Product, commercial_filter)
def test_in_AttributeError(self): # Do not check for non-existent attributes, even if it has the # right prefix. roles = IPersonRoles(self.person) fake_attr = self.factory.getUniqueString() self.assertRaises(AttributeError, getattr, roles, fake_attr) fake_attr = self.factory.getUniqueString(self.prefix) self.assertRaises(AttributeError, getattr, roles, fake_attr)
def test_visible_to_administrator(self): # Launchpad administrators often have a need to see private # Launchpad things in order to fix up fubars by users. branch = self.factory.makeBranch( information_type=InformationType.USERDATA) naked_branch = removeSecurityProxy(branch) admin = getUtility(ILaunchpadCelebrities).admin.teamowner access = AccessBranch(naked_branch) self.assertTrue(access.checkAuthenticated(IPersonRoles(admin)))
def canBeUnsubscribedByUser(self, user): """See `IQuestionSubscription`.""" if user is None: return False # The people who can unsubscribe someone are: # - lp admins # - the person themselves # - the question owner # - people who can reject questions (eg target owner, answer contacts) return (user.inTeam(self.question.owner) or user.inTeam(self.person) or IPersonRoles(user).in_admin or self.question.canReject(user))
def canBeUnsubscribedByUser(self, user): """See `ISpecificationSubscription`.""" if user is None: return False if not IPersonRoles.providedBy(user): user = IPersonRoles(user) if (user.inTeam(self.specification.owner) or user.inTeam(self.person) or user.in_admin): return True # XXX Abel Deuring 2012-11-21, bug=1081677 # People who subscribed users should be able to unsubscribe # them again, similar to branch subscriptions. This is # essential if somebody was erroneuosly subscribed to a # proprietary or embargoed specification. Unfortunately, # SpecificationSubscription does not record who subscribed # somebody else, but if the specification is private, we can # check who issued the artifact grant. artifacts = getUtility(IAccessArtifactSource).find( [self.specification]) wanted = [(artifact, self.person) for artifact in artifacts] if len(wanted) == 0: return False for grant in getUtility(IAccessArtifactGrantSource).find(wanted): if user.inTeam(grant.grantor): return True return False
def test_visible_to_owner(self): # The owners of a branch always have visibility of their own branches. owner = self.factory.makePerson() branch = self.factory.makeBranch( owner=owner, information_type=InformationType.USERDATA) naked_branch = removeSecurityProxy(branch) clear_cache() # Clear authorization cache for check_permission. access = AccessBranch(naked_branch) self.assertFalse(access.checkUnauthenticated()) self.assertTrue(access.checkAuthenticated(IPersonRoles(owner))) self.assertFalse(check_permission('launchpad.View', branch))
def test_visible_to_subscribers(self): # Branches that are not public are viewable by members of the # visibility_team and to subscribers. branch = self.factory.makeBranch( information_type=InformationType.USERDATA) naked_branch = removeSecurityProxy(branch) person = self.factory.makePerson() teamowner = self.factory.makePerson() team = self.factory.makeTeam( membership_policy=TeamMembershipPolicy.MODERATED, owner=teamowner, members=[person]) # Not visible to an unsubscribed person. access = AccessBranch(naked_branch) self.assertFalse(access.checkAuthenticated(IPersonRoles(person))) # Subscribing the team to the branch will allow access to the branch. naked_branch.subscribe(team, BranchSubscriptionNotificationLevel.NOEMAIL, BranchSubscriptionDiffSize.NODIFF, CodeReviewNotificationLevel.NOEMAIL, teamowner) self.assertTrue(access.checkAuthenticated(IPersonRoles(person)))
def initialize(self, series, is_distroseries=True): self._template_name_cache = {} self._packaging_cache = {} self.is_distroseries = is_distroseries if is_distroseries: self.distroseries = series else: self.productseries = series user = IPersonRoles(self.user, None) self.can_admin = (user is not None and (user.in_admin or user.in_rosetta_experts)) self.can_edit = (self.can_admin or check_permission( 'launchpad.TranslationsAdmin', series)) self.user_is_logged_in = (self.user is not None)
def test_branch_access(self): # Accessing any attributes of the Branch content class through the # IBranch interface is configured to require the launchpad.View # permission. The AccessBranch authorization class is used to # authorize users for the combination of the launchpad.View permission # and the IBranch interface. branch = self.factory.makeBranch() naked_branch = removeSecurityProxy(branch) self.assertTrue( isinstance( getAdapter(branch, IAuthorization, name='launchpad.View'), AccessBranch)) access = AccessBranch(naked_branch) self.assertTrue(access.checkUnauthenticated()) person = self.factory.makePerson() self.assertTrue(access.checkAuthenticated(IPersonRoles(person)))
def _getSharedPillars(self, person, user, pillar_class, extra_filter=None): """Helper method for getSharedProjects and getSharedDistributions. pillar_class is either Product or Distribution. Products define the owner foreign key attribute as _owner so we need to account for that, but otherwise the logic is the same for both pillar types. """ if user is None: return [] store = IStore(AccessPolicyGrantFlat) roles = IPersonRoles(user) if roles.in_admin: filter = True else: with_statement = With("teams", Select(TeamParticipation.teamID, tables=TeamParticipation, where=TeamParticipation.person == user.id)) teams_sql = SQL("SELECT team from teams") store = store.with_(with_statement) if IProduct.implementedBy(pillar_class): ownerID = pillar_class._ownerID else: ownerID = pillar_class.ownerID filter = Or( extra_filter or False, ownerID.is_in(teams_sql), pillar_class.driverID.is_in(teams_sql)) tables = [ AccessPolicyGrantFlat, Join( AccessPolicy, AccessPolicyGrantFlat.policy_id == AccessPolicy.id)] if IProduct.implementedBy(pillar_class): access_policy_column = AccessPolicy.product_id else: access_policy_column = AccessPolicy.distribution_id result_set = store.find( pillar_class, pillar_class.id.is_in( Select( columns=access_policy_column, tables=tables, where=(AccessPolicyGrantFlat.grantee_id == person.id)) ), filter) return result_set
def user_has_special_git_repository_access(user, repository=None): """Admins have special access. :param user: An `IPerson` or None. :param repository: An `IGitRepository` or None when checking collection access. """ if user is None: return False roles = IPersonRoles(user) if roles.in_admin: return True if repository is None: return False code_import = repository.code_import if code_import is None: return False return roles.in_vcs_imports
def assertTeamOwnerCanListPrivateTeamWithTeamStatus(self, team_status): main_team_owner = self.factory.makePerson() main_team = self.factory.makeTeam(owner=main_team_owner, visibility=PersonVisibility.PRIVATE) private_team_owner = self.factory.makePerson() private_team = self.factory.makeTeam( owner=private_team_owner, visibility=PersonVisibility.PRIVATE) with admin_logged_in(): # Cannot add a team with a non-APPROVED / PENDING status, so add # it as approved and then edit the membership. main_team.addMember(private_team, main_team_owner, status=TeamMembershipStatus.APPROVED, force_team_add=True) main_team.setMembershipData(private_team, team_status, main_team_owner) checker = PublicOrPrivateTeamsExistence( removeSecurityProxy(private_team)) self.assertTrue( checker.checkAuthenticated(IPersonRoles(main_team_owner)))
def get_bugsummary_filter_for_user(user): """Build a Storm expression to filter BugSummary by visibility. :param user: The user for which visible rows should be calculated. :return: (with_clauses, where_clauses) """ # Admins get to see every bug, everyone else only sees bugs # viewable by them-or-their-teams. # Note that because admins can see every bug regardless of # subscription they will see rather inflated counts. Admins get to # deal. public_filter = And(BugSummary.viewed_by_id == None, BugSummary.access_policy_id == None) if user is None: return [], [public_filter] elif IPersonRoles(user).in_admin: return [], [] else: with_clauses = [ With( 'teams', Select(TeamParticipation.teamID, tables=[TeamParticipation], where=(TeamParticipation.personID == user.id))), With( 'policies', Select(AccessPolicyGrant.policy_id, tables=[AccessPolicyGrant], where=(AccessPolicyGrant.grantee_id.is_in( SQL("SELECT team FROM teams"))))), ] where_clauses = [ Or( public_filter, BugSummary.viewed_by_id.is_in(SQL("SELECT team FROM teams")), BugSummary.access_policy_id.is_in( SQL("SELECT policy FROM policies"))) ] return with_clauses, where_clauses
def test_isOneOfDrivers_no_drivers(self): # If the object does not implement IHasDrivers, False is returned. sprint = self.factory.makeSprint() roles = IPersonRoles(self.person) self.assertFalse(roles.isOneOfDrivers(sprint))
def test_isBugSupervisor(self): # The person can be the bug supervisor of something, e.g. a product. product = self.factory.makeProduct(bug_supervisor=self.person) roles = IPersonRoles(self.person) self.assertTrue(roles.isBugSupervisor(product))
def test_interface(self): roles = IPersonRoles(self.person) verifyObject(IPersonRoles, roles)
def test_isOneOf_AttributeError(self): # Do not try to check for none-existent attributes. obj = self.factory.makeProduct() fake_attr = self.factory.getUniqueString() roles = IPersonRoles(self.person) self.assertRaises(AttributeError, roles.isOneOf, obj, [fake_attr])
def test_isDriver(self): # The person can be the driver of something, e.g. a sprint. sprint = self.factory.makeSprint() sprint.driver = self.person roles = IPersonRoles(self.person) self.assertTrue(roles.isDriver(sprint))
def test_isOwner(self): # The person can be the owner of something, e.g. a product. product = self.factory.makeProduct(owner=self.person) roles = IPersonRoles(self.person) self.assertTrue(roles.isOwner(product))
def test_inTeam_works(self): # Make sure it actually works. team = self.factory.makeTeam(self.person) roles = IPersonRoles(self.person) self.assertTrue(roles.inTeam(team))
def test_inTeam(self): # The method person.inTeam is available as the inTeam attribute. roles = IPersonRoles(self.person) self.assertEquals(self.person.inTeam, roles.inTeam)
def test_person(self): # The person is available through the person attribute. roles = IPersonRoles(self.person) self.assertIs(self.person, roles.person)
def canChangeExpirationDate(self, person): """See `ITeamMembership`.""" person_is_team_admin = self.team in person.getAdministratedTeams() person_is_lp_admin = IPersonRoles(person).in_admin return person_is_team_admin or person_is_lp_admin
def personHasDriverRights(self, person): """See `IHasDrivers`.""" person_roles = IPersonRoles(person) return (person_roles.isOneOfDrivers(self) or person_roles.isOwner(self) or person_roles.in_admin)