Skip to content

Commit 7e14561

Browse files
authored
Merge pull request #23 from capless/feature/api
Feature/api
2 parents df4c74b + 0bc4369 commit 7e14561

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+4088
-541
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ share/python-wheels/
2929
.installed.cfg
3030
*.egg
3131
MANIFEST
32+
carcamp/
3233

3334
# PyInstaller
3435
# Usually these files are written by a python script from a template
@@ -130,3 +131,4 @@ dmypy.json
130131

131132
# Pyre type checker
132133
.pyre/
134+
/pfunk/carcamp/

CLI.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Command Line Interface (CLI)
2+
3+
## Create Project
4+
5+
```commandline
6+
pfunk init <project_name>
7+
```
8+
## Add Stage
9+
10+
```commandline
11+
pfunk add_stage <stage_name>
12+
```
13+
14+
## Publish
15+
16+
```commandline
17+
pfunk publish <stage_name>
18+
```
19+
## Create Admin User
20+
21+
```commandline
22+
pfunk create_admin_user <stage_name>
23+
```
24+
25+
## Seed Keys
26+
27+
```commandline
28+
pfunk seed_keys <stage_name>
29+
```
30+
31+
## Deploy
32+
33+
```commandline
34+
pfunk deploy <stage_name>
35+
```
36+
37+
## Run Server
38+
39+
```commandline
40+
pfunk local
41+
```

CONTRIBUTE.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Contribute to PFunk
2+
3+
## Install Docker and Docker Compose
4+
5+
- Follow the instructions [here to install Docker](https://docs.docker.com/get-docker/)
6+
- Follow the instructions [here to install Docker Compose](https://docs.docker.com/compose/install/)
7+
8+
## Setup Local Environment
9+
10+
### Example Env file
11+
12+
Please create a `.env` file and copy the following to variables to it. You will need to supply values for the following variables.
13+
14+
- FAUNA_SECRET - This should be generated by using the iPython notebook instructions below.
15+
- DEFAULT_FROM_EMAIL
16+
- PROJECT_NAME
17+
- AWS_ACCESS_KEY_ID
18+
- AWS_SECRET_ACCESS_KEY
19+
20+
```commandline
21+
FAUNA_SECRET=your-locally-generated-fauna-secret-key
22+
FAUNA_SCHEME=http
23+
FAUNA_DOMAIN=fauna
24+
FAUNA_PORT=8443
25+
FAUNA_GRAPHQL_IMPORT_URL=http://fauna:8084/import
26+
FAUNA_GRAPHQL_URL=http://fauna:8084/graphql
27+
28+
PROJECT_NAME=TestProject
29+
TEMPLATE_ROOT_DIR=/code/pfunk/carcamp/templates
30+
AWS_ACCESS_KEY_ID=YOUR-AWS-ACCESS-KEY
31+
AWS_SECRET_ACCESS_KEY=YOUR-AWS-SECRET-ACCESS-KEY
32+
```
33+
34+
### Run Docker Compose
35+
36+
Run the command below and copy and paste URL that is generated. Change the port from `8888` to `8010`.
37+
38+
```commandline
39+
docker-compose up
40+
```
41+
42+
### Get Local Fauna Key
43+
Copy `fauna.ipynb.tmpl` to `fauna.ipynb` and run the commands. Copy the generated key from the **Create Key** to the
44+
**FAUNA_SECRET** variable in your .env file above.
45+
46+
47+
## Run Unit Tests
48+
49+
```commandline
50+
docker-compose run web poetry run python -m unittest
51+
```
52+
53+
## Pull Requests
54+
55+
Please open PRs that will merge to the **develop** branch.
56+

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
FROM capless/capless-docker:jupyter
22
COPY . /code
3+
RUN poetry run pip install --upgrade pip
34
RUN poetry install

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Includes GraphQL and generic ABAC auth workflow integrations.
1111
- Create a GraphQL endpoint and a schema validating ORM with the same code.
1212
- Authentication collections, indexes, user-defined functions, and roles included.
1313
- Generic CRUD user-defined functions included
14+
- Create a REST API to integrate Fauna and Non-Fauna related tasks
1415
- Schema validation based on the [Valley](https://github.com/capless/valley) library.
1516

1617
## Full Documentation
@@ -66,7 +67,7 @@ class AbstractGroupCollection(Collection):
6667
# Here we are defining the roles that should be
6768
# created for this collection (by proxy this role will be applied
6869
# to its subclasses. We could however change the list of roles below.
69-
_roles = [GenericGroupBasedRole]
70+
collection_roles = [GenericGroupBasedRole]
7071
title = StringField(required=True)
7172
group = ReferenceField(Group, required=True)
7273

@@ -113,7 +114,7 @@ project.add_resources([User, Group, Product, Story, Sprint])
113114
```
114115
### Auth Workflows
115116

116-
In the example above, the ```_roles``` list on the ```Collection``` classes attaches generic roles to the
117+
In the example above, the ```collection_roles``` list on the ```Collection``` classes attaches generic roles to the
117118
collection. Currently, you can choose a **group based** workflow, **user based**, or a **mix** of the two.
118119

119120
#### User Based Role

TUTORIAL.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Tutorial
2+
3+
In this tutorial we'll show you how to create a simple PFunk project. Let's call our project **SchoolZone**, a
4+
demo app for tracking students and teachers in a school.
5+
6+
## Step 1: Create New Project
7+
8+
Let's use the PFunk CLI to create a new project.
9+
10+
```python
11+
pfunk init schoolzone
12+
```
13+
14+
## Step 2: Create Collections
15+
16+
Let's create some collections to store our data in. If you're new to Fauna, collections are the equivalent to tables in
17+
relational database.
18+
19+
```python
20+
from pfunk.collection import Collection
21+
from pfunk.fields import StringField, IntegerField, ReferenceField, ManyToManyField
22+
from pfunk.contrib.auth.collections import User, Group
23+
from pfunk.contrib.auth.resources import GenericGroupBasedRole
24+
25+
26+
class School(Collection):
27+
collection_roles = [GenericGroupBasedRole]
28+
name = StringField(required=True)
29+
address = StringField(required=False)
30+
group = ReferenceField(Group, required=True)
31+
32+
33+
class Teacher(Collection):
34+
collection_roles = [GenericGroupBasedRole]
35+
first_name = StringField(required=True)
36+
last_name = StringField(required=True)
37+
group = ReferenceField(Group, required=True)
38+
39+
40+
class Class(Collection):
41+
collection_roles = [GenericGroupBasedRole]
42+
name = StringField(required=True)
43+
teacher = ReferenceField(Teacher)
44+
group = ReferenceField(Group, required=True)
45+
46+
47+
class Student(Collection):
48+
collection_roles = [GenericGroupBasedRole]
49+
first_name = StringField(required=True)
50+
last_name = StringField(required=True)
51+
grade = IntegerField(required=True)
52+
group = ReferenceField(Group, required=True)
53+
54+
55+
class StudentClass(Collection):
56+
collection_roles = [GenericGroupBasedRole]
57+
class_ref = ReferenceField(Class)
58+
student_ref = ReferenceField(Student)
59+
final_grade = IntegerField(required=False)
60+
absences = IntegerField()
61+
tardies = IntegerField()
62+
group = ReferenceField(Group, required=True)
63+
64+
65+
66+
```
67+
## Step 3: Add Collections to Project
68+
69+
Open `schoolzone/project.py` and add the collections.
70+
71+
```python
72+
73+
from pfunk import Project
74+
from pfunk.contrib.auth.collections import Key
75+
from .collections import School, Teacher, Class, Student, StudentClass, User, Group
76+
77+
78+
project = Project(_collections=[User, Group, School, Teacher, Class, Student, StudentClass])
79+
```
80+
81+
## Step 4: Seed Keys
82+
83+
PFunk uses encrypted JWTs with private keys that unencrypt the JWT during request/response loop. We need to seed the keys.
84+
85+
```commandline
86+
pfunk seed_keys staging
87+
```
88+
89+
## Step 5: Run the Local Server
90+
91+
Next, we run the local server to test things out.
92+
93+
```commandline
94+
pfunk local
95+
```
96+
97+
## Step 6: Deploy
98+
99+
Publish the GraphQL schema to Fauna and deploy the API to Lambda and API Gateway.
100+
101+
```commandline
102+
pfunk deploy staging
103+
```
104+
105+
If you don't want to deploy the API and just want to publish the GraphQL schema to Fauna.
106+
107+
```commandline
108+
pfunk publish staging
109+
```

docker-compose.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,17 @@ services:
88
context: .
99
expose:
1010
- "8010"
11+
- "3434"
1112
depends_on:
1213
- fauna
1314
ports:
1415
- 8010:8888
16+
- 3434:3434
1517
volumes:
1618
- ./:/code/
1719
env_file: .env
1820
working_dir: /code/
19-
command: /root/.cache/pypoetry/virtualenvs/pfunk-MATOk_fk-py3.7/bin/jupyter notebook --port=8888 --ip=0.0.0.0 --allow-root
21+
command: /root/.cache/pypoetry/virtualenvs/pfunk-MATOk_fk-py3.9/bin/jupyter notebook --port=8888 --ip=0.0.0.0 --allow-root
2022

2123
fauna:
2224
restart: always

fauna.ipynb.tmpl

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "55c01f7e",
6+
"metadata": {},
7+
"source": [
8+
"# Initialize FaunaClient with Default Key"
9+
]
10+
},
11+
{
12+
"cell_type": "code",
13+
"execution_count": null,
14+
"id": "e029e431",
15+
"metadata": {},
16+
"outputs": [],
17+
"source": [
18+
"from pfunk.client import FaunaClient, q\n",
19+
"\n",
20+
"\n",
21+
"client = FaunaClient(secret='secret')"
22+
]
23+
},
24+
{
25+
"cell_type": "markdown",
26+
"id": "61d7a6ed",
27+
"metadata": {},
28+
"source": []
29+
},
30+
{
31+
"cell_type": "code",
32+
"execution_count": null,
33+
"id": "672dd20d",
34+
"metadata": {},
35+
"outputs": [],
36+
"source": [
37+
"client.query(\n",
38+
" q.create_database({'name': 'docker-test'})\n",
39+
")"
40+
]
41+
},
42+
{
43+
"cell_type": "code",
44+
"execution_count": null,
45+
"id": "de9b05f1",
46+
"metadata": {},
47+
"outputs": [],
48+
"source": [
49+
"client.query(\n",
50+
" q.create_key({'database': q.database('docker-test'), 'role':'admin'})\n",
51+
")"
52+
]
53+
}
54+
],
55+
"metadata": {
56+
"kernelspec": {
57+
"display_name": "Python 3",
58+
"language": "python",
59+
"name": "python3"
60+
},
61+
"language_info": {
62+
"codemirror_mode": {
63+
"name": "ipython",
64+
"version": 3
65+
},
66+
"file_extension": ".py",
67+
"mimetype": "text/x-python",
68+
"name": "python",
69+
"nbconvert_exporter": "python",
70+
"pygments_lexer": "ipython3",
71+
"version": "3.9.6"
72+
}
73+
},
74+
"nbformat": 4,
75+
"nbformat_minor": 5
76+
}

pfunk/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
"""
22
.. include:: ../README.md
3+
.. include:: ../TUTORIAL.md
4+
.. include:: ../CLI.md
5+
.. include:: ../CONTRIBUTE.md
36
"""
47
__docformat__ = "google"
58
from .collection import Collection, Enum

0 commit comments

Comments
 (0)