{"id":19090126,"url":"https://github.com/destrangis/odre","last_synced_at":"2025-08-21T19:08:57.401Z","repository":{"id":56933823,"uuid":"478588686","full_name":"destrangis/odre","owner":"destrangis","description":"Bottle extension class that provides user authentication","archived":false,"fork":false,"pushed_at":"2025-06-27T22:01:01.000Z","size":51,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-27T23:18:05.331Z","etag":null,"topics":["authentication","bottlepy","middleware","python3","session-management","web-development"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/destrangis.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-04-06T14:10:47.000Z","updated_at":"2025-06-27T22:01:05.000Z","dependencies_parsed_at":"2025-05-29T23:01:20.950Z","dependency_job_id":"26558eaa-dd66-4688-a09e-899cf452d35c","html_url":"https://github.com/destrangis/odre","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/destrangis/odre","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/destrangis%2Fodre","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/destrangis%2Fodre/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/destrangis%2Fodre/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/destrangis%2Fodre/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/destrangis","download_url":"https://codeload.github.com/destrangis/odre/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/destrangis%2Fodre/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271469154,"owners_count":24765118,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-21T02:00:08.990Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","bottlepy","middleware","python3","session-management","web-development"],"created_at":"2024-11-09T03:01:55.815Z","updated_at":"2025-08-21T19:08:57.340Z","avatar_url":"https://github.com/destrangis.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"====\nOdre\n====\n\nBottle plugin class that provides user authentication based on the ``pgusers`` module.\n\nUsage\n-----\n\nYou just need to import the ``Odre`` object, and use Bottle's ``install`` method to install an authentication wrapper to all the routes whose callback users the ``userinfo`` (or the keyword specified) parameter:\n\n.. code-block:: python\n\n    sample = bottle.Bottle()\n\n    authenticated = Odre(config=config.split(\"\\n\"), keyword=\"userinfo\")\n    sample.install(authenticated)\n\n    @sample.get(\"/hello/\u003cname\u003e\")\n    def hello(name, userinfo):\n        return f\"\u003cp\u003eHello \u003cb\u003e{name} {userinfo}\u003c/b\u003e\u003c/p\u003e\"\n\nIn the example above, when the route ``/hello/\u003cname\u003e`` is accessed for the first time, the user is shown a login form asking for credentials. Upon successful authentication, the user is supplied a token that is set either in a cookie or the client should supply it in the form of an ``Authorization: Bearer \u003ctoken\u003e`` header. The function is then injected the user information in the ```userinfo``` argument.\n\n.. _configuration:\n\nConfiguration\n-------------\n\nThe configuration is an .ini file similar to the following example:\n\n.. code-block:: ini\n\n    [app]\n    name = SAMPLE\n    cookie_name = sample_session_id\n    root_dir = /opt/webapp/dir\n    login_page = /opt/webapp/dir/html/login.html\n\n    [database]\n    host = localhost\n    port = 5432\n    user = sampleuser\n    password = sampleuser\n\n    [userspace]\n    name = SAMPLE\n    # SAMPLE is a different database than the app database and it possibly\n    # has different user, host, port etc.\n    host = localhost\n    port = 5432\n    user = sampleuser\n    password = sampleuser\n\n    [smtp]\n    host = mailhost.domain.com\n    port = 465\n\nThe [app] section\n~~~~~~~~~~~~~~~~~\n:name:\n  The name of the app. Must always be present.\n:cookie_name:\n  The name of the cookie that will be issued. This field is optional, if omitted the response to a successful login will be a json object with the token, which will be the responsibility of the front-end to send on every subsequent request in an ``Authorization: Bearer \u003ctoken\u003e`` header.\n:root_dir:\n  The root directory of the application. This is useful to locate the app's resources. Must always be present.\n:login_page:\n  The path to an html file that contains the login page. If omitted, a default login page will be issued, but it will be probably be too basic. The requirements for the login page are that it must send a form with the following fields: ``username``, ``password``, and ``proceed``. The ``proceed`` field must be a hidden file set to ``{0}`` so that ``Odre`` can substitute it for the path that was originally requested and, upon a successful login, redirect the user there. Alternatively, the front-end can log-in using the pre-installed ``/login`` route sending username and password in a json object with a ``Content-type`` header set to ``application/json``\n\nThe [userspace] section\n~~~~~~~~~~~~~~~~~~~~~~~\n:name:\n  The name of the ``pgusers`` userspace. A *userspace*, is a PostgreSQL database that contains the users and sessions and is handled by the ``pgusers`` module.\n:host:\n  The host where the userspace resides. If omitted, a local connection through a unix-domain socket is assumed.\n:port:\n  The port where PostgreSQL userspace listens. If omitted, Postgres default port 5432 is assumed.\n:user:\n  The PostgreSQL user for the userspace.\n:password:\n  The password for the PostgreSQL user for the userspace.\n\nThe [database] section\n~~~~~~~~~~~~~~~~~~~~~~\nThis section contains the parameters needed to connect to the app database. The fields are the same as those used to create a connection on the ``psycopg2`` module.\n\n:host:\n  The host where the PostgreSQL resides. If omitted, a local connection through a unix-domain socket is assumed.\n:port:\n  The port where PostgreSQL listens. If omitted, Postgres default port 5432 is assumed.\n:user:\n  The PostgreSQL user.\n:password:\n  The password for the PostgreSQL user.\n\nThe [smtp] section\n~~~~~~~~~~~~~~~~~~\nThis section contains the SMTP server parameters to send the user a *reset password* token when such functionality is implemented.\n\n\nThe API\n-------\n\n``app = Odre(config, keyword=\"userinfo\", prefix=\"\")``\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThis is the class constructor. ``Odre`` is a plugin for ``Bottle`` The parameter ``config`` can be used to specify the app configuration_. It can be:\n\n- A string, which is interpreted as a filename\n- A ConfigParser object\n- Any iterable yielding strings, e.g. a file-like object\n\nThe ``keyword`` parameter is the name of the variable that will be injected with the user information on authenticated routes.\nThe ``prefix`` parameter is an optional prefix for the routes that will be installed. E.g. if for any reason it's not desired to use ``/login`` as a route, we can give a value to prefix, for instance ``prefix = \"/odre\"`` so that the login function will be installed on ``/odre/login``.\n\n``@app.authenticated``\n~~~~~~~~~~~~~~~~~~~~~~\nThis decorator, applied before any route (i.e. *below* the routes) marks a\nfunction as accessible only to authenticated users. If the route is being requested\nfor the first time, or without a valid session token specified either in the\ncookie or in a bearer authorisation header, or the token has expired, the\nroute will return the login html page specified in the configuration, or a\nbasic, default login page. Example:\n\n.. code-block:: python\n\n    @app.get(\"/hello/\u003cname\u003e\")\n    @app.authenticated\n    def hello(name):\n        return f\"\u003cp\u003eHello \u003cb\u003e{name}\u003c/b\u003e\u003c/p\u003e\"\n\nThe ``/login`` pre-installed route\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nClient apps that don't want to present the user with the login html page for\nany reason, can always request the ``/login`` route via the ``POST`` http verb.\nThe route expects either a form with content type ``application/x-www-form-urlencoded``\nor an ``application/json`` with the following fields:\n\n:username:\n  The username\n:password:\n  The password\n:proceed:\n  A relative URI to proceed to upon successful authentication. This field is optional\n  and defaults to '/'\n\n\n\nLicense\n-------\nThis software is released with the **MIT License**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdestrangis%2Fodre","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdestrangis%2Fodre","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdestrangis%2Fodre/lists"}