~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/canonical/launchpad/security.py

  • Committer: Launchpad Patch Queue Manager
  • Date: 2011-09-08 02:21:30 UTC
  • mfrom: (13843.9.12 sweep)
  • Revision ID: launchpad@pqm.canonical.com-20110908022130-c582qo5npmh2r37p
[r=gmb][bug=839784] Provide a mechanism for properly looking up
        security adapters for forwarding/chaining.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
from zope.component import (
13
13
    getAdapter,
14
14
    getUtility,
 
15
    queryAdapter,
15
16
    )
16
17
from zope.interface import Interface
17
18
 
37
38
from lp.app.security import (
38
39
    AnonymousAuthorization,
39
40
    AuthorizationBase,
 
41
    DelegatedAuthorization,
40
42
    )
41
43
from lp.archivepublisher.interfaces.publisherconfig import IPublisherConfig
42
44
from lp.blueprints.interfaces.specification import (
1001
1003
            archive.getComponentsForQueueAdmin(user.person)) or user.in_admin
1002
1004
 
1003
1005
 
1004
 
class EditDistroSeriesDifference(AuthorizationBase):
 
1006
class EditDistroSeriesDifference(DelegatedAuthorization):
1005
1007
    """Anyone with lp.View on the distribution can edit a DSD."""
1006
1008
    permission = 'launchpad.Edit'
1007
1009
    usedfor = IDistroSeriesDifferenceEdit
1008
1010
 
1009
 
    def checkAuthenticated(self, user):
1010
 
        return self.forwardCheckAuthenticated(
1011
 
            user, self.obj.derived_series.distribution, 'launchpad.View')
 
1011
    def __init__(self, obj):
 
1012
        super(EditDistroSeriesDifference, self).__init__(
 
1013
            obj, obj.derived_series.distribution, 'launchpad.View')
 
1014
 
 
1015
    def checkUnauthenticated(self):
 
1016
        return False
1012
1017
 
1013
1018
 
1014
1019
class SeriesDrivers(AuthorizationBase):
1924
1929
                self.forwardCheckAuthenticated(user, self.obj.distribution))
1925
1930
 
1926
1931
 
1927
 
class AdminDistributionSourcePackageTranslations(AuthorizationBase):
 
1932
class AdminDistributionSourcePackageTranslations(DelegatedAuthorization):
1928
1933
    """DistributionSourcePackage objects link to a distribution."""
1929
1934
    permission = 'launchpad.TranslationsAdmin'
1930
1935
    usedfor = IDistributionSourcePackage
1931
1936
 
1932
 
    def checkAuthenticated(self, user):
1933
 
        """Distribution admins are admins for source packages as well."""
1934
 
        return self.forwardCheckAuthenticated(user, self.obj.distribution)
 
1937
    def __init__(self, obj):
 
1938
        super(AdminDistributionSourcePackageTranslations, self).__init__(
 
1939
            obj, obj.distribution)
1935
1940
 
1936
1941
 
1937
1942
class AdminProductSeriesTranslations(AuthorizationBase):
1977
1982
            self.branches))
1978
1983
 
1979
1984
 
1980
 
class PreviewDiffView(AuthorizationBase):
 
1985
class PreviewDiffView(DelegatedAuthorization):
1981
1986
    permission = 'launchpad.View'
1982
1987
    usedfor = IPreviewDiff
1983
1988
 
1984
 
    @property
1985
 
    def bmp_view(self):
1986
 
        return BranchMergeProposalView(self.obj.branch_merge_proposal)
1987
 
 
1988
 
    def checkAuthenticated(self, user):
1989
 
        """Is the user able to view the preview diff?
1990
 
 
1991
 
        The user can see a preview diff if they can see the merge proposal.
1992
 
        """
1993
 
        return self.bmp_view.checkAuthenticated(user)
1994
 
 
1995
 
    def checkUnauthenticated(self):
1996
 
        """Is anyone able to view the branch merge proposal?
1997
 
 
1998
 
        The user can see a preview diff if they can see the merge proposal.
1999
 
        """
2000
 
        return self.bmp_view.checkUnauthenticated()
2001
 
 
2002
 
 
2003
 
class CodeReviewVoteReferenceEdit(AuthorizationBase):
 
1989
    def __init__(self, obj):
 
1990
        super(PreviewDiffView, self).__init__(obj, obj.branch_merge_proposal)
 
1991
 
 
1992
 
 
1993
class CodeReviewVoteReferenceEdit(DelegatedAuthorization):
2004
1994
    permission = 'launchpad.Edit'
2005
1995
    usedfor = ICodeReviewVoteReference
2006
1996
 
 
1997
    def __init__(self, obj):
 
1998
        super(CodeReviewVoteReferenceEdit, self).__init__(
 
1999
            obj, obj.branch_merge_proposal.target_branch)
 
2000
 
2007
2001
    def checkAuthenticated(self, user):
2008
2002
        """Only the affected teams may change the review request.
2009
2003
 
2014
2008
        Anyone with edit permissions on the target branch of the merge
2015
2009
        proposal can also edit the reviews.
2016
2010
        """
2017
 
        if user.inTeam(self.obj.reviewer) or user.inTeam(self.obj.registrant):
2018
 
            return True
2019
 
        target_access = EditBranch(
2020
 
            self.obj.branch_merge_proposal.target_branch)
2021
 
        return target_access.checkAuthenticated(user)
2022
 
 
2023
 
 
2024
 
class CodeReviewCommentView(AuthorizationBase):
 
2011
        return (user.inTeam(self.obj.reviewer) or
 
2012
                user.inTeam(self.obj.registrant) or
 
2013
                super(CodeReviewVoteReferenceEdit, self).checkAuthenticated(
 
2014
                    user))
 
2015
 
 
2016
 
 
2017
class CodeReviewCommentView(DelegatedAuthorization):
2025
2018
    permission = 'launchpad.View'
2026
2019
    usedfor = ICodeReviewComment
2027
2020
 
2028
 
    def checkAuthenticated(self, user):
2029
 
        """Is the user able to view the code review comment?
2030
 
 
2031
 
        The user can see a code review comment if they can see the branch
2032
 
        merge proposal.
2033
 
        """
2034
 
        bmp_checker = BranchMergeProposalView(self.obj.branch_merge_proposal)
2035
 
        return bmp_checker.checkAuthenticated(user)
2036
 
 
2037
 
    def checkUnauthenticated(self):
2038
 
        """Are not-logged-in people able to view the code review comment?
2039
 
 
2040
 
        They can see a code review comment if they can see the branch merge
2041
 
        proposal.
2042
 
        """
2043
 
        bmp_checker = BranchMergeProposalView(self.obj.branch_merge_proposal)
2044
 
        return bmp_checker.checkUnauthenticated()
2045
 
 
2046
 
 
2047
 
class CodeReviewCommentDelete(AuthorizationBase):
 
2021
    def __init__(self, obj):
 
2022
        super(CodeReviewCommentView, self).__init__(
 
2023
            obj, obj.branch_merge_proposal)
 
2024
 
 
2025
 
 
2026
class CodeReviewCommentDelete(DelegatedAuthorization):
2048
2027
    permission = 'launchpad.Edit'
2049
2028
    usedfor = ICodeReviewCommentDeletion
2050
2029
 
2051
 
    def checkAuthenticated(self, user):
2052
 
        """Is the user able to view the code review message?
2053
 
 
2054
 
        The user can see a code review message if they can see the branch
2055
 
        merge proposal.
2056
 
        """
2057
 
        bmp_checker = BranchMergeProposalEdit(self.obj.branch_merge_proposal)
2058
 
        return bmp_checker.checkAuthenticated(user)
2059
 
 
2060
 
    def checkUnauthenticated(self):
2061
 
        """Are not-logged-in people able to view the code review message?
2062
 
 
2063
 
        They can see a code review message if they can see the branch merge
2064
 
        proposal.
2065
 
        """
2066
 
        bmp_checker = BranchMergeProposalEdit(self.obj.branch_merge_proposal)
2067
 
        return bmp_checker.checkUnauthenticated()
 
2030
    def __init__(self, obj):
 
2031
        super(CodeReviewCommentDelete, self).__init__(
 
2032
            obj, obj.branch_merge_proposal)
2068
2033
 
2069
2034
 
2070
2035
class BranchMergeProposalEdit(AuthorizationBase):
2325
2290
        return auth_edit.checkAuthenticated(user)
2326
2291
 
2327
2292
 
2328
 
class EditArchiveAuthToken(AuthorizationBase):
 
2293
class EditArchiveAuthToken(DelegatedAuthorization):
2329
2294
    """Restrict editing of archive tokens.
2330
2295
 
2331
2296
    The user should have append privileges to the context archive, or be an
2334
2299
    permission = "launchpad.Edit"
2335
2300
    usedfor = IArchiveAuthToken
2336
2301
 
 
2302
    def __init__(self, obj):
 
2303
        super(EditArchiveAuthToken, self).__init__(
 
2304
            obj, obj.archive, 'launchpad.Append')
 
2305
 
2337
2306
    def checkAuthenticated(self, user):
2338
 
        auth_append = AppendArchive(self.obj.archive)
2339
 
        if auth_append.checkAuthenticated(user):
2340
 
            return True
2341
 
        return user.in_admin
2342
 
 
2343
 
 
2344
 
class ViewPersonalArchiveSubscription(AuthorizationBase):
 
2307
        return (user.in_admin or
 
2308
                super(EditArchiveAuthToken, self).checkAuthenticated(user))
 
2309
 
 
2310
 
 
2311
class ViewPersonalArchiveSubscription(DelegatedAuthorization):
2345
2312
    """Restrict viewing of personal archive subscriptions (non-db class).
2346
2313
 
2347
2314
    The user should be the subscriber, have append privilege to the archive
2350
2317
    permission = "launchpad.View"
2351
2318
    usedfor = IPersonalArchiveSubscription
2352
2319
 
 
2320
    def __init__(self, obj):
 
2321
        super(ViewPersonalArchiveSubscription, self).__init__(
 
2322
            obj, obj.archive, 'launchpad.Append')
 
2323
 
2353
2324
    def checkAuthenticated(self, user):
2354
 
        if user.person == self.obj.subscriber:
2355
 
            return True
2356
 
        append_archive = AppendArchive(self.obj.archive)
2357
 
 
2358
 
        if append_archive.checkAuthenticated(user):
2359
 
            return True
2360
 
 
2361
 
        return user.in_admin
2362
 
 
2363
 
 
2364
 
class ViewArchiveSubscriber(AuthorizationBase):
 
2325
        if user.person == self.obj.subscriber or user.in_admin:
 
2326
            return True
 
2327
        return super(
 
2328
            ViewPersonalArchiveSubscription, self).checkAuthenticated(user)
 
2329
 
 
2330
 
 
2331
class ViewArchiveSubscriber(DelegatedAuthorization):
2365
2332
    """Restrict viewing of archive subscribers.
2366
2333
 
2367
 
    The user should be the subscriber, have append privilege to the
 
2334
    The user should be the subscriber, have edit privilege to the
2368
2335
    archive or be an admin.
2369
2336
    """
2370
2337
    permission = "launchpad.View"
2371
2338
    usedfor = IArchiveSubscriber
2372
2339
 
 
2340
    def __init__(self, obj):
 
2341
        super(ViewArchiveSubscriber, self).__init__(
 
2342
            obj, obj, 'launchpad.Edit')
 
2343
 
2373
2344
    def checkAuthenticated(self, user):
2374
 
        auth_edit = EditArchiveSubscriber(self.obj)
2375
 
        result = auth_edit.checkAuthenticated(user)
2376
 
        if not result:
2377
 
            result = user.inTeam(self.obj.subscriber)
2378
 
        return result
2379
 
 
2380
 
 
2381
 
class EditArchiveSubscriber(AuthorizationBase):
 
2345
        return (user.inTeam(self.obj.subscriber) or
 
2346
                super(ViewArchiveSubscriber, self).checkAuthenticated(user))
 
2347
 
 
2348
 
 
2349
class EditArchiveSubscriber(DelegatedAuthorization):
2382
2350
    """Restrict editing of archive subscribers.
2383
2351
 
2384
2352
    The user should have append privilege to the archive or be an admin.
2386
2354
    permission = "launchpad.Edit"
2387
2355
    usedfor = IArchiveSubscriber
2388
2356
 
2389
 
    def checkAuthenticated(self, user):
2390
 
        auth_append = AppendArchive(self.obj.archive)
2391
 
        if auth_append.checkAuthenticated(user):
2392
 
            return True
2393
 
        return user.in_admin
2394
 
 
2395
 
 
2396
 
class DerivedAuthorization(AuthorizationBase):
2397
 
    """An Authorization that is based on permissions for other objects.
2398
 
 
2399
 
    Implementations must define permission, usedfor and iter_objects.
2400
 
    iter_objects should iterate through the objects to check permission on.
2401
 
 
2402
 
    Failure on the permission check for any object causes an overall failure.
2403
 
    """
2404
 
 
2405
 
    def iter_adapters(self):
2406
 
        return (
2407
 
            getAdapter(obj, IAuthorization, self.permission)
2408
 
            for obj in self.iter_objects())
2409
 
 
2410
 
    def checkAuthenticated(self, user):
2411
 
        for adapter in self.iter_adapters():
2412
 
            if not adapter.checkAuthenticated(user):
2413
 
                return False
2414
 
        return True
2415
 
 
2416
 
    def checkUnauthenticated(self):
2417
 
        for adapter in self.iter_adapters():
2418
 
            if not adapter.checkUnauthenticated():
2419
 
                return False
2420
 
        return True
2421
 
 
2422
 
 
2423
 
class ViewSourcePackageRecipe(DerivedAuthorization):
 
2357
    def __init__(self, obj):
 
2358
        super(EditArchiveSubscriber, self).__init__(
 
2359
            obj, obj.archive, 'launchpad.Append')
 
2360
 
 
2361
    def checkAuthenticated(self, user):
 
2362
        return (user.in_admin or
 
2363
                super(EditArchiveSubscriber, self).checkAuthenticated(user))
 
2364
 
 
2365
 
 
2366
class ViewSourcePackageRecipe(DelegatedAuthorization):
2424
2367
 
2425
2368
    permission = "launchpad.View"
2426
2369
    usedfor = ISourcePackageRecipe
2429
2372
        return self.obj.getReferencedBranches()
2430
2373
 
2431
2374
 
2432
 
class ViewSourcePackageRecipeBuild(DerivedAuthorization):
 
2375
class ViewSourcePackageRecipeBuild(DelegatedAuthorization):
2433
2376
 
2434
2377
    permission = "launchpad.View"
2435
2378
    usedfor = ISourcePackageRecipeBuild
2449
2392
        super(ViewSourcePackagePublishingHistory, self).__init__(obj.archive)
2450
2393
 
2451
2394
 
2452
 
class EditPublishing(AuthorizationBase):
 
2395
class EditPublishing(DelegatedAuthorization):
2453
2396
    """Restrict editing of source and binary packages.."""
2454
2397
    permission = "launchpad.Edit"
2455
2398
    usedfor = IPublishingEdit
2456
2399
 
2457
 
    def checkAuthenticated(self, user):
2458
 
        return AppendArchive(self.obj.archive).checkAuthenticated(user)
 
2400
    def __init__(self, obj):
 
2401
        super(EditPublishing, self).__init__(
 
2402
            obj, obj.archive, 'launchpad.Append')
2459
2403
 
2460
2404
 
2461
2405
class ViewBinaryPackagePublishingHistory(ViewSourcePackagePublishingHistory):
2485
2429
    def checkAuthenticated(self, user):
2486
2430
        """Verify that the user can view the sourcepackagerelease."""
2487
2431
        for archive in self.obj.published_archives:
2488
 
            auth_archive = ViewArchive(archive)
2489
 
            if auth_archive.checkAuthenticated(user):
 
2432
            adapter = queryAdapter(archive, IAuthorization, self.permission)
 
2433
            if adapter is not None and adapter.checkAuthenticated(user):
2490
2434
                return True
2491
2435
        return False
2492
2436