Commit 8ccce137 authored by Dominik Hebeler's avatar Dominik Hebeler
Browse files

Merge branch '1233-replace-basic-auth-with-openid-connect' into 'development'

Resolve "Replace Basic Auth with Openid Connect"

Closes #1233

See merge request !2021
parents 60cb14d3 57d0b9e8
......@@ -14,7 +14,6 @@ kubectl -n $KUBE_NAMESPACE create secret generic ${HELM_RELEASE_NAME} \
--from-file=${BLACKLIST_DESCRIPTION_URL} \
--from-file=${BLACKLIST_DOMAINS} \
--from-file=${BLACKLIST_URL} \
--from-file=${USERSEEDER} \
--dry-run=client \
--save-config \
-o yaml | \
......
......@@ -75,9 +75,6 @@ spec:
- name: secrets
mountPath: /metager/metager_app/config/blacklistDescriptionUrl.txt
subPath: BLACKLIST_DESCRIPTION_URL
- name: secrets
mountPath: /metager/metager_app/database/seeds/UsersSeeder.php
subPath: USERSEEDER
- name: mglogs-persistent-storage
mountPath: /metager/metager_app/storage/logs/metager
readOnly: false
......
......@@ -17,8 +17,6 @@ class AdminInterface extends Controller
public function count(Request $request)
{
if ($request->input('out', 'web') === "web") {
$days = $request->input("days", 28);
$interface = $request->input('interface', 'all');
......@@ -255,4 +253,4 @@ class AdminInterface extends Controller
}
return null;
}
}
}
\ No newline at end of file
......@@ -15,14 +15,14 @@ class Kernel extends HttpKernel
* @var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\LocalizationRedirect::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\LocalizationRedirect::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
......@@ -32,26 +32,29 @@ class Kernel extends HttpKernel
*/
protected $middlewareGroups = [
'web' => [
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'humanverification_routes' => [
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
],
'api' => [
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'enableCookies' => [
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
],
'session' => [
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
......@@ -80,4 +83,4 @@ class Kernel extends HttpKernel
'removekey' => \App\Http\Middleware\RemoveKey::class,
'allow-local-only' => AllowLocalOnly::class,
];
}
}
\ No newline at end of file
......@@ -19,7 +19,8 @@
"mews/captcha": "^3.2.7",
"promphp/prometheus_client_php": "^2.6.0",
"symfony/dom-crawler": "^6.0",
"tio/laravel": "^1.20"
"tio/laravel": "^1.20",
"vizir/laravel-keycloak-web-guard": "^3.0"
},
"require-dev": {
"barryvdh/laravel-ide-helper": "^2.12",
......
......@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "bef46997991684e2585a33612e100f13",
"content-hash": "1061199e4285925f49b2e6d4cb4b7a4d",
"packages": [
{
"name": "brick/math",
......@@ -5690,6 +5690,63 @@
},
"time": "2022-06-16T14:31:10+00:00"
},
{
"name": "vizir/laravel-keycloak-web-guard",
"version": "v3.0.1",
"source": {
"type": "git",
"url": "https://github.com/mariovalney/laravel-keycloak-web-guard.git",
"reference": "eb30758e4479aadde2a784594e18bf54fe6ae07a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mariovalney/laravel-keycloak-web-guard/zipball/eb30758e4479aadde2a784594e18bf54fe6ae07a",
"reference": "eb30758e4479aadde2a784594e18bf54fe6ae07a",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "^6.5|^7.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Vizir\\KeycloakWebGuard\\KeycloakWebGuardServiceProvider"
],
"aliases": {
"KeycloakWeb": "Vizir\\KeycloakWebGuard\\Facades\\KeycloakWeb"
}
}
},
"autoload": {
"psr-4": {
"Vizir\\KeycloakWebGuard\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mário Valney",
"email": "mariovalney@gmail.com"
}
],
"description": "Simple Keycloak Guard to Laravel Web Routes",
"homepage": "https://github.com/Vizir/laravel-keycloak-web-guard",
"keywords": [
"Authentication",
"jwt",
"keycloak",
"laravel"
],
"support": {
"issues": "https://github.com/mariovalney/laravel-keycloak-web-guard/issues",
"source": "https://github.com/mariovalney/laravel-keycloak-web-guard/tree/v3.0.1"
},
"time": "2022-09-28T17:31:42+00:00"
},
{
"name": "vlucas/phpdotenv",
"version": "v5.4.1",
......
......@@ -37,7 +37,7 @@ return [
'guards' => [
'web' => [
'driver' => 'session',
'driver' => 'keycloak-web',
'provider' => 'users',
],
......@@ -66,8 +66,8 @@ return [
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
'driver' => 'keycloak-users',
'model' => Vizir\KeycloakWebGuard\Models\KeycloakUser::class,
],
// 'users' => [
......@@ -99,4 +99,4 @@ return [
],
],
];
];
\ No newline at end of file
<?php
return [
/**
* Keycloak Url
*
* Generally https://your-server.com/auth
*/
'base_url' => env('KEYCLOAK_BASE_URL', ''),
/**
* Keycloak Realm
*
* Default is master
*/
'realm' => env('KEYCLOAK_REALM', 'master'),
/**
* The Keycloak Server realm public key (string).
*
* @see Keycloak >> Realm Settings >> Keys >> RS256 >> Public Key
*/
'realm_public_key' => env('KEYCLOAK_REALM_PUBLIC_KEY', null),
/**
* Keycloak Client ID
*
* @see Keycloak >> Clients >> Installation
*/
'client_id' => env('KEYCLOAK_CLIENT_ID', null),
/**
* Keycloak Client Secret
*
* @see Keycloak >> Clients >> Installation
*/
'client_secret' => env('KEYCLOAK_CLIENT_SECRET', null),
/**
* We can cache the OpenId Configuration
* The result from /realms/{realm-name}/.well-known/openid-configuration
*
* @link https://www.keycloak.org/docs/3.2/securing_apps/topics/oidc/oidc-generic.html
*/
'cache_openid' => env('KEYCLOAK_CACHE_OPENID', false),
/**
* Page to redirect after callback if there's no "intent"
*
* @see Vizir\KeycloakWebGuard\Controllers\AuthController::callback()
*/
'redirect_url' => '/admin',
/**
* The routes for authenticate
*
* Accept a string as the first parameter of route() or false to disable the route.
*
* The routes will receive the name "keycloak.{route}" and login/callback are required.
* So, if you make it false, you shoul register a named 'keycloak.login' route and extend
* the Vizir\KeycloakWebGuard\Controllers\AuthController controller.
*/
'routes' => [
'login' => false,
'logout' => false,
'register' => false,
'callback' => false,
],
/**
* GuzzleHttp Client options
*
* @link http://docs.guzzlephp.org/en/stable/request-options.html
*/
'guzzle_options' => [],
];
\ No newline at end of file
......@@ -4,10 +4,6 @@ return [
"browserverification_enabled" => true,
"browserverification_whitelist" => [
],
"admin" => [
"user" => env("ADMIN_USER", "admin"),
"password" => env("ADMIN_PASSWORD", "admin"),
],
"affiliate_preference" => "adgoal",
"botprotection" => [
"enabled" => env("BOT_PROTECTION", false),
......
......@@ -14,7 +14,7 @@ return [
| Supported: "file", "cookie", "database", "apc",
| "memcached", "redis", "array"
|
*/
*/
'driver' => env('SESSION_DRIVER', 'file'),
......@@ -27,11 +27,11 @@ return [
| to be allowed to remain idle before it expires. If you want them
| to immediately expire on the browser closing, set that option.
|
*/
*/
'lifetime' => 120,
'lifetime' => 60,
'expire_on_close' => false,
'expire_on_close' => true,
/*
|--------------------------------------------------------------------------
......@@ -42,7 +42,7 @@ return [
| should be encrypted before it is stored. All encryption will be run
| automatically by Laravel and you can use the Session like normal.
|
*/
*/
'encrypt' => true,
......@@ -55,7 +55,7 @@ return [
| files may be stored. A default has been set for you but a different
| location may be specified. This is only needed for file sessions.
|
*/
*/
'files' => storage_path('framework/sessions'),
......@@ -68,10 +68,10 @@ return [
| connection that should be used to manage these sessions. This should
| correspond to a connection in your database configuration options.
|
*/
*/
'connection' => env('REDIS_SESSION_CONNECTION', 'cache'),
/*
|--------------------------------------------------------------------------
| Session Database Table
......@@ -81,7 +81,7 @@ return [
| should use to manage the sessions. Of course, a sensible default is
| provided for you; however, you are free to change this as needed.
|
*/
*/
'table' => 'sessions',
......@@ -94,7 +94,7 @@ return [
| cache store that should be used for these sessions. This value must
| correspond with one of the application's configured cache stores.
|
*/
*/
'store' => null,
......@@ -107,7 +107,7 @@ return [
| rid of old sessions from storage. Here are the chances that it will
| happen on a given request. By default, the odds are 2 out of 100.
|
*/
*/
'lottery' => [2, 100],
......@@ -120,7 +120,7 @@ return [
| instance by ID. The name specified here will get used every time a
| new session cookie is created by the framework for every driver.
|
*/
*/
'cookie' => 'mg_session',
......@@ -133,7 +133,7 @@ return [
| be regarded as available. Typically, this will be the root path of
| your application but you are free to change this when necessary.
|
*/
*/
'path' => '/',
......@@ -146,7 +146,7 @@ return [
| in your application. This will determine which domains the cookie is
| available to in your application. A sensible default has been set.
|
*/
*/
'domain' => env('SESSION_DOMAIN', null),
......@@ -159,7 +159,7 @@ return [
| to the server if the browser has a HTTPS connection. This will keep
| the cookie from being sent to you if it can not be done securely.
|
*/
*/
'secure' => env('SESSION_SECURE_COOKIE'),
......@@ -172,8 +172,8 @@ return [
| value of the cookie and the cookie will only be accessible through
| the HTTP protocol. You are free to modify this option if needed.
|
*/
*/
'http_only' => true,
];
];
\ No newline at end of file
......@@ -13,6 +13,6 @@ class DatabaseSeeder extends Seeder
*/
public function run()
{
$this->call(UsersSeeder::class);
// $this->call(UsersSeeder::class);
}
}
}
\ No newline at end of file
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use DB;
use Hash;
class UsersSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
DB::table('users')->truncate();
DB::table('users')->insert(
[
'email' => config("metager.metager.admin.user"),
'name' => config("metager.metager.admin.user"),
'password' => Hash::make(config("metager.metager.admin.password")),
]
);
}
}
require('es6-promise').polyfill();
require('fetch-ie8');
require('chart.js/dist/chart.js');
require("es6-promise").polyfill();
require("fetch-ie8");
require("chart.js/dist/chart.js");
let parallel_fetches = 8;
......@@ -11,239 +11,280 @@ let chart = null;
load();
function load() {
let parallel = Math.floor(parallel_fetches / 2)
let fetches = [];
let fetches_same_time = loadSameTimes(parallel);
let fetches_total = loadTotals(parallel);
fetches = fetches.concat(fetches_same_time, fetches_total);
if (fetches.length > 0) {
let allData = Promise.all(fetches)
allData.then((res) => {
updateTable();
updateChart();
updateRecord();
load();
});
} else {
updateTable();
updateChart();
updateRecord();
}
let parallel = Math.floor(parallel_fetches / 2);
let fetches = [];
let fetches_same_time = loadSameTimes(parallel);
let fetches_total = loadTotals(parallel);
fetches = fetches.concat(fetches_same_time, fetches_total);
if (fetches.length > 0) {
let allData = Promise.all(fetches);
allData.then((res) => {
updateTable();
updateChart();
updateRecord();
load();
});
} else {
updateTable();
updateChart();
updateRecord();
}
}
function updateRecord() {
let record_total = null;
for (let i = 0; i < data.length; i++) {
let total = data[i]["total"]
let same_time = data[i]["same_time"]
let date = document.querySelectorAll("tbody tr .date")[i].dataset.date_formatted
if (typeof total === "number" && typeof same_time === "number" && (record_total === null || record_total < total)) {
record_total = total;
let record_same_time_element = document.querySelector(".record .record-same-time");
let record_total_element = document.querySelector(".record .record-total");
record_same_time_element.innerHTML = same_time.toLocaleString('de-DE', {
maximumFractionDigits: 0
});
record_same_time_element.classList.remove("loading");
record_total_element.innerHTML = record_total.toLocaleString('de-DE', {
maximumFractionDigits: 0
});
record_total_element.classList.remove("loading");
let record_date_element = document.querySelector(".record .record-date");
record_date_element.classList.remove("loading");
record_date_element.innerHTML = date;
}
let record_total = null;
for (let i = 0; i < data.length; i++) {
let total = data[i]["total"];
let same_time = data[i]["same_time"];
let date =
document.querySelectorAll("tbody tr .date")[i].dataset.date_formatted;
if (
typeof total === "number" &&
typeof same_time === "number" &&
(record_total === null || record_total < total)
) {
record_total = total;
let record_same_time_element = document.querySelector(
".record .record-same-time"
);
let record_total_element = document.querySelector(
".record .record-total"
);
record_same_time_element.innerHTML = same_time.toLocaleString("de-DE", {
maximumFractionDigits: 0,
});
record_same_time_element.classList.remove("loading");
record_total_element.innerHTML = record_total.toLocaleString("de-DE", {
maximumFractionDigits: 0,
});
record_total_element.classList.remove("loading");
let record_date_element = document.querySelector(".record .record-date");
record_date_element.classList.remove("loading");
record_date_element.innerHTML = date;
}
}
}
function updateTable() {
let sum = 0;
for (let i = 0; i < data.length; i++) {
if (typeof data[i]["total"] === "number") {
// Update Total Number
let total_element = document.querySelector("[data-days_ago=\"" + i + "\"] .total")
total_element.innerHTML = data[i]["total"].toLocaleString('de-DE', {
maximumFractionDigits: 0
})
total_element.classList.remove("loading")
if (typeof sum !== undefined && i > 0) {
sum += data[i]["total"]
}
} else {
sum = undefined;
}
if (typeof data[i]["same_time"] === "number") {
// Update Total Number
let same_time_element = document.querySelector("[data-days_ago=\"" + i + "\"] .same-time")
same_time_element.innerHTML = data[i]["same_time"].toLocaleString('de-DE', {
maximumFractionDigits: 0
})
same_time_element.classList.remove("loading")
}
if (typeof sum !== undefined) {
let median_element = document.querySelector("[data-days_ago=\"" + i + "\"] .median");
let median = 0;
if (i > 0) {
median = sum / i;
}
median_element.innerHTML = median.toLocaleString('de-DE', {
maximumFractionDigits: 0
});
median_element.classList.remove("loading");
let total_median_days_element = document.querySelector(".total-median .median-days");
total_median_days_element.classList.remove("loading")
total_median_days_element.innerHTML = i + 1
let total_median_values_element = document.querySelector(".total-median .median-value");
total_median_values_element.classList.remove("loading")
total_median_values_element.innerHTML = median.toLocaleString('de-DE', {
maximumFractionDigits: 0
});
let sum = 0;
for (let i = 0; i < data.length; i++) {
if (typeof data[i]["total"] === "number") {
// Update Total Number
let total_element = document.querySelector(
'[data-days_ago="' + i + '"] .total'
);
total_element.innerHTML = data[i]["total"].toLocaleString("de-DE", {
maximumFractionDigits: 0,