mirror of
https://github.com/pypiserver/pypiserver
synced 2024-11-09 16:45:51 +01:00
Added rudimentary support for uploads
This commit is contained in:
parent
1340b90ac9
commit
4ceb82458c
@ -4,7 +4,8 @@ version = __version__ = "0.5.2"
|
||||
|
||||
def app(root=None,
|
||||
redirect_to_fallback=True,
|
||||
fallback_url=None):
|
||||
fallback_url=None,
|
||||
password_file=None):
|
||||
import sys, os
|
||||
from pypiserver import core
|
||||
sys.modules.pop("pypiserver._app", None)
|
||||
@ -20,7 +21,8 @@ def app(root=None,
|
||||
fallback_url="http://pypi.python.org/simple"
|
||||
|
||||
os.listdir(root)
|
||||
_app.configure(root=root, redirect_to_fallback=redirect_to_fallback, fallback_url=fallback_url)
|
||||
_app.configure(root=root, redirect_to_fallback=redirect_to_fallback, fallback_url=fallback_url,
|
||||
password_file=password_file)
|
||||
_app.app.module = _app
|
||||
|
||||
bottle.debug(True)
|
||||
|
@ -8,6 +8,7 @@ else:
|
||||
from bottle import static_file, redirect, request, HTTPError, Bottle
|
||||
from pypiserver import __version__
|
||||
from pypiserver.core import is_allowed_path
|
||||
import md5
|
||||
|
||||
packages = None
|
||||
|
||||
@ -18,9 +19,27 @@ class configuration(object):
|
||||
|
||||
config = configuration()
|
||||
|
||||
|
||||
def read_passwd_file(passwd_file):
|
||||
users = {}
|
||||
for line in open(passwd_file):
|
||||
user, md5_hash = line.strip().split(":")
|
||||
users[user] = md5_hash
|
||||
return users
|
||||
|
||||
|
||||
def validate_user(username, password):
|
||||
if username in config.users:
|
||||
md5_hash = md5.new(password).hexdigest()
|
||||
return config.users[username] == md5_hash
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def configure(root=None,
|
||||
redirect_to_fallback=True,
|
||||
fallback_url=None):
|
||||
fallback_url=None,
|
||||
password_file=None):
|
||||
from pypiserver.core import pkgset
|
||||
global packages
|
||||
|
||||
@ -33,7 +52,12 @@ def configure(root=None,
|
||||
packages = pkgset(root)
|
||||
config.redirect_to_fallback = redirect_to_fallback
|
||||
config.fallback_url = fallback_url
|
||||
|
||||
if password_file:
|
||||
config.users = read_passwd_file(password_file)
|
||||
else:
|
||||
# PyPi server is read only without users
|
||||
config.users = {}
|
||||
|
||||
app = Bottle()
|
||||
|
||||
|
||||
@ -69,6 +93,30 @@ easy_install -i %(URL)ssimple/ PACKAGE
|
||||
</body></html>
|
||||
""" % dict(URL=request.url, VERSION=__version__, NUMPKGS=numpkgs)
|
||||
|
||||
@app.post('/')
|
||||
def update():
|
||||
if request.auth and validate_user(*request.auth):
|
||||
try:
|
||||
content = request.files['content']
|
||||
except KeyError:
|
||||
raise HTTPError(400, output="content file field not found")
|
||||
|
||||
try:
|
||||
action = request.forms[':action']
|
||||
except KeyError:
|
||||
raise HTTPError(400, output=":action field not found")
|
||||
|
||||
if action != "file_upload":
|
||||
raise HTTPError(400, output="actions other than file_upload, not supported")
|
||||
|
||||
if "/" in content.filename:
|
||||
raise HTTPError(400, output="bad filename")
|
||||
|
||||
packages.store(content.filename, content.value)
|
||||
|
||||
return ""
|
||||
else:
|
||||
raise HTTPError(401)
|
||||
|
||||
@app.route("/simple")
|
||||
def simpleindex_redirect():
|
||||
|
@ -65,7 +65,13 @@ class pkgset(object):
|
||||
prefixes.add(pkgname)
|
||||
return prefixes
|
||||
|
||||
|
||||
def store(self, filename, data):
|
||||
assert "/" not in filename
|
||||
dest_fn = os.path.join(self.root, filename)
|
||||
dest_fh = open(dest_fn, "wb")
|
||||
|
||||
dest_fh.write(data)
|
||||
dest_fh.close()
|
||||
|
||||
|
||||
def usage():
|
||||
@ -84,6 +90,9 @@ pypi-server understands the following options:
|
||||
-i INTERFACE, --interface INTERFACE
|
||||
listen on interface INTERFACE (default: 0.0.0.0, any interface)
|
||||
|
||||
-P PASSWORD_FILE --passwords PASSWORD_FILE
|
||||
A file of username:md5(password) lines
|
||||
|
||||
--disable-fallback
|
||||
disable redirect to real PyPI index for packages not found in the
|
||||
local index
|
||||
@ -137,13 +146,14 @@ def main(argv=None):
|
||||
port = 8080
|
||||
server = None
|
||||
redirect_to_fallback = True
|
||||
password_file = None
|
||||
|
||||
update_dry_run = True
|
||||
update_directory = None
|
||||
update_stable_only = True
|
||||
|
||||
try:
|
||||
opts, roots = getopt.getopt(argv[1:], "i:p:r:d:Uuxh", ["interface=", "port=", "root=", "server=", "disable-fallback", "version", "help"])
|
||||
opts, roots = getopt.getopt(argv[1:], "i:p:r:d:P:Uuxh", ["interface=", "passwords=", "port=", "root=", "server=", "disable-fallback", "version", "help"])
|
||||
except getopt.GetoptError:
|
||||
err = sys.exc_info()[1]
|
||||
sys.exit("usage error: %s" % (err,))
|
||||
@ -172,10 +182,13 @@ def main(argv=None):
|
||||
update_stable_only = False
|
||||
elif k == "-d":
|
||||
update_directory = v
|
||||
elif k in ("-P", "--passwords"):
|
||||
password_file = v
|
||||
elif k in ("-h", "--help"):
|
||||
usage()
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if len(roots) == 0:
|
||||
roots.append(os.path.expanduser("~/packages"))
|
||||
elif len(roots) > 1:
|
||||
@ -196,7 +209,7 @@ def main(argv=None):
|
||||
manage.update(packages, update_directory, update_dry_run, stable_only=update_stable_only)
|
||||
return
|
||||
|
||||
a = app(root=root, redirect_to_fallback=redirect_to_fallback)
|
||||
a = app(root=root, redirect_to_fallback=redirect_to_fallback, password_file=password_file)
|
||||
server = server or "auto"
|
||||
sys.stdout.write("This is pypiserver %s serving %r on %s:%s\n\n" % (__version__, root, host, port))
|
||||
run(app=a, host=host, port=port, server=server)
|
||||
|
Loading…
Reference in New Issue
Block a user