From 0166024f48a0fa6a9b91e20b3bf1e8643751e4e8 Mon Sep 17 00:00:00 2001 From: david-loe <56305409+david-loe@users.noreply.github.com> Date: Sat, 28 Sep 2024 10:12:55 +0200 Subject: [PATCH 1/8] adding supervisedProjects to user --- backend/controller/projectController.ts | 3 ++- backend/data/settings.json | 2 +- backend/migrations.ts | 4 +++ backend/models/user.ts | 26 ++++++++++++++----- common/forms/user.json | 2 +- common/locales/de.json | 2 ++ common/locales/en.json | 2 ++ common/types.ts | 5 +++- .../components/elements/ProjectSelector.vue | 4 +-- .../src/components/settings/SettingsPage.vue | 4 +-- .../components/settings/elements/UserList.vue | 8 +++--- 11 files changed, 44 insertions(+), 18 deletions(-) diff --git a/backend/controller/projectController.ts b/backend/controller/projectController.ts index fcb5b7f..d1545a0 100644 --- a/backend/controller/projectController.ts +++ b/backend/controller/projectController.ts @@ -22,7 +22,8 @@ export class ProjectController extends Controller { request.user?.access['examine/travel'] || request.user?.access['examine/expenseReport'] || request.user?.access['examine/healthCareCost'] || - request.user?.access['confirm/healthCareCost'] + request.user?.access['confirm/healthCareCost'] || + request.user?.access['admin'] ) { return await this.getter(Project, { query, projection: { identifier: 1, organisation: 1 } }) } else { diff --git a/backend/data/settings.json b/backend/data/settings.json index a60f1f3..b556eed 100644 --- a/backend/data/settings.json +++ b/backend/data/settings.json @@ -94,5 +94,5 @@ }, "uploadTokenExpireAfterSeconds": 600, "userCanSeeAllProjects": true, - "version": "1.2.3" + "version": "1.2.4" } diff --git a/backend/migrations.ts b/backend/migrations.ts index ffb3134..460ba6f 100644 --- a/backend/migrations.ts +++ b/backend/migrations.ts @@ -55,6 +55,10 @@ export async function checkForMigrations() { throw Error("Couldn't find settings") } } + case '1.2.3': { + console.log('Apply migration from v1.2.3: Move projects from settings.projects to projects.assigned') + await mongoose.connection.collection('users').updateMany({}, { $rename: { 'settings.projects': 'projects.assigned' } }) + } default: if (settings) { settings.migrateFrom = undefined diff --git a/backend/models/user.ts b/backend/models/user.ts index 3f33060..f267491 100644 --- a/backend/models/user.ts +++ b/backend/models/user.ts @@ -53,13 +53,20 @@ export const userSchema = new Schema({ required: true }, access: { type: accessObject, default: () => ({}) }, + projects: { + type: { + assigned: { type: [{ type: Schema.Types.ObjectId, ref: 'Project' }], required: true, label: 'labels.assignedProjects' }, + supervised: { type: [{ type: Schema.Types.ObjectId, ref: 'Project' }], required: true, label: 'labels.supervisedProjects' } + }, + required: true + }, + loseAccessAt: { type: Date, info: 'info.loseAccessAt' }, settings: { type: { language: { type: String, default: process.env.VITE_I18N_LOCALE, enum: locales }, lastCurrencies: { type: [{ type: String, ref: 'Currency' }], required: true }, lastCountries: { type: [{ type: String, ref: 'Country' }], required: true }, - projects: { type: [{ type: Schema.Types.ObjectId, ref: 'Project' }], required: true }, insurance: { type: Schema.Types.ObjectId, ref: 'HealthInsurance' }, organisation: { type: Schema.Types.ObjectId, ref: 'Organisation' } }, @@ -76,7 +83,7 @@ function populate(doc: Document) { doc.populate({ path: 'settings.organisation', select: { name: 1 } }), doc.populate({ path: 'settings.lastCurrencies' }), doc.populate({ path: 'settings.lastCountries', select: { name: 1, flag: 1, currency: 1 } }), - doc.populate({ path: 'settings.projects' }), + doc.populate({ path: 'projects.assigned' }), doc.populate({ path: 'vehicleRegistration', select: { name: 1, type: 1 } }), doc.populate<{ token: Token }>({ path: 'token', populate: { path: 'files', select: { name: 1, type: 1 } } }) ]) @@ -161,12 +168,19 @@ userSchema.methods.merge = async function (this: UserDoc, userToOverwrite: Parti } delete userToOverwrite.access - Object.assign(this.settings, userToOverwrite.settings, thisPojo.settings) - for (const p of userToOverwrite.settings!.projects) { - if (!this.settings.projects.some((tp) => tp._id.equals(p._id))) { - this.settings.projects.push(p) + for (const p of userToOverwrite.projects!.assigned) { + if (!this.projects.assigned.some((tp) => tp._id.equals(p._id))) { + this.projects.assigned.push(p) } } + + for (const p of userToOverwrite.projects!.supervised) { + if (!this.projects.supervised.some((tp) => tp._id.equals(p._id))) { + this.projects.supervised.push(p) + } + } + + Object.assign(this.settings, userToOverwrite.settings, thisPojo.settings) delete userToOverwrite.settings Object.assign(this, userToOverwrite, this.toObject()) diff --git a/common/forms/user.json b/common/forms/user.json index 73a7ced..226955a 100755 --- a/common/forms/user.json +++ b/common/forms/user.json @@ -1 +1 @@ -{"fk":{"rules":["required"],"label":{"de":"Authentifizierung","en":"Authentication"},"type":"object","schema":{"microsoft":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"placeholder":{"de":"Microsoft ID","en":"Microsoft ID"},"type":"text"},"ldapauth":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"placeholder":{"de":"LDAP UID","en":"LDAP UID"},"type":"text"},"magiclogin":{"rules":["nullable","email"],"columns":{"lg":{"container":4},"sm":{"container":6}},"placeholder":{"de":"Magic Login Email","en":"Magic Login Email"},"type":"text"}}},"email":{"rules":["required","email"],"placeholder":{"de":"Email Adresse","en":"Email address"},"type":"text"},"name":{"rules":["required"],"label":{"de":"Name","en":"Name"},"type":"object","schema":{"givenName":{"rules":["required"],"columns":{"lg":{"container":6},"sm":{"container":6}},"placeholder":{"de":"Vorname","en":"Given name"},"type":"text"},"familyName":{"rules":["required"],"columns":{"lg":{"container":6},"sm":{"container":6}},"placeholder":{"de":"Nachname","en":"Family name"},"type":"text"}}},"access":{"rules":["nullable"],"label":{"de":"Zugriffsrechte","en":"Access"},"type":"object","schema":{"user":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":true,"type":"checkbox","text":{"de":"Home","en":"Home"}},"inWork:expenseReport":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":true,"type":"checkbox","text":{"de":"Auslagenabrechnung initiieren","en":"Initiate Expenses"}},"inWork:healthCareCost":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":true,"type":"checkbox","text":{"de":"Krankenkostenabrechnung initiieren","en":"Initiate Health Care Costs"}},"appliedFor:travel":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":true,"type":"checkbox","text":{"de":"Reisekostenabrechnung beantragen","en":"Apply For Travels"}},"approved:travel":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":false,"type":"checkbox","text":{"de":"Reisekostenabrechnung ohne Genehmigung initiieren","en":"Initiate Travel Expenses Without Approval"}},"approve/travel":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":false,"type":"checkbox","text":{"de":"Reisen genehmigen","en":"Approve Travels"}},"examine/travel":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":false,"type":"checkbox","text":{"de":"Reisen prüfen","en":"Examine Travels"}},"examine/expenseReport":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":false,"type":"checkbox","text":{"de":"Auslagen prüfen","en":"Examine Expenses"}},"examine/healthCareCost":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":false,"type":"checkbox","text":{"de":"Krankenkosten prüfen","en":"Examine Health Care Costs"}},"confirm/healthCareCost":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":false,"type":"checkbox","text":{"de":"Krankenkosten bestätigen","en":"Confirm Health Care Costs"}},"admin":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":false,"type":"checkbox","text":{"de":"Administrator","en":"Administrator"}}}},"loseAccessAt":{"rules":["nullable"],"info":{"de":"Stelle hier ein Datum ein, ab dem der Nutzer keinen Zugriff mehr zu abrechnung🧾 haben soll.","en":"Set a date here from which the user should no longer have access to abrechnung🧾"},"type":"date","time":false,"placeholder":{"de":"Ablaufdatum","en":"Expiration date"}},"settings":{"rules":["required"],"label":{"de":"Einstellungen","en":"Settings"},"type":"object","schema":{"language":{"rules":["nullable"],"default":"de","placeholder":{"de":"Sprache","en":"Language"},"type":"select","items":{"de":{"de":"Deutsch 🇩🇪","en":"German 🇩🇪"},"en":{"de":"Englisch 🇬🇧","en":"English 🇬🇧"}}},"lastCurrencies":{"rules":["min:0"],"type":"currency","extendOptions":{"mode":"multiple"},"placeholder":{"de":"Letzte Währungen","en":"Last currencies"}},"lastCountries":{"rules":["min:0"],"type":"country","extendOptions":{"mode":"multiple"},"placeholder":{"de":"Letzte Länder","en":"Last countries"}},"projects":{"rules":["min:0"],"type":"project","extendOptions":{"mode":"multiple"},"placeholder":{"de":"Projekte","en":"Projects"}},"insurance":{"rules":["nullable"],"type":"healthinsurance","placeholder":{"de":"Versicherung","en":"Health insurance"}},"organisation":{"rules":["nullable"],"type":"organisation","placeholder":{"de":"Organisation","en":"Organisation"}}}},"token":{"rules":["nullable"],"type":"token","placeholder":{"de":"labels.token","en":"labels.token"}}} \ No newline at end of file +{"fk":{"rules":["required"],"label":{"de":"Authentifizierung","en":"Authentication"},"type":"object","schema":{"microsoft":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"placeholder":{"de":"Microsoft ID","en":"Microsoft ID"},"type":"text"},"ldapauth":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"placeholder":{"de":"LDAP UID","en":"LDAP UID"},"type":"text"},"magiclogin":{"rules":["nullable","email"],"columns":{"lg":{"container":4},"sm":{"container":6}},"placeholder":{"de":"Magic Login Email","en":"Magic Login Email"},"type":"text"}}},"email":{"rules":["required","email"],"placeholder":{"de":"Email Adresse","en":"Email address"},"type":"text"},"name":{"rules":["required"],"label":{"de":"Name","en":"Name"},"type":"object","schema":{"givenName":{"rules":["required"],"columns":{"lg":{"container":6},"sm":{"container":6}},"placeholder":{"de":"Vorname","en":"Given name"},"type":"text"},"familyName":{"rules":["required"],"columns":{"lg":{"container":6},"sm":{"container":6}},"placeholder":{"de":"Nachname","en":"Family name"},"type":"text"}}},"access":{"rules":["nullable"],"label":{"de":"Zugriffsrechte","en":"Access"},"type":"object","schema":{"user":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":true,"type":"checkbox","text":{"de":"Home","en":"Home"}},"inWork:expenseReport":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":true,"type":"checkbox","text":{"de":"Auslagenabrechnung initiieren","en":"Initiate Expenses"}},"inWork:healthCareCost":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":true,"type":"checkbox","text":{"de":"Krankenkostenabrechnung initiieren","en":"Initiate Health Care Costs"}},"appliedFor:travel":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":true,"type":"checkbox","text":{"de":"Reisekostenabrechnung beantragen","en":"Apply For Travels"}},"approved:travel":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":false,"type":"checkbox","text":{"de":"Reisekostenabrechnung ohne Genehmigung initiieren","en":"Initiate Travel Expenses Without Approval"}},"approve/travel":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":false,"type":"checkbox","text":{"de":"Reisen genehmigen","en":"Approve Travels"}},"examine/travel":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":false,"type":"checkbox","text":{"de":"Reisen prüfen","en":"Examine Travels"}},"examine/expenseReport":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":false,"type":"checkbox","text":{"de":"Auslagen prüfen","en":"Examine Expenses"}},"examine/healthCareCost":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":false,"type":"checkbox","text":{"de":"Krankenkosten prüfen","en":"Examine Health Care Costs"}},"confirm/healthCareCost":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":false,"type":"checkbox","text":{"de":"Krankenkosten bestätigen","en":"Confirm Health Care Costs"}},"admin":{"rules":["nullable"],"columns":{"lg":{"container":4},"sm":{"container":6}},"default":false,"type":"checkbox","text":{"de":"Administrator","en":"Administrator"}}}},"projects":{"rules":["required"],"label":{"de":"Projekte","en":"Projects"},"type":"object","schema":{"assigned":{"rules":["min:0"],"columns":{"lg":{"container":6},"sm":{"container":6}},"type":"project","extendOptions":{"mode":"multiple"},"placeholder":{"de":"Zugewiesene Projekte","en":"Assigned Projects"}},"supervised":{"rules":["min:0"],"columns":{"lg":{"container":6},"sm":{"container":6}},"type":"project","extendOptions":{"mode":"multiple"},"placeholder":{"de":"Betreute Projekte","en":"Supervised Projects"}}}},"loseAccessAt":{"rules":["nullable"],"info":{"de":"Stelle hier ein Datum ein, ab dem der Nutzer keinen Zugriff mehr zu abrechnung🧾 haben soll.","en":"Set a date here from which the user should no longer have access to abrechnung🧾"},"type":"date","time":false,"placeholder":{"de":"Ablaufdatum","en":"Expiration date"}},"settings":{"rules":["required"],"label":{"de":"Einstellungen","en":"Settings"},"type":"object","schema":{"language":{"rules":["nullable"],"default":"de","placeholder":{"de":"Sprache","en":"Language"},"type":"select","items":{"de":{"de":"Deutsch 🇩🇪","en":"German 🇩🇪"},"en":{"de":"Englisch 🇬🇧","en":"English 🇬🇧"}}},"lastCurrencies":{"rules":["min:0"],"type":"currency","extendOptions":{"mode":"multiple"},"placeholder":{"de":"Letzte Währungen","en":"Last currencies"}},"lastCountries":{"rules":["min:0"],"type":"country","extendOptions":{"mode":"multiple"},"placeholder":{"de":"Letzte Länder","en":"Last countries"}},"insurance":{"rules":["nullable"],"type":"healthinsurance","placeholder":{"de":"Versicherung","en":"Health insurance"}},"organisation":{"rules":["nullable"],"type":"organisation","placeholder":{"de":"Organisation","en":"Organisation"}}}},"token":{"rules":["nullable"],"type":"token","placeholder":{"de":"labels.token","en":"labels.token"}}} \ No newline at end of file diff --git a/common/locales/de.json b/common/locales/de.json index baa7620..fe29eb1 100755 --- a/common/locales/de.json +++ b/common/locales/de.json @@ -100,6 +100,8 @@ "vehicleRegistration": "Lade hier den Fahrzeugschein deines Autos hoch." }, "labels": { + "assignedProjects": "Zugewiesene Projekte", + "supervisedProjects": "Betreute Projekte", "access": "Zugriffsrechte", "accessIcons": "Icons für Zugriffsrechte", "add": "Hinzufügen", diff --git a/common/locales/en.json b/common/locales/en.json index fa58335..0e55f56 100755 --- a/common/locales/en.json +++ b/common/locales/en.json @@ -100,6 +100,8 @@ "vehicleRegistration": "Upload the vehicle registration of your car here." }, "labels": { + "assignedProjects": "Assigned Projects", + "supervisedProjects": "Supervised Projects", "access": "Access", "accessIcons": "Icons for access rights", "add": "Add", diff --git a/common/types.ts b/common/types.ts index 33d2b3b..a71221c 100644 --- a/common/types.ts +++ b/common/types.ts @@ -166,12 +166,15 @@ export interface User extends UserSimple { access: { [key in Access]: boolean } + projects: { + assigned: Project[] + supervised: _id[] + } loseAccessAt?: null | Date | string settings: { language: Locale lastCurrencies: Currency[] lastCountries: CountrySimple[] - projects: Project[] insurance?: HealthInsurance | null organisation?: OrganisationSimple | null } diff --git a/frontend/src/components/elements/ProjectSelector.vue b/frontend/src/components/elements/ProjectSelector.vue index 769aa67..a483f44 100644 --- a/frontend/src/components/elements/ProjectSelector.vue +++ b/frontend/src/components/elements/ProjectSelector.vue @@ -65,7 +65,7 @@ export default defineComponent({ }, getProjects(orgaId?: string) { const projects: ProjectSimple[] = [] - for (const project of this.$root.user.settings.projects) { + for (const project of this.$root.user.projects.assigned) { if (!orgaId || project.organisation === orgaId) { projects.push(project) } @@ -73,7 +73,7 @@ export default defineComponent({ for (const project of this.$root.projects) { let alreadyIn = false - for (const userProject of this.$root.user.settings.projects) { + for (const userProject of this.$root.user.projects.assigned) { if (project._id === userProject._id) { alreadyIn = true break diff --git a/frontend/src/components/settings/SettingsPage.vue b/frontend/src/components/settings/SettingsPage.vue index 56d51c8..7b05f7f 100644 --- a/frontend/src/components/settings/SettingsPage.vue +++ b/frontend/src/components/settings/SettingsPage.vue @@ -26,7 +26,7 @@ class="mb-5" endpoint="admin/user/bulk" :transformers="[ - { path: 'settings.projects', key: 'identifier', array: $root.projects }, + { path: 'projects.assigned', key: 'identifier', array: $root.projects }, { path: 'settings.organisation', key: 'name', array: $root.organisations }, {path: 'loseAccessAt', fn: (val:string|undefined) => { if(val){ @@ -44,7 +44,7 @@ 'email', 'fk.magiclogin', 'loseAccessAt', - 'settings.projects', + 'projects.assigned', 'settings.organisation' ]" @imported=";($refs.userList as any).getUsers()" /> diff --git a/frontend/src/components/settings/elements/UserList.vue b/frontend/src/components/settings/elements/UserList.vue index c8bed78..aa55b42 100644 --- a/frontend/src/components/settings/elements/UserList.vue +++ b/frontend/src/components/settings/elements/UserList.vue @@ -22,7 +22,7 @@ :headers="[ { text: $t('labels.name'), value: 'name' }, { text: 'E-Mail', value: 'email' }, - { text: $t('labels.projects'), value: 'settings.projects', sortable: true }, + { text: $t('labels.projects'), value: 'projects.assigned', sortable: true }, { text: $t('labels.access'), value: 'access' }, { value: 'buttons' } ]"> @@ -53,8 +53,8 @@ -