def test_permission_for_subscriber(self): self.archive.newSubscription( self.subscriber, registrant=self.archive.owner) with person_logged_in(self.subscriber): self.assertTrue( check_permission('launchpad.SubscriberView', self.archive)) self.assertFalse(check_permission('launchpad.View', self.archive))
def test_permission_for_subscriber(self): self.archive.newSubscription(self.subscriber, registrant=self.archive.owner) with person_logged_in(self.subscriber): self.assertTrue( check_permission('launchpad.SubscriberView', self.archive)) self.assertFalse(check_permission('launchpad.View', self.archive))
def test_branch_permission(self): #Calling check_permission is used to show that the AccessBranch is in #fact configured correctly. branch = self.factory.makeBranch() login(ANONYMOUS) self.assertTrue(check_permission('launchpad.View', branch)) login('*****@*****.**') self.assertTrue(check_permission('launchpad.View', branch))
def test_admin_can_edit(self): admin = getUtility(IPersonSet).getByEmail('*****@*****.**') login_person(admin) view = create_initialized_view(self.target, '+edit') if IDistributionSourcePackage.providedBy(self.target): self.assertTrue(check_permission('launchpad.BugSupervisor', view)) else: self.assertTrue(check_permission('launchpad.Edit', view))
def test_NameBlacklist_permissions(self): # Verify that non-registry-experts do not have permission to # access the NameBlacklist. name_blacklist = self.name_blacklist_set.create(u'foo') self.assertTrue(check_permission('launchpad.View', name_blacklist)) self.assertTrue(check_permission('launchpad.Edit', name_blacklist)) login(ANONYMOUS) self.assertFalse(check_permission('launchpad.View', name_blacklist)) self.assertFalse(check_permission('launchpad.Edit', name_blacklist))
def test_permissions(self): # Team admins and privileged users can see the view others cannot. team = self.makeTeamWithMailingList() member = self.factory.makePerson() with person_logged_in(team.teamowner): team.addMember(member, team.teamowner) view = create_initialized_view(team, name='+mailinglist-moderate') self.assertIs(True, check_permission('launchpad.Edit', view)) with person_logged_in(member): self.assertIs(False, check_permission('launchpad.Edit', view))
def test_view_private_archive(self): """Recipebuilds with private branches are restricted.""" owner = self.factory.makePerson() archive = self.factory.makeArchive(owner=owner, private=True) with person_logged_in(owner): build = self.factory.makeSourcePackageRecipeBuild(archive=archive) self.assertTrue(check_permission('launchpad.View', build)) with person_logged_in(self.factory.makePerson()): self.assertFalse(check_permission('launchpad.View', build)) login(ANONYMOUS) self.assertFalse(check_permission('launchpad.View', build))
def is_langpack_admin(self, action=None): """Find out if the current user is a Language Packs Admin. This group of users have launchpad.LanguagePacksAdmin rights on the DistroSeries but are not general Rosetta admins. :returns: True if the user is a Language Pack Admin (but not a Rosetta admin).""" return (check_permission("launchpad.LanguagePacksAdmin", self.context) and not check_permission("launchpad.TranslationsAdmin", self.context))
def test_edit_team_view_permission(self): # Only an administrator or the team owner of a team can # change the details of that team. person = self.factory.makePerson() owner = self.factory.makePerson() team = self.factory.makeTeam(owner=owner) view = create_view(team, '+edit') login_person(person) self.assertFalse(check_permission('launchpad.Edit', view)) login_person(owner) self.assertTrue(check_permission('launchpad.Edit', view))
def test_precaching_permissions(self): # The precache_permission_for_objects function updates the security # policy cache for the permission specified. class Boring(object): """A boring, but weakref-able object.""" objects = [Boring(), Boring()] request = LaunchpadTestRequest() login(ANONYMOUS, request) precache_permission_for_objects(request, 'launchpad.View', objects) # Confirm that the objects have the permission set. self.assertTrue(check_permission('launchpad.View', objects[0])) self.assertTrue(check_permission('launchpad.View', objects[1]))
def nominate(self): """Return the 'Target/Nominate for series' Link.""" launchbag = getUtility(ILaunchBag) target = launchbag.product or launchbag.distribution if check_permission("launchpad.Driver", target): text = "Target to series" return Link('+nominate', text, icon='milestone') elif (check_permission("launchpad.BugSupervisor", target) or self.user is None): text = 'Nominate for series' return Link('+nominate', text, icon='milestone') else: return Link('+nominate', '', enabled=False, icon='milestone')
def test_reviewer_can_edit_git_merge_proposal(self): person = self.factory.makePerson() product = self.factory.makeProduct() [target] = self.factory.makeGitRefs(target=product) [source] = self.factory.makeGitRefs(target=product) mp = self.factory.makeBranchMergeProposalForGit(source_ref=source, target_ref=target) with person_logged_in(person): self.assertFalse(check_permission('launchpad.Edit', mp)) with admin_logged_in(): target.repository.reviewer = person with person_logged_in(person): self.assertTrue(check_permission('launchpad.Edit', mp))
def test_view_private_branch(self): """Recipebuilds with private branches are restricted.""" owner = self.factory.makePerson() branch = self.factory.makeAnyBranch(owner=owner) with person_logged_in(owner): recipe = self.factory.makeSourcePackageRecipe(branches=[branch]) build = self.factory.makeSourcePackageRecipeBuild(recipe=recipe) self.assertTrue(check_permission('launchpad.View', build)) removeSecurityProxy(branch).information_type = ( InformationType.USERDATA) with person_logged_in(self.factory.makePerson()): self.assertFalse(check_permission('launchpad.View', build)) login(ANONYMOUS) self.assertFalse(check_permission('launchpad.View', build))
def _getUnsubscribeNotification(self, user, unsubed_dupes): """Construct and return the unsubscribe-from-bug feedback message. :user: The IPerson or ITeam that was unsubscribed from the bug. :unsubed_dupes: The list of IBugs that are dupes from which the user was unsubscribed. """ current_bug = self.context.bug current_user = self.user unsubed_dupes_msg_fragment = self._getUnsubscribedDupesMsgFragment( unsubed_dupes) if user == current_user: # Consider that the current user may have been "locked out" # of a bug if they unsubscribed themselves from a private # bug! if check_permission("launchpad.View", current_bug): # The user still has permission to see this bug, so no # special-casing needed. return structured( "You have been unsubscribed from bug %s%s.", current_bug.id, unsubed_dupes_msg_fragment).escapedtext else: return structured( "You have been unsubscribed from bug %s%s. You no " "longer have access to this private bug.", current_bug.id, unsubed_dupes_msg_fragment).escapedtext else: return structured( "%s has been unsubscribed from bug %s%s.", user.displayname, current_bug.id, unsubed_dupes_msg_fragment).escapedtext
def search_action(self, action, data): """The Action executed when the user uses the search button. Saves the user submitted search parameters in an instance attribute. """ self.search_params.update(**data) self._updateSearchParams() if self.text is None: return if self.start == 0: numeric_token = self._getNumericToken(self.text) if numeric_token is not None: try: bug = getUtility(IBugSet).get(numeric_token) if check_permission("launchpad.View", bug): self._bug = bug except NotFoundError: # Let self._bug remain None. pass self._question = getUtility(IQuestionSet).get(numeric_token) name_token = self._getNameToken(self.text) if name_token is not None: self._person_or_team = self._getPersonOrTeam(name_token) self._pillar = self._getDistributionOrProductOrProjectGroup( name_token) self._pages = self.searchPages(self.text, start=self.start)
def traverse(self, name): """Return the IPOTemplate associated with the given name.""" assert self.request.method in [ 'GET', 'HEAD', 'PATCH', 'POST' ], ('We only know about GET, HEAD, PATCH and POST') # Get the requested potemplate. potemplate = self.context.getPOTemplateByName(name) if potemplate is None: # The template doesn't exist. raise NotFoundError(name) # Get whether the target for the requested template is officially # using Launchpad Translations. if potemplate.distribution is None: product_or_distro = potemplate.productseries.product else: product_or_distro = potemplate.distroseries.distribution translations_usage = product_or_distro.translations_usage if (service_uses_launchpad(translations_usage) and potemplate.iscurrent): # This template is available for translation. return potemplate elif check_permission('launchpad.TranslationsAdmin', potemplate): # User has Edit privileges for this template and can access it. return potemplate else: raise NotFoundError(name)
def sharing_details(self): """Construct the link to the sharing details page.""" tag_template = ( '<a class="sprite %(icon)s" id="sharing-details"' ' href="%(href)s">%(text)s</a>') sourcepackage = self.getTranslationSourcePackage() if sourcepackage is None: return "" productseries = sourcepackage.productseries can_edit_upstream = ( productseries is None or check_permission('launchpad.Edit', productseries)) if can_edit_upstream: icon = 'edit' if self.is_sharing(): text = "Edit sharing details" else: text = "Set up sharing" else: icon = 'info' text = "View sharing details" href = canonical_url( sourcepackage, rootsite='translations', view_name='+sharing-details') return tag_template % dict(icon=icon, text=text, href=href)
def getRelatedSeriesBranchInfo(self, parent_branch, limit_results=None): """See `IBranchTarget`.""" sorted_series = [] for series in self.product.series: if (series.status != SeriesStatus.OBSOLETE and series != self.product.development_focus): sorted_series.append(series) # Now sort the list by name with newer versions before older. sorted_series = sorted_version_numbers(sorted_series, key=attrgetter('name')) # Add the development focus first. sorted_series.insert(0, self.product.development_focus) result = [] for series in sorted_series: try: branch = get_linked_to_branch(series).branch if (branch not in result and branch != parent_branch and check_permission('launchpad.View', branch)): result.append((branch, series)) except NoLinkedBranch: # If there's no branch for a particular series, we don't care. pass if limit_results is not None: # We only want the most recent branches result = result[:limit_results] return result
def can_configure_answers(self): """Can the user configure answers for the `IQuestionTarget`.""" target = self.context if IProduct.providedBy(target) or IDistribution.providedBy(target): return check_permission('launchpad.Edit', self.context) else: return False
def traverse(self, name): """Return the IPOTemplate associated with the given name.""" assert self.request.method in ['GET', 'HEAD', 'PATCH', 'POST'], ( 'We only know about GET, HEAD, PATCH and POST') # Get the requested potemplate. potemplate = self.context.getPOTemplateByName(name) if potemplate is None: # The template doesn't exist. raise NotFoundError(name) # Get whether the target for the requested template is officially # using Launchpad Translations. if potemplate.distribution is None: product_or_distro = potemplate.productseries.product else: product_or_distro = potemplate.distroseries.distribution translations_usage = product_or_distro.translations_usage if (service_uses_launchpad(translations_usage) and potemplate.iscurrent): # This template is available for translation. return potemplate elif check_permission('launchpad.TranslationsAdmin', potemplate): # User has Edit privileges for this template and can access it. return potemplate else: raise NotFoundError(name)
def test_direct_answer_contact_cannot_delete(self): # Answer contacts are broad, and deletion is irreversible, so # they cannot do it themselves. direct_answer_contact = self.factory.makePerson() with person_logged_in(direct_answer_contact): self.addAnswerContact(direct_answer_contact) self.assertFalse(check_permission('launchpad.Delete', self.faq))
def ensureAccessGrants(self, grantees, user, branches=None, bugs=None, specifications=None, ignore_permissions=False): """See `ISharingService`.""" artifacts = [] if branches: artifacts.extend(branches) if bugs: artifacts.extend(bugs) if specifications: artifacts.extend(specifications) if not ignore_permissions: # The user needs to have launchpad.Edit permission on all supplied # bugs and branches or else we raise an Unauthorized exception. for artifact in artifacts or []: if not check_permission('launchpad.Edit', artifact): raise Unauthorized # Ensure there are access artifacts associated with the bugs and # branches. artifacts = getUtility(IAccessArtifactSource).ensure(artifacts) aagsource = getUtility(IAccessArtifactGrantSource) artifacts_with_grants = [ artifact_grant.abstract_artifact for artifact_grant in aagsource.find(product(artifacts, grantees))] # Create access to bugs/branches for the specified grantee for which a # grant does not already exist. missing_artifacts = set(artifacts) - set(artifacts_with_grants) getUtility(IAccessArtifactGrantSource).grant( list(product(missing_artifacts, grantees, [user])))
def can_configure_answers(self): """Can the user configure answers for the `IQuestionTarget`.""" target = self.context if IProduct.providedBy(target) or IDistribution.providedBy(target): return check_permission("launchpad.Edit", self.context) else: return False
def user_can_retry_build(self): """Return True if the user is permitted to Retry Build. The build must be re-tryable. """ return (check_permission('launchpad.Edit', self.context) and self.context.can_be_retried)
def traverse(self, name): # Make /bugs/$bug.id, /bugs/$bug.name /malone/$bug.name and # /malone/$bug.id Just Work bug = getUtility(IBugSet).getByNameOrID(name) if not check_permission("launchpad.View", bug): return None return bug
def subscriptions(self): """Return a decorated list of branch subscriptions.""" # Cache permissions so private subscribers can be rendered. # The security adaptor will do the job also but we don't want or need # the expense of running several complex SQL queries. subscriptions = list(self.context.subscriptions) person_ids = [sub.personID for sub in subscriptions] list( getUtility(IPersonSet).getPrecachedPersonsFromIDs( person_ids, need_validity=True)) if self.user is not None: subscribers = [ subscription.person for subscription in subscriptions ] precache_permission_for_objects(self.request, "launchpad.LimitedView", subscribers) visible_subscriptions = [ subscription for subscription in subscriptions if check_permission('launchpad.LimitedView', subscription.person) ] return sorted(visible_subscriptions, key=lambda subscription: subscription.person.displayname)
def check_distroseries_translations_viewable(distroseries): """Check that these distribution series translations are visible. Launchpad admins, Translations admins, and users with admin rights on the `IDistroSeries` are always allowed. Checks the `hide_all_translations` flag. If it is set, these translations are not to be shown to the public. In that case an appropriate message is composed based on the series' `status`, and a `TranslationUnavailable` exception is raised. :return: Returns normally if this series' translations are viewable to the current user. :raise TranslationUnavailable: if this series' translations are hidden and the user is not one of the limited caste that is allowed to access them. """ if not distroseries.hide_all_translations: # Yup, viewable. return if check_permission("launchpad.TranslationsAdmin", distroseries): return future = [SeriesStatus.EXPERIMENTAL, SeriesStatus.DEVELOPMENT, SeriesStatus.FUTURE] if distroseries.status in future: raise TranslationUnavailable("Translations for this release series are not available yet.") elif distroseries.status == SeriesStatus.OBSOLETE: raise TranslationUnavailable("This release series is obsolete. Its translations are no " "longer available.") else: raise TranslationUnavailable( "Translations for this release series are not currently " "available. Please come back soon." )
def can_configure_blueprints(self): """Can the user configure blueprints for the `ISpecificationTarget`. """ target = self.context if IProduct.providedBy(target) or IDistribution.providedBy(target): return check_permission('launchpad.Edit', self.context) else: return False
def has_exports_enabled(self): """Should information about automatic exports be displayed? Will be True if an export branch exists for the series and if the user is allowed to view that branch branch.""" return self.context.translations_branch is not None and ( check_permission("launchpad.View", self.context.translations_branch) )
def userIsActiveTeamMember(team): """Return True if the user is an active member of this team.""" user = getUtility(ILaunchBag).user if user is None: return False if not check_permission('launchpad.View', team): return False return user in team.activemembers
def __init__(self, *args, **kwargs): super(PersonTranslationView, self).__init__(*args, **kwargs) now = datetime.now(pytz.timezone('UTC')) # Down-to-the-second detail isn't important so the hope is that this # will result in faster queries (cache effects). today = now.replace(minute=0, second=0, microsecond=0) self.history_horizon = today - timedelta(90, 0, 0) self.user_can_edit = check_permission('launchpad.Edit', self.context)
def bugsWithPermission(self): """Return the bugs that the user has permission to remove. This exclude private bugs to which the user doesn't have any permission. """ return [ bug for bug in self.context.bugs if check_permission('launchpad.View', bug) ]
def _getPersonOrTeam(self, name): """Return the matching active person or team.""" person_or_team = getUtility(IPersonSet).getByName(name) if (person_or_team is not None and person_or_team.is_valid_person_or_team and check_permission('launchpad.View', person_or_team)): return person_or_team return None
def test_target_driver_has_edit_rights(self): """Drivers of a blueprint's target can edit that blueprint.""" product = self.factory.makeProduct() driver = self.factory.makePerson() removeSecurityProxy(product).driver = driver specification = self.factory.makeSpecification(product=product) login_person(driver) self.assertTrue(check_permission('launchpad.Edit', specification))
def enable_blacklist_options(self): """Should we enable the blacklisting (ignore) radio widget options. Only enable the options if an editor requests via JS and the user is an archive admin. """ return self.request.is_ajax and check_permission( 'launchpad.Admin', self.context)
def has_exports_enabled(self): """Should information about automatic exports be displayed? Will be True if an export branch exists for the series and if the user is allowed to view that branch branch.""" return self.context.translations_branch is not None and ( check_permission("launchpad.View", self.context.translations_branch))
def test_public_build_private_team_no_permission(self): # A `PackageBuild` for a public `SourcePackageRelease` in an archive # for a private team is rendered gracefully when the user has no # permission. build, _, _ = self._make_public_build_for_private_team() # Make sure this is a valid test; the build itself must be public. self.assertTrue(check_permission('launchpad.View', build)) self.assertEqual('private job', format_link(build))
def getVisibleArtifacts(self, person, branches=None, bugs=None, specifications=None, ignore_permissions=False): """See `ISharingService`.""" bugs_by_id = {} branches_by_id = {} for bug in bugs or []: if (not ignore_permissions and not check_permission('launchpad.View', bug)): raise Unauthorized bugs_by_id[bug.id] = bug for branch in branches or []: if (not ignore_permissions and not check_permission('launchpad.View', branch)): raise Unauthorized branches_by_id[branch.id] = branch for spec in specifications or []: if (not ignore_permissions and not check_permission('launchpad.View', spec)): raise Unauthorized # Load the bugs. visible_bug_ids = [] if bugs_by_id: param = BugTaskSearchParams( user=person, bug=any(*bugs_by_id.keys())) visible_bug_ids = set(getUtility(IBugTaskSet).searchBugIds(param)) visible_bugs = [bugs_by_id[bug_id] for bug_id in visible_bug_ids] # Load the branches. visible_branches = [] if branches_by_id: all_branches = getUtility(IAllBranches) wanted_branches = all_branches.visibleByUser(person).withIds( *branches_by_id.keys()) visible_branches = list(wanted_branches.getBranches()) visible_specs = [] if specifications: visible_private_spec_ids = self._getVisiblePrivateSpecificationIDs( person, specifications) visible_specs = [ spec for spec in specifications if spec.id in visible_private_spec_ids or not spec.private] return visible_bugs, visible_branches, visible_specs
def test_default_request(self): # If no request is provided, the current interaction is used. class Boring(object): """A boring, but weakref-able object.""" obj = Boring() request = LaunchpadTestRequest() login(ANONYMOUS, request) precache_permission_for_objects(None, 'launchpad.View', [obj]) self.assertTrue(check_permission('launchpad.View', obj))
def userIsDriver(self): """Has the current user driver permissions?""" # We only want to look at this if the target is a # distribution source package, in order to maintain # compatibility with the obsolete bug contacts feature. if IDistributionSourcePackage.providedBy(self.context): return check_permission( "launchpad.Driver", self.context.distribution) else: return False
def initial_values(self): """Set initial values for the widgets. The distroseries function as defaults for requesting a build. """ initial_values = {'distroseries': self.context.distroseries} if self.context.daily_build_archive and check_permission( 'launchpad.Append', self.context.daily_build_archive): initial_values['archive'] = self.context.daily_build_archive return initial_values
def has_imports_enabled(self): """Should information about automatic imports be displayed? Will be True if imports are enabled for the series and if the user is allowed to view to the import branch.""" return ( self.context.branch is not None and check_permission("launchpad.View", self.context.branch) and self.context.translations_autoimport_mode != TranslationsBranchImportMode.NO_IMPORT )