Skip to content

Commit

Permalink
Version 5: Filter JSON releases
Browse files Browse the repository at this point in the history
  • Loading branch information
kduma committed Dec 19, 2023
1 parent cb0be37 commit 3662cb8
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 12 deletions.
26 changes: 16 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Private Satis Repository CloudFlare Worker

This is a [CloudFlare Worker](https://workers.cloudflare.com/) that allows you to host your own
This is a [CloudFlare Worker](https://workers.cloudflare.com/) that allows you to host your own
private Composer repository directly from a [CloudFlare R2 Storage bucket](https://developers.cloudflare.com/r2/),
without the need to run any servers. Authentication is done using usernames and passwords stored in [CloudFlare KV](https://developers.cloudflare.com/kv/).

Expand All @@ -14,15 +14,18 @@ To deploy this worker, you need to clone repository, update `wrangler.toml` conf

You need to update `wrangler.toml` file with your own values:

| Variable Name | Description |
|--------------------------------|----------------------------------------------------------------------------------------------------------------|
| `name` | Name of your CloudFlare Worker |
| `vars.PUBLIC_ACCESS_TO_INDEX` | If true, index page will be accessible without authentication |
| `vars.PUBLIC_ACCESS_TO_JSON` | If true, JSON indexes will be accessible without authentication |
| `vars.CHECK_FILE_RESTRICTIONS` | See [selective access](https://opensource.duma.sh/systems/serverless-satis/cloudflare-worker#selective-access) |
| `routes.pattern` | Domain you want to expose your private repository on (need to use CloudFlare DNS) |
| `kv_namespaces.id` | Namespace ID of your Worker KV to read users from |
| `r2_buckets.bucket_name` | Name of private bucket where are stored files generated by `s3-satis` tool |
| Variable Name | Description |
|--------------------------------------|----------------------------------------------------------------------------------------------------------------|
| `name` | Name of your CloudFlare Worker |
| `vars.PUBLIC_ACCESS_TO_INDEX` | If true, index page will be accessible without authentication |
| `vars.PUBLIC_ACCESS_TO_JSON` | If true, JSON indexes will be accessible without authentication |
| `vars.CHECK_FILE_RESTRICTIONS` | See [Selective Access](https://opensource.duma.sh/systems/serverless-satis/cloudflare-worker#selective-access) |
| `vars.CHECK_EXTRA_JSON_RESTRICTIONS` | See [Selective Access](https://opensource.duma.sh/systems/serverless-satis/cloudflare-worker#selective-access) |
| `vars.STORE_PASSWORDS_HASHED` | See [Authentication](https://opensource.duma.sh/systems/serverless-satis/cloudflare-worker#authentication) |
| `vars.ENABLE_USER_ENDPOINT` | See [User Endpoint](https://opensource.duma.sh/systems/serverless-satis/cloudflare-worker#user-endpoint) |
| `routes.pattern` | Domain you want to expose your private repository on (need to use CloudFlare DNS) |
| `kv_namespaces.id` | Namespace ID of your Worker KV to read users from |
| `r2_buckets.bucket_name` | Name of private bucket where are stored files generated by `s3-satis` tool |

```toml
name = "<name>"
Expand All @@ -33,6 +36,9 @@ compatibility_date = "2023-12-06"
PUBLIC_ACCESS_TO_INDEX = false
PUBLIC_ACCESS_TO_JSON = false
CHECK_FILE_RESTRICTIONS = false
CHECK_EXTRA_JSON_RESTRICTIONS = false
STORE_PASSWORDS_HASHED = false
ENABLE_USER_ENDPOINT = false

[[routes]]
pattern = "<domain>"
Expand Down
8 changes: 6 additions & 2 deletions src/helpers/buckets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,12 @@ export default {
})
},
async getPermissions(pathname: string, env: Env): Promise<string[] | null> {
let key = '.tags' + pathname + '.json';
const object = await env.R2_BUCKET.get(key)
// @ts-ignore
return await this.loadJson('/.tags' + pathname + '.json', env);
},
async loadJson(pathname: string, env: Env): Promise<object | null> {
let objectName = pathname.slice(1)
const object = await env.R2_BUCKET.get(objectName)

if (object === null) {
return null;
Expand Down
70 changes: 70 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,76 @@ export default {
}
}

if(env.CHECK_EXTRA_JSON_RESTRICTIONS && url.pathname.startsWith('/p2/') && url.pathname.endsWith('.json')) {
let json: any = await bucketsHelper.loadJson(url.pathname, env);

if(!json) {
return bucketsHelper.objectNotFound(url.pathname);
}

Object.keys(json['packages']).forEach(function(key, index) {
json['packages'][key] = json['packages'][key].map((version: any) => {
if (!('extra' in version)) {
return version;
}

if (!('s3-satis-file-restrictions' in version['extra'])) {
return version;
}

if(user !== null) {
let hasAccess = user.permissions.includes('*');
version['extra']['s3-satis-file-restrictions'].forEach((p: string) => {
// @ts-ignore
if(user.permissions.includes(p)) {
hasAccess = true;
}
});

if (!hasAccess) {
user.permissions.forEach((p: string) => {
if(!p.includes('*')) {
return;
}
let pattern = '^' + p.replace('*', '.*') + '$';
// @ts-ignore
version['extra']['s3-satis-file-restrictions'].forEach((p: string) => {
// @ts-ignore
if(p.match(pattern)) {
hasAccess = true;
}
});
});
}

if(!hasAccess) {
return null;
}
}

delete version['extra']['s3-satis-file-restrictions'];

if(Object.keys(version['extra']).length == 0) {
delete version['extra'];
}

return version;
}).filter((version: any) => {
return version !== null;
});

if(json['packages'][key].length == 0) {
delete json['packages'][key];
}
});

return new Response(JSON.stringify(json, null, 2), {
headers: {
'content-type': 'application/json',
},
});
}

return bucketsHelper.fetch(request, env);
},
};
1 change: 1 addition & 0 deletions worker-configuration.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ interface Env {
PUBLIC_ACCESS_TO_INDEX: boolean;
PUBLIC_ACCESS_TO_JSON: boolean;
CHECK_FILE_RESTRICTIONS: boolean;
CHECK_EXTRA_JSON_RESTRICTIONS: boolean;
STORE_PASSWORDS_HASHED: boolean;
ENABLE_USER_ENDPOINT: boolean;
}
1 change: 1 addition & 0 deletions wrangler.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ compatibility_date = "2023-12-06"
PUBLIC_ACCESS_TO_INDEX = false
PUBLIC_ACCESS_TO_JSON = false
CHECK_FILE_RESTRICTIONS = false
CHECK_EXTRA_JSON_RESTRICTIONS = false
STORE_PASSWORDS_HASHED = false
ENABLE_USER_ENDPOINT = false

Expand Down

0 comments on commit 3662cb8

Please sign in to comment.