Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
650775a
style: change font and polish UI
markstockhausen Jan 27, 2026
79e45a2
style: update font weight
markstockhausen Jan 27, 2026
430e1c2
style: conform to Prettier formatting
markstockhausen Feb 3, 2026
73a402b
Implement optimized Scheduling Service and Pipeline Logic
markstockhausen Feb 3, 2026
8850cf6
style: update comments
markstockhausen Feb 3, 2026
fe676c3
Implement AI suggestions
markstockhausen Feb 9, 2026
b199432
Update Axios, Optimise scheduling pipeline
markstockhausen Feb 9, 2026
67d6e58
Optimise pipeline logic and clean up code
markstockhausen Feb 10, 2026
60d7f66
Optimise pipeline
markstockhausen Feb 10, 2026
6251a3a
Update logic for bidirectional relationship types
markstockhausen Feb 10, 2026
e683410
Streamline implementation
markstockhausen Feb 10, 2026
141bebd
Conform to Prettier formatting
markstockhausen Feb 10, 2026
64c4f20
Implement AI suggestions
markstockhausen Feb 17, 2026
d863e77
Further AI suggestions
markstockhausen Feb 17, 2026
846fd3d
Merge branch 'main' into feature/implement-scheduling-service
markstockhausen Feb 17, 2026
7916901
feat: add dashboard with contribution heatmap, badges, and session su…
markstockhausen Feb 17, 2026
4b03244
style: fix Prettier formatting
markstockhausen Feb 17, 2026
2190551
Update heatmap
markstockhausen Feb 24, 2026
785d9fa
Conform to Prettier formatting
markstockhausen Feb 24, 2026
2704820
Fix security audit
markstockhausen Feb 24, 2026
32ccd39
feat: Add initial version of onboarding
markstockhausen Feb 25, 2026
99f89e1
fix onboarding flow
markstockhausen Feb 25, 2026
4a8eeba
conform to Prettier formatting
markstockhausen Feb 25, 2026
49e98c2
Update profile setup
markstockhausen Feb 27, 2026
c4a25a2
add simple auth implementation
vtotalova Feb 27, 2026
cf2faae
Merge branch 'main' into feature/36-security-implement-secure-authent…
vtotalova Feb 27, 2026
513e8c4
Fix skip feature, update package-lock.json
markstockhausen Mar 2, 2026
47042eb
Add milestone celebration toasts during mapping sessions
markstockhausen Mar 3, 2026
23c8d8b
Update screenshot on main page, extract CompetencyNetworkViz into reu…
markstockhausen Mar 3, 2026
65c98b0
implement auth
vtotalova Mar 4, 2026
f4f7497
fix issues
vtotalova Mar 4, 2026
7303eea
fix issues
vtotalova Mar 4, 2026
2d85326
Merge remote-tracking branch 'origin/main' into feature/onboarding
markstockhausen Mar 4, 2026
f1de300
Merge branch 'main' into feature/36-security-implement-secure-authent…
vtotalova Mar 4, 2026
f3de42b
Merge branch 'main' into feature/36-security-implement-secure-authent…
vtotalova Mar 4, 2026
6f48404
Fix package-lock.json
markstockhausen Mar 4, 2026
333175a
Merge branch 'main' into feature/onboarding
markstockhausen Mar 4, 2026
305892f
Conform to Prettier formatting
markstockhausen Mar 4, 2026
ed96f32
Merge branch 'feature/onboarding' of https://github.com/ls1intum/memo…
markstockhausen Mar 4, 2026
44e8467
Fix package-lock.json
markstockhausen Mar 4, 2026
0cb944d
Fix package-lock.json
markstockhausen Mar 4, 2026
3d6d590
fix merging of main issues
vtotalova Mar 4, 2026
f05a802
Implement AI suggestions
markstockhausen Mar 4, 2026
5c0dcff
Merge branch 'feature/onboarding' into feature/36-security-implement-…
vtotalova Mar 4, 2026
6b55740
fix auth process after merging
vtotalova Mar 4, 2026
15c09ab
implement auth in the onboarding flow
vtotalova Mar 4, 2026
93fb29b
Merge branch 'main' into feature/36-security-implement-secure-authent…
vtotalova Mar 4, 2026
a072b81
fix merge conflict issues
vtotalova Mar 4, 2026
781c6fe
update onboarding with policy link
vtotalova Mar 4, 2026
72bebe5
add fast fail if login email not authorized
vtotalova Mar 4, 2026
1fc4738
remove duplicates
vtotalova Mar 4, 2026
32b1769
fix warnings
vtotalova Mar 23, 2026
d37c5d8
fix quality issues in package
vtotalova Mar 23, 2026
fd6dc02
add admin page
vtotalova Mar 24, 2026
172c52a
refine admin panel
vtotalova Apr 7, 2026
db5fbd2
Merge branch 'main' into feature/40-feat-implement-role-based-access-…
vtotalova Apr 7, 2026
6290d0a
fix npm packeges
vtotalova Apr 7, 2026
75cca56
add night mode support
vtotalova Apr 7, 2026
de0a1f8
fix formating
vtotalova Apr 7, 2026
32f5660
add relationship import system
vtotalova Apr 13, 2026
73c6442
Merge branch 'main' into feature/43-feat-create-relationship-import-s…
vtotalova Apr 13, 2026
b9a62db
fix formating
vtotalova Apr 13, 2026
69ecce9
fix npm packeges
vtotalova Apr 14, 2026
246cf78
Merge branch 'main' into feature/40-feat-implement-role-based-access-…
vtotalova Apr 14, 2026
e55c739
fix npm packages
vtotalova Apr 14, 2026
95ab67e
integrate copilot feedback
vtotalova Apr 14, 2026
285634e
Merge branch 'feature/40-feat-implement-role-based-access-control-rba…
vtotalova Apr 14, 2026
91f9c35
implement copilot feedback
vtotalova Apr 14, 2026
74417d5
Merge branch 'main' into feature/43-feat-create-relationship-import-s…
vtotalova Apr 24, 2026
bbdbc4f
Merge branch 'main' into feature/43-feat-create-relationship-import-s…
MaximilianAnzinger Apr 24, 2026
23d6d79
fix migrations
vtotalova Apr 26, 2026
3b33ec4
fix vuln
vtotalova Apr 26, 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
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions sample-data/competencies-sample.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
title,description
Linear Algebra,Understand vectors and matrices and their applications in computer science.
Probability and Statistics,Apply probability theory and statistical inference to model uncertainty.
Graph Theory,"Represent and analyse graphs, implement BFS and DFS, and solve shortest-path problems."
Lambda Calculus,"Understand alpha-equivalence, beta-reduction, and Church encodings."
Logic and Proof Techniques,"Construct formal proofs using propositional logic, induction, and proof by contradiction."
Compiler Design,"Implement lexers, parsers, and code generators; understand IR and optimisation."
Memory Management,"Manage heap and stack allocation, understand garbage collection and ownership."
Design Patterns,Apply creational and structural design patterns to build maintainable software.
API Design,"Design RESTful and GraphQL APIs with versioning, pagination, and error handling."
Distributed Systems,"Reason about CAP theorem, implement consensus protocols and distributed stores."
Data Structures,
43 changes: 43 additions & 0 deletions sample-data/competencies-sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
[
{
"title": "Linear Algebra",
"description": "Understand vectors, matrices, transformations, eigenvalues, and their applications in computer science."
},
{
"title": "Probability and Statistics",
"description": "Apply probability theory, distributions, and statistical inference to model uncertainty in computational systems."
},
{
"title": "Graph Theory",
"description": "Represent and analyse graphs, implement traversal algorithms (BFS, DFS), and solve shortest-path and spanning-tree problems."
},
{
"title": "Lambda Calculus",
"description": "Understand the foundations of functional computation, alpha-equivalence, beta-reduction, and Church encodings."
},
{
"title": "Logic and Proof Techniques",
"description": "Construct formal proofs using propositional and predicate logic, induction, and proof by contradiction."
},
{
"title": "Compiler Design",
"description": "Implement lexers, parsers, semantic analysers, and code generators; understand intermediate representations and optimisation passes."
},
{
"title": "Memory Management",
"description": "Manage heap and stack allocation, understand garbage collection strategies, and reason about ownership and borrowing."
},
{
"title": "Design Patterns",
"description": "Apply creational, structural, and behavioural design patterns to build maintainable and extensible software systems."
},
{
"title": "API Design",
"description": "Design RESTful and GraphQL APIs; apply versioning, pagination, and error-handling conventions."
},
{
"title": "Distributed Systems",
"description": "Reason about consistency, availability, and partition tolerance; implement consensus protocols and distributed data stores."
},
{ "title": "Duplicate: Data Structures" }
]
21 changes: 21 additions & 0 deletions sample-data/relationships-sample.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
originId,originTitle,destinationId,destinationTitle,relationshipType
comp_ds_001,,comp_fp_001,,ASSUMES
comp_fp_001,,comp_hof_001,,EXTENDS
comp_hof_001,,comp_poly_001,,EXTENDS
comp_poly_001,,comp_mod_001,,ASSUMES
comp_fp_001,,comp_mod_001,,ASSUMES
,Data Structures,comp_alg_001,,ASSUMES
comp_alg_001,,,Complexity Theory,EXTENDS
,Complexity Theory,comp_alg_001,,UNRELATED
,Functional Programming,,Type Checking and Inference,ASSUMES
,Higher-Order Functions,,Functional Programming,MATCHES
comp_alg_001,,,Parsing and Grammars,ASSUMES
,Evaluation Strategies,comp_fp_001,,EXTENDS
comp_fp_001,,comp_err_001,,ASSUMES
comp_alg_001,,comp_test_001,,EXTENDS
comp_db_001,,comp_sec_001,,ASSUMES
comp_os_001,,comp_conc_001,,ASSUMES
comp_net_001,,comp_sec_001,,ASSUMES
,Version Control with Git,,Software Security,UNRELATED
,Testing and Verification,,Error Handling,EXTENDS
,Object-Oriented Design,,Module System and Abstraction,MATCHES
103 changes: 103 additions & 0 deletions sample-data/relationships-sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
[
{
"originId": "comp_ds_001",
"destinationId": "comp_fp_001",
"relationshipType": "ASSUMES"
},
{
"originId": "comp_fp_001",
"destinationId": "comp_hof_001",
"relationshipType": "EXTENDS"
},
{
"originId": "comp_hof_001",
"destinationId": "comp_poly_001",
"relationshipType": "EXTENDS"
},
{
"originId": "comp_poly_001",
"destinationId": "comp_mod_001",
"relationshipType": "ASSUMES"
},
{
"originId": "comp_fp_001",
"destinationId": "comp_mod_001",
"relationshipType": "ASSUMES"
},

{
"originTitle": "Data Structures",
"destinationId": "comp_alg_001",
"relationshipType": "ASSUMES"
},
{
"originId": "comp_alg_001",
"destinationTitle": "Complexity Theory",
"relationshipType": "EXTENDS"
},
{
"originTitle": "Functional Programming",
"destinationTitle": "Type Checking and Inference",
"relationshipType": "ASSUMES"
},
{
"originTitle": "Higher-Order Functions",
"destinationTitle": "Functional Programming",
"relationshipType": "MATCHES"
},
{
"originTitle": "Testing and Verification",
"destinationTitle": "Error Handling",
"relationshipType": "EXTENDS"
},

{
"originId": "comp_alg_001",
"destinationTitle": "Parsing and Grammars",
"relationshipType": "ASSUMES"
},
{
"originTitle": "Evaluation Strategies",
"destinationId": "comp_fp_001",
"relationshipType": "EXTENDS"
},
{
"originId": "comp_os_001",
"destinationTitle": "Concurrency and Parallelism",
"relationshipType": "ASSUMES"
},

{
"originId": "comp_db_001",
"destinationId": "comp_sec_001",
"relationshipType": "ASSUMES"
},
{
"originId": "comp_net_001",
"destinationId": "comp_sec_001",
"relationshipType": "ASSUMES"
},
{
"originId": "comp_alg_001",
"destinationId": "comp_test_001",
"relationshipType": "EXTENDS"
},
{
"originId": "comp_fp_001",
"destinationId": "comp_err_001",
"relationshipType": "ASSUMES"
},

{
"originTitle": "Version Control with Git",
"destinationTitle": "Software Security",
"relationshipType": "UNRELATED"
},
{
"originTitle": "Object-Oriented Design",
"destinationTitle": "Module System and Abstraction",
"relationshipType": "MATCHES"
},

{ "originId": "comp_ds_001", "destinationId": "comp_alg_001" }
]
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import de.tum.cit.memo.dto.CompetencyImportRow;
import de.tum.cit.memo.dto.ImportResult;
import de.tum.cit.memo.dto.RelationshipImportRow;
import de.tum.cit.memo.service.CompetencyRelationshipService;
import de.tum.cit.memo.service.CompetencyService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
Expand All @@ -13,9 +15,9 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVRecord;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -33,6 +35,7 @@
public class AdminController {

private final CompetencyService competencyService;
private final CompetencyRelationshipService competencyRelationshipService;
private final ObjectMapper objectMapper;

@PostMapping("/competencies/import")
Expand All @@ -58,6 +61,67 @@ public ResponseEntity<ImportResult> importFile(
return ResponseEntity.ok(competencyService.bulkImportCompetencies(rows));
}

@PostMapping("/relationships/import")
@Operation(summary = "Bulk import competency relationships from JSON array")
public ResponseEntity<ImportResult> importRelationshipsJson(
@RequestBody List<RelationshipImportRow> rows
) {
return ResponseEntity.ok(competencyRelationshipService.bulkImportRelationships(rows));
}

@PostMapping(value = "/relationships/import/file", consumes = "multipart/form-data")
@Operation(summary = "Bulk import competency relationships from CSV or JSON file")
public ResponseEntity<ImportResult> importRelationshipsFile(
@RequestParam("file") MultipartFile file
) throws IOException {
String originalFilename = file.getOriginalFilename();
List<RelationshipImportRow> rows;
if (originalFilename != null && originalFilename.endsWith(".csv")) {
rows = parseCsvRelationships(file);
} else {
rows = objectMapper.readValue(
file.getInputStream(),
objectMapper.getTypeFactory().constructCollectionType(List.class, RelationshipImportRow.class)
);
}
return ResponseEntity.ok(competencyRelationshipService.bulkImportRelationships(rows));
}

private List<RelationshipImportRow> parseCsvRelationships(MultipartFile file) throws IOException {
List<RelationshipImportRow> rows = new ArrayList<>();
CSVFormat format = CSVFormat.DEFAULT.builder()
.setHeader()
.setSkipHeaderRecord(true)
.setTrim(true)
.setIgnoreHeaderCase(true)
.build();
try (var reader = new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8);
var parser = format.parse(reader)) {
for (CSVRecord record : parser) {
RelationshipImportRow row = new RelationshipImportRow();
row.setOriginId(getMappedValue(record, "originId"));
row.setOriginTitle(getMappedValue(record, "originTitle"));
row.setDestinationId(getMappedValue(record, "destinationId"));
row.setDestinationTitle(getMappedValue(record, "destinationTitle"));
row.setRelationshipType(getMappedValue(record, "relationshipType"));
rows.add(row);
}
}
return rows;
}

private String getMappedValue(CSVRecord record, String header) {
if (!record.isMapped(header)) {
return null;
}
String val = record.get(header);
if (val.isEmpty()) {
return null;
} else {
return val;
}
}

private List<CompetencyImportRow> parseCsv(MultipartFile file) throws IOException {
List<CompetencyImportRow> rows = new ArrayList<>();
CSVFormat format = CSVFormat.DEFAULT.builder()
Expand All @@ -68,18 +132,18 @@ private List<CompetencyImportRow> parseCsv(MultipartFile file) throws IOExceptio
try (var reader = new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8);
var parser = format.parse(reader)) {
for (CSVRecord record : parser) {
String title;
if (record.size() > 0) {
title = record.get(0);
} else {
title = "";
}
String description;
if (record.size() > 1) {
description = record.get(1);
} else {
description = null;
}
String title;
if (record.size() > 0) {
title = record.get(0);
} else {
title = "";
}
String description;
if (record.size() > 1) {
description = record.get(1);
} else {
description = null;
}
rows.add(new CompetencyImportRow(title, description));
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package de.tum.cit.memo.dto;

import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class RelationshipImportRow {

private String originId;
private String originTitle;
private String destinationId;
private String destinationTitle;

/** One of: ASSUMES / EXTENDS / MATCHES / UNRELATED */
private String relationshipType;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
public interface CompetencyRepository extends JpaRepository<Competency, String> {
Expand All @@ -29,4 +30,6 @@ public interface CompetencyRepository extends JpaRepository<Competency, String>
void decrementDegree(@Param("ids") List<String> ids);

boolean existsByTitle(String title);

Optional<Competency> findByTitle(String title);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import de.tum.cit.memo.enums.UserRole;
import de.tum.cit.memo.repository.UserRepository;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import org.springframework.core.convert.converter.Converter;
Expand All @@ -26,8 +27,19 @@ public AbstractAuthenticationToken convert(@NonNull Jwt jwt) {
String subject = Objects.requireNonNullElse(jwt.getSubject(), "");
UserRole role = userRepository.findById(subject)
.map(User::getRole)
.orElse(UserRole.USER);
.orElseGet(() -> extractRoleFromJwt(jwt));
return new JwtAuthenticationToken(jwt,
List.of(new SimpleGrantedAuthority("ROLE_" + role.name())));
}

private UserRole extractRoleFromJwt(Jwt jwt) {
Map<String, Object> realmAccess = jwt.getClaim("realm_access");
if (realmAccess != null) {
Object roles = realmAccess.get("roles");
if (roles instanceof List<?> roleList && roleList.contains("ADMIN")) {
return UserRole.ADMIN;
}
}
return UserRole.USER;
}
}
Loading
Loading