diff --git a/.env.example b/.env.example index 33c168e8..4794f6e4 100644 --- a/.env.example +++ b/.env.example @@ -48,3 +48,9 @@ PUSHER_APP_CLUSTER=mt1 MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" + +AUTH_ROLES_ENABLE=false +AUTH_ROLES_HEADER="remote-groups" +AUTH_ROLES_HTTP_HEADER="HTTP_REMOTE_GROUPS" +AUTH_ROLES_ADMIN="admin" +AUTH_ROLES_DELIMITER="," diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..cda0ab9b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Listen for Xdebug", + "type": "php", + "request": "launch", + "port": 9003, + "pathMappings": { + "/var/www/html": "${workspaceFolder}" + } + } + ] + } + \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..32c9abbf --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,16 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Start Docker Compose", + "type": "shell", + "command": "docker-compose up --build", + "group": { + "kind": "build", + "isDefault": true + }, + "problemMatcher": [] + } + ] + } + \ No newline at end of file diff --git a/app/Http/Controllers/ItemController.php b/app/Http/Controllers/ItemController.php index 07521b31..8a2063c6 100644 --- a/app/Http/Controllers/ItemController.php +++ b/app/Http/Controllers/ItemController.php @@ -33,34 +33,59 @@ class ItemController extends Controller /** * Display a listing of the resource on the dashboard. */ - public function dash(): View + public function dash(Request $request): View { $treat_tags_as = \App\Setting::fetch('treat_tags_as'); $data["treat_tags_as"] = $treat_tags_as; - if ($treat_tags_as == 'categories') { - $data['categories'] = Item::whereHas('children')->with('children', function ($query) { - $query->pinned()->orderBy('order', 'asc'); - })->pinned()->orderBy('order', 'asc')->get(); + if (config('app.auth_roles_enable')) { + $roles = explode(config('app.auth_roles_delimiter'), $request->header(config('app.auth_roles_header'))); + if ($treat_tags_as == 'categories') { + $data['categories'] = Item::whereHas('children')->with('children', function ($query) { + $query->pinned()->orderBy('order', 'asc'); + })->pinned()->orderBy('order', 'asc')->get(); - } elseif ($treat_tags_as == 'tags') { - $data['apps'] = Item::with('parents')->where('type', 0)->pinned()->orderBy('order', 'asc')->get(); - $data['all_apps'] = Item::where('type', 0)->orderBy('order', 'asc')->get(); - $data['taglist'] = Item::where('id', 0)->orWhere(function($query) { - $query->where('type', 1)->pinned(); - })->orderBy('order', 'asc')->get(); + } elseif ($treat_tags_as == 'tags') { + $data['apps'] = Item::with('parents')->where('type', 0)->pinned()->orderBy('order', 'asc')->get(); + $data['all_apps'] = Item::where('type', 0)->orderBy('order', 'asc')->get(); + $data['taglist'] = Item::where('id', 0)->orWhere(function($query) { + $query->where('type', 1)->pinned(); + })->orderBy('order', 'asc')->get(); + } else { + + $data['apps'] = Item::whereHas('parents', function ($query) { + $query->where('id', 0); + })->whereIn('role', $roles)->orWhere('type', 1)->pinned()->orderBy('order', 'asc')->get(); + + $data['all_apps'] = Item::whereHas('parents', function ($query) { + $query->where('id', 0); + })->orWhere('type', 1)->orderBy('order', 'asc')->get(); + } } else { + if ($treat_tags_as == 'categories') { + $data['categories'] = Item::whereHas('children')->with('children', function ($query) { + $query->pinned()->orderBy('order', 'asc'); + })->pinned()->orderBy('order', 'asc')->get(); - $data['apps'] = Item::whereHas('parents', function ($query) { - $query->where('id', 0); - })->orWhere('type', 1)->pinned()->orderBy('order', 'asc')->get(); + } elseif ($treat_tags_as == 'tags') { + $data['apps'] = Item::with('parents')->where('type', 0)->pinned()->orderBy('order', 'asc')->get(); + $data['all_apps'] = Item::where('type', 0)->orderBy('order', 'asc')->get(); + $data['taglist'] = Item::where('id', 0)->orWhere(function($query) { + $query->where('type', 1)->pinned(); + })->orderBy('order', 'asc')->get(); + } else { - $data['all_apps'] = Item::whereHas('parents', function ($query) { - $query->where('id', 0); - })->orWhere(function ($query) { - $query->where('type', 1)->whereNot('id', 0); - })->orderBy('order', 'asc')->get(); + $data['apps'] = Item::whereHas('parents', function ($query) { + $query->where('id', 0); + })->orWhere('type', 1)->pinned()->orderBy('order', 'asc')->get(); + + $data['all_apps'] = Item::whereHas('parents', function ($query) { + $query->where('id', 0); + })->orWhere(function ($query) { + $query->where('type', 1)->whereNot('id', 0); + })->orderBy('order', 'asc')->get(); + } } //$data['all_apps'] = Item::doesntHave('parents')->get(); diff --git a/app/Http/Controllers/TagController.php b/app/Http/Controllers/TagController.php index 79f7ad6e..0a8fec52 100644 --- a/app/Http/Controllers/TagController.php +++ b/app/Http/Controllers/TagController.php @@ -88,11 +88,16 @@ class TagController extends Controller * * @param $slug */ - public function show($slug): View + public function show($slug, Request $request): View { $item = Item::whereUrl($slug)->first(); //print_r($item); - $data['apps'] = $item->children()->pinned()->orderBy('order', 'asc')->get(); + if (config('app.auth_roles_enable')) { + $roles = explode(config('app.auth_roles_delimiter'), $request->header(config('app.auth_roles_header'))); + $data['apps'] = $item->children()->whereIn('role', $roles)->pinned()->orderBy('order', 'asc')->get(); + } else { + $data['apps'] = $item->children()->pinned()->orderBy('order', 'asc')->get(); + } $data['tag'] = $item->id; $data['all_apps'] = $item->children; diff --git a/app/Item.php b/app/Item.php index b0e83b4f..719e50e7 100644 --- a/app/Item.php +++ b/app/Item.php @@ -33,6 +33,7 @@ use Symfony\Component\ClassLoader\ClassMapGenerator; * @property string|null $class * @property string|null $appid * @property string|null $appdescription + * @property string|null $role * @property-read \Illuminate\Database\Eloquent\Collection|Item[] $children * @property-read int|null $children_count * @property-read string $droppable @@ -51,6 +52,7 @@ use Symfony\Component\ClassLoader\ClassMapGenerator; * @method static Builder|Item pinned() * @method static Builder|Item query() * @method static Builder|Item whereAppdescription($value) + * @method static Builder|Item whereRole($value) * @method static Builder|Item whereAppid($value) * @method static Builder|Item whereClass($value) * @method static Builder|Item whereColour($value) @@ -105,6 +107,7 @@ class Item extends Model 'user_id', 'tag_id', 'appid', + 'role', ]; diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 5f9748aa..c44c21bb 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -88,6 +88,11 @@ class AppServiceProvider extends ServiceProvider $view->with('trianglify_seed', $trianglify_seed); $view->with('allusers', $allusers); $view->with('current_user', $current_user); + if (config('app.auth_roles_enable')){ + $view->with('enable_auth_admin_controls', in_array(config('app.auth_roles_admin'),explode(config('app.auth_roles_delimiter'), $_SERVER[config('app.auth_roles_http_header')]))); + } else { + $view->with('enable_auth_admin_controls', true); + } }); $this->app['view']->addNamespace('SupportedApps', app_path('SupportedApps')); diff --git a/config/app.php b/config/app.php index aff138a5..50ad8888 100644 --- a/config/app.php +++ b/config/app.php @@ -192,4 +192,10 @@ return [ 'Yaml' => Symfony\Component\Yaml\Yaml::class, ])->toArray(), + 'auth_roles_enable' => (bool) env('AUTH_ROLES_ENABLE', false), + 'auth_roles_header' => env('AUTH_ROLES_HEADER', 'remote-groups'), + 'auth_roles_http_header' => env('AUTH_ROLES_HTTP_HEADER', 'HTTP_REMOTE_GROUPS'), + 'auth_roles_admin' => env('AUTH_ROLES_ADMIN', 'admin'), + 'auth_roles_delimiter' => env('AUTH_ROLES_DELIMITER', ','), + ]; diff --git a/database/migrations/2023_01_27_121000_add_role_to_item.php b/database/migrations/2023_01_27_121000_add_role_to_item.php new file mode 100644 index 00000000..1ab8d44f --- /dev/null +++ b/database/migrations/2023_01_27_121000_add_role_to_item.php @@ -0,0 +1,32 @@ +text('role')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('items', function (Blueprint $table) { + // + }); + } +} diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 00000000..ff36b6ae --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,26 @@ +version: "3" +services: + nginx: + build: + context: . + dockerfile: nginx/Dockerfile + ports: + - "8080:80" + networks: + - internal + volumes: + - ../:/var/www/html + php: + build: + context: . + dockerfile: php/Dockerfile + networks: + - internal + environment: + XDEBUG_MODE: debug + XDEBUG_CONFIG: client_host=host.docker.internal client_port=9003 + volumes: + - ../:/var/www/html +networks: + internal: + driver: bridge \ No newline at end of file diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile new file mode 100644 index 00000000..a980286d --- /dev/null +++ b/docker/nginx/Dockerfile @@ -0,0 +1,2 @@ +FROM nginx:alpine +COPY ./default.conf /etc/nginx/conf.d \ No newline at end of file diff --git a/docker/nginx/default.conf b/docker/nginx/default.conf new file mode 100644 index 00000000..5279a273 --- /dev/null +++ b/docker/nginx/default.conf @@ -0,0 +1,19 @@ +server { + listen 0.0.0.0:80; + + root /var/www/html; + + location / { + index index.php index.html; + } + + location ~ \.php$ { + include fastcgi_params; + fastcgi_pass php:9000; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; + } + + error_log /var/log/nginx/error.log; + access_log /var/log/nginx/access.log; +} \ No newline at end of file diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile new file mode 100644 index 00000000..ef9f5785 --- /dev/null +++ b/docker/php/Dockerfile @@ -0,0 +1,4 @@ +FROM php:8.4-fpm + +RUN pecl install xdebug \ + && docker-php-ext-enable xdebug diff --git a/lang/de/app.php b/lang/de/app.php index c97d9874..675ba946 100644 --- a/lang/de/app.php +++ b/lang/de/app.php @@ -105,4 +105,7 @@ return array ( 'alert.success.user_restored' => 'Nutzer erfolgreich wiederhergestellt', 'dashboard.reorder' => 'Elemente neu anordnen und anheften', 'dashboard.settings' => 'Einstellungen', + 'role' => 'Authentifizierungsrolle', + 'unauthorized_for_form' => 'Sie haben keinen Zugriff auf diese Seite.', + 'disabled_feature' => 'Diese Funktion ist deaktiviert.', ); \ No newline at end of file diff --git a/lang/en/app.php b/lang/en/app.php index bfd97649..3c31f53d 100644 --- a/lang/en/app.php +++ b/lang/en/app.php @@ -114,4 +114,7 @@ return array ( 'alert.success.user_restored' => 'User restored successfully', 'dashboard.reorder' => 'Reorder and pin items', 'dashboard.settings' => 'Settings', + 'role' => 'Authentication role', + 'unauthorized_for_form' => 'You are not authorized to view this form.', + 'disabled_feature' => 'This feature is disabled.', ); \ No newline at end of file diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index b6a4d065..00055c70 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -1,6 +1,8 @@ @extends('layouts.app') + @section('content') +@if(!$app['config']->get('app.auth_roles_enable', false)) @@ -21,5 +23,14 @@ $user = \App\User::currentUser(); +@else +
+
+
+ {{ __('app.disabled_feature') }} +
+
+
+@endif @endsection diff --git a/resources/views/items/form.blade.php b/resources/views/items/form.blade.php index 8d24a7f1..95265b8c 100644 --- a/resources/views/items/form.blade.php +++ b/resources/views/items/form.blade.php @@ -1,4 +1,5 @@ -
+
+ @if($enable_auth_admin_controls)
{{ __('app.apps.preview') }}
@@ -76,6 +77,13 @@ {!! Form::select('tags[]', $tags, $current_tags, ['class' => 'tags', 'multiple']) !!}
+ @if($app['config']->get('app.auth_roles_enable', false)) +
+ + {!! Form::text('role', $item->role ?? null, array('placeholder' => __('app.role'), 'id' => 'role', 'class' => 'form-control')) !!} +
+ @endif +
@@ -137,6 +145,13 @@ {{ __('app.buttons.cancel') }}
+ @else +
+
+ {{ __('app.unauthorized_for_form') }} +
+
+ @endif
diff --git a/resources/views/items/import.blade.php b/resources/views/items/import.blade.php index 5e30d2c8..f0d4e66e 100644 --- a/resources/views/items/import.blade.php +++ b/resources/views/items/import.blade.php @@ -3,6 +3,7 @@ @section('content')
+ @if($enable_auth_admin_controls)
{{ __('app.import') }}
@@ -31,6 +32,13 @@ {{ __('app.buttons.cancel') }}
+ @else +
+
+ {{ __('app.unauthorized_for_form') }} +
+
+ @endif
diff --git a/resources/views/items/list.blade.php b/resources/views/items/list.blade.php index db7a11a8..162d981a 100644 --- a/resources/views/items/list.blade.php +++ b/resources/views/items/list.blade.php @@ -2,6 +2,7 @@ @section('content')
+ @if($enable_auth_admin_controls)
{{ __('app.apps.app_list') }} @@ -53,6 +54,13 @@ + @else +
+
+ {{ __('app.unauthorized_for_form') }} +
+
+ @endif
diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 4544748a..3ad98899 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -82,7 +82,7 @@ @endif - @if($allusers->count() > 1) + @if(!($allusers->count() <= 1 || config('app.auth_roles_enable')))
@if($current_user->avatar) @@ -94,22 +94,22 @@
@endif @yield('content') + @if($enable_auth_admin_controls)
- - @if(Route::is('dash') || Route::is('tags.show'))
{{ __('app.dashboard.reorder') }}
@endif
{{ __('app.dashboard') }}
- @if($current_user->id === 1) + @if($current_user->id === 1 && !config('app.auth_roles_enable'))
{{ __('app.user.user_list') }}
@endif
{{ __('app.apps.app_list') }}
{{ __('app.apps.tag_list') }}
{{ __('app.dashboard.settings') }}
+ @endif diff --git a/resources/views/settings/form.blade.php b/resources/views/settings/form.blade.php index 1ffacce1..f3739e84 100644 --- a/resources/views/settings/form.blade.php +++ b/resources/views/settings/form.blade.php @@ -1,4 +1,5 @@
+@if($enable_auth_admin_controls)
{{ __($setting->label) }}
@@ -26,5 +27,12 @@ {{ __('app.buttons.cancel') }}
+ @else +
+
+ {{ __('app.unauthorized_for_form') }} +
+
+ @endif -
+
diff --git a/resources/views/settings/list.blade.php b/resources/views/settings/list.blade.php index 923b65a5..e47bf69c 100644 --- a/resources/views/settings/list.blade.php +++ b/resources/views/settings/list.blade.php @@ -2,6 +2,7 @@ @section('content') + @if($enable_auth_admin_controls) @foreach ($groups as $index => $group)
@@ -57,5 +58,14 @@
@endforeach + @else +
+
+
+ {{ __('app.unauthorized_for_form') }} +
+
+
+ @endif @endsection diff --git a/resources/views/tags/form.blade.php b/resources/views/tags/form.blade.php index 634632d0..b6f7fa5e 100644 --- a/resources/views/tags/form.blade.php +++ b/resources/views/tags/form.blade.php @@ -1,4 +1,5 @@ -
+
+ @if($enable_auth_admin_controls)
{{ __('app.apps.add_tag') }}
@@ -30,6 +31,13 @@ {!! Form::text('colour', null, array('placeholder' => __('app.apps.hex'),'class' => 'form-control color-picker')) !!}
+ @if($app['config']->get('app.auth_roles_enable', false)) +
+ + {!! Form::text('role', $item->role ?? null, array('placeholder' => __('app.role'), 'id' => 'role', 'class' => 'form-control')) !!} +
+
+ @endif
@@ -51,6 +59,19 @@
+
+ + {!! Form::hidden('pinned', '0') !!} + +
@@ -62,7 +83,11 @@ {{ __('app.buttons.cancel') }} - + @else +
+
+ {{ __('app.unauthorized_for_form') }} +
+
+ @endif
- - diff --git a/resources/views/tags/list.blade.php b/resources/views/tags/list.blade.php index 7b1c8e1f..3f6ad23b 100644 --- a/resources/views/tags/list.blade.php +++ b/resources/views/tags/list.blade.php @@ -2,6 +2,7 @@ @section('content')
+ @if($enable_auth_admin_controls)
{{ __('app.apps.tag_list') }} @@ -50,7 +51,12 @@ + @else +
+
+ {{ __('app.unauthorized_for_form') }} +
+
+ @endif
- - @endsection diff --git a/resources/views/users/form.blade.php b/resources/views/users/form.blade.php index 45f3f866..afcb4f73 100644 --- a/resources/views/users/form.blade.php +++ b/resources/views/users/form.blade.php @@ -1,4 +1,5 @@
+ @if($enable_auth_admin_controls)
{{ __('app.user.add_user') }}
@@ -91,7 +92,11 @@ {{ __('app.buttons.cancel') }}
- + @else +
+
+ {{ __('app.unauthorized_for_form') }} +
+
+ @endif
- - diff --git a/resources/views/users/index.blade.php b/resources/views/users/index.blade.php index ce4887f2..3c0d1ad4 100644 --- a/resources/views/users/index.blade.php +++ b/resources/views/users/index.blade.php @@ -2,6 +2,7 @@ @section('content')
+ @if($enable_auth_admin_controls)
{{ __('app.user.user_list') }} @@ -60,7 +61,12 @@ + @else +
+
+ {{ __('app.unauthorized_for_form') }} +
+
+ @endif
- - @endsection \ No newline at end of file diff --git a/resources/views/userselect.blade.php b/resources/views/userselect.blade.php index 97f67db8..02eca822 100644 --- a/resources/views/userselect.blade.php +++ b/resources/views/userselect.blade.php @@ -1,7 +1,7 @@ @extends('layouts.users') @section('content') - +@if(!$app['config']->get('app.auth_roles_enable', false))
@foreach($users as $user) @@ -14,5 +14,14 @@ @endforeach
+@else +
+
+
+ {{ __('app.disabled_feature') }} +
+
+
+@endif @endsection \ No newline at end of file diff --git a/xdebug.ini b/xdebug.ini new file mode 100644 index 00000000..9a38d306 --- /dev/null +++ b/xdebug.ini @@ -0,0 +1,5 @@ +zend_extension=xdebug.so +xdebug.mode=debug +xdebug.start_with_request=yes +xdebug.client_host=host.docker.internal +xdebug.client_port=9003