Skip to content

Commit 323bc71

Browse files
authored
Merge pull request #35 from nextcloud/feat/noid/exclude-guests-and-timeline-fixes
Feat/noid/exclude guests and timeline fixes
2 parents 58596a3 + 6e56ee4 commit 323bc71

28 files changed

Lines changed: 596 additions & 89 deletions

SPECIFICATION.md

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ There are four effective roles. A single user may hold several simultaneously
5151

5252
| Role | How assigned | Capabilities |
5353
|------|-------------|--------------|
54-
| **Employee** | Every logged-in user | Create/edit/cancel own requests, view own balance, view own history, see team who's-off calendar. |
54+
| **Employee** | Every logged-in user **except guest accounts** (§2.2) | Create/edit/cancel own requests, view own balance, view own history, see team who's-off calendar. |
5555
| **Line manager** | Derived from the LDAP `manager` attribute (see §2.1) — a user is a manager of everyone whose `manager` attribute points to them | Approve/reject/comment on direct reports' requests, view direct reports' calendars and balances, receive coverage-conflict warnings. |
5656
| **HR** | Membership of a configurable Nextcloud group (default group id `hr`, set in admin settings) | Company-wide overview, statistics, exports, manage entitlements, manage public-holiday calendar, override any decision, act on escalated requests, edit/adjust any request and balance. |
5757
| **App admin** | Nextcloud server admins | Configure app settings (§11): HR group, leave types, escalation window, default entitlements, CalDAV target. |
@@ -72,6 +72,41 @@ There are four effective roles. A single user may hold several simultaneously
7272
- **No manager found:** the request is created with `manager_uid = NULL` and is
7373
routed directly to HR (treated as immediately escalated — see §5.4).
7474

75+
### 2.2 Who counts as an employee (guest accounts)
76+
77+
Not every account on an instance is a member of staff. **Guest accounts — users
78+
created by the [Guests app](https://github.com/nextcloud/guests) — are external
79+
people invited to collaborate on files. They have no entitlement and take no
80+
leave, so the app does not treat them as employees.**
81+
82+
Without this rule every guest would sit in the balances report and the who's-off
83+
calendar forever, with an empty allowance and nothing to show.
84+
85+
- **One definition, one place.** `EmployeeDirectory` is the only component that
86+
enumerates users; `ReportService`, `EntitlementService`, `CoverageService` and
87+
`ManagerResolver` all ask it rather than walking `IUserManager` themselves. A
88+
rule stated in four copies is a rule that holds in three.
89+
- **Detection.** A guest is a user in the Guests app's own user backend, i.e.
90+
`IUser::getBackendClassName() === 'Guests'` — the same thing
91+
`OCA\Guests\GuestManager::isGuest()` checks. Read this way the app needs **no
92+
dependency on the Guests app**: where it is absent or disabled, no account has
93+
that backend and the rule is simply never true.
94+
- **Consequences.** Guests do not appear in balances, statistics, the sick-leave
95+
overview, exports, the who's-off calendar, the HR absence list or any people
96+
picker; they are nobody's direct report or peer, and cannot be resolved as a
97+
line manager (a request routed to one could never be approved).
98+
- **Enforced, not just hidden.** The API rejects creating leave for a guest —
99+
including by HR, who may otherwise record for anyone — nominating a guest as a
100+
replacement, and setting a guest's entitlement. Filtering only the UI would
101+
leave the rule one crafted request away from being bypassed.
102+
- **Pickers.** The people pickers call the app's own
103+
`GET /api/employees/search` rather than core's autocomplete, because only the
104+
server can tell a guest from a colleague. That endpoint wraps the same
105+
collaborator search, so the admin's user-enumeration settings still apply
106+
exactly as elsewhere; guests are removed from what it returns.
107+
- Existing records for someone who later becomes a guest are left untouched in
108+
the database — they simply stop being listed.
109+
75110
---
76111

77112
## 3. Core Concepts & Data Model
@@ -738,6 +773,10 @@ NcContent(app-name="absence")
738773
type, status and year, paged with a "Load more" button. Rows are the same
739774
`RequestListItem` as elsewhere and open the detail sidebar, whose **Edit** and
740775
**Cancel** controls are what let HR correct a wrong vacation or sick day (§5.6).
776+
People are named, never printed as user ids: requests are serialized with an
777+
`employeeName` (display name, falling back to the uid for a deleted account),
778+
and the sidebar names the employee under its title whenever the leave is not
779+
the viewer's own.
741780
Accepts `?employee=&employeeName=&type=&status=&year=` so other views can deep-link
742781
into it — the *Sick leave* overview does, from each employee row.
743782
- **HR** (HR group only): *Balances* (searchable/sortable data table →

appinfo/routes.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
['name' => 'request#reject', 'url' => '/api/requests/{id}/reject', 'verb' => 'POST'],
2222
['name' => 'request#addComment', 'url' => '/api/requests/{id}/comments', 'verb' => 'POST'],
2323

24+
// People (autocomplete for the employee / replacement pickers)
25+
['name' => 'employee#search', 'url' => '/api/employees/search', 'verb' => 'GET'],
26+
2427
// Balances & entitlements
2528
['name' => 'balance#mine', 'url' => '/api/balance', 'verb' => 'GET'],
2629
['name' => 'balance#forEmployee', 'url' => '/api/employees/{uid}/balance', 'verb' => 'GET'],

js/NcCheckboxRadioSwitch-DVdt5Hkq-Dfqo0Dmj.chunk.mjs renamed to js/NcCheckboxRadioSwitch-DVdt5Hkq-anWxu1ok.chunk.mjs

Lines changed: 14 additions & 14 deletions
Large diffs are not rendered by default.

js/NcCheckboxRadioSwitch-DVdt5Hkq-Dfqo0Dmj.chunk.mjs.license renamed to js/NcCheckboxRadioSwitch-DVdt5Hkq-anWxu1ok.chunk.mjs.license

File renamed without changes.

js/NcCheckboxRadioSwitch-DVdt5Hkq-Dfqo0Dmj.chunk.mjs.map renamed to js/NcCheckboxRadioSwitch-DVdt5Hkq-anWxu1ok.chunk.mjs.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/absence-main.mjs

Lines changed: 7 additions & 7 deletions
Large diffs are not rendered by default.

js/absence-main.mjs.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/absence-personal-settings.mjs

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.
Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)