Skip to content

Commit

Permalink
Merge pull request #523 from writer/dev
Browse files Browse the repository at this point in the history
chore: Merge for release
  • Loading branch information
ramedina86 authored Aug 16, 2024
2 parents b35cee4 + 1026de3 commit 2f57da9
Show file tree
Hide file tree
Showing 55 changed files with 3,517 additions and 1,264 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "18.x"
node-version: "20.x"
cache: npm

- name: install python3 environment
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "18.x"
node-version: "20.x"
cache: npm

- name: install python3 environment
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "18.x"
node-version: "20.x"
cache: npm

- name: install python3 environment
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "18.x"
node-version: "20.x"
cache: npm

- name: install python3 environment
Expand Down
14 changes: 9 additions & 5 deletions alfred/ci.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
def ci(front, back, e2e, docs):
no_flags = (not front and not back and not e2e and not docs)

if front or no_flags:
alfred.invoke_command("npm.lint")
alfred.invoke_command("npm.build")
if back or no_flags:
alfred.invoke_command("ci.mypy")
alfred.invoke_command("ci.ruff")
alfred.invoke_command("ci.pytest")
if front or no_flags:
alfred.invoke_command("npm.lint")
alfred.invoke_command("npm.build")
if docs or no_flags:
alfred.invoke_command("npm.docs.test")
if e2e:
Expand All @@ -32,8 +32,12 @@ def ci_mypy():
alfred.run("mypy ./src/writer --exclude app_templates/*")

@alfred.command("ci.ruff", help="linting with ruff")
def ci_ruff():
alfred.run("ruff check")
@alfred.option('--fix', '-f', help="fix linting errors", is_flag=True, default=False)
def ci_ruff(fix):
if fix:
alfred.run("ruff check --fix")
else:
alfred.run("ruff check")

@alfred.command("ci.pytest", help="run pytest on ./tests")
def ci_test():
Expand Down
2 changes: 1 addition & 1 deletion docs/components/component_page.mdx.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,4 @@ A function, in this example `handle_event`, should be implemented in your code t

## Reference

* <a href="https://github.com/streamsync-cloud/streamsync/blob/dev/src/ui/{{fileRef}}" target="_blank" >Explore this component's source code on GitHub</a>
* <a href="https://github.com/writer/writer-framework/blob/dev/src/ui/{{fileRef}}" target="_blank" >Explore this component's source code on GitHub</a>
46 changes: 15 additions & 31 deletions docs/framework/authentication.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
title: "Authentication"
---

The Writer Framework authentication module allows you to restrict access to your application.

Framework will be able to authenticate a user through an identity provider such as Google, Microsoft, Facebook, Github, Auth0, etc.
The Writer Framework authentication module allows you to restrict access to your application. Framework will be able to authenticate a user through an identity provider such as Google, Microsoft, Facebook, Github, Auth0, etc.

<Warning>
Authentication is done before accessing the application. It is not possible to
Expand All @@ -13,19 +11,13 @@ Framework will be able to authenticate a user through an identity provider such

## Use Basic Auth

Basic Auth is a simple authentication method that uses a username and password. Authentication configuration is done in [the `server_setup.py` module](custom-server.md).

::: warning Password authentication is not safe for critical application
Basic Auth authentication is not secure for critical applications.
Basic Auth is a simple authentication method that uses a username and password. Authentication configuration is done in the [server_setup.py module](/framework/custom-server).

A user can intercept the plaintext password if https encryption fails.
It may also try to force password using brute force attacks.

For added security, it's recommended to use identity provider (Google, Microsoft, Facebook, Github, Auth0, etc.).
:::
<Warning>
Password authentication and Basic Auth are not sufficiently secure for critical applications. If HTTPS encryption fails, a user could potentially intercept passwords in plaintext. Additionally, these methods are vulnerable to brute force attacks that attempt to crack passwords. To enhance security, it is advisable to implement authentication through trusted identity providers such as Google, Microsoft, Facebook, GitHub, or Auth0.
</Warning>

*server_setup.py*
```python
```python server_setup.py
import os
import writer.serve
import writer.auth
Expand All @@ -41,12 +33,12 @@ writer.serve.register_auth(auth)
### Brute force protection

A simple brute force protection is implemented by default. If a user fails to log in, the IP of this user is blocked.
Writer framework will ban the IP from either the X-Forwarded-For header or the X-Real-IP header or the client IP address.
Writer framework will ban the IP from either the `X-Forwarded-For` header or the `X-Real-IP` header or the client IP address.

When a user fails to log in, they wait 1 second before they can try again. This time can be modified by
modifying the value of delay_after_failure.
modifying the value of `delay_after_failure`.

<img src="./images/auth_too_many_request.png" style="width: 100%; margin: auto">
![429](/framework/images/429.png)

## Use OIDC provider

Expand All @@ -55,9 +47,7 @@ Here is an example configuration for Google.

![Authentication OIDC Principle](/framework/images/auth.png)

**server_setup.py**

```python
```python server_setup.py
import os
import writer.serve
import writer.auth
Expand Down Expand Up @@ -88,9 +78,7 @@ The Writer Framework provides pre-configured OIDC providers. You can use them di

You have to register your application into [Google Cloud Console](https://console.cloud.google.com/).

_server_setup.py_

```python
```python server_setup.py
import os
import writer.serve
import writer.auth
Expand All @@ -108,9 +96,7 @@ writer.serve.register_auth(oidc)

You have to register your application into [Github](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app#registering-a-github-app)

_server_setup.py_

```python
```python server_setup.py
import os
import writer.serve
import writer.auth
Expand All @@ -128,9 +114,8 @@ writer.serve.register_auth(oidc)

You have to register your application into [Auth0](https://auth0.com/).

_server_setup.py_

```python
```python server_setup.py
import os
import writer.serve
import writer.auth
Expand All @@ -147,13 +132,14 @@ writer.serve.register_auth(oidc)

### Authentication workflow

<img src="./framework/images/authentication_oidc.png" />
<img src="/framework/images/authentication_oidc.png" />

## User information in event handler

When the `user_info` route is configured, user information will be accessible
in the event handler through the `session` argument.


```python
def on_page_load(state, session):
email = session['userinfo'].get('email', None)
Expand Down Expand Up @@ -189,8 +175,6 @@ The default authentication error page look like this:

<img src="/framework/images/auth_unauthorized_default.png" />

_streamsync.auth.Unauthorized_

| Parameter | Description |
| ----------- | ---------------------- |
| status_code | HTTP status code |
Expand Down
10 changes: 5 additions & 5 deletions docs/framework/backend-driven-ui.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ with ui.find(container):

### Component methods

UI manager contains methods linked to each front-end component. For example, in previous code snippets we provide a `ui.Text` method, which is used for creating [Text components](https://www.streamsync.cloud/component-list.html#text).
UI manager contains methods linked to each front-end component. For example, in previous code snippets we provide a `ui.Text` method, which is used for creating [Text components](https://dev.writer.com/components/text).

This method expects `content: dict` as first argument, which enables you to set the field properties of the component, through corresponding keys:
```python
Expand Down Expand Up @@ -147,7 +147,7 @@ In addition to `content`, a set of fields which is specific to the component typ
</Note>
- **`position: int`**: Determines the display order of the component in relation to its siblings.
Position `0` means that the component is the first child of its parent.
Position `-2` is used for components – such as [sidebars](https://www.streamsync.cloud/component-list.html#sidebar) – that have a specific reserved position not related to their siblings.
Position `-2` is used for components – such as [sidebars](https://dev.writer.com/components/sidebar) – that have a specific reserved position not related to their siblings.
```python
ui.Text(
{"text": "Hello Parent, I'm your first child!"},
Expand All @@ -170,7 +170,7 @@ In addition to `content`, a set of fields which is specific to the component typ

ui.Text({"text": "My visibility depends on the @{my_var}!"}, visible="my_var")
```
- **`handlers: dict[str, callable]`**: Attaches [event handlers](https://www.streamsync.cloud/event-handlers.html) to the component. Each dictionary key represents an event, and its value is the corresponding handler.:
- **`handlers: dict[str, callable]`**: Attaches [event handlers](https://dev.writer.com/framework/event-handlersl) to the component. Each dictionary key represents an event, and its value is the corresponding handler.:
```python
def increment(state):
state["counter"] += 1
Expand All @@ -190,7 +190,7 @@ In addition to `content`, a set of fields which is specific to the component typ
# Both approaches yield the same outcome.
```
*A component can be linked to multiple event handlers.*
- **`binding: dict[str, str]`**: Links the component to a state variable via [binding](https://www.streamsync.cloud/builder-basics.html#binding). The dictionary key is the bindable event, and the value is the state variable's name:
- **`binding: dict[str, str]`**: Links the component to a state variable via [binding](https://dev.writer.com/framework/builder-basics#binding). The dictionary key is the bindable event, and the value is the state variable's name:
```python
initial_state = wf.init_state({
"header_text": "Default Text"
Expand Down Expand Up @@ -269,4 +269,4 @@ with ui.refresh_with(id="cmc-column-1"):
{"text": 'To Hello World, or not to Hello World?'},
id="hello-world-new"
)
```
```
Loading

0 comments on commit 2f57da9

Please sign in to comment.