diff --git a/config/config.exs b/config/config.exs
index c3983d9..fc9357b 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -23,7 +23,8 @@ config :nulla, NullaWeb.Endpoint,
live_view: [signing_salt: "jcAt5/U+"]
# Snowflake configuration
-config :nulla, :snowflake, worker_id: 1
+config :nulla, :snowflake,
+ worker_id: 1
# Configures the mailer
#
diff --git a/lib/nulla/activitypub.ex b/lib/nulla/activitypub.ex
index ec6332e..019aef8 100644
--- a/lib/nulla/activitypub.ex
+++ b/lib/nulla/activitypub.ex
@@ -304,16 +304,4 @@ defmodule Nulla.ActivityPub do
)
)
end
-
- @spec outbox(String.t(), String.t(), Integer.t()) :: Jason.OrderedObject.t()
- def outbox(domain, username, total) do
- Jason.OrderedObject.new(
- "@context": "https://www.w3.org/ns/activitystreams",
- id: "https://#{domain}/@#{username}/outbox",
- type: "OrderedCollection",
- totalItems: total,
- first: "https://#{domain}/@#{username}/outbox?page=true",
- last: "https://#{domain}/@#{username}/outbox?min_id=0&page=true"
- )
- end
end
diff --git a/lib/nulla/keygen.ex b/lib/nulla/key_gen.ex
similarity index 100%
rename from lib/nulla/keygen.ex
rename to lib/nulla/key_gen.ex
diff --git a/lib/nulla/models/note.ex b/lib/nulla/models/note.ex
index 83e1eb5..efaf328 100644
--- a/lib/nulla/models/note.ex
+++ b/lib/nulla/models/note.ex
@@ -33,9 +33,4 @@ defmodule Nulla.Models.Note do
def get_note!(id), do: Repo.get!(Note, id)
def get_all_notes!(user_id), do: Repo.all(from n in Note, where: n.user_id == ^user_id)
-
- def get_total_notes_count(user_id) do
- from(n in Note, where: n.user_id == ^user_id)
- |> Repo.aggregate(:count, :id)
- end
end
diff --git a/lib/nulla/models/user.ex b/lib/nulla/models/user.ex
index ce1ce22..b3ef7ce 100644
--- a/lib/nulla/models/user.ex
+++ b/lib/nulla/models/user.ex
@@ -1,7 +1,6 @@
defmodule Nulla.Models.User do
use Ecto.Schema
import Ecto.Changeset
- import Ecto.Query
alias Nulla.Repo
alias Nulla.Snowflake
alias Nulla.Models.User
@@ -9,7 +8,6 @@ defmodule Nulla.Models.User do
@primary_key {:id, :integer, autogenerate: false}
schema "users" do
field :username, :string
- field :domain, :string
field :email, :string
field :password, :string
field :is_moderator, :boolean, default: false
@@ -17,7 +15,7 @@ defmodule Nulla.Models.User do
field :bio, :string
field :location, :string
field :birthday, :date
- field :fields, {:array, :map}
+ field :fields, :map
field :tags, {:array, :string}
field :follow_approval, :boolean, default: false
field :is_bot, :boolean, default: false
@@ -28,7 +26,6 @@ defmodule Nulla.Models.User do
field :public_key, :string
field :avatar, :string
field :banner, :string
- field :last_active_at, :utc_datetime
has_many :user_sessions, Nulla.Models.Session
has_many :notes, Nulla.Models.Note
@@ -42,7 +39,6 @@ defmodule Nulla.Models.User do
user
|> cast(attrs, [
:username,
- :domain,
:email,
:password,
:is_moderator,
@@ -59,12 +55,10 @@ defmodule Nulla.Models.User do
:private_key,
:public_key,
:avatar,
- :banner,
- :last_active_at
+ :banner
])
|> validate_required([
:username,
- :domain,
:email,
:password,
:is_moderator,
@@ -81,8 +75,7 @@ defmodule Nulla.Models.User do
:private_key,
:public_key,
:avatar,
- :banner,
- :last_active_at
+ :banner
])
end
@@ -98,23 +91,4 @@ defmodule Nulla.Models.User do
def get_user_by_username(username), do: Repo.get_by(User, username: username)
def get_user_by_username!(username), do: Repo.get_by!(User, username: username)
-
- def get_total_users_count(domain) do
- Repo.aggregate(from(u in User, where: u.domain == ^domain), :count, :id)
- end
-
- def get_active_users_count(domain, days) do
- cutoff = DateTime.add(DateTime.utc_now(), -days * 86400, :second)
-
- from(u in User,
- where: u.domain == ^domain and u.last_active_at > ^cutoff
- )
- |> Repo.aggregate(:count, :id)
- end
-
- def update_last_active(user) do
- user
- |> Ecto.Changeset.change(last_active_at: DateTime.utc_now())
- |> Repo.update()
- end
end
diff --git a/lib/nulla_web/components/templates.ex b/lib/nulla_web/components/templates.ex
index acec111..87fc303 100644
--- a/lib/nulla_web/components/templates.ex
+++ b/lib/nulla_web/components/templates.ex
@@ -3,6 +3,14 @@ defmodule NullaWeb.UserHTML do
embed_templates "templates/user/*"
+ @doc """
+ Renders a user form.
+ """
+ attr :changeset, Ecto.Changeset, required: true
+ attr :action, :string, required: true
+
+ def user_form(assigns)
+
def format_birthdate(date) do
formatted = Date.to_string(date) |> String.replace("-", "/")
age = Timex.diff(Timex.today(), date, :years)
@@ -76,3 +84,17 @@ defmodule NullaWeb.UserHTML do
end
end
end
+
+defmodule NullaWeb.NoteHTML do
+ use NullaWeb, :html
+
+ embed_templates "templates/note/*"
+
+ @doc """
+ Renders a note form.
+ """
+ attr :changeset, Ecto.Changeset, required: true
+ attr :action, :string, required: true
+
+ def note_form(assigns)
+end
diff --git a/lib/nulla_web/components/templates/note/edit.html.heex b/lib/nulla_web/components/templates/note/edit.html.heex
new file mode 100644
index 0000000..3bef388
--- /dev/null
+++ b/lib/nulla_web/components/templates/note/edit.html.heex
@@ -0,0 +1,8 @@
+<.header>
+ Edit Note {@note.id}
+ <:subtitle>Use this form to manage note records in your database.
+
+
+<.note_form changeset={@changeset} action={~p"/notes/#{@note}"} />
+
+<.back navigate={~p"/notes"}>Back to notes
diff --git a/lib/nulla_web/components/templates/note/index.html.heex b/lib/nulla_web/components/templates/note/index.html.heex
new file mode 100644
index 0000000..ffeedbc
--- /dev/null
+++ b/lib/nulla_web/components/templates/note/index.html.heex
@@ -0,0 +1,23 @@
+<.header>
+ Listing Notes
+ <:actions>
+ <.link href={~p"/notes/new"}>
+ <.button>New Note
+
+
+
+
+<.table id="notes" rows={@notes} row_click={&JS.navigate(~p"/notes/#{&1}")}>
+ <:col :let={note} label="Content">{note.content}
+ <:action :let={note}>
+
+ <.link navigate={~p"/notes/#{note}"}>Show
+
+ <.link navigate={~p"/notes/#{note}/edit"}>Edit
+
+ <:action :let={note}>
+ <.link href={~p"/notes/#{note}"} method="delete" data-confirm="Are you sure?">
+ Delete
+
+
+
diff --git a/lib/nulla_web/components/templates/note/new.html.heex b/lib/nulla_web/components/templates/note/new.html.heex
new file mode 100644
index 0000000..4cf47a4
--- /dev/null
+++ b/lib/nulla_web/components/templates/note/new.html.heex
@@ -0,0 +1,8 @@
+<.header>
+ New Note
+ <:subtitle>Use this form to manage note records in your database.
+
+
+<.note_form changeset={@changeset} action={~p"/notes"} />
+
+<.back navigate={~p"/notes"}>Back to notes
diff --git a/lib/nulla_web/components/templates/note/note_form.html.heex b/lib/nulla_web/components/templates/note/note_form.html.heex
new file mode 100644
index 0000000..da6ac0f
--- /dev/null
+++ b/lib/nulla_web/components/templates/note/note_form.html.heex
@@ -0,0 +1,9 @@
+<.simple_form :let={f} for={@changeset} action={@action}>
+ <.error :if={@changeset.action}>
+ Oops, something went wrong! Please check the errors below.
+
+ <.input field={f[:content]} type="text" label="Content" />
+ <:actions>
+ <.button>Save Note
+
+
diff --git a/lib/nulla_web/components/templates/note/show.html.heex b/lib/nulla_web/components/templates/note/show.html.heex
new file mode 100644
index 0000000..d7f2f70
--- /dev/null
+++ b/lib/nulla_web/components/templates/note/show.html.heex
@@ -0,0 +1,15 @@
+<.header>
+ Note {@note.id}
+ <:subtitle>This is a note record from your database.
+ <:actions>
+ <.link href={~p"/notes/#{@note}/edit"}>
+ <.button>Edit note
+
+
+
+
+<.list>
+ <:item title="Content">{@note.content}
+
+
+<.back navigate={~p"/notes"}>Back to notes
diff --git a/lib/nulla_web/components/templates/user/edit.html.heex b/lib/nulla_web/components/templates/user/edit.html.heex
new file mode 100644
index 0000000..2f8aa66
--- /dev/null
+++ b/lib/nulla_web/components/templates/user/edit.html.heex
@@ -0,0 +1,8 @@
+<.header>
+ Edit User {@user.id}
+ <:subtitle>Use this form to manage user records in your database.
+
+
+<.user_form changeset={@changeset} action={~p"/users/#{@user}"} />
+
+<.back navigate={~p"/users"}>Back to users
diff --git a/lib/nulla_web/components/templates/user/index.html.heex b/lib/nulla_web/components/templates/user/index.html.heex
new file mode 100644
index 0000000..9eca5b7
--- /dev/null
+++ b/lib/nulla_web/components/templates/user/index.html.heex
@@ -0,0 +1,23 @@
+<.header>
+ Listing Users
+ <:actions>
+ <.link href={~p"/users/new"}>
+ <.button>New User
+
+
+
+
+<.table id="users" rows={@users} row_click={&JS.navigate(~p"/users/#{&1}")}>
+ <:col :let={user} label="Username">{user.username}
+ <:action :let={user}>
+
+ <.link navigate={~p"/users/#{user}"}>Show
+
+ <.link navigate={~p"/users/#{user}/edit"}>Edit
+
+ <:action :let={user}>
+ <.link href={~p"/users/#{user}"} method="delete" data-confirm="Are you sure?">
+ Delete
+
+
+
diff --git a/lib/nulla_web/components/templates/user/new.html.heex b/lib/nulla_web/components/templates/user/new.html.heex
new file mode 100644
index 0000000..9248fb0
--- /dev/null
+++ b/lib/nulla_web/components/templates/user/new.html.heex
@@ -0,0 +1,8 @@
+<.header>
+ New User
+ <:subtitle>Use this form to manage user records in your database.
+
+
+<.user_form changeset={@changeset} action={~p"/users"} />
+
+<.back navigate={~p"/users"}>Back to users
diff --git a/lib/nulla_web/components/templates/user/user_form.html.heex b/lib/nulla_web/components/templates/user/user_form.html.heex
new file mode 100644
index 0000000..6871618
--- /dev/null
+++ b/lib/nulla_web/components/templates/user/user_form.html.heex
@@ -0,0 +1,9 @@
+<.simple_form :let={f} for={@changeset} action={@action}>
+ <.error :if={@changeset.action}>
+ Oops, something went wrong! Please check the errors below.
+
+ <.input field={f[:username]} type="text" label="Username" />
+ <:actions>
+ <.button>Save User
+
+
diff --git a/lib/nulla_web/controllers/nodeinfo_controller.ex b/lib/nulla_web/controllers/nodeinfo_controller.ex
index 46a3bed..92efc88 100644
--- a/lib/nulla_web/controllers/nodeinfo_controller.ex
+++ b/lib/nulla_web/controllers/nodeinfo_controller.ex
@@ -14,16 +14,11 @@ defmodule NullaWeb.NodeinfoController do
def show(conn, _params) do
version = Application.spec(:nulla, :vsn) |> to_string()
- instance_settings = InstanceSettings.get_instance_settings!()
- domain = instance_settings.domain
- total = User.get_total_users_count(domain)
- month = User.get_active_users_count(domain, 30)
- halfyear = User.get_active_users_count(domain, 180)
users = %{
- total: total,
- month: month,
- halfyear: halfyear
+ total: 0,
+ month: 0,
+ halfyear: 0
}
instance_settings = InstanceSettings.get_instance_settings!()
diff --git a/lib/nulla_web/controllers/outbox_controller.ex b/lib/nulla_web/controllers/outbox_controller.ex
deleted file mode 100644
index 55d13da..0000000
--- a/lib/nulla_web/controllers/outbox_controller.ex
+++ /dev/null
@@ -1,18 +0,0 @@
-defmodule NullaWeb.OutboxController do
- use NullaWeb, :controller
- alias Nulla.ActivityPub
- alias Nulla.Models.User
- alias Nulla.Models.Note
- alias Nulla.Models.InstanceSettings
-
- def show(conn, %{"username" => username}) do
- instance_settings = InstanceSettings.get_instance_settings!()
- domain = instance_settings.domain
- user = User.get_user_by_username!(username)
- total = Note.get_total_notes_count(user.id)
-
- conn
- |> put_resp_content_type("application/activity+json")
- |> send_resp(200, Jason.encode!(ActivityPub.outbox(domain, username, total)))
- end
-end
diff --git a/lib/nulla_web/controllers/user_controller.ex b/lib/nulla_web/controllers/user_controller.ex
index d85d580..a5467e7 100644
--- a/lib/nulla_web/controllers/user_controller.ex
+++ b/lib/nulla_web/controllers/user_controller.ex
@@ -16,7 +16,7 @@ defmodule NullaWeb.UserController do
if accept in ["application/activity+json", "application/ld+json"] do
conn
|> put_resp_content_type("application/activity+json")
- |> send_resp(200, Jason.encode!(ActivityPub.user(domain, user)))
+ |> send_resp(200, ActivityPub.user(domain, user))
else
following = Utils.count_following_by_username!(user.username)
followers = Utils.count_followers_by_username!(user.username)
diff --git a/lib/nulla_web/router.ex b/lib/nulla_web/router.ex
index 6e50c78..ac27911 100644
--- a/lib/nulla_web/router.ex
+++ b/lib/nulla_web/router.ex
@@ -22,7 +22,6 @@ defmodule NullaWeb.Router do
get "/nodeinfo/2.0", NodeinfoController, :show
get "/@:username", UserController, :show
- get "/@:username/outbox", OutboxController, :show
get "/@:username/following", FollowController, :following
get "/@:username/followers", FollowController, :followers
get "/@:username/:note_id", NoteController, :show
diff --git a/priv/repo/migrations/20250530110822_create_users.exs b/priv/repo/migrations/20250530110822_create_users.exs
index 2b48cfa..b597c2f 100644
--- a/priv/repo/migrations/20250530110822_create_users.exs
+++ b/priv/repo/migrations/20250530110822_create_users.exs
@@ -5,7 +5,6 @@ defmodule Nulla.Repo.Migrations.CreateUsers do
create table(:users, primary_key: false) do
add :id, :bigint, primary_key: true
add :username, :string, null: false, unique: true
- add :domain, :string, null: false
add :email, :string
add :password, :string
add :is_moderator, :boolean, default: false, null: false
@@ -13,7 +12,7 @@ defmodule Nulla.Repo.Migrations.CreateUsers do
add :bio, :text
add :location, :string
add :birthday, :date
- add :fields, :jsonb, default: "[]", null: false
+ add :fields, :map
add :tags, {:array, :string}
add :follow_approval, :boolean, default: false, null: false
add :is_bot, :boolean, default: false, null: false
@@ -24,7 +23,6 @@ defmodule Nulla.Repo.Migrations.CreateUsers do
add :public_key, :string, null: false
add :avatar, :string
add :banner, :string
- add :last_active_at, :utc_datetime
timestamps(type: :utc_datetime)
end