Giter Club home page Giter Club logo

gent's People

Contributors

taneliang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

kunal-kushwaha

gent's Issues

RFC: Access control rules do not support separate rules for the same action

Example

static accessControlRules(police: Police<UserQuery, User>) {
  police

    // Only allow a user to create/update/delete their own record. This works.
    .onCreateUpdateDelete((police) => {
      return police.denyIfUnauthenticated().allowWithRestrictedGraphView((vc, query) => {
        if (vc instanceof UserViewerContext) {
          query.whereIdEquals(vc.user.id);
        } else {
          throw new Error('Only UserViewerContext supported!');
        }
        return query;
      });
    })

    // Expectation: For every user record:
    // 1. The user should be able to see all their own fields.
    // 2. Others can only see an allowed list of fields (e.g. email,
    //    username).
    .onRead((police) => {
      // Reality: like the create/update/delete case above, we can only allow
      // users to see all fields of their own record, OR allow everyone to see
      // that allowed list of fields for all records. We can't have a
      // combination of both.
      return police.allowWithRestrictedGraphView((vc, query) => {
        query.dangerouslyBuildKnexQueryBuilder((kqb) =>
          kqb.clearSelect().select('email,username'),
        );
        return query;
      });
    });
}

Possible implementations

  • Implement post-query access control rules to filter out unauthorized information.

    • Pro: should be really simple to implement and understand.
    • Cons: we'll unnecessarily fetch information before dumping them, and we need to be careful to remove the unauthorized information from all data accesses and caches (or prevent that info from being cached).
    • Facebook seems to be doing this approach with a checkCanSee method, so confidence level โ†—๏ธ. Data is fetched and dumped before being cached by loader. Source: https://youtu.be/etax3aEe2dA?t=779, but as it's a public talk it may be overly simplified; I find it hard to believe that they'll fetch and throw away data on humongous data sets like comments/photos/statuses, but in Gent we mitigate this with restricted subgraph queries. Proposed API:
     class Police<QueryType extends GentQuery<Model>, Model extends GentModel> {
       ...
       allowWithRestrictedGraphView(
         queryBuilder: (vc: ViewerContext, query: QueryType) => QueryType,
         postQueryTransform?: (vc: ViewerContext, fetchedModel: Model) => Model | undefined = undefined
       ): this;
       ...
     }
     return police.allowWithRestrictedGraphView(
       (vc, query) => query,
       (vc, fetchedModel) =>
         fetchedModel.ownerId === vc.user.id
           ? fetchedModel
           : _.pick(fetchedModel, ['id', 'email', 'username']),
     );
    • Problem with the above proposal: Model may not be compatible with the transformed type, e.g. we may require name to be non-nullable in the database, but we may not want to expose name to end users. Possible solutions:
      • Just set non-nullable fields to some default value instead of outright nullifying them. Non-nullable to-one edges will still be a problem as we can't really put a default edge for these. Solutions:
        • Require all edges to be nullable (which currently makes both nullable in SQL and TS). This may be the ideal solution for a system with multiple backends, as it may be impossible to actually enforce any non-nullability. But of course, if we're backed by SQL we'll lose our ability to enforce that relationships exist. For this, we could decouple SQL and TypeScript edge nullability.
        • Define a default edge value. This seems messy.
      • Decouple database nullability from TypeScript class property nullability. This will allow us to enforce non-nullability on the database while still ensuring that the runtime model classes are typed correctly.
      • Allow Police to return another OutputModel type. This may be problematic if we still want Police to sometimes output the original type; e.g. we may want to output both User and OtherUser types. However, this approach may work if both types are compatible, or if we decouple the storage model type from the business layer's type (and eventually the exposed API type).
      • Just #wontfix
  • Somehow implement intent-based access control rules, e.g. getting a list of users' info vs getting one user's info.

    • Con: I suspect this will get unmanageable quickly, since the schema will now need to be aware of actions that can be performed on the entity.
  • Somehow implement query splitting, e.g. splitting the original query for all users into 2 queries, one with the query SELECT <authorized fields>... and the other SELECT * ... WHERE id=....

    • Con: additional query needed, design is unclear

RFC: Implement system to optionally execute observer hooks in a non-blocking fashion

GentMutator currently waits for all observer hook promises to resolve before continuing with its next steps. As these hooks should support slow work such as network requests (for logging, cache updates, search index updates, sending emails, etc) or other long-running, non-urgent computations, it may be a good idea to implement a non-blocking async runner that can execute such tasks without blocking the mutator from progressing.

Running hooks in such an async fashion should be optional, as there are many cases where we do want these hooks to block.

Possible implementations

  • React's experimental scheduler, a cooperative scheduling system that supports interruption and job priorities. It could possibly be used in Gent to allow our hooks to schedule work to be executed when the server is idle, while remaining responsive to new requests. An introduction to how it's used in React concurrent mode is available in this blog post.

Remove Lodash dependency

Currently, we're using Lodash as it's convenient. However, we want to be a good package with as few dependencies as possible. Lodash is not strictly necessary and should be replaced with plain util functions.

RFC: Implement tests

Test coverage is a miserable 20%, and we definitely want to increase that. However, as a lot of the code does code generation, the typical unit test approach won't work as that will not test the generated code.

Possible implementations

  • Only use integration tests for code generating code and on generated code. Have tests generate files, and write other tests for the generated files. This will allow Jest to calculate the test coverage of both the generating and generated code.
  • Generate tests. This will also help Gent users to increase their code coverage without having to write tests for all that generated code. This will likely become messy though due to the amount of generated code required, and the test generators will likely also need to be tested.

Implement hooks

Current wish list:

  • before/after CRUD
  • Mechanism to operate on IDs only or force load?
  • Ability to interrupt operation

Support multiple schema locations

Currently, we assume that all schemas are stored in a "./src/gents" folder. We need to support multiple schema folders to support larger apps.

  • Allow gentgen to look in multiple directories. It is currently hardcoded to "./src/gents" (#3).
  • Modify file import generation to somehow look for referenced schemas (as we assume all schemas are stored in one folder, we currently assume the component can be found at the relative path ../<entity class>/)

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.