Compare commits

..

No commits in common. "master" and "0.6.0" have entirely different histories.

16 changed files with 23 additions and 172 deletions

View File

@ -21,6 +21,9 @@ RECAPTCHA_PRIVATE_KEY=
RECAPTCHA_VERIFY_URL="https://www.google.com/recaptcha/api/siteverify" 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. # 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_STATUS_URL="https://status.mojang.com/check"
MOJANG_API_URL="https://api.mojang.com" MOJANG_API_URL="https://api.mojang.com"
@ -29,7 +32,7 @@ IPGEO_API_URL="https://api.ipgeolocation.io/ipgeo"
ARCANEDEV_LOGVIEWER_MIDDLEWARE=web,auth,can:admin.maintenance.logs.view ARCANEDEV_LOGVIEWER_MIDDLEWARE=web,auth,can:admin.maintenance.logs.view
RELEASE=staffmanagement@0.6.1 RELEASE=staffmanagement@0.2.0
SLACK_INTEGRATION_WEBHOOK= SLACK_INTEGRATION_WEBHOOK=
@ -65,8 +68,4 @@ PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 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= SENTRY_LARAVEL_DSN=
PAPERTRAIL_URL=
PAPERTRAIL_PORT

View File

@ -1,6 +1,6 @@
# RB Recruiter v 0.6.2 [![Crowdin](https://badges.crowdin.net/raspberry-staff-manager/localized.svg)](https://crowdin.com/project/raspberry-staff-manager) # Raspberry Teams - The Simple Staff Application Manager v 0.5.2 [![Crowdin](https://badges.crowdin.net/raspberry-staff-manager/localized.svg)](https://crowdin.com/project/raspberry-staff-manager)
## The quick and pain-free form management solution for communities ## The quick and pain-free staff application manager
Have you ever gotten tired of managing your Minecraft server/network's applications through Discord (or anything else) and having to scroll through hundreds of new messages just to find that one applicant's username? Have you ever gotten tired of managing your Minecraft server/network's applications through Discord (or anything else) and having to scroll through hundreds of new messages just to find that one applicant's username?
@ -48,14 +48,6 @@ Tech stack:
- jQuery / Plain Javascript - jQuery / Plain Javascript
- vueJS (in the future) - vueJS (in the future)
# Stability
Currently, the ``master`` branch is highly unstable, since it's under active development. Expect it to break with each commit. Even though I make an effort to make sure each commit is good to go before pushing, things might still break unexpectedly, and you may find a lot of bugs (which you should report).
Every released version is currently pre-release. If you really want to run this before version ``1.0.0`` comes out, always stay on the latest version, as those will always be tested before release, ensuring less chaos.
*Note: This application is NOT production ready! It won't be until the first stable release comes out, which might take a bit longer.
# Operating System Requirements # Operating System Requirements
Currently, this application is only supported on Linux environments (Ubuntu 20.04 or derivatives are recommended). Currently, this application is only supported on Linux environments (Ubuntu 20.04 or derivatives are recommended).

View File

@ -1,19 +0,0 @@
# Security Policy
## Supported Versions
The following versions are currently supported:
| Version | Supported |
| ------- | ------------------ |
| 0.1.x | :x: |
| 0.5.x | :x: |
| 0.6.x | :white_check_mark: |
## Reporting a Vulnerability
To securely report a vulnerability, you may send me an email directly containing the details of said vulnerability: ``me@nogueira.codes``.
You may optionally encrypt your message with my [public PGP key](http://pool.sks-keyservers.net/pks/lookup?op=get&search=0x48DF709E7405702B).
Use this free [online encryption tool](https://www.igolder.com/pgp/encryption/) if you don't know how to use PGP on your desktop.

View File

@ -17,10 +17,6 @@ class Ban extends Model
]; ];
public $dates = [
'bannedUntil'
];
public function user() public function user()
{ {
return $this->belongsTo('App\User', 'userID', 'id'); return $this->belongsTo('App\User', 'userID', 'id');

View File

@ -99,16 +99,12 @@ class Install extends Command
$settings['MAIL_PASSWORD'] = $this->secret('SMTP Password (Input won\'t be seen)'); $settings['MAIL_PASSWORD'] = $this->secret('SMTP Password (Input won\'t be seen)');
$settings['MAIL_PORT'] = $this->ask('SMTP Server Port'); $settings['MAIL_PORT'] = $this->ask('SMTP Server Port');
$settings['MAIL_HOST'] = $this->ask('SMTP Server Hostname'); $settings['MAIL_HOST'] = $this->ask('SMTP Server Hostname');
$settings['MAIL_FROM_ADDRESS'] = $this->ask('E-mail address to send from');
$this->info('== Notification Settings (5/6) (Slack) =='); $this->info('== Notification Settings (5/6) (Slack) ==');
$settings['SLACK_INTEGRATION_WEBHOOK'] = $this->ask('Integration webhook URL'); $settings['SLACK_INTEGRATION_WEBHOOK'] = $this->ask('Integration webhook URL');
$this->info('== Web Settings (6/6) =='); $this->info('== Web Settings (6/6) ==');
$settings['APP_URL'] = $this->ask('Application\'s URL (ex. https://where.you.installed.theapp.com): '); $settings['APP_URL'] = $this->ask('Application\'s URL');
$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.')); } 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) public function insert(BanUserRequest $request, User $user)
{ {
$this->authorize('create', [Ban::class, $user]); $this->authorize('create', Ban::class);
if (is_null($user->bans)) if (is_null($user->bans))
{ {
@ -50,13 +50,13 @@ class BanController extends Controller
else else
{ {
// Essentially permanent // Essentially permanent
$expiryDate->addYears(5); $expiryDate->addYears(100);
} }
$ban = Ban::create([ $ban = Ban::create([
'userID' => $user->id, 'userID' => $user->id,
'reason' => $reason, 'reason' => $reason,
'bannedUntil' => $expiryDate->format('Y-m-d H:i:s'), 'bannedUntil' => $expiryDate->toDateTimeString() ?? null,
'userAgent' => "Unknown", 'userAgent' => "Unknown",
'authorUserID' => Auth::user()->id 'authorUserID' => Auth::user()->id
]); ]);

View File

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

View File

@ -1,45 +0,0 @@
<?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

@ -1,36 +0,0 @@
<?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,7 +3,6 @@
namespace App\Observers; namespace App\Observers;
use App\Application; use App\Application;
use Illuminate\Support\Facades\Log;
class ApplicationObserver class ApplicationObserver
{ {

View File

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

View File

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

View File

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

View File

@ -7,10 +7,11 @@ use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
use Spatie\Permission\Traits\HasRoles; use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable implements MustVerifyEmail class User extends Authenticatable
{ {
use Notifiable; use Notifiable;
use HasRoles; use HasRoles;
//use MustVerifyEmail;
/** /**
* The attributes that are mass assignable. * 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 (){ Route::group(['prefix' => 'auth', 'middleware' => ['usernameUUID']], function (){
Auth::routes(['verify' => true]); Auth::routes();
Route::post('/twofa/authenticate', 'Auth\TwofaController@verify2FA') Route::post('/twofa/authenticate', 'Auth\TwofaController@verify2FA')
->name('verify2FA'); ->name('verify2FA');
@ -31,7 +31,7 @@ Route::group(['prefix' => LaravelLocalization::setLocale(), 'middleware' => [ 'l
->name('sendSubmission'); ->name('sendSubmission');
Route::group(['middleware' => ['auth', 'forcelogout', '2fa', 'verified']], function(){ Route::group(['middleware' => ['auth', 'forcelogout', '2fa']], function(){
Route::get('/dashboard', 'DashboardController@index') Route::get('/dashboard', 'DashboardController@index')
->name('dashboard') ->name('dashboard')