## About the changes
This admin token user will help us differentiate actions performed by
the system from actions performed with an admin token.
Events created with an admin token should have the id of this user as
createdByUserId property and the username of the token used as the
createdBy property. i.e.
```json
{
"id": 11,
"type": "pat-created",
"createdBy": "admin-token",
"createdAt": "2024-01-16T13:16:27.887Z",
"createdByUserId": -42,
"data": {
"description": "admin-pat",
"expiresAt": "2024-02-15T13:16:25.586Z",
"secret": "***",
"userId": 1
},
"preData": null,
"tags": [],
"featureName": null,
"project": null,
"environment": null
}
```
This improves the role resolution in the value of the default root role,
preventing a bug where settings saved
pre-https://github.com/Unleash/unleash/pull/5887 would show an empty
default root role in the dropdown.
Also makes the role update more robust.
This PR adds uuids as ids using a symbol in order to make sure we only
use this to keep internal order in the viritual DOM. This makes us able
to have predictable mutable lists on the frontend, and makes it easy to
not pass this property along to the backend.
## About the changes
EventsService is a dependency in most of our services. This creates
helper methods to create them easily and replace a few places where
we're creating them manually
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
|
[actions/upload-artifact](https://togithub.com/actions/upload-artifact)
| action | major | `v3` -> `v4` |
---
### Release Notes
<details>
<summary>actions/upload-artifact (actions/upload-artifact)</summary>
### [`v4`](https://togithub.com/actions/upload-artifact/compare/v3...v4)
[Compare
Source](https://togithub.com/actions/upload-artifact/compare/v3...v4)
</details>
---
### Configuration
📅 **Schedule**: Branch creation - "after 7pm every weekday,before 5am
every weekday" in timezone Europe/Madrid, Automerge - At any time (no
schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/Unleash/unleash).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4xMjcuMCIsInVwZGF0ZWRJblZlciI6IjM3LjEyNy4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This change removes the system user's email from the definition, instead
setting it to `null`. It also changes the name to "Unleash System".
The IUser interface doesn't allow `null` email addresses, so we change
the type definition of the system user to get around it. However, using
`null` (instead of just removing the property entirely) is useful
because when you get the system user from the DB, it's email value will
be null (after it has been nulled out).
As of today, there is nowhere in the Unleash system (OSS or Enterprise)
where we use the system user as an IUser (we only use username and ID).
So this change shouldn't break anything.
This should follow https://github.com/Unleash/unleash/pull/5849.
Updates it from 'system@getunleash.io' to `null`. We don't have that
address registered (and probably don't want it), so we'll leave it
empty.
This is a companion PR to
https://github.com/Unleash/unleash/pull/5893. With both of those
merged, the system user in the DB should match the one defined in
`core.ts`
This seems to improve the performance in the role form while still
maintaining the same validation logic.
A big factor was the memoization of the categories calculation and
respective elements, which is especially impactful when there are many
environments.
This PR adds undo functionality so you can restore the state of your
constraint if you make a mistake. We also amend the autosave
functionality to only apply when values are changed and you have a valid
value. See demo:
https://www.loom.com/share/da704da8aee94ac18d4caae697426802
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)
This PR contains the following updates:
| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [react-router](https://togithub.com/remix-run/react-router)
([source](https://togithub.com/remix-run/react-router/tree/HEAD/packages/react-router))
| [`6.20.1` ->
`6.21.1`](https://renovatebot.com/diffs/npm/react-router/6.20.1/6.21.1)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/react-router/6.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-router/6.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-router/6.20.1/6.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-router/6.20.1/6.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [react-router-dom](https://togithub.com/remix-run/react-router)
([source](https://togithub.com/remix-run/react-router/tree/HEAD/packages/react-router-dom))
| [`6.20.1` ->
`6.21.1`](https://renovatebot.com/diffs/npm/react-router-dom/6.20.1/6.21.1)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/react-router-dom/6.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-router-dom/6.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-router-dom/6.20.1/6.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-router-dom/6.20.1/6.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
---
### Release Notes
<details>
<summary>remix-run/react-router (react-router)</summary>
###
[`v6.21.1`](https://togithub.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#6211)
[Compare
Source](https://togithub.com/remix-run/react-router/compare/react-router@6.21.0...react-router@6.21.1)
##### Patch Changes
- Fix bug with `route.lazy` not working correctly on initial SPA load
when `v7_partialHydration` is specified
([#​11121](https://togithub.com/remix-run/react-router/pull/11121))
- Updated dependencies:
- `@remix-run/router@1.14.1`
###
[`v6.21.0`](https://togithub.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#6210)
[Compare
Source](https://togithub.com/remix-run/react-router/compare/react-router@6.20.1...react-router@6.21.0)
##### Minor Changes
- Add a new `future.v7_relativeSplatPath` flag to implement a breaking
bug fix to relative routing when inside a splat route.
([#​11087](https://togithub.com/remix-run/react-router/pull/11087))
This fix was originally added in
[#​10983](https://togithub.com/remix-run/react-router/issues/10983)
and was later reverted in
[#​11078](https://togithub.com/remix-run/react-router/pull/11078)
because it was determined that a large number of existing applications
were relying on the buggy behavior (see
[#​11052](https://togithub.com/remix-run/react-router/issues/11052))
**The Bug**
The buggy behavior is that without this flag, the default behavior when
resolving relative paths is to *ignore* any splat (`*`) portion of the
current route path.
**The Background**
This decision was originally made thinking that it would make the
concept of nested different sections of your apps in `<Routes>` easier
if relative routing would *replace* the current splat:
```jsx
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="dashboard/*" element={<Dashboard />} />
</Routes>
</BrowserRouter>
```
Any paths like `/dashboard`, `/dashboard/team`, `/dashboard/projects`
will match the `Dashboard` route. The dashboard component itself can
then render nested `<Routes>`:
```jsx
function Dashboard() {
return (
<div>
<h2>Dashboard</h2>
<nav>
<Link to="/">Dashboard Home</Link>
<Link to="team">Team</Link>
<Link to="projects">Projects</Link>
</nav>
<Routes>
<Route path="/" element={<DashboardHome />} />
<Route path="team" element={<DashboardTeam />} />
<Route path="projects" element={<DashboardProjects />} />
</Routes>
</div>
);
}
```
Now, all links and route paths are relative to the router above them.
This makes code splitting and compartmentalizing your app really easy.
You could render the `Dashboard` as its own independent app, or embed it
into your large app without making any changes to it.
**The Problem**
The problem is that this concept of ignoring part of a path breaks a lot
of other assumptions in React Router - namely that `"."` always means
the current location pathname for that route. When we ignore the splat
portion, we start getting invalid paths when using `"."`:
```jsx
// If we are on URL /dashboard/team, and we want to link to
/dashboard/team:
function DashboardTeam() {
// ❌ This is broken and results in <a href="/dashboard">
return <Link to=".">A broken link to the Current URL</Link>;
// ✅ This is fixed but super unintuitive since we're already at
/dashboard/team!
return <Link to="./team">A broken link to the Current URL</Link>;
}
```
We've also introduced an issue that we can no longer move our
`DashboardTeam` component around our route hierarchy easily - since it
behaves differently if we're underneath a non-splat route, such as
`/dashboard/:widget`. Now, our `"."` links will, properly point to
ourself *inclusive of the dynamic param value* so behavior will break
from it's corresponding usage in a `/dashboard/*` route.
Even worse, consider a nested splat route configuration:
```jsx
<BrowserRouter>
<Routes>
<Route path="dashboard">
<Route path="*" element={<Dashboard />} />
</Route>
</Routes>
</BrowserRouter>
```
Now, a `<Link to=".">` and a `<Link to="..">` inside the `Dashboard`
component go to the same place! That is definitely not correct!
Another common issue arose in Data Routers (and Remix) where any
`<Form>` should post to it's own route `action` if you the user doesn't
specify a form action:
```jsx
let router = createBrowserRouter({
path: "/dashboard",
children: [
{
path: "*",
action: dashboardAction,
Component() {
// ❌ This form is broken! It throws a 405 error when it submits because
// it tries to submit to /dashboard (without the splat value) and the
parent
// `/dashboard` route doesn't have an action
return <Form method="post">...</Form>;
},
},
],
});
```
This is just a compounded issue from the above because the default
location for a `Form` to submit to is itself (`"."`) - and if we ignore
the splat portion, that now resolves to the parent route.
**The Solution**
If you are leveraging this behavior, it's recommended to enable the
future flag, move your splat to it's own route, and leverage `../` for
any links to "sibling" pages:
```jsx
<BrowserRouter>
<Routes>
<Route path="dashboard">
<Route index path="*" element={<Dashboard />} />
</Route>
</Routes>
</BrowserRouter>
function Dashboard() {
return (
<div>
<h2>Dashboard</h2>
<nav>
<Link to="..">Dashboard Home</Link>
<Link to="../team">Team</Link>
<Link to="../projects">Projects</Link>
</nav>
<Routes>
<Route path="/" element={<DashboardHome />} />
<Route path="team" element={<DashboardTeam />} />
<Route path="projects" element={<DashboardProjects />} />
</Router>
</div>
);
}
```
This way, `.` means "the full current pathname for my route" in all
cases (including static, dynamic, and splat routes) and `..` always
means "my parents pathname".
##### Patch Changes
- Properly handle falsy error values in ErrorBoundary's
([#​11071](https://togithub.com/remix-run/react-router/pull/11071))
- Updated dependencies:
- `@remix-run/router@1.14.0`
</details>
<details>
<summary>remix-run/react-router (react-router-dom)</summary>
###
[`v6.21.1`](https://togithub.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#6211)
[Compare
Source](https://togithub.com/remix-run/react-router/compare/react-router-dom@6.21.0...react-router-dom@6.21.1)
##### Patch Changes
- Updated dependencies:
- `react-router@6.21.1`
- `@remix-run/router@1.14.1`
###
[`v6.21.0`](https://togithub.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#6210)
[Compare
Source](https://togithub.com/remix-run/react-router/compare/react-router-dom@6.20.1...react-router-dom@6.21.0)
##### Minor Changes
- Add a new `future.v7_relativeSplatPath` flag to implement a breaking
bug fix to relative routing when inside a splat route.
([#​11087](https://togithub.com/remix-run/react-router/pull/11087))
This fix was originally added in
[#​10983](https://togithub.com/remix-run/react-router/issues/10983)
and was later reverted in
[#​11078](https://togithub.com/remix-run/react-router/pull/11078)
because it was determined that a large number of existing applications
were relying on the buggy behavior (see
[#​11052](https://togithub.com/remix-run/react-router/issues/11052))
**The Bug**
The buggy behavior is that without this flag, the default behavior when
resolving relative paths is to *ignore* any splat (`*`) portion of the
current route path.
**The Background**
This decision was originally made thinking that it would make the
concept of nested different sections of your apps in `<Routes>` easier
if relative routing would *replace* the current splat:
```jsx
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="dashboard/*" element={<Dashboard />} />
</Routes>
</BrowserRouter>
```
Any paths like `/dashboard`, `/dashboard/team`, `/dashboard/projects`
will match the `Dashboard` route. The dashboard component itself can
then render nested `<Routes>`:
```jsx
function Dashboard() {
return (
<div>
<h2>Dashboard</h2>
<nav>
<Link to="/">Dashboard Home</Link>
<Link to="team">Team</Link>
<Link to="projects">Projects</Link>
</nav>
<Routes>
<Route path="/" element={<DashboardHome />} />
<Route path="team" element={<DashboardTeam />} />
<Route path="projects" element={<DashboardProjects />} />
</Routes>
</div>
);
}
```
Now, all links and route paths are relative to the router above them.
This makes code splitting and compartmentalizing your app really easy.
You could render the `Dashboard` as its own independent app, or embed it
into your large app without making any changes to it.
**The Problem**
The problem is that this concept of ignoring part of a path breaks a lot
of other assumptions in React Router - namely that `"."` always means
the current location pathname for that route. When we ignore the splat
portion, we start getting invalid paths when using `"."`:
```jsx
// If we are on URL /dashboard/team, and we want to link to
/dashboard/team:
function DashboardTeam() {
// ❌ This is broken and results in <a href="/dashboard">
return <Link to=".">A broken link to the Current URL</Link>;
// ✅ This is fixed but super unintuitive since we're already at
/dashboard/team!
return <Link to="./team">A broken link to the Current URL</Link>;
}
```
We've also introduced an issue that we can no longer move our
`DashboardTeam` component around our route hierarchy easily - since it
behaves differently if we're underneath a non-splat route, such as
`/dashboard/:widget`. Now, our `"."` links will, properly point to
ourself *inclusive of the dynamic param value* so behavior will break
from it's corresponding usage in a `/dashboard/*` route.
Even worse, consider a nested splat route configuration:
```jsx
<BrowserRouter>
<Routes>
<Route path="dashboard">
<Route path="*" element={<Dashboard />} />
</Route>
</Routes>
</BrowserRouter>
```
Now, a `<Link to=".">` and a `<Link to="..">` inside the `Dashboard`
component go to the same place! That is definitely not correct!
Another common issue arose in Data Routers (and Remix) where any
`<Form>` should post to it's own route `action` if you the user doesn't
specify a form action:
```jsx
let router = createBrowserRouter({
path: "/dashboard",
children: [
{
path: "*",
action: dashboardAction,
Component() {
// ❌ This form is broken! It throws a 405 error when it submits because
// it tries to submit to /dashboard (without the splat value) and the
parent
// `/dashboard` route doesn't have an action
return <Form method="post">...</Form>;
},
},
],
});
```
This is just a compounded issue from the above because the default
location for a `Form` to submit to is itself (`"."`) - and if we ignore
the splat portion, that now resolves to the parent route.
**The Solution**
If you are leveraging this behavior, it's recommended to enable the
future flag, move your splat to it's own route, and leverage `../` for
any links to "sibling" pages:
```jsx
<BrowserRouter>
<Routes>
<Route path="dashboard">
<Route index path="*" element={<Dashboard />} />
</Route>
</Routes>
</BrowserRouter>
function Dashboard() {
return (
<div>
<h2>Dashboard</h2>
<nav>
<Link to="..">Dashboard Home</Link>
<Link to="../team">Team</Link>
<Link to="../projects">Projects</Link>
</nav>
<Routes>
<Route path="/" element={<DashboardHome />} />
<Route path="team" element={<DashboardTeam />} />
<Route path="projects" element={<DashboardProjects />} />
</Router>
</div>
);
}
```
This way, `.` means "the full current pathname for my route" in all
cases (including static, dynamic, and splat routes) and `..` always
means "my parents pathname".
##### Patch Changes
- Updated dependencies:
- `@remix-run/router@1.14.0`
- `react-router@6.21.0`
</details>
---
### Configuration
📅 **Schedule**: Branch creation - "after 7pm every weekday,before 5am
every weekday" in timezone Europe/Madrid, Automerge - At any time (no
schedule defined).
🚦 **Automerge**: Enabled.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/Unleash/unleash).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4xMjcuMCIsInVwZGF0ZWRJblZlciI6IjM3LjEyNy4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Lots of work here, mostly because I didn't want to turn off the
`noImplicitAnyLet` lint. This PR tries its best to type all the untyped
lets biome complained about (Don't ask me how many hours that took or
how many lints that was >200...), which in the future will force test
authors to actually type their global variables setup in `beforeAll`.
---------
Co-authored-by: Gastón Fournier <gaston@getunleash.io>
This PR describes in closer detail what happens when the user who
scheduled a change request is deleted. It mentions the new suspended
state and what the user can do to get out of it.
This changes the two interfaces IChangeRequest and
IChangeRequestSchedule to be union types instead of interfaces. It also
extracts the constituents of those union types into proper types
themselves (so that they can be used in function type signatures etc).
It also updates the type names.
This turned out to be more work than I had imagined, but I think the end
result pays off, giving us more type safety and control.
I wanted to use just `ChangeRequest` for the IChangeRequest type, but
that caused issues due to naming collisions with the `ChangeRequest`
component that we have, causing tests to fail. I've named it
`ChangeRequestType` as a potential solution, but suggestions are
welcome.
The relevant changes are in
`frontend/src/component/changeRequest/changeRequest.types.ts`.
Everything else is updated references and some necessary refactoring to
respect the new types.