# URL Patterns

The pattern of URLs in gm-data resembles the scheme used in Local setup. All paths are relative to a rood oid, and every root oid is an independent tree.

```bash
/ipfs/sd890fds890e890ds890/index.html
/ipfs/sd890fds890e890ds890/images/cat.jpg
/ipfs/sd890fds890e890ds890/images/
```

GM-Data does a similar thing. But there are quite a few verbs other than just pulling stream content. Since the system is multi-tenant, a root oid (long hash identifier) is associated with every directory, and also with every file. In gm-data, we use a scheme like this for everything:

```bash
/stream/1234/
/list/1234/images             # this is the name of a directory (which you can tell by reading its props)
/stream/1234/images/cat.jpg   # this is the name of file (which you can tell by reading its props)
/props/1234/images/cat.jpg
/derived/1234/images/cat.jpg
/history/1243/images/cat.jpg
```

The first part is the action, second part is the oid, and there is always a slash that begins the path.

```bash
/{verb}/{oid}/{path}
```

In order to correctly store hyperlinked content, paths are equivalent. From a real installation:

At this url, we are pointing at a directory of content.

```bash
https://localhost:9443/services/gmdatax/latest/props/15830d9759b2050c/?
```

In the json that comes back, we see this oid and parent oid:

```javascript
  "name": "gm-data-face",
  "action": "C",
  "oid": "15830d9759b2050c",
  "parentoid": "15830d975999901c",
```

That means that this is an equivalent url:

```bash
https://localhost:9443/services/gmdatax/latest/props/15830d975999901c/gm-data-face
```

And continuing to follow the properties for each parentoid:

```javascript
  "name": "reactdev",
  "action": "C",
  "oid": "15830d975999901c",
  "parentoid": "15830d97591a1490",
```

And so on...

```bash
https://localhost:9443/services/gmdatax/latest/props/15830d97591a1490/reactdev/gm-data-face
```

```javascript
  "name": "react",
  "action": "C",
  "oid": "15830d97591a1490",
  "parentoid": "0000000000000001",
```

Where the parent oid is the root oid...

```bash
https://localhost:9443/services/gmdatax/latest/props/15830d97591a1490/reactdev/gm-data-face
https://localhost:9443/services/gmdatax/latest/props/0000000000000001/react/reactdev/gm-data-face
```

Looking at the properties of the root oid, we can see why it's the (or a) root. Its parentoid is all zeroes.

```bash
https://localhost:9443/services/gmdatax/latest/props/0000000000000001/
```

```javascript
  "oid": "0000000000000001",
  "parentoid": "0000000000000000",
```

This pattern is applied for all of these verbs:

* props
* stream
* list
* history
* derived

> The GM dashboard will segregate statistics by these verbs. That is why the verbs are in the prefix of the URL.

This allows us to upload hyperlinked content and know that it will still work. For example, say that we upload a file called `index.html` with parentoid `1`, and this file was assigned oid `99` for itself:

```markup
  <a href=images/cat.jpg>
```

If images directory has an oid of 42, and cat.jpg is oid 66:

These are equivalent:

```bash
/stream/1/images/cat.jpg
/stream/42/cat.jpg
/stream/66/
```

These are equivalent:

```bash
/stream/1/index.html
/stream/99/
```

The html from window.location of `/stream/1/` asking for `images/cat.jpg` will be fetched correctly by the html. The html cannot fetch by oid, because the static content won't know the oid of files until they are actually uploaded.

> This functionality is critical for applications such as GIS, where you may upload a hyperlinked bit of html that loads Google Maps and has links to layers at predetermined names. It can't use oids, because the static content is uploaded into the system before oids are even known.

## Multi-Tenancy

The use of a required oid for every path allows for multi-tenant scenarios. Presume that two organizations want to host gm-data content in the same system. (The permission syntax is explained later, but it's an expression compared against a user's JWT token to figure out permissions like Read, Execute, Create, Update, Delete):

* The oid 1 is visible by everyone
* The oid 100 is visible only to AliceCorp, with permission like: `(if (contains org alice) (yield R X))`
* The oid 101 is visible only to BobCorp, with permission like: `(if (contains org bob) (yield R X))`

Alice will do a listing of oid `1` to start listing data. Alice only sees the `alicecorp` directory, and does not know that `bobcorp` directory exists. If somebody from `bobcorp` shares out a file that's readable by everyone `(yield R X)`.
