Fix calendar event visibility (#8510)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2025-04-10 09:46:02 +05:00 committed by GitHub
parent 4cae118f5c
commit afcd637ed2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 55 additions and 14 deletions

View File

@ -28,6 +28,7 @@ import { type Contact } from '@hcengineering/contact'
import {
DateRangeMode,
IndexKind,
type Account,
type SystemSpace,
type Domain,
type Markup,
@ -135,6 +136,8 @@ export class TEvent extends TAttachedDoc implements Event {
visibility?: Visibility
timeZone?: string
user!: Ref<Account>
}
@Model(calendar.class.ReccuringEvent, calendar.class.Event)

View File

@ -14,7 +14,7 @@
//
import { type Calendar, calendarId, type Event, type ReccuringEvent } from '@hcengineering/calendar'
import { groupByArray, type Ref, type Space } from '@hcengineering/core'
import core, { groupByArray, toIdMap, type Ref, type Space } from '@hcengineering/core'
import {
createDefaultSpace,
tryMigrate,
@ -122,6 +122,24 @@ async function removeEventDuplicates (client: MigrationClient): Promise<void> {
}
}
async function fillUser (client: MigrationClient): Promise<void> {
const calendars = await client.find<Calendar>(DOMAIN_CALENDAR, {})
const events = await client.find<Event>(DOMAIN_EVENT, {
user: { $exists: false }
})
const map = toIdMap(calendars)
for (const event of events) {
const calendar = map.get(event.calendar)
if (calendar !== undefined) {
await client.update(
DOMAIN_CALENDAR,
{ _id: calendar._id },
{ user: event.createdBy !== core.account.System ? event.createdBy : calendar.createdBy }
)
}
}
}
async function migrateTimezone (client: MigrationClient): Promise<void> {
await client.update(
DOMAIN_CALENDAR,
@ -171,6 +189,11 @@ export const calendarOperation: MigrateOperation = {
state: 'remove-duplicates',
mode: 'upgrade',
func: removeEventDuplicates
},
{
state: 'fill-user',
mode: 'upgrade',
func: fillUser
}
])
},

View File

@ -264,6 +264,7 @@
modifiedOn: Date.now(),
date: e.detail.date.getTime(),
space: calendar.space.Calendar,
user: me._id,
dueDate: new Date(e.detail.date).setMinutes(new Date(e.detail.date).getMinutes() + 30)
}
raw.push(temp)

View File

@ -102,6 +102,7 @@
if (startDate != null) date = startDate
if (date === undefined) return
if (title === '') return
const user = me._id
const _id = generateId<Event>()
if (rules.length > 0) {
await client.addCollection(
@ -128,7 +129,8 @@
allDay,
access: 'owner',
originalStartTime: allDay ? saveUTC(date) : date,
timeZone
timeZone,
user
},
_id as Ref<ReccuringEvent>
)
@ -153,7 +155,8 @@
location,
allDay,
timeZone,
access: 'owner'
access: 'owner',
user
},
_id
)

View File

@ -55,7 +55,8 @@
title: _title,
allDay: false,
reminders: [0],
access: 'owner'
access: 'owner',
user: getCurrentAccount()._id
})
}
</script>

View File

@ -104,7 +104,8 @@ async function deleteRecHandler (res: any, object: ReccuringInstance): Promise<v
exdate: object.exdate,
visibility: object.visibility,
access: object.access,
timeZone: object.timeZone
timeZone: object.timeZone,
user: object.user
},
object._id
)

View File

@ -29,7 +29,7 @@ export function hidePrivateEvents (events: Event[], calendars: IdMap<Calendar>,
const me = getCurrentAccount()._id
const res: Event[] = []
for (const event of events) {
if ((event.createdBy ?? event.modifiedBy) === me && allowMe) {
if (event.user === me && allowMe) {
res.push(event)
} else {
if (event.visibility !== undefined) {
@ -49,14 +49,14 @@ export function hidePrivateEvents (events: Event[], calendars: IdMap<Calendar>,
export function isReadOnly (value: Event): boolean {
const me = getCurrentAccount()._id
if (value.createdBy !== me) return true
if (value.user !== me) return true
if (['owner', 'writer'].includes(value.access)) return false
return true
}
export function isVisible (value: Event, calendars: IdMap<Calendar>): boolean {
const me = getCurrentAccount()._id
if (value.createdBy === me) return true
if (value.user === me) return true
if (value.visibility === 'freeBusy') {
return false
} else if (value.visibility === 'public') {
@ -158,6 +158,7 @@ export async function updateReccuringInstance (
exdate: object.exdate,
rdate: object.rdate,
timeZone: object.timeZone,
user: object.user,
...ops
},
object._id

View File

@ -12,7 +12,7 @@
// limitations under the License.
import { Contact } from '@hcengineering/contact'
import type { AttachedDoc, Class, Doc, Markup, Mixin, Ref, SystemSpace, Timestamp } from '@hcengineering/core'
import type { Account, AttachedDoc, Class, Doc, Markup, Mixin, Ref, SystemSpace, Timestamp } from '@hcengineering/core'
import { NotificationType } from '@hcengineering/notification'
import type { Asset, IntlString, Metadata, Plugin } from '@hcengineering/platform'
import { plugin } from '@hcengineering/platform'
@ -108,6 +108,8 @@ export interface Event extends AttachedDoc {
access: 'freeBusyReader' | 'reader' | 'writer' | 'owner'
timeZone?: string
user: Ref<Account>
}
/**

View File

@ -98,7 +98,8 @@
allDay: false,
access: 'owner',
visibility: todo.visibility === 'public' ? 'public' : 'freeBusy',
reminders: []
reminders: [],
user: acc._id
})
Analytics.handleEvent(TimeEvents.ToDoScheduled, { id })
}
@ -153,7 +154,8 @@
attachedToClass: time.class.ToDo,
collection: 'workslots',
modifiedOn: Date.now(),
modifiedBy: acc._id
modifiedBy: acc._id,
user: acc._id
})
slots = slots
}

View File

@ -67,7 +67,8 @@
allDay: false,
access: 'owner',
visibility: doc.visibility === 'public' ? 'public' : 'freeBusy',
reminders: []
reminders: [],
user: currentUser._id
})
Analytics.handleEvent(TimeEvents.ToDoScheduled, { id: doc._id })
}

View File

@ -133,7 +133,8 @@
participants: [me.person],
modifiedOn: Date.now(),
date: e.detail.date.getTime(),
dueDate: new Date(e.detail.date).setMinutes(new Date(e.detail.date).getMinutes() + 30)
dueDate: new Date(e.detail.date).setMinutes(new Date(e.detail.date).getMinutes() + 30),
user: me._id
}
raw.push(ev)
}

View File

@ -73,6 +73,7 @@
title: todo.title,
allDay: false,
access: 'owner',
user: currentUser._id,
visibility: todo.visibility === 'public' ? 'public' : 'freeBusy',
reminders: []
})

View File

@ -721,7 +721,8 @@ export class CalendarClient {
eventId: event.id ?? '',
calendar: _calendar,
access: this.getAccess(event, accessRole),
timeZone: event.start?.timeZone ?? event.end?.timeZone ?? 'Etc/GMT'
timeZone: event.start?.timeZone ?? event.end?.timeZone ?? 'Etc/GMT',
user: this.user.userId
}
if (participants[1].length > 0) {
res.externalParticipants = participants[1]