Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ name: CI

on: ['push', 'pull_request']

permissions:
contents: read
packages: write

jobs:
tests:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -47,12 +51,13 @@ jobs:
run: vendor/bin/phpunit

docker:
# Only push Docker image for direct pushes to master branch
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
needs: tests
if: github.event_name == 'push' || github.event_name == 'pull_request'
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
Expand Down
137 changes: 119 additions & 18 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,32 +1,39 @@
FROM php:8.1-alpine

RUN apk add --no-cache git jq moreutils
RUN apk add --no-cache $PHPIZE_DEPS postgresql-dev \
&& docker-php-ext-install pdo_pgsql \
# Base tools and PHP extensions
RUN apk add --no-cache git jq moreutils \
&& apk add --no-cache $PHPIZE_DEPS postgresql-dev sqlite-dev \
&& docker-php-ext-install pdo_pgsql pdo_sqlite \
&& pecl install xdebug-3.1.5 \
&& docker-php-ext-enable xdebug \
&& echo "xdebug.mode=debug" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini \
&& echo "xdebug.client_host = 172.19.0.1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini

# Composer + fresh Laravel app
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
RUN composer create-project --prefer-dist laravel/laravel example && \
cd example
RUN composer create-project --prefer-dist laravel/laravel example && cd example

WORKDIR /example

# Link local package
COPY . /laravel-scim-server
RUN jq '.repositories=[{"type": "path","url": "/laravel-scim-server"}]' ./composer.json | sponge ./composer.json

# Install package and dev helpers
RUN composer require arietimmerman/laravel-scim-server @dev && \
composer require laravel/tinker

# SQLite config
RUN touch /example/database.sqlite && \
echo "DB_CONNECTION=sqlite" >> /example/.env && \
echo "DB_DATABASE=/example/database.sqlite" >> /example/.env && \
echo "APP_URL=http://localhost:18123" >> /example/.env

# Make users.password nullable to allow SCIM-created users without passwords
RUN sed -i -E "s/\\$table->string\('password'\);/\\$table->string('password')->nullable();/g" \
database/migrations/*create_users_table.php || true

# Add migration for groups table using heredoc
# Groups table migration
RUN cat > /example/database/migrations/2021_01_01_000001_create_groups_table.php <<'EOM'
<?php

Expand All @@ -51,44 +58,49 @@ return new class extends Migration {
};
EOM

# Add Group model
# Group model with members() relation
RUN cat > app/Models/Group.php <<'EOM'
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use App\Models\User;

class Group extends Model
{
use HasFactory;

protected $fillable = ['displayName'];

public function members(): BelongsToMany
{
return $this->belongsToMany(User::class, 'group_user', 'group_id', 'user_id')->withTimestamps();
}
}
EOM

# Add Custom SCIM Config overriding Group model class
# Override SCIM config to use app's Group model
RUN mkdir -p app/SCIM && cat > app/SCIM/CustomSCIMConfig.php <<'EOM'
<?php

namespace App\SCIM;

use ArieTimmerman\Laravel\SCIMServer\SCIMConfig as BaseSCIMConfig;
use App\Models\Group;

class CustomSCIMConfig extends BaseSCIMConfig
{
public function getGroupConfig()
public function getGroupClass()
{
$config = parent::getGroupConfig();
// Force the group model to the example app's Group model
$config['class'] = \App\Models\Group::class;
return $config;
return Group::class;
}
}
EOM

# Override AppServiceProvider to register custom SCIMConfig binding
# Bind CustomSCIMConfig in the container
RUN cat > app/Providers/AppServiceProvider.php <<'EOM'
<?php

Expand All @@ -107,12 +119,12 @@ class AppServiceProvider extends ServiceProvider

public function boot(): void
{
// Additional boot logic if needed
//
}
}
EOM

# Add Group factory
# Group factory
RUN cat > database/factories/GroupFactory.php <<'EOM'
<?php

Expand All @@ -134,8 +146,97 @@ class GroupFactory extends Factory
}
EOM

# Pivot table for memberships
RUN cat > /example/database/migrations/2021_01_01_000002_create_group_user_table.php <<'EOM'
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
public function up(): void
{
Schema::create('group_user', function (Blueprint $table) {
$table->id();
$table->foreignId('group_id')->constrained('groups')->cascadeOnDelete();
$table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
$table->timestamps();
$table->unique(['group_id', 'user_id']);
});
}

public function down(): void
{
Schema::dropIfExists('group_user');
}
};
EOM

# Ensure User model has groups() relation (overwrite default)
RUN cat > app/Models/User.php <<'EOM'
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;

protected $fillable = [
'name',
'email',
'password',
];

protected $hidden = [
'password',
'remember_token',
];

protected $casts = [
'email_verified_at' => 'datetime',
];

public function groups(): BelongsToMany
{
return $this->belongsToMany(Group::class, 'group_user', 'user_id', 'group_id')->withTimestamps();
}
}
EOM

# Seeder for demo data
RUN cat > /example/database/seeders/DemoSeeder.php <<'EOM'
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\User;
use App\Models\Group;

class DemoSeeder extends Seeder
{
public function run(): void
{
$users = User::factory()->count(50)->create();
$groups = Group::factory()->count(10)->create();

foreach ($groups as $g) {
$g->members()->sync($users->random(rand(3, 10))->pluck('id')->toArray());
}
}
}
EOM

# Run migrations and seed demo data
RUN php artisan migrate && \
echo "User::factory()->count(100)->create(); App\\Models\\Group::factory()->count(10)->create();" | php artisan tinker
RUN php artisan migrate && php artisan db:seed --class=Database\\Seeders\\DemoSeeder

CMD ["php","artisan","serve","--host=0.0.0.0","--port=8000"]

Loading