-
Notifications
You must be signed in to change notification settings - Fork 8
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
Merged
Merged
Changes from 23 commits
Commits
Show all changes
38 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 6335b2c
Modify docker entrypoint file so that JS changes are dynamic when in
devjona aedb2f8
Merge branch 'main' into beacons-regenerate
FionaLMcLaren bd7ade7
chore(deps): bump rails from 8.1.2.1 to 8.1.3
dependabot[bot] 25c04e4
chore(deps): bump thruster from 0.1.19 to 0.1.20
dependabot[bot] 9ca0581
Merge branch 'main' into beacons-regenerate
dmitrytrager 77669fd
- Format some HTML
devjona 0b8672f
Merge branch 'main' into beacons-regenerate
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| module Beacons | ||
| class BaseController < ApplicationController | ||
| before_action :redirect_contributors | ||
|
|
||
| private | ||
|
|
||
| def redirect_contributors | ||
| redirect_to root_path, alert: "You don't have permission to access this page." unless Current.user&.is_admin? | ||
| end | ||
| 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| module Beacons | ||
| class BeaconsController < BaseController | ||
| 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 | ||
| 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 = @beacon.regenerate | ||
| flash[:notice] = "API key has been successfully regenerated. API Key: #{api_key}" | ||
| redirect_to @beacon | ||
|
|
||
| rescue => e | ||
| flash[:alert] = "API key could not be regenerated." | ||
| redirect_to @beacon | ||
| end | ||
|
|
||
| def revoke_key | ||
| api_key = @beacon.revoke! | ||
| flash[:notice] = "API key has been successfully revoked." | ||
| redirect_to @beacon | ||
|
|
||
| rescue => e | ||
| flash[:alert] = "API key could not be revoked." | ||
| redirect_to @beacon | ||
| 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 | ||
| 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,128 @@ | ||
| <%= form_with model: beacon, local: true do |form| %> | ||
| <% if beacon.errors.any? %> | ||
| <div class="bg-red-50 border border-red-200 rounded-lg p-4 mb-6"> | ||
| <div class="flex"> | ||
| <div class="flex-shrink-0"> | ||
| <svg class="h-5 w-5 text-red-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | ||
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/> | ||
| </svg> | ||
| </div> | ||
| <div class="ml-3"> | ||
| <h3 class="text-sm font-medium text-red-800"> | ||
| <%= pluralize(beacon.errors.count, "error") %> prohibited this beacon from being saved: | ||
| </h3> | ||
| <div class="mt-2 text-sm text-red-700"> | ||
| <ul class="list-disc pl-5 space-y-1"> | ||
| <% beacon.errors.full_messages.each do |message| %> | ||
| <li><%= message %></li> | ||
| <% end %> | ||
| </ul> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| <% end %> | ||
|
|
||
| <div class="form-grid"> | ||
| <!-- Basic Information Section --> | ||
| <div class="form-grid-full"> | ||
| <h3 class="text-lg font-semibold text-gray-900 mb-4 pb-2 border-b border-gray-200">Basic Information</h3> | ||
| </div> | ||
|
|
||
| <div> | ||
| <%= form.label :name, class: "form-label" do %> | ||
| Beacon Name | ||
| <span class="form-required">*</span> | ||
| <% end %> | ||
| <%= form.text_field :name, class: "form-input", placeholder: "e.g., Kampala-Central", required: true %> | ||
| <p class="form-help-text">A descriptive name for this beacon deployment</p> | ||
| </div> | ||
|
|
||
| <!-- Document Access Filters Section --> | ||
| <div class="form-grid-full"> | ||
| <h3 class="text-lg font-semibold text-gray-900 mb-4 pb-2 border-b border-gray-200 mt-4"> | ||
| Document Access Filters | ||
| </h3> | ||
| <p class="text-sm text-gray-600 mb-4"> | ||
| Select which documents this beacon can access. Leave filters blank to allow access to all documents. | ||
| </p> | ||
| </div> | ||
|
|
||
| <div> | ||
| <%= form.label :language_id, "Language", class: "form-label" do %> | ||
| Language | ||
| <span class="form-required">*</span> | ||
| <% end %> | ||
| <div style="position:relative;"> | ||
| <%= form.select :language_id, | ||
| options_from_collection_for_select(@languages, :id, :name, beacon.language_id), | ||
| { include_blank: "Select a language" }, | ||
| class: "form-select", required: true %> | ||
| <%= render "shared/dropdown_arrow" %> | ||
| </div> | ||
| <p class="form-help-text">Language for documents this beacon will access</p> | ||
| </div> | ||
|
|
||
| <div> | ||
| <%= form.label :region_id, "Region", class: "form-label" do %> | ||
| Region | ||
| <span class="form-required">*</span> | ||
| <% end %> | ||
| <div style="position:relative;"> | ||
| <%= form.select :region_id, | ||
| options_from_collection_for_select(@regions, :id, :name, beacon.region_id), | ||
| { include_blank: "Select a region" }, | ||
| class: "form-select", required: true %> | ||
| <%= render "shared/dropdown_arrow" %> | ||
| </div> | ||
| <p class="form-help-text">Geographic region for this beacon</p> | ||
| </div> | ||
|
|
||
| <div class="form-grid-full" data-controller="select-tags" data-select-tags-dropdown-parent-value="body"> | ||
| <%= form.label :provider_ids, "Providers", class: "form-label" %> | ||
| <%= form.select :provider_ids, | ||
| options_from_collection_for_select(@providers, :id, :name, beacon.provider_ids), | ||
| { prompt: "Start typing to select providers", include_blank: true }, | ||
| { multiple: true, | ||
| data: { | ||
| "allow-new": "false", | ||
| "allow-clear": "true", | ||
| "select-tags-target": "tagList", | ||
| "dropdown-parent": "body" | ||
| } | ||
| } %> | ||
| <p class="form-help-text">Select which content providers this beacon can access</p> | ||
| </div> | ||
|
|
||
| <div class="form-grid-full" data-controller="select-tags" data-select-tags-dropdown-parent-value="body"> | ||
| <%= form.label :topic_ids, "Topics", class: "form-label" %> | ||
| <%= form.select :topic_ids, | ||
| options_from_collection_for_select(@topics, :id, :title, beacon.topic_ids), | ||
| { prompt: "Start typing to select topics", include_blank: true }, | ||
| { multiple: true, | ||
| data: { | ||
| "allow-new": "false", | ||
| "allow-clear": "true", | ||
| "select-tags-target": "tagList", | ||
| "dropdown-parent": "body" | ||
| } | ||
| } %> | ||
| <p class="form-help-text">Select which topics this beacon can access. Leave blank to allow access to all topics.</p> | ||
| </div> | ||
| </div> | ||
|
|
||
| <!-- Action Buttons --> | ||
| <div class="flex justify-between items-center pt-8 border-t border-gray-100 mt-8"> | ||
| <div class="flex gap-4"> | ||
| <%= form.submit beacon.persisted? ? "Update Beacon" : "Provision Beacon", class: "bg-gradient-green text-white font-semibold py-3 px-8 rounded-lg border-0 cursor-pointer text-sm shadow-md transition-all hover:-translate-y-0.5" %> | ||
| <%= link_to "Back to Beacons", beacons_path, | ||
| class: "bg-gray-100 text-gray-500 font-semibold py-3 px-8 rounded-lg no-underline text-sm transition-all hover:bg-gray-200" %> | ||
| </div> | ||
|
|
||
| <% if beacon.persisted? %> | ||
| <div class="text-gray-500 text-xs"> | ||
| Last updated: <%= beacon.updated_at.strftime("%B %d, %Y at %I:%M %p") %> | ||
| </div> | ||
| <% end %> | ||
| </div> | ||
| <% 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| <% content_for :title, "Edit Beacon" %> | ||
|
|
||
| <div class="bg-gradient-page page-container"> | ||
| <div class="content-wrapper"> | ||
|
|
||
| <!-- Header Section --> | ||
| <div class="section-spacing"> | ||
| <div class="flex items-center gap-4 mb-6"> | ||
| <%= link_to beacon_path(@beacon), class: "text-gray-500 hover:text-gray-700 transition-colors" do %> | ||
| <svg class="icon-size-lg" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | ||
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/> | ||
| </svg> | ||
| <% end %> | ||
| <h1 class="text-3xl font-bold text-gray-800 m-0"> | ||
| Edit Beacon | ||
| </h1> | ||
| </div> | ||
|
|
||
| <!-- Breadcrumb --> | ||
| <nav class="breadcrumb-nav"> | ||
| <ol class="breadcrumb-list"> | ||
| <li><%= link_to "Dashboard", root_path, class: "text-gray-500 no-underline hover:text-gray-700" %></li> | ||
| <li class="breadcrumb-separator">/</li> | ||
| <li><%= link_to "Beacons", beacons_path, class: "text-gray-500 no-underline hover:text-gray-700" %></li> | ||
| <li class="breadcrumb-separator">/</li> | ||
| <li><%= link_to @beacon.name, beacon_path(@beacon), class: "text-gray-500 no-underline hover:text-gray-700" %></li> | ||
| <li class="breadcrumb-separator">/</li> | ||
| <li class="breadcrumb-current">Edit</li> | ||
| </ol> | ||
| </nav> | ||
| </div> | ||
|
|
||
| <!-- Main Form Card --> | ||
| <div class="card-elevated" style="overflow: visible;"> | ||
| <!-- Form Content --> | ||
| <div class="card-body"> | ||
| <%= render "form", beacon: @beacon %> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </div> |
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.
Uh oh!
There was an error while loading. Please reload this page.