changeset 35846:742ce6fbc109 stable

wireproto: move command permissions dict out of hgweb_mod The operation type associated with wire protocol commands is supposed to be defined in a dictionary so it can be used for permissions checking. Since this metadata is closely associated with wire protocol commands themselves, it makes sense to define it in the same module where wire protocol commands are defined. This commit moves hgweb_mod.perms to wireproto.PERMISSIONS and updates most references in the code to use the new home. The old symbol remains an alias for the new symbol. Tests pass with the code pointing at the old symbol. So this should be API compatible for extensions. As part of the code move, we split up the assignment to the dict so it is next to the @wireprotocommand. This reinforces that a @wireprotocommand should have an entry in this dict. In the future, we'll want to declare permissions as part of the @wireprotocommand decorator. But this isn't appropriate for the stable branch.
author Gregory Szorc <gregory.szorc@gmail.com>
date Tue, 20 Feb 2018 18:53:39 -0800
parents bbd4027b019b
children e3c228b4510d
files hgext/largefiles/uisetup.py mercurial/hgweb/hgweb_mod.py mercurial/wireproto.py tests/test-http-permissions.t
diffstat 4 files changed, 20 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/largefiles/uisetup.py	Tue Feb 20 19:09:01 2018 -0800
+++ b/hgext/largefiles/uisetup.py	Tue Feb 20 18:53:39 2018 -0800
@@ -12,7 +12,6 @@
 from mercurial.i18n import _
 
 from mercurial.hgweb import (
-    hgweb_mod,
     webcommands,
 )
 
@@ -175,9 +174,9 @@
 
     # make putlfile behave the same as push and {get,stat}lfile behave
     # the same as pull w.r.t. permissions checks
-    hgweb_mod.perms['putlfile'] = 'push'
-    hgweb_mod.perms['getlfile'] = 'pull'
-    hgweb_mod.perms['statlfile'] = 'pull'
+    wireproto.permissions['putlfile'] = 'push'
+    wireproto.permissions['getlfile'] = 'pull'
+    wireproto.permissions['statlfile'] = 'pull'
 
     extensions.wrapfunction(webcommands, 'decodepath', overrides.decodepath)
 
--- a/mercurial/hgweb/hgweb_mod.py	Tue Feb 20 19:09:01 2018 -0800
+++ b/mercurial/hgweb/hgweb_mod.py	Tue Feb 20 18:53:39 2018 -0800
@@ -36,6 +36,7 @@
     templater,
     ui as uimod,
     util,
+    wireproto,
 )
 
 from . import (
@@ -45,15 +46,8 @@
     wsgicgi,
 )
 
-perms = {
-    'changegroup': 'pull',
-    'changegroupsubset': 'pull',
-    'getbundle': 'pull',
-    'stream_out': 'pull',
-    'listkeys': 'pull',
-    'unbundle': 'push',
-    'pushkey': 'push',
-}
+# Aliased for API compatibility.
+perms = wireproto.permissions
 
 archivespecs = util.sortdict((
     ('zip', ('application/zip', 'zip', '.zip', None)),
--- a/mercurial/wireproto.py	Tue Feb 20 19:09:01 2018 -0800
+++ b/mercurial/wireproto.py	Tue Feb 20 18:53:39 2018 -0800
@@ -677,6 +677,11 @@
 # list of commands
 commands = {}
 
+# Maps wire protocol name to operation type. This is used for permissions
+# checking. All defined @wireiprotocommand should have an entry in this
+# dict.
+permissions = {}
+
 def wireprotocommand(name, args=''):
     """decorator for wire protocol command"""
     def register(func):
@@ -808,6 +813,7 @@
 def capabilities(repo, proto):
     return ' '.join(_capabilities(repo, proto))
 
+permissions['changegroup'] = 'pull'
 @wireprotocommand('changegroup', 'roots')
 def changegroup(repo, proto, roots):
     nodes = decodelist(roots)
@@ -817,6 +823,7 @@
     gen = iter(lambda: cg.read(32768), '')
     return streamres(gen=gen)
 
+permissions['changegroupsubset'] = 'pull'
 @wireprotocommand('changegroupsubset', 'bases heads')
 def changegroupsubset(repo, proto, bases, heads):
     bases = decodelist(bases)
@@ -833,6 +840,7 @@
     opts = options('debugwireargs', ['three', 'four'], others)
     return repo.debugwireargs(one, two, **pycompat.strkwargs(opts))
 
+permissions['getbundle'] = 'pull'
 @wireprotocommand('getbundle', '*')
 def getbundle(repo, proto, others):
     opts = options('getbundle', gboptsmap.keys(), others)
@@ -915,6 +923,7 @@
     '''
     return "capabilities: %s\n" % (capabilities(repo, proto))
 
+permissions['listkeys'] = 'pull'
 @wireprotocommand('listkeys', 'namespace')
 def listkeys(repo, proto, namespace):
     d = repo.listkeys(encoding.tolocal(namespace)).items()
@@ -936,6 +945,7 @@
 def known(repo, proto, nodes, others):
     return ''.join(b and "1" or "0" for b in repo.known(decodelist(nodes)))
 
+permissions['pushkey'] = 'push'
 @wireprotocommand('pushkey', 'namespace key old new')
 def pushkey(repo, proto, namespace, key, old, new):
     # compatibility with pre-1.8 clients which were accidentally
@@ -968,6 +978,7 @@
                      encoding.tolocal(old), new)
     return '%s\n' % int(r)
 
+permissions['stream_out'] = 'pull'
 @wireprotocommand('stream_out')
 def stream(repo, proto):
     '''If the server supports streaming clone, it advertises the "stream"
@@ -976,6 +987,7 @@
     '''
     return streamres_legacy(streamclone.generatev1wireproto(repo))
 
+permissions['unbundle'] = 'push'
 @wireprotocommand('unbundle', 'heads')
 def unbundle(repo, proto, heads):
     their_heads = decodelist(heads)
--- a/tests/test-http-permissions.t	Tue Feb 20 19:09:01 2018 -0800
+++ b/tests/test-http-permissions.t	Tue Feb 20 18:53:39 2018 -0800
@@ -21,11 +21,11 @@
   > @wireproto.wireprotocommand('customwritenoperm')
   > def customwritenoperm(repo, proto):
   >     return b'write command no defined permissions\n'
-  > hgweb_mod.perms['customreadwithperm'] = 'pull'
+  > wireproto.permissions['customreadwithperm'] = 'pull'
   > @wireproto.wireprotocommand('customreadwithperm')
   > def customreadwithperm(repo, proto):
   >     return b'read-only command w/ defined permissions\n'
-  > hgweb_mod.perms['customwritewithperm'] = 'push'
+  > wireproto.permissions['customwritewithperm'] = 'push'
   > @wireproto.wireprotocommand('customwritewithperm')
   > def customwritewithperm(repo, proto):
   >     return b'write command w/ defined permissions\n'