Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
d5ad64a
docs(README): docker ports in documentation should match compose file
menof36go Jan 4, 2026
66fabcc
docs(README): docker ports in documentation should match compose file…
menof36go Jan 6, 2026
7bbfa5a
feature(DOCKER): compose profiles
menof36go Jan 6, 2026
8244c31
feature(FileStorage): storeFile shouldn't dump for reupload
menof36go Jan 6, 2026
d6b1e8b
fix(VitruvCli): Fix subprocess execution on Windows, make location of…
menof36go Jan 6, 2026
05c8a00
Bump org.assertj:assertj-core from 3.27.3 to 3.27.7 in /builder
dependabot[bot] Jan 26, 2026
f7abf10
Merge pull request #186 from vitruv-tools/dependabot/maven/builder/or…
arlange Jan 27, 2026
1591b96
Update issue templates
arlange Feb 5, 2026
08b8953
Merge pull request #189 from vitruv-tools/issue-template
arlange Feb 5, 2026
f64039c
Merge pull request #197 from vitruv-tools/develop
ma-mirzaei Feb 9, 2026
244bd3e
chore(deps-dev): bump org.assertj:assertj-core in /app
dependabot[bot] Feb 9, 2026
a1cf78e
Merge pull request #198 from vitruv-tools/dependabot/maven/app/org.as…
arlange Feb 17, 2026
bf04323
feat: add CI/CD workflows for production and staging deployments
ma-mirzaei Feb 20, 2026
ebd03bc
Merge pull request #209 from vitruv-tools/CD
ma-mirzaei Feb 20, 2026
b2a7281
feat: update CI/CD workflow to include main and develop branches for …
ma-mirzaei Feb 20, 2026
4c2f5dc
Merge branch 'develop' into CD
ma-mirzaei Feb 20, 2026
79dde9e
Merge pull request #210 from vitruv-tools/CD
ma-mirzaei Feb 20, 2026
1120dda
change in dc stage
ma-mirzaei Feb 20, 2026
79b08d6
Merge branch 'develop' into CD
ma-mirzaei Feb 20, 2026
fcfcc23
Merge pull request #211 from vitruv-tools/CD
ma-mirzaei Feb 20, 2026
af33ad1
change in dc stage
ma-mirzaei Feb 20, 2026
21313ee
Merge branch 'develop' into CD
ma-mirzaei Feb 20, 2026
6092a17
Merge pull request #212 from vitruv-tools/CD
ma-mirzaei Feb 20, 2026
621835f
change in CD stage
ma-mirzaei Feb 20, 2026
3f574a3
feat: enhance CD workflow for staging with Java setup and improved im…
ma-mirzaei Feb 20, 2026
e6c08c3
fix: update jar preparation step in CD workflow for improved reliability
ma-mirzaei Feb 20, 2026
acc18ae
fix: update jar preparation step in CD workflow for improved reliability
ma-mirzaei Feb 20, 2026
5a6a258
fix: update jar preparation step in CD workflow for improved reliability
ma-mirzaei Feb 20, 2026
64567c0
fix: update jar preparation step in CD workflow for improved reliability
ma-mirzaei Feb 20, 2026
31d4414
fix: add passphrase to SSH configuration in CD workflow for staging
ma-mirzaei Feb 20, 2026
d10e5c0
fix: update SSH username in CD workflow for staging
ma-mirzaei Feb 20, 2026
6a3fa97
fix: update SSH username in CD workflow for staging
ma-mirzaei Feb 20, 2026
e7b26d7
Remove CD
ma-mirzaei Feb 23, 2026
d2da8ea
Merge branch 'main' into develop
ma-mirzaei Feb 23, 2026
4d0d84b
Merge pull request #214 from vitruv-tools/develop
ma-mirzaei Feb 23, 2026
6991825
Modify messages
ma-mirzaei Mar 2, 2026
ca501bf
Merge pull request #216 from vitruv-tools/215-reaction-not-found-mess…
ma-mirzaei Mar 2, 2026
39bdf5f
Merge branch 'main' into develop
ma-mirzaei Mar 2, 2026
f9412a2
Merge pull request #217 from vitruv-tools/develop
ma-mirzaei Mar 3, 2026
04d975e
feat(LowCode): Add low-code reaction metadata controller and service
menof36go Mar 3, 2026
0267608
feat(Auth): Add no-auth dev profile for swagger convenience
menof36go Mar 3, 2026
8bc0b64
style(LowCode): refactor
menof36go Mar 3, 2026
fb8c2ba
feat(LowCode): move saving into vsum sync changes like the rest
menof36go Mar 10, 2026
0a9effe
feat(LowCode): add and remove fine-granular relations and correspondi…
menof36go Mar 10, 2026
d283061
fix(LowCode): fine-granular reaction file storage id mapper
menof36go Mar 10, 2026
c487b9b
fix(LowCode): fine-granular response mapping
menof36go Mar 10, 2026
2bdd8ab
fix(LowCode): low code reaction request mapper
menof36go Mar 11, 2026
bafbd31
fix(FineGranularRelation): fix infinite recursion and duplicate confl…
menof36go Mar 11, 2026
08baf89
fix(LowCode): fix wrong alias in composite reaction template
menof36go Mar 11, 2026
95183f0
fix(LowCode): fix wrong indentation in composite reaction template
menof36go Mar 11, 2026
fbf1661
feat(FineGranularRelation): building now takes multiple reaction file…
menof36go Mar 11, 2026
ae4277b
Merge remote-tracking branch 'origin/main' into internship-reinbold
menof36go Mar 21, 2026
607cf59
fix: :ambulance: merge related issues
menof36go Mar 21, 2026
e2202bc
style: :art: apply spotless and minor test fixes
menof36go Mar 22, 2026
aba4b69
refactor: add javadoc
menof36go Mar 22, 2026
b5b4f19
refactor: add javadoc, resolve some checkstyle issues
menof36go Mar 22, 2026
e933c01
test: update test file for VsumServiceTest, MetaModelRelationServiceT…
menof36go Mar 22, 2026
84a0451
fix(LowCode): remove unsupported bidirectional attribute
menof36go Mar 22, 2026
778e6ca
style: :art: apply spotless
menof36go Mar 31, 2026
a4e6d7f
Merge remote-tracking branch 'upstream/develop' into internship-reinbold
menof36go Apr 8, 2026
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
38 changes: 38 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]

**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]

**Additional context**
Add any other context about the problem here.
8 changes: 6 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ on:
branches:
- main
- develop
push:
branches:
- main
- develop
# nightly
schedule:
- cron: "0 3 * * *"
Expand Down Expand Up @@ -39,7 +43,7 @@ jobs:
--batch-mode
--update-snapshots
--no-transfer-progress

- name: Stage build results (Unix)
run: mkdir staging-ubuntu-latest && find . -path '*/target/*.jar' -exec cp {} staging-ubuntu-latest/ \;

Expand All @@ -52,7 +56,7 @@ jobs:
sonar:
name: SonarQube analysis
runs-on: ubuntu-latest
needs: [verify]
needs: [ verify ]
if: github.event_name == 'schedule' || (github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]')
strategy:
fail-fast: true
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,5 @@ replay_pid*
/builder/target/
/app/target/
/.vscode/

opt/vitruv/work/
7 changes: 6 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"java.configuration.updateBuildConfiguration": "automatic",
"java.compile.nullAnalysis.mode": "automatic"
"java.compile.nullAnalysis.mode": "automatic",
"java.configuration.annotationProcessing.enabled": true,
"maven.executable.path": "${workspaceFolder}/mvnw.cmd",
"maven.terminal.useJavaHome": true,
"files.encoding": "utf8",
"java.checkstyle.configuration": "${workspaceFolder}\\checkstyle.xml"
}
20 changes: 15 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ using Docker Compose and the included realm template.
- Build
- Run (development)
- Configuration
- Dependency setup (REQUIRED)
- Keycloak setup (REQUIRED)
- Start Keycloak with Docker Compose
- Import the provided realm (methodologist)
Expand Down Expand Up @@ -67,7 +68,8 @@ Run tests:
./mvnw test
```

The runnable JAR will be created under `target/` (for example: `target/methodologist.jar`).
Two runnable JARs will be created under `target/`.
The `methodologist-build-jar-with-dependencies.jar` contains all dependencies.

---

Expand All @@ -76,7 +78,7 @@ The runnable JAR will be created under `target/` (for example: `target/methodolo
Run the packaged JAR with a custom configuration directory:

```bash
java -jar target/methodologist.jar --spring.config.location=file:/absolute/path/to/config/
java -jar target/methodologist-build-jar-with-dependencies.jar --spring.config.location=file:/absolute/path/to/config/
```

The directory provided to `spring.config.location` must contain `application.properties` or `application.yml`. Use
Expand Down Expand Up @@ -156,6 +158,14 @@ Adjust the structure above to match any additional modules in your clone.

---

## Dependency setup (REQUIRED)

The backend requires multiple jar files to be placed at specific configurable locations manually.
- The `methodologist-build-jar-with-dependencies.jar` generated during build must be renamed to `methodologist-build.jar` and must be placed at the property path `builder.jarPath` manually.
- The project requires a [vitruv-cli.jar](https://github.com/vitruv-tools/Vitruv-CLI), which must be built separately and placed at the property path `vitruv.cli.jar` manually.

---

## Keycloak setup (REQUIRED)

The backend requires a Keycloak server with a realm named `methodologist`. The repository includes a realm template at:
Expand All @@ -175,7 +185,7 @@ If a `docker-compose.yaml` is present at the project root and contains a `keyclo
docker compose up -d keycloak
```

After the container is running, open the Admin Console (typically `http://localhost:8080/`) and log in with the admin
After the container is running, open the Admin Console (`http://localhost:7668/admin`) and log in with the admin
credentials defined in the compose file.

#### Import the `methodologist` realm via the Admin Console
Expand All @@ -189,7 +199,7 @@ credentials defined in the compose file.
Run Keycloak in development mode (example using Keycloak 20+ `start-dev` image):

```bash
docker run --rm -p 8080:8080 \
docker run --rm -p 7668:8080 \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD=admin \
quay.io/keycloak/keycloak:latest \
Expand All @@ -205,7 +215,7 @@ supported by your Keycloak image) to import the realm on first start. This behav
and version. Example (pseudo):

```bash
docker run --rm -p 8080:8080 \
docker run --rm -p 7668:8080 \
-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin \
-v $(pwd)/docker/keycloak/realm-template.json:/opt/keycloak/data/import/realm-template.json \
-e KC_IMPORT=/opt/keycloak/data/import/realm-template.json \
Expand Down
6 changes: 5 additions & 1 deletion app/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.27.3</version>
<version>3.27.7</version>
<scope>test</scope>
</dependency>
<dependency>
Expand All @@ -185,6 +185,10 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,19 @@
import lombok.Getter;
import lombok.Setter;

/**
* Generic DTO for API responses.
*
* @param <T> the type of the data contained in the response
*/
@Setter
@Getter
@Builder
@AllArgsConstructor
public class ResponseTemplateDto<T> {
/** The data returned in the response. */
private T data;

/** A message providing additional information about the response. */
private String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package tools.vitruv.methodologist.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/** Annotation to provide metadata for reactions. */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface ReactionMetadata {
/**
* The name of the reaction or field.
*
* @return the name
*/
String name() default "";

/**
* The description of the reaction or field.
*
* @return the description
*/
String description() default "";

/**
* Whether the reaction or field should be hidden.
*
* @return true if hidden, false otherwise
*/
boolean hide() default false;

// TODO: Add readonly property
/**
* The default string value.
*
* @return the default string value
*/
String defaultStringValue() default "";

/**
* The default integer value.
*
* @return the default integer value
*/
int defaultIntValue() default 0;

/**
* The default boolean value.
*
* @return the default boolean value
*/
boolean defaultBooleanValue() default false;

/**
* The default double value.
*
* @return the default double value
*/
double defaultDoubleValue() default 0.0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import java.time.Duration;
import java.util.Map;
Expand Down Expand Up @@ -34,9 +34,16 @@
*/
@Component
public class KeycloakApiHandler {
/** The timeout for API responses in seconds. */
public static final int RESPONSE_TIMEOUT_IN_SECONDS = 5;

/** The URL for posting token requests. */
public static final String POST_TOKEN_URL = "/realms/methodologist/protocol/openid-connect/token";

/** The WebClient used for making API calls. */
private final WebClient webClient;

/** The object mapper used for JSON serialization/deserialization. */
private final ObjectMapper mapper = new ObjectMapper();

@Value("${methodologist.keycloak.client-id}")
Expand Down Expand Up @@ -182,7 +189,7 @@ public KeycloakWebToken getAccessTokenByRefreshToken(String refreshToken) {
/** DTO for token exchange request body parameters. */
@Setter
@Getter
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public static class ExchangeTokenPostBody {

/** DTO for token request body parameters. */
Expand Down Expand Up @@ -215,7 +222,7 @@ public ExchangeTokenPostBody(String subjectToken, String requestedSubject) {
@Getter
@Builder
@AllArgsConstructor
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public static class TokenPostBody {
private String clientId;
private String grantType;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package tools.vitruv.methodologist.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;

/** Configuration class for enabling method-level security. */
@Configuration
@Profile("!noauth")
@EnableMethodSecurity(jsr250Enabled = true)
public class MethodSecurityConfiguration {}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
Expand All @@ -23,7 +24,6 @@
*/
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(jsr250Enabled = true, prePostEnabled = true)
public class SecurityConfiguration {

@Value("${allowed.origins:*}")
Expand All @@ -32,6 +32,28 @@ public class SecurityConfiguration {
@Value("${allowed.headers:*}")
private String allowedHeaders;

/**
* Dev-only security filter chain that permits all requests.
*
* @param http the {@link HttpSecurity} to configure
* @return the built {@link SecurityFilterChain}
* @throws Exception on configuration errors
*/
@Bean
@Profile({"noauth"})
@Order(0)
public SecurityFilterChain devPermitAllSecurityFilterChain(HttpSecurity http) throws Exception {
return http.csrf(csrf -> csrf.disable())
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
.sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll())
.oauth2ResourceServer(oauth2 -> oauth2.disable())
.httpBasic(basic -> basic.disable())
.formLogin(form -> form.disable())
.logout(logout -> logout.disable())
.build();
}

/**
* Defines the security filter chain:
*
Expand All @@ -47,6 +69,7 @@ public class SecurityConfiguration {
* @throws Exception on configuration errors
*/
@Bean
@Profile("!noauth")
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.csrf(csrf -> csrf.disable())
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ public class ErrorResponse {
private String message;

private String path;

private String stackTrace;
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package tools.vitruv.methodologist.exception;

/**
* Exception thrown when a user attempts to upload a file that is already stored in the system.
* This0 exception is used to prevent duplicate file storage for the same user.
* Exception thrown when a user attempts to upload a file that is already stored in the system. This
* exception is used to prevent duplicate file storage for the same user.
*/
public class FileAlreadyExistsException extends RuntimeException {
public static final String MESSAGE_TEMPLATE = "This file already exists.";
Expand Down
Loading
Loading