From 40e0a9672b20da4b9c0c9d65ed62c20fb686ac26 Mon Sep 17 00:00:00 2001 From: SychO9 Date: Wed, 22 Sep 2021 22:08:51 +0100 Subject: [PATCH] File permissions alert and clear command failure message. --- extensions/package-manager/extend.php | 17 ++- extensions/package-manager/js/dist/admin.js | 133 ++++++++++++++++-- .../package-manager/js/dist/admin.js.map | 2 +- .../admin/components/ComposerFailureModal.tsx | 41 ++++++ .../js/src/admin/components/Installer.tsx | 10 ++ .../package-manager/js/src/admin/index.js | 12 ++ extensions/package-manager/less/admin.less | 4 + extensions/package-manager/locale/en.yml | 8 ++ .../Controller/RequireExtensionController.php | 13 +- .../src/Command/RequireExtensionHandler.php | 7 +- .../ComposerCommandFailedExceptionHandler.php | 48 +++++++ .../ComposerRequireFailedException.php | 24 ++++ 12 files changed, 299 insertions(+), 20 deletions(-) create mode 100644 extensions/package-manager/js/src/admin/components/ComposerFailureModal.tsx create mode 100644 extensions/package-manager/src/Exception/ComposerCommandFailedExceptionHandler.php create mode 100644 extensions/package-manager/src/Exception/ComposerRequireFailedException.php diff --git a/extensions/package-manager/extend.php b/extensions/package-manager/extend.php index c4d79bcf4..75a168b86 100644 --- a/extensions/package-manager/extend.php +++ b/extensions/package-manager/extend.php @@ -8,7 +8,9 @@ namespace SychO\PackageManager; use Flarum\Extend; use Flarum\Foundation\Paths; -use Illuminate\Console\Scheduling\Event; +use Flarum\Frontend\Document; +use SychO\PackageManager\Exception\ComposerCommandFailedExceptionHandler; +use SychO\PackageManager\Exception\ComposerRequireFailedException; return [ (new Extend\Routes('api')) @@ -18,10 +20,21 @@ return [ (new Extend\Frontend('admin')) ->css(__DIR__ . '/less/admin.less') - ->js(__DIR__ . '/js/dist/admin.js'), + ->js(__DIR__ . '/js/dist/admin.js') + ->content(function (Document $document) { + $paths = resolve(Paths::class); + + $document->payload['isRequiredDirectoriesWritable'] = is_writable($paths->vendor) + && is_writable($paths->storage.'/.composer') + && is_writable($paths->base.'/composer.json') + && is_writable($paths->base.'/composer.lock'); + }), new Extend\Locales(__DIR__ . '/locale'), (new Extend\ServiceProvider) ->register(PackageManagerServiceProvider::class), + + (new Extend\ErrorHandling) + ->handler(ComposerRequireFailedException::class, ComposerCommandFailedExceptionHandler::class), ]; diff --git a/extensions/package-manager/js/dist/admin.js b/extensions/package-manager/js/dist/admin.js index c6d8e99a8..a6e64a78d 100644 --- a/extensions/package-manager/js/dist/admin.js +++ b/extensions/package-manager/js/dist/admin.js @@ -140,6 +140,68 @@ function _setPrototypeOf(o, p) { return _setPrototypeOf(o, p); } +/***/ }), + +/***/ "./src/admin/components/ComposerFailureModal.tsx": +/*!*******************************************************!*\ + !*** ./src/admin/components/ComposerFailureModal.tsx ***! + \*******************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return ComposerFailureModal; }); +/* harmony import */ var _babel_runtime_helpers_esm_inheritsLoose__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/esm/inheritsLoose */ "./node_modules/@babel/runtime/helpers/esm/inheritsLoose.js"); +/* harmony import */ var flarum_admin_app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! flarum/admin/app */ "flarum/admin/app"); +/* harmony import */ var flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(flarum_admin_app__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var flarum_common_components_Modal__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! flarum/common/components/Modal */ "flarum/common/components/Modal"); +/* harmony import */ var flarum_common_components_Modal__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(flarum_common_components_Modal__WEBPACK_IMPORTED_MODULE_2__); + + + + +var ComposerFailureModal = /*#__PURE__*/function (_Modal) { + Object(_babel_runtime_helpers_esm_inheritsLoose__WEBPACK_IMPORTED_MODULE_0__["default"])(ComposerFailureModal, _Modal); + + function ComposerFailureModal() { + return _Modal.apply(this, arguments) || this; + } + + var _proto = ComposerFailureModal.prototype; + + _proto.oninit = function oninit(vnode) { + _Modal.prototype.oninit.call(this, vnode); + + if (this.attrs.error.guessed_cause) { + this.alertAttrs = { + type: 'error', + content: flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans("sycho-package-manager.admin.failure_modal.guessed_cause." + this.attrs.error.guessed_cause) + }; + } + }; + + _proto.className = function className() { + return 'Modal--large ComposerFailureModal'; + }; + + _proto.title = function title() { + return flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('sycho-package-manager.admin.failure_modal.title'); + }; + + _proto.content = function content() { + return m("div", { + className: "Modal-body" + }, m("details", null, m("summary", null, flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('sycho-package-manager.admin.failure_modal.show_composer_output')), m("pre", { + className: "ComposerFailureModal-output" + }, this.attrs.error.output))); + }; + + return ComposerFailureModal; +}(flarum_common_components_Modal__WEBPACK_IMPORTED_MODULE_2___default.a); + + + /***/ }), /***/ "./src/admin/components/Installer.tsx": @@ -163,6 +225,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var flarum_common_utils_Stream__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(flarum_common_utils_Stream__WEBPACK_IMPORTED_MODULE_4__); /* harmony import */ var flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! flarum/admin/components/LoadingModal */ "flarum/admin/components/LoadingModal"); /* harmony import */ var flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_5__); +/* harmony import */ var _ComposerFailureModal__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./ComposerFailureModal */ "./src/admin/components/ComposerFailureModal.tsx"); + @@ -236,6 +300,17 @@ var Installer = /*#__PURE__*/function (_Component) { url: flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.forum.attribute('apiUrl') + "/package-manager/extensions", body: { data: this.data() + }, + errorHandler: function errorHandler(e) { + var error = e.response.errors[0]; + + if (error.code !== 'composer_command_failure') { + throw e; + } + + flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.modal.show(_ComposerFailureModal__WEBPACK_IMPORTED_MODULE_6__["default"], { + error: error + }); } }).then(function (response) { var extensionId = response.data.attributes.id; @@ -272,13 +347,16 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var flarum_common_extend__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(flarum_common_extend__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var flarum_admin_app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! flarum/admin/app */ "flarum/admin/app"); /* harmony import */ var flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(flarum_admin_app__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var flarum_admin_components_ExtensionPage__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! flarum/admin/components/ExtensionPage */ "flarum/admin/components/ExtensionPage"); -/* harmony import */ var flarum_admin_components_ExtensionPage__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(flarum_admin_components_ExtensionPage__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! flarum/common/components/Button */ "flarum/common/components/Button"); -/* harmony import */ var flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! flarum/admin/components/LoadingModal */ "flarum/admin/components/LoadingModal"); -/* harmony import */ var flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_4__); -/* harmony import */ var _components_Installer__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./components/Installer */ "./src/admin/components/Installer.tsx"); +/* harmony import */ var flarum_common_components_Alert__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! flarum/common/components/Alert */ "flarum/common/components/Alert"); +/* harmony import */ var flarum_common_components_Alert__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(flarum_common_components_Alert__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var flarum_admin_components_ExtensionPage__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! flarum/admin/components/ExtensionPage */ "flarum/admin/components/ExtensionPage"); +/* harmony import */ var flarum_admin_components_ExtensionPage__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(flarum_admin_components_ExtensionPage__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! flarum/common/components/Button */ "flarum/common/components/Button"); +/* harmony import */ var flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_4__); +/* harmony import */ var flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! flarum/admin/components/LoadingModal */ "flarum/admin/components/LoadingModal"); +/* harmony import */ var flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_5__); +/* harmony import */ var _components_Installer__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./components/Installer */ "./src/admin/components/Installer.tsx"); + @@ -287,16 +365,27 @@ __webpack_require__.r(__webpack_exports__); flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.initializers.add('sycho-package-manager', function (app) { app.extensionData["for"]('sycho-package-manager').registerSetting(function () { - return m(_components_Installer__WEBPACK_IMPORTED_MODULE_5__["default"], null); + if (!app.data.isRequiredDirectoriesWritable) { + return m("div", { + className: "Form-group" + }, m(flarum_common_components_Alert__WEBPACK_IMPORTED_MODULE_2___default.a, { + type: "warning", + dismissible: false + }, app.translator.trans('sycho-package-manager.admin.file_permissions'))); + } + }).registerSetting(function () { + if (app.data.isRequiredDirectoriesWritable) { + return m(_components_Installer__WEBPACK_IMPORTED_MODULE_6__["default"], null); + } }); - Object(flarum_common_extend__WEBPACK_IMPORTED_MODULE_0__["extend"])(flarum_admin_components_ExtensionPage__WEBPACK_IMPORTED_MODULE_2___default.a.prototype, 'topItems', function (items) { + Object(flarum_common_extend__WEBPACK_IMPORTED_MODULE_0__["extend"])(flarum_admin_components_ExtensionPage__WEBPACK_IMPORTED_MODULE_3___default.a.prototype, 'topItems', function (items) { var _this = this; - items.add('remove', m(flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_3___default.a, { + items.add('remove', m(flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_4___default.a, { className: "Button Button--danger", icon: "fas fa-times", onclick: function onclick() { - app.modal.show(flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_4___default.a); + app.modal.show(flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_5___default.a); app.request({ url: app.forum.attribute('apiUrl') + "/package-manager/extensions/" + _this.extension.id, method: 'DELETE' @@ -359,6 +448,17 @@ module.exports = flarum.core.compat['common/Component']; /***/ }), +/***/ "flarum/common/components/Alert": +/*!****************************************************************!*\ + !*** external "flarum.core.compat['common/components/Alert']" ***! + \****************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +module.exports = flarum.core.compat['common/components/Alert']; + +/***/ }), + /***/ "flarum/common/components/Button": /*!*****************************************************************!*\ !*** external "flarum.core.compat['common/components/Button']" ***! @@ -370,6 +470,17 @@ module.exports = flarum.core.compat['common/components/Button']; /***/ }), +/***/ "flarum/common/components/Modal": +/*!****************************************************************!*\ + !*** external "flarum.core.compat['common/components/Modal']" ***! + \****************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +module.exports = flarum.core.compat['common/components/Modal']; + +/***/ }), + /***/ "flarum/common/extend": /*!******************************************************!*\ !*** external "flarum.core.compat['common/extend']" ***! diff --git a/extensions/package-manager/js/dist/admin.js.map b/extensions/package-manager/js/dist/admin.js.map index 3b8427201..e5c4a111a 100644 --- a/extensions/package-manager/js/dist/admin.js.map +++ b/extensions/package-manager/js/dist/admin.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack://@sycho/flarum-package-manager/webpack/bootstrap","webpack://@sycho/flarum-package-manager/./admin.js","webpack://@sycho/flarum-package-manager/./node_modules/@babel/runtime/helpers/esm/inheritsLoose.js","webpack://@sycho/flarum-package-manager/./node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js","webpack://@sycho/flarum-package-manager/./src/admin/components/Installer.tsx","webpack://@sycho/flarum-package-manager/./src/admin/index.js","webpack://@sycho/flarum-package-manager/external \"flarum.core.compat['admin/app']\"","webpack://@sycho/flarum-package-manager/external \"flarum.core.compat['admin/components/ExtensionPage']\"","webpack://@sycho/flarum-package-manager/external \"flarum.core.compat['admin/components/LoadingModal']\"","webpack://@sycho/flarum-package-manager/external \"flarum.core.compat['common/Component']\"","webpack://@sycho/flarum-package-manager/external \"flarum.core.compat['common/components/Button']\"","webpack://@sycho/flarum-package-manager/external \"flarum.core.compat['common/extend']\"","webpack://@sycho/flarum-package-manager/external \"flarum.core.compat['common/utils/Stream']\""],"names":["_inheritsLoose","subClass","superClass","prototype","Object","create","constructor","setPrototypeOf","_setPrototypeOf","o","p","__proto__","Installer","packageName","isLoading","oninit","vnode","Stream","view","app","translator","trans","extiverse","onsubmit","bind","data","modal","show","LoadingModal","request","method","url","forum","attribute","body","then","response","extensionId","attributes","id","alerts","type","extension","window","location","href","reload","m","redraw","Component","initializers","add","extensionData","registerSetting","extend","ExtensionPage","items","close"],"mappings":"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","file":"admin.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./admin.js\");\n","export * from './src/admin';","import setPrototypeOf from \"./setPrototypeOf.js\";\nexport default function _inheritsLoose(subClass, superClass) {\n subClass.prototype = Object.create(superClass.prototype);\n subClass.prototype.constructor = subClass;\n setPrototypeOf(subClass, superClass);\n}","export default function _setPrototypeOf(o, p) {\n _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {\n o.__proto__ = p;\n return o;\n };\n\n return _setPrototypeOf(o, p);\n}","import type Mithril from 'mithril';\nimport app from 'flarum/admin/app';\nimport Component from 'flarum/common/Component';\nimport Button from \"flarum/common/components/Button\";\nimport Stream from \"flarum/common/utils/Stream\";\nimport LoadingModal from \"flarum/admin/components/LoadingModal\";\n\nexport default class Installer extends Component {\n packageName!: Stream;\n isLoading: boolean = false;\n\n oninit(vnode: Mithril.Vnode): void {\n super.oninit(vnode);\n\n this.packageName = Stream('');\n }\n\n view(): Mithril.Children {\n return (\n
\n \n

{app.translator.trans('sycho-package-manager.admin.extensions.install_help', {\n extiverse: extiverse.com\n })}

\n
\n \n \n
\n
\n );\n }\n\n data(): any {\n return {\n package: this.packageName(),\n };\n }\n\n onsubmit(): void {\n this.isLoading = true;\n app.modal.show(LoadingModal);\n\n app.request({\n method: 'POST',\n url: `${app.forum.attribute('apiUrl')}/package-manager/extensions`,\n body: {\n data: this.data()\n },\n }).then((response) => {\n const extensionId = response.data.attributes.id;\n app.alerts.show({ type: 'success' }, app.translator.trans('sycho-package-manager.admin.extensions.successful_install', { extension: extensionId }));\n window.location.href = `${app.forum.attribute('adminUrl')}#/extension/${extensionId}`;\n window.location.reload();\n }).finally(() => {\n this.isLoading = false;\n m.redraw();\n });\n }\n}\n","import { extend } from 'flarum/common/extend';\nimport app from 'flarum/admin/app';\nimport ExtensionPage from 'flarum/admin/components/ExtensionPage';\nimport Button from 'flarum/common/components/Button';\nimport LoadingModal from 'flarum/admin/components/LoadingModal';\nimport Installer from \"./components/Installer\";\n\napp.initializers.add('sycho-package-manager', (app) => {\n app.extensionData\n .for('sycho-package-manager')\n .registerSetting(() => {\n return (\n \n );\n });\n\n extend(ExtensionPage.prototype, 'topItems', function (items) {\n items.add(\n 'remove',\n {\n app.modal.show(LoadingModal);\n\n app.request({\n url: `${app.forum.attribute('apiUrl')}/package-manager/extensions/${this.extension.id}`,\n method: 'DELETE',\n }).then(() => {\n app.alerts.show({ type: 'success' }, app.translator.trans('sycho-package-manager.admin.extensions.successful_remove'));\n window.location = app.forum.attribute('adminUrl');\n }).finally(() => {\n app.modal.close();\n });\n }}>\n Remove\n \n );\n });\n});\n","module.exports = flarum.core.compat['admin/app'];","module.exports = flarum.core.compat['admin/components/ExtensionPage'];","module.exports = flarum.core.compat['admin/components/LoadingModal'];","module.exports = flarum.core.compat['common/Component'];","module.exports = flarum.core.compat['common/components/Button'];","module.exports = flarum.core.compat['common/extend'];","module.exports = flarum.core.compat['common/utils/Stream'];"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack://@sycho/flarum-package-manager/webpack/bootstrap","webpack://@sycho/flarum-package-manager/./admin.js","webpack://@sycho/flarum-package-manager/./node_modules/@babel/runtime/helpers/esm/inheritsLoose.js","webpack://@sycho/flarum-package-manager/./node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js","webpack://@sycho/flarum-package-manager/./src/admin/components/ComposerFailureModal.tsx","webpack://@sycho/flarum-package-manager/./src/admin/components/Installer.tsx","webpack://@sycho/flarum-package-manager/./src/admin/index.js","webpack://@sycho/flarum-package-manager/external \"flarum.core.compat['admin/app']\"","webpack://@sycho/flarum-package-manager/external \"flarum.core.compat['admin/components/ExtensionPage']\"","webpack://@sycho/flarum-package-manager/external \"flarum.core.compat['admin/components/LoadingModal']\"","webpack://@sycho/flarum-package-manager/external \"flarum.core.compat['common/Component']\"","webpack://@sycho/flarum-package-manager/external \"flarum.core.compat['common/components/Alert']\"","webpack://@sycho/flarum-package-manager/external \"flarum.core.compat['common/components/Button']\"","webpack://@sycho/flarum-package-manager/external \"flarum.core.compat['common/components/Modal']\"","webpack://@sycho/flarum-package-manager/external \"flarum.core.compat['common/extend']\"","webpack://@sycho/flarum-package-manager/external \"flarum.core.compat['common/utils/Stream']\""],"names":["_inheritsLoose","subClass","superClass","prototype","Object","create","constructor","setPrototypeOf","_setPrototypeOf","o","p","__proto__","ComposerFailureModal","oninit","vnode","attrs","error","guessed_cause","alertAttrs","type","content","app","translator","trans","className","title","output","Modal","Installer","packageName","isLoading","Stream","view","extiverse","onsubmit","bind","data","modal","show","LoadingModal","request","method","url","forum","attribute","body","errorHandler","e","response","errors","code","then","extensionId","attributes","id","alerts","extension","window","location","href","reload","m","redraw","Component","initializers","add","extensionData","registerSetting","isRequiredDirectoriesWritable","extend","ExtensionPage","items","close"],"mappings":"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","file":"admin.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./admin.js\");\n","export * from './src/admin';","import setPrototypeOf from \"./setPrototypeOf.js\";\nexport default function _inheritsLoose(subClass, superClass) {\n subClass.prototype = Object.create(superClass.prototype);\n subClass.prototype.constructor = subClass;\n setPrototypeOf(subClass, superClass);\n}","export default function _setPrototypeOf(o, p) {\n _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {\n o.__proto__ = p;\n return o;\n };\n\n return _setPrototypeOf(o, p);\n}","import app from 'flarum/admin/app';\nimport Modal from 'flarum/common/components/Modal';\nimport { ComponentAttrs } from \"flarum/common/Component\";\nimport Alert from \"flarum/common/components/Alert\";\nimport Mithril from \"mithril\";\n\ninterface Attrs extends ComponentAttrs {\n output: string;\n}\n\nexport default class ComposerFailureModal extends Modal {\n oninit(vnode: Mithril.Vnode) {\n super.oninit(vnode);\n\n if (this.attrs.error.guessed_cause) {\n this.alertAttrs = {\n type: 'error',\n content: app.translator.trans(`sycho-package-manager.admin.failure_modal.guessed_cause.${this.attrs.error.guessed_cause}`),\n };\n }\n }\n\n className() {\n return 'Modal--large ComposerFailureModal';\n }\n\n title() {\n return app.translator.trans('sycho-package-manager.admin.failure_modal.title');\n }\n\n content() {\n return (\n
\n
\n {app.translator.trans('sycho-package-manager.admin.failure_modal.show_composer_output')}\n
{this.attrs.error.output}
\n
\n
\n );\n }\n}\n","import type Mithril from 'mithril';\nimport app from 'flarum/admin/app';\nimport Component from 'flarum/common/Component';\nimport Button from \"flarum/common/components/Button\";\nimport Stream from \"flarum/common/utils/Stream\";\nimport LoadingModal from \"flarum/admin/components/LoadingModal\";\nimport ComposerFailureModal from \"./ComposerFailureModal\";\n\nexport default class Installer extends Component {\n packageName!: Stream;\n isLoading: boolean = false;\n\n oninit(vnode: Mithril.Vnode): void {\n super.oninit(vnode);\n\n this.packageName = Stream('');\n }\n\n view(): Mithril.Children {\n return (\n
\n \n

{app.translator.trans('sycho-package-manager.admin.extensions.install_help', {\n extiverse: extiverse.com\n })}

\n
\n \n \n
\n
\n );\n }\n\n data(): any {\n return {\n package: this.packageName(),\n };\n }\n\n onsubmit(): void {\n this.isLoading = true;\n app.modal.show(LoadingModal);\n\n app.request({\n method: 'POST',\n url: `${app.forum.attribute('apiUrl')}/package-manager/extensions`,\n body: {\n data: this.data()\n },\n errorHandler: (e: any) => {\n const error = e.response.errors[0];\n\n if (error.code !== 'composer_command_failure') {\n throw e;\n }\n\n app.modal.show(ComposerFailureModal, { error });\n },\n }).then((response) => {\n const extensionId = response.data.attributes.id;\n app.alerts.show({ type: 'success' }, app.translator.trans('sycho-package-manager.admin.extensions.successful_install', { extension: extensionId }));\n window.location.href = `${app.forum.attribute('adminUrl')}#/extension/${extensionId}`;\n window.location.reload();\n }).finally(() => {\n this.isLoading = false;\n m.redraw();\n });\n }\n}\n","import { extend } from 'flarum/common/extend';\nimport app from 'flarum/admin/app';\nimport Alert from 'flarum/common/components/Alert';\nimport ExtensionPage from 'flarum/admin/components/ExtensionPage';\nimport Button from 'flarum/common/components/Button';\nimport LoadingModal from 'flarum/admin/components/LoadingModal';\nimport Installer from \"./components/Installer\";\n\napp.initializers.add('sycho-package-manager', (app) => {\n app.extensionData\n .for('sycho-package-manager')\n .registerSetting(() => {\n if (!app.data.isRequiredDirectoriesWritable) {\n return (\n
\n {app.translator.trans('sycho-package-manager.admin.file_permissions')}\n
\n );\n }\n })\n .registerSetting(() => {\n if (app.data.isRequiredDirectoriesWritable) {\n return (\n \n );\n }\n });\n\n extend(ExtensionPage.prototype, 'topItems', function (items) {\n items.add(\n 'remove',\n {\n app.modal.show(LoadingModal);\n\n app.request({\n url: `${app.forum.attribute('apiUrl')}/package-manager/extensions/${this.extension.id}`,\n method: 'DELETE',\n }).then(() => {\n app.alerts.show({ type: 'success' }, app.translator.trans('sycho-package-manager.admin.extensions.successful_remove'));\n window.location = app.forum.attribute('adminUrl');\n }).finally(() => {\n app.modal.close();\n });\n }}>\n Remove\n \n );\n });\n});\n","module.exports = flarum.core.compat['admin/app'];","module.exports = flarum.core.compat['admin/components/ExtensionPage'];","module.exports = flarum.core.compat['admin/components/LoadingModal'];","module.exports = flarum.core.compat['common/Component'];","module.exports = flarum.core.compat['common/components/Alert'];","module.exports = flarum.core.compat['common/components/Button'];","module.exports = flarum.core.compat['common/components/Modal'];","module.exports = flarum.core.compat['common/extend'];","module.exports = flarum.core.compat['common/utils/Stream'];"],"sourceRoot":""} \ No newline at end of file diff --git a/extensions/package-manager/js/src/admin/components/ComposerFailureModal.tsx b/extensions/package-manager/js/src/admin/components/ComposerFailureModal.tsx new file mode 100644 index 000000000..5fd616aa7 --- /dev/null +++ b/extensions/package-manager/js/src/admin/components/ComposerFailureModal.tsx @@ -0,0 +1,41 @@ +import app from 'flarum/admin/app'; +import Modal from 'flarum/common/components/Modal'; +import { ComponentAttrs } from "flarum/common/Component"; +import Alert from "flarum/common/components/Alert"; +import Mithril from "mithril"; + +interface Attrs extends ComponentAttrs { + output: string; +} + +export default class ComposerFailureModal extends Modal { + oninit(vnode: Mithril.Vnode) { + super.oninit(vnode); + + if (this.attrs.error.guessed_cause) { + this.alertAttrs = { + type: 'error', + content: app.translator.trans(`sycho-package-manager.admin.failure_modal.guessed_cause.${this.attrs.error.guessed_cause}`), + }; + } + } + + className() { + return 'Modal--large ComposerFailureModal'; + } + + title() { + return app.translator.trans('sycho-package-manager.admin.failure_modal.title'); + } + + content() { + return ( +
+
+ {app.translator.trans('sycho-package-manager.admin.failure_modal.show_composer_output')} +
{this.attrs.error.output}
+
+
+ ); + } +} diff --git a/extensions/package-manager/js/src/admin/components/Installer.tsx b/extensions/package-manager/js/src/admin/components/Installer.tsx index b889978ed..ab421b700 100644 --- a/extensions/package-manager/js/src/admin/components/Installer.tsx +++ b/extensions/package-manager/js/src/admin/components/Installer.tsx @@ -4,6 +4,7 @@ import Component from 'flarum/common/Component'; import Button from "flarum/common/components/Button"; import Stream from "flarum/common/utils/Stream"; import LoadingModal from "flarum/admin/components/LoadingModal"; +import ComposerFailureModal from "./ComposerFailureModal"; export default class Installer extends Component { packageName!: Stream; @@ -48,6 +49,15 @@ export default class Installer extends Component { body: { data: this.data() }, + errorHandler: (e: any) => { + const error = e.response.errors[0]; + + if (error.code !== 'composer_command_failure') { + throw e; + } + + app.modal.show(ComposerFailureModal, { error }); + }, }).then((response) => { const extensionId = response.data.attributes.id; app.alerts.show({ type: 'success' }, app.translator.trans('sycho-package-manager.admin.extensions.successful_install', { extension: extensionId })); diff --git a/extensions/package-manager/js/src/admin/index.js b/extensions/package-manager/js/src/admin/index.js index b2a9efbc7..9d3f933ca 100644 --- a/extensions/package-manager/js/src/admin/index.js +++ b/extensions/package-manager/js/src/admin/index.js @@ -1,5 +1,6 @@ import { extend } from 'flarum/common/extend'; import app from 'flarum/admin/app'; +import Alert from 'flarum/common/components/Alert'; import ExtensionPage from 'flarum/admin/components/ExtensionPage'; import Button from 'flarum/common/components/Button'; import LoadingModal from 'flarum/admin/components/LoadingModal'; @@ -9,9 +10,20 @@ app.initializers.add('sycho-package-manager', (app) => { app.extensionData .for('sycho-package-manager') .registerSetting(() => { + if (!app.data.isRequiredDirectoriesWritable) { + return ( +
+ {app.translator.trans('sycho-package-manager.admin.file_permissions')} +
+ ); + } + }) + .registerSetting(() => { + if (app.data.isRequiredDirectoriesWritable) { return ( ); + } }); extend(ExtensionPage.prototype, 'topItems', function (items) { diff --git a/extensions/package-manager/less/admin.less b/extensions/package-manager/less/admin.less index a0b536357..bb5abb89f 100644 --- a/extensions/package-manager/less/admin.less +++ b/extensions/package-manager/less/admin.less @@ -4,3 +4,7 @@ flex-wrap: wrap; gap: 4px; } + +.ComposerFailureModal-output { + white-space: break-spaces; +} diff --git a/extensions/package-manager/locale/en.yml b/extensions/package-manager/locale/en.yml index 58d5f1fc5..a413eb9f6 100644 --- a/extensions/package-manager/locale/en.yml +++ b/extensions/package-manager/locale/en.yml @@ -7,3 +7,11 @@ sycho-package-manager: successful_install: "{extension} was installed successfully, redirecting.." successful_remove: Extension removed successfully. + failure_modal: + title: Operation Failed + guessed_cause: + extension_incompatible_with_instance: The extension is most likely incompatible with your current Flarum instance. + show_composer_output: Show Advanced Details + + file_permissions: > + The package manager requires read and write permissions on the following files and directories: composer.json, composer.lock, vendor, storage/.composer diff --git a/extensions/package-manager/src/Api/Controller/RequireExtensionController.php b/extensions/package-manager/src/Api/Controller/RequireExtensionController.php index 88351212b..7213357c9 100644 --- a/extensions/package-manager/src/Api/Controller/RequireExtensionController.php +++ b/extensions/package-manager/src/Api/Controller/RequireExtensionController.php @@ -3,6 +3,9 @@ namespace SychO\PackageManager\Api\Controller; use Flarum\Bus\Dispatcher; +use Laminas\Diactoros\Response\JsonResponse; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Server\RequestHandlerInterface; use SychO\PackageManager\Api\Serializer\ExtensionSerializer; use SychO\PackageManager\Command\RequireExtension; use SychO\PackageManager\Extension\ExtensionUtils; @@ -12,10 +15,8 @@ use Illuminate\Support\Arr; use Psr\Http\Message\ServerRequestInterface; use Tobscure\JsonApi\Document; -class RequireExtensionController extends AbstractCreateController +class RequireExtensionController implements RequestHandlerInterface { - public $serializer = ExtensionSerializer::class; - /** * @var Dispatcher */ @@ -26,13 +27,15 @@ class RequireExtensionController extends AbstractCreateController $this->bus = $bus; } - protected function data(ServerRequestInterface $request, Document $document) + public function handle(ServerRequestInterface $request): ResponseInterface { $actor = RequestUtil::getActor($request); $package = Arr::get($request->getParsedBody(), 'data.package'); - return $this->bus->dispatch( + $data = $this->bus->dispatch( new RequireExtension($actor, $package) ); + + return new JsonResponse($data); } } diff --git a/extensions/package-manager/src/Command/RequireExtensionHandler.php b/extensions/package-manager/src/Command/RequireExtensionHandler.php index 57a9e5a1f..5d429f907 100644 --- a/extensions/package-manager/src/Command/RequireExtensionHandler.php +++ b/extensions/package-manager/src/Command/RequireExtensionHandler.php @@ -4,6 +4,7 @@ namespace SychO\PackageManager\Command; use Composer\Console\Application; use Flarum\Extension\ExtensionManager; +use SychO\PackageManager\Exception\ComposerRequireFailedException; use SychO\PackageManager\Extension\ExtensionUtils; use SychO\PackageManager\RequirePackageValidator; use Symfony\Component\Console\Input\ArrayInput; @@ -56,7 +57,11 @@ class RequireExtensionHandler 'packages' => [$command->package], ]); - $this->composer->run($input, $output); + $exitCode = $this->composer->run($input, $output); + + if ($exitCode !== 0) { + throw new ComposerRequireFailedException($command->package, $output->fetch()); + } return ['id' => $extensionId]; } diff --git a/extensions/package-manager/src/Exception/ComposerCommandFailedExceptionHandler.php b/extensions/package-manager/src/Exception/ComposerCommandFailedExceptionHandler.php new file mode 100644 index 000000000..7aaa72dc2 --- /dev/null +++ b/extensions/package-manager/src/Exception/ComposerCommandFailedExceptionHandler.php @@ -0,0 +1,48 @@ +withDetails($this->errorDetails($e)); + } + + protected function errorDetails(ComposerRequireFailedException $e): array + { + $details = [ + 'output' => $e->getMessage(), + ]; + + if ($guessedCause = $this->guessCause($e)) { + $details['guessed_cause'] = $guessedCause; + } + + return [$details]; + } + + protected function guessCause(ComposerRequireFailedException $e): ?string + { + error_log(str_replace('{PACKAGE_NAME}', preg_quote($e->packageName, '/'), self::INCOMPATIBLE_REGEX)); + $hasMatches = preg_match(str_replace('{PACKAGE_NAME}', preg_quote($e->packageName, '/'), self::INCOMPATIBLE_REGEX), $e->getMessage(), $matches); + + if ($hasMatches) { + return 'extension_incompatible_with_instance'; + } + + return null; + } +} diff --git a/extensions/package-manager/src/Exception/ComposerRequireFailedException.php b/extensions/package-manager/src/Exception/ComposerRequireFailedException.php new file mode 100644 index 000000000..cb68e21e7 --- /dev/null +++ b/extensions/package-manager/src/Exception/ComposerRequireFailedException.php @@ -0,0 +1,24 @@ +packageName = $packageName; + + parent::__construct($output); + } +}