diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f6150ead..6ac2829d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,3 +9,13 @@ updates: directory: "/" schedule: interval: "daily" + + - package-ecosystem: "npm" + directory: "/desktop/angular" + schedule: + interval: "daily" + + - package-ecosystem: "cargo" + directory: "/desktop/tauri" + schedule: + interval: "daily" \ No newline at end of file diff --git a/.github/workflows/angular.yml b/.github/workflows/angular.yml new file mode 100644 index 00000000..eef0b8fa --- /dev/null +++ b/.github/workflows/angular.yml @@ -0,0 +1,61 @@ +name: Angular + +on: + push: + paths: + - 'desktop/angular/**' + branches: + - master + - develop + - migration/mono-repo + + pull_request: + paths: + - 'desktop/angular/**' + branches: + - master + - develop + - migration/mono-repo + +jobs: + lint: + name: Linter + runs-on: ubuntu-latest + defaults: + run: + working-directory: desktop/angular + + steps: + - name: Check out code + uses: actions/checkout@v4 + + - uses: actions/setup-node@v3 + with: + node-version: 18 + + - run: npm install + + - uses: sibiraj-s/action-eslint@v3 + with: + annotations: true + extensions: 'ts,html' + working-directory: desktop/angular + + test: + name: Build + runs-on: ubuntu-latest + steps: + - uses: earthly/actions-setup@v1 + with: + version: v0.8.0 + - uses: actions/checkout@v4 + + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build angular projects + run: earthly --ci --remote-cache=ghcr.io/safing/build-cache --push +build-angular diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 8362ac6d..2aaa9639 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -45,5 +45,13 @@ jobs: with: version: v0.8.0 - uses: actions/checkout@v4 - - name: Run tests - run: earthly --ci +test-go --TESTFLAGS="-short" + + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build angular projects + run: earthly --ci --remote-cache=ghcr.io/safing/build-cache --push +test-go --TESTFLAGS="-short" diff --git a/.github/workflows/tauri.yml b/.github/workflows/tauri.yml new file mode 100644 index 00000000..0ffc5c7a --- /dev/null +++ b/.github/workflows/tauri.yml @@ -0,0 +1,38 @@ +name: Tauri + +on: + push: + paths: + - 'desktop/tauri/**' + branches: + - master + - develop + - migration/mono-repo + + pull_request: + paths: + - 'desktop/tauri/**' + branches: + - master + - develop + - migration/mono-repo + +jobs: + build: + name: Build + runs-on: ubuntu-latest + steps: + - uses: earthly/actions-setup@v1 + with: + version: v0.8.0 + - uses: actions/checkout@v4 + + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build angular projects + run: earthly --ci --remote-cache=ghcr.io/safing/build-cache --push +tauri-release diff --git a/Earthfile b/Earthfile index 12b4aeb8..4df0dbfc 100644 --- a/Earthfile +++ b/Earthfile @@ -66,11 +66,11 @@ go-base: LET version = $(git tag --points-at) IF [ "${version}" = "" ] - SET version = $(git describe --tags --abbrev=0 || echo "dev build") + SET version = $(git describe --tags --abbrev=0 || echo "dev_build") END ENV VERSION="${version}" - LET source = $( ( git remote -v | cut -f2 | cut -d" " -f1 | head -n 1 ) || echo "unknown source" ) + LET source = $( ( git remote -v | cut -f2 | cut -d" " -f1 | head -n 1 ) || echo "unknown_source" ) ENV SOURCE="${source}" # updates all go dependencies and runs go mod tidy, saving go.mod and go.sum locally. @@ -222,6 +222,11 @@ angular-project: SAVE ARTIFACT "./${project}.zip" AS LOCAL ${outputDir}/${project}.zip SAVE ARTIFACT "./dist" AS LOCAL ${outputDir}/${project} +# Builds all angular projects +build-angular: + BUILD +angular-project --project=portmaster --dist=./dist --configuration=development --baseHref=/ui/modules/portmaster/ + BUILD +angular-project --project=tauri-builtin --dist=./dist/tauri-builtin --configuration=development --baseHref=/ + # Build the angular projects (portmaster-UI and tauri-builtin) in production mode angular-release: BUILD +angular-project --project=portmaster --dist=./dist --configuration=production --baseHref=/ui/modules/portmaster/ diff --git a/desktop/angular/.eslintrc.json b/desktop/angular/.eslintrc.json new file mode 100644 index 00000000..8bcdf9d2 --- /dev/null +++ b/desktop/angular/.eslintrc.json @@ -0,0 +1,54 @@ +{ + "root": true, + "ignorePatterns": [ + "projects/**/*" + ], + "parserOptions": { + "tsconfigRootDir": "desktop/angular" + }, + "overrides": [ + { + "files": [ + "*.ts" + ], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:@angular-eslint/recommended", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ], + "@typescript-eslint/no-explicit-any": "off" + } + }, + { + "files": [ + "*.html" + ], + "extends": [ + "plugin:@angular-eslint/template/recommended", + "plugin:@angular-eslint/template/accessibility" + ], + "rules": { + "@angular-eslint/template/click-events-have-key-events": "off", + "@angular-eslint/template/interactive-supports-focus": "off" + } + } + ] +} diff --git a/desktop/angular/package.json b/desktop/angular/package.json index 21207615..c1c058c8 100644 --- a/desktop/angular/package.json +++ b/desktop/angular/package.json @@ -96,7 +96,6 @@ "protractor": "~7.0.0", "tailwindcss": "^3.3.2", "ts-node": "^10.9.1", - "tslint": "~6.1.0", "typescript": "4.9", "webpack-bundle-analyzer": "^4.8.0", "webpack-ext-reloader": "^1.1.9", diff --git a/desktop/angular/projects/safing/ui/src/lib/select/select.html b/desktop/angular/projects/safing/ui/src/lib/select/select.html index bccf19af..c3d144eb 100644 --- a/desktop/angular/projects/safing/ui/src/lib/select/select.html +++ b/desktop/angular/projects/safing/ui/src/lib/select/select.html @@ -1,5 +1,5 @@ -
@@ -129,7 +129,7 @@ Quick Settings
    -
  • {{ qds.name }}
  • @@ -350,7 +350,7 @@ d="M11 3a1 1 0 10-2 0v1a1 1 0 102 0V3zM15.657 5.757a1 1 0 00-1.414-1.414l-.707.707a1 1 0 001.414 1.414l.707-.707zM18 10a1 1 0 01-1 1h-1a1 1 0 110-2h1a1 1 0 011 1zM5.05 6.464A1 1 0 106.464 5.05l-.707-.707a1 1 0 00-1.414 1.414l.707.707zM5 10a1 1 0 01-1 1H3a1 1 0 110-2h1a1 1 0 011 1zM8 16v-1h4v1a2 2 0 11-4 0zM12 14c.015-.34.208-.646.477-.859a4 4 0 10-4.954 0c.27.213.462.519.476.859h4.002z" /> Pro Tip: - +
diff --git a/desktop/angular/src/app/shared/netquery/netquery.component.ts b/desktop/angular/src/app/shared/netquery/netquery.component.ts index d4befb47..a09d18eb 100644 --- a/desktop/angular/src/app/shared/netquery/netquery.component.ts +++ b/desktop/angular/src/app/shared/netquery/netquery.component.ts @@ -39,6 +39,7 @@ const freeTextSearchFields: (keyof Partial)[] = [ 'as_owner', 'path', 'profile_name', + 'remote_ip' ] const groupByKeys: (keyof Partial)[] = [ diff --git a/desktop/angular/src/app/shared/netquery/textql/lexer.ts b/desktop/angular/src/app/shared/netquery/textql/lexer.ts index 008cbd6e..a3f2fe93 100644 --- a/desktop/angular/src/app/shared/netquery/textql/lexer.ts +++ b/desktop/angular/src/app/shared/netquery/textql/lexer.ts @@ -43,7 +43,7 @@ export class Lexer { } /** reads a number token */ - private readNumber(): Token { + private readNumber(): Token | null { const start = this._input.pos; let has_dot = false; @@ -59,9 +59,10 @@ export class Lexer { return isDigit(ch); }); - if (!this._input.eof() && isIdentChar(this._input.peek())) { - this._input.revert(number.length + 1); - this._input.croak("invalid number character") + if (!this._input.eof() && !isWhitespace(this._input.peek())) { + this._input.revert(number.length); + + return null; } return { @@ -182,13 +183,11 @@ export class Lexer { return this.readString('\'', true); } - try { - if (isDigit(ch)) { - return this.readNumber(); + if (isDigit(ch)) { + const number = this.readNumber(); + if (number !== null) { + return number; } - } catch (err) { - // we ignore that error here as it may only happen for unqoted strings - // that start with a number. } if (ch === ':') { diff --git a/desktop/angular/src/theme/_button.scss b/desktop/angular/src/theme/_button.scss index 39012ee7..b1ac1976 100644 --- a/desktop/angular/src/theme/_button.scss +++ b/desktop/angular/src/theme/_button.scss @@ -7,6 +7,8 @@ @apply capitalize; @apply rounded-sm; @apply font-medium; + @apply focus:underline focus:underline-offset-4; + user-select: none; outline: none; cursor: pointer; diff --git a/desktop/angular/tslint.json b/desktop/angular/tslint.json deleted file mode 100644 index eba6f798..00000000 --- a/desktop/angular/tslint.json +++ /dev/null @@ -1,153 +0,0 @@ -{ - "extends": "tslint:recommended", - "rules": { - "align": { - "options": [ - "parameters", - "statements" - ] - }, - "array-type": false, - "arrow-return-shorthand": true, - "curly": true, - "deprecation": { - "severity": "warning" - }, - "component-class-suffix": true, - "contextual-lifecycle": true, - "directive-class-suffix": true, - "directive-selector": [ - true, - "attribute", - "app", - "camelCase" - ], - "component-selector": [ - true, - "element", - "app", - "kebab-case" - ], - "eofline": true, - "import-blacklist": [ - true, - "rxjs/Rx" - ], - "import-spacing": true, - "indent": { - "options": [ - "spaces" - ] - }, - "max-classes-per-file": false, - "max-line-length": [ - true, - 140 - ], - "member-ordering": [ - true, - { - "order": [ - "static-field", - "instance-field", - "static-method", - "instance-method" - ] - } - ], - "no-any": true, - "no-console": [ - true, - "debug", - "info", - "time", - "timeEnd", - "trace" - ], - "no-empty": false, - "no-inferrable-types": [ - true, - "ignore-params" - ], - "no-non-null-assertion": true, - "no-redundant-jsdoc": true, - "no-switch-case-fall-through": true, - "no-var-requires": false, - "object-literal-key-quotes": [ - true, - "as-needed" - ], - "quotemark": [ - true, - "single" - ], - "semicolon": { - "options": [ - "always" - ] - }, - "space-before-function-paren": { - "options": { - "anonymous": "never", - "asyncArrow": "always", - "constructor": "never", - "method": "never", - "named": "never" - } - }, - "typedef": [ - true, - "call-signature" - ], - "typedef-whitespace": { - "options": [ - { - "call-signature": "nospace", - "index-signature": "nospace", - "parameter": "nospace", - "property-declaration": "nospace", - "variable-declaration": "nospace" - }, - { - "call-signature": "onespace", - "index-signature": "onespace", - "parameter": "onespace", - "property-declaration": "onespace", - "variable-declaration": "onespace" - } - ] - }, - "variable-name": { - "options": [ - "ban-keywords", - "check-format", - "allow-pascal-case" - ] - }, - "whitespace": { - "options": [ - "check-branch", - "check-decl", - "check-operator", - "check-separator", - "check-type", - "check-typecast" - ] - }, - "no-conflicting-lifecycle": true, - "no-host-metadata-property": true, - "no-input-rename": true, - "no-inputs-metadata-property": true, - "no-output-native": true, - "no-output-on-prefix": true, - "no-output-rename": true, - "no-outputs-metadata-property": true, - "template-banana-in-box": true, - "template-no-negated-async": true, - "use-lifecycle-interface": true, - "use-pipe-transform-interface": true - }, - "rulesDirectory": [ - "codelyzer" - ] -} \ No newline at end of file