Skip to content

Commit dd62fd3

Browse files
authored
Merge pull request #30 from Hub-of-all-Things/2.3.0
2.3.0
2 parents c431494 + a6c0c15 commit dd62fd3

File tree

129 files changed

+9077
-628
lines changed

Some content is hidden

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

129 files changed

+9077
-628
lines changed

.gitmodules

+9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
11
[submodule "hat-database-schema"]
22
path = hat/conf/evolutions/hat-database-schema
33
url = https://github.com/Hub-of-all-Things/hat-database-schema.git
4+
[submodule "hat-client-scala-play"]
5+
path = hat-client-scala-play
6+
url = git@github.com:Hub-of-all-Things/hat-client-scala-play.git
7+
[submodule "marketsquare-client-scala-play"]
8+
path = marketsquare-client-scala-play
9+
url = git@github.com:Hub-of-all-Things/marketsquare-client-scala-play.git
10+
[submodule "frontend"]
11+
path = frontend
12+
url = git@github.com:Hub-of-all-Things/Rumpel.git

build-frontend.sh

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/bash
2+
3+
cd ./frontend
4+
5+
npm install
6+
7+
ng build -prod
8+
9+
cd ..
10+
11+
cp ./frontend/dist/inline.*.bundle.js ./hat/app/org/hatdex/hat/phata/assets/js/inline.bundle.js
12+
13+
cp ./frontend/dist/polyfills.*.bundle.js ./hat/app/org/hatdex/hat/phata/assets/js/polyfills.bundle.js
14+
15+
cp ./frontend/dist/main.*.bundle.js ./hat/app/org/hatdex/hat/phata/assets/js/main.bundle.js
16+
17+
cp ./frontend/dist/vendor.*.bundle.js ./hat/app/org/hatdex/hat/phata/assets/js/vendor.bundle.js
18+
19+
cp ./frontend/dist/styles.*.bundle.css ./hat/app/org/hatdex/hat/phata/assets/stylesheets/styles.bundle.css
20+
21+
gzip --keep --force ./hat/app/org/hatdex/hat/phata/assets/js/*.bundle.js

codegen/src/main/scala/org/hatdex/hat/dal/CustomizedCodeGenerator.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ object CustomizedCodeGenerator {
5050
args(0),
5151
args(1),
5252
"Tables",
53-
"Tables.scala"
54-
)
53+
"Tables.scala")
5554
}
5655

5756
codegenFuture.onFailure {
@@ -89,6 +88,7 @@ object CustomizedCodeGenerator {
8988
case "int4[]" => "List[Int]"
9089
case "text[]" => "List[String]"
9190
case "_int4" => "List[Int]"
91+
case "_text" => "List[String]"
9292
case "jsonb" => "play.api.libs.json.JsValue"
9393
case _ => "String"
9494
}).getOrElse("String")

codegen/src/main/scala/org/hatdex/hat/dal/SlickPostgresDriver.scala

+1-2
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@ trait SlickPostgresDriver extends ExPostgresDriver
5252
new AdvancedArrayJdbcType[JsValue](
5353
pgjson,
5454
(s) => utils.SimpleArrayUtils.fromString[JsValue](Json.parse(_))(s).orNull,
55-
(v) => utils.SimpleArrayUtils.mkString[JsValue](_.toString())(v)
56-
).to(_.toList)
55+
(v) => utils.SimpleArrayUtils.mkString[JsValue](_.toString())(v)).to(_.toList)
5756
}
5857

5958
}

deployment/docker/docker-build-images.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ HAT_HOME=${HAT_HOME:-"$PWD"} #if executing from deployment/ : "$PWD/../.."
44
DOCKER=${DOCKER:-"${HAT_HOME}/deployment/docker"}
55

66
bash ${DOCKER}/hat/docker-build.sh
7-
bash ${DOCKER}/hat-postgres/docker-build.sh
7+
#bash ${DOCKER}/hat-postgres/docker-build.sh

deployment/docker/hat/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ RUN ["chown", "-R", "daemon:daemon", "."]
55
USER daemon
66
EXPOSE 8080
77
ENV JAVA_OPTS="-Xmx500m -Xms100m"
8-
ENTRYPOINT ["bin/the-hat", "-DapplicationHost=0.0.0.0"]
8+
ENTRYPOINT ["bin/hat", "-Dhttp.port=8080"]
99
CMD []

deployment/docker/hat/docker-build.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
set -e
44

55
#typically Docker HAT container folder is in HAT2.0/deployment/docker/hat
6-
HAT_HOME=${HAT_HOME:-"$PWD"} #if executing from deployment/ : "$PWD/../.."
6+
HAT_HOME=${HAT_HOME:-"$PWD/hat"} #if executing from deployment/ : "$PWD/../.."
77
DOCKER=${DOCKER:-"$PWD/deployment/docker/hat"}
88
DOCKER_DEPLOY=$DOCKER/docker-deploy
99

deployment/elasticBeanstalk/eb-deploy.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
set -e
44

5-
BUCKET="hat-cloud-formation-eu"
5+
BUCKET=${AWS_BUCKET:-hat-cloud-formation-eu}
66
VERSION=`git log --format="%H" -n 1`
77
APPLICATION_NAME="hat"
88

9-
echo "Build version ${APPLICATION_NAME}-${VERSION}"
9+
echo "Build version ${APPLICATION_NAME} ${VERSION}"
1010
sbt "project hat" docker:stage
1111

1212
echo "Create package"

docs/fileUploadDocs.md

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# HAT File Storage
2+
3+
File storage is a rather different beast from structured (meta)data about your personal digital life:
4+
5+
- they are big to store
6+
- sending them back and forth requires a lot of bandwidth
7+
- databases very useful for storing structured data are not well-suited for storing files
8+
- data in a file can not normally be sliced and diced as structured metadata could
9+
- files would often be uploaded from a low-bandwidth (e.g. mobile) device that is likely to have intermittent connectivity
10+
11+
These considerations further play with the requirements for file storage to be reliable, secure and cost-efficient especially if we want to make HATs affordable. And we still want to be able to attach metadata to files, maintain fine-granularity access control.
12+
13+
APIs are also rather different from web pages in terms of how file uploads tend to be or can be handled. Not going into a lot of detail here there are plenty of reasons why [uploading using multipart forms mostly sucks](https://philsturgeon.uk/api/2016/01/04/http-rest-api-file-uploads/) as well as pretty good examples on how file uploads could be done, e.g. [YouTube Resumable Uploads](https://developers.google.com/youtube/v3/guides/using_resumable_upload_protocol). As a building block to satisfy all the requirements we picked AWS S3
14+
15+
## Uploads
16+
17+
File upload happens in three steps:
18+
19+
1. Posting file metadata to the HAT and retrieving URL to send the file to directly
20+
2. Directly uploading the file to the (securely signed) URL
21+
3. Marking the file complete at the HAT
22+
23+
Uploading metadata is simple: call `POST /api/v2/files/upload` with the file details:
24+
25+
```curl
26+
curl -X POST -H "Accept: application/json" -H "X-Auth-Token: ${HAT_AUTH_TOKEN}" \
27+
-H "Content-Type: application/json" \
28+
-d '{
29+
"name": "testFile.png",
30+
"source": "test",
31+
"tags": ["tag1", "tag2"],
32+
"title": "test Title",
33+
"description": "a very interesting test file",
34+
}' \
35+
"https://${HAT_ADDRESS}/api/v2/files/upload"
36+
```
37+
38+
Only `name` and `source` properties are mandatory - all others are optional. You can also attach `dateCreated` and `lastUpdated` fields with Unix timestamps to set them accordingly. If everything is successful, the HAT will respond with a copy of the metadata as well as additional information:
39+
40+
```
41+
{
42+
"fileId": "testtestfile-12.png",
43+
"name": "testFile.png",
44+
"source": "test",
45+
"tags": ["tag1", "tag2"],
46+
"title": "test Title",
47+
"description": "a very interesting test file",
48+
"dateCreated": 1487871142325,
49+
"lastUpdated": 1487871142329,
50+
"status": {
51+
"status": "New"
52+
},
53+
"contentUrl": "https://hat-storage-test.s3.amazonaws.com/HAT_ADDRESS/testtestfile-12.png?AWSAccessKeyId=AKIAJSOXH3FJPB43SWGQ&Expires=1487871442&Signature=CTRdDW8nKBqNcuwK0ssH77zjkec%3D",
54+
"contentPublic": false,
55+
"permissions": [
56+
{
57+
"userId": "694dd8ed-56ae-4910-abf1-6ec4887b4c42",
58+
"contentReadable": true
59+
}
60+
]
61+
}
62+
```
63+
64+
Importantly, it includes the unique file identifier for the HAT `fileId` and `contentUrl` indicating where the file should be uploaded. The upload `contentUrl` is signed and has limited duration validity, most likely 5 minutes, after which it becomes invalid. Then uploading itself could be done as (*note:* `x-amz-server-side-encryption` header is mandatory):
65+
66+
```curl
67+
curl -v -T ${LOCAL_FILE} \
68+
-H "x-amz-server-side-encryption: AES256"\
69+
"https://hat-storage-test.s3.amazonaws.com/HAT_ADDRESS/testtestfile-12.png?AWSAccessKeyId=AKIAJSOXH3FJPB43SWGQ&Expires=1487871442&Signature=CTRdDW8nKBqNcuwK0ssH77zjkec%3D"
70+
```
71+
72+
Finally, to mark the file "Completed", call `PUT /api/v2/files/file/:fileId/complete`. It will again respond with file metadata:
73+
74+
```
75+
{
76+
"fileId": "postmantestfile-12.png",
77+
"name": "testFile.png",
78+
"source": "postman",
79+
"tags": ["tag1", "tag2"],
80+
"title": "test Title",
81+
"description": "a very interesting test file",
82+
"dateCreated": 1487871142325,
83+
"lastUpdated": 1487871142329,
84+
"status": {
85+
"size": 154639,
86+
"status": "Completed"
87+
},
88+
"contentPublic": false,
89+
"permissions": [
90+
{
91+
"userId": "694dd8ed-56ae-4910-abf1-6ec4887b4c42",
92+
"contentReadable": true
93+
}
94+
]
95+
}
96+
```
97+
98+
File `status` has now been marked as `Completed` and also contains file size in bytes! The request will fail if the file doesn't exist, hasn't been fully uploaded or you do not have permissions to mark the file completed (you will if you started the upload in the first place).
99+
100+
Finally, files can be deleted (by *owner* only!) by calling `DELETE /api/v2/files/file/:fileId`
101+
102+
## Viewing contents
103+
104+
- `GET api/v2/files/file/:fileId` to list metadata of a file, including `contentUrl` pointing to a pre-signed temporary URL for file contents if the user is permitted file access
105+
- `GET /api/v2/files/content/:fileId` to get contents of a file if file is marked publicly accessible or the client is permitted file content access. The endpoint redirects to the pre-signed temporary content URL or returns 404 error code (Not Found) if the file does not exist or is not accessible
106+
107+
## Access Control
108+
109+
HAT owner can access all files, but otherwise there are three options for file access:
110+
111+
- another HAT user can be marked to have access to file's metadata
112+
- another HAT user can be marked to have access to both file's metadata and contents
113+
- a file can be marked to have its contents publicly accessible (e.g. publishing photos or your book!)
114+
115+
By default, the user who saved the file onto the HAT is allowed to see the file's metadata and contents, but only the `owner` can adjust file permissions by:
116+
117+
- calling `GET /api/v2/files/allowAccess/:fileId/:userId` to allow a specific user (`:userId`) to access a specific file (`:fileId`), optionally setting `content` query parameter to `true`/`false` to control content access (`false` by default). Conversely, calling `GET /api/v2/files/restrictAccess/:fileId/:userId` to restrict access.
118+
- calling `POST /api/v2/files/allowAccess/:userId` sending file template to grant access to a set of files (same syntax as for file search!). Conversely, calling `POST /api/v2/files/restrictAccess/:userId` to restrict access.
119+
- calling `GET /api/v2/files/allowAccessPublic/:fileId` and `GET /api/v2/files/restrictAccessPublic/:fileId` to control public file access
120+
121+
## Search
122+
123+
HAT files can be looked up by any part of metadata attached to them:
124+
125+
- `fileId` for an exact match, where one or no files are returned
126+
- `name` for an exact match on the original name, but multiple files could potentially be returned. *Empty* string if you do not want to match against `name`
127+
- `source` matching all files from a specific source such as `facebook`. *Empty* string if you do not want to match against `source`
128+
- `tags` a set of all tags matching files need to have attached
129+
- `title` and `description` for an approximate, text-based search matching the fields
130+
- `status` to filter e.g. only files that are marked `Completed`
131+
132+
To search for files call `POST /api/v2/files/search` sending file template to match against. All calls must be authenticated with the user's token and only files the user is allowed to access are returned (all files for the HAT owner!):
133+
134+
```curl
135+
curl -X POST -H "Accept: application/json" -H "X-Auth-Token: ${HAT_AUTH_TOKEN}" \
136+
-H "Content-Type: application/json" \
137+
-d '{
138+
"name": "testFile.png",
139+
"source": "test",
140+
"tags": ["tag1", "tag2"],
141+
"title": "test Title",
142+
"description": "a very interesting test file",
143+
"status": { "status": "Completed", "size": 0}
144+
}' \
145+
"https://${HAT_ADDRESS}/api/v2/files/search"
146+
```

frontend

Submodule frontend added at b83deef

hat-client-scala-play

Submodule hat-client-scala-play added at a0026c5

0 commit comments

Comments
 (0)