Skip to content

Commit d5e5397

Browse files
add docs/tutorial
Co-authored-by: tc-imba <[email protected]> Co-authored-by: Reapor-Yurnero <[email protected]>
1 parent 6822aae commit d5e5397

File tree

4 files changed

+189
-0
lines changed

4 files changed

+189
-0
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Write a Permission Profile
2+
3+
A permission profile is a function-like object that takes in a few Brick-typed arguments and returns two lists of building resources for read and (read plus) write capability respectively.
4+
The derivation of the two capability lists is defined by two SPARQL queries which use the provided arguments as parameters.
5+
Note that the permission profile is statically typed --- arguments must be of the specified Brick class.
6+
7+
For example, this is a permission profile that takes `room` as an argument.
8+
To distinguish arguments and normal brackets (`{` and `}`), you should escape them with (`{{` and `}}`) in the sparql query.
9+
10+
```sparql
11+
SELECT ?p WHERE {{
12+
?e brick:feeds {room} .
13+
?e brick:hasPoint ?p .
14+
?p a ?o .
15+
FILTER (?o IN (
16+
brick:Temperature_Sensor,
17+
brick:Occupancy_Sensor,
18+
brick:On_Off_Command,
19+
brick:CO2_Sensor,
20+
brick:Warm_Cool_Adjust_Sensor)
21+
)
22+
}}
23+
```
24+
25+
The arguments of the permission profile should be explicitly defined with their types in Brick.
26+
27+
```json
28+
{"room":"brick:Room"}
29+
```

docs/tutorial/write_an_app.md

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# Write an App
2+
3+
The folder `apps/demo` (https://github.com/BrickSchema/playground/tree/master/apps/demo) contains a demo app, which is a minimized read/write actuator with Brick and Playground
4+
interfaces.
5+
6+
The demo app contains the following files:
7+
8+
```text
9+
├── backend # a simple backend written by express.js
10+
│ └── index.js
11+
├── frontend # a simple frontend in pure html
12+
│ └── index.html
13+
├── build.sh # a script that packs backend.zip and frontend.zip
14+
├── Dockerfile # sbos-playground uses the Dockerfile to build the image
15+
├── package.json # define the dependencies in the backend
16+
└── yarn.lock # lock the dependencies in package.json
17+
```
18+
19+
You can use any language and framework to write the app backend and frontend.
20+
21+
## Backend
22+
23+
### Dockerfile
24+
25+
For the backend, you must provide a `Dockerfile` and other files (if necessary) to build the docker image.
26+
27+
For example, the `Dockerfile` of the demo app use `node 18` as base image, install the packages and run the backend file `backend/index.js`. For more information about how to write a `Dockerfile`, please refer to the official documentation of `Docker`.
28+
29+
!!! important
30+
You should start the backend server on `localhost:5000` in the docker image so that it can be accessed by the frontend.
31+
32+
```Dockerfile
33+
FROM node:18-alpine
34+
35+
ENV HOME="/root"
36+
WORKDIR /root
37+
38+
COPY ./package.json ./yarn.lock /root/
39+
RUN --mount=type=cache,target=/usr/local/share/.config/yarn/global yarn
40+
COPY . /root
41+
42+
CMD node backend/index.js
43+
```
44+
45+
### Get JWT (JSON Web Token)
46+
47+
When running the docker image, `playground` provides an environment variable `BRICK_SERVER_API_TOKEN`, which is a JWT (
48+
JSON Web Token) to authorize the requests to the API endpoints in `playground`.
49+
50+
For example, the following code snippets get the JWT from the environment variable and parse the information in the JWT.
51+
52+
=== "Python"
53+
54+
```python
55+
import os
56+
import jwt
57+
api_token = os.environ.get('BRICK_SERVER_API_TOKEN')
58+
decoded_token = jwt.decode(api_token, options={"verify_signature": False})
59+
```
60+
61+
=== "NodeJS"
62+
63+
```js
64+
const apiToken = process.env.BRICK_SERVER_API_TOKEN;
65+
const decodedToken = JSON.parse(Buffer.from(apiToken.split('.')[1], 'base64').toString());
66+
```
67+
68+
The decoded (parsed) JWT is a JSON object, which is in the format of
69+
70+
```json
71+
{
72+
73+
"aud": [
74+
"brick"
75+
],
76+
"domain": "Center_Hall",
77+
"app": "demo",
78+
"domain_user_app": "66c4ec995317281fb487ccd3",
79+
"exp": 1747595485
80+
}
81+
```
82+
83+
| Key | Description |
84+
|-----------------|------------------------------------------|
85+
| sub | User using this app |
86+
| aud | JWT audience (always "brick") |
87+
| domain | The domain this app currently working in |
88+
| app | Name of this app |
89+
| domain_user_app | ObjectId of this app instance in DB |
90+
| exp | Expiration time of the JWT (Unix Epoch) |
91+
92+
### Make API Requests to `playground`
93+
94+
The backend should add the JWT in the header as a bearer token when sending API requests to `playground`
95+
96+
```python
97+
headers = {
98+
'Content-Type': 'application/json',
99+
'Authorization': 'Bearer <JWT token>',
100+
}
101+
```
102+
103+
The base API endpoint of `playground` is https://brickserver.ucsd.edu/brickapi/v1/, you can also check https://brickserver.ucsd.edu/brickapi/v1/docs for a detailed documentation of the available APIs.
104+
105+
106+
107+
## Frontend
108+
109+
For the frontend, you must provide a `index.html` and other files (such as `js`, `css` files if necessary), and the folder will be served as static files on `playground`.
110+
Though we only use a single html file as the frontend in the demo app, you can choose any frontend framework and use the build files as the frontend.
111+
112+
### Get JWT
113+
114+
When a user accesses the frontend through `playground`, the same JWT provided to the backend is included in the query parameter `token`. You can use `Javascript` to read the JWT.
115+
116+
```js
117+
const baseURL = "https://brickserver.ucsd.edu/brickapi/v1/apps/api";
118+
const params = new URL(document.location).searchParams;
119+
const token = params.get("token");
120+
```
121+
122+
### Make API Requests to Backend
123+
124+
`playground` designed special API endpoint translation rules for the frontend to access to backend APIs.
125+
The base API endpoint for such API requests is https://brickserver.ucsd.edu/brickapi/v1/apps/api.
126+
127+
For example, if the backend has an API endpoint on `localhost:5000/example`, the frontend should send a request to https://brickserver.ucsd.edu/brickapi/v1/apps/api/example with the JWT in the header as a bearer token (same as how it is used in the backend).
128+
129+
## Submit the App
130+
131+
### Backend and Frontend Files
132+
133+
The backend and frontend files should be zipped into `backend.zip` and `frontend.zip` before submission. Make sure that the files are in the root of the zip archive.
134+
135+
For example, the structure of `backend.zip` in the demo app is
136+
137+
```text
138+
backend.zip
139+
├── backend
140+
│ └── index.js
141+
├── Dockerfile
142+
├── package.json
143+
└── yarn.lock
144+
```
145+
146+
The structure of `frontend.zip` in the demo app is
147+
148+
```text
149+
frontend.zip
150+
└── index.html
151+
```
152+
153+
The file `build.sh` is a helper script to generate these two zip files in the demo app.
154+
155+
### Permission Profile
156+
157+
158+

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,4 @@ nav:
7171
- Tutorials:
7272
- Tutorial@CPSIoT25!: tutorial/cpsiot25.md
7373
- Write a Brick based building app: tutorial/write_an_app.md
74+
- Write a Permission Profile: tutorial/write_a_permission_profile.md

projects/sbos-frontend/config/defaultSettings.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const Settings: ProLayoutProps & {
2323
// 参见ts声明,demo 见文档,通过token 修改样式
2424
//https://procomponents.ant.design/components/layout#%E9%80%9A%E8%BF%87-token-%E4%BF%AE%E6%94%B9%E6%A0%B7%E5%BC%8F
2525
},
26+
locale: "en-US",
2627
};
2728

2829
export default Settings;

0 commit comments

Comments
 (0)