Magatunga - 3 — The Block System and Role Expansion
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,Blockmodel, and related lesson/module logic.Confirmed and stabilized six block types:
text,image,audio,video,quiz, anddownload.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
videotype to the controller’s creation allow-list so video blocks can now be created directly.
⚙️ Data Alignment & Refactor
Standardized the
Blockmodel’s$fillableand$casts:protected $fillable = ['lesson_id','type','position','is_active','data']; protected $casts = ['data'=>'array','is_active'=>'boolean','position'=>'integer'];Removed legacy
contentreferences to prevent mass-assignment conflicts.
🧑🏫 Opened Builder Access for Teachers
Extended route definitions to allow teachers with the
courses.authorpermission 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 fromDatabaseSeeder):Creates roles:
admin,teacher,student.Creates permissions:
courses.author,courses.publish, plus all admin navigation permissions.Assigns
courses.authorto teachers,courses.publish+ nav perms to admin.
Optional improvement added: also give
courses.authorto admin for full builder access.
🧰 Migration & Seeding Cleanup
Ran a complete
migrate:fresh --seedto 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.