diff --git a/src/ep.json b/src/ep.json
index 59cbf3aa4..a4242890b 100644
--- a/src/ep.json
+++ b/src/ep.json
@@ -8,7 +8,7 @@
{ "name": "apicalls", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/apicalls:expressCreateServer" } },
{ "name": "importexport", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/importexport:expressCreateServer" } },
{ "name": "errorhandling", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/errorhandling:expressCreateServer" } },
- { "name": "socketio", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/socketio:expressCreateServer" } }
-
+ { "name": "socketio", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/socketio:expressCreateServer" } },
+ { "name": "adminplugins", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/adminplugins:expressCreateServer" } }
]
}
diff --git a/src/node/hooks/express/adminplugins.js b/src/node/hooks/express/adminplugins.js
new file mode 100644
index 000000000..a3fbc2af3
--- /dev/null
+++ b/src/node/hooks/express/adminplugins.js
@@ -0,0 +1,34 @@
+var path = require('path');
+var eejs = require('ep_etherpad-lite/node/eejs');
+var installer = require('ep_etherpad-lite/static/js/pluginfw/installer');
+
+exports.expressCreateServer = function (hook_name, args, cb) {
+ args.app.get('/admin/plugins', function(req, res) {
+ var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins");
+ var render_args = {
+ plugins: plugins.plugins,
+ query: req.query,
+ search_results: {},
+ errors: [],
+ };
+
+ var render = function () {
+ res.send(eejs.require(
+ "ep_etherpad-lite/templates/admin/plugins.html",
+ render_args), {});
+ };
+
+ if (req.query.search && req.query.search != "") {
+ installer.search(req.query.search, function (er, data) {
+ if (er) {
+ render_args.errors.push(er);
+ return render();
+ }
+ render_args.search_results = data;
+ render();
+ });
+ } else {
+ render();
+ }
+ });
+}
\ No newline at end of file
diff --git a/src/static/js/pluginfw/installer.js b/src/static/js/pluginfw/installer.js
new file mode 100644
index 000000000..3ba7f4589
--- /dev/null
+++ b/src/static/js/pluginfw/installer.js
@@ -0,0 +1,45 @@
+var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins");
+var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks");
+var npm = require("npm");
+var registry = require("npm/lib/utils/npm-registry-client/index.js");
+
+exports.uninstall = function(plugin_name, cb) {
+ npm.load({}, function (er) {
+ if (er) return cb(er)
+ npm.commands.uninstall([plugin_name], function (er) {
+ if (er) return cb(er);
+ hooks.aCallAll("pluginUninstall", {plugin_name: plugin_name}, function (er) {
+ cb(er);
+ });
+ })
+ })
+}
+
+exports.install = function(plugin_name, cb) {
+ npm.load({}, function (er) {
+ if (er) return cb(er)
+ npm.commands.install([plugin_name], function (er) {
+ if (er) return cb(er);
+ hooks.aCallAll("pluginInstall", {plugin_name: plugin_name}, function (er) {
+ cb(er);
+ });
+ });
+ })
+}
+
+exports.search = function(pattern, cb) {
+ npm.load({}, function (er) {
+ registry.get(
+ "/-/all", null, 600, false, true,
+ function (er, data) {
+ if (er) return cb(er);
+ var res = {};
+ for (key in data) {
+ if (/*key.indexOf(plugins.prefix) == 0 &&*/ key.indexOf(pattern) != -1)
+ res[key] = data[key];
+ }
+ cb(null, res);
+ }
+ );
+ });
+}
diff --git a/src/templates/admin/plugins.html b/src/templates/admin/plugins.html
new file mode 100644
index 000000000..2b40d33c0
--- /dev/null
+++ b/src/templates/admin/plugins.html
@@ -0,0 +1,86 @@
+
+
+ Plugin manager
+
+
+
+ <% if (errors.length) { %>
+
+ <% errors.forEach(function (item) { %>
+
<%= item.toString() %>
+ <% }) %>
+
+ <% } %>
+
+
+ Installed plugins
+
+
+
+ | Name |
+ Description |
+ |
+
+
+
+ <% for (var plugin_name in plugins) { %>
+ <% var plugin = plugins[plugin_name]; %>
+
+ | <%= plugin.package.name %> |
+ <%= plugin.package.description %> |
+
+
+ |
+
+ <% } %>
+
+
+
+
+
+ Search for plugins to install
+
+
+
+
+ | Name |
+ Description |
+ |
+
+
+
+ <% for (var plugin_name in search_results) { %>
+ <% var plugin = search_results[plugin_name]; %>
+
+ | <%= plugin.name %> |
+ <%= plugin.description %> |
+
+
+ |
+
+ <% } %>
+
+
+
+
+
+