Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,15 @@ name: Docker deploy

on:
push:
branches: [ "development_1.x" ]
branches: [ "development_2.1" ]
# Publish semver tags as releases.
tags: [ 'v*.*.*' ]
pull_request:
branches: [ "development_1.x" ]
branches: [ "development_2.1" ]

env:
# Use docker.io for Docker Hub if empty
REGISTRY: docker.io
# github.repository as <account>/<repo>
IMAGE_NAME: "grisera_ui"
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}


jobs:
Expand Down Expand Up @@ -56,8 +54,8 @@ jobs:
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Bump version and push tag
if: github.event_name != 'pull_request'
Expand All @@ -66,7 +64,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.THIS_GITHUB_TOKEN }}
DEFAULT_BRANCH: ${{ github.ref_name }}
DEFAULT_BUMP: minor
DEFAULT_BUMP: patch
WITH_V: true

# Extract metadata (tags, labels) for Docker
Expand All @@ -75,8 +73,10 @@ jobs:
id: meta
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
with:
images: ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.IMAGE_NAME }}
tags: type=semver,pattern={{version}},value=${{ steps.version_bump.outputs.new_tag }}
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=semver,pattern={{version}},value=${{ steps.version_bump.outputs.new_tag }}
2.1-latest

# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
Expand Down
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,8 @@ node_modules
.DS_Store
/dist
.env.local
.env.*.local
.env.*.local
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@ npm install axios
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

### Deployment
For security reasons it is required for OAuth client to regenerate client secrets and update them in configuration.
9 changes: 6 additions & 3 deletions config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
export default {
// 'process.env.VUE_APP_API_URL' and 'process.env.VUE_APP_AUTH_MS_URL' are needed for entrypoint.sh script
// 'VUE_APP_API_URL' and 'VUE_APP_AUTH_MS_URL' are needed for entrypoint.sh script
// used to create prod image of grisera-ui using prod.dockerfile
apiUrl: process.env.VUE_APP_API_URL || 'process.env.VUE_APP_API_URL',
authUrl: process.env.VUE_APP_AUTH_MS_URL || 'process.env.VUE_APP_AUTH_MS_URL',
apiUrl: 'VUE_APP_API_URL' || 'http://localhost:8085',
authUrl: 'VUE_APP_AUTH_MS_URL' || 'http://localhost:8081/api',
keycloakUrl: 'VUE_APP_KEYCLOAK_URL' || 'http://localhost:8090',
keycloakClientId: 'VUE_APP_KEYCLOAK_CLIENT_ID' || 'grisera-ui',
realm: 'VUE_APP_KEYCLOAK_REALM' || 'grisera',
sessionDurationMinutes: 30,
};
67 changes: 67 additions & 0 deletions docker-compose.prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
version: "3.9" # optional since v1.27.0
services:
grisera_api_mongodb:
image: maczomen/grisera_core_mongo:0.2.3
depends_on:
- mongodb
ports:
- "18085:80"
environment:
- MONGO_API_HOST=user:password@mongodb
- MONGO_API_PORT=27017
- TIMEOUT=300


frontend-ms:
build:
context: .
dockerfile: prod.dockerfile
depends_on:
- auth-ms
- grisera_api_mongodb
ports:
- "8080:80"
environment:
- VUE_APP_API_URL=http://localhost:18085
- VUE_APP_AUTH_MS_URL=http://localhost:8081/api


auth-ms:
image: maczomen/grisera_auth:0.3.3
depends_on:
- mongodb
ports:
- "8081:3000"
environment:
- JWT_SECRET=jwtsecret
- DB_URL=mongodb://user:password@mongodb:27017/auth?authSource=admin
- DB_NAME=auth

mongodb:
image: mongo
restart: always
volumes:
- mongodbdata:/data/db
environment:
- MONGO_INITDB_ROOT_USERNAME=user
- MONGO_INITDB_ROOT_PASSWORD=password
- MONGO_INITDB_DATABASE=auth

mongodb-show:
image: mongo-express
ports:
- "8084:8081"
depends_on:
- mongodb
restart: always
environment:
ME_CONFIG_MONGODB_SERVER: mongodb
ME_CONFIG_MONGODB_PORT: 27017
ME_CONFIG_BASICAUTH_USERNAME: user
ME_CONFIG_BASICAUTH_PASSWORD: password
ME_CONFIG_MONGODB_AUTH_DATABASE: admin
ME_CONFIG_MONGODB_ADMINUSERNAME: user
ME_CONFIG_MONGODB_ADMINPASSWORD: password

volumes:
mongodbdata:
11 changes: 11 additions & 0 deletions docker-compose.tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
services:
playwright-tests:
image: playwright-tests
build:
context: .
dockerfile: tests.Dockerfile
volumes:
- .:/app
ports:
- "9323:9323"
network_mode: host
58 changes: 48 additions & 10 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,41 +1,69 @@
version: "3.9" # optional since v1.27.0
services:
grisera_api_mongodb:
image: maczomen/grisera_core_mongo:0.2.3
image: ghcr.io/grisera/grisera-core-mongo:2.1.1
depends_on:
- mongodb
ports:
- "18085:80"
- "8085:80"
environment:
- MONGO_API_HOST=user:password@mongodb
- MONGO_API_HOST=mongodb
- MONGO_API_PORT=27017
- TIMEOUT=300
- MONGO_API_USER=user
- MONGO_API_PASSWORD=password
- KEYCLOAK_SERVER=http://keycloak:8080
- REALM=grisera
- PERMISSIONS_ENDPOINT=http://auth-ms:3000/api/permissions
- CLIENT_SECRET=6UkCrp7UqFy78vh5TVhkaYP0OuVagNTd



frontend-ms:
build:
context: .
dockerfile: prod.dockerfile
volumes:
- .:/app
depends_on:
- auth-ms
- grisera_api_mongodb
ports:
- "8080:80"
- "3000:80"
environment:
- VUE_APP_API_URL=http://localhost:18085
- VUE_APP_API_URL=http://localhost:8085
- VUE_APP_AUTH_MS_URL=http://localhost:8081/api

- VUE_APP_KEYCLOAK_URL=http://localhost:8090
- VUE_APP_KEYCLOAK_CLIENT_ID=grisera-ui
- VUE_APP_KEYCLOAK_REALM=grisera

auth-ms:
image: maczomen/grisera_auth:0.3.3
image: ghcr.io/grisera/grisera-auth:2.1.8
depends_on:
- mongodb
ports:
- "8081:3000"
environment:
- JWT_SECRET=jwtsecret
- DB_URL=mongodb://user:password@mongodb:27017/auth?authSource=admin
- DB_NAME=auth
- KEYCLOAK_URL=http://keycloak:8080
- REALM=grisera
- CLIENT_ID=grisera-auth
- CLIENT_SECRET=1FrVLc5QFTDNvrJVNvJdqkeWkcpulPJZ

keycloak:
image: ghcr.io/grisera/grisera-auth-keycloak:2.1.8
depends_on:
- postgres
ports:
- "8090:8080"
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
KC_DB: postgres
KC_DB_URL_HOST: postgres
KC_DB_URL_DATABASE: keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: password

mongodb:
image: mongo
Expand All @@ -50,7 +78,7 @@ services:
mongodb-show:
image: mongo-express
ports:
- "8084:8081"
- "8888:8081"
depends_on:
- mongodb
restart: always
Expand All @@ -63,5 +91,15 @@ services:
ME_CONFIG_MONGODB_ADMINUSERNAME: user
ME_CONFIG_MONGODB_ADMINPASSWORD: password

postgres:
image: postgres:latest
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: password
volumes:
- postgresdata:/var/lib/postgresql/data

volumes:
mongodbdata:
postgresdata:
36 changes: 36 additions & 0 deletions e2e-tests/pages/AccessPermissionsTab.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { expect } from '@playwright/test';
import { BasePage } from './BasePage';

export class AccessPermissionsTab extends BasePage {
async visit(): Promise<void> {
await this.page.getByRole('tab', { name: 'Access Permissions' }).click();
}

private get usernameInput() {
return this.page.getByRole('textbox', { name: 'Username' });
}

private get roleInput() {
return this.page.getByRole('textbox', { name: 'Role' });
}

private get addButton() {
return this.page.getByRole('Button', {name: 'add'});
}

async addPermission(username: string, role: string) {
await this.usernameInput.fill(username);
await this.page.getByRole('option', { name: username }).click();

await this.roleInput.click();
await this.page.getByRole("option", {name: role}).click();


await this.addButton.click();
await expect(this.page.getByRole("cell", {name: username})).toBeVisible();
await expect(this.page.getByRole("cell", {name: role})).toBeVisible();

}
}


38 changes: 38 additions & 0 deletions e2e-tests/pages/ActivityPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {BasePage} from "./BasePage";

export class ActivityPage extends BasePage {
async visit(): Promise<void> {
await this.page.goto('/activities');
await this.waitForPageLoad();
}

private get createButton() {
return this.page.getByRole('button', { name: 'Create' });
}

private get nameInput() {
return this.page.getByLabel('Name');
}

private get descriptionInput() {
return this.page.getByLabel('Description');
}

private get typeDropdown() {
return this.page.getByLabel('Type');
}

private get createActivityButton() {
return this.page.getByRole('button', { name: 'Create new activity' });
}


async createActivity(name: string, description: string, type: string): Promise<void> {
await this.createButton.click();
await this.nameInput.fill(name);
await this.descriptionInput.fill(description);
await this.typeDropdown.click();
await this.page.getByText(type).click();
await this.createActivityButton.click();
}
}
15 changes: 15 additions & 0 deletions e2e-tests/pages/BasePage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Page } from '@playwright/test';

export abstract class BasePage {
protected page: Page;

protected constructor(page: Page) {
this.page = page;
}

abstract visit(): Promise<void>;

async waitForPageLoad(): Promise<void> {
await this.page.waitForLoadState('domcontentloaded');
}
}
Loading