Dan Brown

Cleaned tests up, Started LDAP tests, Created LDAP wrapper

...@@ -36,6 +36,14 @@ APP_URL=http://bookstack.dev ...@@ -36,6 +36,14 @@ APP_URL=http://bookstack.dev
36 # External services such as Gravatar 36 # External services such as Gravatar
37 DISABLE_EXTERNAL_SERVICES=false 37 DISABLE_EXTERNAL_SERVICES=false
38 38
39 +# LDAP Settings
40 +LDAP_SERVER=false
41 +LDAP_BASE_DN=false
42 +LDAP_DN=false
43 +LDAP_PASS=false
44 +LDAP_USER_FILTER=false
45 +LDAP_VERSION=false
46 +
39 # Mail settings 47 # Mail settings
40 MAIL_DRIVER=smtp 48 MAIL_DRIVER=smtp
41 MAIL_HOST=localhost 49 MAIL_HOST=localhost
......
...@@ -118,17 +118,20 @@ class AuthController extends Controller ...@@ -118,17 +118,20 @@ class AuthController extends Controller
118 */ 118 */
119 protected function authenticated(Request $request, Authenticatable $user) 119 protected function authenticated(Request $request, Authenticatable $user)
120 { 120 {
121 - if(!$user->exists && $user->email === null && !$request->has('email')) { 121 + // Explicitly log them out for now if they do no exist.
122 + if (!$user->exists) auth()->logout($user);
123 +
124 + if (!$user->exists && $user->email === null && !$request->has('email')) {
122 $request->flash(); 125 $request->flash();
123 session()->flash('request-email', true); 126 session()->flash('request-email', true);
124 return redirect('/login'); 127 return redirect('/login');
125 } 128 }
126 129
127 - if(!$user->exists && $user->email === null && $request->has('email')) { 130 + if (!$user->exists && $user->email === null && $request->has('email')) {
128 $user->email = $request->get('email'); 131 $user->email = $request->get('email');
129 } 132 }
130 133
131 - if(!$user->exists) { 134 + if (!$user->exists) {
132 $user->save(); 135 $user->save();
133 $this->userRepo->attachDefaultRole($user); 136 $this->userRepo->attachDefaultRole($user);
134 auth()->login($user); 137 auth()->login($user);
......
...@@ -38,6 +38,7 @@ class Authenticate ...@@ -38,6 +38,7 @@ class Authenticate
38 if(auth()->check() && auth()->user()->email_confirmed == false) { 38 if(auth()->check() && auth()->user()->email_confirmed == false) {
39 return redirect()->guest('/register/confirm/awaiting'); 39 return redirect()->guest('/register/confirm/awaiting');
40 } 40 }
41 +
41 if ($this->auth->guest() && !Setting::get('app-public')) { 42 if ($this->auth->guest() && !Setting::get('app-public')) {
42 if ($request->ajax()) { 43 if ($request->ajax()) {
43 return response('Unauthorized.', 401); 44 return response('Unauthorized.', 401);
......
1 <?php 1 <?php
2 2
3 -Route::get('/test', function() {
4 - // TODO - remove this
5 - $service = new \BookStack\Services\LdapService();
6 - dd($service->getUserDetails('ksmith'));
7 -});
8 -
9 // Authenticated routes... 3 // Authenticated routes...
10 Route::group(['middleware' => 'auth'], function () { 4 Route::group(['middleware' => 'auth'], function () {
11 5
......
...@@ -86,8 +86,10 @@ class LdapUserProvider implements UserProvider ...@@ -86,8 +86,10 @@ class LdapUserProvider implements UserProvider
86 */ 86 */
87 public function updateRememberToken(Authenticatable $user, $token) 87 public function updateRememberToken(Authenticatable $user, $token)
88 { 88 {
89 - $user->setRememberToken($token); 89 + if ($user->exists) {
90 - $user->save(); 90 + $user->setRememberToken($token);
91 + $user->save();
92 + }
91 } 93 }
92 94
93 /** 95 /**
...@@ -113,6 +115,7 @@ class LdapUserProvider implements UserProvider ...@@ -113,6 +115,7 @@ class LdapUserProvider implements UserProvider
113 $model->name = $userDetails['name']; 115 $model->name = $userDetails['name'];
114 $model->external_auth_id = $userDetails['uid']; 116 $model->external_auth_id = $userDetails['uid'];
115 $model->email = $userDetails['email']; 117 $model->email = $userDetails['email'];
118 + $model->email_confirmed = true;
116 return $model; 119 return $model;
117 } 120 }
118 121
......
1 +<?php namespace BookStack\Services;
2 +
3 +
4 +/**
5 + * Class Ldap
6 + * An object-orientated thin abstraction wrapper for common PHP LDAP functions.
7 + * Allows the standard LDAP functions to be mocked for testing.
8 + * @package BookStack\Services
9 + */
10 +class Ldap
11 +{
12 +
13 + /**
14 + * Connect to a LDAP server.
15 + * @param string $hostName
16 + * @param int $port
17 + * @return resource
18 + */
19 + public function connect($hostName, $port)
20 + {
21 + return ldap_connect($hostName, $port);
22 + }
23 +
24 + /**
25 + * Set the value of a LDAP option for the given connection.
26 + * @param resource $ldapConnection
27 + * @param int $option
28 + * @param mixed $value
29 + * @return bool
30 + */
31 + public function setOption($ldapConnection, $option, $value)
32 + {
33 + return ldap_set_option($ldapConnection, $option, $value);
34 + }
35 +
36 + /**
37 + * Search LDAP tree using the provided filter.
38 + * @param resource $ldapConnection
39 + * @param string $baseDn
40 + * @param string $filter
41 + * @param array|null $attributes
42 + * @return resource
43 + */
44 + public function search($ldapConnection, $baseDn, $filter, array $attributes = null)
45 + {
46 + return ldap_search($ldapConnection, $baseDn, $filter, $attributes);
47 + }
48 +
49 + /**
50 + * Get entries from an ldap search result.
51 + * @param resource $ldapConnection
52 + * @param resource $ldapSearchResult
53 + * @return array
54 + */
55 + public function getEntries($ldapConnection, $ldapSearchResult)
56 + {
57 + return ldap_get_entries($ldapConnection, $ldapSearchResult);
58 + }
59 +
60 + /**
61 + * Search and get entries immediately.
62 + * @param resource $ldapConnection
63 + * @param string $baseDn
64 + * @param string $filter
65 + * @param array|null $attributes
66 + * @return resource
67 + */
68 + public function searchAndGetEntries($ldapConnection, $baseDn, $filter, array $attributes = null)
69 + {
70 + $search = $this->search($ldapConnection, $baseDn, $filter, $attributes);
71 + return $this->getEntries($ldapConnection, $search);
72 + }
73 +
74 + /**
75 + * Bind to LDAP directory.
76 + * @param resource $ldapConnection
77 + * @param string $bindRdn
78 + * @param string $bindPassword
79 + * @return bool
80 + */
81 + public function bind($ldapConnection, $bindRdn = null, $bindPassword = null)
82 + {
83 + return ldap_bind($ldapConnection, $bindRdn, $bindPassword);
84 + }
85 +
86 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -4,10 +4,27 @@ ...@@ -4,10 +4,27 @@
4 use BookStack\Exceptions\LdapException; 4 use BookStack\Exceptions\LdapException;
5 use Illuminate\Contracts\Auth\Authenticatable; 5 use Illuminate\Contracts\Auth\Authenticatable;
6 6
7 +/**
8 + * Class LdapService
9 + * Handles any app-specific LDAP tasks.
10 + * @package BookStack\Services
11 + */
7 class LdapService 12 class LdapService
8 { 13 {
9 14
15 + protected $ldap;
10 protected $ldapConnection; 16 protected $ldapConnection;
17 + protected $config;
18 +
19 + /**
20 + * LdapService constructor.
21 + * @param Ldap $ldap
22 + */
23 + public function __construct(Ldap $ldap)
24 + {
25 + $this->ldap = $ldap;
26 + $this->config = config('services.ldap');
27 + }
11 28
12 /** 29 /**
13 * Get the details of a user from LDAP using the given username. 30 * Get the details of a user from LDAP using the given username.
...@@ -21,17 +38,16 @@ class LdapService ...@@ -21,17 +38,16 @@ class LdapService
21 $ldapConnection = $this->getConnection(); 38 $ldapConnection = $this->getConnection();
22 39
23 // Find user 40 // Find user
24 - $userFilter = $this->buildFilter(config('services.ldap.user_filter'), ['user' => $userName]); 41 + $userFilter = $this->buildFilter($this->config['user_filter'], ['user' => $userName]);
25 - $baseDn = config('services.ldap.base_dn'); 42 + $baseDn = $this->config['base_dn'];
26 - $ldapSearch = ldap_search($ldapConnection, $baseDn, $userFilter, ['cn', 'uid', 'dn', 'mail']); 43 + $users = $this->ldap->searchAndGetEntries($ldapConnection, $baseDn, $userFilter, ['cn', 'uid', 'dn', 'mail']);
27 - $users = ldap_get_entries($ldapConnection, $ldapSearch);
28 if ($users['count'] === 0) return null; 44 if ($users['count'] === 0) return null;
29 45
30 $user = $users[0]; 46 $user = $users[0];
31 return [ 47 return [
32 - 'uid' => $user['uid'][0], 48 + 'uid' => $user['uid'][0],
33 - 'name' => $user['cn'][0], 49 + 'name' => $user['cn'][0],
34 - 'dn' => $user['dn'], 50 + 'dn' => $user['dn'],
35 'email' => (isset($user['mail'])) ? $user['mail'][0] : null 51 'email' => (isset($user['mail'])) ? $user['mail'][0] : null
36 ]; 52 ];
37 } 53 }
...@@ -50,7 +66,12 @@ class LdapService ...@@ -50,7 +66,12 @@ class LdapService
50 if ($ldapUser['uid'] !== $user->external_auth_id) return false; 66 if ($ldapUser['uid'] !== $user->external_auth_id) return false;
51 67
52 $ldapConnection = $this->getConnection(); 68 $ldapConnection = $this->getConnection();
53 - $ldapBind = @ldap_bind($ldapConnection, $ldapUser['dn'], $password); 69 + try {
70 + $ldapBind = $this->ldap->bind($ldapConnection, $ldapUser['dn'], $password);
71 + } catch (\ErrorException $e) {
72 + $ldapBind = false;
73 + }
74 +
54 return $ldapBind; 75 return $ldapBind;
55 } 76 }
56 77
...@@ -62,14 +83,14 @@ class LdapService ...@@ -62,14 +83,14 @@ class LdapService
62 */ 83 */
63 protected function bindSystemUser($connection) 84 protected function bindSystemUser($connection)
64 { 85 {
65 - $ldapDn = config('services.ldap.dn'); 86 + $ldapDn = $this->config['dn'];
66 - $ldapPass = config('services.ldap.pass'); 87 + $ldapPass = $this->config['pass'];
67 88
68 $isAnonymous = ($ldapDn === false || $ldapPass === false); 89 $isAnonymous = ($ldapDn === false || $ldapPass === false);
69 if ($isAnonymous) { 90 if ($isAnonymous) {
70 - $ldapBind = ldap_bind($connection); 91 + $ldapBind = $this->ldap->bind($connection);
71 } else { 92 } else {
72 - $ldapBind = ldap_bind($connection, $ldapDn, $ldapPass); 93 + $ldapBind = $this->ldap->bind($connection, $ldapDn, $ldapPass);
73 } 94 }
74 95
75 if (!$ldapBind) throw new LdapException('LDAP access failed using ' . $isAnonymous ? ' anonymous bind.' : ' given dn & pass details'); 96 if (!$ldapBind) throw new LdapException('LDAP access failed using ' . $isAnonymous ? ' anonymous bind.' : ' given dn & pass details');
...@@ -86,20 +107,22 @@ class LdapService ...@@ -86,20 +107,22 @@ class LdapService
86 if ($this->ldapConnection !== null) return $this->ldapConnection; 107 if ($this->ldapConnection !== null) return $this->ldapConnection;
87 108
88 // Check LDAP extension in installed 109 // Check LDAP extension in installed
89 - if (!function_exists('ldap_connect')) { 110 + if (!function_exists('ldap_connect') && config('app.env') !== 'testing') {
90 throw new LdapException('LDAP PHP extension not installed'); 111 throw new LdapException('LDAP PHP extension not installed');
91 } 112 }
92 113
93 // Get port from server string if specified. 114 // Get port from server string if specified.
94 - $ldapServer = explode(':', config('services.ldap.server')); 115 + $ldapServer = explode(':', $this->config['server']);
95 - $ldapConnection = ldap_connect($ldapServer[0], count($ldapServer) > 1 ? $ldapServer[1] : 389); 116 + $ldapConnection = $this->ldap->connect($ldapServer[0], count($ldapServer) > 1 ? $ldapServer[1] : 389);
96 117
97 if ($ldapConnection === false) { 118 if ($ldapConnection === false) {
98 throw new LdapException('Cannot connect to ldap server, Initial connection failed'); 119 throw new LdapException('Cannot connect to ldap server, Initial connection failed');
99 } 120 }
100 121
101 // Set any required options 122 // Set any required options
102 - ldap_set_option($ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3); // TODO - make configurable 123 + if ($this->config['version']) {
124 + $this->ldap->setOption($ldapConnection, LDAP_OPT_PROTOCOL_VERSION, $this->config['version']);
125 + }
103 126
104 $this->ldapConnection = $ldapConnection; 127 $this->ldapConnection = $ldapConnection;
105 return $this->ldapConnection; 128 return $this->ldapConnection;
...@@ -107,7 +130,7 @@ class LdapService ...@@ -107,7 +130,7 @@ class LdapService
107 130
108 /** 131 /**
109 * Build a filter string by injecting common variables. 132 * Build a filter string by injecting common variables.
110 - * @param $filterString 133 + * @param string $filterString
111 * @param array $attrs 134 * @param array $attrs
112 * @return string 135 * @return string
113 */ 136 */
......
...@@ -54,7 +54,8 @@ return [ ...@@ -54,7 +54,8 @@ return [
54 'dn' => env('LDAP_DN', false), 54 'dn' => env('LDAP_DN', false),
55 'pass' => env('LDAP_PASS', false), 55 'pass' => env('LDAP_PASS', false),
56 'base_dn' => env('LDAP_BASE_DN', false), 56 'base_dn' => env('LDAP_BASE_DN', false),
57 - 'user_filter' => env('LDAP_USER_FILTER', '(&(uid=${user}))') 57 + 'user_filter' => env('LDAP_USER_FILTER', '(&(uid=${user}))'),
58 + 'version' => env('LDAP_VERSION', false)
58 ] 59 ]
59 60
60 ]; 61 ];
......
...@@ -5,19 +5,19 @@ ...@@ -5,19 +5,19 @@
5 5
6 <!-- Meta --> 6 <!-- Meta -->
7 <meta name="viewport" content="width=device-width"> 7 <meta name="viewport" content="width=device-width">
8 + <meta name="token" content="{{ csrf_token() }}">
8 <meta charset="utf-8"> 9 <meta charset="utf-8">
9 10
10 <!-- Styles and Fonts --> 11 <!-- Styles and Fonts -->
11 <link rel="stylesheet" href="{{ versioned_asset('css/styles.css') }}"> 12 <link rel="stylesheet" href="{{ versioned_asset('css/styles.css') }}">
12 <link rel="stylesheet" media="print" href="{{ versioned_asset('css/print-styles.css') }}"> 13 <link rel="stylesheet" media="print" href="{{ versioned_asset('css/print-styles.css') }}">
13 - <link href='//fonts.googleapis.com/css?family=Roboto:400,400italic,500,500italic,700,700italic,300italic,100,300' rel='stylesheet' type='text/css'>
14 <link rel="stylesheet" href="/libs/material-design-iconic-font/css/material-design-iconic-font.min.css"> 14 <link rel="stylesheet" href="/libs/material-design-iconic-font/css/material-design-iconic-font.min.css">
15 15
16 <!-- Scripts --> 16 <!-- Scripts -->
17 - <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> 17 + <script src="/libs/jquery/jquery.min.js?version=2.1.4"></script>
18 18
19 </head> 19 </head>
20 -<body class="@yield('body-class')" id="app"> 20 +<body class="@yield('body-class')" ng-app="bookStack">
21 21
22 @include('partials/notifications') 22 @include('partials/notifications')
23 23
...@@ -37,13 +37,16 @@ ...@@ -37,13 +37,16 @@
37 @yield('header-buttons') 37 @yield('header-buttons')
38 </div> 38 </div>
39 @if(isset($signedIn) && $signedIn) 39 @if(isset($signedIn) && $signedIn)
40 - <img class="avatar" src="{{$currentUser->getAvatar(30)}}" alt="{{ $currentUser->name }}"> 40 + <div class="dropdown-container" dropdown>
41 - <div class="dropdown-container" data-dropdown> 41 + <span class="user-name" dropdown-toggle>
42 - <span class="user-name" data-dropdown-toggle> 42 + <img class="avatar" src="{{$currentUser->getAvatar(30)}}" alt="{{ $currentUser->name }}">
43 - {{ $currentUser->name }} <i class="zmdi zmdi-caret-down"></i> 43 + <span class="name" ng-non-bindable>{{ $currentUser->name }}</span> <i class="zmdi zmdi-caret-down"></i>
44 </span> 44 </span>
45 <ul> 45 <ul>
46 <li> 46 <li>
47 + <a href="/users/{{$currentUser->id}}" class="text-primary"><i class="zmdi zmdi-edit zmdi-hc-lg"></i>Edit Profile</a>
48 + </li>
49 + <li>
47 <a href="/logout" class="text-neg"><i class="zmdi zmdi-run zmdi-hc-lg"></i>Logout</a> 50 <a href="/logout" class="text-neg"><i class="zmdi zmdi-run zmdi-hc-lg"></i>Logout</a>
48 </li> 51 </li>
49 </ul> 52 </ul>
......
...@@ -7,7 +7,7 @@ use Illuminate\Foundation\Testing\DatabaseTransactions; ...@@ -7,7 +7,7 @@ use Illuminate\Foundation\Testing\DatabaseTransactions;
7 class ActivityTrackingTest extends TestCase 7 class ActivityTrackingTest extends TestCase
8 { 8 {
9 9
10 - public function testRecentlyViewedBooks() 10 + public function test_recently_viewed_books()
11 { 11 {
12 $books = \BookStack\Book::all()->take(10); 12 $books = \BookStack\Book::all()->take(10);
13 13
...@@ -21,7 +21,7 @@ class ActivityTrackingTest extends TestCase ...@@ -21,7 +21,7 @@ class ActivityTrackingTest extends TestCase
21 ->seeInElement('#recents', $books[1]->name); 21 ->seeInElement('#recents', $books[1]->name);
22 } 22 }
23 23
24 - public function testPopularBooks() 24 + public function test_popular_books()
25 { 25 {
26 $books = \BookStack\Book::all()->take(10); 26 $books = \BookStack\Book::all()->take(10);
27 27
......
...@@ -5,23 +5,19 @@ use BookStack\EmailConfirmation; ...@@ -5,23 +5,19 @@ use BookStack\EmailConfirmation;
5 class AuthTest extends TestCase 5 class AuthTest extends TestCase
6 { 6 {
7 7
8 - public function testAuthWorking() 8 + public function test_auth_working()
9 { 9 {
10 $this->visit('/') 10 $this->visit('/')
11 ->seePageIs('/login'); 11 ->seePageIs('/login');
12 } 12 }
13 13
14 - public function testLogin() 14 + public function test_login()
15 { 15 {
16 - $this->visit('/')
17 - ->seePageIs('/login');
18 -
19 $this->login('admin@admin.com', 'password') 16 $this->login('admin@admin.com', 'password')
20 - ->seePageIs('/') 17 + ->seePageIs('/');
21 - ->see('BookStack');
22 } 18 }
23 19
24 - public function testPublicViewing() 20 + public function test_public_viewing()
25 { 21 {
26 $settings = app('BookStack\Services\SettingService'); 22 $settings = app('BookStack\Services\SettingService');
27 $settings->put('app-public', 'true'); 23 $settings->put('app-public', 'true');
...@@ -30,7 +26,7 @@ class AuthTest extends TestCase ...@@ -30,7 +26,7 @@ class AuthTest extends TestCase
30 ->see('Sign In'); 26 ->see('Sign In');
31 } 27 }
32 28
33 - public function testRegistrationShowing() 29 + public function test_registration_showing()
34 { 30 {
35 // Ensure registration form is showing 31 // Ensure registration form is showing
36 $this->setSettings(['registration-enabled' => 'true']); 32 $this->setSettings(['registration-enabled' => 'true']);
...@@ -40,7 +36,7 @@ class AuthTest extends TestCase ...@@ -40,7 +36,7 @@ class AuthTest extends TestCase
40 ->seePageIs('/register'); 36 ->seePageIs('/register');
41 } 37 }
42 38
43 - public function testNormalRegistration() 39 + public function test_normal_registration()
44 { 40 {
45 // Set settings and get user instance 41 // Set settings and get user instance
46 $this->setSettings(['registration-enabled' => 'true']); 42 $this->setSettings(['registration-enabled' => 'true']);
...@@ -58,7 +54,8 @@ class AuthTest extends TestCase ...@@ -58,7 +54,8 @@ class AuthTest extends TestCase
58 ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email]); 54 ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email]);
59 } 55 }
60 56
61 - public function testConfirmedRegistration() 57 +
58 + public function test_confirmed_registration()
62 { 59 {
63 // Set settings and get user instance 60 // Set settings and get user instance
64 $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true']); 61 $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true']);
...@@ -102,7 +99,32 @@ class AuthTest extends TestCase ...@@ -102,7 +99,32 @@ class AuthTest extends TestCase
102 ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => true]); 99 ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => true]);
103 } 100 }
104 101
105 - public function testUserCreation() 102 + public function test_restricted_registration()
103 + {
104 + $this->setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true', 'registration-restrict' => 'example.com']);
105 + $user = factory(\BookStack\User::class)->make();
106 + // Go through registration process
107 + $this->visit('/register')
108 + ->type($user->name, '#name')
109 + ->type($user->email, '#email')
110 + ->type($user->password, '#password')
111 + ->press('Create Account')
112 + ->seePageIs('/register')
113 + ->dontSeeInDatabase('users', ['email' => $user->email])
114 + ->see('That email domain does not have access to this application');
115 +
116 + $user->email = 'barry@example.com';
117 +
118 + $this->visit('/register')
119 + ->type($user->name, '#name')
120 + ->type($user->email, '#email')
121 + ->type($user->password, '#password')
122 + ->press('Create Account')
123 + ->seePageIs('/register/confirm')
124 + ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => false]);
125 + }
126 +
127 + public function test_user_creation()
106 { 128 {
107 $user = factory(\BookStack\User::class)->make(); 129 $user = factory(\BookStack\User::class)->make();
108 130
...@@ -120,7 +142,7 @@ class AuthTest extends TestCase ...@@ -120,7 +142,7 @@ class AuthTest extends TestCase
120 ->see($user->name); 142 ->see($user->name);
121 } 143 }
122 144
123 - public function testUserUpdating() 145 + public function test_user_updating()
124 { 146 {
125 $user = \BookStack\User::all()->last(); 147 $user = \BookStack\User::all()->last();
126 $password = $user->password; 148 $password = $user->password;
...@@ -136,7 +158,7 @@ class AuthTest extends TestCase ...@@ -136,7 +158,7 @@ class AuthTest extends TestCase
136 ->notSeeInDatabase('users', ['name' => $user->name]); 158 ->notSeeInDatabase('users', ['name' => $user->name]);
137 } 159 }
138 160
139 - public function testUserPasswordUpdate() 161 + public function test_user_password_update()
140 { 162 {
141 $user = \BookStack\User::all()->last(); 163 $user = \BookStack\User::all()->last();
142 $userProfilePage = '/users/' . $user->id; 164 $userProfilePage = '/users/' . $user->id;
...@@ -156,7 +178,7 @@ class AuthTest extends TestCase ...@@ -156,7 +178,7 @@ class AuthTest extends TestCase
156 $this->assertTrue(Hash::check('newpassword', $userPassword)); 178 $this->assertTrue(Hash::check('newpassword', $userPassword));
157 } 179 }
158 180
159 - public function testUserDeletion() 181 + public function test_user_deletion()
160 { 182 {
161 $userDetails = factory(\BookStack\User::class)->make(); 183 $userDetails = factory(\BookStack\User::class)->make();
162 $user = $this->getNewUser($userDetails->toArray()); 184 $user = $this->getNewUser($userDetails->toArray());
...@@ -170,7 +192,7 @@ class AuthTest extends TestCase ...@@ -170,7 +192,7 @@ class AuthTest extends TestCase
170 ->notSeeInDatabase('users', ['name' => $user->name]); 192 ->notSeeInDatabase('users', ['name' => $user->name]);
171 } 193 }
172 194
173 - public function testUserCannotBeDeletedIfLastAdmin() 195 + public function test_user_cannot_be_deleted_if_last_admin()
174 { 196 {
175 $adminRole = \BookStack\Role::getRole('admin'); 197 $adminRole = \BookStack\Role::getRole('admin');
176 // Ensure we currently only have 1 admin user 198 // Ensure we currently only have 1 admin user
...@@ -184,7 +206,7 @@ class AuthTest extends TestCase ...@@ -184,7 +206,7 @@ class AuthTest extends TestCase
184 ->see('You cannot delete the only admin'); 206 ->see('You cannot delete the only admin');
185 } 207 }
186 208
187 - public function testLogout() 209 + public function test_logout()
188 { 210 {
189 $this->asAdmin() 211 $this->asAdmin()
190 ->visit('/') 212 ->visit('/')
...@@ -200,7 +222,7 @@ class AuthTest extends TestCase ...@@ -200,7 +222,7 @@ class AuthTest extends TestCase
200 * @param string $password 222 * @param string $password
201 * @return $this 223 * @return $this
202 */ 224 */
203 - private function login($email, $password) 225 + protected function login($email, $password)
204 { 226 {
205 return $this->visit('/login') 227 return $this->visit('/login')
206 ->type($email, '#email') 228 ->type($email, '#email')
......
1 +<?php
2 +
3 +use BookStack\Services\LdapService;
4 +use BookStack\User;
5 +
6 +class LdapTest extends \TestCase
7 +{
8 +
9 + protected $mockLdap;
10 + protected $mockUser;
11 + protected $resourceId = 'resource-test';
12 +
13 + public function setUp()
14 + {
15 + parent::setUp();
16 + app('config')->set(['auth.method' => 'ldap', 'services.ldap.base_dn' => 'dc=ldap,dc=local', 'auth.providers.users.driver' => 'ldap']);
17 + $this->mockLdap = Mockery::mock(BookStack\Services\Ldap::class);
18 + $this->app['BookStack\Services\Ldap'] = $this->mockLdap;
19 + $this->mockUser = factory(User::class)->make();
20 + }
21 +
22 + public function test_ldap_login()
23 + {
24 + $this->mockLdap->shouldReceive('connect')->once()->andReturn($this->resourceId);
25 + $this->mockLdap->shouldReceive('setOption')->once();
26 + $this->mockLdap->shouldReceive('searchAndGetEntries')->twice()
27 + ->with($this->resourceId, config('services.ldap.base_dn'), Mockery::type('string'), Mockery::type('array'))
28 + ->andReturn(['count' => 1, 0 => [
29 + 'uid' => [$this->mockUser->name],
30 + 'cn' => [$this->mockUser->name],
31 + 'dn' => ['dc=test'.config('services.ldap.base_dn')]
32 + ]]);
33 + $this->mockLdap->shouldReceive('bind')->times(1)->andReturn(true);
34 +
35 + $this->visit('/login')
36 + ->see('Username')
37 + ->type($this->mockUser->name, '#username')
38 + ->type($this->mockUser->password, '#password')
39 + ->press('Sign In')
40 + ->seePageIs('/login')->see('Please enter an email to use for this account.');
41 + }
42 +
43 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
3 class SocialAuthTest extends TestCase 3 class SocialAuthTest extends TestCase
4 { 4 {
5 5
6 - public function testSocialRegistration() 6 + public function test_social_registration()
7 { 7 {
8 // http://docs.mockery.io/en/latest/reference/startup_methods.html 8 // http://docs.mockery.io/en/latest/reference/startup_methods.html
9 $user = factory(\BookStack\User::class)->make(); 9 $user = factory(\BookStack\User::class)->make();
10 10
11 $this->setSettings(['registration-enabled' => 'true']); 11 $this->setSettings(['registration-enabled' => 'true']);
12 - $this->setEnvironment(['GOOGLE_APP_ID' => 'abc123', 'GOOGLE_APP_SECRET' => '123abc', 'APP_URL' => 'http://localhost']); 12 + config(['GOOGLE_APP_ID' => 'abc123', 'GOOGLE_APP_SECRET' => '123abc', 'APP_URL' => 'http://localhost']);
13 13
14 $mockSocialite = Mockery::mock('Laravel\Socialite\Contracts\Factory'); 14 $mockSocialite = Mockery::mock('Laravel\Socialite\Contracts\Factory');
15 $this->app['Laravel\Socialite\Contracts\Factory'] = $mockSocialite; 15 $this->app['Laravel\Socialite\Contracts\Factory'] = $mockSocialite;
...@@ -32,11 +32,4 @@ class SocialAuthTest extends TestCase ...@@ -32,11 +32,4 @@ class SocialAuthTest extends TestCase
32 $this->seeInDatabase('social_accounts', ['user_id' => $user->id]); 32 $this->seeInDatabase('social_accounts', ['user_id' => $user->id]);
33 } 33 }
34 34
35 - protected function setEnvironment($array)
36 - {
37 - foreach ($array as $key => $value) {
38 - putenv("$key=$value");
39 - }
40 - }
41 -
42 } 35 }
......
...@@ -5,7 +5,7 @@ use Illuminate\Support\Facades\DB; ...@@ -5,7 +5,7 @@ use Illuminate\Support\Facades\DB;
5 class EntityTest extends TestCase 5 class EntityTest extends TestCase
6 { 6 {
7 7
8 - public function testEntityCreation() 8 + public function test_entity_creation()
9 { 9 {
10 10
11 // Test Creation 11 // Test Creation
...@@ -51,7 +51,7 @@ class EntityTest extends TestCase ...@@ -51,7 +51,7 @@ class EntityTest extends TestCase
51 return \BookStack\Book::find($book->id); 51 return \BookStack\Book::find($book->id);
52 } 52 }
53 53
54 - public function testBookSortPageShows() 54 + public function test_book_sort_page_shows()
55 { 55 {
56 $books = \BookStack\Book::all(); 56 $books = \BookStack\Book::all();
57 $bookToSort = $books[0]; 57 $bookToSort = $books[0];
...@@ -65,7 +65,7 @@ class EntityTest extends TestCase ...@@ -65,7 +65,7 @@ class EntityTest extends TestCase
65 ->see($books[1]->name); 65 ->see($books[1]->name);
66 } 66 }
67 67
68 - public function testBookSortItemReturnsBookContent() 68 + public function test_book_sort_item_returns_book_content()
69 { 69 {
70 $books = \BookStack\Book::all(); 70 $books = \BookStack\Book::all();
71 $bookToSort = $books[0]; 71 $bookToSort = $books[0];
...@@ -155,7 +155,7 @@ class EntityTest extends TestCase ...@@ -155,7 +155,7 @@ class EntityTest extends TestCase
155 return $book; 155 return $book;
156 } 156 }
157 157
158 - public function testPageSearch() 158 + public function test_page_search()
159 { 159 {
160 $book = \BookStack\Book::all()->first(); 160 $book = \BookStack\Book::all()->first();
161 $page = $book->pages->first(); 161 $page = $book->pages->first();
...@@ -170,7 +170,7 @@ class EntityTest extends TestCase ...@@ -170,7 +170,7 @@ class EntityTest extends TestCase
170 ->seePageIs($page->getUrl()); 170 ->seePageIs($page->getUrl());
171 } 171 }
172 172
173 - public function testInvalidPageSearch() 173 + public function test_invalid_page_search()
174 { 174 {
175 $this->asAdmin() 175 $this->asAdmin()
176 ->visit('/') 176 ->visit('/')
...@@ -180,7 +180,7 @@ class EntityTest extends TestCase ...@@ -180,7 +180,7 @@ class EntityTest extends TestCase
180 ->seeStatusCode(200); 180 ->seeStatusCode(200);
181 } 181 }
182 182
183 - public function testEmptySearchRedirectsBack() 183 + public function test_empty_search_redirects_back()
184 { 184 {
185 $this->asAdmin() 185 $this->asAdmin()
186 ->visit('/') 186 ->visit('/')
...@@ -188,7 +188,7 @@ class EntityTest extends TestCase ...@@ -188,7 +188,7 @@ class EntityTest extends TestCase
188 ->seePageIs('/'); 188 ->seePageIs('/');
189 } 189 }
190 190
191 - public function testBookSearch() 191 + public function test_book_search()
192 { 192 {
193 $book = \BookStack\Book::all()->first(); 193 $book = \BookStack\Book::all()->first();
194 $page = $book->pages->last(); 194 $page = $book->pages->last();
...@@ -202,7 +202,7 @@ class EntityTest extends TestCase ...@@ -202,7 +202,7 @@ class EntityTest extends TestCase
202 ->see($chapter->name); 202 ->see($chapter->name);
203 } 203 }
204 204
205 - public function testEmptyBookSearchRedirectsBack() 205 + public function test_empty_book_search_redirects_back()
206 { 206 {
207 $book = \BookStack\Book::all()->first(); 207 $book = \BookStack\Book::all()->first();
208 $this->asAdmin() 208 $this->asAdmin()
...@@ -212,7 +212,7 @@ class EntityTest extends TestCase ...@@ -212,7 +212,7 @@ class EntityTest extends TestCase
212 } 212 }
213 213
214 214
215 - public function testEntitiesViewableAfterCreatorDeletion() 215 + public function test_entities_viewable_after_creator_deletion()
216 { 216 {
217 // Create required assets and revisions 217 // Create required assets and revisions
218 $creator = $this->getNewUser(); 218 $creator = $this->getNewUser();
...@@ -225,7 +225,7 @@ class EntityTest extends TestCase ...@@ -225,7 +225,7 @@ class EntityTest extends TestCase
225 $this->checkEntitiesViewable($entities); 225 $this->checkEntitiesViewable($entities);
226 } 226 }
227 227
228 - public function testEntitiesViewableAfterUpdaterDeletion() 228 + public function test_entities_viewable_after_updater_deletion()
229 { 229 {
230 // Create required assets and revisions 230 // Create required assets and revisions
231 $creator = $this->getNewUser(); 231 $creator = $this->getNewUser();
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
3 class PublicViewTest extends TestCase 3 class PublicViewTest extends TestCase
4 { 4 {
5 5
6 - public function testBooksViewable() 6 + public function test_books_viewable()
7 { 7 {
8 $this->setSettings(['app-public' => 'true']); 8 $this->setSettings(['app-public' => 'true']);
9 $books = \BookStack\Book::orderBy('name', 'asc')->take(10)->get(); 9 $books = \BookStack\Book::orderBy('name', 'asc')->take(10)->get();
...@@ -13,14 +13,14 @@ class PublicViewTest extends TestCase ...@@ -13,14 +13,14 @@ class PublicViewTest extends TestCase
13 $this->visit('/books') 13 $this->visit('/books')
14 ->seeStatusCode(200) 14 ->seeStatusCode(200)
15 ->see($books[0]->name) 15 ->see($books[0]->name)
16 - // Check indavidual book page is showing and it's child contents are visible. 16 + // Check individual book page is showing and it's child contents are visible.
17 ->click($bookToVisit->name) 17 ->click($bookToVisit->name)
18 ->seePageIs($bookToVisit->getUrl()) 18 ->seePageIs($bookToVisit->getUrl())
19 ->see($bookToVisit->name) 19 ->see($bookToVisit->name)
20 ->see($bookToVisit->chapters()->first()->name); 20 ->see($bookToVisit->chapters()->first()->name);
21 } 21 }
22 22
23 - public function testChaptersViewable() 23 + public function test_chapters_viewable()
24 { 24 {
25 $this->setSettings(['app-public' => 'true']); 25 $this->setSettings(['app-public' => 'true']);
26 $chapterToVisit = \BookStack\Chapter::first(); 26 $chapterToVisit = \BookStack\Chapter::first();
...@@ -30,7 +30,7 @@ class PublicViewTest extends TestCase ...@@ -30,7 +30,7 @@ class PublicViewTest extends TestCase
30 $this->visit($chapterToVisit->getUrl()) 30 $this->visit($chapterToVisit->getUrl())
31 ->seeStatusCode(200) 31 ->seeStatusCode(200)
32 ->see($chapterToVisit->name) 32 ->see($chapterToVisit->name)
33 - // Check indavidual chapter page is showing and it's child contents are visible. 33 + // Check individual chapter page is showing and it's child contents are visible.
34 ->see($pageToVisit->name) 34 ->see($pageToVisit->name)
35 ->click($pageToVisit->name) 35 ->click($pageToVisit->name)
36 ->see($chapterToVisit->book->name) 36 ->see($chapterToVisit->book->name)
......