add support for installation of single file plugins
This commit is contained in:
Родитель
f0eb148924
Коммит
29fc14a8ac
|
@ -452,11 +452,12 @@ def validate_url(url):
|
|||
raise BadRequest("Invalid url: " + url)
|
||||
return url
|
||||
|
||||
@expose(r'^/project/fromurl/(?P<project_name>[^/]+)', "POST")
|
||||
def import_from_url(request, response):
|
||||
project_name = request.kwargs['project_name']
|
||||
|
||||
url = validate_url(request.body)
|
||||
def _download_data(url, request):
|
||||
"""downloads the data to a temporary file, raising BadRequest
|
||||
if there are issues, doing a HEAD request first to ensure that
|
||||
the URL is good and also ensuring that the user has enough
|
||||
space available."""
|
||||
url = validate_url(url)
|
||||
try:
|
||||
resp = httplib2.Http().request(url, method="HEAD")
|
||||
except httplib2.HttpLib2Error, e:
|
||||
|
@ -478,6 +479,14 @@ def import_from_url(request, response):
|
|||
tempdatafile.write(datafile.read())
|
||||
datafile.close()
|
||||
tempdatafile.seek(0)
|
||||
return tempdatafile
|
||||
|
||||
|
||||
@expose(r'^/project/fromurl/(?P<project_name>[^/]+)', "POST")
|
||||
def import_from_url(request, response):
|
||||
project_name = request.kwargs['project_name']
|
||||
|
||||
tempdatafile = _download_data(request.body, request)
|
||||
url_parts = urlparse(url)
|
||||
filename = os.path.basename(url_parts[2])
|
||||
_perform_import(request.user, project_name, filename, tempdatafile)
|
||||
|
@ -1164,6 +1173,35 @@ def _wrap_script(plugin_name, script_path, script_text):
|
|||
;}); tiki.script('%s:%s');""" % (plugin_name, module_name,
|
||||
script_text, plugin_name, script_path)
|
||||
|
||||
urlmatch = re.compile(r'^(http|https)://')
|
||||
|
||||
@expose(r'^/plugin/install/', 'POST')
|
||||
def install_plugin(request, response):
|
||||
"""Installs a plugin into the user's BespinSettings/plugins directory."""
|
||||
user = request.user
|
||||
url = request.POST.get('url')
|
||||
plugin_name = request.POST.get('pluginName')
|
||||
|
||||
if not url or not urlmatch.search(url):
|
||||
raise BadRequest("URL not provided")
|
||||
|
||||
if not plugin_name or "/" in plugin_name or ".." in plugin_name:
|
||||
raise BadRequest("Invalid plugin name. / and .. are not permitted")
|
||||
|
||||
tempdatafile = _download_data(url, request)
|
||||
settings_project = get_project(user, user, "BespinSettings")
|
||||
destination = settings_project.location / "plugins"
|
||||
path_entry = dict(name="user", chop=len(user.get_location()))
|
||||
plugin = plugins.install_plugin(tempdatafile, url, destination,
|
||||
path_entry, plugin_name)
|
||||
tempdatafile.close()
|
||||
|
||||
plugin_collection = dict()
|
||||
plugin_collection[plugin.name] = plugin.metadata
|
||||
response.body = simplejson.dumps(plugin_collection)
|
||||
response.content_type = "application/json"
|
||||
return response()
|
||||
|
||||
|
||||
def db_middleware(app):
|
||||
def wrapped(environ, start_response):
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
#
|
||||
import os
|
||||
from urlparse import urlparse
|
||||
|
||||
from dryice.plugins import (Plugin as BasePlugin,
|
||||
find_plugins as base_find_plugins,
|
||||
|
@ -105,3 +107,22 @@ def lookup_plugin(name, search_path=None):
|
|||
search_path = config.c.plugin_path
|
||||
|
||||
return base_lookup_plugin(name, search_path, cls=Plugin)
|
||||
|
||||
def install_plugin(f, url, destination, path_entry, plugin_name=None):
|
||||
if not destination.exists():
|
||||
destination.mkdir()
|
||||
|
||||
if plugin_name is None:
|
||||
url_parts = urlparse(url)
|
||||
filename = os.path.basename(url_parts[2])
|
||||
plugin_name = os.path.splitext(filename)[0]
|
||||
|
||||
|
||||
# check for single file plugin
|
||||
if url.endswith(".js"):
|
||||
destination = destination / (plugin_name + ".js")
|
||||
destination.write_bytes(f.read())
|
||||
plugin = Plugin(plugin_name, destination, path_entry)
|
||||
return plugin
|
||||
|
||||
|
|
@ -41,6 +41,7 @@ from simplejson import loads
|
|||
|
||||
from bespin import config, plugins, controllers
|
||||
from bespin.database import User, Base
|
||||
from bespin.filesystem import get_project
|
||||
|
||||
from __init__ import BespinTestApp
|
||||
|
||||
|
@ -77,6 +78,32 @@ def _init_data():
|
|||
|
||||
macgyver = User.find_user("MacGyver")
|
||||
|
||||
|
||||
def test_install_single_file_plugin():
|
||||
_init_data()
|
||||
settings_project = get_project(macgyver, macgyver, "BespinSettings")
|
||||
destination = settings_project.location / "plugins"
|
||||
path_entry = dict(chop=len(macgyver.get_location()), name="user")
|
||||
sfp = plugindir / "SingleFilePlugin1.js"
|
||||
plugin = plugins.install_plugin(open(sfp), "http://somewhere/file.js",
|
||||
destination, path_entry, "APlugin")
|
||||
destfile = destination / "APlugin.js"
|
||||
assert destfile.exists()
|
||||
desttext = destfile.text()
|
||||
assert "someFunction" in desttext
|
||||
assert plugin.name == "APlugin"
|
||||
assert plugin.location == destfile
|
||||
assert plugin.relative_location == "BespinSettings/plugins/APlugin.js"
|
||||
metadata = plugin.metadata
|
||||
type = metadata['type']
|
||||
assert type == "user"
|
||||
|
||||
plugin = plugins.install_plugin(open(sfp), "http://somewhere/Flibber.js",
|
||||
destination, path_entry)
|
||||
destfile = destination / "Flibber.js"
|
||||
assert destfile.exists()
|
||||
assert plugin.name == "Flibber"
|
||||
|
||||
# Web tests
|
||||
|
||||
def test_default_plugin_registration():
|
||||
|
@ -171,4 +198,3 @@ def test_plugin_reload():
|
|||
assert '"plugin2": {' in response.body
|
||||
# just need the plugin, not its dependents
|
||||
assert '"depends": ["plugin2"]' not in response.body
|
||||
|
Загрузка…
Ссылка в новой задаче