mirror of
https://github.com/LukeHagar/connexion.git
synced 2025-12-06 04:19:26 +00:00
Convert README from rst to md (#1772)
rst lacks different features on both Github and PyPI, making it difficult to build an rst README that will be rendered well on both. [The release pipeline was failing due to this.](https://github.com/spec-first/connexion/actions/runs/6724758517/job/18277703972)
This commit is contained in:
@@ -1,20 +0,0 @@
|
|||||||
Contributing to Connexion/TODOs
|
|
||||||
===============================
|
|
||||||
|
|
||||||
We welcome your ideas, issues, and pull requests. Just follow the usual/standard GitHub practices.
|
|
||||||
|
|
||||||
Unless you explicitly state otherwise in advance, any non trivial
|
|
||||||
contribution intentionally submitted for inclusion in this project by you
|
|
||||||
to the steward of this repository (Zalando SE, Berlin) shall be under the
|
|
||||||
terms and conditions of the `Apache License 2.0`_,
|
|
||||||
without any additional copyright information, terms or conditions.
|
|
||||||
|
|
||||||
|
|
||||||
TODOs
|
|
||||||
-----
|
|
||||||
|
|
||||||
If you'd like to become a more consistent contributor to Connexion, we'd love your help working on
|
|
||||||
these we have a list of `issues where we are looking for contributions`_.
|
|
||||||
|
|
||||||
.. _issues where we are looking for contributions: https://github.com/zalando/connexion/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22
|
|
||||||
.. _Apache License 2.0: README.rst#license
|
|
||||||
@@ -1,40 +1,34 @@
|
|||||||
.. raw:: html
|
<a id="top"></a>
|
||||||
|
<p align="center">
|
||||||
|
<img src="docs/images/logo_banner.svg" width="100%"/>
|
||||||
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://pypi.org/project/connexion"><img alt="coveralls" src="https://img.shields.io/pypi/status/connexion.svg?style=flat-square&color=brightgreen"></a>
|
||||||
|
<a href="https://pypi.org/project/connexion"><img alt="PyPI version" src="https://img.shields.io/pypi/v/connexion?color=brightgreen&style=flat-square"></a>
|
||||||
|
<a href="https://github.com/spec-first/connexion/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/pypi/l/connexion?style=flat-square&color=brightgreen"></a>
|
||||||
|
<a href="https://github.com/spec-first/connexion/actions/workflows/pipeline.yml"><img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/spec-first/connexion/pipeline.yml?style=flat-square"></a>
|
||||||
|
<a href="https://coveralls.io/github/spec-first/connexion?branch=main"><img alt="Coveralls" src="https://img.shields.io/coverallsCoverage/github/spec-first/connexion?style=flat-square"></a>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<a href="https://connexion.readthedocs.io/en/stable/"><strong>Explore the docs »</strong></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
<a id="top"></a>
|
---
|
||||||
<p align="center">
|
|
||||||
<img src="docs/images/logo_banner.svg" width="100%"/>
|
|
||||||
</p>
|
|
||||||
<p align="center">
|
|
||||||
<a href="https://pypi.org/project/connexion"><img alt="coveralls" src="https://img.shields.io/pypi/status/connexion.svg?style=flat-square&color=brightgreen"></a>
|
|
||||||
<a href="https://pypi.org/project/connexion"><img alt="PyPI version" src="https://img.shields.io/pypi/v/connexion?color=brightgreen&style=flat-square"></a>
|
|
||||||
<a href="https://github.com/spec-first/connexion/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/pypi/l/connexion?style=flat-square&color=brightgreen"></a>
|
|
||||||
<a href="https://github.com/spec-first/connexion/actions/workflows/pipeline.yml"><img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/spec-first/connexion/pipeline.yml?style=flat-square"></a>
|
|
||||||
<a href="https://coveralls.io/github/spec-first/connexion?branch=main"><img alt="Coveralls" src="https://img.shields.io/coverallsCoverage/github/spec-first/connexion?style=flat-square"></a>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
<a href="https://connexion.readthedocs.io/en/stable/"><strong>Explore the docs »</strong></a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
Connexion is a modern Python web framework that makes spec-first and api-first development easy.
|
Connexion is a modern Python web framework that makes spec-first and api-first development easy.
|
||||||
You describe your API in an `OpenAPI`_ (or `Swagger`_) specification with as much detail as you
|
You describe your API in an [OpenAPI][OpenAPI] (or [Swagger][Swagger]) specification with as much
|
||||||
want and Connexion will guarantee that it works as you specified.
|
detail as you want and Connexion will guarantee that it works as you specified.
|
||||||
|
|
||||||
It works either standalone, or in combination with any ASGI or WSGI-compatible framework!
|
It works either standalone, or in combination with any ASGI or WSGI-compatible framework!
|
||||||
|
|
||||||
.. raw:: html
|
<p align="center">
|
||||||
|
<br>
|
||||||
|
<a href="https://connexion.readthedocs.io/en/latest/v3.html"><strong>📢 Connexion 3 was recently released! Read about the changes here »</strong></a>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
## ✨ Features
|
||||||
<br>
|
|
||||||
<a href="https://connexion.readthedocs.io/en/latest/v3.html"><strong>📢 Connexion 3 was recently released! Read about the changes here »</strong></a>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
✨ Features
|
|
||||||
===========
|
|
||||||
|
|
||||||
Connexion provides the following functionality **based on your specification**:
|
Connexion provides the following functionality **based on your specification**:
|
||||||
|
|
||||||
@@ -48,16 +42,13 @@ Connexion provides the following functionality **based on your specification**:
|
|||||||
|
|
||||||
Connexion also **helps you write your OpenAPI specification** and develop against it by providing a command line interface which lets you test and mock your specification.
|
Connexion also **helps you write your OpenAPI specification** and develop against it by providing a command line interface which lets you test and mock your specification.
|
||||||
|
|
||||||
.. code-block:: bash
|
```shell
|
||||||
|
|
||||||
connexion run openapi.yaml
|
connexion run openapi.yaml
|
||||||
|
```
|
||||||
|
|
||||||
.. raw:: html
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
|
|
||||||
<p align="right">(<a href="#top">back to top</a>)</p>
|
## 🪤 Why Connexion
|
||||||
|
|
||||||
🪤 Why Connexion
|
|
||||||
================
|
|
||||||
|
|
||||||
With Connexion, you write the spec first. Connexion then calls your Python
|
With Connexion, you write the spec first. Connexion then calls your Python
|
||||||
code, handling the mapping from the specification to the code. This
|
code, handling the mapping from the specification to the code. This
|
||||||
@@ -74,85 +65,74 @@ Some disadvantages of generating specifications based on code is that
|
|||||||
they often end up lacking details or mix your documentation with the implementation
|
they often end up lacking details or mix your documentation with the implementation
|
||||||
logic of your application.
|
logic of your application.
|
||||||
|
|
||||||
.. raw:: html
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
|
|
||||||
<p align="right">(<a href="#top">back to top</a>)</p>
|
## ⚒️ How to Use
|
||||||
|
|
||||||
⚒️ How to Use
|
### Installation
|
||||||
=============
|
|
||||||
|
|
||||||
Installation
|
|
||||||
------------
|
|
||||||
|
|
||||||
You can install connexion using pip:
|
You can install connexion using pip:
|
||||||
|
|
||||||
.. code-block:: bash
|
```shell
|
||||||
|
|
||||||
$ pip install connexion
|
$ pip install connexion
|
||||||
|
```
|
||||||
|
|
||||||
Connexion provides 'extras' with optional dependencies to unlock additional features:
|
Connexion provides 'extras' with optional dependencies to unlock additional features:
|
||||||
|
|
||||||
- ``swagger-ui``: Enables a Swagger UI console for your application.
|
- `swagger-ui`: Enables a Swagger UI console for your application.
|
||||||
- ``uvicorn``: Enables to run the your application using :code:`app.run()` for
|
- `uvicorn`: Enables to run the your application using `app.run()` for
|
||||||
development instead of using an external ASGI server.
|
development instead of using an external ASGI server.
|
||||||
- ``flask``: Enables the ``FlaskApp`` to build applications compatible with the Flask
|
- `flask`: Enables the `FlaskApp` to build applications compatible with the Flask
|
||||||
ecosystem.
|
ecosystem.
|
||||||
|
|
||||||
You can install them as follows:
|
You can install them as follows:
|
||||||
|
|
||||||
.. code-block:: bash
|
```shell
|
||||||
|
|
||||||
$ pip install connexion[swagger-ui]
|
$ pip install connexion[swagger-ui]
|
||||||
$ pip install connexion[swagger-ui,uvicorn].
|
$ pip install connexion[swagger-ui,uvicorn].
|
||||||
|
```
|
||||||
|
|
||||||
.. raw:: html
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
|
|
||||||
<p align="right">(<a href="#top">back to top</a>)</p>
|
### Creating your application
|
||||||
|
|
||||||
|
|
||||||
Creating your application
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
Connexion can be used either as a standalone application or as a middleware wrapping an existing
|
Connexion can be used either as a standalone application or as a middleware wrapping an existing
|
||||||
ASGI (or WSGI) application written using a different framework. The standalone application can be
|
ASGI (or WSGI) application written using a different framework. The standalone application can be
|
||||||
built using either the :code:`AsyncApp` or :code:`FlaskApp`.
|
built using either the `AsyncApp` or `FlaskApp`.
|
||||||
|
|
||||||
- The :code:`AsyncApp` is a lightweight application with native asynchronous support. Use it if you
|
- The `AsyncApp` is a lightweight application with native asynchronous support. Use it if you
|
||||||
are starting a new project and have no specific reason to use one of the other options.
|
are starting a new project and have no specific reason to use one of the other options.
|
||||||
|
|
||||||
.. code-block:: python
|
```Python
|
||||||
|
|
||||||
from connexion import AsyncApp
|
from connexion import AsyncApp
|
||||||
|
|
||||||
app = AsyncApp(__name__)
|
app = AsyncApp(__name__)
|
||||||
|
```
|
||||||
|
|
||||||
- The :code:`FlaskApp` leverages the `Flask` framework, which is useful if you're migrating from
|
- The `FlaskApp` leverages the `Flask` framework, which is useful if you're migrating from
|
||||||
connexion 2.X or you want to leverage the `Flask` ecosystem.
|
connexion 2.X or you want to leverage the `Flask` ecosystem.
|
||||||
|
|
||||||
.. code-block:: python
|
```python
|
||||||
|
|
||||||
from connexion import FlaskApp
|
from connexion import FlaskApp
|
||||||
|
|
||||||
app = FlaskApp(__name__)
|
app = FlaskApp(__name__)
|
||||||
|
```
|
||||||
|
|
||||||
- The :code:`ConnexionMiddleware` can be wrapped around any existing ASGI or WSGI application.
|
- The `ConnexionMiddleware` can be wrapped around any existing ASGI or WSGI application.
|
||||||
Use it if you already have an application written in a different framework and want to add
|
Use it if you already have an application written in a different framework and want to add
|
||||||
functionality provided by connexion
|
functionality provided by connexion
|
||||||
|
|
||||||
.. code-block:: python
|
```python
|
||||||
|
|
||||||
from asgi_framework import App
|
from asgi_framework import App
|
||||||
from connexion import ConnexionMiddleware
|
from connexion import ConnexionMiddleware
|
||||||
|
|
||||||
app = App(__name__)
|
app = App(__name__)
|
||||||
app = ConnexionMiddleware(app)
|
app = ConnexionMiddleware(app)
|
||||||
|
```
|
||||||
|
|
||||||
.. raw:: html
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
|
|
||||||
<p align="right">(<a href="#top">back to top</a>)</p>
|
### Registering an API
|
||||||
|
|
||||||
Registering an API
|
|
||||||
------------------
|
|
||||||
|
|
||||||
While you can register individual routes on your application, Connexion really shines when you
|
While you can register individual routes on your application, Connexion really shines when you
|
||||||
register an API defined by an OpenAPI (or Swagger) specification.
|
register an API defined by an OpenAPI (or Swagger) specification.
|
||||||
@@ -160,17 +140,16 @@ The operation described in your specification is automatically linked to your Py
|
|||||||
|
|
||||||
**run.py**
|
**run.py**
|
||||||
|
|
||||||
.. code-block:: python
|
```python
|
||||||
|
|
||||||
def post_greeting(name: str, greeting: str): # Paramaeters are automatically unpacked
|
def post_greeting(name: str, greeting: str): # Paramaeters are automatically unpacked
|
||||||
return f"{greeting} {name}", 200 # Responses are automatically serialized
|
return f"{greeting} {name}", 200 # Responses are automatically serialized
|
||||||
|
|
||||||
app.add_api("openapi.yaml")
|
app.add_api("openapi.yaml")
|
||||||
|
```
|
||||||
|
|
||||||
**openapi.yaml**
|
**openapi.yaml**
|
||||||
|
|
||||||
.. code-block:: yaml
|
```yaml
|
||||||
|
|
||||||
...
|
...
|
||||||
paths:
|
paths:
|
||||||
/greeting/{name}:
|
/greeting/{name}:
|
||||||
@@ -193,81 +172,62 @@ The operation described in your specification is automatically linked to your Py
|
|||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
|
```
|
||||||
|
|
||||||
.. raw:: html
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
|
|
||||||
<p align="right">(<a href="#top">back to top</a>)</p>
|
### Running your application
|
||||||
|
|
||||||
Running your application
|
If you installed connexion using `connexion[uvicorn]`, you can run it using the
|
||||||
------------------------
|
`run` method. This is only recommended for development:
|
||||||
|
|
||||||
If you installed connexion using :code:`connexion[uvicorn]`, you can run it using the
|
|
||||||
:code:`run` method. This is only recommended for development:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
|
```python
|
||||||
app.run()
|
app.run()
|
||||||
|
```
|
||||||
|
|
||||||
In production, run your application using an ASGI server such as `uvicorn`. If you defined your
|
In production, run your application using an ASGI server such as `uvicorn`. If you defined your
|
||||||
:code:`app` in a python module called :code:`run.py`, you can run it as follows:
|
`app` in a python module called `run.py`, you can run it as follows:
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
|
```shell
|
||||||
$ uvicorn run:app
|
$ uvicorn run:app
|
||||||
|
```
|
||||||
|
|
||||||
Or with gunicorn:
|
Or with gunicorn:
|
||||||
|
|
||||||
.. code-block:: bash
|
```shell
|
||||||
|
|
||||||
$ gunicorn -k uvicorn.workers.UvicornWorker run:app
|
$ gunicorn -k uvicorn.workers.UvicornWorker run:app
|
||||||
|
```
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
Now you're able to run and use Connexion!
|
Now you're able to run and use Connexion!
|
||||||
|
|
||||||
See the `examples`_ folder for more examples.
|
See the [examples][examples] folder for more examples.
|
||||||
|
|
||||||
.. raw:: html
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
|
|
||||||
<p align="right">(<a href="#top">back to top</a>)</p>
|
## 🙏 Thanks
|
||||||
|
|
||||||
🙏 Thanks
|
|
||||||
=========
|
|
||||||
|
|
||||||
We'd like to thank all of Connexion's contributors for working on this
|
We'd like to thank all of Connexion's contributors for working on this
|
||||||
project, Swagger/OpenAPI for their support, and Zalando for originally developing and releasing Connexion.
|
project, Swagger/OpenAPI for their support, and Zalando for originally developing and releasing Connexion.
|
||||||
|
|
||||||
Sponsors
|
### Sponsors
|
||||||
--------
|
|
||||||
|
|
||||||
.. image:: ./docs/images/sponsors/ML6.png
|
[][ML6]
|
||||||
:alt: GitHub Sponsors
|
|
||||||
:target: https://www.ml6.eu
|
|
||||||
|
|
||||||
|
|
|
||||||
Sponsors help us dedicate time to maintain Connexion. Want to help?
|
Sponsors help us dedicate time to maintain Connexion. Want to help?
|
||||||
|
|
||||||
.. raw:: html
|
<a href="https://github.com/sponsors/spec-first"><strong>Explore the options »</strong></a>
|
||||||
|
|
||||||
<a href="https://github.com/sponsors/spec-first"><strong>Explore the options »</strong></a>
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
|
|
||||||
.. raw:: html
|
## 📜 Changes
|
||||||
|
|
||||||
<p align="right">(<a href="#top">back to top</a>)</p>
|
A full changelog is maintained on the [GitHub releases page][Releases].
|
||||||
|
|
||||||
📜 Changes
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
==========
|
|
||||||
|
|
||||||
A full changelog is maintained on the `GitHub releases page`_.
|
## 🤲 Contributing
|
||||||
|
|
||||||
.. _GitHub releases page: https://github.com/spec-first/connexion/releases
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<p align="right">(<a href="#top">back to top</a>)</p>
|
|
||||||
|
|
||||||
🤲 Contributing
|
|
||||||
===============
|
|
||||||
|
|
||||||
We welcome your ideas, issues, and pull requests. Just follow the
|
We welcome your ideas, issues, and pull requests. Just follow the
|
||||||
usual/standard GitHub practices.
|
usual/standard GitHub practices.
|
||||||
@@ -275,14 +235,14 @@ usual/standard GitHub practices.
|
|||||||
For easy development, install connexion using poetry with all extras, and
|
For easy development, install connexion using poetry with all extras, and
|
||||||
install the pre-commit hooks to automatically run black formatting and static analysis checks.
|
install the pre-commit hooks to automatically run black formatting and static analysis checks.
|
||||||
|
|
||||||
.. code-block:: bash
|
```shell
|
||||||
|
|
||||||
pip install poetry
|
pip install poetry
|
||||||
poetry install --all-extras
|
poetry install --all-extras
|
||||||
pre-commit install
|
pre-commit install
|
||||||
|
```
|
||||||
|
|
||||||
You can find out more about how Connexion works and where to apply your changes by having a look
|
You can find out more about how Connexion works and where to apply your changes by having a look
|
||||||
at our `architecture <./docs/images/architecture.png>`_.
|
at our [architecture][Architecture].
|
||||||
|
|
||||||
Unless you explicitly state otherwise in advance, any non trivial
|
Unless you explicitly state otherwise in advance, any non trivial
|
||||||
contribution intentionally submitted for inclusion in this project by you
|
contribution intentionally submitted for inclusion in this project by you
|
||||||
@@ -290,34 +250,33 @@ to the steward of this repository shall be under the
|
|||||||
terms and conditions of Apache License 2.0 written below, without any
|
terms and conditions of Apache License 2.0 written below, without any
|
||||||
additional copyright information, terms or conditions.
|
additional copyright information, terms or conditions.
|
||||||
|
|
||||||
.. raw:: html
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
|
|
||||||
<p align="right">(<a href="#top">back to top</a>)</p>
|
## 📚 Recommended Resources
|
||||||
|
|
||||||
📚 Recommended Resources
|
|
||||||
========================
|
|
||||||
|
|
||||||
About the advantages of working spec-first:
|
About the advantages of working spec-first:
|
||||||
|
|
||||||
* `Blog Atlassian`_
|
* [Blog Atlassian][Blog Atlassian]
|
||||||
* `API guidelines Zalando`_
|
* [API guidelines Zalando][API guidelines Zalando]
|
||||||
* `Blog ML6`_
|
* [Blog ML6][Blog ML6]
|
||||||
* `Blog Zalando`_
|
* [Blog Zalando][Blog Zalando]
|
||||||
|
|
||||||
Tools to help you work spec-first:
|
Tools to help you work spec-first:
|
||||||
|
|
||||||
* `Online swagger editor`_
|
* [Online swagger editor][Online swagger editor]
|
||||||
* `VS Code plugin`_
|
* [VS Code plugin][VS Code plugin]
|
||||||
* `Pycharm plugin`_
|
* [Pycharm plugin][Pycharm plugin]
|
||||||
|
|
||||||
.. _v3 documentation: https://connexion.readthedocs.io/en/latest/v3.html
|
[OpenAPI]: https://openapis.org/
|
||||||
.. _OpenAPI: https://openapis.org/
|
[Swagger]: http://swagger.io/open-source-integrations/
|
||||||
.. _Swagger: http://swagger.io/open-source-integrations/
|
[Blog atlassian]: https://www.atlassian.com/blog/technology/spec-first-api-development
|
||||||
.. _Blog atlassian: https://www.atlassian.com/blog/technology/spec-first-api-development
|
[Blog ML6]: https://blog.ml6.eu/why-we-decided-to-help-maintain-connexion-c9f449877083
|
||||||
.. _Blog ML6: https://blog.ml6.eu/why-we-decided-to-help-maintain-connexion-c9f449877083
|
[Blog Zalando]: https://engineering.zalando.com/posts/2016/12/crafting-effective-microservices-in-python.html
|
||||||
.. _Blog Zalando: https://engineering.zalando.com/posts/2016/12/crafting-effective-microservices-in-python.html
|
[API guidelines Zalando]: https://opensource.zalando.com/restful-api-guidelines/#api-first
|
||||||
.. _API guidelines Zalando: https://opensource.zalando.com/restful-api-guidelines/#api-first
|
[Online swagger editor]: https://editor.swagger.io/
|
||||||
.. _Online swagger editor: https://editor.swagger.io/
|
[VS Code plugin]: https://marketplace.visualstudio.com/items?itemName=42Crunch.vscode-openapi
|
||||||
.. _VS Code plugin: https://marketplace.visualstudio.com/items?itemName=42Crunch.vscode-openapi
|
[Pycharm plugin]: https://plugins.jetbrains.com/plugin/14837-openapi-swagger-editor
|
||||||
.. _Pycharm plugin: https://plugins.jetbrains.com/plugin/14837-openapi-swagger-editor
|
[examples]: https://github.com/spec-first/connexion/blob/main/examples
|
||||||
.. _examples: ./examples
|
[ML6]: https://www.ml6.eu
|
||||||
|
[Releases]: https://github.com/spec-first/connexion/releases
|
||||||
|
[Architecture]: https://github.com/spec-first/connexion/blob/main/docs/images/architecture.png
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
name = "connexion"
|
name = "connexion"
|
||||||
version = "3.0.dev0"
|
version = "3.0.dev0"
|
||||||
description = "Connexion - API first applications with OpenAPI/Swagger"
|
description = "Connexion - API first applications with OpenAPI/Swagger"
|
||||||
readme = "README.rst"
|
readme = "README.md"
|
||||||
keywords = ["api", "swagger", "openapi"]
|
keywords = ["api", "swagger", "openapi"]
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
authors = [
|
authors = [
|
||||||
|
|||||||
Reference in New Issue
Block a user