Compare commits

...

34 Commits

Author SHA1 Message Date
Miguel Nogueira 85c719c24d Fix bad key name 2020-12-19 01:33:59 +00:00
Miguel Nogueira 5df3f965ef Merged in revert-pr-6 (pull request #7)
Revert "Apply fixes from StyleCI (pull request #6)"
2020-10-21 00:31:11 +00:00
Miguel Nogueira 4eb115d165 Revert "Apply fixes from StyleCI (pull request #6)"
This reverts pull request #6.

> This pull request applies code style fixes from an analysis carried out by [StyleCI](https://bitbucket.styleci.io).
> 
> For more information, click [here](https://bitbucket.styleci.io/analyses/a2Jl7D).
2020-10-21 00:29:50 +00:00
Miguel Nogueira 0433ce7693 Merged in analysis-a2Jl7D (pull request #6)
Apply fixes from StyleCI
2020-10-21 00:24:54 +00:00
Miguel Nogueira 773ec570d9 Apply fixes from StyleCI 2020-10-21 00:01:41 +00:00
Miguel Nogueira 53c23f3698 Changed branding for the repo 2020-10-21 00:01:32 +00:00
Miguel Nogueira f1db159eee
Update SECURITY.md 2020-09-08 17:44:56 +01:00
Miguel Nogueira 0d14a65ee5
Create SECURITY.md 2020-09-08 17:32:56 +01:00
Miguel Nogueira 2942157603
Update README.md 2020-09-08 06:16:27 +01:00
Miguel Nogueira 11f3fb90d0
Update README.md 2020-09-08 06:16:14 +01:00
Miguel Nogueira 937a0206a5 Added existing account check to logs 2020-09-08 01:38:56 +01:00
Miguel Nogueira 3598a32ecf Added existing account check to logs 2020-09-08 01:37:33 +01:00
Miguel Nogueira ac8b303e2c Update to logauthfailure 2020-09-08 01:34:47 +01:00
Miguel Nogueira e93abd2ab7 Added logging for successful authentication attempts 2020-09-08 01:31:09 +01:00
Miguel Nogueira 20ab381076 Added logging for failed authentication attempts 2020-09-08 01:26:27 +01:00
Miguel Nogueira e566e40404 Update target user in logs 2020-09-08 00:07:50 +01:00
Miguel Nogueira b0a935b8b3 Add acceptable "permanent" ban time 2020-09-08 00:06:27 +01:00
Miguel Nogueira 0dfb68dba2 Add acceptable "permanent" ban time 2020-09-08 00:05:37 +01:00
Miguel Nogueira 24303052ad Ban validation update 2020-09-07 23:57:50 +01:00
Miguel Nogueira 178bc31a6e Ban datetime format 2020-09-07 23:44:14 +01:00
Miguel Nogueira 98e557a840 Update ban dates 2020-09-07 23:42:09 +01:00
Miguel Nogueira 95bf7c239e Update ban time logic 2020-09-07 23:38:25 +01:00
Miguel Nogueira 4d2595dd39 Update ban logic 2020-09-07 23:33:35 +01:00
Miguel Nogueira 4e81a41210 Updated installation process 2020-09-07 23:22:25 +01:00
Miguel Nogueira 1319ce6b86 Added more debug logging 2020-09-07 22:56:54 +01:00
Miguel Nogueira bea83b650c Added more debug logging 2020-09-07 22:54:20 +01:00
Miguel Nogueira 675cc3c329 Import missing facade 2020-09-07 22:35:42 +01:00
Miguel Nogueira e8119b763c Register Application observers 2020-09-07 21:43:48 +01:00
Miguel Nogueira 04838048ce
Merge pull request #10 from spacejewel-hosting/translate
Force new users to verify email
2020-09-03 20:22:11 +01:00
Miguel Nogueira 7292aab4b7
Merge pull request #9 from spacejewel-hosting/translate
Menu translations and source files
2020-09-03 17:38:18 +01:00
Miguel Nogueira e37b38f2d9
Update README.md 2020-09-03 17:19:15 +01:00
Miguel Nogueira c83e720a6d
Create CONTRIBUTING.md 2020-09-03 17:18:28 +01:00
Miguel Nogueira fbd1e83306
Create CODE_OF_CONDUCT.md 2020-09-03 04:47:42 +01:00
Miguel Nogueira 50ed47964c
Merge pull request #5 from spacejewel-hosting/translate
New translations (i10n)

This merge adds the following;
 - Completed Portuguese translations
 - Spanish and French translation templates
 - Several bugfixes to Vacancies, Applications, and Appointments
 - Added missing translations
 - Language selection menu

Next feature for 0.6.0:
 - Self updater with Artisan command for non-git installations
2020-09-03 04:38:25 +01:00
16 changed files with 274 additions and 19 deletions

View File

@ -21,9 +21,6 @@ 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"
@ -32,7 +29,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.2.0 RELEASE=staffmanagement@0.6.1
SLACK_INTEGRATION_WEBHOOK= SLACK_INTEGRATION_WEBHOOK=
@ -68,4 +65,8 @@ 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

76
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at support@spacejewel-hosting.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

29
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,29 @@
# Thank you for contributing!
Read this file carefully before contributing to the project. It's important that everyone follows these rules to ensure smooth contribution.
## General workflow
Since the project is under version 1.0.0, the master branch can be quite unstable, and even unusable. For this reason, I recommend you stick to the published
releases, unless you intend on helping out with the project.
New features are commited directly to the ``master`` branch, while translations are commited to a special service branch, merged onto ``translate``, tested, and
merged back to master. Above version 1.0.0, new features should follow the same procedure as translations.
## Before commiting
Before commiting, make sure your code adheres to the Laravel coding guidelines, as well as PSR-4. I'll personally review and merge each PR.
Thank you for your interest!
# Bug reports
As always, bug reports should stick to the bug report template. GitHub makes this easy for you by letting you choose which issue template you'd like to use
before reporting an isuse. This helps everyone stay in the same page.
Issues published without a template might take longer to be resolved, or may be ignored and marked ``wontfix``.
# Licensing
Any contributions you make will be under the GNU GPL v3 license, which is the license that covers this project.

View File

@ -1,6 +1,6 @@
# Raspberry Teams - The Simple Staff Application Manager v 0.1.0 [![Crowdin](https://badges.crowdin.net/raspberry-staff-manager/localized.svg)](https://crowdin.com/project/raspberry-staff-manager) # RB Recruiter v 0.6.2 [![Crowdin](https://badges.crowdin.net/raspberry-staff-manager/localized.svg)](https://crowdin.com/project/raspberry-staff-manager)
## The quick and pain-free staff application manager ## The quick and pain-free form management solution for communities
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,6 +48,14 @@ 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).

19
SECURITY.md Normal file
View File

@ -0,0 +1,19 @@
# 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,6 +17,10 @@ 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,12 +99,16 @@ 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'); $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.')); } 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); $this->authorize('create', [Ban::class, $user]);
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(100); $expiryDate->addYears(5);
} }
$ban = Ban::create([ $ban = Ban::create([
'userID' => $user->id, 'userID' => $user->id,
'reason' => $reason, 'reason' => $reason,
'bannedUntil' => $expiryDate->toDateTimeString() ?? null, 'bannedUntil' => $expiryDate->format('Y-m-d H:i:s'),
'userAgent' => "Unknown", 'userAgent' => "Unknown",
'authorUserID' => Auth::user()->id 'authorUserID' => Auth::user()->id
]); ]);

View File

@ -7,6 +7,7 @@ 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
{ {
@ -29,17 +30,33 @@ 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
{ {
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); 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|integer', 'durationOperand' => 'nullable|string',
'durationOperator' => '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; namespace App\Observers;
use App\Application; use App\Application;
use Illuminate\Support\Facades\Log;
class ApplicationObserver class ApplicationObserver
{ {

View File

@ -38,18 +38,19 @@ 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) public function create(User $user, User $targetUser)
{ {
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') && Auth::user()->isNot($user); return $user->hasRole('admin') && $user->isNot($targetUser);
} }
/** /**

View File

@ -2,6 +2,8 @@
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;
@ -32,7 +34,9 @@ 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,7 +2,11 @@
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;
@ -20,6 +24,12 @@ 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'
], ],