Skip to main content

Overview

The User model extends Laravel’s Authenticatable class and manages user authentication, authorization, and relationships with assignments, submissions, and classes.

Traits

use Notifiable;
  • Notifiable: Enables email and notification features

Fillable Fields

username
string
required
Unique username for loginUsed throughout the system for identification and file paths
email
string
required
User’s email address
password
string
required
Hashed password for authenticationHidden: Not included in JSON serialization
display_name
string
User’s full name for display purposes
role_id
integer
required
Foreign key to the roles tableDetermines user permissions and access levels
trial_time
integer
Trial period duration in hours for new student accountsAfter trial expires, students are automatically downgraded to guest role

Hidden Fields

protected $hidden = [
    'password',
    'remember_token',
];
These fields are excluded from array/JSON serialization for security.

Casts

protected $casts = [
    'email_verified_at' => 'datetime',
    'first_login_time' => 'datetime:Y-m-d\TH:i:sP',
    'last_login_time' => 'datetime:Y-m-d\TH:i:sP',
];

Additional Columns

While not in $fillable, these columns exist in the users table:
  • email_verified_at (datetime) - When email was verified
  • first_login_time (datetime) - First time user logged in
  • last_login_time (datetime) - Most recent login time
  • remember_token (string) - For “remember me” functionality
  • selected_assignment_id (integer) - Currently selected assignment in UI
  • created_at (timestamp) - Account creation time
  • updated_at (timestamp) - Last update time

Relationships

role()

role
BelongsTo<Role>
The user’s role determining permissionsCommon roles:
  • admin - Full system access
  • head_instructor - Can manage assignments and classes
  • instructor - Can create problems and view student work
  • student - Can submit to assigned problems
  • guest - Read-only access, cannot submit
$user->role // Returns Role model
$user->role->name // Returns: 'student', 'admin', etc.

submissions()

submissions
HasMany<Submission>
All submissions made by this user
$user->submissions // Returns collection of Submission models

problems()

problems
HasMany<Problem>
Problems created/owned by this userOnly applicable for instructors and admins
$user->problems // Returns collection of Problem models

lops()

lops
BelongsToMany<Lop>
Classes (“lops”) this user belongs to
  • Students: Classes they’re enrolled in
  • Instructors: Classes they teach
$user->lops // Returns collection of Lop (class) models

selected_assignment()

selected_assignment
BelongsTo<Assignment>
The assignment currently selected in the user’s UIUsed to persist user’s current context across page loads
$user->selected_assignment // Returns Assignment model or null

Role Hierarchy

Roles are hierarchical with different permission levels:

Admin (role_id: 1)

  • Full access to all features
  • Can edit any assignment, problem, or user
  • Can submit to any problem (including practice)
  • Bypasses all permission checks

Head Instructor (role_id: 2)

  • Can create and manage assignments
  • Can manage their own classes (lops)
  • Can edit assignments they created or that belong to their classes
  • Can view all student submissions in their classes
  • Can use sharable problems from other instructors

Instructor (role_id: 3)

  • Can create problems
  • Can view student work
  • Can use sharable problems
  • Limited assignment management

Student (role_id: 4)

  • Can submit to assigned problems
  • Can practice on problems with allow_practice = true
  • Can view their own submissions
  • Subject to assignment time limits and permissions

Guest (role_id: 5)

  • Read-only access
  • Cannot make submissions
  • Students are auto-downgraded to guest after trial period expires

Trial Account System

From Assignment.php:712, the trial system works as follows:
if ($user->trial_time && 
    in_array($user->role->name, ['student']) &&
    $user->created_at->addHours($user->trial_time) <= Carbon::now()
) {
    $user->role_id = 5; // Downgrade to guest
    $user->save();
}
How it works:
  1. When creating a student account, set trial_time (in hours)
  2. On submission attempt, system checks if trial expired
  3. If created_at + trial_time <= now, auto-downgrade to guest
  4. Guest users cannot submit
Example:
// Create student with 72-hour trial
$user = User::create([
    'username' => 'trial_user',
    'email' => '[email protected]',
    'password' => Hash::make('password'),
    'role_id' => 4, // student
    'trial_time' => 72, // 3 days
]);

// After 3 days, user is automatically downgraded to guest on next submission

Permission Helpers

While not defined in the model, these permission patterns are used throughout the codebase:

Check if user can edit assignment

$error = $assignment->cannot_edit($user);
if ($error !== false) {
    abort(403, $error);
}

Check if user can submit

$result = $assignment->can_submit($user, $problem);
if (!$result->can_submit) {
    return response()->json(['error' => $result->error_message], 403);
}

Check if user can practice problem

if (!$problem->can_practice($user)) {
    abort(403, 'Practice not allowed');
}

Check if user can edit problem

if (!$problem->can_edit($user)) {
    abort(403, 'You cannot edit this problem');
}

Example Usage

// Create a new user
$user = User::create([
    'username' => 'john_doe',
    'email' => '[email protected]',
    'password' => Hash::make('secret'),
    'display_name' => 'John Doe',
    'role_id' => 4, // student
    'trial_time' => 168, // 1 week trial
]);

// Assign to classes
$user->lops()->attach([1, 2, 3]);

// Get user's submissions
$submissions = $user->submissions()
    ->where('assignment_id', 5)
    ->with('problem')
    ->get();

// Check permissions
if ($user->role->name === 'admin') {
    // Admin-only action
}

if (in_array($user->role->name, ['admin', 'head_instructor'])) {
    // Instructor-level action
}

// Get user's created problems (for instructors)
$myProblems = $user->problems()
    ->where('sharable', true)
    ->get();

// Update last login
$user->update([
    'last_login_time' => now(),
]);

if (!$user->first_login_time) {
    $user->update(['first_login_time' => now()]);
}

// Set selected assignment
$user->update(['selected_assignment_id' => $assignmentId]);
$currentAssignment = $user->selected_assignment;

Authentication

The User model extends Authenticatable and works with Laravel’s authentication system:
// Login
if (Auth::attempt(['username' => $username, 'password' => $password])) {
    // Authentication passed
    $user = Auth::user();
}

// Get current user
$user = Auth::user();
$username = Auth::user()->username;

// Logout
Auth::logout();

// Check authentication
if (Auth::check()) {
    // User is authenticated
}

Security Notes

  1. Password Hashing: Always use Hash::make() when setting passwords
  2. Hidden Fields: password and remember_token are automatically hidden from JSON
  3. Role Validation: Always check $user->role->name before allowing privileged actions
  4. Trial Expiration: System auto-enforces trial expiration on submission attempts

Filesystem Integration

Usernames are used in filesystem paths:
# Submission directory
/var/www/assignments/assignment_5/problem_10/{username}/

# Example
/var/www/assignments/assignment_5/problem_10/john_doe/
  ├── solution_123.cpp
  ├── result-123.html
  └── compile-123.txt
Usernames should not contain special characters or spaces to avoid filesystem issues.

Build docs developers (and LLMs) love