-
Notifications
You must be signed in to change notification settings - Fork 6
Beacon Configuration Admin View, with CRUD and Regenerate and Revoke Tokens Actions #585
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
FionaLMcLaren
wants to merge
31
commits into
main
Choose a base branch
from
beacons-regenerate
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,132
−7
Open
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
035abfa
wip
seanmarcia 27ab546
Merge feature/device-management-api-keys into beacons branch
seanmarcia 1b77f29
Update beacon UI to use API key system from feature/device-management…
seanmarcia b4cfadd
Fix topic field reference - use 'title' instead of 'name'
seanmarcia b4540fa
Improve API key display and add regeneration feature
seanmarcia fb7b72c
Add document and file count to beacon show page
seanmarcia 16a8485
Wip
seanmarcia ee1549b
Regenerate and Revoke Tokens on Beacon Configuration Admin View
FionaLMcLaren ca83796
Adds Request Spec for Beacons, and route for revoking a Beacon's API
FionaLMcLaren 0a53932
chore(deps): bump bootsnap from 1.20.1 to 1.22.0 (#576)
dependabot[bot] 9056305
chore(deps): bump tailwindcss-rails from 4.3.0 to 4.4.0 (#577)
dependabot[bot] dd6b8e9
chore(deps): bump thruster from 0.1.17 to 0.1.18 (#578)
dependabot[bot] b459b7e
Update Favicon (#563)
seanmarcia b37d46e
Upgrade to Ruby 4.0.1 (#570)
devjona 4727750
Add macOS 15 platform to Gemfile.lock
oatkins8 75f1500
chore(deps-dev): bump brakeman from 8.0.1 to 8.0.2 (#583)
dependabot[bot] 07a9fdf
Tailwind migration cleanup – sidebar (#584)
hydrognomik 10a48ea
Fixing error - turns out did not call `set_beacon` for `revoke_key`
FionaLMcLaren 3954d6e
Gets rid of the redundant specs in the `Beacon` request spec
FionaLMcLaren c125a91
Merge branch 'main' into beacons-regenerate
FionaLMcLaren a24368c
Review changes
FionaLMcLaren 8dd9f8e
Review changes
FionaLMcLaren c595113
More review changes
FionaLMcLaren 99069e6
Review changes:
FionaLMcLaren a1d7031
Merge branch 'main' into beacons-regenerate
dmitrytrager 2c5ffc1
rescue from StandardError in beacons controller
dmitrytrager 107c2de
eliminate beacons helper, use method from model
dmitrytrager d6a6a4e
move beacons out of redundant beacons module
dmitrytrager d2e4b6f
fix(beacons): use explicit click event in Stimulus action descriptor
dmitrytrager 04aa30e
feat(beacons): filter topics and providers based on selected language…
dmitrytrager b07c42f
fix: resolve code style issues
dmitrytrager File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| class BeaconsController < ApplicationController | ||
| include Authentication | ||
|
|
||
| before_action :set_beacon, only: %i[show edit update regenerate_key revoke_key] | ||
| before_action :prepare_associations, only: %i[new edit] | ||
|
|
||
| def index | ||
| @beacons = Beacon.includes(:language, :region, :providers, :topics).order(created_at: :desc) | ||
| end | ||
|
|
||
| def new | ||
| @beacon = Beacon.new | ||
| end | ||
|
|
||
| def create | ||
| success, @beacon, api_key = Beacons::Creator.new.call(beacon_params) | ||
|
|
||
| if success | ||
| flash[:notice] = "Beacon was successfully provisioned. API Key: #{api_key}" | ||
| redirect_to beacon_path(@beacon, api_key: api_key) | ||
| else | ||
| prepare_associations | ||
| render :new, status: :unprocessable_entity | ||
| end | ||
| end | ||
|
|
||
| def show; end | ||
|
|
||
| def edit; end | ||
|
|
||
| def update | ||
| if @beacon.update(beacon_params) | ||
| redirect_to @beacon, notice: "Beacon was successfully updated." | ||
| else | ||
| prepare_associations | ||
| render :edit, status: :unprocessable_entity | ||
| end | ||
| end | ||
|
|
||
| def regenerate_key | ||
| _, api_key = Beacons::KeyRegenerator.new.call(@beacon) | ||
| flash[:notice] = "API key has been successfully regenerated. API Key: #{api_key}" | ||
| redirect_to beacon_path(@beacon, api_key: api_key) | ||
|
|
||
| rescue => StandardError | ||
| flash[:alert] = "API key could not be regenerated." | ||
| redirect_to @beacon | ||
| end | ||
|
|
||
| def filter_options | ||
| topics = if params[:language_id].present? | ||
| Topic.active.where(language_id: params[:language_id]).order(:title) | ||
| else | ||
| Topic.active.order(:title) | ||
| end | ||
|
|
||
| providers = if params[:region_id].present? | ||
| Provider.joins(:branches).where(branches: { region_id: params[:region_id] }).distinct.order(:name) | ||
| else | ||
| Provider.order(:name) | ||
| end | ||
|
|
||
| render json: { | ||
| topics: topics.select(:id, :title), | ||
| providers: providers.select(:id, :name), | ||
| } | ||
| end | ||
|
|
||
| def revoke_key | ||
| api_key = @beacon.revoke! | ||
| flash[:notice] = "API key has been successfully revoked." | ||
| redirect_to @beacon | ||
|
|
||
| rescue => StandardError | ||
| flash[:alert] = "API key could not be revoked." | ||
| redirect_to @beacon | ||
| end | ||
|
|
||
| def non_contributor_redirect_path | ||
| root_path | ||
| end | ||
|
|
||
| private | ||
|
|
||
| def set_beacon | ||
| @beacon = Beacon.find(params[:id]) | ||
| end | ||
|
|
||
| def prepare_associations | ||
| @languages = Language.order(:name) | ||
| @providers = Provider.order(:name) | ||
| @regions = Region.order(:name) | ||
| @topics = Topic.active.order(:title) | ||
| end | ||
|
|
||
| def beacon_params | ||
| params.require(:beacon).permit(:name, :language_id, :region_id, provider_ids: [], topic_ids: []) | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| import { Controller } from "@hotwired/stimulus" | ||
| import { get } from "@rails/request.js" | ||
|
|
||
| export default class extends Controller { | ||
| static targets = ["languageSelect", "regionSelect", "topicsSelect", "providersSelect"] | ||
| static values = { filterUrl: String } | ||
|
|
||
| connect() { | ||
| // Defer until select-tags children have initialized their TomSelect instances | ||
| requestAnimationFrame(() => this.fetchOptions()) | ||
| } | ||
|
|
||
| fetchOptions() { | ||
| const params = new URLSearchParams() | ||
| const languageId = this.languageSelectTarget.value | ||
| const regionId = this.regionSelectTarget.value | ||
|
|
||
| if (languageId) params.set("language_id", languageId) | ||
| if (regionId) params.set("region_id", regionId) | ||
|
|
||
| get(`${this.filterUrlValue}?${params}`, { responseKind: "json" }) | ||
| .then(response => response.json) | ||
| .then(data => { | ||
| this.#updateSelect(this.topicsSelectTarget, data.topics, "title") | ||
| this.#updateSelect(this.providersSelectTarget, data.providers, "name") | ||
| }) | ||
| } | ||
|
|
||
| #updateSelect(selectElement, items, textKey) { | ||
| const tomSelect = selectElement.tomselect | ||
| if (!tomSelect) return | ||
|
|
||
| const previousValues = [].concat(tomSelect.getValue()) | ||
|
|
||
| tomSelect.clear(true) | ||
| tomSelect.clearOptions() | ||
|
|
||
| items.forEach(item => { | ||
| tomSelect.addOption({ value: String(item.id), text: item[textKey] }) | ||
| }) | ||
|
|
||
| const stillValidValues = previousValues.filter(v => | ||
| items.some(item => String(item.id) === v) | ||
| ) | ||
| if (stillValidValues.length > 0) { | ||
| tomSelect.setValue(stillValidValues, true) | ||
| } | ||
|
|
||
| tomSelect.refreshOptions(false) | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| import { Controller } from "@hotwired/stimulus" | ||
|
|
||
| export default class extends Controller { | ||
| static targets = ["button", "beaconApiKey"] | ||
|
|
||
| copyApiKey() { | ||
| const apiKey = this.beaconApiKeyTarget.textContent; | ||
|
|
||
| navigator.clipboard.writeText(apiKey).then(() => { | ||
| const button = this.buttonTarget; | ||
| const originalText = button.textContent; | ||
| button.textContent = "Copied!"; | ||
| button.classList.add("text-green-600"); | ||
|
|
||
| setTimeout(() => { | ||
| button.textContent = originalText; | ||
| button.classList.remove("text-green-600"); | ||
| }, 2000); | ||
| }).catch(err => { | ||
| console.error("Failed to copy:", err); | ||
| alert("Failed to copy API key to clipboard"); | ||
| }); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this copy functionality is working (tried locally).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could add to a later ticket, but the user can still see the API Key and manually select, copy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What was the outcome in your case?