877 Commits

Author SHA1 Message Date
Jamil
05dafabbad fix(portal): Fix human display of geo location (#8665)
These seem to be swapped. Generally accepted is `city, country`.
2025-04-09 01:28:35 +00:00
Jamil
8ca43300cd chore(portal): Fix typo: counties -> countries (#8666) 2025-04-05 08:11:05 +00:00
dependabot[bot]
a66423c25c build(deps): bump @fontsource/source-sans-3 from 5.1.1 to 5.2.6 in /elixir/apps/web/assets (#8599)
Bumps
[@fontsource/source-sans-3](https://github.com/fontsource/font-files/tree/HEAD/fonts/google/source-sans-3)
from 5.1.1 to 5.2.6.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/fontsource/font-files/commits/HEAD/fonts/google/source-sans-3">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@fontsource/source-sans-3&package-manager=npm_and_yarn&previous-version=5.1.1&new-version=5.2.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 02:50:46 +00:00
Jamil
6e336fc3bc fix(portal): Update flows fkey constraints to cascade deletes (#8645)
The `flows` table currently has `ON DELETE SET NULL` behavior for many
of its foreign key constraints. The problem is that if we try to delete
any of the associated entities, setting a null here causes the DB
operation to fail with:

```
ERROR:  null value in column "policy_id" of relation "flows" violates not-null constraint
```

I can understand why it was originally architected like this to preserve
connection log data, but we'll be using another approach for that that
doesn't require maintaining relational data in perpetuity.

Related: #949
2025-04-03 16:29:19 -07:00
Jamil
fb9f132a49 fix(portal): Interpret missing members as empty list (#8640)
The Google API will often return a missing `members` key alongside a
`200` response from their members API. The documentation here isn't
clear whether this key is expected or not, but since the sync has been
working fine up until #8608, we can only surmise that the missing key in
fact means the group has no members.

This PR updates the Google API client so that a `default_if_missing` can
be passed in which is returned if the API response is missing the JSON
key to fetch.

For the users, groups, and organization units fetches, we consider a
missing key to be an error and we return `{:error, :invalid_response}`
since this most likely indicates an API problem.

For the members endpoint, we consider the missing key to be the empty
set.

Additionally, a bug is fixed that was introduced in #8608 whereupon we
returned `{:error, :retry_later}` for newly-accounted-for API responses,
which would have caused a "sync failed" email to be sent to the admins
on the instance.

Instead, we want to return `{:error, :invalid_response}` which will stop
the sync from progressing, and log it internally.
2025-04-03 11:27:39 -07:00
Jamil
2f7598c648 fix(portal): Delete soft-deleted synced actor_groups (#8638)
The previous migration only accounted for soft-deleted rows that have an
active counterpart.

This fails the new unique index if multiple soft-deleted rows exist for
the same `account_id, provider_id, provider_identifier` combination.

Instead, to appease the new index, we need to delete all soft-deleted
rows where these fields exist.

Related: #8615
2025-04-03 07:21:06 -07:00
Jamil
713ff1e7de chore(portal): Log problematic identity api responses (#8623)
After merging #8608, we discovered that we receive unexpected API
responses on the regular. This adds improved logging to uncover what
exactly these unexpected API responses are.
2025-04-02 14:59:16 -07:00
Jamil
f275bf70d9 fix(portal): Resurrect deleted identities and groups (#8615)
When syncing identities from an identity, we have logic in place that
resurrects any soft-deleted identities in order to maintain their
session history, group memberships and any other relevant data. Users
can be temporarily suspended from their identity provider and then
resumed.

Groups, however, based on cursory research, can never be temporarily
suspended at the identity provider. However, this doesn't mean that we
can't see the group disappear and reappear at a later point in time.
This can happen due to a temporary sync issue, or in the upcoming Group
Filters PR: #8381.

This PR adds more robust testing to ensure we can in fact resurrect
identities as expected.

It also updates the group sync logic to similarly resurrect soft-deleted
groups if they are seen again in a subsequent sync.

To achieve this, we need to update the `UNIQUE CONSTRAINT` used in the
upsert clause during the sync. Before, it was possible for two (or more)
groups to exist with the same provider_identifier and provider_id, if
`deleted_at IS NOT NULL`. Now, we need to ensure that only one group
with the same `account_id, provider_id, provider_identifier` can exist,
since we want to resurrect and not recreate these.

To do this, we use a migration that does the following:

1. Ensures any potentially problematic data is permanently deleted
2. Drops the existing unique constraint
3. Recreates it, omitting `WHERE DELETED_AT IS NULL` from the partial
index.

Based on exploring the production DB data, this should not cause any
issues, but it would be a good idea to double-check before rolling this
out to prod.


Lastly, the final missing piece to the resurrection story is Policies.
This is saved for a future PR since we need to first define the
difference between a policy that was soft-deleted via a sync job, and a
policy that was "perma" deleted by a user.

Related: #8187
2025-04-02 21:12:44 +00:00
Jamil
88c4e723a6 fix(portal): Gracefully handle dir sync error responses (#8608)
When calling the various directory sync endpoints, we had error cases
that matched a few of the possible error scenarios in an appropriate way
by returning either `{:error, :retry_later}` or the `{:error, ...}`
tuples.

However, as we've recently learned in [this
thread](https://firezonehq.slack.com/archives/C069H865MHP/p1743521884037159),
it's possible for identity provider APIs to return all kinds of bogus
data here, and we need a more defensive approach.

The specific issue this PR addresses is the case where we receive a
`2xx` response, but without the expected JSON key in the response body.
That will result in the `list*` functions returning an empty list, which
the calling code paths then use to soft-delete all existing record types
in the DB.

This is wrong. If the JSON response is missing a key we're expecting, we
instead log a warning and return `{:error, :retry_later}`. It's
currently unknown when exactly this happens and why, but with better
monitoring here we'll have a much better picture as to why.
2025-04-02 19:04:43 +00:00
Jamil
8805d906aa chore(portal): Leave notes around sync frequency (#8605)
When reading through these modules, it's helpful to know that the actual
sync data update doesn't occur more often than 10 minutes due to a
database check.
2025-04-01 18:25:33 +00:00
Jamil
936f5ddb01 chore(billing): Enable automatic tax calculation by default (#8552)
When a customer signs up for Starter or Team, we don't enable tax
calculation by default. This means customers can upgrade to Team, start
paying invoices, and we won't collect taxes.

This creates a management issue and possible tax liability since I need
to manually reconcile these.

Instead, since we have Stripe Tax configured on our account, we can
enable automatic tax calculation when the subscription is created. Any
products (Starter/Team/Enterprise) therefore in the subscription will
automatically collect tax appropriately.

In most cases in the US, the tax rate is 0. In EU transactions, for B2B
sales, the tax rate for us is also 0 (reverse charge basis). If we sell
a Team subscription to an individual, however, we need to collect VAT.

There doesn't seem to be a way to block consumer EU transactions in
Stripe, so we'll likely need to register for VAT in the EU if we cross
the reporting threshold.
2025-03-31 13:23:39 +00:00
Jamil
2dbfae9ba9 fix(portal): Use old policy for broadcasting events when updated (#8550)
A regression was introduced in d0f0de0f8d
whereupon we started using the updated policy record for broadcasting
the `delete_policy` and `expire_flows` events. This caused a security
issue because if the actor group changed from `Everyone` to `thomas`,
for example, we'd only expire flows and broadcast policy removal (i.e.
resource removal) events for `thomas`, and `Everyone` would still have
access granted by the old policy.

To fix this, we broadcast the destructive events to the old policy, so
that its `actor_group_id` and `resource_id` are used, and not the new
policy's.

Fixes #8549
2025-03-30 03:26:11 +00:00
Jamil
95d3f765f4 feat(portal): Show Internet Resource in resources/index (#8495)
After removing some of the functionality for viewing the Internet
Resource, customer was confused where to find it again.

This places an `Internet` section in the Resources index page (similar
to Sites page) with a short help text and an action button to view the
Internet Resource.

This also adds a convenient helper that allows us to route to
`/#{account}/resources/internet` for a nicer-looking URL that users can
bookmark if needed.

<img width="1423" alt="Screenshot 2025-03-19 at 11 52 31 PM"
src="https://github.com/user-attachments/assets/f2da1c31-92b2-429e-832f-73ddd0524155"
/>


Fixes #8479
2025-03-26 21:30:11 +00:00
Brian Manifold
3313e7377e feat(portal): Add account delete button (#8487)
Why:

* This commit will allow account admins to send a request through the
Firezone portal to schedule a deletion of their account, rather than
having the account admins email their request manually. Doing this
through the portal allows us to verify that the request actually came
from an admin of the account.
2025-03-19 18:23:32 +00:00
Jamil
595fb7efd9 refactor(portal): Rename resource_cidrs -> device_cidrs (#8482)
I was debugging some of this just now and realized our naming / comments
are incorrect here, so thought I'd open a PR to tidy things up for the
next person reading this.

Resource CIDRs actually occupy the `100.96.0.0/11` range (and IPv6
equivalent), but the portal doesn't generate these.
2025-03-19 01:54:08 +00:00
Brian Manifold
e14e5c4008 refactor(portal): Use appropriate access token for Google IdP (#8478)
Why:

* Previously, when running a directory sync with the Google Workspace
IdP adapter, if a service account had been configured but there was a
problem getting an access token for the service account, the sync job
would fall back to using a personal access token. We no longer want to
rely on any personal access token once a service account has been
configured. This commit will make sure that if a service account is
configured there is no way to fall back to any personal access token.


Fixes #8409
2025-03-18 16:46:08 +00:00
Jamil
366215b1d6 fix(gateway): Prefer setting FIREZONE_ID over /var/lib/firezone (#8475)
When deploying a Gateway from the admin portal UI, we show various
environment variables required for setup. Until now, we've relied on the
`/var/lib/firezone` persistence method for identifying the Gateway.

However, this can cause issues on some systems that don't have writeable
access to /var/lib/firezone, or old versions of systemd that don't
support sandboxed access to this directory.

This PR updates each deployment method to use `FIREZONE_ID` instead
everywhere. Additionally, since the Docker upgrade script needs to
reinvoke the new container using the same arguments (more or less) as
the install, we need to extract the old `/var/lib/firezone/gateway_id`
file out of the existing container if it exists, and try to insert it
into the upgraded container.

Tested both scripts, including upgrades for the Docker script.

Fixes: #8471
2025-03-18 04:08:21 +00:00
Jamil
d143d4dc89 feat(portal): Add changelog link to outdated gateway email (#8458)
It would be useful to have a link to the changelog in our outdated
gateway email.

See https://firezonehq.slack.com/archives/C069H865MHP/p1742088424077639

<img width="638" alt="Screenshot 2025-03-16 at 9 39 22 PM"
src="https://github.com/user-attachments/assets/f67b9b3e-9796-45a9-ae90-26eeabc40740"
/>
2025-03-18 02:43:06 +00:00
Jamil
4ce2f160e3 fix(portal): Allow .local for search_domains (#8472)
This apparently is explicitly used by customers. See
https://firezonehq.slack.com/archives/C08FPHECLUF/p1742221580587719?thread_ts=1741639183.188459&cid=C08FPHECLUF
2025-03-17 20:18:51 +00:00
Jamil
43d084f97f refactor(portal): Enforce internet resource site exclusion (#8448)
Finishes up the Internet Resource migration by enforcing:

- No internet resources in non-internet sites
- No regular resources in internet sites
- Removing the prompt to migrate

~~I've already migrated the existing internet resources in customer's
accounts. No one that was using the internet resource hadn't already
migrated.~~

Edit: I started to head down that path, then decided doing this here in
a data migration was going to be a better approach.

Fixes #8212
2025-03-15 18:25:32 -05:00
Jamil
06aa485e18 ci: Use search_domain for one resource in CI test (#8393)
- Adds a `search_domain` of `httpbin.test` in seeds
- Updates one of our DNS resources under CI test to use this
2025-03-15 13:27:22 +00:00
Jamil
7df1bf2718 feat(portal): Create pgaudit extension (#8435)
[Step
2](https://cloud.google.com/sql/docs/postgres/pg-audit#set-pgaudit-flag-values)
of the pgaudit setup guide for Google Cloud SQL. It would be good to
have detailed pg audit logs on the master application instance in case
things go wrong.

Notably, this prevents erroring out when the `pgaudit` is not available,
which by default, it is. Enabling the `pgaudit` extension for our dev
instance is left as a future endeavor.

Supersedes #5442
2025-03-14 20:04:47 +00:00
Jamil
4cd4c2c6a4 fix(portal): Fix submit button spacing in settings/dns (#8440)
The submit button on the settings -> dns page has a couple UX issues
with the new search domain section:

- It's ambiguous what the `Save` is actually saving
- The spacing makes it look like it's only saving upstream resolvers

This PR introduces a simple fix that address the two issues by:

- Updating the button text to `Save DNS Settings`
- Increasing spacing between submit button and form elements
- Slightly decreasing spacing between the `search domain` and `upstream
resolvers` inputs


<img width="968" alt="Screenshot 2025-03-14 at 12 06 02 AM"
src="https://github.com/user-attachments/assets/651f54c8-3b5f-4747-ad3a-e2ae32eccbf0"
/>


Related #5248
2025-03-14 09:20:29 +00:00
Brian Manifold
d133ee84b7 feat(portal): Add API rate limiting (#8417) 2025-03-13 03:21:09 +00:00
Brian Manifold
27b8fc676a refactor(portal): Update 500 error page (#8420)
Why:

* This commit updates the 500 error page in the portal to have the same
look and feel of the 404 error page in order to be consistent within the
portal UI.
2025-03-12 15:44:07 +00:00
Jamil
6d527c1308 feat(portal): Search domain UI and JSON view (#8401)
- Adds a simple text input to configure search domains ("default DNS
suffix") in the Settings -> DNS page.
- Sends the `search_domain` field as part of the client's `init` message
- Fixes a minor UI alignment inconsistency for the upstream resolvers
field so that the total form width and `New resolver` button width are
the same.


<img width="1137" alt="Screenshot 2025-03-09 at 10 56 56 PM"
src="https://github.com/user-attachments/assets/a1d5a570-8eae-4aa9-8a1c-6aaeb9f4c33a"
/>



Fixes #8365
2025-03-10 17:46:40 +00:00
Jamil
6cfe500b11 fix(portal): Add more validation to search_domain (#8392)
- Prevents `.local`
- Allows ending with `.`

https://github.com/firezone/firezone/pull/8391/files#r1985958387
2025-03-08 14:39:04 +00:00
Jamil
d723336c2a feat(portal): Support search_domain field in Account.Config (#8391)
Introduces a simple `search_domain` field embed into our existing
`Accounts.Account.Config` embedded schema. This will be sent to clients
to append to single-label DNS queries.

UI and API changes will come in subsequent PRs: this one adds field and
(lots of) validations only.

Related: #8365
2025-03-08 03:08:33 +00:00
Jamil
e3897aebd8 feat(portal): Add Mock sync adapter and more seeds (#8370)
- Adds more actor groups to the existing `oidc_provider`
- Configures a rand seed so our seed data is reproducible across
machines
- Formats the seeds file to allow for some refactoring a later PR
- Adds a `Mock` identity provider adapter with sync enabled
2025-03-07 09:37:32 -08:00
Jamil
25ed48114a fix(portal): Use explicit UTC timezone for NOW() (#8374)
Fixes #8373
2025-03-06 17:59:49 +00:00
Jamil
e4ab0f1cb4 fix(portal): Gracefully handle missing params in auth callbacks (#8346)
Rather than the current behavior of raising a 500 when we receive
missing / invalid params in IdP auth callbacks, it would be helpful to
show the user which params were provided, in case the IdP has set
anything useful to aid the user.

For example, we recently received these params from `okta` for a pilot
account (and subsequently rendered them a 500):

```
%{"account_id_or_slug" => "<redacted>", "error" => "access_denied", "error_description" => "User is not assigned to the client application.", "provider_id" => "<redacted>", "state" => "<redacted>"}
```
2025-03-05 12:17:27 +00:00
Jamil
383a67ef09 fix(portal): Use href when navigating out of liveview (#8363)
Not a major issue, but LiveView emits a warning for these that cause
monitoring noise.
2025-03-05 02:34:32 +00:00
Jamil
c3a9bac465 feat(portal): Add client endpoints to REST API (#8355)
Adds the following endpoints:

- `PUT /clients/:id` for updating the `name`
- `PUT /clients/:client_id/verify` for verifying a client
- `PUT /clients/:client_id/unverify` for unverifying a client
- `GET /clients` for listing clients in an account
- `GET /clients/:id` for getting a single client
- `DELETE /clients/:id` for deleting a client

Related: #8081
2025-03-05 00:37:01 +00:00
Jamil
e064cf5821 fix(portal): Debounce relays_presence (#8302)
If the websocket connection between a relay and the portal experiences a
temporary network split, the portal will immediately send the
disconnected id of the relay to any connected clients and gateways, and
all relayed connections (and current allocations) will be immediately
revoked by connlib.

This tight coupling is needlessly disruptive. As we've seen in staging
and production logs, relay disconnects can happen randomly, and in the
vast majority of cases immediately reconnect. Currently we see about 1-2
dozen of these **per day**.

To better account for this, we introduce a debounce mechanism in the
portal for `relays_presence` disconnects that works as follows:

- When a relay disconnects, record its `stamp_secret` (this is somewhat
tricky as we don't get this at the time of disconnect - we need to cache
it by relay_id beforehand)
- If the same `relay_id` reconnects again with the same `stamp_secret`
within `relays_presence_debounce_timeout` -> no-op
- If the same `relay_id` reconnects again with a **different**
`stamp_secret` -> disconnect immediately
- If it doesn't reconnect, **then** send the `relays_presence` with the
disconnected_id after the `relays_presence_debounce_timeout`

There are several ways connlib detects a relay is down:

1. Binding requests time out. These happen every 25s, so on average we
don't know a Relay is down for 12.5s + backoff timer.
2. `relays_presence` - this is currently the fastest way to detect
relays are down. With this change, the caveat is we will now detect this
with a delay of `relays_presence_debounce_timer`.

Fixes #8301
2025-03-04 23:56:40 +00:00
Jamil
f5d4d86412 fix(portal): Don't use liveview navigate for mailtos (#8345)
These cause full page reloads along with a warning. These should be
`link href` instead.
2025-03-04 03:10:14 +00:00
dependabot[bot]
c64c54a95b build(deps): bump flowbite from 3.1.1 to 3.1.2 in /elixir/apps/web/assets (#8313)
Bumps [flowbite](https://github.com/themesberg/flowbite) from 3.1.1 to
3.1.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/themesberg/flowbite/releases">flowbite's
releases</a>.</em></p>
<blockquote>
<h2>v3.1.2</h2>
<ul>
<li>create new theme file to move CSS variables</li>
<li>update quickstart guide to reflect this change</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="4ffec1008a"><code>4ffec10</code></a>
refactor(flowbite): move color theme variables to css file</li>
<li><a
href="38984c12ae"><code>38984c1</code></a>
refactor(colors): move colors from plugin to theme file</li>
<li><a
href="23732fd518"><code>23732fd</code></a>
docs(datepicker): specify that you need to set source</li>
<li>See full diff in <a
href="https://github.com/themesberg/flowbite/compare/v3.1.1...v3.1.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=flowbite&package-manager=npm_and_yarn&previous-version=3.1.1&new-version=3.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-04 00:12:39 +00:00
Jamil
fee808bc62 chore(portal): Log error for unknown channel messages (#8299)
Instead of crashing, it would make sense to log these and let the
connected entity maintain its WebSocket connection.

This should never happen in practice if we maintain our version
compatibility matrix properly, but it will help reduce the blast radius
of a channel message bug that happens to slip out into the wild.

Fixes #4679
2025-03-03 21:21:39 +00:00
Jamil
e5ae00ab99 fix(portal): norely -> noreply in gateway/channel.ex (#8329)
Fixes a typo that snuck in in #8267
2025-03-03 08:15:46 +00:00
Jamil
cb0bf44815 chore: Remove ability to create GCP log sinks (#8298)
This has long since been removed in the Clients.
2025-02-28 20:57:21 +00:00
Jamil
15938991d5 chore(portal): Remove NEW badge for DNS matching (#8259)
Fixes #8099
2025-02-28 04:52:56 +00:00
Jamil
e03047d549 feat(portal): Send gateway ipv4 and ipv6 to client (#8291)
In order to properly handle SRV and TXT records on the clients, we need
to be able to pick a Gateway using the initial query itself. After that,
we need to know the Gateway Tunnel IPs we're connecting to so we can
have the query perform the lookup.

Fixes #8281
2025-02-28 03:52:27 +00:00
Jamil
d09e9cfe08 fix(portal): Increase assert diff for last_flushed_at (#8292)
Fixes #8290
2025-02-28 01:23:37 +00:00
Jamil
d7be59707a fix(portal): Improve resource address validation (#8288)
We had a number of validation issues:

- DNS resources allow address `1.1.1.1` or `1.1.1.1/32`. These are not
valid and will cause issues during resolution.
- IP resources were allowing basically any string character on `edit`
caused by a logic bug in the changeset
- CIDR resources, same as above
- `*.*.*.*.google.com` and similar DNS wildcard resources were not
allowed

This PR beefs all of those up so that we have a higher degree of
certainty that our data is valid. If invalid data reaches connlib, it
will cause a panic.

This PR also introduces a migration to migrate any invalid resources
into the proper format in the DB.

Fixes #8287
2025-02-27 23:41:11 +00:00
Brian Manifold
bc150156ce fix(portal): Update gateway channel to process resource_update (#8280)
Why:

* After merging #8267 it was discovered that there was a race condition
that allowed a `resource_create` message to end up at the Gateway
Channel process. Previously, this message would not have ever arrived,
because we were replacing Resource IDs when a breaking change was made,
but since that is no longer the case, it is possible that a connection
could be established between the time the `delete_resource` and
`create_resource` messages are sent and the `create_resource` would end
up at the Gateway Channel process. This commit adds a no-op handler to
make sure the message gets processed without throwing an error.
2025-02-27 01:46:13 +00:00
Brian Manifold
d0f0de0f8d refactor(portal): Allow breaking changes in Resources/Policies (#8267)
Why:

* Rather than using a persistent_id field in Resources/Policies, it was
decided that we should allow "breaking changes" to these entities. This
means that Resources/Policies will now be able to update all fields on
the schema without changing the primary key ID of the entity.
* This change will greatly help the API and Terraform provider
development.

@jamilbk, would you like me to put a migration in this PR to actually
get rid of all of the existing soft deleted entities?

@thomaseizinger, I tagged you on this, because I wanted to make sure
that these changes weren't going to break any expectations in the client
and/or gateways.

---------

Signed-off-by: Brian Manifold <bmanifold@users.noreply.github.com>
Co-authored-by: Jamil <jamilbk@users.noreply.github.com>
2025-02-26 17:05:34 +00:00
Jamil
5650150b3f chore(portal): Enforce only internet resource in internet site (#8254)
Currently, it would theoretically be possible for an admin to connect
non-internet Resources to the Internet site. This PR fixes that by
enforcing only the `internet` Resource type can belong to the `Internet`
gateway group.


Related: #6834
2025-02-25 03:45:40 +00:00
Jamil
31111257e1 fix(portal): Fix layout of live_table filters controls (#8256)
Fixes layout of filters controls. A more permanent fix will be
introduced as part of #8255
2025-02-24 18:27:50 -08:00
Jamil
8bd94599a9 chore(portal): Remove dead ScimController (#8253)
This is leftover from a previous prototype and can be removed.
2025-02-24 22:58:38 +00:00
Jamil
c5929d4063 fix(portal): Show reload button when table data is stale (#8143)
Sentry uncovered a bug in the resources index liveview where it looks
like some code copy-pasted from the policies index view wasn't updated
properly to work in the resources live view, causing the view to crash
if an admin was viewing the table while the resources are changed in
another page.

In debugging that, I realized the best UX when viewing these tables is
usually just to show a `Reload` button and not update the data live
while the admin is viewing it, as this can cause missed clicks and other
annoyances.

This PR adds an optional `stale` component attribute that, if true, will
render a `Reload` button in the live table which upon clicking will
reload the live table.

Not all index views are updated with this - in some views there is
already logic to handle making an intelligent update without breaking
the view if the data is updated - for example for the clients table.

Ideally, we live-update things that don't reflow layout inline (such as
`online/offline` presence) and for things that do cause layout reflow
(create/delete), we show the `Reload` button.

However that work is saved for a future PR as this one fixes the
immediate bug and this is not the highest priority.

<img width="1195" alt="Screenshot 2025-02-16 at 8 44 43 AM"
src="https://github.com/user-attachments/assets/114efffa-85ea-490d-9cea-78c607081ce3"
/>
<img width="401" alt="Screenshot 2025-02-16 at 9 59 53 AM"
src="https://github.com/user-attachments/assets/8a570213-d4ec-4b6c-a489-dcd9ad1c351c"
/>
2025-02-24 15:39:16 +00:00
Jamil
29f0ac0a00 fix(portal): Handle missing params in idp callback (#8239)
It's possible for a client or admin to try and load the redirect URL
directly, or a misconfigured IdP may redirect back to us with missing
params. We should redirect with an error flash instead of 500'ing.
2025-02-24 13:38:10 +00:00