Skip to content

Commit 2ff7be3

Browse files
Documented VSCode configuration
1 parent 7fcedf9 commit 2ff7be3

File tree

3 files changed

+70
-18
lines changed

3 files changed

+70
-18
lines changed

docs/customization.qmd

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ The project uses Poetry to manage dependencies:
1515
- Install dependencies: `poetry install`
1616
- Update all dependencies: `poetry update`
1717

18+
If you are using VSCode or Cursor as your IDE, you will need to select the Poetry-managed Python version as your interpreter for the project. To find the location of the Poetry-managed Python interpreter, run `poetry env info` and look for the `Path` field. Then, in VSCode, go to `View > Command Palette`, search for `Python: Select Interpreter`, and either select Poetry's Python version from the list (if it has been auto-detected) or "Enter interpreter path" manually.
19+
1820
### Testing
1921

2022
The project uses Pytest for unit testing. It's highly recommended to write and run tests before committing code to ensure nothing is broken!
@@ -96,7 +98,7 @@ We name our GET routes using the convention `read_<name>`, where `<name>` is the
9698
We divide our GET routes into authenticated and unauthenticated routes, using commented section headers in our code that look like this:
9799

98100
```python
99-
# -- Authenticated Routes --
101+
# --- Authenticated Routes ---
100102
```
101103

102104
Some of our routes take request parameters, which we pass as keyword arguments to the route handler. These parameters should be type annotated for validation purposes.
@@ -243,11 +245,16 @@ SQLModel is an Object-Relational Mapping (ORM) library that allows us to interac
243245
Our database models are defined in `utils/models.py`. Each model is a Python class that inherits from `SQLModel` and represents a database table. The key models are:
244246

245247
- `Organization`: Represents a company or team
246-
- `User`: Represents a user account
247-
- `Role`: Represents a discrete set of user permissions within an organization
248-
- `Permission`: Represents specific actions a user can perform
249-
- `RolePermissionLink`: Maps roles to their allowed permissions
250-
- `PasswordResetToken`: Manages password reset functionality
248+
- `User`: Represents a user account with name, email, and avatar
249+
- `Role`: Represents a set of permissions within an organization
250+
- `Permission`: Represents specific actions a user can perform (defined by ValidPermissions enum)
251+
- `PasswordResetToken`: Manages password reset functionality with expiration
252+
- `UserPassword`: Stores hashed user passwords separately from user data
253+
254+
Two additional models are used by SQLModel to manage many-to-many relationships; you generally will not need to interact with them directly:
255+
256+
- `UserRoleLink`: Maps users to their roles (many-to-many relationship)
257+
- `RolePermissionLink`: Maps roles to their permissions (many-to-many relationship)
251258

252259
Here's an entity-relationship diagram (ERD) of the current database schema, automatically generated from our SQLModel definitions:
253260

@@ -297,6 +304,17 @@ async def get_users(session: Session = Depends(get_session)):
297304

298305
The session automatically handles transaction management, ensuring that database operations are atomic and consistent.
299306

307+
There is also a helper method on the `User` model that checks if a user has a specific permission for a given organization. Its first argument must be a `ValidPermissions` enum value (from `utils/models.py`), and its second argument must be an `Organization` object or an `int` representing an organization ID:
308+
309+
```python
310+
permission = ValidPermissions.CREATE_ROLE
311+
organization = session.exec(select(Organization).where(Organization.name == "Acme Inc.")).first()
312+
313+
user.has_permission(permission, organization)
314+
```
315+
316+
You should create custom `ValidPermissions` enum values for your application and validate that users have the necessary permissions before allowing them to modify organization data resources.
317+
300318
#### Cascade deletes
301319

302320
Cascade deletes (in which deleting a record from one table deletes related records from another table) can be handled at either the ORM level or the database level. This template handles cascade deletes at the ORM level, via SQLModel relationships. Inside a SQLModel `Relationship`, we set:

docs/installation.qmd

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ If you use VSCode with Docker to develop in a container, the following VSCode De
1818
}
1919
```
2020

21-
Simply create a `.devcontainer` folder in the root of the project and add a `devcontainer.json` file in the folder with the above content. VSCode may prompt you to install the Dev Container extension if you haven't already, and/or to open the project in a container. If not, you can manually select "Dev Containers: Reopen in Container" from View > Command Palette.
21+
Simply create a `.devcontainer` folder in the root of the project and add a `devcontainer.json` file in the folder with the above content. VSCode may prompt you to install the Dev Container extension if you haven't already, and/or to open the project in a container. If not, you can manually select "Dev Containers: Reopen in Container" from `View > Command Palette`.
2222

2323
*IMPORTANT: If using this dev container configuration, you will need to set the `DB_HOST` environment variable to "host.docker.internal" in the `.env` file.*
2424

@@ -69,6 +69,12 @@ poetry shell
6969

7070
(Note: You will need to activate the shell every time you open a new terminal session. Alternatively, you can use the `poetry run` prefix before other commands to run them without activating the shell.)
7171

72+
### Configure IDE
73+
74+
If you are using VSCode or Cursor as your IDE, you will need to select the Poetry-managed Python version as your interpreter for the project. To find the location of the Poetry-managed Python interpreter, run `poetry env info` and look for the `Path` field. Then, in VSCode, go to `View > Command Palette`, search for `Python: Select Interpreter`, and either select Poetry's Python version from the list (if it has been auto-detected) or "Enter interpreter path" manually.
75+
76+
It is also recommended to install the [Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python) and [Quarto](https://marketplace.visualstudio.com/items?itemName=quarto.quarto) IDE extensions.
77+
7278
## Install documentation dependencies manually
7379

7480
### Quarto CLI

docs/static/documentation.txt

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,11 @@ with open(output_path, 'w', encoding='utf-8') as f:
192192
f.write(final_content)
193193
```
194194

195-
In line with the [llms.txt standard](https://llmstxt.org/), we have provided a Markdown-formatted prompt—designed to help LLM agents understand how to work with this template—as a [text file](docs/static/llms.txt). One use case for this file is to rename it to `.cursorrules` and place it in your project directory is using the Cursor IDE (see the [Cursor docs](https://docs.cursor.com/context/rules-for-ai) on this for more information).
195+
In line with the [llms.txt standard](https://llmstxt.org/), we have provided a Markdown-formatted prompt—designed to help LLM agents understand how to work with this template—as a text file: [llms.txt](docs/static/llms.txt).
196196

197-
We have also exposed the full Markdown-formatted project documentation as a [single text file](docs/static/documentation.txt) for easy downloading and embedding.
197+
One use case for this file, if using the Cursor IDE, is to rename it to `.cursorrules` and place it in your project directory (see the [Cursor docs](https://docs.cursor.com/context/rules-for-ai) on this for more information). Alternatively, you could use it as a custom system prompt in the web interface for ChatGPT, Claude, or the LLM of your choice.
198+
199+
We have also exposed the full Markdown-formatted project documentation as a [single text file](docs/static/documentation.txt) for easy downloading and embedding for RAG workflows.
198200

199201
## Contributing
200202

@@ -517,7 +519,7 @@ If you use VSCode with Docker to develop in a container, the following VSCode De
517519
}
518520
```
519521

520-
Simply create a `.devcontainer` folder in the root of the project and add a `devcontainer.json` file in the folder with the above content. VSCode may prompt you to install the Dev Container extension if you haven't already, and/or to open the project in a container. If not, you can manually select "Dev Containers: Reopen in Container" from View > Command Palette.
522+
Simply create a `.devcontainer` folder in the root of the project and add a `devcontainer.json` file in the folder with the above content. VSCode may prompt you to install the Dev Container extension if you haven't already, and/or to open the project in a container. If not, you can manually select "Dev Containers: Reopen in Container" from `View > Command Palette`.
521523

522524
*IMPORTANT: If using this dev container configuration, you will need to set the `DB_HOST` environment variable to "host.docker.internal" in the `.env` file.*
523525

@@ -568,6 +570,12 @@ poetry shell
568570

569571
(Note: You will need to activate the shell every time you open a new terminal session. Alternatively, you can use the `poetry run` prefix before other commands to run them without activating the shell.)
570572

573+
### Configure IDE
574+
575+
If you are using VSCode or Cursor as your IDE, you will need to select the Poetry-managed Python version as your interpreter for the project. To find the location of the Poetry-managed Python interpreter, run `poetry env info` and look for the `Path` field. Then, in VSCode, go to `View > Command Palette`, search for `Python: Select Interpreter`, and either select Poetry's Python version from the list (if it has been auto-detected) or "Enter interpreter path" manually.
576+
577+
It is also recommended to install the [Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python) and [Quarto](https://marketplace.visualstudio.com/items?itemName=quarto.quarto) IDE extensions.
578+
571579
## Install documentation dependencies manually
572580

573581
### Quarto CLI
@@ -659,6 +667,8 @@ The project uses Poetry to manage dependencies:
659667
- Install dependencies: `poetry install`
660668
- Update all dependencies: `poetry update`
661669

670+
If you are using VSCode or Cursor as your IDE, you will need to select the Poetry-managed Python version as your interpreter for the project. To find the location of the Poetry-managed Python interpreter, run `poetry env info` and look for the `Path` field. Then, in VSCode, go to `View > Command Palette`, search for `Python: Select Interpreter`, and either select Poetry's Python version from the list (if it has been auto-detected) or "Enter interpreter path" manually.
671+
662672
### Testing
663673

664674
The project uses Pytest for unit testing. It's highly recommended to write and run tests before committing code to ensure nothing is broken!
@@ -692,9 +702,11 @@ We find that mypy is an enormous time-saver, catching many errors early and grea
692702

693703
### Developing with LLMs
694704

695-
In line with the [llms.txt standard](https://llmstxt.org/), we have provided a Markdown-formatted prompt—designed to help LLM agents understand how to work with this template—as a [text file](static/llms.txt). One use case for this file is to rename it to `.cursorrules` and place it in your project directory is using the Cursor IDE (see the [Cursor docs](https://docs.cursor.com/context/rules-for-ai) on this for more information).
705+
In line with the [llms.txt standard](https://llmstxt.org/), we have provided a Markdown-formatted prompt—designed to help LLM agents understand how to work with this template—as a text file: [llms.txt](static/llms.txt).
706+
707+
One use case for this file, if using the Cursor IDE, is to rename it to `.cursorrules` and place it in your project directory (see the [Cursor docs](https://docs.cursor.com/context/rules-for-ai) on this for more information). Alternatively, you could use it as a custom system prompt in the web interface for ChatGPT, Claude, or the LLM of your choice.
696708

697-
We have also exposed the full Markdown-formatted project documentation as a [single text file](static/documentation.txt) for easy downloading and embedding.
709+
We have also exposed the full Markdown-formatted project documentation as a [single text file](static/documentation.txt) for easy downloading and embedding for RAG workflows.
698710

699711
## Project structure
700712

@@ -738,7 +750,7 @@ We name our GET routes using the convention `read_<name>`, where `<name>` is the
738750
We divide our GET routes into authenticated and unauthenticated routes, using commented section headers in our code that look like this:
739751

740752
```python
741-
# -- Authenticated Routes --
753+
# --- Authenticated Routes ---
742754
```
743755

744756
Some of our routes take request parameters, which we pass as keyword arguments to the route handler. These parameters should be type annotated for validation purposes.
@@ -885,11 +897,16 @@ SQLModel is an Object-Relational Mapping (ORM) library that allows us to interac
885897
Our database models are defined in `utils/models.py`. Each model is a Python class that inherits from `SQLModel` and represents a database table. The key models are:
886898

887899
- `Organization`: Represents a company or team
888-
- `User`: Represents a user account
889-
- `Role`: Represents a discrete set of user permissions within an organization
890-
- `Permission`: Represents specific actions a user can perform
891-
- `RolePermissionLink`: Maps roles to their allowed permissions
892-
- `PasswordResetToken`: Manages password reset functionality
900+
- `User`: Represents a user account with name, email, and avatar
901+
- `Role`: Represents a set of permissions within an organization
902+
- `Permission`: Represents specific actions a user can perform (defined by ValidPermissions enum)
903+
- `PasswordResetToken`: Manages password reset functionality with expiration
904+
- `UserPassword`: Stores hashed user passwords separately from user data
905+
906+
Two additional models are used by SQLModel to manage many-to-many relationships; you generally will not need to interact with them directly:
907+
908+
- `UserRoleLink`: Maps users to their roles (many-to-many relationship)
909+
- `RolePermissionLink`: Maps roles to their permissions (many-to-many relationship)
893910

894911
Here's an entity-relationship diagram (ERD) of the current database schema, automatically generated from our SQLModel definitions:
895912

@@ -939,6 +956,17 @@ async def get_users(session: Session = Depends(get_session)):
939956

940957
The session automatically handles transaction management, ensuring that database operations are atomic and consistent.
941958

959+
There is also a helper method on the `User` model that checks if a user has a specific permission for a given organization. Its first argument must be a `ValidPermissions` enum value (from `utils/models.py`), and its second argument must be an `Organization` object or an `int` representing an organization ID:
960+
961+
```python
962+
permission = ValidPermissions.CREATE_ROLE
963+
organization = session.exec(select(Organization).where(Organization.name == "Acme Inc.")).first()
964+
965+
user.has_permission(permission, organization)
966+
```
967+
968+
You should create custom `ValidPermissions` enum values for your application and validate that users have the necessary permissions before allowing them to modify organization data resources.
969+
942970
#### Cascade deletes
943971

944972
Cascade deletes (in which deleting a record from one table deletes related records from another table) can be handled at either the ORM level or the database level. This template handles cascade deletes at the ORM level, via SQLModel relationships. Inside a SQLModel `Relationship`, we set:

0 commit comments

Comments
 (0)