Skip to main content

Command Palette

Search for a command to run...

Magatunga - 3 — The Block System and Role Expansion

Updated
3 min read

After the Admin foundation was in place, we shifted focus to deepening the learning-content layer and expanding access control for teachers.
This phase was about moving from a course skeleton to real, editable building blocks — and ensuring the platform’s permission system could scale beyond the admin role.


The Challenge

With the Course → Module → Lesson hierarchy functional, we needed to make the “Block” concept more robust and accessible.
Until now, blocks existed only as UI placeholders; the goal was to connect them to the backend, allow full CRUD operations, and prepare the way for teachers to author their own course material safely.


What We Did

🧱 Implemented a Fully-Functional Block System

  • Located and completed the BlockController, Block model, and related lesson/module logic.

  • Confirmed and stabilized six block types:
    text, image, audio, video, quiz, and download.

  • Each block stores its data in a JSON field (data) for maximum flexibility and easy future extension.

  • Enabled file uploads (images, audio, video, downloads) under /storage/uploads/{type} with automatic path injection into the JSON payload.

  • Added the missing video type to the controller’s creation allow-list so video blocks can now be created directly.

⚙️ Data Alignment & Refactor

  • Standardized the Block model’s $fillable and $casts:

      protected $fillable = ['lesson_id','type','position','is_active','data'];
      protected $casts = ['data'=>'array','is_active'=>'boolean','position'=>'integer'];
    
  • Removed legacy content references to prevent mass-assignment conflicts.

🧑‍🏫 Opened Builder Access for Teachers

  • Extended route definitions to allow teachers with the courses.author permission to use the builder:

      Route::middleware(['auth','role:teacher','permission:courses.author'])
          ->prefix('teacher')->as('teacher.')->group(function () {
              Route::post('/lessons/{lesson}/blocks', [AdminBlock::class, 'store'])->name('blocks.store');
              Route::put('/blocks/{block}', [AdminBlock::class, 'update'])->name('blocks.update');
              Route::patch('/blocks/{block}/toggle', [AdminBlock::class, 'toggle'])->name('blocks.toggle');
              Route::patch('/blocks/{block}/move', [AdminBlock::class, 'move'])->name('blocks.move');
              Route::patch('/blocks/{block}/reorder', [AdminBlock::class, 'reorder'])->name('blocks.reorder');
              Route::delete('/blocks/{block}', [AdminBlock::class, 'destroy'])->name('blocks.destroy');
          });
    

    Teachers without this permission are automatically blocked with a 403 response.

🔐 Verified Role & Permission Seeder

  • Reviewed the active PermissionsSeeder (called from DatabaseSeeder):

    • Creates roles: admin, teacher, student.

    • Creates permissions: courses.author, courses.publish, plus all admin navigation permissions.

    • Assigns courses.author to teachers, courses.publish + nav perms to admin.

  • Optional improvement added: also give courses.author to admin for full builder access.

🧰 Migration & Seeding Cleanup

  • Ran a complete migrate:fresh --seed to reset dev environment.

  • Fixed Database\Factories\fake() namespace error by switching factories to $this->faker->... syntax and adding $faker = app(\Faker\Generator::class) to seeders.

  • Verified clean seeding with proper demo roles and users.


Result

The Magatunga backend now fully supports modular content creation.
Admins and authorized teachers can build complete course structures, upload media, and manage interactive quizzes — all within the web interface.
Role-based access ensures content authorship remains organized and secure.

The development environment has been reset and reseeded successfully, clearing the path for staging deployment and functional testing of the teacher workflow.

More from this blog

F

FNHP Dev Diaries

9 posts