Authenticate by role on frontend

This commit is contained in:
Almira Krdzic
2018-10-19 17:57:27 +02:00
parent 038b622eca
commit a5a795af93
3 changed files with 96 additions and 115 deletions

View File

@@ -13,19 +13,16 @@ class Wiaas_Authentication {
public static function init() { public static function init() {
// authenticate current user // authenticate current user
add_action('determine_current_user', array(__CLASS__, 'authenticate_current_user'), 999); // add_action('determine_current_user', array(__CLASS__, 'authenticate_current_user'), 999);
// authenticates user on login // authenticates user on login
add_filter( 'authenticate', array( __CLASS__, 'authenticate_user_on_login' ), 999, 3); // add_filter( 'authenticate', array( __CLASS__, 'authenticate_user_on_login' ), 999, 3);
// retrieve preferred user role for user // retrieve preferred user role for user
add_filter('get_user_metadata', array(__CLASS__, 'maybe_filter_user_roles'), 10, 3); add_filter('get_user_metadata', array(__CLASS__, 'maybe_filter_user_roles'), 10, 3);
// redirect to dashboard after login // redirect to dashboard after login
add_filter( 'login_redirect', array( __CLASS__, 'login_redirect' ) ); // add_filter( 'login_redirect', array( __CLASS__, 'login_redirect' ) );
// add role selector to login form
add_action('login_form', array(__CLASS__, 'pick_role_on_login'));
} }
/** /**
@@ -37,26 +34,18 @@ class Wiaas_Authentication {
return admin_url('index.php') ; return admin_url('index.php') ;
} }
/**
* Add role selector to login form
*/
public static function pick_role_on_login() {
?>
<p>
<label for="user_role"><?php esc_html_e( 'Role' , 'wiaas'); ?><br />
<select id="user_role" class="input" name="role">
<option value="administrator"><?php esc_html_e('Administrator', 'wiaas') ?></option>
<option value="supplier"><?php esc_html_e('Supplier', 'wiaas') ?></option>
<option value="commercial_lead"><?php esc_html_e('Commercial Lead', 'wiaas') ?></option>
</select>
</p>
<?php
}
/** /**
* Authenticate current user based on roles assigned to organization * Authenticate current user based on roles assigned to organization
* *
* User role will be determined in `maybe_filter_user_roles` based on his organization roles
*
* If this is REST API request user will be only authenticated with customer role if his organization has
* customer role assigned to it.
*
* If this is backend request user will be authenticated with previously selected or first available role
* from his organization roles.
*
* @param int|false $user_id * @param int|false $user_id
* @return int|false|WP_Error * @return int|false|WP_Error
*/ */
@@ -66,17 +55,11 @@ class Wiaas_Authentication {
return $user_id; return $user_id;
} }
$is_rest_api = strpos($_SERVER['REQUEST_URI'], rest_get_url_prefix()); $user = new WP_User($user_id);
$role = $is_rest_api ? if (empty($user->roles)) {
'customer' : return new WP_Error('wiaas_authentication_error', 'No permissions!');
get_user_meta($user_id, '_wiaas_current_user_admin_role', true); }
$result = self::_can_user_have_role($user_id, $role, $is_rest_api);
if (is_wp_error($result)) {
return false;
}
return $user_id; return $user_id;
} }
@@ -84,36 +67,27 @@ class Wiaas_Authentication {
/** /**
* Authenticate wiaas user on login based on roles assigned to organization * Authenticate wiaas user on login based on roles assigned to organization
* *
* User role will be determined in `maybe_filter_user_roles` based on his organization roles
*
* If this is REST API login request user will be only authenticated with customer role if his organization his
* customer role assigned to it.
*
* If this is backend login request user will be authenticated with previously selected or first available role
* from his organization roles.
*
* @param WP_User $user * @param WP_User $user
* @return WP_User|WP_Error * @return WP_User|WP_Error
*/ */
public static function authenticate_user_on_login($user) { public static function authenticate_user_on_login($user) {
// check if rest request
$is_rest_api = strpos($_SERVER['REQUEST_URI'], rest_get_url_prefix());
// do nothing if there is an error already, // do nothing if there is an error already,
// user is super admin or // user is super admin
// this is rest request if (is_wp_error($user) || $user->ID === 1) {
if (is_wp_error($user) || $user->ID === 1 || $is_rest_api) {
return $user; return $user;
} }
if (empty($_POST['role'])) { if (empty($user->roles)) {
return new WP_Error('error', 'You must selected role to login!'); return new WP_Error('wiaas_authentication_error', 'No permissions!');
} }
// get selected role
$requested_role = sanitize_key($_POST['role']);
// validate can user have requested role
$result = self::_can_user_have_role($user->ID, $requested_role, false);
// if user organization has no requested role prevent access
if (is_wp_error($result)) {
return $result;
}
// remember role for user and continue
update_user_meta($user->ID, '_wiaas_current_user_admin_role', $requested_role);
return $user; return $user;
} }
@@ -121,8 +95,12 @@ class Wiaas_Authentication {
/** /**
* *
* Filters user roles retrieval so that selected user role is retrieved for admin panel * Override default user roles with only his organization roles.
* and customer role is retrieved for JSON API request *
* If this is REST API request retrieve customer role if organization has that role.
*
* If this is backend request retrieve previously selected role or first available organization role with
* backend access.
* *
* @param $null * @param $null
* @param int $user_id * @param int $user_id
@@ -135,66 +113,67 @@ class Wiaas_Authentication {
if ($user_id !== 0 && $user_id !== self::SUPER_ADMIN_USER_ID && $meta_key === $wpdb->get_blog_prefix() . 'capabilities') { if ($user_id !== 0 && $user_id !== self::SUPER_ADMIN_USER_ID && $meta_key === $wpdb->get_blog_prefix() . 'capabilities') {
$is_rest_api = strpos($_SERVER['REQUEST_URI'], rest_get_url_prefix()); return array( array( 'customer' => true ) );
$role = $is_rest_api ? // import organization functions (during user authentication it is not yet loaded)
'customer' : require_once dirname( __FILE__ ) . '/user/wiaas-organization-functions.php';
get_user_meta($user_id, '_wiaas_current_user_admin_role', true);
// get user organization
$organization_id = wiaas_get_user_organization_id($user_id);
// validate if user has organization
if ( empty( $organization_id) ) {
return array();
}
// get organization roles
$roles = wiaas_get_organization_roles($organization_id);
// if organization has no roles assigned to it user will have no roles
if ( empty($roles) ) {
return array();
}
/**
* REST API access
*/
// for REST API access allow only customer role for user
if ( $is_rest_api = strpos($_SERVER['REQUEST_URI'], rest_get_url_prefix()) ) {
return in_array('customer', $roles) ? array( array( 'customer' => true ) ) : array();
}
/**
* BACKEND ACCESS
*/
// remove customer role
$roles = array_diff($roles, array( 'customer'));
// not available backend roles for user
if ( empty($roles) ) {
return array();
}
// retrieve selected role for user
$role = get_user_meta($user_id, '_wiaas_current_user_admin_role', true);
// if user has no selected role, selected role in invalid (deleted) or organization has no selected role
// assign first available role to user
if ( empty($role) ||
! wp_roles()->is_role($role) ||
! in_array($role, $roles) ) {
// pick first role
$role = $roles[0];
update_user_meta($user_id, '_wiaas_current_user_admin_role', $role);
}
return array( array ( "$role" => true )); return array( array ( "$role" => true ));
} }
return null; return null;
} }
// PRIVATE
/**
* Determines if user can have requested role based on his organization roles
*
* @param int $user_id
* @param string $user_role
* @param bool $is_rest_api
* @return bool|WP_Error
*/
private static function _can_user_have_role($user_id, $user_role, $is_rest_api) {
// check if role valid for access
if (! wp_roles()->is_role($user_role)) {
return new WP_Error('error', 'Role is not valid!');
}
// only customer role can access API
if ($is_rest_api && $user_role !== 'customer') {
return new WP_Error('error', 'No access!');
}
// customer role cannot access admin backend
if (! $is_rest_api && $user_role === 'customer') {
return new WP_Error('error', 'No access!');
}
// import organization functions (during user authentication it is not yet loaded)
require_once dirname( __FILE__ ) . '/user/wiaas-organization-functions.php';
// get user organization
$organization_id = wiaas_get_user_organization_id($user_id);
// validate if user has organization
if (empty( $organization_id)) {
return new WP_Error('error', 'Account not completed!');
}
// get organization roles
$roles = wiaas_get_organization_roles($organization_id);
// validate if user has organization roles
if (!in_array($user_role, $roles)) {
return new WP_Error( 'error', 'Your account is not authorized for requested role. Please contact us for help.' );
}
return true;
}
} }
Wiaas_Authentication::init(); Wiaas_Authentication::init();

View File

@@ -388,6 +388,7 @@ class Wiaas_Document {
'show_admin_column' => true, 'show_admin_column' => true,
'query_var' => true, 'query_var' => true,
'rewrite' => array( 'slug' => 'wiaas_doc_type' ), 'rewrite' => array( 'slug' => 'wiaas_doc_type' ),
'show_in_rest' => false,
'capabilities' => array( 'capabilities' => array(
'manage_terms' => 'manage_wiaas_doc_terms', 'manage_terms' => 'manage_wiaas_doc_terms',
'edit_terms' => 'edit_wiaas_doc_terms', 'edit_terms' => 'edit_wiaas_doc_terms',
@@ -399,9 +400,11 @@ class Wiaas_Document {
register_taxonomy( 'wiaas_doc_type', array( 'wiaas_doc' ), $args ); register_taxonomy( 'wiaas_doc_type', array( 'wiaas_doc' ), $args );
foreach (self::$available_doc_types as $key => $available_doc_type) { foreach (self::$available_doc_types as $key => $available_doc_type) {
wp_insert_term($available_doc_type['name'], 'wiaas_doc_type', array( if (! has_term($available_doc_type['name'], 'wiaas_doc_type')) {
'slug' => $key wp_insert_term($available_doc_type['name'], 'wiaas_doc_type', array(
)); 'slug' => $key
));
}
} }
} }

View File

@@ -15,8 +15,7 @@ class Wiaas_User_Organization extends WP_User_Taxonomy {
'plural' => __('Organizations', 'wiaas'), 'plural' => __('Organizations', 'wiaas'),
'exclusive' => true, 'exclusive' => true,
'public' => true, 'public' => true,
'show_in_rest' => true, 'show_in_rest' => false,
'rest_base' => 'organization'
); );
$labels = array(); $labels = array();
$caps = array(); $caps = array();