Coder Social home page Coder Social logo

h5p's People

Contributors

artkob avatar davitekpl avatar dicani0 avatar dyfero avatar hareom284 avatar herbertiv avatar krzescola avatar krzysztofdziedziechescolasoft avatar mako321 avatar pa-cholek avatar qunabu avatar tarreislam avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

h5p's Issues

admin content fetch bu author

you should be able to fetch content by authors

each content should save by whom it was created

admin/hh5p/content should have an query param author_id

There should be new permissions as well

  • admin should fetch all content
  • tutors should fetch only his content and edit only his

there should be transaltions for content

scenario

  1. launch demo https://github.com/EscolaLMS/h5p-laravel-demo
  2. change languge to PL
  3. editor and each content should be in polish (this is not reactive change, you might need to refresh browser after change)

This might be good starting point https://github.com/EscolaLMS/H5P/blob/main/src/Services/HeadlessH5PService.php#L383

How this should work

All of this is taken from API

index error

https://api-stage.escolalms.com/api/admin/hh5p/content?pageSize=20&current=1&per_page=20&page=1

message: "SQLSTATE[42702]: Ambiguous column: 7 ERROR:  column reference \"id\" is ambiguous\nLINE 1: ...elect count(*) as aggregate from (select \"title\", \"id\", \"lib...\n                                                             ^ (SQL: select count(*) as aggregate from (select \"title\", \"id\", \"library_id\", COUNT(topic_h5ps.value) as count_h5p from \"hh5p_contents\" left join \"topic_h5ps\" on (\"topic_h5ps\".\"value\" = \"hh5p_contents\".\"id\") group by \"hh5p_contents\".\"id\") as \"aggregate_table\")"

missing implementation of methods in src/Repositories/H5PEditorAjaxRepository.php

see src/Repositories/H5PEditorAjaxRepository.php

there are some methods that have empty implmentation eg

    /**
     * Gets recently used libraries for the current author
     *
     * @return array machine names. The first element in the array is the
     * most recently used.
     */
    public function getAuthorsRecentlyUsedLibraries()
    {
        // TODO implment this
        return [];
    }

    /**
     * Checks if the provided token is valid for this endpoint
     *
     * @param string $token The token that will be validated for.
     *
     * @return bool True if successful validation
     */
    public function validateEditorToken($token)
    {
        // TODO this is better resolved
        return true;
    }

    /**
     * Get translations for a language for a list of libraries
     *
     * @param array $libraries An array of libraries, in the form "<machineName> <majorVersion>.<minorVersion>
     * @param string $language_code
     * @return array
     */
    public function getTranslations($libraries, $language_code)
    {
    }

library endpoint post 500

scenario

  1. create fresh demo eg https://h5p-laravel-demo.herokuapp.com/editor/new
  2. login and install "fill the blanks"
  3. use it to create new content

editor call library endpoint and receives an error

curl 'http://localhost/api/admin/hh5p/content?page=1' \
  -H 'Accept: application/json' \
  -H 'Accept-Language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7' \
  -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIxIiwianRpIjoiZGRkMzMyN2ZkNzRlNmU5NDNkNWQwZmMwYzM0MTVlNDQxNGNlYmMyNDY5MzE2NzAyMDc4NzczMDFlODFkMDg3NzcwYWM0ZjExZmNkODU5NzMiLCJpYXQiOjE2NTg3NTcyODEuODg4NzkyLCJuYmYiOjE2NTg3NTcyODEuODg4NzkzLCJleHAiOjE2NjE0MzU2ODEuODg1OTA0LCJzdWIiOiIzIiwic2NvcGVzIjpbXX0.gfBd_IqK6BAWhupmJCRj_kATuDMHwK5LPmzCBUHE4IG0mMvaKsQPMKZh1lu8MeUUCLQSthBcS-55SpT_NvhzlWMJEwmcRgMykDhESEyGt6j2dnqgk4_tNHOm7t8ie8bnPLVqBY20VZ8BqAvHJVM1iv47NVw1g2B_2vU8_uw1my1J5zXodfqgoJbnSo1lzA60s7M85M7K1fOMONHZpCyG5Xj1bQV4RUb9QyfAXWEX0-8S3ouNNq2EHEdeW1cA5RXWmWaTyCk6YkRIRMdN2E4wugrlLIPFUhF8orWje1qqyfiZoFBN3wJAeztlInN0eJF570AbQnTrQpdIeiyRa3NlYYF4nm7mfW9yZIGGZkQmxYCxwnCP-XCgPonFS2AsAn3TmInJ3Elk1pL9aV83XicEYuK5UtQU98d4WwnF_ZxGOEfcufpUvDHwjt5ulWygwNiA3fLdprpbZJ-TdpUzD09KFKzg93yNMnFf6E8Qrt049W14WWLgqD-olR8XRwtyanINHvPFgAAH912RVXRP3V-HBeIfzLtpglLwuYWD0U7D3xWJ9krkvVk0wljt934mQ2SL2TDRvZ8rwA892eYagXTqliX79HHA5j9R_YYzPCLfYiUaR-94rWZHrxofR3AlJgjKZZZ36jhrpNenFLYk5TJtIm-AJNQ1__h0CzIYuURWqaU' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -H 'Cookie: __clnds=nnvvc412h1; structurizr.hideDiagramEditorIntroduction=true; adminer_key=660639f1065b11d01f7c274f1f992846; adminer_sid=0decc96225e3943497a16b10fb9c2991; adminer_permanent=cGdzcWw%3D-cG9zdGdyZXM%3D-ZGVmYXVsdA%3D%3D-ZGVmYXVsdA%3D%3D%3AvdhEIsqHtPkkyJxp; adminer_settings=; adminer_import=output%3Dtext%26format%3Dsql; XSRF-TOKEN=eyJpdiI6IjZQMFlXNHh0SVdBYUpncGVON296Z1E9PSIsInZhbHVlIjoiRTVVVWZnMW11Nmk0K2hwZ05seDhKMW1SYVpEYWlERUNnWkNLTnpFbDhFYnIxOUlyMlZSUmhTYkRsVGxDMWNIZlN5UEJSckZ2akdIQUR0T01UWVNxMHNzbHhEUnhkTTNXa2JzOFlmbG5mc3dZemhmQlo1RHRUditkdU9Ed1RyVDUiLCJtYWMiOiI3MTAzYjM2OTUzOGE2N2ZiNzI2MjE5N2E3NDg3ZTEyODc2NjMwYmYzY2U4MjU3YzA2YzZhYTk4YTU0MGY2YmYxIiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6InJ1L09wemdTSGsvRXVvU2VCTThLK3c9PSIsInZhbHVlIjoibExuOXR4TFRweHUrWUtRV3gvVHIyWlVzbjBkWkdCSE1WQTVrMnZrYjlkNnluakpmRVRLT3JXYjJGWjhjWU9TZkNCS1NGNUIxSHhFU0R5UlFrSGhaK0FYRkZEalBmRjA3RWswVm1KSVFJdXNHNFF0eVFQREI3WmxER0t0bnR0ekwiLCJtYWMiOiJhZTdhZmZlZjRkNjA1YWUwZTYwOWQ3ZjM5Zjc0MDMzYWZkOTZkNDFkZmFlOTU3ODQ2NWM5ZTdkZTAyNDA2ZDY4IiwidGFnIjoiIn0%3D' \
  -H 'Pragma: no-cache' \
  -H 'Referer: http://localhost/index' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36' \
  -H 'sec-ch-ua: ".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  --compressed
{
    "message": "Attempt to read property \"name\" on null",
    "exception": "ErrorException",
    "file": "/app/vendor/h5p/h5p-editor/h5peditor.class.php",
    "line": 124,
    "trace": [
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php",
            "line": 257,
            "function": "handleError",
            "class": "Illuminate\\Foundation\\Bootstrap\\HandleExceptions",
            "type": "->"
        },
        {
            "file": "/app/vendor/h5p/h5p-editor/h5peditor.class.php",
            "line": 124,
            "function": "Illuminate\\Foundation\\Bootstrap\\{closure}",
            "class": "Illuminate\\Foundation\\Bootstrap\\HandleExceptions",
            "type": "->"
        },
        {
            "file": "/app/vendor/escolalms/headless-h5p/src/Services/HeadlessH5PService.php",
            "line": 182,
            "function": "getLibraries",
            "class": "H5peditor",
            "type": "->"
        },
        {
            "file": "/app/vendor/escolalms/headless-h5p/src/Http/Controllers/LibraryApiController.php",
            "line": 52,
            "function": "getLibraries",
            "class": "EscolaLms\\HeadlessH5P\\Services\\HeadlessH5PService",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Routing/Controller.php",
            "line": 54,
            "function": "libraries",
            "class": "EscolaLms\\HeadlessH5P\\Http\\Controllers\\LibraryApiController",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php",
            "line": 45,
            "function": "callAction",
            "class": "Illuminate\\Routing\\Controller",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Routing/Route.php",
            "line": 261,
            "function": "dispatch",
            "class": "Illuminate\\Routing\\ControllerDispatcher",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Routing/Route.php",
            "line": 204,
            "function": "runController",
            "class": "Illuminate\\Routing\\Route",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 725,
            "function": "run",
            "class": "Illuminate\\Routing\\Route",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 141,
            "function": "Illuminate\\Routing\\{closure}",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 116,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 726,
            "function": "then",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 703,
            "function": "runRouteWithinStack",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 667,
            "function": "runRoute",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
            "line": 656,
            "function": "dispatchToRoute",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
            "line": 167,
            "function": "dispatch",
            "class": "Illuminate\\Routing\\Router",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 141,
            "function": "Illuminate\\Foundation\\Http\\{closure}",
            "class": "Illuminate\\Foundation\\Http\\Kernel",
            "type": "->"
        },
        {
            "file": "/app/vendor/escolalms/core/src/Http/Middleware/SetTimezoneForUserMiddleware.php",
            "line": 26,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 180,
            "function": "handle",
            "class": "EscolaLms\\Core\\Http\\Middleware\\SetTimezoneForUserMiddleware",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php",
            "line": 21,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php",
            "line": 31,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 180,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php",
            "line": 21,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php",
            "line": 40,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 180,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\TrimStrings",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php",
            "line": 27,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 180,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php",
            "line": 86,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 180,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php",
            "line": 62,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 180,
            "function": "handle",
            "class": "Illuminate\\Http\\Middleware\\HandleCors",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php",
            "line": 39,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 180,
            "function": "handle",
            "class": "Illuminate\\Http\\Middleware\\TrustProxies",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
            "line": 116,
            "function": "Illuminate\\Pipeline\\{closure}",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
            "line": 142,
            "function": "then",
            "class": "Illuminate\\Pipeline\\Pipeline",
            "type": "->"
        },
        {
            "file": "/app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
            "line": 111,
            "function": "sendRequestThroughRouter",
            "class": "Illuminate\\Foundation\\Http\\Kernel",
            "type": "->"
        },
        {
            "file": "/app/public/index.php",
            "line": 52,
            "function": "handle",
            "class": "Illuminate\\Foundation\\Http\\Kernel",
            "type": "->"
        }
    ]
}

search elements

index endpoint should allow to search by

  • title
  • used library

Content CRUD- API endpoints

  • symlink for h5p-core & h5p-editor
  • symlink for h5p libs & content
  • content list with pagination
  • adding new content (without uploading)
  • adding new content (with uploading)
  • updating content (without uploading)
  • updating new content (with uploading)
  • deleting content
  • tests for each endpoint

combining js/css

helper that takes array of files, combine them into one and return it

database column `title` is not needed

you might actually leave this in database after investigation yet

  • there should be a special POST attrubute title when you create/edit h5p content - this is already in the processed jason payload - editor requires that every content must have title

the title in the responses/resouces should remain in the response but taken from json in other table
Screenshot 2022-07-25 at 16 54 04

unsecure hub calls

    Route::get('content-type-cache', [LibraryApiController::class, 'contentTypeCache'])->name('hh5p.library.content-type-cache');
    Route::get('content-hub-metadata-cache', [LibraryApiController::class, 'contentHubMetadata'])->name('hh5p.library.content-hub-metadata-cache');

    Route::post('library-install', [LibraryApiController::class, 'libraryInstall'])->name('hh5p.ajax.library-install');
    Route::post('library-upload', [LibraryApiController::class, 'libraryUpload'])->name('hh5p.ajax.library-upload');

those calls are automaticaly called by hub, yet without cookies we should be able to inject any type of security if user has permissions to call those

Scenario

  1. Create fresh demo https://h5p-laravel-demo.herokuapp.com/editor/new
  2. Install any library from the list

It calls in first place content-type-cache `'content-hub-metadata-cache', those might be public as this isn't very insecure yet latter ones

    Route::post('library-install', [LibraryApiController::class, 'libraryInstall'])->name('hh5p.ajax.library-install');
    Route::post('library-upload', [LibraryApiController::class, 'libraryUpload'])->name('hh5p.ajax.library-upload');

definitely should have security validation

change routes for admin

except of /api/hh5p/content/{id} all routes are for admin only so they should should be prefixed /api/admin/*

usage endpoint (how many content is used by the library)

  • there should be a way to add "usage" of the h5p content, this means:
  • if there is any topic assigned to this h5p content then usage incements
  • but it should be agnostic, so this package doens't know if this is course usage or anything
  • so there should be some point of injection in index controller

example

ID Title Used n times
1 Content #1 0
2 Content #2 10
3 Content #3 1
4 Content #4 0

this package should just contain method of adding this query to index endpoint

but the actuall query/method should be added later in courses or topic types

getLatestLibraryVersions should be filtered with versions

src/Repositories/H5PEditorAjaxRepository.php

    // TODO those libraries should be filtered by maximum sem ver 
    /*
    $versions = ['1.0.8', '1.0.9', '1.0.10'];
    usort($versions, 'version_compare');
    */

so if there are two or more same libraries one on the list

        return $libraries_result;

should be one with latest versions $versions = ['1.0.8', '1.0.9', '1.0.10']; -> '1.0.10'

see the wordpress implemenation ๐Ÿ˜ฎ https://github.com/h5p/h5p-wordpress-plugin/blob/d9072b6d1b1f40b5b37e9f57e6248ea6851346d9/admin/class-h5p-editor-wordpress-ajax.php#L10

readme.md update. commands & cors

details in readme.md about

  • running command for symlink
  • and cors on Laravel
  • cors on files (required by some h5p libs)
cd public
ln -sf ../vendor/h5p/h5p-editor/
ln -sf ../vendor/h5p/h5p-core/  
ln -sf ../storage/app/h5p/

Cascade Deleting

  • deleting lib should delete files
  • deleting lib should delete content

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.