Skip to content

Commit

Permalink
Merge branch 'develop' into enhancement/learning-path/user-interface
Browse files Browse the repository at this point in the history
  • Loading branch information
MaximilianAnzinger authored Oct 15, 2023
2 parents af50800 + 60927d0 commit d30fe88
Show file tree
Hide file tree
Showing 245 changed files with 5,310 additions and 1,884 deletions.
11 changes: 11 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ node_modules
# exclude build binaries except a pre-built .war file
build/*
!build/libs/*.war
# exlude the .cache of angular
.cache
# exclude the .gradle cache
.gradle

#########################
# exclude Artemis configs
Expand All @@ -38,6 +42,13 @@ build/*
# exclude the docker files and the /docker/.docker-data folders
docker/

######################
# Artemis resources
######################
/src/main/resources/config/application-local*.yml
/src/main/resources/id_*
/src/main/resources/known_hosts

# files inside of the root directory not needed
CITATION.cff
CODE_OF_CONDUCT.md
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ jobs:
context: .
tags: ghcr.io/ls1intum/artemis:${{ steps.compute-tag.outputs.result }}
push: true
cache-from: type=gha
cache-to: type=gha,mode=min

# TODO: Push to Docker Hub (develop + tag)

Expand Down
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ dependencies {
implementation "commons-fileupload:commons-fileupload:1.5"
implementation "net.lingala.zip4j:zip4j:2.11.5"
implementation "org.jgrapht:jgrapht-core:1.5.2"
implementation 'com.github.seancfoley:ipaddress:5.4.0'


annotationProcessor "org.hibernate:hibernate-jpamodelgen:${hibernate_version}"
Expand Down Expand Up @@ -431,6 +432,11 @@ node {
npmVersion = "${npm_version}"
}

// Set the npm cache (used in the Dockerfile)
task npmSetCacheDockerfile(type: NpmTask) {
args = ['set', 'cache', '/opt/artemis/.npm']
}

// Command to execute the JavaDoc checkstyle verification ./gradlew checkstyleMain
checkstyle {
toolVersion "${checkstyle_version}"
Expand Down
38 changes: 33 additions & 5 deletions docker/artemis/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,44 @@ ARG WAR_FILE_STAGE="builder"
#-----------------------------------------------------------------------------------------------------------------------
FROM --platform=$BUILDPLATFORM docker.io/library/eclipse-temurin:17-jdk as builder

WORKDIR /opt/artemis

# some Apple M1 (arm64) builds need python3 and build-essential(make+gcc) for node-gyp to not fail
RUN echo "Installing build dependencies" \
&& apt-get update && apt-get install -y --no-install-recommends python3 build-essential \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /opt/artemis
# copy gradle related files
COPY gradlew gradlew.bat ./
COPY build.gradle gradle.properties settings.gradle ./
COPY gradle gradle/
# copy npm related files and install node modules
# (from https://stackoverflow.com/questions/63961934/how-to-use-docker-build-cache-when-version-bumping-a-react-app)
COPY package.json package-lock.json ./
RUN \
# Mount global cache for Gradle (project cache in /opt/artemis/.gradle doesn't seem to be populated)
--mount=type=cache,target=/root/.gradle/caches \
# Mount cache for npm
--mount=type=cache,target=/opt/artemis/.npm \
# Create .npm directory if not yet available
mkdir -p /opt/artemis/.npm \
# Set .npm directory as npm cache
&& ./gradlew -i --stacktrace --no-daemon -Pprod -Pwar npmSetCacheDockerfile \
# Pre-populate the npm and gradle caches if related files change (see COPY statements above)
&& ./gradlew -i --stacktrace --no-daemon -Pprod -Pwar npm_ci

# so far just using the .dockerignore to define what isn't necessary here
COPY . .

RUN ./gradlew -i --stacktrace --no-daemon -Pprod -Pwar clean bootWar
RUN \
# Mount global cache for Gradle (project cache in /opt/artemis/.gradle doesn't seem to be populated)
--mount=type=cache,target=/root/.gradle/caches \
# Mount cache for npm
--mount=type=cache,target=/opt/artemis/.npm \
# Mount cache for the Angular CLI
--mount=type=cache,target=/opt/artemis/.cache \
# Build the .war file
./gradlew -i --stacktrace --no-daemon -Pprod -Pwar clean bootWar

#-----------------------------------------------------------------------------------------------------------------------
# external build stage
Expand Down Expand Up @@ -73,15 +99,17 @@ RUN echo "Installing needed dependencies" \
&& rm -rf /var/lib/apt/lists/*

# See https://github.com/ls1intum/Artemis/issues/4439
RUN echo "Fixing locales" \
RUN \
echo "Fixing locales" \
&& sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \
&& locale-gen
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US.UTF-8

# Create directories for volumes, create artemis user and set right owners
RUN mkdir -p /opt/artemis/config /opt/artemis/data /opt/artemis/public/content \
RUN \
mkdir -p /opt/artemis/config /opt/artemis/data /opt/artemis/public/content \
&& groupadd --gid ${GID} artemis \
&& useradd -m --gid ${GID} --uid ${UID} --shell /bin/bash artemis \
&& chown -R artemis:artemis /opt/artemis
Expand Down
2 changes: 1 addition & 1 deletion docs/dev/setup.rst
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,7 @@ Other useful commands
``docker compose start <name of the service>``)
- Restart a service: ``docker compose restart <name of the service>``
- Remove all local Docker containers: ``docker container rm $(docker ps -a -q)``
- Remove all local Artemis Docker images: ``docker rmi $(docker images -q ghcr.io/ls1intum/artemis)``
- Remove all local Artemis Docker images: ``docker rmi $(docker images --filter=reference="ghcr.io/ls1intum/artemis:*" -q)``

------------------------------------------------------------------------------------------------------------------------

Expand Down
108 changes: 80 additions & 28 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,78 @@
const esModules = ['lodash-es', 'franc-min', 'trigram-utils', 'n-gram', 'collapse-white-space', '@angular/animations', '@angular/common', '@ls1intum/apollon',
'@angular/compiler', '@angular/core', '@angular/forms', '@angular/localize', '@angular/platform-browser', '@angular/platform-browser-dynamic', '@angular/router',
'@ngx-translate/core', '@ngx-translate/http-loader', '@fortawesome/angular-fontawesome', '@angular/cdk', '@angular/material', '@angular/cdk', 'dayjs/esm',
'rxjs/operators', '@ng-bootstrap/ng-bootstrap', 'ngx-webstorage', '@ctrl/ngx-emoji-mart', 'ngx-device-detector', '@swimlane/ngx-charts',
'@angular/service-worker', '@danielmoncada/angular-datetime-picker', '@flaviosantoro92/ngx-datatable', 'd3-color', 'd3-interpolate', 'd3-transition', 'd3-brush',
'd3-drag', 'd3-selection', 'd3-scale', 'd3-array', 'd3-format', 'd3-shape', 'd3-path', 'd3-ease', 'd3-time', 'd3-hierarchy', 'ngx-infinite-scroll', 'internmap',
'@swimlane/ngx-graph'].join('|');
const esModules = [
'lodash-es',
'franc-min',
'trigram-utils',
'n-gram',
'collapse-white-space',
'@angular/animations',
'@angular/common',
'@ls1intum/apollon',
'@angular/compiler',
'@angular/core',
'@angular/forms',
'@angular/localize',
'@angular/platform-browser',
'@angular/platform-browser-dynamic',
'@angular/router',
'@ngx-translate/core',
'@ngx-translate/http-loader',
'@fortawesome/angular-fontawesome',
'@angular/cdk',
'@angular/material',
'@angular/cdk',
'dayjs/esm',
'rxjs/operators',
'@ng-bootstrap/ng-bootstrap',
'ngx-webstorage',
'@ctrl/ngx-emoji-mart',
'ngx-device-detector',
'@swimlane/ngx-charts',
'@angular/service-worker',
'@danielmoncada/angular-datetime-picker',
'@flaviosantoro92/ngx-datatable',
'd3-color',
'd3-interpolate',
'd3-transition',
'd3-brush',
'd3-drag',
'd3-selection',
'd3-scale',
'd3-array',
'd3-format',
'd3-shape',
'd3-path',
'd3-ease',
'd3-time',
'd3-hierarchy',
'ngx-infinite-scroll',
'internmap',
'@swimlane/ngx-graph',
].join('|');

const {
compilerOptions: { baseUrl = './' },
} = require('./tsconfig.json');

module.exports = {
globalSetup: 'jest-preset-angular/global-setup',
globals: {
'ts-jest': {
tsconfig: '<rootDir>/tsconfig.spec.json',
stringifyContentPathRegex: '\\.html$',
isolatedModules: true,
diagnostics: {
ignoreCodes: [151001],
},
},
},
testEnvironmentOptions: {
url: 'https://artemis.fake/test'
url: 'https://artemis.fake/test',
},
roots: ['<rootDir>', `<rootDir>/${baseUrl}`],
modulePaths: [`<rootDir>/${baseUrl}`],
setupFiles: ['jest-date-mock'],
cacheDirectory: '<rootDir>/build/jest-cache',
coverageDirectory: '<rootDir>/build/test-results/',
reporters: ['default', ['jest-junit', { outputDirectory: '<rootDir>/build/test-results/', outputName: 'TESTS-results-jest.xml' }]],
reporters: [
'default',
[
'jest-junit',
{
outputDirectory: '<rootDir>/build/test-results/',
outputName: 'TESTS-results-jest.xml',
},
],
],
collectCoverageFrom: ['src/main/webapp/**/*.{js,jsx,ts,tsx}', '!src/main/webapp/**/*.module.{js,jsx,ts,tsx}'],
coveragePathIgnorePatterns: [
'/node_modules/',
Expand All @@ -53,24 +95,34 @@ module.exports = {
'src/main/webapp/app/exercises/modeling/manage/modeling-exercise.route.ts',
'src/main/webapp/app/exam/manage/exam-management.route.ts',
'src/main/webapp/app/exercises/shared/exercise-hint/manage/exercise-hint.route.ts',
'src/main/webapp/app/core/config/prod.config.ts'
'src/main/webapp/app/core/config/prod.config.ts',
],
coverageThreshold: {
global: {
// TODO: in the future, the following values should increase to at least 90%
statements: 85.6,
branches: 72.8,
functions: 79.4,
lines: 85.8,
statements: 85.9,
branches: 73.2,
functions: 79.7,
lines: 86.1,
},
},
coverageReporters: ["clover", "json", "lcov", "text-summary"],
coverageReporters: ['clover', 'json', 'lcov', 'text-summary'],
setupFilesAfterEnv: ['<rootDir>/src/test/javascript/spec/jest-test-setup.ts', 'jest-extended/all'],
moduleFileExtensions: ['ts', 'html', 'js', 'json', 'mjs'],
resolver: '<rootDir>/jest.resolver.js',
transformIgnorePatterns: [`/node_modules/(?!${esModules})`],
transform: {
'^.+\\.(ts|js|mjs|html|svg)$': 'jest-preset-angular',
'^.+\\.(ts|js|mjs|html|svg)$': [
'jest-preset-angular',
{
tsconfig: '<rootDir>/tsconfig.spec.json',
stringifyContentPathRegex: '\\.html$',
isolatedModules: true,
diagnostics: {
ignoreCodes: [151001],
},
},
],
},
modulePathIgnorePatterns: [],
testTimeout: 3000,
Expand All @@ -84,7 +136,7 @@ module.exports = {
'<rootDir>/src/test/javascript/spec/util/**/*.spec.ts',
'<rootDir>/src/test/javascript/spec/interceptor/**/*.spec.ts',
'<rootDir>/src/test/javascript/spec/config/**/*.spec.ts',
'<rootDir>/src/test/javascript/spec/core/**/*.spec.ts'
'<rootDir>/src/test/javascript/spec/core/**/*.spec.ts',
],
moduleNameMapper: {
'^app/(.*)': '<rootDir>/src/main/webapp/app/$1',
Expand All @@ -94,6 +146,6 @@ module.exports = {
'@env': '<rootDir>/src/main/webapp/environments/environment',
'@src/(.*)': '<rootDir>/src/src/$1',
'@state/(.*)': '<rootDir>/src/app/state/$1',
"^lodash-es$": "lodash"
'^lodash-es$': 'lodash',
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

/**
* A set of related exam sessions that are suspicious.
* An exam session is suspicious if it shares the same browser fingerprint hash or user agent or IP address with another
* An exam session is suspicious if it fulfills one of the criteria defined in {@link SuspiciousSessionReason}.
* exam session that attempts a different student exam.
*
* @param examSessions the set of exam sessions that are suspicious
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
* Enum representing reasons why a session is considered suspicious.
*/
public enum SuspiciousSessionReason {
SAME_IP_ADDRESS, SAME_BROWSER_FINGERPRINT
DIFFERENT_STUDENT_EXAMS_SAME_IP_ADDRESS, DIFFERENT_STUDENT_EXAMS_SAME_BROWSER_FINGERPRINT, SAME_STUDENT_EXAM_DIFFERENT_IP_ADDRESSES,
SAME_STUDENT_EXAM_DIFFERENT_BROWSER_FINGERPRINTS, IP_ADDRESS_OUTSIDE_OF_RANGE
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package de.tum.in.www1.artemis.domain.exam;

/**
* Options for the analysis of suspicious sessions.
* The options define which criteria are used to determine whether a session is suspicious.
*
* @param sameBrowserFingerprintDifferentStudentExams whether sessions should be analyzed for the same browser fingerprint but different student exams
* @param sameIpAddressDifferentStudentExams whether sessions should be analyzed for the same IP address but different student exams
* @param differentIpAddressesSameStudentExam whether sessions should be analyzed for different IP addresses but the same student exam
* @param differentBrowserFingerprintsSameStudentExam whether sessions should be analyzed for different browser fingerprints but the same student exam
* @param ipAddressOutsideOfRange whether sessions should be analyzed for IP addresses outside the specified IP range
*/
public record SuspiciousSessionsAnalysisOptions(boolean sameIpAddressDifferentStudentExams, boolean sameBrowserFingerprintDifferentStudentExams,
boolean differentIpAddressesSameStudentExam, boolean differentBrowserFingerprintsSameStudentExam, boolean ipAddressOutsideOfRange) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ public class IrisSubSettings extends DomainObject {
@Column(name = "preferredModel")
private String preferredModel;

@Nullable
@Column(name = "rateLimit")
private Integer rateLimit;

@Nullable
@Column(name = "rateLimitTimeframeHours")
private Integer rateLimitTimeframeHours;

public boolean isEnabled() {
return enabled;
}
Expand All @@ -57,4 +65,22 @@ public String getPreferredModel() {
public void setPreferredModel(@Nullable String preferredModel) {
this.preferredModel = preferredModel;
}

@Nullable
public Integer getRateLimit() {
return rateLimit;
}

public void setRateLimit(@Nullable Integer rateLimit) {
this.rateLimit = rateLimit;
}

@Nullable
public Integer getRateLimitTimeframeHours() {
return rateLimitTimeframeHours;
}

public void setRateLimitTimeframeHours(@Nullable Integer rateLimitTimeframeHours) {
this.rateLimitTimeframeHours = rateLimitTimeframeHours;
}
}
Loading

0 comments on commit d30fe88

Please sign in to comment.