From 5b9f981868ba05a16185f46cd8942d09c125818e Mon Sep 17 00:00:00 2001 From: Christian Einvik <84850107+chrieinv@users.noreply.github.com> Date: Fri, 17 Jan 2025 12:41:01 +0100 Subject: [PATCH 01/12] Add owner info to use/edit response (#2916) --- .../Http/Controllers/ContentController.php | 8 +++--- sourcecode/hub/app/Models/ContentVersion.php | 27 ++++++++++++++----- sourcecode/hub/composer.lock | 8 +++--- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/sourcecode/hub/app/Http/Controllers/ContentController.php b/sourcecode/hub/app/Http/Controllers/ContentController.php index ab68c19fa..e139139c6 100644 --- a/sourcecode/hub/app/Http/Controllers/ContentController.php +++ b/sourcecode/hub/app/Http/Controllers/ContentController.php @@ -242,14 +242,12 @@ public function use( ?? throw new BadMethodCallException('Not in LTI selection context'); assert(is_string($returnUrl)); - $credentials = LtiPlatform::where('key', $request->session()->get('lti.oauth_consumer_key')) - ->firstOrFail() - ->getOauth1Credentials(); + $platform = LtiPlatform::where('key', $request->session()->get('lti.oauth_consumer_key'))->firstOrFail(); $ltiRequest = $itemSelectionFactory->createItemSelection( - [$version->toLtiLinkItem()], + [$version->toLtiLinkItem($platform)], $returnUrl, - $credentials, + $platform->getOauth1Credentials(), $request->session()->get('lti.data'), ); diff --git a/sourcecode/hub/app/Models/ContentVersion.php b/sourcecode/hub/app/Models/ContentVersion.php index 10ca8cee1..b1f85471b 100755 --- a/sourcecode/hub/app/Models/ContentVersion.php +++ b/sourcecode/hub/app/Models/ContentVersion.php @@ -4,6 +4,7 @@ namespace App\Models; +use App\Enums\ContentRole; use App\Events\ContentVersionDeleting; use App\Events\ContentVersionSaving; use App\Lti\ContentItemSelectionFactory; @@ -26,6 +27,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Session; use function app; use function assert; @@ -80,9 +82,16 @@ class ContentVersion extends Model 'saving' => ContentVersionSaving::class, ]; - public function toLtiLinkItem(): EdlibLtiLinkItem + public function toLtiLinkItem(LtiPlatform $platform): EdlibLtiLinkItem { $iconUrl = $this->icon?->getUrl(); + $ownerEmail = null; + + if (Session::get('lti.ext_edlib3_include_owner_info') === '1' && $platform->authorizes_edit) { + $ownerEmail = $this->content?->users->first( + fn(User $user) => $user->getRelationValue('pivot')->role === ContentRole::Owner, + )?->email; + } return (new EdlibLtiLinkItem( title: $this->getTitle(), @@ -96,6 +105,7 @@ public function toLtiLinkItem(): EdlibLtiLinkItem ->withLanguageIso639_3($this->language_iso_639_3) ->withLicense($this->license) ->withTags($this->getSerializedTags()) + ->withOwnerEmail($ownerEmail) ; } @@ -134,14 +144,17 @@ public function toItemSelectionRequest(): Oauth1Request ?? throw new BadMethodCallException('Not in LTI selection context'); assert(is_string($returnUrl)); - $credentials = LtiPlatform::where('key', session()->get('lti.oauth_consumer_key')) - ->firstOrFail() - ->getOauth1Credentials(); - + $platform = LtiPlatform::where('key', session()->get('lti.oauth_consumer_key'))->firstOrFail(); $data = session()->get('lti.data'); - return app()->make(ContentItemSelectionFactory::class) - ->createItemSelection([$this->toLtiLinkItem()], $returnUrl, $credentials, $data); + return app() + ->make(ContentItemSelectionFactory::class) + ->createItemSelection( + [$this->toLtiLinkItem($platform)], + $returnUrl, + $platform->getOauth1Credentials(), + $data, + ); } /** diff --git a/sourcecode/hub/composer.lock b/sourcecode/hub/composer.lock index a23b13b59..bb4934c31 100644 --- a/sourcecode/hub/composer.lock +++ b/sourcecode/hub/composer.lock @@ -293,12 +293,12 @@ "source": { "type": "git", "url": "https://github.com/cerpus/php-edlib-resource-kit.git", - "reference": "af41490a0c70c69491616eab8382ae3dc01be55d" + "reference": "a3671acd6ffd26a421a750a4081a6b6f4ff1b1df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cerpus/php-edlib-resource-kit/zipball/af41490a0c70c69491616eab8382ae3dc01be55d", - "reference": "af41490a0c70c69491616eab8382ae3dc01be55d", + "url": "https://api.github.com/repos/cerpus/php-edlib-resource-kit/zipball/a3671acd6ffd26a421a750a4081a6b6f4ff1b1df", + "reference": "a3671acd6ffd26a421a750a4081a6b6f4ff1b1df", "shasum": "" }, "require": { @@ -345,7 +345,7 @@ "issues": "https://github.com/cerpus/Edlib/issues", "source": "https://github.com/cerpus/php-edlib-resource-kit/tree/master" }, - "time": "2024-11-21T12:26:48+00:00" + "time": "2025-01-17T08:54:44+00:00" }, { "name": "cerpus/edlib-resource-kit-laravel", From 290e42a4a7d72556cf4f56226e03694a2224bb20 Mon Sep 17 00:00:00 2001 From: Christian Einvik <84850107+chrieinv@users.noreply.github.com> Date: Fri, 17 Jan 2025 12:53:41 +0100 Subject: [PATCH 02/12] Docs: Update LTI extended parameters (#2917) --- docs/docs/developers/content-types.mdx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/docs/developers/content-types.mdx b/docs/docs/developers/content-types.mdx index 48cac73ad..5706dff9d 100644 --- a/docs/docs/developers/content-types.mdx +++ b/docs/docs/developers/content-types.mdx @@ -29,6 +29,16 @@ support this, content selected via the default endpoint just replaces the previo Make the 'Use Content' button in item selections return a link to the current version of a resource. +* `ext_edlib3_include_owner_info` + + If enabled, and the LTI Platform has setting `The platform authorizes edit access` enabled, the e-mail address of + the content owner will be included in the response. Set to `"1"` to enable, not enabled by default. + +* `ext_edlib3_copy_before_save` + + For edit requests. Instructs Edlib to create a copy of the content and save the changes to the copy. + Set to `"1"` to enable, not enabled by default. + ## Extended LTI parameters sent to LTI tools by the Hub * `ext_edlib3_embed_resize_code` From 02ac24490bc78f1663dec5047ef97a738bbb3aea Mon Sep 17 00:00:00 2001 From: Christian Einvik <84850107+chrieinv@users.noreply.github.com> Date: Fri, 17 Jan 2025 15:02:59 +0100 Subject: [PATCH 03/12] CA: Adjust paths for php-cs-fixer (#2910) --- .../apis/contentauthor/.php-cs-fixer.dist.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/sourcecode/apis/contentauthor/.php-cs-fixer.dist.php b/sourcecode/apis/contentauthor/.php-cs-fixer.dist.php index 3df94d2de..ec33b3527 100644 --- a/sourcecode/apis/contentauthor/.php-cs-fixer.dist.php +++ b/sourcecode/apis/contentauthor/.php-cs-fixer.dist.php @@ -1,13 +1,12 @@ in(__DIR__) - ->path('app') - ->path('bootstrap/app.php') - ->path('config') - ->path('database') - ->path('routes') - ->path('tests') + ->in(__DIR__ . '/app/') + ->in(__DIR__ . '/bootstrap/')->exclude('cache')->name('/app.php') + ->in(__DIR__ . '/config/') + ->in(__DIR__ . '/database/') + ->in(__DIR__ . '/routes/') + ->in(__DIR__ . '/tests/') ; return (new PhpCsFixer\Config()) From 3bab59e37e850d9d05128b02de21181aea72281d Mon Sep 17 00:00:00 2001 From: "Emma C. Hughes" <84008144+emmachughes@users.noreply.github.com> Date: Fri, 17 Jan 2025 15:15:02 +0100 Subject: [PATCH 04/12] add job for attaching context to contents (#2918) --- .../Controllers/Admin/ContextController.php | 24 +++++++++++++++++ .../AttachContextToContentsRequest.php | 27 +++++++++++++++++++ .../hub/app/Jobs/AttachContextToContents.php | 27 +++++++++++++++++++ sourcecode/hub/lang/en/messages.php | 3 +++ .../contexts/attach-to-contents.blade.php | 18 +++++++++++++ .../hub/resources/views/admin/index.blade.php | 6 +++++ sourcecode/hub/routes/web.php | 7 +++++ 7 files changed, 112 insertions(+) create mode 100644 sourcecode/hub/app/Http/Requests/AttachContextToContentsRequest.php create mode 100644 sourcecode/hub/app/Jobs/AttachContextToContents.php create mode 100644 sourcecode/hub/resources/views/admin/contexts/attach-to-contents.blade.php diff --git a/sourcecode/hub/app/Http/Controllers/Admin/ContextController.php b/sourcecode/hub/app/Http/Controllers/Admin/ContextController.php index 720c22cf8..61a4c9578 100644 --- a/sourcecode/hub/app/Http/Controllers/Admin/ContextController.php +++ b/sourcecode/hub/app/Http/Controllers/Admin/ContextController.php @@ -4,8 +4,11 @@ namespace App\Http\Controllers\Admin; +use App\Http\Requests\AttachContextToContentsRequest; use App\Http\Requests\StoreContextRequest; +use App\Jobs\AttachContextToContents; use App\Models\Context; +use Illuminate\Contracts\Bus\Dispatcher; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Response; @@ -31,4 +34,25 @@ public function add(StoreContextRequest $request): RedirectResponse return redirect()->route('admin.contexts.index') ->with('alert', trans('messages.context-added')); } + + public function attachToContents(): Response + { + $contexts = Context::all() + ->mapWithKeys(fn(Context $context) => [$context->id => $context->name]); + + return response()->view('admin.contexts.attach-to-contents', [ + 'available_contexts' => $contexts, + ]); + } + + public function performAttachToContents( + AttachContextToContentsRequest $request, + Dispatcher $dispatcher, + ): RedirectResponse { + $dispatcher->dispatch( + new AttachContextToContents($request->getContext()), + ); + + return redirect()->route('admin.index'); + } } diff --git a/sourcecode/hub/app/Http/Requests/AttachContextToContentsRequest.php b/sourcecode/hub/app/Http/Requests/AttachContextToContentsRequest.php new file mode 100644 index 000000000..4adf07103 --- /dev/null +++ b/sourcecode/hub/app/Http/Requests/AttachContextToContentsRequest.php @@ -0,0 +1,27 @@ + + */ + public function rules(): array + { + return [ + 'context' => ['required', Rule::exists(Context::class, 'id')], + ]; + } + + public function getContext(): Context + { + return Context::where('id', $this->validated('context'))->firstOrFail(); + } +} diff --git a/sourcecode/hub/app/Jobs/AttachContextToContents.php b/sourcecode/hub/app/Jobs/AttachContextToContents.php new file mode 100644 index 000000000..a39974590 --- /dev/null +++ b/sourcecode/hub/app/Jobs/AttachContextToContents.php @@ -0,0 +1,27 @@ +each(function (Content $content) { + $content->contexts()->syncWithoutDetaching([$this->context]); + }); + } +} diff --git a/sourcecode/hub/lang/en/messages.php b/sourcecode/hub/lang/en/messages.php index b75eeaab0..cd9d80c27 100644 --- a/sourcecode/hub/lang/en/messages.php +++ b/sourcecode/hub/lang/en/messages.php @@ -238,4 +238,7 @@ 'context-added' => 'The context was added.', 'theme-edlib' => 'Edlib light', 'theme-dark' => 'Edlib dark', + 'attach-context-to-contents' => 'Attach context to contents', + 'attach-context-to-contents-warning' => 'This adds a context to all contents', + 'start-job' => 'Start job', ]; diff --git a/sourcecode/hub/resources/views/admin/contexts/attach-to-contents.blade.php b/sourcecode/hub/resources/views/admin/contexts/attach-to-contents.blade.php new file mode 100644 index 000000000..4227526dd --- /dev/null +++ b/sourcecode/hub/resources/views/admin/contexts/attach-to-contents.blade.php @@ -0,0 +1,18 @@ + + {{ trans('messages.attach-context-to-contents') }} + +

{{ trans('messages.attach-context-to-contents-warning') }}

+ + + + + {{ trans('messages.start-job') }} + +
diff --git a/sourcecode/hub/resources/views/admin/index.blade.php b/sourcecode/hub/resources/views/admin/index.blade.php index 199b550d8..e94eef4ba 100644 --- a/sourcecode/hub/resources/views/admin/index.blade.php +++ b/sourcecode/hub/resources/views/admin/index.blade.php @@ -20,6 +20,12 @@ +
  • + + {{ trans('messages.attach-context-to-contents') }} + +
  • +
  • diff --git a/sourcecode/hub/routes/web.php b/sourcecode/hub/routes/web.php index 9b68935cf..ddc094300 100644 --- a/sourcecode/hub/routes/web.php +++ b/sourcecode/hub/routes/web.php @@ -266,6 +266,13 @@ ->uses([ContextController::class, 'add']) ->name('admin.contexts.add'); + Route::get('/attach-context-to-contents') + ->uses([ContextController::class, 'attachToContents']) + ->name('admin.attach-context-to-contents'); + + Route::post('/attach-context-to-contents') + ->uses([ContextController::class, 'performAttachToContents']); + Route::prefix('/lti-platforms')->group(function () { Route::get('') ->uses([LtiPlatformController::class, 'index']) From 63271658f6f6d74404284504e7490e463c19a614 Mon Sep 17 00:00:00 2001 From: "Emma C. Hughes" <84008144+emmachughes@users.noreply.github.com> Date: Tue, 21 Jan 2025 09:08:14 +0100 Subject: [PATCH 05/12] add confirmation for reindex button (#2919) --- .../Controllers/Admin/AdminController.php | 16 ++++++++++++++-- sourcecode/hub/lang/en/messages.php | 2 ++ .../hub/resources/views/admin/index.blade.php | 19 +++++++++++++------ sourcecode/hub/tests/Browser/AdminTest.php | 8 ++++++++ 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/sourcecode/hub/app/Http/Controllers/Admin/AdminController.php b/sourcecode/hub/app/Http/Controllers/Admin/AdminController.php index 766320b7a..1b9e79680 100644 --- a/sourcecode/hub/app/Http/Controllers/Admin/AdminController.php +++ b/sourcecode/hub/app/Http/Controllers/Admin/AdminController.php @@ -8,10 +8,14 @@ use App\Jobs\RebuildContentIndex; use App\Models\LtiToolExtra; use Illuminate\Contracts\Bus\Dispatcher; -use Illuminate\Http\RedirectResponse; +use Illuminate\Http\Request; use Illuminate\View\View; +use Symfony\Component\HttpFoundation\Response; use function back; +use function response; +use function route; +use function trans; use function view; final class AdminController extends Controller @@ -23,10 +27,18 @@ public function index(): View ]); } - public function rebuildContentIndex(Dispatcher $dispatcher): RedirectResponse + public function rebuildContentIndex(Dispatcher $dispatcher, Request $request): Response { $dispatcher->dispatch(new RebuildContentIndex()); + $request->session() + ->flash('alert', trans('messages.alert-rebuilding-content-index')); + + if ($request->header('HX-Request')) { + return response()->noContent() + ->header('HX-Redirect', route('admin.index')); + } + return back() ->with('alert', trans('messages.alert-rebuilding-content-index')); } diff --git a/sourcecode/hub/lang/en/messages.php b/sourcecode/hub/lang/en/messages.php index cd9d80c27..c08c80c3d 100644 --- a/sourcecode/hub/lang/en/messages.php +++ b/sourcecode/hub/lang/en/messages.php @@ -241,4 +241,6 @@ 'attach-context-to-contents' => 'Attach context to contents', 'attach-context-to-contents-warning' => 'This adds a context to all contents', 'start-job' => 'Start job', + 'danger-zone' => 'Danger zone', + 'confirm-reindex' => 'Reindexing will make content listings unavailable until the process has completed. Are you sure you want to continue?', ]; diff --git a/sourcecode/hub/resources/views/admin/index.blade.php b/sourcecode/hub/resources/views/admin/index.blade.php index e94eef4ba..bfa809ece 100644 --- a/sourcecode/hub/resources/views/admin/index.blade.php +++ b/sourcecode/hub/resources/views/admin/index.blade.php @@ -25,14 +25,21 @@ {{ trans('messages.attach-context-to-contents') }}
  • - -
  • - - - -
  • +

    {{ trans('messages.danger-zone') }}

    + + + + +

    Admin tools