1
0
mirror of https://github.com/cydrobolt/polr.git synced 2024-11-09 11:42:28 +01:00

Merge branch 'master' of https://github.com/ashazar/polr into ashazar-master

This commit is contained in:
Chaoyi Zha 2016-10-11 22:48:09 -04:00
commit d52e78f475
10 changed files with 279 additions and 14 deletions

View File

@ -4,9 +4,10 @@ namespace App\Factories;
use Hash;
use App\Models\User;
use App\Helpers\CryptoHelper;
use App\Helpers\UserHelper;
class UserFactory {
public static function createUser($username, $email, $password, $active=0, $ip='127.0.0.1', $api_key=false, $api_active=0) {
public static function createUser($username, $email, $password, $active=0, $ip='127.0.0.1', $api_key=false, $api_active=0, $role='') {
$hashed_password = Hash::make($password);
$recovery_key = CryptoHelper::generateRandomHex(50);
@ -17,6 +18,8 @@ class UserFactory {
$user->recovery_key = $recovery_key;
$user->active = $active;
$user->ip = $ip;
$role = ($role == '') ? UserHelper::UserRole('DEFAULT') : $role;
$user->role = $role;
$user->api_key = $api_key;
$user->api_active = $api_active;

View File

@ -105,4 +105,16 @@ class UserHelper {
return self::getUserBy('email', $email, $inactive);
}
public static function getUserRoles() { // Return Array: list of user roles
return array(
'ADMIN' => 'admin',
'DEFAULT' => '',
);
}
public static function UserRole($role) {
$userRoles = self::getUserRoles();
return $userRoles[$role];
}
}

View File

@ -31,6 +31,8 @@ class AdminController extends Controller {
return view('admin', [
'role' => $role,
'admin_role' => UserHelper::UserRole('ADMIN'),
'user_roles' => UserHelper::getUserRoles(),
'api_key' => $user->api_key,
'api_active' => $user->api_active,
'api_quota' => $user->api_quota,

View File

@ -5,6 +5,7 @@ use Yajra\Datatables\Facades\Datatables;
use App\Models\Link;
use App\Models\User;
use App\Helpers\UserHelper;
class AdminPaginationController extends Controller {
/**
@ -16,15 +17,48 @@ class AdminPaginationController extends Controller {
public function paginateAdminUsers(Request $request) {
self::ensureAdmin();
$admin_users = User::select(['username', 'email', 'created_at', 'active', 'api_key', 'api_active', 'api_quota', 'id']);
$admin_users = User::select(['username', 'email', 'created_at', 'active', 'api_key', 'api_active', 'api_quota', 'role', 'id']);
return Datatables::of($admin_users)
->addColumn('api_action', function ($user) {
// Add "API Info" action button
return '<a class="activate-api-modal btn btn-sm btn-info"
ng-click="openAPIModal($event, \'' . $user->username . '\', \'' . $user->api_key . '\', \'' . $user->api_active . '\', \'' . $user->api_quota . '\', \'' . $user->id . '\')">
ng-click="openAPIModal($event, \'' . $user->username . '\', \'' . $user->id . '\')" id="api_info_btn_' . $user->id . '" data-api-active="' . $user->api_active . '" data-api-key="' . $user->api_key . '" data-api-quota="' . $user->api_quota . '">
API info
</a>';
})
->addColumn('toggle_active', function ($user) {
// Toggle User Active status
$btn_class = '';
if (session('username') == $user->username) {
$btn_class = ' disabled';
}
if ($user->active) {
$active_text = 'Active';
$btn_color_class = ' btn-success';
}
else {
$active_text = 'Inactive';
$btn_color_class = ' btn-danger';
}
return '<a class="btn btn-sm status-display' . $btn_color_class . $btn_class . '" ng-click="toggleUserActiveStatus($event)" '
. 'data-user-id="' . $user->id . '">' . $active_text . '</a>';
})
->addColumn('change_role', function ($user) {
// Add "Change Role" Select Box
if (session('username') == $user->username) {
return 'ADMIN';
}
$selectrole = '<select onchange="changeUserRole($(this));" id="user_roles" data-user-id=\'' . $user->id . '\' style="width: 100%; height: 85%;">';
foreach (UserHelper::getUserRoles() as $role_text => $role_val) {
$selectrole .= '<option value="' . $role_val . '"';
if ($user->role == $role_val) $selectrole .= ' selected';
$selectrole .= '>' . $role_text . '</option>';
}
$selectrole .= '</select>';
return $selectrole;
})
->addColumn('delete', function ($user) {
// Add "Delete" action button
$btn_class = '';

View File

@ -6,6 +6,7 @@ use App\Helpers\LinkHelper;
use App\Helpers\CryptoHelper;
use App\Helpers\UserHelper;
use App\Models\User;
use App\Factories\UserFactory;
class AjaxController extends Controller {
/**
@ -116,6 +117,61 @@ class AjaxController extends Controller {
return "OK";
}
public function toggleUserActive(Request $request) {
self::ensureAdmin();
$user_id = $request->input('user_id');
$user = UserHelper::getUserById($user_id, true);
if (!$user) {
abort(404, 'User not found.');
}
$current_status = $user->active;
if ($current_status == 1) {
$new_status = 0;
}
else {
$new_status = 1;
}
$user->active = $new_status;
$user->save();
return $user->active;
}
public function changeUserRole(Request $request) {
self::ensureAdmin();
$user_id = $request->input('user_id');
$role = $request->input('role');
$user = UserHelper::getUserById($user_id, true);
if (!$user) {
abort(404, 'User not found.');
}
$user->role = $role;
$user->save();
return "OK";
}
public function addNewUser(Request $request) {
self::ensureAdmin();
$ip = $request->ip();
$user_name = $request->input('user_name');
$user_password = $request->input('user_password');
$user_email = $request->input('user_email');
$user_role = $request->input('user_role');
UserFactory::createUser($user_name, $user_email, $user_password, 1, $ip, false, 0, $user_role);
return "OK";
}
public function deleteUser(Request $request) {
self::ensureAdmin();

View File

@ -6,6 +6,7 @@ use Illuminate\Support\Facades\Artisan;
use App\Helpers\CryptoHelper;
use App\Models\User;
use App\Helpers\UserHelper;
use App\Factories\UserFactory;
use Cache;
@ -97,7 +98,7 @@ class SetupController extends Controller {
$acct_username = $request->input('acct:username');
$acct_email = $request->input('acct:email');
$acct_password = $request->input('acct:password');
$acct_group = "admin";
$acct_group = UserHelper::UserRole('ADMIN');
// if true, only logged in users can shorten
$st_shorten_permission = $request->input('setting:shorten_permission');
@ -214,9 +215,7 @@ class SetupController extends Controller {
return redirect(route('setup'))->with('error', 'Could not create database. Perhaps some credentials were incorrect?');
}
$user = UserFactory::createUser($setup_finish_args->acct_username, $setup_finish_args->acct_email, $setup_finish_args->acct_password, 1, $request->ip());
$user->role = 'admin';
$user->save();
$user = UserFactory::createUser($setup_finish_args->acct_username, $setup_finish_args->acct_email, $setup_finish_args->acct_password, 1, $request->ip(), false, 0, UserHelper::UserRole('ADMIN'));
return view('setup_thanks')->with('success', 'Set up completed! Thanks for using Polr!');
}

View File

@ -13,7 +13,8 @@ $app->get('/', ['as' => 'index', 'uses' => 'IndexController@showIndexPage']);
$app->get('/logout', ['as' => 'logout', 'uses' => 'UserController@performLogoutUser']);
$app->get('/login', ['as' => 'login', 'uses' => 'UserController@displayLoginPage']);
$app->get('/about', ['as' => 'about', 'uses' => 'StaticPageController@displayAbout']);
$app->get('/signup', ['as' => 'signup', 'uses' => 'UserController@displaySignupPage']);
if (env('POLR_ALLOW_ACCT_CREATION'))
$app->get('/signup', ['as' => 'signup', 'uses' => 'UserController@displaySignupPage']);
$app->get('/lost_password', ['as' => 'lost_password', 'uses' => 'UserController@displayLostPasswordPage']);
$app->get('/activate/{username}/{recovery_key}', ['as' => 'activate', 'uses' => 'UserController@performActivation']);
$app->get('/reset_password/{username}/{recovery_key}', ['as' => 'reset_password', 'uses' => 'UserController@performPasswordReset']);
@ -31,7 +32,8 @@ $app->get('/{short_url}/{secret_key}', ['uses' => 'LinkController@performRedirec
/* POST endpoints */
$app->post('/login', ['as' => 'plogin', 'uses' => 'UserController@performLogin']);
$app->post('/signup', ['as' => 'psignup', 'uses' => 'UserController@performSignup']);
if (env('POLR_ALLOW_ACCT_CREATION'))
$app->post('/signup', ['as' => 'psignup', 'uses' => 'UserController@performSignup']);
$app->post('/shorten', ['as' => 'pshorten', 'uses' => 'LinkController@performShorten']);
$app->post('/lost_password', ['as' => 'plost_password', 'uses' => 'UserController@performSendPasswordResetCode']);
$app->post('/reset_password/{username}/{recovery_key}', ['as' => 'preset_password', 'uses' => 'UserController@performPasswordReset']);
@ -44,6 +46,9 @@ $app->group(['prefix' => '/api/v2', 'namespace' => 'App\Http\Controllers'], func
$app->post('admin/toggle_api_active', ['as' => 'api_toggle_api_active', 'uses' => 'AjaxController@toggleAPIActive']);
$app->post('admin/generate_new_api_key', ['as' => 'api_generate_new_api_key', 'uses' => 'AjaxController@generateNewAPIKey']);
$app->post('admin/edit_api_quota', ['as' => 'api_edit_quota', 'uses' => 'AjaxController@editAPIQuota']);
$app->post('admin/toggle_user_active', ['as' => 'api_generate_new_api_key', 'uses' => 'AjaxController@toggleUserActive']);
$app->post('admin/change_user_role', ['as' => 'api_generate_new_api_key', 'uses' => 'AjaxController@changeUserRole']);
$app->post('admin/add_new_user', ['as' => 'api_generate_new_api_key', 'uses' => 'AjaxController@addNewUser']);
$app->post('admin/delete_user', ['as' => 'api_generate_new_api_key', 'uses' => 'AjaxController@deleteUser']);
$app->post('admin/toggle_link', ['as' => 'api_toggle_link', 'uses' => 'AjaxController@toggleLink']);
$app->post('admin/delete_link', ['as' => 'api_delete_link', 'uses' => 'AjaxController@deleteLink']);

View File

@ -27,9 +27,10 @@ polr.controller('AdminCtrl', function($scope, $compile) {
{className: 'wrap-text', data: 'username', name: 'username'},
{className: 'wrap-text', data: 'email', name: 'email'},
{data: 'created_at', name: 'created_at'},
{data: 'active', name: 'active'},
{data: 'toggle_active', name: 'toggle_active'},
{data: 'api_action', name: 'api_action', orderable: false, searchable: false},
{data: 'change_role', name: 'change_role'},
{data: 'delete', name: 'delete', orderable: false, searchable: false}
]
}, datatables_config));
@ -86,10 +87,105 @@ polr.controller('AdminCtrl', function($scope, $compile) {
el.parent().parent().slideUp();
};
$scope.toggleUserActiveStatus = function($event) {
var el = $($event.target);
var user_id = el.data('user-id');
apiCall('admin/toggle_user_active', {
'user_id': user_id,
}, function(new_status) {
var text = (new_status == 1) ? 'Active' : 'Inactive';
el.text(text);
if (el.hasClass('btn-success')) {
el.removeClass('btn-success').addClass('btn-danger');
}
else {
el.removeClass('btn-danger').addClass('btn-success');
}
});
}
$scope.toggleNewUserBox = function($event) {
var el = $($event.target);
$('#add_user_box').toggle();
if (el.text() == 'Add New User') {
el.text('Cancel');
$('#new_user_name').focus();
}
else {
el.text('Add New User');
$scope.resetNewUserFields();
}
}
$scope.resetNewUserFields = function() {
$('#new_user_name').val('');
$('#new_user_password').val('');
$('#new_user_email').val('');
$("#new_user_role").val($("#new_user_role option:first").val());
$('#new_user_status').text('');
$('#new_user_status').css('color', '#000');
};
$scope.checkNewUserFiels = function() {
var user_name = $('#new_user_name').val();
var user_password = $('#new_user_password').val();
var user_email = $('#new_user_email').val();
if (user_name.trim() == '' || user_password.trim() == '' || user_email.trim() == '') return false;
return true;
}
$scope.addNewUser = function($event) {
const status_error1 = 'Fields cannot be empty !';
const status_error2 = 'Unknown Error !';
const status_ok = 'New User added !\nPlease refresh page to see all users.';
var user_name = $('#new_user_name').val();
var user_password = $('#new_user_password').val();
var user_email = $('#new_user_email').val();
var user_role = $('#new_user_role').val();
if (!$scope.checkNewUserFiels()) {
$('#new_user_status').text(status_error1);
$('#new_user_status').css('color', '#f00');
return;
}
apiCall('admin/add_new_user', {
'user_name': user_name,
'user_password': user_password,
'user_email': user_email,
'user_role': user_role,
}, function(result) {
if (result == 'OK') {
$('#new_user_status').text(status_ok).css('color', '#325d88').hide();
$('#new_user_status').fadeIn('normal', function() {
$(this).delay(3000).fadeOut('slow', function() {
$('#add_user_box').toggle();
$('#add_user_btn').text('Add New User');
$('#new_user_status').show();
$scope.resetNewUserFields();
});
});
}
else {
$('#new_user_status').text(status_error2);
$('#new_user_status').css('color', '#f00');
}
});
}
// Delete user
$scope.deleteUser = function($event) {
var el = $($event.target);
var user_id = el.data('user-id');
var user_name = el.data('user-name');
var confirmation = confirm("User '" + user_name + "' will be deleted.\nAre you sure?");
if (!confirmation) return;
apiCall('admin/delete_user', {
'user_id': user_id,
@ -126,6 +222,7 @@ polr.controller('AdminCtrl', function($scope, $compile) {
} else {
status_display_elem.text(new_status);
}
$('a#api_info_btn_' + user_id).attr('data-api-key', new_status);
});
};
@ -137,6 +234,7 @@ polr.controller('AdminCtrl', function($scope, $compile) {
apiCall('admin/toggle_api_active', {
'user_id': user_id,
}, function(new_status) {
$('a#api_info_btn_' + user_id).attr('data-api-active', new_status);
new_status = res_value_to_text(new_status);
status_display_elem.text(new_status);
});
@ -172,13 +270,18 @@ polr.controller('AdminCtrl', function($scope, $compile) {
'user_id': user_id,
'new_quota': parseInt(new_quota)
}, function(next_action) {
$('a#api_info_btn_' + user_id).attr('data-api-quota', new_quota);
toastr.success("Quota successfully changed.", "Success");
});
};
// Open user API settings menu
$scope.openAPIModal = function($event, username, api_key, api_active, api_quota, user_id) {
$scope.openAPIModal = function($event, username, user_id) {
var el = $($event.target);
api_active = $('a#api_info_btn_' + user_id).attr('data-api-active');
api_key = $('a#api_info_btn_' + user_id).attr('data-api-key');
api_quota = $('a#api_info_btn_' + user_id).attr('data-api-quota');
var markup = $('#api-modal-template').html();
@ -222,3 +325,24 @@ polr.controller('AdminCtrl', function($scope, $compile) {
$scope.init();
});
function changeUserRole(what) {
var user_id = what.attr('data-user-id');
var role = what.val();
apiCall('admin/change_user_role', {
'user_id': user_id,
'role': role,
}, function(result) {
if (result == 'OK') {
var parent_td = what.parent();
var add = '<div id="role_changed_' + user_id + '" style="display: none; color: #fff; background: #0a0; font-weight: bold; text-align: center;">Changed</div>';
parent_td.append(add);
$('#role_changed_' + user_id).fadeIn('normal', function() {
$(this).delay(1000).fadeOut('slow', function() {
$('#role_changed_' + user_id).remove();
});
});
}
});
}

View File

@ -13,7 +13,7 @@
<li role='presentation' aria-controls="links" class='admin-nav-item'><a href='#links'>Links</a></li>
<li role='presentation' aria-controls="settings" class='admin-nav-item'><a href='#settings'>Settings</a></li>
@if ($role == 'admin')
@if ($role == $admin_role)
<li role='presentation' class='admin-nav-item'><a href='#admin'>Admin</a></li>
@endif
@ -45,7 +45,7 @@
</form>
</div>
@if ($role == 'admin')
@if ($role == $admin_role)
<div role="tabpanel" class="tab-pane" id="admin">
<h3>Links</h3>
@include('snippets.link_table', [
@ -54,7 +54,8 @@
<h3>Users</h3>
@include('snippets.user_table', [
'table_id' => 'admin_users_table'
'table_id' => 'admin_users_table',
'roles' => $user_roles
])
</div>

View File

@ -1,3 +1,31 @@
<div style="margin-bottom: 30px;">
<a ng-click="toggleNewUserBox($event)" id="add_user_btn" class='btn btn-primary btn-sm status-display'>Add New User</a>
<div id="add_user_box" style="display: none; margin-top: 10px;">
<table class="table">
<tr>
<th width="20%">Username</th>
<th width="20%">Password</th>
<th width="20%">Email</th>
<th width="10%">Role</th>
<th width="10%"></th>
</tr>
<tr>
<td><input id="new_user_name" /></td>
<td><input id="new_user_password" /></td>
<td><input id="new_user_email" /></td>
<td>
<select id="new_user_role" style="width: 100%; height: 85%;">
@foreach ($roles as $role_text => $role_val)
<option value="{{$role_val}}">{{$role_text}}</option>
@endforeach
</select>
</td>
<td><a ng-click="addNewUser($event)" class='btn btn-primary btn-sm status-display' style="padding-left: 15px; padding-right: 15px;">Add</a></td>
</tr>
</table>
<div id="new_user_status" style="text-align: center;"></div>
</div>
</div>
<table id="{{$table_id}}" class="table table-hover">
<thead>
<tr>
@ -6,6 +34,7 @@
<th>Created At</th>
<th>Activated</th>
<th>API</th>
<th>Role</th>
<th>Delete</th>
</tr>
</thead>