diff --git a/Gemfile b/Gemfile
index da197c2..5b552a4 100644
--- a/Gemfile
+++ b/Gemfile
@@ -133,4 +133,7 @@ gem "foreman", "~> 0.87.2"
gem "mass_encryption", "~> 0.1.1"
gem "console1984"
+
gem "audits1984"
+
+gem "local_time", "~> 3.0"
diff --git a/Gemfile.lock b/Gemfile.lock
index c51043b..119cb90 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -184,6 +184,7 @@ GEM
listen (3.8.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
+ local_time (3.0.2)
loofah (2.22.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
@@ -490,6 +491,7 @@ DEPENDENCIES
foreman (~> 0.87.2)
importmap-rails (~> 1.2)
jbuilder
+ local_time (~> 3.0)
mass_encryption (~> 0.1.1)
mission_control-jobs (~> 0.1.1)
pg
diff --git a/app/javascript/application.js b/app/javascript/application.js
index 9d14d68..c254b36 100644
--- a/app/javascript/application.js
+++ b/app/javascript/application.js
@@ -1,5 +1,7 @@
import "controllers"
import "@hotwired/turbo-rails"
+import LocalTime from "local-time"
import "selectlist"
import("selectlist")
+LocalTime.start()
diff --git a/app/javascript/controllers/broadcast_controller.js b/app/javascript/controllers/broadcast_controller.js
new file mode 100644
index 0000000..0662f56
--- /dev/null
+++ b/app/javascript/controllers/broadcast_controller.js
@@ -0,0 +1,15 @@
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ static targets = [ "dialog" ]
+ connect() {
+ console.log("connected")
+ if (!localStorage.getItem(this.dialogTarget.id)) {
+ this.dialogTarget.setAttribute("open","")
+ }
+ }
+
+ close() {
+ localStorage.setItem(this.dialogTarget.id, "closed")
+ }
+}
diff --git a/app/mailers/announcement_mailer.rb b/app/mailers/announcement_mailer.rb
new file mode 100644
index 0000000..1c9724e
--- /dev/null
+++ b/app/mailers/announcement_mailer.rb
@@ -0,0 +1,6 @@
+class AnnouncementMailer < ApplicationMailer
+ default from: "announcements@obl.ong", return_path: "team@obl.ong", message_steam: "broadcast"
+ def announce(user, subject, content)
+ mail(to: user.email, subject: subject, body: content)
+ end
+end
diff --git a/app/models/broadcast.rb b/app/models/broadcast.rb
new file mode 100644
index 0000000..2c2df85
--- /dev/null
+++ b/app/models/broadcast.rb
@@ -0,0 +1,5 @@
+class Broadcast < ApplicationRecord
+ def self.unexpired
+ select { |b| b.expires_at > DateTime.now }
+ end
+end
diff --git a/app/models/broadcast/announcement.rb b/app/models/broadcast/announcement.rb
new file mode 100644
index 0000000..04b3f3a
--- /dev/null
+++ b/app/models/broadcast/announcement.rb
@@ -0,0 +1,9 @@
+class Broadcast::Announcement < Broadcast
+ after_create_commit :announce
+
+ def announce
+ User::User.find_each do |u|
+ AnnouncementMailer.announce(u, subject, content).deliver_later
+ end
+ end
+end
diff --git a/app/models/broadcast/notice.rb b/app/models/broadcast/notice.rb
new file mode 100644
index 0000000..2376eb9
--- /dev/null
+++ b/app/models/broadcast/notice.rb
@@ -0,0 +1,2 @@
+class Broadcast::Notice < Broadcast
+end
diff --git a/app/views/application/_broadcast.html.erb b/app/views/application/_broadcast.html.erb
new file mode 100644
index 0000000..ac18de7
--- /dev/null
+++ b/app/views/application/_broadcast.html.erb
@@ -0,0 +1,34 @@
+
+
+
diff --git a/app/views/layouts/admin.html.erb b/app/views/layouts/admin.html.erb
index 88b8084..8334270 100644
--- a/app/views/layouts/admin.html.erb
+++ b/app/views/layouts/admin.html.erb
@@ -32,6 +32,17 @@
<% end %>
+
+
+
+<% Broadcast.unexpired.each do |b| %>
+ <%= render partial: "application/broadcast", object: b %>
+<% end %>
+
<%= yield_nested %>
diff --git a/config/importmap.rb b/config/importmap.rb
index d22dfb8..295c83d 100644
--- a/config/importmap.rb
+++ b/config/importmap.rb
@@ -9,3 +9,4 @@
pin_all_from "app/javascript"
pin "selectlist", to: "https://esm.sh/selectlist-polyfill@0.3.0", preload: true
pin "cursor-chat", to: "https://esm.sh/gh/obl-ong/cursor-chat-actioncable@9befe0089b/dist/cursor-chat.es.js"
+pin "local-time", to: "https://ga.jspm.io/npm:local-time@3.0.2/app/assets/javascripts/local-time.es2017-esm.js"
diff --git a/db/migrate/20240222163537_create_broadcasts.rb b/db/migrate/20240222163537_create_broadcasts.rb
new file mode 100644
index 0000000..2c4b557
--- /dev/null
+++ b/db/migrate/20240222163537_create_broadcasts.rb
@@ -0,0 +1,11 @@
+class CreateBroadcasts < ActiveRecord::Migration[7.1]
+ def change
+ create_table :broadcasts do |t|
+ t.string :type
+ t.text :content
+ t.datetime :expires_at
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20240222185700_add_broadcast_subject.rb b/db/migrate/20240222185700_add_broadcast_subject.rb
new file mode 100644
index 0000000..5a3a63f
--- /dev/null
+++ b/db/migrate/20240222185700_add_broadcast_subject.rb
@@ -0,0 +1,5 @@
+class AddBroadcastSubject < ActiveRecord::Migration[7.1]
+ def change
+ add_column :broadcasts, :subject, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 95df74f..985b013 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.1].define(version: 2024_02_20_173759) do
+ActiveRecord::Schema[7.1].define(version: 2024_02_22_185700) do
create_table "audits1984_audits", force: :cascade do |t|
t.integer "status", default: 0, null: false
t.text "notes"
@@ -22,6 +22,15 @@
t.index ["session_id"], name: "index_audits1984_audits_on_session_id"
end
+ create_table "broadcasts", force: :cascade do |t|
+ t.string "type"
+ t.text "content"
+ t.datetime "expires_at"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.string "subject"
+ end
+
create_table "console1984_commands", force: :cascade do |t|
t.text "statements"
t.integer "sensitive_access_id"
diff --git a/test/fixtures/broadcast/announcements.yml b/test/fixtures/broadcast/announcements.yml
new file mode 100644
index 0000000..d7a3329
--- /dev/null
+++ b/test/fixtures/broadcast/announcements.yml
@@ -0,0 +1,11 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+# This model initially had no columns defined. If you add columns to the
+# model remove the "{}" from the fixture names and add the columns immediately
+# below each fixture, per the syntax in the comments below
+#
+one: {}
+# column: value
+#
+two: {}
+# column: value
diff --git a/test/fixtures/broadcast/notices.yml b/test/fixtures/broadcast/notices.yml
new file mode 100644
index 0000000..d7a3329
--- /dev/null
+++ b/test/fixtures/broadcast/notices.yml
@@ -0,0 +1,11 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+# This model initially had no columns defined. If you add columns to the
+# model remove the "{}" from the fixture names and add the columns immediately
+# below each fixture, per the syntax in the comments below
+#
+one: {}
+# column: value
+#
+two: {}
+# column: value
diff --git a/test/fixtures/broadcasts.yml b/test/fixtures/broadcasts.yml
new file mode 100644
index 0000000..2ad3ec5
--- /dev/null
+++ b/test/fixtures/broadcasts.yml
@@ -0,0 +1,11 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ type:
+ content: MyText
+ expires_at: 2024-02-22 16:35:37
+
+two:
+ type:
+ content: MyText
+ expires_at: 2024-02-22 16:35:37
diff --git a/test/mailers/announcement_mailer_test.rb b/test/mailers/announcement_mailer_test.rb
new file mode 100644
index 0000000..00d6361
--- /dev/null
+++ b/test/mailers/announcement_mailer_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class AnnouncementMailerTest < ActionMailer::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/mailers/previews/announcement_mailer_preview.rb b/test/mailers/previews/announcement_mailer_preview.rb
new file mode 100644
index 0000000..e8bf073
--- /dev/null
+++ b/test/mailers/previews/announcement_mailer_preview.rb
@@ -0,0 +1,3 @@
+# Preview all emails at http://localhost:3000/rails/mailers/announcement_mailer
+class AnnouncementMailerPreview < ActionMailer::Preview
+end
diff --git a/test/models/broadcast/announcement_test.rb b/test/models/broadcast/announcement_test.rb
new file mode 100644
index 0000000..298837c
--- /dev/null
+++ b/test/models/broadcast/announcement_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class Broadcast::AnnouncementTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/models/broadcast/notice_test.rb b/test/models/broadcast/notice_test.rb
new file mode 100644
index 0000000..dac09b9
--- /dev/null
+++ b/test/models/broadcast/notice_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class Broadcast::NoticeTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/models/broadcast_test.rb b/test/models/broadcast_test.rb
new file mode 100644
index 0000000..cbd522f
--- /dev/null
+++ b/test/models/broadcast_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class BroadcastTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end