Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modular ACLS #91

Closed
wants to merge 299 commits into from
Closed

Modular ACLS #91

wants to merge 299 commits into from

Conversation

ryanrath
Copy link
Contributor

@ryanrath ryanrath commented Apr 7, 2017

note: I'll update this to not suck presently.

The intent of these changes is to provide an easy method for modules / module writers to interact with ACLS ( previously Roles ). In short, to take us from a hard coded set of roles / hierarchy to a more flexible architecture.

Description

The basic premise of how the system is used goes something like this: A module writer decides that they will require a new ACL with which to gate some/all of the functionality that they are providing. They write up a couple of json files to tell the system some basic information about their module and the acl they want to create. At install time these files are included / executed by an ETL action which incorporates them into the correct tables. Users can now be assigned the acl / they can check for it's existence in php code etc.

The overarching data flow is thus:

  • json files / sql files are utilized at system / module install to ensure that database tables are present and properly populated.
  • All run time utilization of this information should now be drawn from these database tables. The config files need not be referenced.

This flow, coupled with table foreign keys provides ample information when attempting to track down where a piece of information came from ( module ).

Motivation and Context

We have a very static set of roles / hierarchies at the moment.

Tests performed

All tests performed were manual tests utilizing both the site itself and Postman where appropriate to ensure that current data / behavior.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project as found in the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

The intent of these changes is to provide an easy method for modules / module writers to interact with ACLS ( previously Roles ). In short, to take us from a hard coded set of roles / hierarchy to a more flexible architecture.

- Had the logic flipped for 'isAuthorized'
- Added hasAcl[s] functions to the XDUser class so that a particular
  user object can be interrogated as to whether or not it belongs to
  the provided Acl[s].
- Added hasAsset[s] functions to the XDUser class so that a particular
  user object can be interrogated as to whether or not it has access to
  the provided Asset[s].
- Think the odd behavior that lead to this change was due to rest
  testing w/ the same session id.
- Base Rest Authorization function now utilizes user acls as opposed to
  user roles. First implementation for PoC.
- Added the public acl as an actual acl as opposed to something that
  just lives in code.
- Added a default 'pub' acl to the public user.
- Exception had the wrong 2nd parameter, this was supposed to be the
  previous exception, not the code. Updated to be in line with the
  constructor arguments.
- Changed from authorization -> authentication because to be authorized
  you need to be authenticated first and at the point 'login' is called
  users are, by definition, not authenticated and therefor cannot be
  authorized.
- authenticate does not return a user object like authorization. So
  just retrieve the user object as normal.
- rejiggered the logic for what constitutes success in the new acl
  based authorization function.
- was just mucking up the logic.
- Just re-writing the logical conditions on what constitutes invalid
  requirements so as to be more intelligible.
- Updated the is[PublicUser, Developer, Manager] functions to utilize
  acls vs. roles ( since they're interchangeable ).
- Many calls to 'getRoles' utilized the values for their string /
  equivalency to the db column 'abbrev' ( which correlates to
  Acl->name ). Added a new '$names' argument with a default value of
  'false' so that a caller can specify whether or not they want the
  object representation or just the keys ( 'name' values ).
- Updated the return value for getAcls($names=true) to use the
  array_keys function as opposed to iterating through each item and
  retrieving the name.
- Added some more detailed documentation for $_acls and $_assets.
- Added documentation types for all functions in the xd_utilities
  namespace that could be reasonably inferred. Also added @throws where
  appropriate.
- Swapped out $user->getRoles() for $user->getAcls(true). The result of
  $user->getRoles() was an array of $role->abbrev and is used to fill in
  a WHERE IN (role_values) clause. The result of $user->getAcls(true) is
  functionally the same, returning the equivalent value of the acl, ie.
  name.
- Just added acls to the returned User Details. Will remove roles when
  the front end has been modified to handle it.
- replaced the role based security w/ acl based security. It pains me
  to leave this in place but it will be overhauled when we finish moving
  the controllers to the new rest stack.
- the function was not used (hint: roles->getRoleCategories() was
  instead).
- Added the remaining DB models required to continue work on the ACL
  replacement.
- Added table setup files for:
  filters
  acl_filters
  group_by_filters
- Also added these new setup files to the acl_setup ACLTableManagement
  action
- user_acls.sql populates the initial values for this table w/ the
  contents of UserRoleParameters iff the values have not already been
  inserted.
- report_template_acl.json just updates the table to be consistent with
  it's name ( which was fortuitous ).
- Added a script that will populate the ReportTemplateACL table with
  the initial values.

$isAuthorized = function (Request $request, Application $app) {
$user = $this->getUserFromRequest($request);
$authorized = Authorization::authorized($user, array('mgr'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function authorized() always returns an array, which contains a status code. This should be checked.

Why don't you change the authorized() function to just directly throw the unauthorized exception, thus reducing the amount of boiler plate code that you have to write and maintain?

$isAuthorized = function (Request $request, Application $app) {
$user = $this->getUserFromRequest($request);
$authorized = Authorization::authorized($user, array('mgr'));
if (!$authorized) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function authorized() always returns an array, which contains a status code. This should be checked.

Why don't you change the authorized() function to just directly throw the unauthorized exception, thus reducing the amount of boiler plate code that you have to write and maintain?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed ( and change incoming ) re: checking the status code.
The reason for the funky return format / not throwing an Exception inside authorized was to try and keep the code in BaseControllerProvider.php:276 - BaseControllerProvider.php:290 the same. But there's nothing to say that we can't move this logic into the 'authorized' function itself seeing as how we have access to the XDUser there.

);
}

public static function getRealmById($realmId)
Copy link
Member

@jpwhite4 jpwhite4 Apr 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this function used for? I can't find anywhere in the code that calls it. How has this been tested?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it looks like both getRealmByName and getRealmById are not currently used. Not sure what getRealmByName was about but I believe getRealmById was to support basic CRUD operations:

  • GET /realms : list all currently installed realms
  • GET /realms/{realm_id} : list information about realm identified by realm_id
  • POST /realms : create a new realm
  • DELETE /realms/{realm_id} : delete the realm identified by realm_id
  • PATCH|PUT /realms/{realm_id} : update the realm identified by realm_id

etc. etc.
Seeing as how the route(s) that would utilize this function doesn't exist it pretty obviously doesn't need to be here. I'll go ahead and remove it.

use Exception;
use Statistic;

/**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget that all new classes need to be in a namespace. Please make sure that all of the new classes that you have added are in a namespace. (I note that phpcs will find these errors).

$old = $this->getBooleanParam($request, 'old', false, false);


$statistics = $old == false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code looks like you are trying to support an 'old' mechanism as well as the new one. Why are you doing this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not support so much as test that the new output matches the old. But it obviously shouldn't have made it into the PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add unit and integration tests to check that the new output matches the old output.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed, I'll make sure to have those added in the new smaller PR's

- Moved all of the new classes that lived in classes/ to classes/Models
- Moved all of the new service classes that lived in classes/ to
  classes/Models/Services.
- Updated all of the 'use' directives to point to the newly moved classes.
@@ -0,0 +1,23 @@
<?php namespace Models;

use DBObject;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should not "use DBObject" it is a class! DBObject needs to be in a namespace and then you can use the namespace that contains it.

Seeing as how we will not need these for a while / are not using them now. The
asset infrastructure is being removed from this PR to clean things up.
- Moved the base 'DBObject' class into the Models namespace per review comment
  by @jpwhite4
- Removed 'use DBObject' statements as they are all now in the same namespace
- Moved the logic from 'BaseControllerProvider.php:273' into the 'authorized'
  function.
- 'Authorization::authorized' now throws either an UnauthorizedHTTPException or
  AccessDeniedException based on whether or not the user is a public user when
  the authorization attempt fails. No Exception is to be interpreted as a
  success. The call sites for this function have been updated to reflect this
  change.
- Added the function back to 'Acls' ( Not sure when it was removed ) so that
  the AclsControllerProvider::getPermittedStatistics route works correctly.
- Updated the SQL from it's original form so that it uses the current table
  layout.
* );
* @throws \Exception if the user provided is null
* if the requirements is not an array or it is an array but has no contents
* @throws \Exception if the user provided is null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User cant be null and it doesn't throw an exception for that. Please remove.

- Resolving a number of phpcs errors
- Reverted as the UI changes that drove this change are not included in this PR.
- Added documentation to all of the functions with expected types where
  appropriate.
- Changed the 'null === $variable' tests in 'listPermittedStatistics' to
  'is_string($variable) === false' as 'is_string' will account for nulls and we
  really do expect these to be strings.
- Small update to the sql query used in _listPermittedStatistics due to a column
  name change.
- Removed unneeded code
- Acl and AclType had invalid references to DBObject. Just updating them so that
  they're valid now.
- user_acl_parameters was replaced by user_acl_group_by_parameters as it was a
  more accurate representation of the data being tracked. It also has slight
  structural differences ( namely the fk to group_bys ).
- Added a use clause for Module as they no long reside within the same namespace
- Added a use clause for Exception as there wasn't one previously.
@ryanrath ryanrath closed this Apr 18, 2017
ryanrath added a commit to ryanrath/xdmod that referenced this pull request Apr 27, 2017
- Updated all references to the 'integer' type to 'int(11)' per
  review comment by @smgallo in ubccr#91
  this ensures that the columns are not continually altered.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Enhancement of the functionality of an existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants