20 Commits
0.6.0 ... 0.6.2

Author SHA1 Message Date
937a0206a5 Added existing account check to logs 2020-09-08 01:38:56 +01:00
3598a32ecf Added existing account check to logs 2020-09-08 01:37:33 +01:00
ac8b303e2c Update to logauthfailure 2020-09-08 01:34:47 +01:00
e93abd2ab7 Added logging for successful authentication attempts 2020-09-08 01:31:09 +01:00
20ab381076 Added logging for failed authentication attempts 2020-09-08 01:26:27 +01:00
e566e40404 Update target user in logs 2020-09-08 00:07:50 +01:00
b0a935b8b3 Add acceptable "permanent" ban time 2020-09-08 00:06:27 +01:00
0dfb68dba2 Add acceptable "permanent" ban time 2020-09-08 00:05:37 +01:00
24303052ad Ban validation update 2020-09-07 23:57:50 +01:00
178bc31a6e Ban datetime format 2020-09-07 23:44:14 +01:00
98e557a840 Update ban dates 2020-09-07 23:42:09 +01:00
95bf7c239e Update ban time logic 2020-09-07 23:38:25 +01:00
4d2595dd39 Update ban logic 2020-09-07 23:33:35 +01:00
4e81a41210 Updated installation process 2020-09-07 23:22:25 +01:00
1319ce6b86 Added more debug logging 2020-09-07 22:56:54 +01:00
bea83b650c Added more debug logging 2020-09-07 22:54:20 +01:00
675cc3c329 Import missing facade 2020-09-07 22:35:42 +01:00
e8119b763c Register Application observers 2020-09-07 21:43:48 +01:00
04838048ce Merge pull request #10 from spacejewel-hosting/translate
Force new users to verify email
2020-09-03 20:22:11 +01:00
87f8e63b24 Force new users to verify email 2020-09-03 20:06:29 +01:00
14 changed files with 143 additions and 21 deletions

View File

@@ -21,9 +21,6 @@ RECAPTCHA_PRIVATE_KEY=
RECAPTCHA_VERIFY_URL="https://www.google.com/recaptcha/api/siteverify"
# WARNING: Your contact form will be useless if you change this value. Only change this URL if Google updates it.
IPGEO_API_KEY=""
IPGEO_API_URL=""
MOJANG_STATUS_URL="https://status.mojang.com/check"
MOJANG_API_URL="https://api.mojang.com"
@@ -32,7 +29,7 @@ IPGEO_API_URL="https://api.ipgeolocation.io/ipgeo"
ARCANEDEV_LOGVIEWER_MIDDLEWARE=web,auth,can:admin.maintenance.logs.view
RELEASE=staffmanagement@0.2.0
RELEASE=staffmanagement@0.6.1
SLACK_INTEGRATION_WEBHOOK=
@@ -68,4 +65,8 @@ PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
# Mostly for developers, but with Papertrail, you can easily see what the app's users are doing without relying on
# the internal log viewer.
SENTRY_LARAVEL_DSN=
PAPERTRAIL_URL=
PAPERTRAIL_PORT

View File

@@ -8,7 +8,7 @@ class Ban extends Model
{
public $fillable = [
'userID',
'reason',
'bannedUntil',
@@ -16,7 +16,11 @@ class Ban extends Model
'authorUserID'
];
public $dates = [
'bannedUntil'
];
public function user()
{
return $this->belongsTo('App\User', 'userID', 'id');

View File

@@ -99,12 +99,16 @@ class Install extends Command
$settings['MAIL_PASSWORD'] = $this->secret('SMTP Password (Input won\'t be seen)');
$settings['MAIL_PORT'] = $this->ask('SMTP Server Port');
$settings['MAIL_HOST'] = $this->ask('SMTP Server Hostname');
$settings['MAIL_FROM'] = $this->ask('E-mail address to send from: ');
$this->info('== Notification Settings (5/6) (Slack) ==');
$settings['SLACK_INTEGRATION_WEBHOOK'] = $this->ask('Integration webhook URL');
$this->info('== Web Settings (6/6) ==');
$settings['APP_URL'] = $this->ask('Application\'s URL');
$settings['APP_URL'] = $this->ask('Application\'s URL (ex. https://where.you.installed.theapp.com): ');
$settings['APP_LOGO'] = $this->ask('App logo (Link to an image): ');
$settings['APP_SITEHOMEPAGE'] = $this->ask('Site homepage (appears in the main header): ');
} while(!$this->confirm('Are you sure you want to save these settings? You can always go back and try again.'));

View File

@@ -15,7 +15,7 @@ class BanController extends Controller
public function insert(BanUserRequest $request, User $user)
{
$this->authorize('create', Ban::class);
$this->authorize('create', [Ban::class, $user]);
if (is_null($user->bans))
{
@@ -50,13 +50,13 @@ class BanController extends Controller
else
{
// Essentially permanent
$expiryDate->addYears(100);
$expiryDate->addYears(5);
}
$ban = Ban::create([
'userID' => $user->id,
'reason' => $reason,
'bannedUntil' => $expiryDate->toDateTimeString() ?? null,
'bannedUntil' => $expiryDate->format('Y-m-d H:i:s'),
'userAgent' => "Unknown",
'authorUserID' => Auth::user()->id
]);

View File

@@ -7,6 +7,7 @@ use App\Options as Option;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
class OptionsController extends Controller
{
@@ -29,17 +30,33 @@ class OptionsController extends Controller
{
if (Auth::user()->can('admin.settings.edit'))
{
Log::debug('Updating application options', [
'ip' => $request->ip(),
'ua' => $request->userAgent(),
'username' => Auth::user()->username
]);
foreach($request->all() as $optionName => $option)
{
try
{
if (Options::optionExists($option))
Log::debug('Going through option ' . $optionName);
if (Options::optionExists($optionName))
{
Log::debug('Option exists, updating to new values', [
'opt' => $optionName,
'new_value' => $option
]);
Options::changeOption($optionName, $option);
}
}
catch(\Exception $ex)
{
Log::error('Unable to update options!', [
'msg' => $ex->getMessage(),
'trace' => $ex->getTraceAsString()
]);
report($ex);
$errorCond = true;
$request->session()->flash('error', 'An error occurred while trying to save settings: ' . $ex->getMessage());
}

View File

@@ -27,7 +27,7 @@ class BanUserRequest extends FormRequest
{
return [
'reason' => 'required|string',
'durationOperand' => 'nullable|integer',
'durationOperand' => 'nullable|string',
'durationOperator' => 'nullable|string'
];
}

View File

@@ -0,0 +1,45 @@
<?php
namespace App\Listeners;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
class LogAuthenticationFailure
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle($event)
{
$targetAccountID = 0;
$originalIP = "0.0.0.0";
if (isset($event->user->id))
{
$targetAccountID = $event->user->id;
}
Log::alert('SECURITY (login): Detected failed authentication attempt!', [
'targetAccountID' => $targetAccountID,
'existingAccount' => ($targetAccountID == 0) ? false : true,
'sourceIP' => request()->ip(),
'matchesAccountLastIP' => request()->ip() == $originalIP,
'sourceUserAgent' => request()->userAgent(),
]);
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace App\Listeners;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
class LogAuthenticationSuccess
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle($event)
{
Log::info('SECURITY (postauth-pre2fa): Detected successful login attempt', [
'accountID' => $event->user->id,
'sourceIP' => request()->ip(),
'matchesAccountLastIP' => request()->ip() == $event->user->originalIP,
'sourceUserAgent' => request()->userAgent(),
]);
}
}

View File

@@ -3,6 +3,7 @@
namespace App\Observers;
use App\Application;
use Illuminate\Support\Facades\Log;
class ApplicationObserver
{
@@ -55,7 +56,7 @@ class ApplicationObserver
}
}
// application can now be deleted
// application can now be deleted
}
/**

View File

@@ -38,18 +38,19 @@ class BanPolicy
/**
* Determine whether the user can create models.
*
* @param \App\User $user
* @param \App\User $user
* @param User $targetUser
* @return mixed
*/
public function create(User $user)
public function create(User $user, User $targetUser)
{
Log::debug("Authorization check started", [
'requiredRoles' => 'admin',
'currentRoles' => $user->roles(),
'hasRequiredRole' => $user->hasRole('admin'),
'targetUser' => $targetUser->username,
'isCurrentUser' => Auth::user()->is($user)
]);
return $user->hasRole('admin') && Auth::user()->isNot($user);
return $user->hasRole('admin') && $user->isNot($targetUser);
}
/**

View File

@@ -2,6 +2,8 @@
namespace App\Providers;
use App\Application;
use App\Observers\ApplicationObserver;
use App\Observers\UserObserver;
use App\User;
use Illuminate\Support\Facades\Schema;
@@ -32,7 +34,9 @@ class AppServiceProvider extends ServiceProvider
]);
Schema::defaultStringLength(191);
User::observe(UserObserver::class);
Application::observe(ApplicationObserver::class);
$this->app['request']->server->set('HTTPS', $this->app->environment() != 'local');
}

View File

@@ -2,7 +2,11 @@
namespace App\Providers;
use App\Listeners\LogAuthenticationFailure;
use App\Listeners\LogAuthenticationSuccess;
use App\Listeners\OnUserRegistration;
use Illuminate\Auth\Events\Failed;
use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
@@ -20,6 +24,12 @@ class EventServiceProvider extends ServiceProvider
SendEmailVerificationNotification::class,
OnUserRegistration::class
],
Failed::class => [
LogAuthenticationFailure::class
],
Login::class => [
LogAuthenticationSuccess::class
],
'App\Events\ApplicationApprovedEvent' => [
'App\Listeners\PromoteUser'
],

View File

@@ -7,11 +7,10 @@ use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
class User extends Authenticatable implements MustVerifyEmail
{
use Notifiable;
use HasRoles;
//use MustVerifyEmail;
/**
* The attributes that are mass assignable.

View File

@@ -17,7 +17,7 @@ Route::group(['prefix' => LaravelLocalization::setLocale(), 'middleware' => [ 'l
Route::group(['prefix' => 'auth', 'middleware' => ['usernameUUID']], function (){
Auth::routes();
Auth::routes(['verify' => true]);
Route::post('/twofa/authenticate', 'Auth\TwofaController@verify2FA')
->name('verify2FA');
@@ -31,7 +31,7 @@ Route::group(['prefix' => LaravelLocalization::setLocale(), 'middleware' => [ 'l
->name('sendSubmission');
Route::group(['middleware' => ['auth', 'forcelogout', '2fa']], function(){
Route::group(['middleware' => ['auth', 'forcelogout', '2fa', 'verified']], function(){
Route::get('/dashboard', 'DashboardController@index')
->name('dashboard')