2017-01-12 19:40:20 -08:00
< ? php
namespace App\Http\Controllers\Api ;
use App\Http\Controllers\Controller ;
2019-03-13 20:12:03 -07:00
use App\Http\Transformers\LoginAttemptsTransformer ;
2021-06-10 13:15:52 -07:00
use App\Models\Ldap ;
2017-10-16 07:07:21 -07:00
use App\Models\Setting ;
2018-03-02 18:01:20 -08:00
use App\Notifications\MailTest ;
2019-03-13 20:12:03 -07:00
use App\Services\LdapAd ;
2021-06-10 13:15:52 -07:00
use GuzzleHttp\Client ;
2018-12-06 14:05:43 -08:00
use Illuminate\Http\JsonResponse ;
2019-03-13 20:12:03 -07:00
use Illuminate\Http\Request ;
2020-10-05 20:34:17 -07:00
use Illuminate\Http\Response ;
2019-03-13 20:12:03 -07:00
use Illuminate\Support\Facades\DB ;
2018-12-06 14:05:43 -08:00
use Illuminate\Support\Facades\Log ;
2019-03-13 20:12:03 -07:00
use Illuminate\Support\Facades\Notification ;
2020-10-05 20:34:17 -07:00
use Illuminate\Support\Facades\Storage ;
2021-06-10 13:15:52 -07:00
use Illuminate\Support\Facades\Validator ; // forward-port of v4 LDAP model for Sync
2017-01-12 19:40:20 -08:00
class SettingsController extends Controller
{
2018-12-06 14:05:43 -08:00
/**
* Test the ldap settings
2021-06-10 13:15:52 -07:00
*
2018-12-06 14:05:43 -08:00
* @ author Wes Hulette < jwhulette @ gmail . com >
2021-06-10 13:15:52 -07:00
*
2018-12-06 14:05:43 -08:00
* @ since 5.0 . 0
2021-06-10 13:15:52 -07:00
*
2018-12-06 14:05:43 -08:00
* @ param App\Models\LdapAd $ldap
2021-06-10 13:15:52 -07:00
*
2018-12-06 14:05:43 -08:00
* @ return \Illuminate\Http\JsonResponse
*/
public function ldapAdSettingsTest ( LdapAd $ldap ) : JsonResponse
2017-07-07 23:44:48 -07:00
{
2021-06-10 13:15:52 -07:00
if ( ! $ldap -> init ()) {
2021-03-17 19:24:28 -07:00
Log :: info ( 'LDAP is not enabled so we cannot test.' );
2021-06-10 13:15:52 -07:00
2017-10-16 07:07:21 -07:00
return response () -> json ([ 'message' => 'LDAP is not enabled, cannot test.' ], 400 );
}
2018-12-06 14:05:43 -08:00
// The connect, bind and resulting users message
$message = [];
2017-07-07 23:44:48 -07:00
2021-03-17 19:24:28 -07:00
// This is all kinda fucked right now. The connection test doesn't actually do what you think,
// // and the way we parse the errors
2021-06-10 13:15:52 -07:00
// on the JS side is horrible.
2018-12-06 14:05:43 -08:00
Log :: info ( 'Preparing to test LDAP user login' );
// Test user can connect to the LDAP server
2017-07-07 23:44:48 -07:00
try {
2018-12-06 14:05:43 -08:00
$ldap -> testLdapAdUserConnection ();
$message [ 'login' ] = [
2021-06-10 13:15:52 -07:00
'message' => 'Successfully connected to LDAP server.' ,
2018-12-06 14:05:43 -08:00
];
} catch ( \Exception $ex ) {
2021-06-10 13:15:52 -07:00
\Log :: debug ( 'Connection to LDAP server ' . Setting :: getSettings () -> ldap_server . ' failed. Please check your LDAP settings and try again. Server Responded with error: ' . $ex -> getMessage ());
2021-03-17 19:24:28 -07:00
return response () -> json (
2021-06-10 13:15:52 -07:00
[ 'message' => 'Connection to LDAP server ' . Setting :: getSettings () -> ldap_server . " failed. Verify that the LDAP hostname is entered correctly and that it can be reached from this web server. \n \n Server Responded with error: " . $ex -> getMessage (),
2019-12-04 14:54:36 -08:00
2021-03-17 19:24:28 -07:00
], 400 );
2017-07-07 23:44:48 -07:00
}
2018-12-06 14:05:43 -08:00
Log :: info ( 'Preparing to test LDAP bind connection' );
// Test user can bind to the LDAP server
try {
2020-04-23 22:46:02 -07:00
Log :: info ( 'Testing Bind' );
2018-12-06 14:05:43 -08:00
$ldap -> testLdapAdBindConnection ();
$message [ 'bind' ] = [
2021-06-10 13:15:52 -07:00
'message' => 'Successfully bound to LDAP server.' ,
2018-12-06 14:05:43 -08:00
];
} catch ( \Exception $ex ) {
2020-04-23 22:46:02 -07:00
Log :: info ( 'LDAP Bind failed' );
2021-06-10 13:15:52 -07:00
return response () -> json ([ 'message' => 'Connection to LDAP successful, but we were unable to Bind the LDAP user ' . Setting :: getSettings () -> ldap_uname . " . Verify your that your LDAP Bind username and password are correct. \n \n Server Responded with error: " . $ex -> getMessage (),
2018-12-06 14:05:43 -08:00
], 400 );
2017-10-16 07:07:21 -07:00
}
2018-12-06 14:05:43 -08:00
Log :: info ( 'Preparing to get sample user set from LDAP directory' );
// Get a sample of 10 users so user can verify the data is correct
2020-11-30 17:11:44 -08:00
$settings = Setting :: getSettings ();
2017-10-16 06:34:04 -07:00
try {
2020-04-23 22:46:02 -07:00
Log :: info ( 'Testing LDAP sync' );
2020-09-09 14:18:05 -07:00
error_reporting ( E_ALL & ~ E_DEPRECATED ); // workaround for php7.4, which deprecates ldap_control_paged_result
2020-11-30 17:11:44 -08:00
// $users = $ldap->testUserImportSync(); // from AdLdap2 from v5, disabling and falling back to v4's sync code
$users = collect ( Ldap :: findLdapUsers ()) -> slice ( 0 , 11 ) -> filter ( function ( $value , $key ) { //choosing ELEVEN because one is going to be the count, which we're about to filter out in the next line
return is_int ( $key );
}) -> map ( function ( $item ) use ( $settings ) {
return ( object ) [
'username' => $item [ $settings [ 'ldap_username_field' ]][ 0 ] ? ? null ,
'employee_number' => $item [ $settings [ 'ldap_emp_num' ]][ 0 ] ? ? null ,
'lastname' => $item [ $settings [ 'ldap_lname_field' ]][ 0 ] ? ? null ,
'firstname' => $item [ $settings [ 'ldap_fname_field' ]][ 0 ] ? ? null ,
'email' => $item [ $settings [ 'ldap_email' ]][ 0 ] ? ? null ,
];
});
2021-03-17 19:24:28 -07:00
if ( $users -> count () > 0 ) {
2021-06-10 13:15:52 -07:00
$message [ 'user_sync' ] = [
'users' => $users ,
2021-03-17 19:24:28 -07:00
];
} else {
2021-06-10 13:15:52 -07:00
$message [ 'user_sync' ] = [
'message' => 'Connection to LDAP was successful, however there were no users returned from your query. You should confirm the Base Bind DN above.' ,
2021-03-17 19:24:28 -07:00
];
2021-06-10 13:15:52 -07:00
2021-03-17 19:24:28 -07:00
return response () -> json ( $message , 400 );
}
2018-12-06 14:05:43 -08:00
} catch ( \Exception $ex ) {
2020-04-23 22:46:02 -07:00
Log :: info ( 'LDAP sync failed' );
2021-06-10 13:15:52 -07:00
$message [ 'user_sync' ] = [
'message' => 'Error getting users from LDAP directory, error: ' . $ex -> getMessage (),
2018-12-06 14:05:43 -08:00
];
2021-06-10 13:15:52 -07:00
2018-12-06 14:05:43 -08:00
return response () -> json ( $message , 400 );
2017-10-16 06:34:04 -07:00
}
2018-12-06 14:05:43 -08:00
return response () -> json ( $message , 200 );
2017-10-16 06:34:04 -07:00
}
2020-11-16 21:23:08 -08:00
public function ldaptestlogin ( Request $request , LdapAd $ldap )
{
2021-06-10 13:15:52 -07:00
if ( Setting :: getSettings () -> ldap_enabled != '1' ) {
2020-11-16 21:23:08 -08:00
\Log :: debug ( 'LDAP is not enabled. Cannot test.' );
2021-06-10 13:15:52 -07:00
2020-11-16 21:23:08 -08:00
return response () -> json ([ 'message' => 'LDAP is not enabled, cannot test.' ], 400 );
}
2021-06-10 13:15:52 -07:00
$rules = [
2020-11-16 21:23:08 -08:00
'ldaptest_user' => 'required' ,
2021-06-10 13:15:52 -07:00
'ldaptest_password' => 'required' ,
];
2020-11-16 21:23:08 -08:00
$validator = Validator :: make ( $request -> all (), $rules );
if ( $validator -> fails ()) {
\Log :: debug ( 'LDAP Validation test failed.' );
2021-06-10 13:15:52 -07:00
$validation_errors = implode ( ' ' , $validator -> errors () -> all ());
2020-11-16 21:23:08 -08:00
return response () -> json ([ 'message' => $validator -> errors () -> all ()], 400 );
}
\Log :: debug ( 'Preparing to test LDAP login' );
try {
DB :: beginTransaction (); //this was the easiest way to invoke a full test of an LDAP login without adding new users to the DB (which may not be desired)
// $results = $ldap->ldap->auth()->attempt($request->input('ldaptest_username'), $request->input('ldaptest_password'), true);
// can't do this because that's a protected property.
$results = $ldap -> ldapLogin ( $request -> input ( 'ldaptest_user' ), $request -> input ( 'ldaptest_password' )); // this would normally create a user on success (if they didn't already exist), but for the transaction
2021-06-10 13:15:52 -07:00
if ( $results ) {
return response () -> json ([ 'message' => 'It worked! ' . $request -> input ( 'ldaptest_user' ) . ' successfully binded to LDAP.' ], 200 );
2020-11-16 21:23:08 -08:00
} else {
2021-06-10 13:15:52 -07:00
return response () -> json ([ 'message' => 'Login Failed. ' . $request -> input ( 'ldaptest_user' ) . ' did not successfully bind to LDAP.' ], 400 );
2020-11-16 21:23:08 -08:00
}
} catch ( \Exception $e ) {
\Log :: debug ( 'Connection failed' );
2021-06-10 13:15:52 -07:00
2020-11-16 21:23:08 -08:00
return response () -> json ([ 'message' => $e -> getMessage ()], 400 );
} finally {
DB :: rollBack (); // ALWAYS rollback, whether success or failure
}
}
2020-09-15 23:05:27 -07:00
public function slacktest ( Request $request )
2018-02-22 16:35:34 -08:00
{
2021-12-06 11:40:24 -08:00
// Only attempt the slack request if the validation passes
if ( $request -> validate ([
'slack_endpoint' => 'url|required_with:slack_channel|starts_with:https://hooks.slack.com|nullable' ,
'slack_channel' => 'required_with:slack_endpoint|starts_with:#|nullable' ,
])) {
$slack = new Client ([
'base_url' => e ( $request -> input ( 'slack_endpoint' )),
'defaults' => [
'exceptions' => false ,
],
2020-09-15 23:05:27 -07:00
]);
2018-02-22 16:35:34 -08:00
2021-12-06 11:40:24 -08:00
$payload = json_encode (
[
'channel' => e ( $request -> input ( 'slack_channel' )),
'text' => trans ( 'general.slack_test_msg' ),
'username' => e ( $request -> input ( 'slack_botname' )),
'icon_emoji' => ':heart:' ,
]);
2021-06-10 13:15:52 -07:00
2021-12-06 11:40:24 -08:00
try {
$slack -> post ( $request -> input ( 'slack_endpoint' ), [ 'body' => $payload ]);
return response () -> json ([ 'message' => 'Success' ], 200 );
} catch ( \Exception $e ) {
return response () -> json ([ 'message' => 'Oops! Please check the channel name and webhook endpoint URL. Slack responded with: ' . $e -> getMessage ()], 400 );
}
2018-02-22 16:35:34 -08:00
}
2020-09-15 23:05:27 -07:00
return response () -> json ([ 'message' => 'Something went wrong :( ' ], 400 );
2018-02-22 16:35:34 -08:00
}
2017-10-19 08:18:56 -07:00
/**
* Test the email configuration
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ since [ v3 . 0 ]
* @ return Redirect
*/
public function ajaxTestEmail ()
{
2021-06-10 13:15:52 -07:00
if ( ! config ( 'app.lock_passwords' )) {
2017-10-19 08:33:46 -07:00
try {
2018-03-02 18:01:20 -08:00
Notification :: send ( Setting :: first (), new MailTest ());
2021-06-10 13:15:52 -07:00
2017-11-03 14:58:49 -07:00
return response () -> json ([ 'message' => 'Mail sent to ' . config ( 'mail.reply_to.address' )], 200 );
2020-11-12 14:27:59 -08:00
} catch ( \Exception $e ) {
2017-10-19 08:33:46 -07:00
return response () -> json ([ 'message' => $e -> getMessage ()], 500 );
}
2017-10-19 08:18:56 -07:00
}
2021-06-10 13:15:52 -07:00
return response () -> json ([ 'message' => 'Mail would have been sent, but this application is in demo mode! ' ], 200 );
2017-10-19 08:18:56 -07:00
}
2020-10-05 20:34:17 -07:00
/**
* Delete server - cached barcodes
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ since [ v5 . 0.0 ]
* @ return Response
*/
public function purgeBarcodes ()
{
$file_count = 0 ;
$files = Storage :: disk ( 'public' ) -> files ( 'barcodes' );
foreach ( $files as $file ) { // iterate files
2021-06-10 13:15:52 -07:00
$file_parts = explode ( '.' , $file );
2020-10-05 20:34:17 -07:00
$extension = end ( $file_parts );
\Log :: debug ( $extension );
// Only generated barcodes would have a .png file extension
2021-06-10 13:15:52 -07:00
if ( $extension == 'png' ) {
2020-10-05 20:34:17 -07:00
\Log :: debug ( 'Deleting: ' . $file );
2021-06-10 13:15:52 -07:00
try {
2020-10-05 20:34:17 -07:00
Storage :: disk ( 'public' ) -> delete ( $file );
\Log :: debug ( 'Deleting: ' . $file );
$file_count ++ ;
} catch ( \Exception $e ) {
\Log :: debug ( $e );
}
}
}
return response () -> json ([ 'message' => 'Deleted ' . $file_count . ' barcodes' ], 200 );
}
2018-08-01 03:51:59 -07:00
/**
* Get a list of login attempts
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ since [ v5 . 0.0 ]
* @ param \Illuminate\Http\Request $request
* @ return array
*/
public function showLoginAttempts ( Request $request )
{
2021-06-10 13:15:52 -07:00
$allowed_columns = [ 'id' , 'username' , 'remote_ip' , 'user_agent' , 'successful' , 'created_at' ];
2018-08-01 03:51:59 -07:00
2021-06-10 13:15:52 -07:00
$login_attempts = DB :: table ( 'login_attempts' );
2018-08-01 03:51:59 -07:00
$order = $request -> input ( 'order' ) === 'asc' ? 'asc' : 'desc' ;
$sort = in_array ( $request -> get ( 'sort' ), $allowed_columns ) ? $request -> get ( 'sort' ) : 'created_at' ;
$total = $login_attempts -> count ();
$login_attempts -> orderBy ( $sort , $order );
2021-06-10 13:15:52 -07:00
$login_attempt_results = $login_attempts -> skip ( request ( 'offset' , 0 )) -> take ( request ( 'limit' , 20 )) -> get ();
2018-08-01 03:51:59 -07:00
return ( new LoginAttemptsTransformer ) -> transformLoginAttempts ( $login_attempt_results , $total );
}
2017-01-12 19:40:20 -08:00
}