Giter VIP home page Giter VIP logo

forms-manager's Introduction

WIP prototype to use micronaut with hazelcast to create an in-memory data source that micronaut works from and uses Hazelcast's system for cross-app communication

Endpoints

  1. POST /form (Create a Form)
  2. GET /form/:uuid (Get a form)
  3. PATCH /form (Update a form)
  4. POST /form/:uuid/schema?isDefault=true (Create a Form Schema)
  5. PATH /form/:uuid/schema/:uuid?isDefault=true (Update a Form Schema)
  6. GET /form/:uuid/schema (Get the default schema for the form)
  7. GET /form/:uuid/schemas (Get all schemas)
  8. GET /form/:uuid/schema/:uuid (Get a specific form schema for a specific form)
  9. POST /form/validate (Generic validation)
  10. POST /form/:uuid/validate (Validation against the Default Form Schema)
  11. POST /form/:uuid/schemas/:schemaUuid/validate (Validation Against a specific Form Schema for a Specific Form)
  12. POST /form/:uuid/schemas/:schemaUuid/submit (For use with the Submission Handler)

Viewers

Swagger file: `http://localhost:8080/swagger/forms-manager-1.0.yml

  1. Swagger-Ui: http://localhost:8080/swagger-ui/index.html
  2. ReDoc: http://localhost:8080/redoc/index.html
  3. RapiDoc: http://localhost:8080/rapidoc/index.html

Docker

  1. Go to project
  2. Run docker build -t forms-manager .
  3. Run docker run -p 8080:8080 --name forms-manager forms-manager

Notes:

  1. Use Distributed Task for sync requests: Single Request <-> Single Response

  2. Use ReliableTopic for broadcasts / Messages that do not have a single destination and can be received by many.

  3. Added a InjectAware annotation to tell MN when to inject context

  4. If custom code needs to be shipped around to each member (the member does not actual have the code), then Jet tasks should be used.

  5. If required to use confirmation authentication (to perform a sensitive action), then we do JWT + Password login on the endpoint.

  6. Shiro Annotations supported through Micronaut SecurityRule beans

  7. Issue with performance on Paging Predicate for Hazelcast: hazelcast/hazelcast#10828. A replacement of the Hazelcast query engine is supposed to be introduced for 4.1/4.2 that would "fix" this issue. Timeline is ~Fall 2020.

  8. Users are owned by a Tenant. A user can have access to many tenants (through permissions), but lives in only one tenant.

  9. A Administrative users or users who control multiple tenants will still have a "home tenant" to which they log in with (where they user exists), and then their permissions provide which tenants they can access.

  10. Distributed Query for Hazelcast only works with items that are in Mem (obviously ;) ). So If items are evicted from the mem based on TTL, then query will not find them. Items that require search need to be findable based ID. Use a object as ID that is a makeup of known values for that item.

  11. MapKeys are based on a combination of multiple values in a Entity that make up the unique text. That text is this turned into a UUID v3

  12. When using the Near Cache on a IMap with Shrio Authz cache, make sure Principal Objects are Serializable (example PrimaryPrincipal.class had to be made serializable) so it can be cached by Shrio. @TODO Review for ways to remove this need.

  13. add expression handler to build custom dynmaic permissions for shiro wildcard https://stackoverflow.com/questions/2286648/named-placeholders-in-string-formatting

  14. InjectAware needs to be added to all Tasks. The inherit does not work apply to the inject.. it would only inject on the extended properties

  15. Fields that are @Inject should try and always make them public because that way it does not require reflection.

  16. ExecutorService in MN has overlap interfaces with Hazelcast: as a result when you create a bean for IExecutorService it will trigger Bean Event triggers for ExecutorService and cause the app to fail.

  17. There are 4 Serializers:

    1. jackson used internally by Camunda
    2. jackson created by Micronuat (with Singleton imports and the Application.yml configuration)
    3. Jackson used for Smile: formsmanager.core.serialization.JacksonSmileSerialization.class
    4. Jackson used for Map Store Persistence (JDBC persistence with Hazelcast Mapstore (How the data is stored as JSON in the DB)): formsmanager.core.map.persistence.serialization.JacksonDBSerializationFactory.class
  18. Add ability for dynamic permissions applied to objects such as: a Single BU memberhsip but difference between staff and citizne: how do you filter out services that are only for the staff? Would need to be able to apply a logic to staff that only staff can see a specific service (maybe a custom predicate rule applied?)

questions

  1. Member selection for distributed tasks: To only have specific nodes work on specific tasks.

todo:

  1. Add Avro support
  2. Build an annotation processor for automating field logic updates such as Optimistic Locking increments, UpdatedDate, etc. Basically any field that cannot be updated by the user.
  3. Move controllers to module that is Hazelcast client based
  4. Add Camunda node
  5. Add TTL for maps with configuration options to clear out/evict memory for seldom used objects. (Evict does not delete from the hazelcast mapstore, it only evicts from in-memory)
  6. Add local caching (with TTL) for WildcardPermissions that were generated from Strings in the User Entity
  7. Add updated to UserDetails (Micronaut security) for working with Subject from Shiro, so we can use the Micronaut Annotation support @secured and accessing the Shiro permission validator.
  8. Eventually move to an ID Generator that is not built in UUID, as UUID is only 99.99 and could be collisions
  9. Add user registration limits for username and password: length, password complexity, etc
  10. Create a user Entity update page for Admin and for Regular users.
  11. ** deal with scenarios of who owns tenants and groups: and how someone can assign the owner of an object: (Likely a permission)**
  12. ** Convert to modern binary serialization to replace Serialization for Shiro Cache (Using Hz) **
  13. Create a new PrincipalCollection class. Dont use SimplePrincipalCollection as it does not have good enough typing...
  14. Create a Mixin Bean support to auto add mixins based on configs
  15. Add Indexes and composite indexes in hz config for Camunda History entities
  16. Remove use of Injecting IMap as a Bean due to potential deadlocks with Eager MapStore loading

Python execution service:

https://groups.google.com/forum/#!topic/hazelcast/jGZcxpNDc5k https://github.com/hazelcast/hazelcast-python-client https://github.com/hazelcast/hazelcast-python-client/blob/master/hazelcast/proxy/executor.py

Formio Links:

  1. https://formio.github.io/formio.js/app/examples/
  2. Web builder: https://formio.github.io/formio.js/app/builder
  3. CUSTOM SUBMISSION: https://formio.github.io/formio.js/app/examples/customendpoint.html
  4. Thank you page: https://formio.github.io/formio.js/app/examples/thanyou.html
  5. Multiple Languages: https://formio.github.io/formio.js/app/examples/language.html

OLD---> REBUILD ---> Building a Hazelcast based CRUD Repository

A Hazelcast based CRUD Repository is four components:

  1. EntityWrapper
  2. HazelcastRepository
  3. MapStore
  4. MapStoreRepository

See FormRepository.class for example usage.

1. Entity Wrapper

The entity wrapper is an extend of MapStoreItemWrapperEntity which is a generic for creating the DB entity that will be stored in the JdbcRepository.

Example:

@Entity
class FormEntityWrapper(key: UUID,
                        classId: String,
                        value: FormEntity) : MapStoreItemWrapperEntity<FormEntity>(key, classId, value)

2. Hazelcast Crud Repository

This is the repository specific to interacting with Hazelcast. It is the repository that you would inject into your services that wish to perform CRUD operations.

The repository provides:

  1. create
  2. update
  3. exists
  4. delete
  5. find by key

Example:

@Singleton
class FormHazelcastRepository(private val jetService: HazelcastJetManager) :
        HazelcastCrudRepository<UUID, FormEntity>(
                jetService = jetService,
                mapName = "forms"
        ) {
}

3. MapStore Repository

A MapStore Repository extends the CruddableMapStoreRepository which extends the Micronaut CrudRepository. This repository provides the JDBC connectivity that the MapStore will use.

Example:

@JdbcRepository(dialect = Dialect.H2)
interface FormsMapStoreRepository : CrudableMapStoreRepository<FormEntityWrapper>

4. MapStore

The MapStore should extend from the CrudableMapStore. The CrudableMapStore provides ready to use setup with the CrudableMapStoreRepository.

Example:

@Singleton
class FormsMapStore(mapStoreRepository: FormsMapStoreRepository) :
        CurdableMapStore<FormEntity, FormEntityWrapper, FormsMapStoreRepository>(mapStoreRepository)

Create/Update logic notes:

  1. Create: Optimistic Locking performs automatically at the Entry Processor level before the insert/update logic is executed.
  2. Update logic requires specific updates of fields such as:
     formHazelcastRepository.update(formEntity) { originalItem, newItem ->
         newItem.copy(
                 ol = originalItem.ol + 1,
                 id = originalItem.id,
                 type = originalItem.type,
                 createdAt = originalItem.createdAt,
                 updatedAt = Instant.now()
         )
     }
  3. During an Update, the new item is injected into the .update() to apply the internal automatic checks and updates (such as the Optimistic locking check).

Words:

Default Strategy Simple Basic Factory Service System Handler

Permissions

Roles

"roles:create:${entity.tenant}" "roles:read:${g.tenant}" "roles:update:${originalItem.tenant}"

"groups:create:${groupEntity.tenant}" "groups:read:${g.tenant}" "groups:update:${originalItem.tenant}"

"users:read:${ue.tenant}:${ue.internalId}" "users:update:${userEntity.tenant}:${userEntity.internalId}"

"tenants:create" "tenants:read:${te.internalId}" "tenants:update:${originalItem.internalId}"

"forms:create:${formEntity.owner}:${formEntity.tenant}" "forms:read:${fe.owner}:${fe.tenant}" "forms:update:${originalItem.owner}:${originalItem.tenant}" "forms:update:${fe.owner}:${fe.tenant}" "form_schemas:update:${fe.owner}:${fe.tenant}" "forms:update:${fe.owner}:${fe.tenant}" "form_schemas:create:${fe.owner}:${fe.tenant}" "form_schemas:read:${fe.owner}:${fe.tenant}" "form_schemas:read:${fe.owner}:${fe.tenant}" "form_schemas:validate:${fe.owner}:${fe.tenant}"

Camunda Message Buffer

Prevent race conditions and support operation conditions. Retry correlations that failed to correlate.

Sometimes you have correlation occurring to multiple instances. But not all instances were ready at the same time, and durring the correlation, some were missed. Retry support is provided to continue to correlate until all expected correlations occurred.

Actions:

  1. Retry if no matches
  2. Exponential Retry
  3. Expected Matches: Keep Retry until number of expected matches. Throw error if too many matches?
  4. Retry after expiry
  5. Correlate with Response + timeout: if timeout is reached, the result is not waited for, but client will still get a 200.
  6. Correlate without Response
  7. Callback URL on completion?
  8. Correlate with Start Event
  9. Correlate with Activity Execution
  10. Correlate with StartEvent and/or Activity Execution
  11. Max Events in Buffer
  12. Max Correlated Messages In Buffer
  13. Max Correlating Messages in Buffer
  14. Pause Un-Correlated
  15. Metadata about Message Submitter
  16. Delegate code support to submit into buffer from scripts and delegates.
  17. Complex permissions support: Send Messages per topic, process Def, with and without variables, etc.

Permissions For

tasks:complete tasks:view tasks:assign tasks:claim tasks:unclaim

tasks:read_variable:*

Form Submissions are multiple variables. They are json If data should not be shared, then it should be split into a different variable for visibility by another user. (can do this because the practice is that variables are more stable) Example: UT1 -> Submit form. in UT2 user should only be able to see specific fields of a Form. So in UT2, a new form should be created that loads that specific data. If further constraints are needed, then Process Instance separation, or Variable permissions should be used.

Further permissions logic and special considerations should VERY likely be used within a Cases model. WHere a Process Instance is where is being done, but the outcome is stored in a case.

Task Complete:

  1. Is Assignee
  2. Is member of Candidate Users
  3. Is Member of Candidate Group
  4. Has instance permission

View Completed Task Info:

  1. Is Assignee
  2. Is Member of Candidate Group
  3. Has Instance Permission
  4. Participated in process instance (optional toggle) (query of activity history for that process instance)

Process Instance:

  1. Has Instance Permission
  2. Participated in Task in instance (query of activity history for that process instance)
  3. Has Instance Permission to Definition
  4. Member of Process Instance Owner BU
  5. Member of Process Definition Owner BU

Process Definition:

  1. Process Definition Owner BU
  2. Definition instance Permission

Dynamics:

  1. Tenant
  2. BU membership
  3. Process Instance

Workflowic

Workflow for the workaholic

Real world business problems with real world workflow solutions

  1. Forms Manager

    1. Form Schemas Storage and Management
    2. Apply a Form Schema to a BPMN Form key
    3. BPMN Start Event Forms Support
    4. BPMN User Task Forms Support
    5. Submit data
  2. Camunda Workflow Engine

    1. Reactive External Tasks
    2. Hazelcast History Event Provider
    3. Micronaut Context
    4. Message Buffer
    5. Shiro Security (optional)
    6. Hazelcast backed variables
    7. Camunda Extensions Properties Caching and API
    8. Business Calendar Support
  3. Hazelcast Data Grid + Hazelcast Jet

    1. Store any entity as native object and let hazelcast store it in the DB for you!
    2. Distributed Queries
    3. Repository Interfaces for Hazelcast Map access: Store your data like a regular Data Repository interface
  4. Query API: use SQL Where Query Syntax for query of objects and json data.

    1. Query Camunda History Data
    2. Query All objects in the platform.
  5. Shiro Security

    1. Groups, Roles, Permissions
    2. JWT Security
  6. Multi-Tenancy

  7. Services

  8. Business Units

forms-manager's People

Contributors

stephenott avatar

Stargazers

Liu Qingle avatar

Watchers

James Cloos avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.