Skip to content

Commit

Permalink
Merge 33f9742 into 90a6460
Browse files Browse the repository at this point in the history
  • Loading branch information
Falx committed Feb 9, 2022
2 parents 90a6460 + 33f9742 commit 8d84c2b
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 13 deletions.
49 changes: 46 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,15 @@ jobs:
github-token: ${{ secrets.github_token }}
parallel-finished: true

docker:
docker-main-branch:
needs:
- lint
- test-unit
- test-integration
- test-integration-windows
- validate-components
# Only run on tags starting with v prefix for now -- extra push need for triggering CI again
if: startsWith(github.ref, 'refs/tags/v')
# Only run on tag push events starting with v prefix for now OR main branch push events
if: startsWith(github.ref, 'refs/tags/v') || (github.ref == 'refs/heads/main')
runs-on: ubuntu-latest
steps:
- name: Checkout
Expand All @@ -158,7 +158,9 @@ jobs:
with:
images: |
solidproject/community-server
# edge will always be executed (without latest tag), semver only on tag push events (with latest tag)
tags: |
type=edge
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
Expand All @@ -178,6 +180,47 @@ jobs:
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

docker-versions-branch:
needs:
- lint
- test-unit
- test-integration
- test-integration-windows
- validate-components
# Only run on push events on a versions/* branch (ASSUMPTION: THERE SHOULD ONLY BE ONE THERE!)
if: startsWith(github.ref, 'refs/heads/versions/')
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
ref: ${{ github.ref }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v3
with:
images: |
solidproject/community-server
# Just one label: next (no latest here) for the last pushed commit on this branch
tags: |
type=raw,value=next
github-token: ${{ secrets.github_token }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

docs:
runs-on: ubuntu-latest
Expand Down
23 changes: 21 additions & 2 deletions .github/workflows/schedule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ jobs:
- name: Install dependencies and run build scripts
run: npm ci
- name: Start the server in the background
run: npm start &
run: npm start > server-output.log &
- name: Create the necessary folders
run: mkdir -p reports/css
- name: Pull the conformance harness docker
run: docker pull solidconformancetestbeta/conformance-test-harness
run: docker pull solidproject/conformance-test-harness
- name: Wait until the server has started
run: |
until $(curl --output /dev/null --silent --head --fail -k http://localhost:3000/); do
Expand All @@ -47,3 +47,22 @@ jobs:
solidproject/conformance-test-harness
--output=/reports
--target=https://github.com/solid/conformance-test-harness/css
# Steps below use `always()` to make sure logs get uploaded in case the CTH errors
- name: Sanitize branch name for artifact upload
id: sanitize
if: always()
uses: yeouchien/sanitize-branch-name-action@v1
with:
branch-name: ${{ matrix.branch }}
- name: Save the reports
if: always()
uses: actions/upload-artifact@v2
with:
name: ${{ steps.sanitize.outputs.sanitized-branch-name }} reports
path: reports
- name: Save the server output
if: always()
uses: actions/upload-artifact@v2
with:
name: ${{ steps.sanitize.outputs.sanitized-branch-name }} server output
path: server-output.log
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"files.eol": "\n"
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ to some commonly used settings:
| parameter name | default value | description |
| -------------- | ------------- | ----------- |
| `--port, -p` | `3000` | The TCP port on which the server runs. |
| `--baseUrl. -b` | `http://localhost:$PORT/` | The public URL of your server. |
| `--baseUrl, -b` | `http://localhost:$PORT/` | The public URL of your server. |
| `--loggingLevel, -l` | `info` | The detail level of logging; useful for debugging problems. |
| `--config, -c` | `@css:config/default.json` | The configuration for the server. The default only stores data in memory; to persist to your filesystem, use `@css:config/file.json` |
| `--rootFilePath, -f` | `./` | Root folder of the server, when using a file-based configuration. |
Expand Down
14 changes: 14 additions & 0 deletions config/identity/handler/account-store/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,21 @@
"saltRounds": 10,
"storage": {
"@id": "urn:solid-server:default:AccountStorage"
},
"forgotPasswordStorage": {
"@id": "urn:solid-server:default:ExpiringForgotPasswordStorage"
}
},
{
"comment": "Stores expiring data. This class has a `finalize` function that needs to be called after stopping the server.",
"@id": "urn:solid-server:default:ExpiringForgotPasswordStorage",
"@type": "WrappedExpiringStorage",
"source": { "@id": "urn:solid-server:default:ForgotPasswordStorage" }
},
{
"comment": "Makes sure the expiring storage cleanup timer is stopped when the application needs to stop.",
"@id": "urn:solid-server:default:Finalizer",
"ParallelFinalizer:_finalizers": [ { "@id": "urn:solid-server:default:ExpiringForgotPasswordStorage" } ]
}
]
}
5 changes: 5 additions & 0 deletions config/storage/key-value/memory.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@
"comment": "Storage used by setup components.",
"@id": "urn:solid-server:default:SetupStorage",
"@type": "MemoryMapStorage"
},
{
"comment": "Storage used for ForgotPassword records",
"@id": "urn:solid-server:default:ForgotPasswordStorage",
"@type":"MemoryMapStorage"
}
]
}
8 changes: 8 additions & 0 deletions config/storage/key-value/resource-store.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@
"baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" },
"container": "/.internal/accounts/"
},
{
"comment": "Storage used for ForgotPassword records",
"@id": "urn:solid-server:default:ForgotPasswordStorage",
"@type":"JsonResourceStorage",
"source": { "@id": "urn:solid-server:default:ResourceStore" },
"baseUrl": { "@id": "urn:solid-server:default:variable:baseUrl" },
"container": "/.internal/forgot-password/"
},
{
"comment": "Storage used by setup components.",
"@id": "urn:solid-server:default:SetupStorage",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import assert from 'assert';
import { hash, compare } from 'bcrypt';
import { v4 } from 'uuid';
import type { ExpiringStorage } from '../../../../storage/keyvalue/ExpiringStorage';
import type { KeyValueStorage } from '../../../../storage/keyvalue/KeyValueStorage';
import type { AccountSettings, AccountStore } from './AccountStore';

Expand All @@ -26,15 +27,25 @@ export interface ForgotPasswordPayload {
export type EmailPasswordData = AccountPayload | ForgotPasswordPayload | AccountSettings;

/**
* A EmailPasswordStore that uses a KeyValueStorage
* to persist its information.
* A EmailPasswordStore that uses a KeyValueStorage to persist its information and an
* ExpiringStorage to persist ForgotPassword records.
*
* `forgotPasswordExpiration` parameter is how long the ForgotPassword record should be
* stored in minutes. *(defaults to 15 minutes)*
*/
export class BaseAccountStore implements AccountStore {
private readonly storage: KeyValueStorage<string, EmailPasswordData>;
private readonly forgotPasswordStorage: ExpiringStorage<string, EmailPasswordData>;
private readonly saltRounds: number;
private readonly forgotPasswordExpiration: number;

public constructor(storage: KeyValueStorage<string, EmailPasswordData>, saltRounds: number) {
public constructor(storage: KeyValueStorage<string, EmailPasswordData>,
forgotPasswordStorage: KeyValueStorage<string, EmailPasswordData>,
saltRounds: number,
forgotPasswordExpiration = 15) {
this.storage = storage;
this.forgotPasswordStorage = forgotPasswordStorage;
this.forgotPasswordExpiration = forgotPasswordExpiration * 60 * 1000;
this.saltRounds = saltRounds;
}

Expand Down Expand Up @@ -130,20 +141,21 @@ export class BaseAccountStore implements AccountStore {
public async generateForgotPasswordRecord(email: string): Promise<string> {
const recordId = v4();
await this.getAccountPayload(email, true);
await this.storage.set(
await this.forgotPasswordStorage.set(
this.getForgotPasswordRecordResourceIdentifier(recordId),
{ recordId, email },
this.forgotPasswordExpiration,
);
return recordId;
}

public async getForgotPasswordRecord(recordId: string): Promise<string | undefined> {
const identifier = this.getForgotPasswordRecordResourceIdentifier(recordId);
const forgotPasswordRecord = await this.storage.get(identifier) as ForgotPasswordPayload | undefined;
const forgotPasswordRecord = await this.forgotPasswordStorage.get(identifier) as ForgotPasswordPayload | undefined;
return forgotPasswordRecord?.email;
}

public async deleteForgotPasswordRecord(recordId: string): Promise<void> {
await this.storage.delete(this.getForgotPasswordRecordResourceIdentifier(recordId));
await this.forgotPasswordStorage.delete(this.getForgotPasswordRecordResourceIdentifier(recordId));
}
}
2 changes: 2 additions & 0 deletions test/deploy/conformance.env
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ USERS_BOB_PASSWORD=pass1234
RESOURCE_SERVER_ROOT=http://localhost:3000
TEST_CONTAINER=/alice/
quarkus.log.category."ResultLogger".level=INFO
quarkus.log.category."com.intuit.karate".level=DEBUG
MAXTHREADS=1
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import type {
EmailPasswordData,
} from '../../../../../../src/identity/interaction/email-password/storage/BaseAccountStore';
import { BaseAccountStore } from '../../../../../../src/identity/interaction/email-password/storage/BaseAccountStore';
import type { ExpiringStorage } from '../../../../../../src/storage/keyvalue/ExpiringStorage';
import type { KeyValueStorage } from '../../../../../../src/storage/keyvalue/KeyValueStorage';

describe('A BaseAccountStore', (): void => {
let storage: KeyValueStorage<string, EmailPasswordData>;
let forgotPasswordStorage: ExpiringStorage<string, EmailPasswordData>;
const saltRounds = 11;
let store: BaseAccountStore;
const email = 'test@test.com';
Expand All @@ -22,7 +24,13 @@ describe('A BaseAccountStore', (): void => {
delete: jest.fn((id: string): any => map.delete(id)),
} as any;

store = new BaseAccountStore(storage, saltRounds);
forgotPasswordStorage = {
get: jest.fn((id: string): any => map.get(id)),
set: jest.fn((id: string, value: any): any => map.set(id, value)),
delete: jest.fn((id: string): any => map.delete(id)),
} as any;

store = new BaseAccountStore(storage, forgotPasswordStorage, saltRounds);
});

it('can create accounts.', async(): Promise<void> => {
Expand Down

0 comments on commit 8d84c2b

Please sign in to comment.