Skip to content

Authorizations via engines & two examples#2024

Merged
josepjaume merged 42 commits intomasterfrom
feature/authorizations_via_engine
Nov 29, 2017
Merged

Authorizations via engines & two examples#2024
josepjaume merged 42 commits intomasterfrom
feature/authorizations_via_engine

Conversation

@deivid-rodriguez
Copy link
Copy Markdown
Contributor

@deivid-rodriguez deivid-rodriguez commented Oct 11, 2017

🎩 What? Why?

This PR implements multi-step and multi-side authorizations via engines as suggested in #1871. It keeps support as is for simpler authorizations via rectify forms but introduces the possibility to implement more complex scenarios by declaring a manifest with a engine and (optionally) an admin engine. I've called these new authorization methods "workflow authorizations" as opposed to "handler authorizations".

The manifest is currently very simple and just allows to register the verification workflow and its engines:

# frozen_string_literal: true
Decidim::Verifications.register_workflow(:id_documents) do |workflow|
workflow.engine = Decidim::Verifications::IdDocuments::Engine
workflow.admin_engine = Decidim::Verifications::IdDocuments::AdminEngine
end

I'm not sure whether these new authorization engines should live in a separate gem, in a separate repo, namespaced inside decidim-{core,admin}? For now I've gone with the first option but I'm open to suggestions.

As the first examples, I've added authorizations via identity document upload as explained in #1815, and authorizations via code by postal mail as explained in #2030.

📌 Related Issues

📋 Subtasks

Common
  • Introduce pending verifications.
  • Implement authorization workflows.
  • Get "form authorizations" and "workflow authorizations" play nice together.
Identity documents
  • Identiy document upload.
  • Identity document verification.
  • Identity document rejection (allows uploading the documents again).
Letters
  • Address form for postal mail verification.
  • Code confirmation for postal mail verification.
  • Admin UI to mark letters as sent.
Ideas for future iterations (will migrate to separate tickets if accepted as improvements)
  • Extract verification of authorizations to a separate model so it can hold more information about the verification (verification time, user who verified the user if any, ...).
  • Allow customizing which fields of the identity document get checked via a manifest setting.
  • Allow multiple document upload?
  • Allow batch downloading of letters with codes (in pdf) ready to be sent.
  • Notifications.
  • Unique hashed verification code deterministically generated from user data & application secrets, so letters can be sent out of the platform and users can get verified with it as soon as they get registered Verification by postal mail code #2030 (comment)
  • Reasons for identity document rejection.

📷 Screenshots (optional)

Enabling authorization methods for an organization

enableorgauthorizations

Enabling authorization methods for specific actions

enableactionauthorizations

Verification with identity documents

authorizingwithdocs

Verification with postal letter

authorizingwithletter

👻 GIF

immaterialimpracticalduckbillplatypus-small

@ghost ghost added the in-progress label Oct 11, 2017
@codecov
Copy link
Copy Markdown

codecov bot commented Oct 11, 2017

Codecov Report

Merging #2024 into master will increase coverage by 0.02%.
The diff coverage is 98.78%.

@@            Coverage Diff            @@
##           master   #2024      +/-   ##
=========================================
+ Coverage   98.58%   98.6%   +0.02%     
=========================================
  Files        1190    1239      +49     
  Lines       27442   28439     +997     
=========================================
+ Hits        27053   28042     +989     
- Misses        389     397       +8

@deivid-rodriguez deivid-rodriguez force-pushed the feature/authorizations_via_engine branch from 44dd944 to 4ec46ba Compare October 11, 2017 10:41
@deivid-rodriguez deivid-rodriguez force-pushed the feature/authorizations_via_engine branch 3 times, most recently from f9211b5 to babf43c Compare October 18, 2017 06:59
@deivid-rodriguez deivid-rodriguez changed the title [WIP] Authorizations via engines & a first example (identity document upload) [WIP] Authorizations via engines & two examples Oct 18, 2017
@deivid-rodriguez deivid-rodriguez force-pushed the feature/authorizations_via_engine branch 2 times, most recently from d169425 to 9ba8a55 Compare October 19, 2017 08:41
@deivid-rodriguez
Copy link
Copy Markdown
Contributor Author

deivid-rodriguez commented Oct 19, 2017

Hei! This should be ready now for an initial review. I finally added "postal letter verifications" as well in here. Let me know if you want it splitted away, or if it's fine.

I've updated the PR's description and I'll be posting some more screenshots later today.

@deivid-rodriguez deivid-rodriguez changed the title [WIP] Authorizations via engines & two examples Authorizations via engines & two examples Oct 19, 2017
@deivid-rodriguez deivid-rodriguez force-pushed the feature/authorizations_via_engine branch from 9ba8a55 to dad47ea Compare October 19, 2017 09:08
@josepjaume
Copy link
Copy Markdown
Contributor

josepjaume commented Oct 19, 2017

Hi @deivid-rodriguez - this looks very promising. Before reviewing the code though, there's a tricky scenario you maybe didn't have into account: managed users. Managed users can't be impersonated without re-entering the user's authorization data, which looks kind of incompatible with "deferred" (engine?) authorizations.

Maybe we could include that information (deferred authorizations) in the manifest in order to exclude them from managed users? It doesn't seem trivial to manage it in a different way.

Thanks!

@deivid-rodriguez
Copy link
Copy Markdown
Contributor Author

Hi @deivid-rodriguez - this looks very promising. Before reviewing the code though, there's a tricky scenario you maybe didn't have into account: managed users. Managed users can't be impersonated without re-entering the user's authorization data, which looks kind of incompatible with "deferred" (engine?) authorizations.

Yes, I did! 😄 See #1871 (comment). My solution is to only use direct authorization handlers for impersonations.

@deivid-rodriguez
Copy link
Copy Markdown
Contributor Author

deivid-rodriguez commented Oct 19, 2017

Maybe we could include that information (deferred authorizations) in the manifest in order to exclude them from managed users? It doesn't seem trivial to manage it in a different way.

Regarding the implementation, at the moment authorization handlers are not registered through a manifest but just like they are registered now through a global configuration. So to figure out the "authorization" type I "auto-detect" it:

  • If registered through manifest, it's a workflow (deferred) method.
  • If constantizable to a class, then it's a handler (direct) method.

It's this magic here:

# frozen_string_literal: true
module Decidim
module Verifications
autoload :HandlerWrapper, "decidim/verifications/handler_wrapper"
autoload :WorkflowWrapper, "decidim/verifications/workflow_wrapper"
class Adapter
def self.from_collection(collection)
collection.map { |e| from_element(e) }
end
def self.from_element(element)
new(element).wrapper
end
def initialize(element)
@element = element
end
def wrapper
manifest_wrapper || handler_wrapper
end
def manifest_wrapper
return unless manifest
WorkflowWrapper.new(manifest)
end
def handler_wrapper
handler = handler_for(element) || handler_for(element.classify)
return unless handler
HandlerWrapper.new(handler)
end
private
def handler_for(name)
klass = name.constantize
return unless klass < Decidim::AuthorizationHandler
klass
rescue NameError
nil
end
def manifest
Verifications.find_workflow_manifest(element)
end
attr_reader :element
end
end
end

I wanted to keep backwards compatibility in this first MVP and it seemed nice to still be able to register handlers directly as it's done now. But looking backwards I should've probably unified everything under a manifest.

@deivid-rodriguez deivid-rodriguez force-pushed the feature/authorizations_via_engine branch from 3b570e4 to ef30dde Compare October 20, 2017 00:35
@deivid-rodriguez
Copy link
Copy Markdown
Contributor Author

Some heads up here, I renewed the screenshots. While recording them, I found several bugs and improvements which I've fixed and added. There's some general fixes in here that I could extract out of this PR if you wanted me to.

@mrcasals
Copy link
Copy Markdown
Contributor

@deivid-rodriguez screenshots look superawesome! I'll try to find some time today to review the PR! 😄

@deivid-rodriguez
Copy link
Copy Markdown
Contributor Author

@mrcasals Do you see them as blurry as I do? The screen recording process I'm using not only quasi-freezes my laptop but also doesn't generate great gifs. But things should look better in real life 😃

@mrcasals
Copy link
Copy Markdown
Contributor

Ah yes, GIFs look blurry, but that's a problem with GIFs I guess, so we can't do much about it...

@mrcasals
Copy link
Copy Markdown
Contributor

@deivid-rodriguez with this PR, does this mean we can extend decidim with new authorizations bundled in a gem? I'm thinking about the Spanish IDs (DNI, NIE, passport) we're using in Barcelona/Terrassa/Sant Cugat. They are mostly the same (census authorization), they mostly use the same fields, and only change how to check the values to an API.

Would we be able to extract this in a gem?

@josepjaume
Copy link
Copy Markdown
Contributor

josepjaume commented Oct 20, 2017 via email

mrcasals
mrcasals previously approved these changes Oct 20, 2017
authorization method they require. For example, a decidim instance might
choose to require census authorization to create proposals, but a fully
verified address via a verification code for voting on proposals. which
authorization. methods to use to let users get verified, and
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This last sentence looks weird.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oooops, I'll fix this.

verification_number: 'Verification #%{n}'
rejections:
create:
success: Verification rejected. User will be prompted to ammend her documents
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

s/ammend/amend/

@mrcasals
Copy link
Copy Markdown
Contributor

@deivid-rodriguez über-nice work! I think I'll need to work on adding a new authorization method in order to fully understand how to do that, because it looks a bit complicated, but that's OK.

Should we move the authorizations we have in core to this new engine? They might be simple enough, but this way we keep similar things together.

Apart from that, really nice work, thanks! ❤️

@deivid-rodriguez
Copy link
Copy Markdown
Contributor Author

@deivid-rodriguez über-nice work! I think I'll need to work on adding a new authorization method in order to fully understand how to do that, because it looks a bit complicated, but that's OK.

Yes, it is a bit complicated... In a future iteration I think we could unify everything under a manifest like @josepjaume intended / suggested. This will be simpler implementation-wise and towards users since we'll have a single way of registering (and documenting) authorization methods.

Something like:

 Decidim::Verifications.register_verification_method(:id_documents) do |verification| 
   verification.engine = Decidim::Verifications::IdDocuments::Engine 
   verification.admin_engine = Decidim::Verifications::IdDocuments::AdminEngine 
 end

or, for current handlers,

 Decidim::Verifications.register_verification_method(:barcelona_census) do |verification| 
   verification.form = Decidim::Barcelona::CensusHandler 
 end

However, I think we can release this way for now, since it allows us to start experimenting with this new authorization methods without breaking compatibility with the old ones (and thus not having to deal yet with data migrations, and so on).

@deivid-rodriguez
Copy link
Copy Markdown
Contributor Author

Should we move the authorizations we have in core to this new engine? They might be simple enough, but this way we keep similar things together.

Absolutely! I scheduled myself to do this, but I forgot! Assuming you mean under the new "gem" (note that there's one "engine" per authorization method, or even two if the authorization method needs admin intervention).

Copy link
Copy Markdown
Contributor

@josepjaume josepjaume left a comment

Choose a reason for hiding this comment

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

You did an amazing work here, @deivid-rodriguez. Top quality! Sorry it took so long to review, but we've had lots of stuff in our plate. Merging this in!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants