Commit Graph

242 Commits

Author SHA1 Message Date
Jamil
cafe6554ff refactor(portal): reduce cache memory usage (#10058)
Napkin math shows that we can save substantial memory (~3x or more) on
the API nodes as connected clients/gateways grow if we just store the
fields we need in order to keep the client and gateway state maintained
in the channel pids.

To facilitate this, we create new `Cacheable` structs that represent
their `Domain` cousins, which use byte arrays for `id`s and strip out
unused fields.

Additionally, all business logic involved with maintaining these caches
is now contained within two modules: `Domain.Cache.Client` and
`Domain.Cache.Gateway`, and type specs have been added to aid in static
analysis and code documentation.

Comprehensive testing is now added not only for the cache modules, but
for their associated channel modules as well to ensure we handle
different kinds of edge cases gracefully.

The `Events` nomenclature was renamed to `Changes` to better name what
we are doing: Change-Data-Capture.

Lastly, the following related changes are included in this PR since they
were "in the way" so to speak of getting this done:

- We save the last received LSN in each channel and drop the `change`
with a warning if we receive it twice in a row, or we receive it out of
order
- The client/gateway version compatibility calculations have been moved
to `Domain.Resources` and `Domain.Gateways` and have been simplified to
make them easier to understand and maintain going forward.


Related: #10174 
Fixes: #9392 
Fixes: #9965
Fixes: #9501 
Fixes: #10227

---------

Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-22 21:52:29 +00:00
Jamil
cacb44f7bb test(portal): fix flaky acceptance auth test (#10140)
Occasionally, this fails because the element is found, but not visible
due to a race condition. To fix this, we assert that the element should
be visible before clicking on it.

Fixes
https://github.com/firezone/firezone/actions/runs/16751908154/job/47424125321
2025-08-05 14:53:18 +00:00
Jamil
f379e85e9b refactor(portal): cache access state in channel pids (#9773)
When changes occur in the Firezone DB that trigger side effects, we need
some mechanism to broadcast and handle these.

Before, the system we used was:

- Each process subscribes to a myriad of topics related to data it wants
to receive. In some cases it would subscribe to new topics based on
received events from existing topics (I.e. flows in the gateway
channel), and sometimes in a loop. It would then need to be sure to
_unsubscribe_ from these topics
- Handle the side effect in the `after_commit` hook of the Ecto function
call after it completes
- Broadcast only a simply (thin) event message with a DB id
- In the receiver, use the id(s) to re-evaluate, or lookup one or many
records associated with the change
- After the lookup completes, `push` the relevant message(s) to the
LiveView, `client` pid, or `gateway` pid in their respective channel
processes

This system had a number of drawbacks ranging from scalability issues to
undesirable access bugs:

1. The `after_commit` callback, on each App node, is not globally
ordered. Since we broadcast a thin event schema and read from the DB to
hydrate each event, this meant we had a `read after write` problem in
our event architecture, leading to the potential for lost updates. Case
in point: if a policy is updated from `resource_id-1` to
`resource_id-2`, and then back to `resource_id-1`, it's possible that,
given the right amount of delay, the gateway channel will receive two
`reject_access` events for `resource_id-1`, as opposed to one for
`resource_id-1` and one for `resource_id-2`, leading to the potential
for unauthorized access.
1. It was very difficult to ensure that the correct topics were being
subscribed to and unsubscribed from, and the correct number of times,
leading to maintenance issues for other engineers.
1. We had a nasty N+1 query problem whenever memberships were added or
removed that resolved in essentially all access related to that
membership (so all Policies touching its actor group) to be
re-evaluated, and broadcasted. This meant that any bulk addition or
deletion of memberships would generate so many queries that they'd
timeout or consume the entire connection pool.
1. We had no durability for side-effect processing. In some places, we
were iterating over many returned records to send broadcasts.
Broadcasting is not a zero-time operation, each call takes a small
amount of CPU time to copy the message into the receiver's mailbox. If
we deployed while this was happening, the state update would be lost
forever. If this was a `reject_access` for a Gateway, the Gateway would
never remove access for that particular flow.
1. On each flow authorization, we needed to hit `us-east1` not only to
"authorize" the flow, but to log it as well. This incurs latency
especially for users in other parts of the world, which happens on
_each_ connection setup to a new resource.
1. Since we read and re-authorize access due to the thin events
broadcasted from side effects, we risk hitting thundering herd problems
(see the N+1 query problem above) where a single DB change could result
in all receivers hitting the DB at once to "hydrate" their
processing.ion
1. If an administrator modifies the DB directly, or, if we need to run a
DB migration that involves side effects, they'll be lost, because the
side effect triggers happened in `after_commit` hooks that are only
available when querying the DB through Ecto. Manually deleting (or
resurrecting) a policy, for example, would not have updated any
connected clients or gateways with the new state.


To fix all of the above, we move to the system introduced in this PR:

- All changes are now serialized (for free) by Postgres and broadcasted
as a single event stream
- The number of topics has been reduced to just one, the `account_id` of
an account. All receivers subscribe to this one topic for the lifetime
of their pid and then only filter the events they want to act upon,
ignoring all other messages
- The events themselves have been turned into "fat" structs based on the
schemas they present. By making them properly typed, we can apply things
like the existing Policy authorizer functions to them as if we had just
fetched them from the DB.
- All flow creation now happens in memory and doesn't not need to incur
a DB hit in `us-east1` to proceed.
- Since clients and gateways now track state in a push-based manner from
the DB, this means very few actual DB queries are needed to maintain
state in the channel procs, and it also means we can be smarter about
when to send `resource_deleted` and `resource_created_or_updated`
appropriately, since we can always diff between what the client _had_
access to, and what they _now_ have access to.
- All DB operations, whether they happen from the application code, a
`psql` prompt, or even via Google SQL Studio in the GCP console, will
trigger the _same_ side effects.
- We now use a replication consumer based off Postgres logical decoding
of the write-ahead log using a _durable slot_. This means that Postgres
will retain _all events_ until they are acknowledged, giving us the
ability to ensure at-least-once processing semantics for our system.
Today, the ACK is simply, "did we broadcast this event successfully".
But in the future, we can assert that replies are received before we
acknowledge the event as processed back to Postgres.



The tests in this PR have been updated to pass given the refactor.
However, since we are tracking more state now in the channel procs, it
would be a good idea to add more tests for those edge cases. That is
saved as a later PR because (1) this one is already huge, and (2) we
need to get this out to staging to smoke test everything anyhow.

Fixes: #9908 
Fixes: #9909 
Fixes: #9910
Fixes: #9900 
Related: #9501
2025-07-18 22:47:18 +00:00
Jamil
dddd1b57fc refactor(portal): remove flow_activities (#9693)
This has been dead code for a long time. The feature this was meant to
support, #8353, will require a different domain model, views, and user
flows.

Related: #8353
2025-06-27 20:40:25 +00:00
Jamil
6c0a62aa73 fix(tests): wait for visible els before click (#9697)
We had an old bug in one of our acceptance tests that is just now being
hit again due to the faster runners.

- We need to wait for the dropdown to become visible before clicking
- We fix a minor timer issue that was calculating elapsed time
incorrectly when determining when time out finding an el.
2025-06-27 19:06:59 +00:00
Jamil
0b09d9f2f5 refactor(portal): don't rely on flows.expires_at (#9692)
The `expires_at` column on the `flows` table was never used outside of
the context in which the flow was created in the Client Channel. This
ephemeral state, which is created in the `Domain.Flows.authorize_flow/4`
function, is never read from the DB in any meaningful capacity, so it
can be safely removed.

The `expire_flows_for` family of functions now simply reads the needed
fields from the flows table in order to broadcast `{:expire_flow,
flow_id, client_id, resource_id}` directly to the subscribed entities.

This PR is step 1 in removing the reliance on `Flows` to manage
ephemeral access state. In a subsequent PR we will actually change the
structure of what state is kept in the channel PIDs such that reliance
on this Flows table will no longer be necessary.

Additionally, in a few places, we were referencing a Flows.Show view
that was never available in production, so this dead code has been
removed.

Lastly, the `flows` table subscription and associated hook processing
has been completely removed as it is no longer needed. We've implemented
in #9667 logic to remove publications from removed table subscriptions,
so we can expect to get a couple ingest warnings when we deploy this as
the `Hooks.Flows` processor no longer exists, and the WAL data may have
lingering flows records in the queue. These can be safely ignored.
2025-06-27 18:29:12 +00:00
Jamil
c6545fe853 refactor(portal): consolidate pubsub functions (#9529)
We issue broadcasts and subscribes in many places throughout the portal.
To help keep the cognitive overhead low, this PR consolidates all PubSub
functionality to the `Domain.PubSub` module.

This allows for:

- better maintainability
- see all of the topics we use at a glance
- consolidate repeated functionality (saved for a future PR)
- use the module hierarchy to define function names, which feels more
intuitive when reading and sets a convention

We also introduce a `Domain.Events.Hooks` behavior to ensure all hooks
comply with this simple contract, and we also introduce a convention to
standardize on topic names using the module hierarchy defined herein.

Lastly, we add convenience functions to the Presence modules to save a
bit of duplication and chance for errors.

This will make it much easier to maintain PubSub going forward.


Related: #9501
2025-06-15 04:30:57 +00:00
Jamil
cbe33cd108 refactor(portal): move policy events to WAL (#9521)
Moves all of the policy lifecycle events to be broadcasted from the WAL
consumer.

#### Test

- [x] Enable policy
- [x] Disable policy
- [x] Delete policy
- [x] Non-breaking change
- [x] Breaking change


Related: #6294

---------

Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
2025-06-14 01:10:09 +00:00
Jamil
817eeff19f refactor(portal): simplify managed groups (#9513)
In many places throughout the portal codebase, we called a function
"update_dynamic_group_memberships/1" which recomputed all of the
dynamic/managed memberships for a particular account, and reapplied them
to each affected group.

Since the `has_many :memberships` relationship used `on_replace:
:delete`, this caused Ecto to delete _all_ the `Everyone` group
memberships, and reinsert them on each sync.

Since each membership change triggers a policy re-evaluation for all
policies to the affected actor
(`Policies.broadcast_access_events_for/3`), this in effect was causing a
massive amount of queries to be triggered upon each sync job as each
membership deletion and insertion triggered a lookup for all resources
available to that particular actor.

To fix this, we introduce the following changes:

- Remove `dynamic` group type. This will never be used as it will create
an immense amount of complexity for any organization trying to manage
groups this way
- Refactor `update_dynamic_group_memberships/1` to use a smarter query
that first gathers all the _needed_ changes and applies them within a
transaction using Ecto.Multi. Previously all memberships would be rolled
over unconditionally due to the `on_replace: :delete` option on the
relationship. Note that the option is still there, but we generally
don't set memberships on groups any longer unless editing the affected
group directly, where the everyone group doesn't apply.

Resolves: #8407 
Resolves: #8408
Related: #6294

---------

Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-13 18:55:37 +00:00
Jamil
c31f51d138 refactor(portal): move resource events to WAL (#9406)
We move the resource events to the WAL system. Notably, we no longer
need `fetch_and_update_breakable` for resource updates, so a bit of
refactoring is included to update the call sites for those.

Additionally, we need to add a `Flow.expire_flows_for_resource_id/1`
function to expire flows from the WAL system. This is now being called
in the WAL event handler. To prevent this from blocking the WAL
consumer/broadcaster, we wrap it with a Task.async. These will be
cleaned up when the lookup table for access is implemented next.

Another thing to note is that we lose the `subject` when moving from
`Flows.expire_flows_for(%Resource{}, subject)` to
`Flows.expire_flows_for_resource_id(resource_id)` when a resource is
deleted or updated by an actor since we respond to this event in the WAL
where that data isn't available. However, we don't actually _use_ the
subject when expiring flows (other than authorize the initial resource
update), so this isn't an issue.

Related: #9501

---------

Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Brian Manifold <bmanifold@users.noreply.github.com>
2025-06-11 00:12:45 +00:00
Jamil
f58176a447 chore: remove docs writer (#9494)
This was added in an earlier era and will be just too cumbersome to
maintain going forward. We have OpenAPI docs which are more flexible.
2025-06-10 02:51:46 +00:00
Jamil
38c1de351c refactor(portal): move membership events to WAL (#9388)
Membership events are quite simple to move to the WAL:

- Only one topic is used to determine which client(s) receive updates
for which Actor(s).
- The unsubscribe was removed because it was unused.
- Notably, the N+1 query problem regarding re-evaluating all access
again after each membership is updated is still present. This will be
fixed using a lookup table in the client channel in the last PR to move
events to the WAL.

Related: https://github.com/firezone/firezone/issues/6294
Related: https://github.com/firezone/firezone/issues/8187
2025-06-06 06:23:33 +00:00
Jamil
6fc7d2e4e0 feat(portal): configurable ip stack for DNS resources (#9303)
Some poorly-behaved applications (e.g. mongo) will fail to connect if
they see both IPv4 and IPv6 addresses for a DNS resource, because they
will try to connect to both of them and fail the whole connection setup
if either one is not routable.

To fix this, we need to introduce a knob to allow admins to restrict DNS
resources to only A or AAAA records.


<img width="750" alt="Screenshot 2025-06-02 at 10 48 39 AM"
src="https://github.com/user-attachments/assets/4dbcb6ae-685f-43ee-b9e8-1502b365a294"
/>

<img width="1174" alt="Screenshot 2025-06-02 at 11 05 53 AM"
src="https://github.com/user-attachments/assets/02d0a4b3-e6e8-4b6d-89fa-d3d999b5811e"
/>

---

Related:
https://firezonehq.slack.com/archives/C08KPQKJZKM/p1746720923535349
Related: #9300
Fixes: #9042
2025-06-03 02:24:41 +00:00
Jamil
73c3e2d87b refactor(portal): move gateway events to WAL (#9299)
This PR moves Gateway events to be triggered by the WAL broadcaster.
Some things of note that are cleaned up:

- The gateway `:update` event was never received anywhere (but in a
test) and so has been removed
- The account topic has been removed as it was also never acted upon
anywhere. Presence yes, but topic no
- The group topic has also been removed as it was only used to receive
broadcasted disconnects when a group is deleted, but this was already
handled by the token deletion and so is redundant.
2025-06-01 16:40:28 +00:00
Brian Manifold
a51b35a6b4 refactor(portal): remove created_by_<identity/actor> columns (#9306)
Why:

* Now that we have started using the `created_by_subject` field on
various tables, we no longer need to keep the
`created_by_<identity/actor>` fields. This will help remove a foreign
key reference and will be one step closer to allowing us to hard delete
data rather than soft deleting all data in order to keep foreign key
references like these.
2025-05-30 21:06:35 +00:00
Jamil
5fb36cf327 fix(portal): Fix sign out acceptance test (#9302)
In #9294, we moved the token deletion side effect to the WAL consumer,
which is not executed for standard tests. As such, we need to call this
callback manually in the sign out acceptance test.

Fixes
https://github.com/firezone/firezone/actions/runs/15337858094/job/43158416750?pr=9295

---------

Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-30 07:16:55 +00:00
Jamil
e09c7b42b0 refactor(portal): Move token events to WAL broadcaster (#9294)
Moves the broadcasting of `disconnect` messages caused by token
soft-deletions to the WAL broadcaster.

Notably, many tests had to be cleaned up because they were specifically
testing this side effect. Instead, these tests now test (1) the token is
deleted, and then the token deletion handler is tested to ensure the
message is broadcasted.
2025-05-29 17:46:57 +00:00
Jamil
6cea0cd6ec refactor(portal): Move client updates to WAL broadcaster (#9288)
Client updates are next on the path to moving more side effects to the
WAL broadcaster. This one has the following notable changes:

- ~~The `actor_clients` pubsub topic were only used to broadcast removal
of clients belonging to an actor; these are no longer needed since we
handle this in the individual removal event~~ EDIT: only the presence is
kept
- The `account_clients:{account_id}` pubsub and presence topic
definition has been moved to `Events.Hooks.Accounts` because these are
broadcasted using the account_id field based on account changes, and
have nothing to do with the client lifecycle


Related: #6294 
Related: #8187
2025-05-29 16:56:08 +00:00
Brian Manifold
1358da189d refactor(portal): start using created_by_subject (#9284)
Now that we've added the `created_by_subject` column on all relevant
tables, we can start using that data in the portal.
2025-05-28 14:57:36 +00:00
Brian Manifold
12b4a12f26 feat(portal): Add created_by_subject (#9176)
Why:

* We have decided to change the way we will do audit logging. Instead of
soft deleting data and keeping it in the table it was created in, we
will be moving to an audit trail table where various actions will be
recorded in a table/DB specifically for auditing purposes. Due to this
change we need to make sure that we don't have stale/dangling
references. One set of references we keep everywhere is
`created_by_identity_id` and `created_by_actor_id`. Those foreign key
references won't be able to be used after moving to the new audit
system. This commit will allow us to keep that info by pulling the
values and storing the data in a created_by_subject field on the record.
2025-05-20 20:03:46 +00:00
Jamil
65c58ee254 feat(portal): Zero-click client authentication (#9144)
Adds a new field to `settings/identity_providers` that allows an Admin
to designate any non-email/otp provider as the `default` for client
authentication. Clients will then navigate directly to the provider's
`/redirect` endpoint when authenticating, which in many cases will
automatically sign them in.

No existing providers are updated in this PR.



https://github.com/user-attachments/assets/7b962a25-76fd-491f-a194-60ed993821fc
2025-05-16 19:26:08 +00:00
Brian Manifold
3f3f007920 fix(portal): Update copy to clipboard button (#8907)
Why:

* The copy to clipboard button was not working at all on the API new
token page due to the fact that the FlowbiteJS library expects the
presence of the elements in the DOM on first render. This was not true
of the API Token code block. Along with that issue the existing code
blocks copy to clipboard buttons did not give any visual indication that
the copy had been completed. It was also somewhat difficult to see the
copy to clipboard button on those code blocks as well. This commit
updates the buttons to be more visible, as well as adds a phx-hook to
make sure the FlowbiteJS init functions are run on every code block even
if it's inserted after the initial load of the page and adds functions
that are run as a callback to toggle the button text and icon to show
the text has been copied.
2025-04-26 00:43:43 +00:00
Jamil
0a2a393d4c fix(portal): Prevent additional email identities per actor (#8888)
This is a UI-only change for now to serve as a stop-gap while we work to
overhaul the identity domain model.

Related: #6294
2025-04-22 21:13:37 +00:00
Brian Manifold
4c9848453d refactor(portal): Add more logging around sign in errors (#8789)
Why:

* To allow for more accurate and efficient troubleshooting in
production.
2025-04-15 14:25:06 +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
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
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
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
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
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
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
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
Jamil
9b5a7e5fb3 fix(portal): Fix grammar on account lockout message (#8149) 2025-02-17 06:06:28 +00:00
Andrew Dryga
bacb4596b7 feat(portal): Internet Sites (#6905)
Related #6834

Co-authored-by: Jamil Bou Kheir <jamilbk@users.noreply.github.com>
2025-02-15 00:34:30 +00:00
Jamil
a93f40befd chore(portal): Bump elixir to 1.18.2 (#8009)
This is mostly to stay up to date with current Elixir and benefit from
the new included [JSON parser](https://hexdocs.pm/elixir/JSON.html).

Removing `Jason` in favor of the embedded `JSON` parser is saved for a
[future PR](https://github.com/firezone/firezone/issues/8011).

It found a couple type violations which were simple to fix, and some
formatting changes.
2025-02-05 23:52:58 +00:00
dependabot[bot]
bbbd6eded2 build(deps): bump phoenix_live_view from 1.0.0-rc.6 to 1.0.3 in /elixir (#7983)
Bumps
[phoenix_live_view](https://github.com/phoenixframework/phoenix_live_view)
from 1.0.0-rc.6 to 1.0.3.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/phoenixframework/phoenix_live_view/blob/v1.0.3/CHANGELOG.md">phoenix_live_view's
changelog</a>.</em></p>
<blockquote>
<h2>1.0.3 (2025-01-28)</h2>
<h3>Bug fixes</h3>
<ul>
<li>Fix regression where browser back/forward buttons used
<code>patch</code> instead of <code>navigate</code>, failing to update
the page (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/issues/3529">#3529</a>)</li>
<li>Fix client hooks inside streams that contain nested LiveViews (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/issues/3530">#3530</a>)</li>
<li>Fix LiveComponents in nested LiveViews not updating under certain
conditions (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/issues/3626">#3626</a>)</li>
<li>Fix client-side hooks not being cleared properly (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/issues/3628">#3628</a>)</li>
<li>Fix LiveUpload from client hook not auto uploading when immediately
followed by form event (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/issues/3647">#3647</a>)</li>
<li>Fix inputs being cleared in some cases when patching locked trees
(<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/issues/3647">#3647</a>)</li>
<li>Fix client hooks with dynamic IDs not being destroyed properly when
parts of the DOM are locked (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/issues/3651">#3651</a>)</li>
</ul>
<h3>Enhancements</h3>
<ul>
<li>Allow to configure if duplicate IDs / other detected errors should
warn or raise by passing <code>on_error</code> to
<code>Phoenix.LiveViewTest.live/3</code> /
<code>Phoenix.LiveViewTest.live_isolated/3</code> (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/pull/3653">#3653</a>)</li>
<li>Also detect duplicate LiveComponents that are added dynamically to
the page in LiveViewTest (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/pull/3653">#3653</a>)</li>
<li>Log an error in the JavaScript console when detecting a stream
container with missing <code>phx-update=&quot;stream&quot;</code>
attribute (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/pull/3645">#3645</a>)</li>
<li>Update documentation to mention <code>:fun</code> and <code>{:fun,
arity}</code> as valid attribute types for
<code>Phoenix.Component.attr/3</code> (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/pull/3635">#3635</a>)</li>
<li>Update documentation to mention ways for <a
href="https://hexdocs.pm/phoenix_live_view/1.0.3/Phoenix.Component.html#module-dynamic-component-rendering">dynamically
rendering function components</a> (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/pull/3632">#3632</a>)</li>
<li>Update documentation to mention <code>{:inner, selector}</code> and
<code>{:closest, selector}</code> as <a
href="https://hexdocs.pm/phoenix_live_view/1.0.3/Phoenix.LiveView.JS.html#module-dom-selectors">valid
options for <code>to</code></a> in JS commands (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/pull/3638">#3638</a>)</li>
</ul>
<h2>1.0.2 (2025-01-09)</h2>
<h3>Bug fixes</h3>
<ul>
<li>Fix inconsistency between <code>mix format</code> and <code>mix
format --check-formatted</code> with new curly interpolation syntax (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/issues/3590">#3590</a>)</li>
<li>Fix unnecessary compile time dependencies when using
<code>attr</code> / <code>on_mount</code> / <code>live</code> (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/issues/3592">#3592</a>)</li>
<li>Fix crash when testing LiveViews with embedded XML (e.g. SVGs) (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/issues/3594">#3594</a>)</li>
<li>Fix type warning when using <code>follow_redirect</code> (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/issues/3581">#3581</a>)</li>
<li>Prevent <code>phx-trigger-action</code> from clashing with locked
forms (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/issues/3591">#3591</a>)</li>
<li>Fix form recovery sending wrong event name when using JS commands in
<code>phx-change</code> (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/issues/3607">#3607</a>)</li>
</ul>
<h3>Enhancements</h3>
<ul>
<li>Deduplicate items on <code>stream/4</code> /
<code>steam_insert/4</code> (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/pull/3599">#3599</a>)</li>
<li>Restore scroll position on initial navigation (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/pull/3572">#3572</a>)</li>
<li>Change-track non existing keys in maps (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/pull/3584">#3584</a>)</li>
<li>Only warn instead of raising when detecting a duplicate ID in
LiveViewTest (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/pull/3603">#3603</a>)</li>
</ul>
<h2>1.0.1 (2024-12-13)</h2>
<h3>Bug fixes</h3>
<ul>
<li>Raise when duplicate DOM IDs are found when rendering a LiveView
during tests to avoid undefined behaviour</li>
<li>Fix live session verification causing logged errors, push_patch
failures, and failed mounts when a cold deploy occurs</li>
<li>Fix a bug where the <code>live_session</code>'s
<code>on_mount</code> hooks would be called for sticky live views on
connected mount. Now a <code>sticky</code> live view is consistently
marked as <code>:not_mounted_at_router</code></li>
</ul>
<h2>1.0.0 (2024-12-03) 🚀</h2>
<h2>1.0.0-rc.9 (2024-12-03)</h2>
<h3>Enhancements</h3>
<ul>
<li>Support <code>phx-no-curly-interpolation</code> to disable HEEx
curly interpolation in a specific tag body</li>
</ul>
<h2>1.0.0-rc.8 (2024-12-02)</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="8ea6b487de"><code>8ea6b48</code></a>
Release 1.0.3</li>
<li><a
href="e419029347"><code>e419029</code></a>
mix format</li>
<li><a
href="df82b86f4b"><code>df82b86</code></a>
small refactor of on_error tests</li>
<li><a
href="f1b9d2b492"><code>f1b9d2b</code></a>
only raise by default in later release</li>
<li><a
href="aee1b64972"><code>aee1b64</code></a>
update tests to not use deprecated struct update syntax</li>
<li><a
href="7a69ff77ec"><code>7a69ff7</code></a>
update changelog</li>
<li><a
href="6ca0b8b655"><code>6ca0b8b</code></a>
Update assets</li>
<li><a
href="f100c75de3"><code>f100c75</code></a>
fail early when hook element is not owned by view (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/issues/3618">#3618</a>)</li>
<li><a
href="a414c2cdd9"><code>a414c2c</code></a>
Update assets</li>
<li><a
href="07e4340c30"><code>07e4340</code></a>
remove replaceRootHistory (<a
href="https://redirect.github.com/phoenixframework/phoenix_live_view/issues/3625">#3625</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/phoenixframework/phoenix_live_view/compare/v1.0.0-rc.6...v1.0.3">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=phoenix_live_view&package-manager=hex&previous-version=1.0.0-rc.6&new-version=1.0.3)](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>
Co-authored-by: Jamil Bou Kheir <jamilbk@users.noreply.github.com>
2025-02-04 14:18:00 +00:00
Jamil
acfecc11ec feat(portal): Sort resources by name ASC by default (#7884)
Updates the Resource's pagination cursor such that the default cursor
(with no HTTP params applied) uses `{:resources, :asc, :name}` as the
default, which correctly updates all Resources live tables to sort by
`name`.

The reason this is updated at the Query layer is because I wanted to
achieve this without populating URL params by default, and still
allowing the sort icon to properly reflect the default sort order upon
page load, which it does.

My initial attempt went down the path of updating `assign_live_table/3`
to take a `default_order_by` option. That didn't work because upon page
load we `handle_params` which resets the ordering immediately based on
the URL params.

Rather than update the UI code to track even more state in order to use
`default_order_by` when the `order_by` param is not specified, I opted
to updated the Query module instead which the UI uses.

Fixes #7842
2025-01-27 17:38:19 +00:00
Jamil
24640cad34 test(portal): Update resource type/address (#7881)
While investigating the cause of #7879, I noticed we don't have tests
specifically for updating a Resource's type or address.

Related: #7879
2025-01-27 16:23:06 +00:00
Jamil
fa19bbf486 refactor(portal): Authorized Sessions -> Recent Connections (#7830)
We've gotten feedback recently that the expiration field causes
confusion among auditors who assume it has actual security relevance.

In reality, this is simply the maximum amount of time a connection
between Client and Gateway will stay alive for, and it has no relation
to "sessions" from a security perspective. As such, it's removed, and
the table renamed "Recent connections" to better name what these are.

The `expiration` column is also removed because this is not actionable
by the admin or end-user. In nearly all cases, the connection will have
been "expired" by some other means naturally, such as toggling Firezone
on/off or a policy or resource change. In other words, we do not rely on
this `expiration` field to enforce any security-related timeout.

Fixes #7712
2025-01-22 16:10:57 +00:00
Brian Manifold
1ef286ac55 fix(portal): API clients 'show' page should always be in settings (#7371)
Why:

* The portal currently shows API clients in the Actors index list. Each
Actor in the list has a link to their own 'show' page. Prior to this
commit, selecting an API client from the list would result an error.
While API clients are technically an Actor, they aren't quite the same
as all other Actors because they are only used to configure the portal
for a given account. Because of this, they don't have the same
information to show as all other Actors. This commit sets the 'show' URL
for API clients to the 'settings' page to show the proper info for the
API client.

Fixes: #7370
2024-11-18 18:52:23 +00:00
Andrew Dryga
a67c12de7e fix(portal): Polish link in peeks (#7180) 2024-10-29 19:22:20 -06:00
Andrew Dryga
f296dc5ad2 feat(portal): Show clients peek on actors index (#7100)
We will show up to 5 recently started client icons and a status for them
as a green dot badge (no dot when it's offline to keep things simple).
Additional details are available on hover.

<img width="1415" alt="1"
src="https://github.com/user-attachments/assets/1d48d08b-f024-4016-837a-3a2ac9a34718">
<img width="1413" alt="2"
src="https://github.com/user-attachments/assets/101ff122-26e2-4282-ae1d-073b4eba9c56">

I also extended the `Clients` table on "Actor" view page to match the
"Clients" index view.

Also closes #7096
2024-10-28 16:06:22 -06:00
Andrew Dryga
5888aa0f49 fix(portal): Only show one icon next to client name and make it match the style of heroicons (#7085)
<img width="1376" alt="Screenshot 2024-10-17 at 2 05 35 PM"
src="https://github.com/user-attachments/assets/4d294e60-35c5-4ebf-b3cc-6bfdbf5230e3">
2024-10-17 16:00:36 -06:00
Andrew Dryga
268825d45b fix(portal): Fix table titles (#7080) 2024-10-16 16:27:09 -06:00
Andrew Dryga
37ef2cb591 feat(portal): Allow filtering clients by presence and deleting them (#7078)
Closes #7073

<img width="1434" alt="Screenshot 2024-10-16 at 12 40 50 PM"
src="https://github.com/user-attachments/assets/2c03f38c-c67e-49db-9453-e23651c8d61c">

<img width="1154" alt="Screenshot 2024-10-16 at 12 47 37 PM"
src="https://github.com/user-attachments/assets/da519458-1447-4dfe-9cef-536bf7760ce2">
2024-10-16 13:29:24 -06:00
Andrew Dryga
1abfa10fb7 fix(portal): UX improvements (#7013)
This PR accumulates lots of small UX fixes from #6645.

---------

Co-authored-by: Jamil Bou Kheir <jamilbk@users.noreply.github.com>
2024-10-14 11:32:44 -06:00
Brian Manifold
7fda4c52c4 feat(portal): Add outdated gateway notifications (#6841)
Why:

* Without some type of notification, users do not realize that new
Gateway versions have been released and thus do not seem to be upgrading
their deployed Gateways.
2024-10-11 12:46:00 +00:00
Brian Manifold
4dde7293d5 fix(portal): Fix show page errors when entity was created by API (#7002)
Why:

* A handful of 'show' pages were throwing errors for entities created
using the API. The reason was due to the fact that the
`created_by_actor` was not being preloaded and when the details on the
show page were being rendered. This commit updates the various pages to
preload the `created_by_actor` to allow for both API created entities
and UI created entities.
2024-10-10 15:44:53 +00:00