{ "info": { "author": "David P Hilton", "author_email": "david.hilton.p@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Database" ], "description": "# Overview\n\nsqlalchemy_auth provides authorization mechanisms for SQLAlchemy DB access.\n\nIt is easy to use, and easy to bypass when needed.\n\n1. You set a `badge` on a session, which is passed to various handlers.\n2. All mapped classes can add implicit filters on queries and implicit data on inserts.\n3. All mapped classes can selectively block attribute access.\n\nYour `badge` is shared between all queries and mapped class instances within a session.\n\n\n# Getting Started\n\n### Session\n\nCreate a session using the AuthSession and AuthQuery classes:\n\n```python\nSession = sessionmaker(bind=engine, class_=AuthSession, query_cls=AuthQuery, badge=DENY)\nsession = Session()\n```\n\nBy default you don't need no stinking `badge`. It is set to `ALLOW`, bypassing all auth\nmechanisms (the default is overridden above). Change `badge` from `ALLOW` to enable\nauthorization:\n\n```python\nsession.badge=badge\n```\n\nTemporarily switch `badge`:\n\n```python\nwith session.switch_badge(badge):\n ...\n```\n\n`badge` can be anything (the current user, their role, etc.), and will be passed in to \n`add_auth_filters` and `add_auth_insert_data` (unless it's `ALLOW` or `DENY`).\n\n\n### Filters\n\nTo add filters, define `add_auth_filters`:\n\n```python\nclass Data(Base):\n __tablename__ = \"data\"\n\n id = Column(Integer, primary_key=True)\n owner = Column(Integer)\n data = Column(String)\n\n @classmethod\n def add_auth_filters(cls, query, badge):\n return query.filter_by(owner=badge.user_id)\n```\n\n\n### Inserts\n\nTo add data on insert, define `add_auth_insert_data`:\n\n```python\nclass Data(Base):\n __tablename__ = \"data\"\n\n id = Column(Integer, primary_key=True)\n owner = Column(Integer)\n data = Column(String)\n\n def add_auth_insert_data(self, badge):\n self.owner = badge.user_id\n```\n\n\n### Default Filters and Inserts\n\nIf your `Base` inherits from `AuthBase`, you will inherit no-op `add_auth_filters` \nand `add_auth_insert_data` methods.\n\n\n### Attribute Blocking\n\nTo block attributes, inherit from the `BlockBase` class (you can also use\nmixins instead of `declarative_base(cls=BlockBase)`):\n\n```python\nBase = declarative_base(cls=BlockBase)\n\nclass AttributeCheck(Base):\n __tablename__ = \"attributecheck\"\n\n id = Column(Integer, primary_key=True)\n owner = Column(String)\n data = Column(String)\n secret = Column(String)\n\n def _blocked_read_attributes(self, badge):\n if self.owner == badge.user_id:\n return []\n return [\"secret\"]\n\n def _blocked_write_attributes(self, badge):\n blocked = [\"id\", \"owner\"]\n if self.owner != badge.user_id:\n blocked.append(\"data\")\n return blocked\n```\n\nThese methods are only called if badge != `ALLOW` and you are within a transaction.\nBy default, `_blocked_write_attributes` calls `_blocked_read_attributes`.\n\nFour convenience methods are defined:\n\n`readable_attrs()`, `read_blocked_attrs()`, `writable_attrs()` and `write_blocked_attrs()`\n\nHere are some examples of attribute blocking:\n\n```python\na = session.query(AttributeCheck).one()\n\nif \"secret\" in a.readable_attrs():\n display_secret(a)\n\ntry:\n a.data = \"value\"\nexcept AuthException:\n raise\n```\n\nAttribute blocking is only effective for instances of the mapped class.\n\n\n# Gotchas\n\n### One Badge per Session/Query/Objects Group\n\nOnly one badge exists between a session, its queries and returned objects.\nFor example:\n\n```python\nsession.badge = ALLOW\nquery = session.query(Data)\nunfiltered = query.all()\n\nsession.badge = badge\nfiltered = query.all()\n```\n\nIn this example, `unfiltered` will contain all Data objects, but the same \nquery later would return a `filtered` subset.\n\n\n### Mixed Permissions of Objects\n\nRelationships may be loaded with a different badge from their parent/child.\n\n```python\nsession.badge = badge\nshared_data = session.query(Data).first()\n\nsession.badge = ALLOW\nshared_data.owners\n\nsession.badge = badge\nshared_data.owners\n```\n\nIn the above example the `owners` relationship is loaded without filtering.\nChanging `badge` does not invalidate or reload `owners`; it will persist and\nnot be filtered.\n\n`session.expunge_all()` will invalidate all objects, so all objects will be\nre-filtered. `session.expunge(shared_data)` would also work above.\n\n\n### Scoped Session Usage\n\nTo support `scoped_session.query` style syntax with `badge` and `switch_badge`, you must run\n`instrument_scoped_session` on the value returned by `sqlalchemy.orm.scoped_session()`.\n\nIf you do not, setting `badge` will have no effect and calling `switch_badge` will raise\n`AttributeError: 'scoped_session' object has no attribute 'switch_badge'`.\n\n\n### Attribute Blocking Limitations\n\nAttribute blocking relies on the object being an instance of the class with blocks.\nIn the following example, `add_auth_filters` is applied, but blocks are not:\n\n```python\nobj = session.query(Class.attr, Class.blocked_attr).first()\nobj.blocked_attr = \"foo\"\n```\n\nSimilarly, `update` bypasses attribute blocks:\n\n```python\nquery = session.query(Class.blocked).update({Class.blocked: \"unchecked write\"})\n```\n\n### BakedQueries not Cached\n\nBakedQuery will correctly execute, but will not be baked/cached.\n\nsqlalchemy_auth hooks sqlalchemy's compilation, which only occurs once per\nBakedQuery. The query would be baked with one badge, forever.\n\nThis would include relationship queries.\n\n\n--------------------------\n\nSee auth_query_test.py for end-to-end examples.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/dhiltonp/sqlalchemy_auth", "keywords": "", "license": "mit", "maintainer": "", "maintainer_email": "", "name": "sqlalchemy_auth", "package_url": "https://pypi.org/project/sqlalchemy_auth/", "platform": "any", "project_url": "https://pypi.org/project/sqlalchemy_auth/", "project_urls": { "Homepage": "https://github.com/dhiltonp/sqlalchemy_auth" }, "release_url": "https://pypi.org/project/sqlalchemy_auth/1.2.8/", "requires_dist": [ "sqlalchemy" ], "requires_python": "", "summary": "Provides authorization mechanisms for SQLAlchemy", "version": "1.2.8" }, "last_serial": 4004806, "releases": { "1.2.0": [ { "comment_text": "", "digests": { "md5": "36db126f5c8a3d986a25875bf1b684f8", "sha256": "08c904c087ebdc7d798fd78c273cf97d6d8f56e66bb5fcdb7f1b8c037efc100f" }, "downloads": -1, "filename": "sqlalchemy_auth-1.2.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "36db126f5c8a3d986a25875bf1b684f8", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 11120, "upload_time": "2018-02-12T07:50:53", "url": "https://files.pythonhosted.org/packages/94/2e/fd4113019984d3262f479eba0212e2d6b0f7d08343c4ba651c5468a45fdd/sqlalchemy_auth-1.2.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "923712d9fd17d86345fa81a57b90cbf9", "sha256": "9d253cf8529ada7f62b24b49904cbe0df55884f36ff1ccbf092766d76765ddb6" }, "downloads": -1, "filename": "sqlalchemy_auth-1.2.0.tar.gz", "has_sig": false, "md5_digest": "923712d9fd17d86345fa81a57b90cbf9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13733, "upload_time": "2018-02-12T07:50:52", "url": "https://files.pythonhosted.org/packages/1c/19/df38d8514b38998bbd240c6a6b084e95c481c7aea37b37bf51f544de17c5/sqlalchemy_auth-1.2.0.tar.gz" } ], "1.2.2": [ { "comment_text": "", "digests": { "md5": "988a66408f7cdea152efccdb5657c48b", "sha256": "571492a977dbb6ecaa0abe03abc2bfbf15617879c642e38d143dce2076c0659e" }, "downloads": -1, "filename": "sqlalchemy_auth-1.2.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "988a66408f7cdea152efccdb5657c48b", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 11160, "upload_time": "2018-02-12T08:24:07", "url": "https://files.pythonhosted.org/packages/d1/c3/f765ce4a2ec9d024dee6eec94240e0972c9d3bcee39f1a1fa1d60ccd6d56/sqlalchemy_auth-1.2.2-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "bcd145d8644a00490def203fc238fb6b", "sha256": "374dbd454f9e96428c04a2320636797b6ba0bbe2dc60ad98ffdbc6ea0fce3cd8" }, "downloads": -1, "filename": "sqlalchemy_auth-1.2.2.tar.gz", "has_sig": false, "md5_digest": "bcd145d8644a00490def203fc238fb6b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13739, "upload_time": "2018-02-12T08:24:02", "url": "https://files.pythonhosted.org/packages/a9/9c/00fe64675f87df50e842bb7f998facab2cdfac49ae85f2bc2fcc11425719/sqlalchemy_auth-1.2.2.tar.gz" } ], "1.2.3": [ { "comment_text": "", "digests": { "md5": "80bef171b10fd1bfdcd4ee3a79c24de7", "sha256": "a7990a6494290dfadfbb43369db3fadb02da82f377932a15913289cb2b2d283b" }, "downloads": -1, "filename": "sqlalchemy_auth-1.2.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "80bef171b10fd1bfdcd4ee3a79c24de7", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 11235, "upload_time": "2018-02-12T09:51:57", "url": "https://files.pythonhosted.org/packages/54/f1/0b3dcb13f9d6e153de72fc064c2d20163e21eb78a54c8157f69a281f8700/sqlalchemy_auth-1.2.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "29513a5cfe093f3dca2952992a85466f", "sha256": "cb1689852c1c832a26cdac5b292c597c5aaae1d1b6ac274d12310694338cd1c3" }, "downloads": -1, "filename": "sqlalchemy_auth-1.2.3.tar.gz", "has_sig": false, "md5_digest": "29513a5cfe093f3dca2952992a85466f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13462, "upload_time": "2018-02-12T09:51:55", "url": "https://files.pythonhosted.org/packages/f3/97/4e1a5879dff2ab664ec33baa7dc1de7132a34927ae4efa939c35c99a00f3/sqlalchemy_auth-1.2.3.tar.gz" } ], "1.2.4": [ { "comment_text": "", "digests": { "md5": "2a7add29b9a64852e7db9e9cc95b3936", "sha256": "ee06beec23d08ad06639913aae29551c2fe7c30a5c13570e6f6069e3a30d588a" }, "downloads": -1, "filename": "sqlalchemy_auth-1.2.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "2a7add29b9a64852e7db9e9cc95b3936", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 11690, "upload_time": "2018-02-12T21:36:51", "url": "https://files.pythonhosted.org/packages/fc/30/a1c9b71e48772350188c663e849c45458e5da7755f4d665dae242ab3c38a/sqlalchemy_auth-1.2.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e007dd248e4f7a6bddad82c1b8b7d661", "sha256": "83cd0a5f9e6ba0a5ec11e1b1a9a491a06dfe1c5e880bb1017246cdb2f5f6e9a1" }, "downloads": -1, "filename": "sqlalchemy_auth-1.2.4.tar.gz", "has_sig": false, "md5_digest": "e007dd248e4f7a6bddad82c1b8b7d661", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12202, "upload_time": "2018-02-12T21:36:49", "url": "https://files.pythonhosted.org/packages/1f/7b/69cf06cf76a6d29999bc923f50ac11d9b9aef0c383f07785e8d53d959a48/sqlalchemy_auth-1.2.4.tar.gz" } ], "1.2.5": [ { "comment_text": "", "digests": { "md5": "1b34d8033c12f060f6cc75bffb4951f4", "sha256": "0b03c46e25cc13cd3a5772ba36864368c8feb47c668020480f05d9c374156b03" }, "downloads": -1, "filename": "sqlalchemy_auth-1.2.5.tar.gz", "has_sig": false, "md5_digest": "1b34d8033c12f060f6cc75bffb4951f4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14299, "upload_time": "2018-02-28T22:14:20", "url": "https://files.pythonhosted.org/packages/e3/2c/dd1836df4fe6868feb1f717d0b1657f6d1e2407faa1e28980ce39cfd96db/sqlalchemy_auth-1.2.5.tar.gz" } ], "1.2.8": [ { "comment_text": "", "digests": { "md5": "4c22f6ae685b91667789d52522cbf03b", "sha256": "7b8647340bd15dd66fd9b33bb220ceadca37124e867db7d1e8c67c14a2638a9d" }, "downloads": -1, "filename": "sqlalchemy_auth-1.2.8-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "4c22f6ae685b91667789d52522cbf03b", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 14029, "upload_time": "2018-06-26T19:37:23", "url": "https://files.pythonhosted.org/packages/f6/d7/7bf0917bd4c15d4324ba52a6767d684c78f42d9d2afc77bb858af5037a81/sqlalchemy_auth-1.2.8-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e22b2f2a849468a6a6dd59b644d6af67", "sha256": "5d2454bb05ffee1f40a5376b7416d3bf1858ed63e15f67671de0d879a0e308e7" }, "downloads": -1, "filename": "sqlalchemy_auth-1.2.8.tar.gz", "has_sig": false, "md5_digest": "e22b2f2a849468a6a6dd59b644d6af67", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13617, "upload_time": "2018-06-26T19:37:25", "url": "https://files.pythonhosted.org/packages/ff/96/ec8e1643c385e96a978510b4943bcc2735c43f7c70d8c95836604cbb6201/sqlalchemy_auth-1.2.8.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "4c22f6ae685b91667789d52522cbf03b", "sha256": "7b8647340bd15dd66fd9b33bb220ceadca37124e867db7d1e8c67c14a2638a9d" }, "downloads": -1, "filename": "sqlalchemy_auth-1.2.8-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "4c22f6ae685b91667789d52522cbf03b", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 14029, "upload_time": "2018-06-26T19:37:23", "url": "https://files.pythonhosted.org/packages/f6/d7/7bf0917bd4c15d4324ba52a6767d684c78f42d9d2afc77bb858af5037a81/sqlalchemy_auth-1.2.8-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e22b2f2a849468a6a6dd59b644d6af67", "sha256": "5d2454bb05ffee1f40a5376b7416d3bf1858ed63e15f67671de0d879a0e308e7" }, "downloads": -1, "filename": "sqlalchemy_auth-1.2.8.tar.gz", "has_sig": false, "md5_digest": "e22b2f2a849468a6a6dd59b644d6af67", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13617, "upload_time": "2018-06-26T19:37:25", "url": "https://files.pythonhosted.org/packages/ff/96/ec8e1643c385e96a978510b4943bcc2735c43f7c70d8c95836604cbb6201/sqlalchemy_auth-1.2.8.tar.gz" } ] }