diff --git a/.github/workflows/baseimage.yaml b/.github/workflows/baseimage.yaml index d4c28a7968..0d33f7f07f 100644 --- a/.github/workflows/baseimage.yaml +++ b/.github/workflows/baseimage.yaml @@ -31,7 +31,7 @@ jobs: "containerd-snapshotter": true } } - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 1 filter: tree:0 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 753708009e..c71da5d6e5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -68,7 +68,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: ref: ${{ github.event.inputs.ref || github.ref }} fetch-depth: 0 @@ -78,7 +78,7 @@ jobs: with: node-version-file: '.nvmrc' - name: Cache node modules - uses: actions/cache@v5 + uses: actions/cache@v6 env: cache-name: cache-node-platform with: @@ -127,7 +127,7 @@ jobs: run: node common/scripts/install-run-rush.js validate - name: Cache build results - uses: actions/cache@v5 + uses: actions/cache@v6 env: cache-name: cache-build-results with: @@ -139,7 +139,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 0 filter: tree:0 @@ -150,7 +150,7 @@ jobs: node-version-file: '.nvmrc' - name: Cache build results - uses: actions/cache@v5 + uses: actions/cache@v6 env: cache-name: cache-build-results with: @@ -165,7 +165,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 0 submodules: recursive @@ -173,7 +173,7 @@ jobs: with: node-version-file: '.nvmrc' - name: Cache build results - uses: actions/cache@v5 + uses: actions/cache@v6 env: cache-name: cache-build-results with: @@ -196,7 +196,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 0 filter: tree:0 @@ -205,7 +205,7 @@ jobs: with: node-version-file: '.nvmrc' - name: Cache build results - uses: actions/cache@v5 + uses: actions/cache@v6 env: cache-name: cache-build-results with: @@ -234,7 +234,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 0 filter: tree:0 @@ -243,7 +243,7 @@ jobs: with: node-version-file: '.nvmrc' - name: Cache node modules - uses: actions/cache@v5 + uses: actions/cache@v6 env: cache-name: cache-node-platform with: @@ -322,7 +322,7 @@ jobs: name: playwright-results path: ./tests/sanity/playwright-report/ # - name: Get Allure history - # uses: actions/checkout@v6 + # uses: actions/checkout@v7 # if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') }} # continue-on-error: true # with: @@ -366,7 +366,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 0 filter: tree:0 @@ -375,7 +375,7 @@ jobs: with: node-version-file: '.nvmrc' - name: Cache node modules - uses: actions/cache@v5 + uses: actions/cache@v6 env: cache-name: cache-node-platform with: @@ -463,7 +463,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 0 filter: tree:0 @@ -472,7 +472,7 @@ jobs: with: node-version-file: '.nvmrc' - name: Cache node modules - uses: actions/cache@v5 + uses: actions/cache@v6 env: cache-name: cache-node-platform with: @@ -544,7 +544,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 0 filter: tree:0 @@ -553,7 +553,7 @@ jobs: with: node-version-file: '.nvmrc' - name: Cache node modules - uses: actions/cache@v5 + uses: actions/cache@v6 env: cache-name: cache-node-platform with: @@ -641,7 +641,7 @@ jobs: timeout-minutes: 60 steps: # https://github.com/actions/runner-images/issues/2840#issuecomment-790492173 - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 0 filter: tree:0 @@ -674,7 +674,7 @@ jobs: with: version: 10 - name: Cache node modules - uses: actions/cache@v5 + uses: actions/cache@v6 env: cache-name: cache-node-platform with: @@ -744,7 +744,7 @@ jobs: runs-on: macos-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 0 filter: tree:0 @@ -755,7 +755,7 @@ jobs: node-version-file: '.nvmrc' - name: Cache node modules - uses: actions/cache@v5 + uses: actions/cache@v6 env: cache-name: node with: @@ -847,7 +847,7 @@ jobs: runs-on: macos-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: fetch-depth: 0 filter: tree:0 @@ -858,7 +858,7 @@ jobs: node-version-file: '.nvmrc' - name: Cache node modules - uses: actions/cache@v5 + uses: actions/cache@v6 env: cache-name: node with: @@ -949,7 +949,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: ref: ${{ github.event.inputs.ref || github.ref }} fetch-depth: 0 @@ -957,7 +957,7 @@ jobs: with: node-version-file: '.nvmrc' - name: Cache node modules - uses: actions/cache@v5 + uses: actions/cache@v6 env: cache-name: cache-node-platform with: diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 617a7671c2..7321d99ac0 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: ref: ${{ github.event.inputs.ref }} fetch-depth: 0 @@ -23,7 +23,7 @@ jobs: with: node-version-file: '.nvmrc' - name: Cache node modules - uses: actions/cache@v5 + uses: actions/cache@v6 env: cache-name: cache-node-platform with: diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..6f1b1e345e --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,27 @@ +# Security Policy + +## Reporting a Vulnerability + +We take security seriously. If you discover a security vulnerability in the +Huly Platform, please report it privately — **do not open a public issue.** + +Use GitHub's private vulnerability reporting: + +1. Go to the [Security tab](https://github.com/hcengineering/platform/security) of this repository. +2. Click **"Report a vulnerability"**. +3. Fill in the advisory with as much detail as possible (affected component, + reproduction steps, impact, suggested fix if any). + +We'll acknowledge your report, investigate, and coordinate a fix and +disclosure timeline with you before any public disclosure. + +## Supported Versions + +Security fixes are applied to the latest release on the `main`/`develop` +branch. Older versions are not guaranteed to receive patches. + +## Scope + +This policy covers the code in this repository. Vulnerabilities in +third-party dependencies should be reported upstream, though we're happy to +hear about them too if they affect the Platform directly. diff --git a/models/hr/src/migration.ts b/models/hr/src/migration.ts index a0fa8fe9e8..366bd38a7a 100644 --- a/models/hr/src/migration.ts +++ b/models/hr/src/migration.ts @@ -22,7 +22,8 @@ import { DOMAIN_MODEL_TX, type TxCUD } from '@hcengineering/core' -import { type Department } from '@hcengineering/hr' +import contact, { type Employee, type Person } from '@hcengineering/contact' +import { type Department, type Staff } from '@hcengineering/hr' import { migrateSpace, tryMigrate, @@ -32,6 +33,7 @@ import { type MigrationUpgradeClient } from '@hcengineering/model' import core, { DOMAIN_SPACE, getAccountsFromTxes } from '@hcengineering/model-core' +import { DOMAIN_CONTACT } from '@hcengineering/model-contact' import hr, { DOMAIN_HR, hrId } from './index' @@ -103,6 +105,52 @@ async function migrateDepartmentMembersToEmployee (client: MigrationClient): Pro } } +async function rebuildDepartmentMembersFromStaff (client: MigrationClient): Promise { + const departments = await client.find(DOMAIN_HR, { _class: hr.class.Department }) + const departmentById = new Map(departments.map((department) => [department._id, department])) + const membersByDepartment = new Map, Set>>( + departments.map((department) => [department._id, new Set>()]) + ) + + const getHierarchy = (department: Ref): Ref[] => { + const result: Ref[] = [] + let current: Ref | undefined = department + + while (current !== undefined) { + if (result.includes(current)) { + break + } + + const currentDepartment = departmentById.get(current) + if (currentDepartment === undefined) { + break + } + + result.push(currentDepartment._id) + current = currentDepartment.parent ?? (currentDepartment._id !== hr.ids.Head ? hr.ids.Head : undefined) + } + + return result + } + + const persons = await client.find(DOMAIN_CONTACT, { _class: contact.class.Person }) + for (const person of persons) { + const staff = client.hierarchy.asIf(person, hr.mixin.Staff) + if (staff?.department === undefined || !staff.active) { + continue + } + + for (const department of getHierarchy(staff.department)) { + membersByDepartment.get(department)?.add(person._id as Ref) + } + } + + for (const department of departments) { + const members = Array.from(membersByDepartment.get(department._id) ?? []) + await client.update(DOMAIN_HR, { _id: department._id }, { members }) + } +} + export const hrOperation: MigrateOperation = { async migrate (client: MigrationClient, mode): Promise { await tryMigrate(mode, client, hrId, [ @@ -120,6 +168,10 @@ export const hrOperation: MigrateOperation = { { state: 'migrateDepartmentMembersToEmployee', func: migrateDepartmentMembersToEmployee + }, + { + state: 'rebuildDepartmentMembersFromStaff', + func: rebuildDepartmentMembersFromStaff } ]) }, diff --git a/models/server-hr/src/index.ts b/models/server-hr/src/index.ts index 5370433f12..d936356bdf 100644 --- a/models/server-hr/src/index.ts +++ b/models/server-hr/src/index.ts @@ -41,6 +41,14 @@ export function createModel (builder: Builder): void { } }) + builder.createDoc(serverCore.class.Trigger, core.space.Model, { + trigger: serverHr.trigger.OnDepartmentUpdate, + txMatch: { + objectClass: hr.class.Department, + _class: core.class.TxUpdateDoc + } + }) + builder.createDoc(serverCore.class.Trigger, core.space.Model, { trigger: serverHr.trigger.OnRequestCreate, txMatch: { diff --git a/plugins/hr-resources/src/components/DepartmentCard.svelte b/plugins/hr-resources/src/components/DepartmentCard.svelte index a23c2c6d3f..611e877410 100644 --- a/plugins/hr-resources/src/components/DepartmentCard.svelte +++ b/plugins/hr-resources/src/components/DepartmentCard.svelte @@ -77,7 +77,8 @@ $: dragPersonId = dragPerson?._id - $: values = allEmployees.filter((it) => it.department === value._id && it._id !== dragPersonId) + $: members = new Set>(value.members as Ref[]) + $: values = allEmployees.filter((it) => members.has(it._id) && it._id !== dragPersonId) $: dragging = value._id === dragOver?._id && dragPersonId !== undefined diff --git a/plugins/hr-resources/src/components/DepartmentStaff.svelte b/plugins/hr-resources/src/components/DepartmentStaff.svelte index a7f5979792..ba809b73fa 100644 --- a/plugins/hr-resources/src/components/DepartmentStaff.svelte +++ b/plugins/hr-resources/src/components/DepartmentStaff.svelte @@ -13,10 +13,10 @@ // limitations under the License. --> diff --git a/plugins/hr-resources/src/components/schedule/StaffPresenter.svelte b/plugins/hr-resources/src/components/schedule/StaffPresenter.svelte index c5870bdad9..7c9d662f6f 100644 --- a/plugins/hr-resources/src/components/schedule/StaffPresenter.svelte +++ b/plugins/hr-resources/src/components/schedule/StaffPresenter.svelte @@ -14,7 +14,8 @@ -->