Introduce authorizations with Rajska
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
86
lib/graphql/authorization.ex
Normal file
86
lib/graphql/authorization.ex
Normal file
@@ -0,0 +1,86 @@
|
||||
defmodule Mobilizon.GraphQL.Authorization do
|
||||
@moduledoc """
|
||||
Check authorizations
|
||||
"""
|
||||
|
||||
use Rajska,
|
||||
valid_roles: [:user, :moderator, :administrator],
|
||||
super_role: :administrator,
|
||||
default_rule: :default
|
||||
|
||||
alias Mobilizon.Applications.ApplicationToken
|
||||
alias Mobilizon.GraphQL.Authorization.AppScope
|
||||
alias Mobilizon.Users.User
|
||||
import Mobilizon.Web.Gettext, only: [dgettext: 3]
|
||||
|
||||
@impl true
|
||||
def has_user_access?(%User{}, _scope, _rule), do: true
|
||||
|
||||
def has_user_access?(%ApplicationToken{scope: scope} = _current_app_token, _struct, rule)
|
||||
when rule != :forbid_app_access do
|
||||
AppScope.has_app_access?(scope, rule)
|
||||
end
|
||||
|
||||
def has_user_access?(_current_user, _scoped_struct, _rule), do: false
|
||||
|
||||
@impl true
|
||||
def get_current_user(%{current_auth_app_token: app_token}), do: app_token
|
||||
def get_current_user(%{current_user: current_user}), do: current_user
|
||||
def get_current_user(_ctx), do: nil
|
||||
|
||||
@impl true
|
||||
def role_authorized?(_user_role, :all), do: true
|
||||
def role_authorized?(role, _allowed_role) when is_super_role(role), do: true
|
||||
|
||||
def role_authorized?(user_role, allowed_role) when is_atom(user_role) and is_atom(allowed_role),
|
||||
do: user_role === allowed_role
|
||||
|
||||
def role_authorized?(user_role, allowed_roles)
|
||||
when is_atom(user_role) and is_list(allowed_roles),
|
||||
do: user_role in allowed_roles
|
||||
|
||||
@impl true
|
||||
def get_user_role(%ApplicationToken{user: %{role: role}}), do: role
|
||||
def get_user_role(%{role: role}), do: role
|
||||
def get_user_role(nil), do: nil
|
||||
|
||||
@impl true
|
||||
def unauthorized_message(resolution) do
|
||||
case Map.get(resolution.context, :current_user) do
|
||||
nil ->
|
||||
"unauthenticated"
|
||||
|
||||
_ ->
|
||||
"unauthorized"
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def unauthorized_query_scope_message(_resolution, object_type) do
|
||||
dgettext("errors", "Not authorized to access this %{object_type}",
|
||||
object_type: replace_underscore(object_type)
|
||||
)
|
||||
end
|
||||
|
||||
@impl true
|
||||
def unauthorized_object_scope_message(_result_object, object) do
|
||||
dgettext("errors", "Not authorized to access object %{object}", object: object.identifier)
|
||||
end
|
||||
|
||||
@impl true
|
||||
def unauthorized_object_message(_resolution, object) do
|
||||
dgettext("errors", "Not authorized to access object %{object}", object: object.identifier)
|
||||
end
|
||||
|
||||
@impl true
|
||||
def unauthorized_field_message(_resolution, field),
|
||||
do: dgettext("errors", "Not authorized to access field %{field}", field: field)
|
||||
|
||||
defp replace_underscore(string) when is_binary(string), do: String.replace(string, "_", " ")
|
||||
|
||||
defp replace_underscore(atom) when is_atom(atom) do
|
||||
atom
|
||||
|> Atom.to_string()
|
||||
|> replace_underscore()
|
||||
end
|
||||
end
|
||||
118
lib/graphql/authorization/app_scope.ex
Normal file
118
lib/graphql/authorization/app_scope.ex
Normal file
@@ -0,0 +1,118 @@
|
||||
defmodule Mobilizon.GraphQL.Authorization.AppScope do
|
||||
@moduledoc """
|
||||
Module referencing all scopes usable in the Mobilizon API
|
||||
"""
|
||||
|
||||
require Logger
|
||||
|
||||
@global_scope %{
|
||||
"write" => [
|
||||
# Media
|
||||
:"write:media:upload",
|
||||
:"write:media:remove",
|
||||
# Event permissions
|
||||
:"write:event:create",
|
||||
:"write:event:update",
|
||||
:"write:event:delete",
|
||||
# Comment permissions
|
||||
:"write:comment:create",
|
||||
:"write:comment:update",
|
||||
:"write:comment:delete",
|
||||
# Event participation permission
|
||||
:"write:participation",
|
||||
# User account permissions
|
||||
:"write:user:settings",
|
||||
:"write:user:setting:activity",
|
||||
:"write:user:setting:push",
|
||||
# Profile permissions
|
||||
:"write:profile:create",
|
||||
:"write:profile:update",
|
||||
:"write:profile:delete",
|
||||
:"write:profile:feed_token:create",
|
||||
:"write:feed_token:delete",
|
||||
# Membership permissions
|
||||
:"write:group_membership",
|
||||
# Group permissions
|
||||
:"write:group:create",
|
||||
:"write:group:update",
|
||||
:"write:group:delete",
|
||||
# Group discussions permissions
|
||||
:"write:group:discussion:create",
|
||||
:"write:group:discussion:update",
|
||||
:"write:group:discussion:delete",
|
||||
# Group resources permissions
|
||||
:"write:group:resources:create",
|
||||
:"write:group:resources:update",
|
||||
:"write:group:resources:delete",
|
||||
# Group members
|
||||
:"write:group:members",
|
||||
# Post permissions
|
||||
:"write:group:post:create",
|
||||
:"write:group:post:update",
|
||||
:"write:group:post:delete"
|
||||
],
|
||||
"read" => [
|
||||
:"read:event",
|
||||
:"read:event:participants",
|
||||
:"read:event:participants:export",
|
||||
:"read:user:settings",
|
||||
# Profile permissions
|
||||
:"read:profile",
|
||||
:"read:profile:organized_events",
|
||||
:"read:profile:participations",
|
||||
:"read:profile:memberships",
|
||||
:"read:profile:follows",
|
||||
# Group details permissions
|
||||
:"read:group",
|
||||
:"read:group:events",
|
||||
:"read:group:discussions",
|
||||
:"read:group:resources",
|
||||
:"read:group:members",
|
||||
:"read:group:followers",
|
||||
:"read:group:todo_lists",
|
||||
:"read:group:activities"
|
||||
]
|
||||
}
|
||||
|
||||
@spec get_scopes :: list(atom())
|
||||
def get_scopes do
|
||||
@global_scope
|
||||
|> Map.values()
|
||||
|> Enum.concat()
|
||||
|> Enum.concat([:read, :write])
|
||||
end
|
||||
|
||||
@spec scopes_valid?(String.t()) :: boolean()
|
||||
def scopes_valid?(scopes) do
|
||||
scopes
|
||||
|> String.split(" ")
|
||||
|> Enum.all?(&scope_valid?/1)
|
||||
end
|
||||
|
||||
@spec scope_valid?(String.t() | atom()) :: boolean()
|
||||
def scope_valid?(scope) when is_binary(scope) do
|
||||
scope in Enum.map(get_scopes(), &to_string/1)
|
||||
end
|
||||
|
||||
def scope_valid?(scope) when is_atom(scope) do
|
||||
scope in get_scopes()
|
||||
end
|
||||
|
||||
@spec has_app_access?(binary, atom | binary) :: boolean
|
||||
def has_app_access?(scope, rule) do
|
||||
Logger.debug("Has app token access? scope: #{inspect(scope)}, rule: #{inspect(rule)}")
|
||||
scope = String.split(scope, " ")
|
||||
scope_acceptable_for_rule?(scope, rule) or global_scopes_acceptable_for_rule?(scope, rule)
|
||||
end
|
||||
|
||||
@spec scope_acceptable_for_rule?(list(String.t() | atom()), String.t() | atom()) :: boolean()
|
||||
defp scope_acceptable_for_rule?(scope, rule) when is_list(scope) do
|
||||
to_string(rule) in Enum.map(scope, &to_string/1)
|
||||
end
|
||||
|
||||
defp global_scopes_acceptable_for_rule?(scope, rule),
|
||||
do: Enum.any?(scope, &global_scope_acceptable_for_rule?(&1, rule))
|
||||
|
||||
defp global_scope_acceptable_for_rule?(global_scope, rule),
|
||||
do: scope_acceptable_for_rule?(Map.get(@global_scope, global_scope, []), rule)
|
||||
end
|
||||
@@ -30,6 +30,17 @@ defmodule Mobilizon.GraphQL.Error do
|
||||
handle(reason)
|
||||
end
|
||||
|
||||
# It's unclear why returned errors are now binaries instead of atoms
|
||||
# but we can still convert them back
|
||||
def normalize(string) when is_binary(string) do
|
||||
string
|
||||
|> String.to_existing_atom()
|
||||
|> handle()
|
||||
rescue
|
||||
ArgumentError ->
|
||||
handle(string)
|
||||
end
|
||||
|
||||
# Unhandled errors
|
||||
def normalize(other) do
|
||||
handle(other)
|
||||
@@ -65,6 +76,9 @@ defmodule Mobilizon.GraphQL.Error do
|
||||
end
|
||||
|
||||
defp handle(reason) when is_binary(reason) do
|
||||
Logger.debug("Unknown error")
|
||||
Logger.debug(reason)
|
||||
|
||||
%Error{
|
||||
code: :unknown_error,
|
||||
message: reason,
|
||||
@@ -101,6 +115,11 @@ defmodule Mobilizon.GraphQL.Error do
|
||||
defp metadata(:group_not_found), do: {404, dgettext("errors", "Group not found")}
|
||||
defp metadata(:resource_not_found), do: {404, dgettext("errors", "Resource not found")}
|
||||
defp metadata(:discussion_not_found), do: {404, dgettext("errors", "Discussion not found")}
|
||||
defp metadata(:application_not_found), do: {404, dgettext("errors", "Application not found")}
|
||||
|
||||
defp metadata(:application_token_not_found),
|
||||
do: {404, dgettext("errors", "Application token not found")}
|
||||
|
||||
defp metadata(:unknown), do: {500, dgettext("errors", "Something went wrong")}
|
||||
|
||||
defp metadata(code) do
|
||||
|
||||
@@ -12,7 +12,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Application do
|
||||
require Logger
|
||||
|
||||
@doc """
|
||||
Create an application
|
||||
Authorize an application
|
||||
"""
|
||||
@spec authorize(any(), map(), Absinthe.Resolution.t()) :: {:ok, map()} | {:error, String.t()}
|
||||
def authorize(
|
||||
@@ -21,8 +21,16 @@ defmodule Mobilizon.GraphQL.Resolvers.Application do
|
||||
%{context: %{current_user: %User{id: user_id}}}
|
||||
) do
|
||||
case Applications.autorize(client_id, redirect_uri, scope, user_id) do
|
||||
{:ok, code} ->
|
||||
{:ok, %{code: code, state: state}}
|
||||
{:ok,
|
||||
%ApplicationToken{
|
||||
application: %Application{client_id: client_id},
|
||||
scope: scope,
|
||||
authorization_code: code
|
||||
}} ->
|
||||
{:ok, %{code: code, state: state, client_id: client_id, scope: scope}}
|
||||
|
||||
{:error, %Ecto.Changeset{} = err} ->
|
||||
{:error, err}
|
||||
|
||||
{:error, :application_not_found} ->
|
||||
{:error,
|
||||
@@ -41,18 +49,18 @@ defmodule Mobilizon.GraphQL.Resolvers.Application do
|
||||
end
|
||||
|
||||
def authorize(_parent, _args, _context) do
|
||||
{:error, dgettext("errors", "You need to be logged-in to autorize applications")}
|
||||
{:error, :unauthenticated}
|
||||
end
|
||||
|
||||
@spec get_application(any(), map(), Absinthe.Resolution.t()) ::
|
||||
{:ok, Application.t()} | {:error, :not_found | :unauthenticated}
|
||||
{:ok, Application.t()} | {:error, :application_not_found | :unauthenticated}
|
||||
def get_application(_parent, %{client_id: client_id}, %{context: %{current_user: %User{}}}) do
|
||||
case ApplicationManager.get_application_by_client_id(client_id) do
|
||||
%Application{} = application ->
|
||||
{:ok, application}
|
||||
|
||||
nil ->
|
||||
{:error, :not_found}
|
||||
{:error, :application_not_found}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -82,7 +90,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Application do
|
||||
end
|
||||
|
||||
_ ->
|
||||
{:error, :not_found}
|
||||
{:error, :application_token_not_found}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -93,29 +101,53 @@ defmodule Mobilizon.GraphQL.Resolvers.Application do
|
||||
def activate_device(_parent, %{user_code: user_code}, %{
|
||||
context: %{current_user: %User{} = user}
|
||||
}) do
|
||||
with {:ok, %ApplicationDeviceActivation{} = app_device_activation} <-
|
||||
Applications.activate_device(user_code, user) do
|
||||
{:ok, app_device_activation |> Map.from_struct() |> Map.take([:application, :id, :scope])}
|
||||
case Applications.activate_device(user_code, user) do
|
||||
{:ok, %ApplicationDeviceActivation{} = app_device_activation} ->
|
||||
{:ok, app_device_activation |> Map.from_struct() |> Map.take([:application, :id, :scope])}
|
||||
|
||||
{:error, :expired} ->
|
||||
{:error, dgettext("errors", "The given user code has expired")}
|
||||
|
||||
{:error, :not_found} ->
|
||||
{:error, dgettext("errors", "The given user code is invalid")}
|
||||
end
|
||||
end
|
||||
|
||||
def activate_device(_parent, _args, _resolution) do
|
||||
{:error, :unauthenticated}
|
||||
end
|
||||
|
||||
@spec authorize_device_application(any(), map(), Absinthe.Resolution.t()) ::
|
||||
{:ok, map()} | {:error, String.t()}
|
||||
def authorize_device_application(
|
||||
_parent,
|
||||
%{client_id: client_id, user_code: user_code},
|
||||
%{context: %{current_user: %User{id: user_id}}}
|
||||
%{context: %{current_user: %User{}}}
|
||||
) do
|
||||
case Applications.autorize_device_application(client_id, user_code, user_id) do
|
||||
{:ok, %Application{} = app} ->
|
||||
case Applications.autorize_device_application(client_id, user_code) do
|
||||
{:ok, %ApplicationDeviceActivation{application: app}} ->
|
||||
{:ok, app}
|
||||
|
||||
{:error, :application_not_found} ->
|
||||
{:error, :not_confirmed} ->
|
||||
{:error,
|
||||
dgettext(
|
||||
"errors",
|
||||
"No application with this client_id was found"
|
||||
"The device user code was not provided before approving the application"
|
||||
)}
|
||||
|
||||
{:error, :not_found} ->
|
||||
{:error,
|
||||
dgettext(
|
||||
"errors",
|
||||
"The given user code is invalid"
|
||||
)}
|
||||
|
||||
{:error, :expired} ->
|
||||
{:error, dgettext("errors", "The given user code has expired")}
|
||||
end
|
||||
end
|
||||
|
||||
def authorize_device_application(_parent, _args, _resolution) do
|
||||
{:error, :unauthenticated}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -44,7 +44,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Media do
|
||||
def upload_media(
|
||||
_parent,
|
||||
%{file: %Plug.Upload{} = file} = args,
|
||||
%{context: %{current_actor: %Actor{id: actor_id}}}
|
||||
%{context: %{current_actor: %Actor{id: default_actor_id}}}
|
||||
) do
|
||||
with {:ok,
|
||||
%{
|
||||
@@ -62,7 +62,7 @@ defmodule Mobilizon.GraphQL.Resolvers.Media do
|
||||
{:ok, media = %Media{}} <-
|
||||
Medias.create_media(%{
|
||||
file: args,
|
||||
actor_id: actor_id,
|
||||
actor_id: Map.get(args, :actor_id, default_actor_id),
|
||||
metadata: Map.take(uploaded, [:width, :height, :blurhash])
|
||||
}) do
|
||||
{:ok, transform_media(media)}
|
||||
|
||||
@@ -20,8 +20,8 @@ defmodule Mobilizon.GraphQL.Schema do
|
||||
alias Mobilizon.Actors.{Actor, Follower, Member}
|
||||
alias Mobilizon.Discussions.Comment
|
||||
alias Mobilizon.Events.{Event, Participant}
|
||||
alias Mobilizon.GraphQL.{Authorization, Schema}
|
||||
alias Mobilizon.GraphQL.Middleware.{CurrentActorProvider, ErrorHandler, OperationNameLogger}
|
||||
alias Mobilizon.GraphQL.Schema
|
||||
alias Mobilizon.GraphQL.Schema.Custom
|
||||
alias Mobilizon.Storage.Repo
|
||||
|
||||
@@ -57,11 +57,13 @@ defmodule Mobilizon.GraphQL.Schema do
|
||||
|
||||
@desc "A struct containing the id of the deleted object"
|
||||
object :deleted_object do
|
||||
meta(:authorize, :all)
|
||||
field(:id, :id)
|
||||
end
|
||||
|
||||
@desc "A JWT and the associated user ID"
|
||||
object :login do
|
||||
meta(:authorize, :all)
|
||||
field(:access_token, non_null(:string), description: "A JWT Token for this session")
|
||||
|
||||
field(:refresh_token, non_null(:string),
|
||||
@@ -75,6 +77,7 @@ defmodule Mobilizon.GraphQL.Schema do
|
||||
Represents a notification for an user
|
||||
"""
|
||||
object :notification do
|
||||
meta(:authorize, :user)
|
||||
field(:id, :id, description: "The notification ID")
|
||||
field(:user, :user, description: "The user to transmit the notification to")
|
||||
field(:actor, :actor, description: "The notification target profile")
|
||||
@@ -133,7 +136,9 @@ defmodule Mobilizon.GraphQL.Schema do
|
||||
|> Dataloader.add_source(Resources, default_source)
|
||||
|> Dataloader.add_source(Todos, default_source)
|
||||
|
||||
Map.put(ctx, :loader, loader)
|
||||
ctx
|
||||
|> Map.put(:loader, loader)
|
||||
|> Map.put(:authorization, Authorization)
|
||||
end
|
||||
|
||||
def plugins do
|
||||
@@ -201,11 +206,19 @@ defmodule Mobilizon.GraphQL.Schema do
|
||||
end
|
||||
|
||||
@spec middleware(list(module()), any(), map()) :: list(module())
|
||||
def middleware(middleware, _field, %{identifier: type}) when type in [:query, :mutation] do
|
||||
[CurrentActorProvider] ++ middleware ++ [ErrorHandler, OperationNameLogger]
|
||||
def middleware(middleware, field, %{identifier: type}) when type in [:query, :mutation] do
|
||||
[CurrentActorProvider | middleware]
|
||||
|> Enum.map(&fix_middleware_format_for_rajska/1)
|
||||
|> Rajska.add_query_authorization(field, Authorization)
|
||||
|> Rajska.add_object_authorization()
|
||||
|> List.insert_at(-1, ErrorHandler)
|
||||
|> List.insert_at(-1, OperationNameLogger)
|
||||
end
|
||||
|
||||
def middleware(middleware, _field, _object) do
|
||||
middleware
|
||||
def middleware(middleware, field, object) do
|
||||
Rajska.add_field_authorization(middleware, field, object)
|
||||
end
|
||||
|
||||
defp fix_middleware_format_for_rajska({mod, config}), do: {mod, config}
|
||||
defp fix_middleware_format_for_rajska(mod), do: {mod, nil}
|
||||
end
|
||||
|
||||
@@ -25,11 +25,13 @@ defmodule Mobilizon.GraphQL.Schema.ActivityType do
|
||||
end
|
||||
|
||||
object :activity_param_item do
|
||||
meta(:authorize, :user)
|
||||
field(:key, :string)
|
||||
field(:value, :string)
|
||||
end
|
||||
|
||||
interface :activity_object do
|
||||
meta(:authorize, :user)
|
||||
field(:id, :id)
|
||||
|
||||
resolve_type(fn
|
||||
@@ -66,11 +68,13 @@ defmodule Mobilizon.GraphQL.Schema.ActivityType do
|
||||
A paginated list of activity items
|
||||
"""
|
||||
object :paginated_activity_list do
|
||||
meta(:authorize, :user)
|
||||
field(:elements, list_of(:activity), description: "A list of activities")
|
||||
field(:total, :integer, description: "The total number of elements in the list")
|
||||
end
|
||||
|
||||
object :activity do
|
||||
meta(:authorize, :user)
|
||||
field(:id, :id, description: "The activity item ID")
|
||||
field(:inserted_at, :datetime, description: "When was the activity inserted")
|
||||
field(:priority, :integer)
|
||||
|
||||
@@ -13,6 +13,7 @@ defmodule Mobilizon.GraphQL.Schema.ActorInterface do
|
||||
|
||||
@desc "An ActivityPub actor"
|
||||
interface :actor do
|
||||
meta(:authorize, :all)
|
||||
field(:id, :id, description: "Internal ID for this actor")
|
||||
field(:url, :string, description: "The ActivityPub actor's URL")
|
||||
field(:type, :actor_type, description: "The type of Actor (Person, Group,…)")
|
||||
@@ -65,18 +66,21 @@ defmodule Mobilizon.GraphQL.Schema.ActorInterface do
|
||||
@desc "Suspend an actor"
|
||||
field :suspend_profile, :deleted_object do
|
||||
arg(:id, non_null(:id), description: "The remote profile ID to suspend")
|
||||
middleware(Rajska.QueryAuthorization, permit: :moderator, scope: false)
|
||||
resolve(&ActorResolver.suspend_profile/3)
|
||||
end
|
||||
|
||||
@desc "Unsuspend an actor"
|
||||
field :unsuspend_profile, :actor do
|
||||
arg(:id, non_null(:id), description: "The remote profile ID to unsuspend")
|
||||
middleware(Rajska.QueryAuthorization, permit: :moderator, scope: false)
|
||||
resolve(&ActorResolver.unsuspend_profile/3)
|
||||
end
|
||||
|
||||
@desc "Refresh a profile"
|
||||
field :refresh_profile, :actor do
|
||||
arg(:id, non_null(:id), description: "The remote profile ID to refresh")
|
||||
middleware(Rajska.QueryAuthorization, permit: :moderator, scope: false)
|
||||
resolve(&ActorResolver.refresh_profile/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,6 +10,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.ApplicationType do
|
||||
Represents an application
|
||||
"""
|
||||
object :application do
|
||||
meta(:authorize, :all)
|
||||
interfaces([:actor])
|
||||
|
||||
field(:id, :id, description: "Internal ID for this application")
|
||||
|
||||
@@ -9,6 +9,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.FollowerType do
|
||||
Represents an actor's follower
|
||||
"""
|
||||
object :follower do
|
||||
meta(:authorize, :user)
|
||||
field(:id, :id, description: "The follow ID")
|
||||
field(:target_actor, :actor, description: "What or who the profile follows")
|
||||
field(:actor, :actor, description: "Which profile follows")
|
||||
@@ -30,6 +31,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.FollowerType do
|
||||
A paginated list of follower objects
|
||||
"""
|
||||
object :paginated_follower_list do
|
||||
meta(:authorize, :user)
|
||||
field(:elements, list_of(:follower), description: "A list of followers")
|
||||
field(:total, :integer, description: "The total number of elements in the list")
|
||||
end
|
||||
@@ -43,6 +45,8 @@ defmodule Mobilizon.GraphQL.Schema.Actors.FollowerType do
|
||||
description: "Whether the follower has been approved by the target actor or not"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
|
||||
resolve(&Followers.update_follower/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -29,6 +29,9 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
Represents a group of actors
|
||||
"""
|
||||
object :group do
|
||||
meta(:authorize, :all)
|
||||
meta(:scope_field?, true)
|
||||
|
||||
interfaces([:actor, :interactable, :activity_object, :action_log_object, :group_search_result])
|
||||
|
||||
field(:id, :id, description: "Internal ID for this group")
|
||||
@@ -77,7 +80,8 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
)
|
||||
|
||||
# This one should have a privacy setting
|
||||
field :organized_events, :paginated_event_list do
|
||||
field :organized_events, :paginated_event_list,
|
||||
meta: [private: true, rule: :"read:group:events"] do
|
||||
arg(:after_datetime, :datetime,
|
||||
default_value: nil,
|
||||
description: "Filter events that begin after this datetime"
|
||||
@@ -94,7 +98,8 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
description("A list of the events this actor has organized")
|
||||
end
|
||||
|
||||
field :discussions, :paginated_discussion_list do
|
||||
field :discussions, :paginated_discussion_list,
|
||||
meta: [private: true, rule: :"read:group:discussions"] do
|
||||
arg(:page, :integer,
|
||||
default_value: 1,
|
||||
description: "The page in the paginated discussion list"
|
||||
@@ -111,7 +116,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
description: "Whether the group is opened to all or has restricted access"
|
||||
)
|
||||
|
||||
field :members, :paginated_member_list do
|
||||
field :members, :paginated_member_list, meta: [private: true, rule: :"read:group:members"] do
|
||||
arg(:name, :string, description: "A name to filter members by")
|
||||
arg(:page, :integer, default_value: 1, description: "The page in the paginated member list")
|
||||
arg(:limit, :integer, default_value: 10, description: "The limit of members per page")
|
||||
@@ -120,7 +125,8 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
description("A paginated list of group members")
|
||||
end
|
||||
|
||||
field :resources, :paginated_resource_list do
|
||||
field :resources, :paginated_resource_list,
|
||||
meta: [private: true, rule: :"read:group:resources"] do
|
||||
arg(:page, :integer,
|
||||
default_value: 1,
|
||||
description: "The page in the paginated resource list"
|
||||
@@ -138,7 +144,8 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
description("A paginated list of the posts this group has")
|
||||
end
|
||||
|
||||
field :todo_lists, :paginated_todo_list_list do
|
||||
field :todo_lists, :paginated_todo_list_list,
|
||||
meta: [private: true, rule: :"read:group:todo_lists"] do
|
||||
arg(:page, :integer,
|
||||
default_value: 1,
|
||||
description: "The page in the paginated todo-lists list"
|
||||
@@ -149,7 +156,8 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
description("A paginated list of the todo lists this group has")
|
||||
end
|
||||
|
||||
field :followers, :paginated_follower_list do
|
||||
field :followers, :paginated_follower_list,
|
||||
meta: [private: true, rule: :"read:group:followers"] do
|
||||
arg(:page, :integer,
|
||||
default_value: 1,
|
||||
description: "The page in the paginated followers list"
|
||||
@@ -166,7 +174,8 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
description("A paginated list of the followers this group has")
|
||||
end
|
||||
|
||||
field :activity, :paginated_activity_list do
|
||||
field :activity, :paginated_activity_list,
|
||||
meta: [private: true, rule: :"read:group:activities"] do
|
||||
arg(:page, :integer,
|
||||
default_value: 1,
|
||||
description: "The page in the paginated activity items list"
|
||||
@@ -204,6 +213,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
A paginated list of groups
|
||||
"""
|
||||
object :paginated_group_list do
|
||||
meta(:authorize, :all)
|
||||
field(:elements, list_of(:group), description: "A list of groups")
|
||||
field(:total, :integer, description: "The total number of groups in the list")
|
||||
end
|
||||
@@ -215,12 +225,6 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
value(:private, description: "Visible only to people with the link - or invited")
|
||||
end
|
||||
|
||||
object :group_follow do
|
||||
field(:group, :group, description: "The group followed")
|
||||
field(:profile, :group, description: "The group followed")
|
||||
field(:notify, :boolean, description: "Whether to notify profile from group activity")
|
||||
end
|
||||
|
||||
object :group_queries do
|
||||
@desc "Get all groups"
|
||||
field :groups, :paginated_group_list do
|
||||
@@ -236,12 +240,25 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
arg(:suspended, :boolean, default_value: false, description: "Filter by suspended status")
|
||||
arg(:page, :integer, default_value: 1, description: "The page in the paginated group list")
|
||||
arg(:limit, :integer, default_value: 10, description: "The limit of groups per page")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: [:administrator, :moderator],
|
||||
scope: Mobilizon.Actors.Actor,
|
||||
args: %{}
|
||||
)
|
||||
|
||||
resolve(&Group.list_groups/3)
|
||||
end
|
||||
|
||||
@desc "Get a group by its ID"
|
||||
field :get_group, :group do
|
||||
arg(:id, non_null(:id), description: "The group ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: [:administrator, :moderator],
|
||||
scope: Mobilizon.Actors.Actor
|
||||
)
|
||||
|
||||
resolve(&Group.get_group/3)
|
||||
end
|
||||
|
||||
@@ -251,15 +268,9 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
description: "The group preferred_username, eventually containing their domain if remote"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&Group.find_group/3)
|
||||
end
|
||||
|
||||
@desc "Get a group by its preferred username"
|
||||
field :group_by_id, :group do
|
||||
arg(:id, non_null(:id), description: "The group local ID")
|
||||
|
||||
resolve(&Group.find_group_by_id/3)
|
||||
end
|
||||
end
|
||||
|
||||
object :group_mutations do
|
||||
@@ -291,7 +302,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
)
|
||||
|
||||
arg(:physical_address, :address_input, description: "The physical address for the group")
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&Group.create_group/3)
|
||||
end
|
||||
|
||||
@@ -323,14 +334,14 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
)
|
||||
|
||||
arg(:physical_address, :address_input, description: "The physical address for the group")
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&Group.update_group/3)
|
||||
end
|
||||
|
||||
@desc "Delete a group"
|
||||
field :delete_group, :deleted_object do
|
||||
arg(:group_id, non_null(:id), description: "The group ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&Group.delete_group/3)
|
||||
end
|
||||
|
||||
@@ -343,6 +354,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
default_value: true
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&Group.follow_group/3)
|
||||
end
|
||||
|
||||
@@ -355,13 +367,14 @@ defmodule Mobilizon.GraphQL.Schema.Actors.GroupType do
|
||||
default_value: true
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&Group.update_group_follow/3)
|
||||
end
|
||||
|
||||
@desc "Unfollow a group"
|
||||
field :unfollow_group, :follower do
|
||||
arg(:group_id, non_null(:id), description: "The group ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&Group.unfollow_group/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,6 +10,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.MemberType do
|
||||
Represents a member of a group
|
||||
"""
|
||||
object :member do
|
||||
meta(:authorize, :user)
|
||||
interfaces([:activity_object])
|
||||
field(:id, :id, description: "The member's ID")
|
||||
field(:parent, :group, description: "Of which the profile is member")
|
||||
@@ -37,6 +38,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.MemberType do
|
||||
A paginated list of members
|
||||
"""
|
||||
object :paginated_member_list do
|
||||
meta(:authorize, :user)
|
||||
field(:elements, list_of(:member), description: "A list of members")
|
||||
field(:total, :integer, description: "The total number of elements in the list")
|
||||
end
|
||||
@@ -46,6 +48,13 @@ defmodule Mobilizon.GraphQL.Schema.Actors.MemberType do
|
||||
field :join_group, :member do
|
||||
arg(:group_id, non_null(:id), description: "The group ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Actors.Member,
|
||||
rule: :"write:group_membership",
|
||||
args: %{parent_id: :group_id}
|
||||
)
|
||||
|
||||
resolve(&Group.join_group/3)
|
||||
end
|
||||
|
||||
@@ -53,9 +62,42 @@ defmodule Mobilizon.GraphQL.Schema.Actors.MemberType do
|
||||
field :leave_group, :deleted_object do
|
||||
arg(:group_id, non_null(:id), description: "The group ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Actors.Member,
|
||||
rule: :"write:group_membership",
|
||||
args: %{parent_id: :group_id}
|
||||
)
|
||||
|
||||
resolve(&Group.leave_group/3)
|
||||
end
|
||||
|
||||
@desc "Accept an invitation to a group"
|
||||
field :accept_invitation, :member do
|
||||
arg(:id, non_null(:id), description: "The member ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Actors.Member,
|
||||
rule: :"write:group_membership"
|
||||
)
|
||||
|
||||
resolve(&Member.accept_invitation/3)
|
||||
end
|
||||
|
||||
@desc "Reject an invitation to a group"
|
||||
field :reject_invitation, :member do
|
||||
arg(:id, non_null(:id), description: "The member ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Actors.Member,
|
||||
rule: :"write:group_membership"
|
||||
)
|
||||
|
||||
resolve(&Member.reject_invitation/3)
|
||||
end
|
||||
|
||||
@desc "Invite an actor to join the group"
|
||||
field :invite_member, :member do
|
||||
arg(:group_id, non_null(:id), description: "The group ID")
|
||||
@@ -64,29 +106,29 @@ defmodule Mobilizon.GraphQL.Schema.Actors.MemberType do
|
||||
description: "The targeted person's federated username"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Actors.Member,
|
||||
rule: :"write:group:members",
|
||||
args: %{parent_id: :group_id}
|
||||
)
|
||||
|
||||
resolve(&Member.invite_member/3)
|
||||
end
|
||||
|
||||
@desc "Accept an invitation to a group"
|
||||
field :accept_invitation, :member do
|
||||
arg(:id, non_null(:id), description: "The member ID")
|
||||
|
||||
resolve(&Member.accept_invitation/3)
|
||||
end
|
||||
|
||||
@desc "Reject an invitation to a group"
|
||||
field :reject_invitation, :member do
|
||||
arg(:id, non_null(:id), description: "The member ID")
|
||||
|
||||
resolve(&Member.reject_invitation/3)
|
||||
end
|
||||
|
||||
@desc """
|
||||
Approve a membership request
|
||||
"""
|
||||
field :approve_member, :member do
|
||||
arg(:member_id, non_null(:id), description: "The member ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Actors.Member,
|
||||
rule: :"write:group:members",
|
||||
args: %{parent_id: :member_id}
|
||||
)
|
||||
|
||||
resolve(&Member.approve_member/3)
|
||||
end
|
||||
|
||||
@@ -96,6 +138,13 @@ defmodule Mobilizon.GraphQL.Schema.Actors.MemberType do
|
||||
field :reject_member, :member do
|
||||
arg(:member_id, non_null(:id), description: "The member ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Actors.Member,
|
||||
rule: :"write:group:members",
|
||||
args: %{parent_id: :member_id}
|
||||
)
|
||||
|
||||
resolve(&Member.reject_member/3)
|
||||
end
|
||||
|
||||
@@ -106,6 +155,13 @@ defmodule Mobilizon.GraphQL.Schema.Actors.MemberType do
|
||||
arg(:member_id, non_null(:id), description: "The member ID")
|
||||
arg(:role, non_null(:member_role_enum), description: "The new member role")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Actors.Member,
|
||||
rule: :"write:group:members",
|
||||
args: %{parent_id: :member_id}
|
||||
)
|
||||
|
||||
resolve(&Member.update_member/3)
|
||||
end
|
||||
|
||||
@@ -118,6 +174,13 @@ defmodule Mobilizon.GraphQL.Schema.Actors.MemberType do
|
||||
description: "Whether the member should be excluded from the group"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Actors.Member,
|
||||
rule: :"write:group:members",
|
||||
args: %{parent_id: :member_id}
|
||||
)
|
||||
|
||||
resolve(&Member.remove_member/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -16,6 +16,8 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
Represents a person identity
|
||||
"""
|
||||
object :person do
|
||||
meta(:authorize, :all)
|
||||
meta(:scope_field?, true)
|
||||
interfaces([:actor, :action_log_object])
|
||||
field(:id, :id, description: "Internal ID for this person")
|
||||
|
||||
@@ -72,7 +74,8 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
|
||||
# This one should have a privacy setting
|
||||
field(:organized_events, :paginated_event_list,
|
||||
description: "A list of the events this actor has organized"
|
||||
description: "A list of the events this actor has organized",
|
||||
meta: [private: true, rule: :"read:profile:organized_events"]
|
||||
) do
|
||||
arg(:page, :integer, default_value: 1, description: "The page in the paginated event list")
|
||||
arg(:limit, :integer, default_value: 10, description: "The limit of events per page")
|
||||
@@ -81,7 +84,8 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
|
||||
@desc "The list of events this person goes to"
|
||||
field(:participations, :paginated_participant_list,
|
||||
description: "The list of events this person goes to"
|
||||
description: "The list of events this person goes to",
|
||||
meta: [private: true, rule: :"read:profile:participations"]
|
||||
) do
|
||||
arg(:event_id, :id, description: "Filter by event ID")
|
||||
|
||||
@@ -97,7 +101,8 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
|
||||
@desc "The list of groups this person is member of"
|
||||
field(:memberships, :paginated_member_list,
|
||||
description: "The list of group this person is member of"
|
||||
description: "The list of group this person is member of",
|
||||
meta: [private: true, rule: :"read:profile:memberships"]
|
||||
) do
|
||||
arg(:group, :string, description: "Filter by group federated username")
|
||||
arg(:group_id, :id, description: "Filter by group ID")
|
||||
@@ -113,7 +118,8 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
|
||||
@desc "The list of groups this person follows"
|
||||
field(:follows, :paginated_follower_list,
|
||||
description: "The list of groups this person follows"
|
||||
description: "The list of groups this person follows",
|
||||
meta: [private: true, rule: :"read:profile:follows"]
|
||||
) do
|
||||
arg(:group, :string, description: "Filter by group federated username")
|
||||
|
||||
@@ -131,6 +137,7 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
A paginated list of persons
|
||||
"""
|
||||
object :paginated_person_list do
|
||||
meta(:authorize, :all)
|
||||
field(:elements, list_of(:person), description: "A list of persons")
|
||||
field(:total, :integer, description: "The total number of persons in the list")
|
||||
end
|
||||
@@ -138,23 +145,46 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
object :person_queries do
|
||||
@desc "Get the current actor for the logged-in user"
|
||||
field :logged_person, :person do
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Actors.Actor,
|
||||
args: %{}
|
||||
)
|
||||
|
||||
resolve(&Person.get_current_person/3)
|
||||
end
|
||||
|
||||
@desc "Get a person by its (federated) username"
|
||||
field :fetch_person, :person do
|
||||
arg(:preferred_username, non_null(:string), description: "The person's federated username")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Actors.Actor,
|
||||
args: %{preferred_username: :preferred_username}
|
||||
)
|
||||
|
||||
resolve(&Person.fetch_person/3)
|
||||
end
|
||||
|
||||
@desc "Get a person by its ID"
|
||||
field :person, :person do
|
||||
arg(:id, non_null(:id), description: "The person ID")
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&Person.get_person/3)
|
||||
end
|
||||
|
||||
@desc "Get the persons for an user"
|
||||
field :identities, list_of(:person) do
|
||||
deprecate("Use the loggedUser query instead")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: [:user, :moderator, :administrator],
|
||||
scope: Mobilizon.Actors.Actor,
|
||||
args: %{},
|
||||
rule: :user_self_identities
|
||||
)
|
||||
|
||||
resolve(&Person.identities/3)
|
||||
end
|
||||
|
||||
@@ -172,6 +202,13 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
arg(:suspended, :boolean, default_value: false, description: "Filter by suspended status")
|
||||
arg(:page, :integer, default_value: 1, description: "The page in the paginated person list")
|
||||
arg(:limit, :integer, default_value: 10, description: "The limit of persons per page")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: [:administrator, :moderator],
|
||||
scope: Mobilizon.Actors.Actor,
|
||||
args: %{}
|
||||
)
|
||||
|
||||
resolve(&Person.list_persons/3)
|
||||
end
|
||||
end
|
||||
@@ -195,6 +232,13 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
"The banner for the profile, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Actors.Actor,
|
||||
args: %{},
|
||||
rule: :"write:profile:create"
|
||||
)
|
||||
|
||||
resolve(&Person.create_person/3)
|
||||
end
|
||||
|
||||
@@ -216,6 +260,12 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
"The banner for the profile, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Actors.Actor,
|
||||
rule: :"write:profile:update"
|
||||
)
|
||||
|
||||
resolve(&Person.update_person/3)
|
||||
end
|
||||
|
||||
@@ -223,6 +273,12 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
field :delete_person, :person do
|
||||
arg(:id, non_null(:id), description: "The person's ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Actors.Actor,
|
||||
rule: :"write:profile:delete"
|
||||
)
|
||||
|
||||
resolve(&Person.delete_person/3)
|
||||
end
|
||||
|
||||
@@ -245,6 +301,8 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
"The banner for the profile, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :all, scope: Mobilizon.Actors.Actor, args: %{})
|
||||
|
||||
resolve(&Person.register_person/3)
|
||||
end
|
||||
end
|
||||
@@ -254,6 +312,12 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
field :event_person_participation_changed, :person do
|
||||
arg(:person_id, non_null(:id), description: "The person's ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Actors.Actor,
|
||||
args: %{id: :person_id}
|
||||
)
|
||||
|
||||
config(fn args, _ ->
|
||||
{:ok, topic: args.person_id}
|
||||
end)
|
||||
@@ -264,6 +328,12 @@ defmodule Mobilizon.GraphQL.Schema.Actors.PersonType do
|
||||
arg(:person_id, non_null(:id), description: "The person's ID")
|
||||
arg(:group, non_null(:string), description: "The group's federated username")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Actors.Actor,
|
||||
args: %{id: :person_id}
|
||||
)
|
||||
|
||||
config(fn args, _ ->
|
||||
{:ok, topic: [args.group, args.person_id]}
|
||||
end)
|
||||
|
||||
@@ -10,6 +10,7 @@ defmodule Mobilizon.GraphQL.Schema.AddressType do
|
||||
An address object
|
||||
"""
|
||||
object :address do
|
||||
meta(:authorize, :all)
|
||||
field(:geom, :point, description: "The geocoordinates for the point where this address is")
|
||||
field(:street, :string, description: "The address's street name (with number)")
|
||||
field(:locality, :string, description: "The address's locality")
|
||||
@@ -29,6 +30,7 @@ defmodule Mobilizon.GraphQL.Schema.AddressType do
|
||||
A phone address
|
||||
"""
|
||||
object :phone_address do
|
||||
meta(:authorize, :all)
|
||||
field(:phone, :string, description: "The phone number")
|
||||
field(:info, :string, description: "Additional information about the phone number")
|
||||
end
|
||||
@@ -37,11 +39,13 @@ defmodule Mobilizon.GraphQL.Schema.AddressType do
|
||||
An online address
|
||||
"""
|
||||
object :online_address do
|
||||
meta(:authorize, :all)
|
||||
field(:url, :string)
|
||||
field(:info, :string)
|
||||
end
|
||||
|
||||
object :picture_info_element do
|
||||
meta(:authorize, :all)
|
||||
field(:name, :string)
|
||||
field(:url, :string)
|
||||
end
|
||||
@@ -50,6 +54,7 @@ defmodule Mobilizon.GraphQL.Schema.AddressType do
|
||||
A picture associated with an address
|
||||
"""
|
||||
object :picture_info do
|
||||
meta(:authorize, :all)
|
||||
field(:url, :string)
|
||||
field(:author, :picture_info_element)
|
||||
field(:source, :picture_info_element)
|
||||
@@ -100,7 +105,7 @@ defmodule Mobilizon.GraphQL.Schema.AddressType do
|
||||
arg(:limit, :integer, default_value: 10, description: "The limit of search results per page")
|
||||
|
||||
arg(:type, :address_search_type, description: "Filter by type of results")
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&Address.search/3)
|
||||
end
|
||||
|
||||
@@ -115,6 +120,7 @@ defmodule Mobilizon.GraphQL.Schema.AddressType do
|
||||
description: "The user's locale. Geocoding backends will make use of this value."
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&Address.reverse_geocode/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,6 +15,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
|
||||
@desc "An action log"
|
||||
object :action_log do
|
||||
meta(:authorize, :moderator)
|
||||
field(:id, :id, description: "Internal ID for this comment")
|
||||
field(:actor, :actor, description: "The actor that acted")
|
||||
field(:object, :action_log_object, description: "The object that was acted upon")
|
||||
@@ -26,6 +27,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
A paginated list of action logs
|
||||
"""
|
||||
object :paginated_action_log_list do
|
||||
meta(:authorize, :moderator)
|
||||
field(:elements, list_of(:action_log), description: "A list of action logs")
|
||||
field(:total, :integer, description: "The total number of action logs in the list")
|
||||
end
|
||||
@@ -49,6 +51,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
|
||||
@desc "The objects that can be in an action log"
|
||||
interface :action_log_object do
|
||||
meta(:authorize, [:moderator, :administrator])
|
||||
field(:id, :id, description: "Internal ID for this object")
|
||||
|
||||
resolve_type(fn
|
||||
@@ -82,6 +85,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
Language information
|
||||
"""
|
||||
object :language do
|
||||
meta(:authorize, :administrator)
|
||||
field(:code, :string, description: "The iso-639-3 language code")
|
||||
field(:name, :string, description: "The language name")
|
||||
end
|
||||
@@ -90,6 +94,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
Dashboard information
|
||||
"""
|
||||
object :dashboard do
|
||||
meta(:authorize, :administrator)
|
||||
field(:last_public_event_published, :event, description: "Last public event published")
|
||||
field(:last_group_created, :group, description: "Last public group created")
|
||||
field(:number_of_users, :integer, description: "The number of local users")
|
||||
@@ -109,6 +114,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
Admin settings
|
||||
"""
|
||||
object :admin_settings do
|
||||
meta(:authorize, :administrator)
|
||||
field(:instance_name, :string, description: "The instance's name")
|
||||
field(:instance_description, :string, description: "The instance's description")
|
||||
field(:instance_long_description, :string, description: "The instance's long description")
|
||||
@@ -184,6 +190,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
An instance representation
|
||||
"""
|
||||
object :instance do
|
||||
meta(:authorize, :administrator)
|
||||
field(:domain, :id, description: "The domain name of the instance")
|
||||
field(:follower_status, :instance_follow_status, description: "Do we follow this instance")
|
||||
field(:followed_status, :instance_follow_status, description: "Does this instance follow us?")
|
||||
@@ -226,6 +233,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
A paginated list of instances
|
||||
"""
|
||||
object :paginated_instance_list do
|
||||
meta(:authorize, :administrator)
|
||||
field(:elements, list_of(:instance), description: "A list of instances")
|
||||
field(:total, :integer, description: "The total number of instances in the list")
|
||||
end
|
||||
@@ -235,6 +243,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
field :action_logs, type: :paginated_action_log_list do
|
||||
arg(:page, :integer, default_value: 1)
|
||||
arg(:limit, :integer, default_value: 10)
|
||||
middleware(Rajska.QueryAuthorization, permit: :moderator, scope: false)
|
||||
resolve(&Admin.list_action_logs/3)
|
||||
end
|
||||
|
||||
@@ -247,6 +256,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
"The user's locale. The list of languages will be translated with this locale"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&Admin.get_list_of_languages/3)
|
||||
end
|
||||
|
||||
@@ -254,6 +264,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
Get dashboard information
|
||||
"""
|
||||
field :dashboard, type: :dashboard do
|
||||
middleware(Rajska.QueryAuthorization, permit: :administrator)
|
||||
resolve(&Admin.get_dashboard/3)
|
||||
end
|
||||
|
||||
@@ -261,6 +272,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
Get admin settings
|
||||
"""
|
||||
field :admin_settings, type: :admin_settings do
|
||||
middleware(Rajska.QueryAuthorization, permit: :administrator)
|
||||
resolve(&Admin.get_settings/3)
|
||||
end
|
||||
|
||||
@@ -278,6 +290,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
description: "The limit of relay followers per page"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :administrator)
|
||||
resolve(&Admin.list_relay_followers/3)
|
||||
end
|
||||
|
||||
@@ -301,6 +314,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
)
|
||||
|
||||
arg(:direction, :string, default_value: :desc, description: "The sorting direction")
|
||||
middleware(Rajska.QueryAuthorization, permit: :administrator)
|
||||
resolve(&Admin.list_relay_followings/3)
|
||||
end
|
||||
|
||||
@@ -336,6 +350,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
)
|
||||
|
||||
arg(:direction, :string, default_value: :desc, description: "The sorting direction")
|
||||
middleware(Rajska.QueryAuthorization, permit: :administrator)
|
||||
resolve(&Admin.get_instances/3)
|
||||
end
|
||||
|
||||
@@ -344,6 +359,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
"""
|
||||
field :instance, :instance do
|
||||
arg(:domain, non_null(:id), description: "The instance domain")
|
||||
middleware(Rajska.QueryAuthorization, permit: :administrator)
|
||||
resolve(&Admin.get_instance/3)
|
||||
end
|
||||
end
|
||||
@@ -352,28 +368,28 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
@desc "Add an instance subscription"
|
||||
field :add_instance, type: :instance do
|
||||
arg(:domain, non_null(:string), description: "The instance domain to add")
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :administrator)
|
||||
resolve(&Admin.create_instance/3)
|
||||
end
|
||||
|
||||
@desc "Delete a relay subscription"
|
||||
field :remove_relay, type: :follower do
|
||||
arg(:address, non_null(:string), description: "The relay hostname to delete")
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :administrator)
|
||||
resolve(&Admin.remove_relay/3)
|
||||
end
|
||||
|
||||
@desc "Accept a relay subscription"
|
||||
field :accept_relay, type: :follower do
|
||||
arg(:address, non_null(:string), description: "The accepted relay hostname")
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :administrator)
|
||||
resolve(&Admin.accept_subscription/3)
|
||||
end
|
||||
|
||||
@desc "Reject a relay subscription"
|
||||
field :reject_relay, type: :follower do
|
||||
arg(:address, non_null(:string), description: "The rejected relay hostname")
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :administrator)
|
||||
resolve(&Admin.reject_subscription/3)
|
||||
end
|
||||
|
||||
@@ -402,7 +418,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
arg(:instance_rules, :string, description: "The instance's rules")
|
||||
arg(:registrations_open, :boolean, description: "Whether the registrations are opened")
|
||||
arg(:instance_languages, list_of(:string), description: "The instance's languages")
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :administrator)
|
||||
resolve(&Admin.save_settings/3)
|
||||
end
|
||||
|
||||
@@ -420,6 +436,7 @@ defmodule Mobilizon.GraphQL.Schema.AdminType do
|
||||
description: "Whether or not to notify the user of the change"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :administrator)
|
||||
resolve(&Admin.update_user/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,15 +7,17 @@ defmodule Mobilizon.GraphQL.Schema.AuthApplicationType do
|
||||
|
||||
@desc "An application"
|
||||
object :auth_application do
|
||||
meta(:authorize, :user)
|
||||
field(:id, :id)
|
||||
field(:name, :string)
|
||||
field(:client_id, :string)
|
||||
field(:scopes, :string)
|
||||
field(:scope, :string)
|
||||
field(:website, :string)
|
||||
end
|
||||
|
||||
@desc "An application"
|
||||
object :auth_application_token do
|
||||
meta(:authorize, :user)
|
||||
field(:id, :id)
|
||||
field(:inserted_at, :string)
|
||||
field(:last_used_at, :string)
|
||||
@@ -24,11 +26,15 @@ defmodule Mobilizon.GraphQL.Schema.AuthApplicationType do
|
||||
|
||||
@desc "The informations returned after authorization"
|
||||
object :application_code_and_state do
|
||||
meta(:authorize, :user)
|
||||
field(:code, :string)
|
||||
field(:state, :string)
|
||||
field(:client_id, :string)
|
||||
field(:scope, :string)
|
||||
end
|
||||
|
||||
object :application_device_activation do
|
||||
meta(:authorize, :user)
|
||||
field(:id, :id)
|
||||
field(:application, :auth_application)
|
||||
field(:scope, :string)
|
||||
@@ -38,6 +44,14 @@ defmodule Mobilizon.GraphQL.Schema.AuthApplicationType do
|
||||
@desc "Get an application"
|
||||
field :auth_application, :auth_application do
|
||||
arg(:client_id, non_null(:string), description: "The application's client_id")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Applications.Application,
|
||||
rule: :forbid_app_access,
|
||||
args: %{client_id: :client_id}
|
||||
)
|
||||
|
||||
resolve(&Application.get_application/3)
|
||||
end
|
||||
end
|
||||
@@ -51,18 +65,33 @@ defmodule Mobilizon.GraphQL.Schema.AuthApplicationType do
|
||||
description: "The URI to redirect to with the code and state"
|
||||
)
|
||||
|
||||
arg(:scope, :string, description: "The scope for the authorization")
|
||||
arg(:scope, non_null(:string), description: "The scope for the authorization")
|
||||
|
||||
arg(:state, :string,
|
||||
description: "A state parameter to check that the request wasn't altered"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Applications.Application,
|
||||
rule: :forbid_app_access,
|
||||
args: %{client_id: :client_id}
|
||||
)
|
||||
|
||||
resolve(&Application.authorize/3)
|
||||
end
|
||||
|
||||
@desc "Revoke an authorized application"
|
||||
field :revoke_application_token, :deleted_object do
|
||||
arg(:app_token_id, non_null(:string), description: "The application token's ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Applications.ApplicationToken,
|
||||
rule: :forbid_app_access,
|
||||
args: %{id: :app_token_id}
|
||||
)
|
||||
|
||||
resolve(&Application.revoke_application_token/3)
|
||||
end
|
||||
|
||||
@@ -72,13 +101,30 @@ defmodule Mobilizon.GraphQL.Schema.AuthApplicationType do
|
||||
description: "The code provided by the application entered by the user"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Applications.ApplicationDeviceActivation,
|
||||
rule: :forbid_app_access,
|
||||
args: %{id: :user_code}
|
||||
)
|
||||
|
||||
resolve(&Application.activate_device/3)
|
||||
end
|
||||
|
||||
@desc "Activate an user device"
|
||||
field :authorize_device_application, :auth_application do
|
||||
arg(:client_id, non_null(:string), description: "The application's client_id")
|
||||
arg(:scope, :string, description: "The scope for the authorization")
|
||||
|
||||
arg(:user_code, non_null(:string),
|
||||
description: "The code provided by the application entered by the user"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Applications.ApplicationDeviceActivation,
|
||||
rule: :forbid_app_access,
|
||||
args: %{id: :client_id}
|
||||
)
|
||||
|
||||
resolve(&Application.authorize_device_application/3)
|
||||
end
|
||||
|
||||
@@ -8,6 +8,7 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
|
||||
@desc "A config object"
|
||||
object :config do
|
||||
meta(:authorize, :all)
|
||||
# Instance name
|
||||
field(:name, :string, description: "The instance's name")
|
||||
field(:description, :string, description: "The instance's short description")
|
||||
@@ -87,6 +88,7 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
The instance's terms configuration
|
||||
"""
|
||||
object :terms do
|
||||
meta(:authorize, :all)
|
||||
field(:url, :string, description: "The instance's terms URL.")
|
||||
field(:type, :instance_terms_type, description: "The instance's terms type")
|
||||
field(:body_html, :string, description: "The instance's terms body text")
|
||||
@@ -96,6 +98,7 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
The instance's privacy policy configuration
|
||||
"""
|
||||
object :privacy do
|
||||
meta(:authorize, :all)
|
||||
field(:url, :string, description: "The instance's privacy policy URL")
|
||||
field(:type, :instance_privacy_type, description: "The instance's privacy policy type")
|
||||
field(:body_html, :string, description: "The instance's privacy policy body text")
|
||||
@@ -105,6 +108,7 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
Geographic coordinates
|
||||
"""
|
||||
object :lonlat do
|
||||
meta(:authorize, :all)
|
||||
field(:longitude, :float, description: "The coordinates longitude")
|
||||
field(:latitude, :float, description: "The coordinates latitude")
|
||||
# field(:accuracy_radius, :integer)
|
||||
@@ -114,6 +118,8 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
Instance geocoding configuration
|
||||
"""
|
||||
object :geocoding do
|
||||
meta(:authorize, :all)
|
||||
|
||||
field(:autocomplete, :boolean,
|
||||
description: "Whether autocomplete in address fields can be enabled"
|
||||
)
|
||||
@@ -125,6 +131,7 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
Instance maps configuration
|
||||
"""
|
||||
object :maps do
|
||||
meta(:authorize, :all)
|
||||
field(:tiles, :tiles, description: "The instance's maps tiles configuration")
|
||||
field(:routing, :routing, description: "The instance's maps routing configuration")
|
||||
end
|
||||
@@ -133,6 +140,7 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
Instance map tiles configuration
|
||||
"""
|
||||
object :tiles do
|
||||
meta(:authorize, :all)
|
||||
field(:endpoint, :string, description: "The instance's tiles endpoint")
|
||||
field(:attribution, :string, description: "The instance's tiles attribution text")
|
||||
end
|
||||
@@ -141,6 +149,7 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
Instance map routing configuration
|
||||
"""
|
||||
object :routing do
|
||||
meta(:authorize, :all)
|
||||
field(:type, :routing_type, description: "The instance's routing type")
|
||||
end
|
||||
|
||||
@@ -153,6 +162,8 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
Instance anonymous configuration
|
||||
"""
|
||||
object :anonymous do
|
||||
meta(:authorize, :all)
|
||||
|
||||
field(:participation, :anonymous_participation,
|
||||
description: "The instance's anonymous participation settings"
|
||||
)
|
||||
@@ -172,6 +183,7 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
Instance anonymous participation configuration
|
||||
"""
|
||||
object :anonymous_participation do
|
||||
meta(:authorize, :all)
|
||||
field(:allowed, :boolean, description: "Whether anonymous participations are allowed")
|
||||
|
||||
field(:validation, :anonymous_participation_validation,
|
||||
@@ -183,6 +195,8 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
Instance anonymous participation validation configuration
|
||||
"""
|
||||
object :anonymous_participation_validation do
|
||||
meta(:authorize, :all)
|
||||
|
||||
field(:email, :anonymous_participation_validation_email,
|
||||
description: "The policy to validate anonymous participations by email"
|
||||
)
|
||||
@@ -196,6 +210,8 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
Instance anonymous participation with validation by email configuration
|
||||
"""
|
||||
object :anonymous_participation_validation_email do
|
||||
meta(:authorize, :all)
|
||||
|
||||
field(:enabled, :boolean,
|
||||
description: "Whether anonymous participation validation by email is enabled"
|
||||
)
|
||||
@@ -209,6 +225,8 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
Instance anonymous participation with validation by captcha configuration
|
||||
"""
|
||||
object :anonymous_participation_validation_captcha do
|
||||
meta(:authorize, :all)
|
||||
|
||||
field(:enabled, :boolean,
|
||||
description: "Whether anonymous participation validation by captcha is enabled"
|
||||
)
|
||||
@@ -218,6 +236,7 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
Instance anonymous event creation configuration
|
||||
"""
|
||||
object :anonymous_event_creation do
|
||||
meta(:authorize, :all)
|
||||
field(:allowed, :boolean, description: "Whether anonymous event creation is enabled")
|
||||
|
||||
field(:validation, :anonymous_event_creation_validation,
|
||||
@@ -229,6 +248,8 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
Instance anonymous event creation validation configuration
|
||||
"""
|
||||
object :anonymous_event_creation_validation do
|
||||
meta(:authorize, :all)
|
||||
|
||||
field(:email, :anonymous_event_creation_validation_email,
|
||||
description: "The policy to validate anonymous event creations by email"
|
||||
)
|
||||
@@ -242,6 +263,8 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
Instance anonymous event creation email validation configuration
|
||||
"""
|
||||
object :anonymous_event_creation_validation_email do
|
||||
meta(:authorize, :all)
|
||||
|
||||
field(:enabled, :boolean,
|
||||
description: "Whether anonymous event creation with email validation is enabled"
|
||||
)
|
||||
@@ -255,6 +278,8 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
Instance anonymous event creation captcha validation configuration
|
||||
"""
|
||||
object :anonymous_event_creation_validation_captcha do
|
||||
meta(:authorize, :all)
|
||||
|
||||
field(:enabled, :boolean,
|
||||
description: "Whether anonymous event creation with validation by captcha is enabled"
|
||||
)
|
||||
@@ -264,6 +289,7 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
Instance anonymous reports
|
||||
"""
|
||||
object :anonymous_reports do
|
||||
meta(:authorize, :all)
|
||||
field(:allowed, :boolean, description: "Whether anonymous reports are allowed")
|
||||
end
|
||||
|
||||
@@ -271,6 +297,7 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
A resource provider details
|
||||
"""
|
||||
object :resource_provider do
|
||||
meta(:authorize, :all)
|
||||
field(:type, :string, description: "The resource provider's type")
|
||||
field(:endpoint, :string, description: "The resource provider's endpoint")
|
||||
field(:software, :string, description: "The resource provider's software")
|
||||
@@ -280,17 +307,22 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
The instance's features
|
||||
"""
|
||||
object :features do
|
||||
meta(:authorize, :all)
|
||||
field(:groups, :boolean, description: "Whether groups are activated on this instance")
|
||||
|
||||
field(:event_creation, :boolean,
|
||||
description: "Whether event creation is allowed on this instance"
|
||||
)
|
||||
|
||||
field(:antispam, :boolean, description: "Whether anti-spam is activated on this instance")
|
||||
end
|
||||
|
||||
@desc """
|
||||
The instance's restrictions
|
||||
"""
|
||||
object :restrictions do
|
||||
meta(:authorize, :all)
|
||||
|
||||
field(:only_admin_can_create_groups, :boolean,
|
||||
description: "Whether groups creation is allowed only for admin, not for all users"
|
||||
)
|
||||
@@ -304,6 +336,7 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
The instance's auth configuration
|
||||
"""
|
||||
object :auth do
|
||||
meta(:authorize, :all)
|
||||
field(:ldap, :boolean, description: "Whether or not LDAP auth is enabled")
|
||||
field(:database_login, :boolean, description: "Whether or not database login is enabled")
|
||||
field(:oauth_providers, list_of(:oauth_provider), description: "List of oauth providers")
|
||||
@@ -313,6 +346,7 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
An oAuth Provider
|
||||
"""
|
||||
object :oauth_provider do
|
||||
meta(:authorize, :all)
|
||||
field(:id, :string, description: "The provider ID")
|
||||
field(:label, :string, description: "The label for the auth provider")
|
||||
end
|
||||
@@ -321,21 +355,25 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
An upload limits configuration
|
||||
"""
|
||||
object :upload_limits do
|
||||
meta(:authorize, :all)
|
||||
field(:default, :integer, description: "The default limitation, in bytes")
|
||||
field(:avatar, :integer, description: "The avatar limitation, in bytes")
|
||||
field(:banner, :integer, description: "The banner limitation, in bytes")
|
||||
end
|
||||
|
||||
object :instance_feeds do
|
||||
meta(:authorize, :all)
|
||||
field(:enabled, :boolean, description: "Whether the instance-wide feeds are enabled")
|
||||
end
|
||||
|
||||
object :web_push do
|
||||
meta(:authorize, :all)
|
||||
field(:enabled, :boolean, description: "Whether the WebPush feature is enabled")
|
||||
field(:public_key, :string, description: "The server's public WebPush VAPID key")
|
||||
end
|
||||
|
||||
object :analytics do
|
||||
meta(:authorize, :all)
|
||||
field(:id, :string, description: "ID of the analytics service")
|
||||
field(:enabled, :boolean, description: "Whether the service is activated or not")
|
||||
|
||||
@@ -352,16 +390,19 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
end
|
||||
|
||||
object :analytics_configuration do
|
||||
meta(:authorize, :all)
|
||||
field(:key, :string, description: "The key for the analytics configuration element")
|
||||
field(:value, :string, description: "The value for the analytics configuration element")
|
||||
field(:type, :analytics_configuration_type, description: "The analytics configuration type")
|
||||
end
|
||||
|
||||
object :search_settings do
|
||||
meta(:authorize, :all)
|
||||
field(:global, :global_search_settings, description: "The instance's global search settings")
|
||||
end
|
||||
|
||||
object :global_search_settings do
|
||||
meta(:authorize, :all)
|
||||
field(:is_enabled, :boolean, description: "Whether global search is enabled")
|
||||
field(:is_default, :boolean, description: "Whether global search is the default")
|
||||
end
|
||||
@@ -370,6 +411,8 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
Export formats configuration
|
||||
"""
|
||||
object :export_formats do
|
||||
meta(:authorize, :all)
|
||||
|
||||
field(:event_participants, list_of(:string),
|
||||
description: "The list of formats the event participants can be exported to"
|
||||
)
|
||||
@@ -379,6 +422,7 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
Event categories list configuration
|
||||
"""
|
||||
object :event_category_option do
|
||||
meta(:authorize, :all)
|
||||
field(:id, :string, description: "The ID of the event category")
|
||||
field(:label, :string, description: "The translated name of the event category")
|
||||
end
|
||||
@@ -386,6 +430,7 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
|
||||
object :config_queries do
|
||||
@desc "Get the instance config"
|
||||
field :config, :config do
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&Config.get_config/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,6 +11,7 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.CommentType do
|
||||
|
||||
@desc "A comment"
|
||||
object :comment do
|
||||
meta(:authorize, :all)
|
||||
interfaces([:action_log_object, :activity_object])
|
||||
field(:id, :id, description: "Internal ID for this comment")
|
||||
field(:uuid, :uuid, description: "An UUID for this comment")
|
||||
@@ -73,6 +74,7 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.CommentType do
|
||||
|
||||
@desc "A paginated list of comments"
|
||||
object :paginated_comment_list do
|
||||
meta(:authorize, :all)
|
||||
field(:elements, list_of(:comment), description: "A list of comments")
|
||||
field(:total, :integer, description: "The total number of comments in the list")
|
||||
end
|
||||
@@ -81,6 +83,7 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.CommentType do
|
||||
@desc "Get replies for thread"
|
||||
field :thread, type: list_of(:comment) do
|
||||
arg(:id, non_null(:id), description: "The comment ID")
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&Comment.get_thread/3)
|
||||
end
|
||||
end
|
||||
@@ -95,6 +98,13 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.CommentType do
|
||||
|
||||
arg(:is_announcement, :boolean, description: "Should this comment be announced to everyone?")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Discussions.Comment,
|
||||
rule: :"write:comment:create",
|
||||
args: %{event_id: :event_id}
|
||||
)
|
||||
|
||||
resolve(&Comment.create_comment/3)
|
||||
end
|
||||
|
||||
@@ -106,6 +116,13 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.CommentType do
|
||||
|
||||
arg(:is_announcement, :boolean, description: "Should this comment be announced to everyone?")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Discussions.Comment,
|
||||
rule: :"write:comment:update",
|
||||
args: %{id: :comment_id}
|
||||
)
|
||||
|
||||
resolve(&Comment.update_comment/3)
|
||||
end
|
||||
|
||||
@@ -113,6 +130,13 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.CommentType do
|
||||
field :delete_comment, type: :comment do
|
||||
arg(:comment_id, non_null(:id), description: "The comment ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: [:user, :moderator],
|
||||
scope: Mobilizon.Discussions.Comment,
|
||||
rule: :"write:comment:delete",
|
||||
args: %{id: :comment_id}
|
||||
)
|
||||
|
||||
resolve(&Comment.delete_comment/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,6 +11,7 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.DiscussionType do
|
||||
|
||||
@desc "A discussion"
|
||||
object :discussion do
|
||||
meta(:authorize, :user)
|
||||
interfaces([:activity_object])
|
||||
field(:id, :id, description: "Internal ID for this discussion")
|
||||
field(:title, :string, description: "The title for this discussion")
|
||||
@@ -36,6 +37,7 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.DiscussionType do
|
||||
|
||||
@desc "A paginated list of discussions"
|
||||
object :paginated_discussion_list do
|
||||
meta(:authorize, :user)
|
||||
field(:elements, list_of(:discussion), description: "A list of discussion")
|
||||
field(:total, :integer, description: "The total number of discussions in the list")
|
||||
end
|
||||
@@ -45,6 +47,13 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.DiscussionType do
|
||||
field :discussion, type: :discussion do
|
||||
arg(:id, :id, description: "The discussion's ID")
|
||||
arg(:slug, :string, description: "The discussion's slug")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Discussions.Discussion,
|
||||
rule: :"read:group:discussions"
|
||||
)
|
||||
|
||||
resolve(&Discussion.get_discussion/3)
|
||||
end
|
||||
end
|
||||
@@ -56,6 +65,13 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.DiscussionType do
|
||||
arg(:text, non_null(:string), description: "The discussion's first comment body")
|
||||
arg(:actor_id, non_null(:id), description: "The discussion's group ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Discussions.Discussion,
|
||||
rule: :"write:group:discussion:create",
|
||||
args: %{actor_id: :actor_id}
|
||||
)
|
||||
|
||||
resolve(&Discussion.create_discussion/3)
|
||||
end
|
||||
|
||||
@@ -63,6 +79,14 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.DiscussionType do
|
||||
field :reply_to_discussion, type: :discussion do
|
||||
arg(:discussion_id, non_null(:id), description: "The discussion's ID")
|
||||
arg(:text, non_null(:string), description: "The discussion's reply body")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Discussions.Discussion,
|
||||
rule: :"write:group:discussion:update",
|
||||
args: %{id: :discussion_id}
|
||||
)
|
||||
|
||||
resolve(&Discussion.reply_to_discussion/3)
|
||||
end
|
||||
|
||||
@@ -70,6 +94,14 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.DiscussionType do
|
||||
field :update_discussion, type: :discussion do
|
||||
arg(:title, non_null(:string), description: "The updated discussion's title")
|
||||
arg(:discussion_id, non_null(:id), description: "The discussion's ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Discussions.Discussion,
|
||||
rule: :"write:group:discussion:update",
|
||||
args: %{id: :discussion_id}
|
||||
)
|
||||
|
||||
resolve(&Discussion.update_discussion/3)
|
||||
end
|
||||
|
||||
@@ -77,6 +109,13 @@ defmodule Mobilizon.GraphQL.Schema.Discussions.DiscussionType do
|
||||
field :delete_discussion, type: :discussion do
|
||||
arg(:discussion_id, non_null(:id), description: "The discussion's ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Discussions.Discussion,
|
||||
rule: :"write:group:discussion:delete",
|
||||
args: %{id: :discussion_id}
|
||||
)
|
||||
|
||||
resolve(&Discussion.delete_discussion/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,6 +17,8 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
|
||||
@desc "An event"
|
||||
object :event do
|
||||
meta(:authorize, :all)
|
||||
meta(:scope_field?, true)
|
||||
interfaces([:action_log_object, :interactable, :activity_object, :event_search_result])
|
||||
field(:id, :id, description: "Internal ID for this event")
|
||||
field(:uuid, :uuid, description: "The Event UUID")
|
||||
@@ -61,10 +63,9 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
description: "The event's organizer (as a person)"
|
||||
)
|
||||
|
||||
field(:tags, list_of(:tag),
|
||||
resolve: &Tag.list_tags_for_event/3,
|
||||
description: "The event's tags"
|
||||
)
|
||||
field(:tags, list_of(:tag), description: "The event's tags") do
|
||||
resolve(&Tag.list_tags_for_event/3)
|
||||
end
|
||||
|
||||
field(:category, :event_category, description: "The event's category")
|
||||
|
||||
@@ -75,7 +76,10 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
resolve: &Event.stats_participants/3
|
||||
)
|
||||
|
||||
field(:participants, :paginated_participant_list, description: "The event's participants") do
|
||||
field(:participants, :paginated_participant_list,
|
||||
description: "The event's participants",
|
||||
meta: [private: true, rule: :"read:event:participants"]
|
||||
) do
|
||||
arg(:page, :integer,
|
||||
default_value: 1,
|
||||
description: "The page in the paginated participants list"
|
||||
@@ -134,12 +138,14 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
|
||||
@desc "A paginated list of events"
|
||||
object :paginated_event_list do
|
||||
meta(:authorize, :all)
|
||||
field(:elements, list_of(:event), description: "A list of events")
|
||||
field(:total, :integer, description: "The total number of events in the list")
|
||||
end
|
||||
|
||||
@desc "Participation statistics"
|
||||
object :participant_stats do
|
||||
meta(:authorize, :all)
|
||||
field(:going, :integer, description: "The number of approved participants")
|
||||
field(:not_approved, :integer, description: "The number of not approved participants")
|
||||
field(:not_confirmed, :integer, description: "The number of not confirmed participants")
|
||||
@@ -158,6 +164,7 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
An event offer
|
||||
"""
|
||||
object :event_offer do
|
||||
meta(:authorize, :all)
|
||||
field(:price, :float, description: "The price amount for this offer")
|
||||
field(:price_currency, :string, description: "The currency for this price offer")
|
||||
field(:url, :string, description: "The URL to access to this offer")
|
||||
@@ -167,6 +174,7 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
An event participation condition
|
||||
"""
|
||||
object :event_participation_condition do
|
||||
meta(:authorize, :all)
|
||||
field(:title, :string, description: "The title for this condition")
|
||||
field(:content, :string, description: "The content for this condition")
|
||||
field(:url, :string, description: "The URL to access this condition")
|
||||
@@ -201,6 +209,8 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
Event options
|
||||
"""
|
||||
object :event_options do
|
||||
meta(:authorize, :all)
|
||||
|
||||
field(:maximum_attendee_capacity, :integer,
|
||||
description: "The maximum attendee capacity for this event"
|
||||
)
|
||||
@@ -307,6 +317,7 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
end
|
||||
|
||||
object :event_metadata do
|
||||
meta(:authorize, :all)
|
||||
field(:key, :string, description: "The key for the metadata")
|
||||
field(:title, :string, description: "The title for the metadata")
|
||||
field(:value, :string, description: "The value for the metadata")
|
||||
@@ -350,12 +361,15 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
description: "Direction for the sort"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
|
||||
resolve(&Event.list_events/3)
|
||||
end
|
||||
|
||||
@desc "Get an event by uuid"
|
||||
field :event, :event do
|
||||
arg(:uuid, non_null(:uuid), description: "The event's UUID")
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&Event.find_event/3)
|
||||
end
|
||||
end
|
||||
@@ -416,6 +430,13 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
arg(:contacts, list_of(:contact), default_value: [], description: "The events contacts")
|
||||
arg(:language, :string, description: "The event language", default_value: "und")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Events.Event,
|
||||
rule: :"write:event:create",
|
||||
args: %{organizer_actor_id: :organizer_actor_id}
|
||||
)
|
||||
|
||||
resolve(&Event.create_event/3)
|
||||
end
|
||||
|
||||
@@ -460,6 +481,13 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
arg(:contacts, list_of(:contact), default_value: [], description: "The events contacts")
|
||||
arg(:language, :string, description: "The event language", default_value: "und")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Events.Event,
|
||||
args: %{id: :event_id},
|
||||
rule: :"write:event:update"
|
||||
)
|
||||
|
||||
resolve(&Event.update_event/3)
|
||||
end
|
||||
|
||||
@@ -467,6 +495,13 @@ defmodule Mobilizon.GraphQL.Schema.EventType do
|
||||
field :delete_event, :deleted_object do
|
||||
arg(:event_id, non_null(:id), description: "The event ID to delete")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: [:user, :moderator, :administrator],
|
||||
scope: Mobilizon.Events.Event,
|
||||
rule: :"write:event:delete",
|
||||
args: %{id: :event_id}
|
||||
)
|
||||
|
||||
resolve(&Event.delete_event/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,6 +17,8 @@ defmodule Mobilizon.GraphQL.Schema.Events.FeedTokenType do
|
||||
or an Atom feed for just a profile.
|
||||
"""
|
||||
object :feed_token do
|
||||
meta(:authorize, :user)
|
||||
|
||||
field(
|
||||
:actor,
|
||||
:actor,
|
||||
@@ -36,6 +38,7 @@ defmodule Mobilizon.GraphQL.Schema.Events.FeedTokenType do
|
||||
|
||||
@desc "Represents a deleted feed_token"
|
||||
object :deleted_feed_token do
|
||||
meta(:authorize, :user)
|
||||
field(:user, :deleted_object, description: "The user that owned the deleted feed token")
|
||||
field(:actor, :deleted_object, description: "The actor that owned the deleted feed token")
|
||||
end
|
||||
@@ -45,6 +48,13 @@ defmodule Mobilizon.GraphQL.Schema.Events.FeedTokenType do
|
||||
field :create_feed_token, :feed_token do
|
||||
arg(:actor_id, :id, description: "The actor ID for the feed token")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Events.FeedToken,
|
||||
rule: :"write:profile:feed_token:create",
|
||||
args: %{}
|
||||
)
|
||||
|
||||
resolve(&FeedToken.create_feed_token/3)
|
||||
end
|
||||
|
||||
@@ -52,6 +62,13 @@ defmodule Mobilizon.GraphQL.Schema.Events.FeedTokenType do
|
||||
field :delete_feed_token, :deleted_feed_token do
|
||||
arg(:token, non_null(:string), description: "The token to delete")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Events.FeedToken,
|
||||
rule: :"write:feed_token:delete",
|
||||
args: %{token: :token}
|
||||
)
|
||||
|
||||
resolve(&FeedToken.delete_feed_token/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,6 +12,7 @@ defmodule Mobilizon.GraphQL.Schema.Events.ParticipantType do
|
||||
|
||||
@desc "Represents a participant to an event"
|
||||
object :participant do
|
||||
meta(:authorize, :all)
|
||||
field(:id, :id, description: "The participation ID")
|
||||
|
||||
field(
|
||||
@@ -41,6 +42,8 @@ defmodule Mobilizon.GraphQL.Schema.Events.ParticipantType do
|
||||
Metadata about a participant
|
||||
"""
|
||||
object :participant_metadata do
|
||||
meta(:authorize, :all)
|
||||
|
||||
field(:cancellation_token, :string,
|
||||
description: "The eventual token to leave an event when user is anonymous"
|
||||
)
|
||||
@@ -53,6 +56,7 @@ defmodule Mobilizon.GraphQL.Schema.Events.ParticipantType do
|
||||
A paginated list of participants
|
||||
"""
|
||||
object :paginated_participant_list do
|
||||
meta(:authorize, :user)
|
||||
field(:elements, list_of(:participant), description: "A list of participants")
|
||||
field(:total, :integer, description: "The total number of participants in the list")
|
||||
end
|
||||
@@ -78,6 +82,7 @@ defmodule Mobilizon.GraphQL.Schema.Events.ParticipantType do
|
||||
|
||||
@desc "Represents a deleted participant"
|
||||
object :deleted_participant do
|
||||
meta(:authorize, :all)
|
||||
field(:id, :id, description: "The participant ID")
|
||||
field(:event, :deleted_object, description: "The participant's event")
|
||||
field(:actor, :deleted_object, description: "The participant's actor")
|
||||
@@ -92,7 +97,7 @@ defmodule Mobilizon.GraphQL.Schema.Events.ParticipantType do
|
||||
arg(:message, :string, description: "The anonymous participant's message")
|
||||
arg(:locale, :string, description: "The anonymous participant's locale")
|
||||
arg(:timezone, :string, description: "The anonymous participant's timezone")
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :all, rule: :"write:participation")
|
||||
resolve(&Participant.actor_join_event/3)
|
||||
end
|
||||
|
||||
@@ -101,7 +106,7 @@ defmodule Mobilizon.GraphQL.Schema.Events.ParticipantType do
|
||||
arg(:event_id, non_null(:id), description: "The event ID the participant left")
|
||||
arg(:actor_id, non_null(:id), description: "The actor ID for the participant")
|
||||
arg(:token, :string, description: "The anonymous participant participation token")
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :all, rule: :"write:participation")
|
||||
resolve(&Participant.actor_leave_event/3)
|
||||
end
|
||||
|
||||
@@ -110,12 +115,19 @@ defmodule Mobilizon.GraphQL.Schema.Events.ParticipantType do
|
||||
arg(:id, non_null(:id), description: "The participant ID")
|
||||
arg(:role, non_null(:participant_role_enum), description: "The participant new role")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Events.Participant,
|
||||
rule: :"write:participation"
|
||||
)
|
||||
|
||||
resolve(&Participant.update_participation/3)
|
||||
end
|
||||
|
||||
@desc "Confirm a participation"
|
||||
field :confirm_participation, :participant do
|
||||
arg(:confirmation_token, non_null(:string), description: "The participation token")
|
||||
middleware(Rajska.QueryAuthorization, permit: :all, rule: :"write:participation")
|
||||
resolve(&Participant.confirm_participation_from_token/3)
|
||||
end
|
||||
|
||||
@@ -131,6 +143,14 @@ defmodule Mobilizon.GraphQL.Schema.Events.ParticipantType do
|
||||
)
|
||||
|
||||
arg(:format, :export_format_enum, description: "The format in which to return the file")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Events.Event,
|
||||
rule: :"read:event:participants:export",
|
||||
args: %{id: :event_id}
|
||||
)
|
||||
|
||||
resolve(&Participant.export_event_participants/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,12 +6,14 @@ defmodule Mobilizon.GraphQL.Schema.FollowedGroupActivityType do
|
||||
|
||||
@desc "A paginated list of follow group events"
|
||||
object :paginated_followed_group_events do
|
||||
meta(:authorize, :user)
|
||||
field(:elements, list_of(:followed_group_event), description: "A list of follow group events")
|
||||
field(:total, :integer, description: "The total number of follow group events in the list")
|
||||
end
|
||||
|
||||
@desc "A follow group event"
|
||||
object :followed_group_event do
|
||||
meta(:authorize, :user)
|
||||
field(:user, :user)
|
||||
field(:profile, :person)
|
||||
field(:group, :group)
|
||||
|
||||
@@ -8,6 +8,7 @@ defmodule Mobilizon.GraphQL.Schema.MediaType do
|
||||
|
||||
@desc "A media"
|
||||
object :media do
|
||||
meta(:authorize, :all)
|
||||
field(:id, :id, description: "The media's ID")
|
||||
field(:alt, :string, description: "The media's alternative text")
|
||||
field(:name, :string, description: "The media's name")
|
||||
@@ -21,6 +22,7 @@ defmodule Mobilizon.GraphQL.Schema.MediaType do
|
||||
A paginated list of medias
|
||||
"""
|
||||
object :paginated_media_list do
|
||||
meta(:authorize, :all)
|
||||
field(:elements, list_of(:media), description: "The list of medias")
|
||||
field(:total, :integer, description: "The total number of medias in the list")
|
||||
end
|
||||
@@ -29,6 +31,7 @@ defmodule Mobilizon.GraphQL.Schema.MediaType do
|
||||
Some metadata associated with a media
|
||||
"""
|
||||
object :media_metadata do
|
||||
meta(:authorize, :all)
|
||||
field(:width, :integer, description: "The media width (if a picture)")
|
||||
field(:height, :integer, description: "The media width (if a height)")
|
||||
field(:blurhash, :string, description: "The media blurhash (if a picture")
|
||||
@@ -54,6 +57,7 @@ defmodule Mobilizon.GraphQL.Schema.MediaType do
|
||||
@desc "Get a media"
|
||||
field :media, :media do
|
||||
arg(:id, non_null(:id), description: "The media ID")
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&Media.media/3)
|
||||
end
|
||||
end
|
||||
@@ -64,6 +68,15 @@ defmodule Mobilizon.GraphQL.Schema.MediaType do
|
||||
arg(:name, non_null(:string), description: "The media's name")
|
||||
arg(:alt, :string, description: "The media's alternative text")
|
||||
arg(:file, non_null(:upload), description: "The media file")
|
||||
arg(:actor_id, :id, description: "The actor that uploads the media")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Medias.Media,
|
||||
rule: :"write:media:upload",
|
||||
args: %{}
|
||||
)
|
||||
|
||||
resolve(&Media.upload_media/3)
|
||||
end
|
||||
|
||||
@@ -72,6 +85,13 @@ defmodule Mobilizon.GraphQL.Schema.MediaType do
|
||||
"""
|
||||
field :remove_media, :deleted_object do
|
||||
arg(:id, non_null(:id), description: "The media's ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Medias.Media,
|
||||
rule: :"write:media:remove"
|
||||
)
|
||||
|
||||
resolve(&Media.remove_media/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,6 +7,7 @@ defmodule Mobilizon.GraphQL.Schema.PostType do
|
||||
|
||||
@desc "A post"
|
||||
object :post do
|
||||
meta(:authorize, :all)
|
||||
interfaces([:activity_object])
|
||||
field(:id, :id, description: "The post's ID")
|
||||
field(:title, :string, description: "The post's title")
|
||||
@@ -22,21 +23,20 @@ defmodule Mobilizon.GraphQL.Schema.PostType do
|
||||
field(:updated_at, :datetime, description: "The post's last update date")
|
||||
field(:language, :string, description: "The post language")
|
||||
|
||||
field(:tags, list_of(:tag),
|
||||
resolve: &Tag.list_tags_for_post/3,
|
||||
description: "The post's tags"
|
||||
)
|
||||
field(:tags, list_of(:tag), description: "The post's tags") do
|
||||
resolve(&Tag.list_tags_for_post/3)
|
||||
end
|
||||
|
||||
field(:picture, :media,
|
||||
description: "The posts's media",
|
||||
resolve: &Media.media/3
|
||||
)
|
||||
field(:picture, :media, description: "The posts's media") do
|
||||
resolve(&Media.media/3)
|
||||
end
|
||||
end
|
||||
|
||||
@desc """
|
||||
A paginated list of posts
|
||||
"""
|
||||
object :paginated_post_list do
|
||||
meta(:authorize, :all)
|
||||
field(:elements, list_of(:post), description: "A list of posts")
|
||||
field(:total, :integer, description: "The total number of posts in the list")
|
||||
end
|
||||
@@ -56,6 +56,7 @@ defmodule Mobilizon.GraphQL.Schema.PostType do
|
||||
@desc "Get a post"
|
||||
field :post, :post do
|
||||
arg(:slug, non_null(:string), description: "The post's slug")
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&Post.get_post/3)
|
||||
end
|
||||
end
|
||||
@@ -84,6 +85,13 @@ defmodule Mobilizon.GraphQL.Schema.PostType do
|
||||
"The banner for the post, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Posts.Post,
|
||||
rule: :"write:group:post:create",
|
||||
args: %{}
|
||||
)
|
||||
|
||||
resolve(&Post.create_post/3)
|
||||
end
|
||||
|
||||
@@ -108,12 +116,25 @@ defmodule Mobilizon.GraphQL.Schema.PostType do
|
||||
"The banner for the post, either as an object or directly the ID of an existing media"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Posts.Post,
|
||||
rule: :"write:group:post:update"
|
||||
)
|
||||
|
||||
resolve(&Post.update_post/3)
|
||||
end
|
||||
|
||||
@desc "Delete a post"
|
||||
field :delete_post, :deleted_object do
|
||||
arg(:id, non_null(:id), description: "The post's ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Posts.Post,
|
||||
rule: :"write:group:post:delete"
|
||||
)
|
||||
|
||||
resolve(&Post.delete_post/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,11 +11,12 @@ defmodule Mobilizon.GraphQL.Schema.ReportType do
|
||||
|
||||
@desc "A report object"
|
||||
object :report do
|
||||
meta(:authorize, :all)
|
||||
interfaces([:action_log_object])
|
||||
field(:id, :id, description: "The internal ID of the report")
|
||||
field(:content, :string, description: "The comment the reporter added about this report")
|
||||
field(:status, :report_status, description: "Whether the report is still active")
|
||||
field(:uri, :string, description: "The URI of the report")
|
||||
field(:uri, :string, description: "The URI of the report", meta: [private: true])
|
||||
field(:reported, :actor, description: "The actor that is being reported")
|
||||
field(:reporter, :actor, description: "The actor that created the report")
|
||||
field(:event, :event, description: "The event that is being reported")
|
||||
@@ -23,6 +24,7 @@ defmodule Mobilizon.GraphQL.Schema.ReportType do
|
||||
|
||||
field(:notes, list_of(:report_note),
|
||||
description: "The notes made on the event",
|
||||
meta: [private: true],
|
||||
resolve: dataloader(Reports)
|
||||
)
|
||||
|
||||
@@ -31,12 +33,14 @@ defmodule Mobilizon.GraphQL.Schema.ReportType do
|
||||
end
|
||||
|
||||
object :paginated_report_list do
|
||||
meta(:authorize, :moderator)
|
||||
field(:elements, list_of(:report), description: "A list of reports")
|
||||
field(:total, :integer, description: "The total number of reports in the list")
|
||||
end
|
||||
|
||||
@desc "A report note object"
|
||||
object :report_note do
|
||||
meta(:authorize, :moderator)
|
||||
interfaces([:action_log_object])
|
||||
field(:id, :id, description: "The internal ID of the report note")
|
||||
field(:content, :string, description: "The content of the note")
|
||||
@@ -73,12 +77,20 @@ defmodule Mobilizon.GraphQL.Schema.ReportType do
|
||||
arg(:limit, :integer, default_value: 10, description: "The limit of reports per page")
|
||||
arg(:status, :report_status, default_value: :open, description: "Filter reports by status")
|
||||
arg(:domain, :string, default_value: nil, description: "Filter reports by domain name")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :moderator,
|
||||
scope: Mobilizon.Reports.Report,
|
||||
args: %{}
|
||||
)
|
||||
|
||||
resolve(&Report.list_reports/3)
|
||||
end
|
||||
|
||||
@desc "Get a report by id"
|
||||
field :report, :report do
|
||||
arg(:id, non_null(:id), description: "The report ID")
|
||||
middleware(Rajska.QueryAuthorization, permit: :moderator, scope: Mobilizon.Reports.Report)
|
||||
resolve(&Report.get_report/3)
|
||||
end
|
||||
end
|
||||
@@ -101,6 +113,8 @@ defmodule Mobilizon.GraphQL.Schema.ReportType do
|
||||
"Whether to forward the report to the original instance if the content is remote"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
|
||||
resolve(&Report.create_report/3)
|
||||
end
|
||||
|
||||
@@ -113,6 +127,12 @@ defmodule Mobilizon.GraphQL.Schema.ReportType do
|
||||
description: "The feedback to send to the anti-spam system"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :moderator,
|
||||
scope: Mobilizon.Reports.Report,
|
||||
args: %{id: :report_id}
|
||||
)
|
||||
|
||||
resolve(&Report.update_report/3)
|
||||
end
|
||||
|
||||
@@ -120,12 +140,26 @@ defmodule Mobilizon.GraphQL.Schema.ReportType do
|
||||
field :create_report_note, type: :report_note do
|
||||
arg(:content, :string, description: "The note's content")
|
||||
arg(:report_id, non_null(:id), description: "The report's ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :moderator,
|
||||
scope: Mobilizon.Reports.Report,
|
||||
args: %{id: :report_id}
|
||||
)
|
||||
|
||||
resolve(&Report.create_report_note/3)
|
||||
end
|
||||
|
||||
@desc "Delete a note on a report"
|
||||
field :delete_report_note, type: :deleted_object do
|
||||
arg(:note_id, non_null(:id), description: "The note's ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :moderator,
|
||||
scope: Mobilizon.Reports.Note,
|
||||
args: %{id: :note_id}
|
||||
)
|
||||
|
||||
resolve(&Report.delete_report_note/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,6 +9,7 @@ defmodule Mobilizon.GraphQL.Schema.ResourceType do
|
||||
|
||||
@desc "A resource"
|
||||
object :resource do
|
||||
meta(:authorize, :user)
|
||||
interfaces([:activity_object])
|
||||
field(:id, :id, description: "The resource's ID")
|
||||
field(:title, :string, description: "The resource's title")
|
||||
@@ -44,6 +45,7 @@ defmodule Mobilizon.GraphQL.Schema.ResourceType do
|
||||
A paginated list of resources
|
||||
"""
|
||||
object :paginated_resource_list do
|
||||
meta(:authorize, :user)
|
||||
field(:elements, list_of(:resource), description: "A list of resources")
|
||||
field(:total, :integer, description: "The total number of resources in the list")
|
||||
end
|
||||
@@ -52,6 +54,7 @@ defmodule Mobilizon.GraphQL.Schema.ResourceType do
|
||||
The metadata associated to the resource
|
||||
"""
|
||||
object :resource_metadata do
|
||||
meta(:authorize, :user)
|
||||
field(:type, :string, description: "The type of the resource")
|
||||
field(:title, :string, description: "The resource's metadata title")
|
||||
field(:description, :string, description: "The resource's metadata description")
|
||||
@@ -84,6 +87,13 @@ defmodule Mobilizon.GraphQL.Schema.ResourceType do
|
||||
description: "The federated username for the group resource"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Resources.Resource,
|
||||
rule: :"read:group:resources",
|
||||
args: %{path: :path}
|
||||
)
|
||||
|
||||
resolve(&Resource.get_resource/3)
|
||||
end
|
||||
end
|
||||
@@ -101,6 +111,13 @@ defmodule Mobilizon.GraphQL.Schema.ResourceType do
|
||||
arg(:resource_url, :string, description: "This resource's own original URL")
|
||||
arg(:type, :string, default_value: "link", description: "The type for this resource")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Resources.Resource,
|
||||
rule: :"write:group:resources:create",
|
||||
args: %{actor_id: :actor_id}
|
||||
)
|
||||
|
||||
resolve(&Resource.create_resource/3)
|
||||
end
|
||||
|
||||
@@ -112,18 +129,39 @@ defmodule Mobilizon.GraphQL.Schema.ResourceType do
|
||||
arg(:parent_id, :id, description: "The new resource parent ID (if the resource is moved)")
|
||||
arg(:resource_url, :string, description: "The new resource URL")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Resources.Resource,
|
||||
rule: :"write:group:resources:update"
|
||||
)
|
||||
|
||||
resolve(&Resource.update_resource/3)
|
||||
end
|
||||
|
||||
@desc "Delete a resource"
|
||||
field :delete_resource, :deleted_object do
|
||||
arg(:id, non_null(:id), description: "The resource ID")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Resources.Resource,
|
||||
rule: :"write:group:resources:delete"
|
||||
)
|
||||
|
||||
resolve(&Resource.delete_resource/3)
|
||||
end
|
||||
|
||||
@desc "Get a preview for a resource link"
|
||||
field :preview_resource_link, :resource_metadata do
|
||||
arg(:resource_url, non_null(:string), description: "The link to crawl to get of preview of")
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: Mobilizon.Resources.Resource,
|
||||
rule: :"read:group:resources",
|
||||
args: %{}
|
||||
)
|
||||
|
||||
resolve(&Resource.preview_resource_link/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,6 +10,7 @@ defmodule Mobilizon.GraphQL.Schema.SearchType do
|
||||
alias Mobilizon.Service.GlobalSearch.{EventResult, GroupResult}
|
||||
|
||||
interface :event_search_result do
|
||||
meta(:authorize, :all)
|
||||
field(:id, :id, description: "Internal ID for this event")
|
||||
field(:uuid, :uuid, description: "The Event UUID")
|
||||
field(:url, :string, description: "The ActivityPub Event URL")
|
||||
@@ -43,6 +44,7 @@ defmodule Mobilizon.GraphQL.Schema.SearchType do
|
||||
|
||||
@desc "Search event result"
|
||||
object :event_result do
|
||||
meta(:authorize, :all)
|
||||
interfaces([:event_search_result])
|
||||
field(:id, :id, description: "Internal ID for this event")
|
||||
field(:uuid, :uuid, description: "The Event UUID")
|
||||
@@ -65,6 +67,7 @@ defmodule Mobilizon.GraphQL.Schema.SearchType do
|
||||
end
|
||||
|
||||
interface :group_search_result do
|
||||
meta(:authorize, :all)
|
||||
field(:id, :id, description: "Internal ID for this group")
|
||||
field(:url, :string, description: "The ActivityPub actor's URL")
|
||||
field(:type, :actor_type, description: "The type of Actor (Person, Group,…)")
|
||||
@@ -92,6 +95,7 @@ defmodule Mobilizon.GraphQL.Schema.SearchType do
|
||||
|
||||
@desc "Search group result"
|
||||
object :group_result do
|
||||
meta(:authorize, :all)
|
||||
interfaces([:group_search_result])
|
||||
field(:id, :id, description: "Internal ID for this group")
|
||||
field(:url, :string, description: "The ActivityPub actor's URL")
|
||||
@@ -109,18 +113,21 @@ defmodule Mobilizon.GraphQL.Schema.SearchType do
|
||||
|
||||
@desc "Search persons result"
|
||||
object :persons do
|
||||
meta(:authorize, [:administrator, :moderator])
|
||||
field(:total, non_null(:integer), description: "Total elements")
|
||||
field(:elements, non_null(list_of(:person)), description: "Person elements")
|
||||
end
|
||||
|
||||
@desc "Search groups result"
|
||||
object :groups do
|
||||
meta(:authorize, :all)
|
||||
field(:total, non_null(:integer), description: "Total elements")
|
||||
field(:elements, non_null(list_of(:group_search_result)), description: "Group elements")
|
||||
end
|
||||
|
||||
@desc "Search events result"
|
||||
object :events do
|
||||
meta(:authorize, :all)
|
||||
field(:total, non_null(:integer), description: "Total elements")
|
||||
field(:elements, non_null(list_of(:event_search_result)), description: "Event elements")
|
||||
end
|
||||
@@ -179,7 +186,7 @@ defmodule Mobilizon.GraphQL.Schema.SearchType do
|
||||
arg(:term, :string, default_value: "", description: "Search term")
|
||||
arg(:page, :integer, default_value: 1, description: "Result page")
|
||||
arg(:limit, :integer, default_value: 10, description: "Results limit per page")
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: [:administrator, :moderator], scope: false)
|
||||
resolve(&Search.search_persons/3)
|
||||
end
|
||||
|
||||
@@ -225,6 +232,7 @@ defmodule Mobilizon.GraphQL.Schema.SearchType do
|
||||
description: "How to sort search results"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&Search.search_groups/3)
|
||||
end
|
||||
|
||||
@@ -275,13 +283,14 @@ defmodule Mobilizon.GraphQL.Schema.SearchType do
|
||||
description: "How to sort search results"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&Search.search_events/3)
|
||||
end
|
||||
|
||||
@desc "Interact with an URI"
|
||||
field :interact, :interactable do
|
||||
arg(:uri, non_null(:string), description: "The URI for to interact with")
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&Search.interact/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,6 +8,7 @@ defmodule Mobilizon.GraphQL.Schema.StatisticsType do
|
||||
|
||||
@desc "A statistics object"
|
||||
object :statistics do
|
||||
meta(:authorize, :all)
|
||||
# Instance name
|
||||
field(:number_of_users, :integer, description: "The number of local users")
|
||||
field(:number_of_events, :integer, description: "The total number of events")
|
||||
@@ -27,6 +28,7 @@ defmodule Mobilizon.GraphQL.Schema.StatisticsType do
|
||||
end
|
||||
|
||||
object :category_statistics do
|
||||
meta(:authorize, :all)
|
||||
field(:key, :string, description: "The key for the category")
|
||||
field(:number, :integer, description: "The number of events for the given category")
|
||||
end
|
||||
@@ -34,11 +36,13 @@ defmodule Mobilizon.GraphQL.Schema.StatisticsType do
|
||||
object :statistics_queries do
|
||||
@desc "Get the instance statistics"
|
||||
field :statistics, :statistics do
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&Statistics.get_statistics/3)
|
||||
end
|
||||
|
||||
@desc "Get the instance's category statistics"
|
||||
field :category_statistics, list_of(:category_statistics) do
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&Statistics.get_category_statistics/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,6 +8,7 @@ defmodule Mobilizon.GraphQL.Schema.TagType do
|
||||
|
||||
@desc "A tag"
|
||||
object :tag do
|
||||
meta(:authorize, :all)
|
||||
field(:id, :id, description: "The tag's ID")
|
||||
field(:slug, :string, description: "The tags's slug")
|
||||
field(:title, :string, description: "The tag's title")
|
||||
@@ -26,6 +27,7 @@ defmodule Mobilizon.GraphQL.Schema.TagType do
|
||||
arg(:filter, :string, description: "The filter to apply to the search")
|
||||
arg(:page, :integer, default_value: 1, description: "The page in the paginated tags list")
|
||||
arg(:limit, :integer, default_value: 10, description: "The limit of tags per page")
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&Tag.list_tags/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,6 +9,7 @@ defmodule Mobilizon.GraphQL.Schema.Todos.TodoType do
|
||||
|
||||
@desc "A todo"
|
||||
object :todo do
|
||||
meta(:authorize, :user)
|
||||
field(:id, :id, description: "The todo's ID")
|
||||
field(:title, :string, description: "The todo's title")
|
||||
field(:status, :boolean, description: "The todo's status")
|
||||
@@ -30,6 +31,7 @@ defmodule Mobilizon.GraphQL.Schema.Todos.TodoType do
|
||||
A paginated list of todos
|
||||
"""
|
||||
object :paginated_todo_list do
|
||||
meta(:authorize, :user)
|
||||
field(:elements, list_of(:todo), description: "A list of todos")
|
||||
field(:total, :integer, description: "The total number of todos in the list")
|
||||
end
|
||||
@@ -38,6 +40,7 @@ defmodule Mobilizon.GraphQL.Schema.Todos.TodoType do
|
||||
@desc "Get a todo"
|
||||
field :todo, :todo do
|
||||
arg(:id, non_null(:id), description: "The todo ID")
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&TodoResolver.get_todo/3)
|
||||
end
|
||||
end
|
||||
@@ -50,6 +53,7 @@ defmodule Mobilizon.GraphQL.Schema.Todos.TodoType do
|
||||
arg(:status, :boolean, description: "The todo status")
|
||||
arg(:due_date, :datetime, description: "The todo due date")
|
||||
arg(:assigned_to_id, :id, description: "The actor this todo is assigned to")
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
|
||||
resolve(&TodoResolver.create_todo/3)
|
||||
end
|
||||
@@ -62,7 +66,7 @@ defmodule Mobilizon.GraphQL.Schema.Todos.TodoType do
|
||||
arg(:status, :boolean, description: "The new todo status")
|
||||
arg(:due_date, :datetime, description: "The new todo due date")
|
||||
arg(:assigned_to_id, :id, description: "The new id of the actor this todo is assigned to")
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&TodoResolver.update_todo/3)
|
||||
end
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ defmodule Mobilizon.GraphQL.Schema.Todos.TodoListType do
|
||||
|
||||
@desc "A todo list"
|
||||
object :todo_list do
|
||||
meta(:authorize, :user)
|
||||
field(:id, :id, description: "The todo list's ID")
|
||||
field(:title, :string, description: "The todo list's title")
|
||||
|
||||
@@ -37,6 +38,7 @@ defmodule Mobilizon.GraphQL.Schema.Todos.TodoListType do
|
||||
A paginated list of todo-lists
|
||||
"""
|
||||
object :paginated_todo_list_list do
|
||||
meta(:authorize, :user)
|
||||
field(:elements, list_of(:todo_list), description: "A list of todo lists")
|
||||
field(:total, :integer, description: "The total number of todo lists in the list")
|
||||
end
|
||||
@@ -45,6 +47,7 @@ defmodule Mobilizon.GraphQL.Schema.Todos.TodoListType do
|
||||
@desc "Get a todo list"
|
||||
field :todo_list, :todo_list do
|
||||
arg(:id, non_null(:id), description: "The todo-list ID")
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&Todos.get_todo_list/3)
|
||||
end
|
||||
end
|
||||
@@ -54,6 +57,7 @@ defmodule Mobilizon.GraphQL.Schema.Todos.TodoListType do
|
||||
field :create_todo_list, :todo_list do
|
||||
arg(:title, non_null(:string), description: "The todo list title")
|
||||
arg(:group_id, non_null(:id), description: "The group ID")
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&Todos.create_todo_list/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,6 +15,8 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
|
||||
@desc "A local user of Mobilizon"
|
||||
object :user do
|
||||
meta(:authorize, :all)
|
||||
meta(:scope_field?, true)
|
||||
interfaces([:action_log_object])
|
||||
field(:id, :id, description: "The user's ID")
|
||||
field(:email, non_null(:string), description: "The user's email")
|
||||
@@ -63,7 +65,8 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
field(:disabled, :boolean, description: "Whether the user is disabled")
|
||||
|
||||
field(:participations, :paginated_participant_list,
|
||||
description: "The list of participations this user has"
|
||||
description: "The list of participations this user has",
|
||||
meta: [private: true]
|
||||
) do
|
||||
arg(:after_datetime, :datetime, description: "Filter participations by event start datetime")
|
||||
|
||||
@@ -83,7 +86,8 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
end
|
||||
|
||||
field(:memberships, :paginated_member_list,
|
||||
description: "The list of memberships for this user"
|
||||
description: "The list of memberships for this user",
|
||||
meta: [private: true]
|
||||
) do
|
||||
arg(:name, :string, description: "A name to filter members by")
|
||||
|
||||
@@ -97,7 +101,8 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
end
|
||||
|
||||
field(:drafts, :paginated_event_list,
|
||||
description: "The list of draft events this user has created"
|
||||
description: "The list of draft events this user has created",
|
||||
meta: [private: true]
|
||||
) do
|
||||
arg(:page, :integer,
|
||||
default_value: 1,
|
||||
@@ -109,7 +114,8 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
end
|
||||
|
||||
field(:followed_group_events, :paginated_followed_group_events,
|
||||
description: "The suggested events from the groups this user follows"
|
||||
description: "The suggested events from the groups this user follows",
|
||||
meta: [private: true]
|
||||
) do
|
||||
arg(:page, :integer,
|
||||
default_value: 1,
|
||||
@@ -128,7 +134,10 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
resolve(&User.user_followed_group_events/3)
|
||||
end
|
||||
|
||||
field(:settings, :user_settings, description: "The list of settings for this user") do
|
||||
field(:settings, :user_settings,
|
||||
description: "The list of settings for this user",
|
||||
meta: [private: true]
|
||||
) do
|
||||
resolve(&User.user_settings/3)
|
||||
end
|
||||
|
||||
@@ -142,7 +151,10 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
description: "The IP adress the user's currently signed-in with"
|
||||
)
|
||||
|
||||
field(:media, :paginated_media_list, description: "The user's media objects") do
|
||||
field(:media, :paginated_media_list,
|
||||
description: "The user's media objects",
|
||||
meta: [private: true]
|
||||
) do
|
||||
arg(:page, :integer,
|
||||
default_value: 1,
|
||||
description: "The page in the paginated user media list"
|
||||
@@ -158,14 +170,18 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
)
|
||||
|
||||
field(:activity_settings, list_of(:activity_setting),
|
||||
resolve: &ActivitySettings.user_activity_settings/3,
|
||||
description: "The user's activity settings"
|
||||
)
|
||||
description: "The user's activity settings",
|
||||
meta: [private: true]
|
||||
) do
|
||||
resolve(&ActivitySettings.user_activity_settings/3)
|
||||
end
|
||||
|
||||
field(:auth_authorized_applications, list_of(:auth_application_token),
|
||||
resolve: &Application.get_user_applications/3,
|
||||
description: "The user's authorized authentication apps"
|
||||
)
|
||||
description: "The user's authorized authentication apps",
|
||||
meta: [private: true, rule: :forbid_app_access]
|
||||
) do
|
||||
resolve(&Application.get_user_applications/3)
|
||||
end
|
||||
end
|
||||
|
||||
@desc "The list of roles an user can have"
|
||||
@@ -177,12 +193,14 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
|
||||
@desc "Token"
|
||||
object :refreshed_token do
|
||||
meta(:authorize, :all)
|
||||
field(:access_token, non_null(:string), description: "Generated access token")
|
||||
field(:refresh_token, non_null(:string), description: "Generated refreshed token")
|
||||
end
|
||||
|
||||
@desc "Users list"
|
||||
object :users do
|
||||
meta(:authorize, [:administrator, :moderator])
|
||||
field(:total, non_null(:integer), description: "Total elements")
|
||||
field(:elements, non_null(list_of(:user)), description: "User elements")
|
||||
end
|
||||
@@ -196,6 +214,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
A set of user settings
|
||||
"""
|
||||
object :user_settings do
|
||||
meta(:authorize, :user)
|
||||
field(:timezone, :string, description: "The timezone for this user")
|
||||
|
||||
field(:notification_on_day, :boolean,
|
||||
@@ -254,6 +273,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
end
|
||||
|
||||
object :location do
|
||||
meta(:authorize, :user)
|
||||
field(:range, :integer, description: "The range in kilometers the user wants to see events")
|
||||
|
||||
field(:geohash, :string, description: "A geohash representing the user's preferred location")
|
||||
@@ -276,11 +296,13 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
@desc "Get an user"
|
||||
field :user, :user do
|
||||
arg(:id, non_null(:id))
|
||||
middleware(Rajska.QueryAuthorization, permit: [:administrator, :moderator], scope: false)
|
||||
resolve(&User.find_user/3)
|
||||
end
|
||||
|
||||
@desc "Get the current user"
|
||||
field :logged_user, :user do
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&User.get_current_user/3)
|
||||
end
|
||||
|
||||
@@ -297,7 +319,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
|
||||
arg(:sort, :sortable_user_field, default_value: :id, description: "Sort column")
|
||||
arg(:direction, :sort_direction, default_value: :desc, description: "Sort direction")
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: [:administrator, :moderator], scope: false)
|
||||
resolve(&User.list_users/3)
|
||||
end
|
||||
end
|
||||
@@ -308,7 +330,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
arg(:email, non_null(:string), description: "The new user's email")
|
||||
arg(:password, non_null(:string), description: "The new user's password")
|
||||
arg(:locale, :string, description: "The new user's locale")
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&User.create_user/3)
|
||||
end
|
||||
|
||||
@@ -318,6 +340,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
description: "The token that will be used to validate the user"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&User.validate_user/3)
|
||||
end
|
||||
|
||||
@@ -325,6 +348,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
field :resend_confirmation_email, type: :string do
|
||||
arg(:email, non_null(:string), description: "The email used to register")
|
||||
arg(:locale, :string, description: "The user's locale")
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&User.resend_confirmation_email/3)
|
||||
end
|
||||
|
||||
@@ -332,6 +356,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
field :send_reset_password, type: :string do
|
||||
arg(:email, non_null(:string), description: "The user's email")
|
||||
arg(:locale, :string, description: "The user's locale")
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&User.send_reset_password/3)
|
||||
end
|
||||
|
||||
@@ -343,6 +368,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
|
||||
arg(:password, non_null(:string), description: "The new password")
|
||||
arg(:locale, :string, default_value: "en", description: "The user's locale")
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&User.reset_password/3)
|
||||
end
|
||||
|
||||
@@ -350,24 +376,28 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
field :login, type: :login do
|
||||
arg(:email, non_null(:string), description: "The user's email")
|
||||
arg(:password, non_null(:string), description: "The user's password")
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&User.login_user/3)
|
||||
end
|
||||
|
||||
@desc "Refresh a token"
|
||||
field :refresh_token, type: :refreshed_token do
|
||||
arg(:refresh_token, non_null(:string), description: "A refresh token")
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&User.refresh_token/3)
|
||||
end
|
||||
|
||||
@desc "Logout an user, deleting a refresh token"
|
||||
field :logout, :string do
|
||||
arg(:refresh_token, non_null(:string))
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&User.logout/3)
|
||||
end
|
||||
|
||||
@desc "Change default actor for user"
|
||||
field :change_default_actor, :user do
|
||||
arg(:preferred_username, non_null(:string), description: "The actor preferred_username")
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&User.change_default_actor/3)
|
||||
end
|
||||
|
||||
@@ -375,6 +405,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
field :change_password, :user do
|
||||
arg(:old_password, non_null(:string), description: "The user's current password")
|
||||
arg(:new_password, non_null(:string), description: "The user's new password")
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&User.change_password/3)
|
||||
end
|
||||
|
||||
@@ -382,6 +413,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
field :change_email, :user do
|
||||
arg(:email, non_null(:string), description: "The user's new email")
|
||||
arg(:password, non_null(:string), description: "The user's current password")
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&User.change_email/3)
|
||||
end
|
||||
|
||||
@@ -391,6 +423,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
description: "The token that will be used to validate the email change"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :all)
|
||||
resolve(&User.validate_email/3)
|
||||
end
|
||||
|
||||
@@ -398,6 +431,7 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
field :delete_account, :deleted_object do
|
||||
arg(:password, :string, description: "The user's password")
|
||||
arg(:user_id, :id, description: "The user's ID")
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&User.delete_account/3)
|
||||
end
|
||||
|
||||
@@ -435,12 +469,14 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
||||
description: "A geohash of the user's preferred location, where they want to see events"
|
||||
)
|
||||
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&User.set_user_setting/3)
|
||||
end
|
||||
|
||||
@desc "Update the user's locale"
|
||||
field :update_locale, :user do
|
||||
arg(:locale, :string, description: "The user's new locale")
|
||||
middleware(Rajska.QueryAuthorization, permit: :user, scope: false)
|
||||
resolve(&User.update_locale/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,6 +6,7 @@ defmodule Mobilizon.GraphQL.Schema.Users.ActivitySetting do
|
||||
alias Mobilizon.GraphQL.Resolvers.Users.ActivitySettings
|
||||
|
||||
object :activity_setting do
|
||||
meta(:authorize, :user)
|
||||
field(:key, :string)
|
||||
field(:method, :string)
|
||||
field(:enabled, :boolean)
|
||||
@@ -17,6 +18,13 @@ defmodule Mobilizon.GraphQL.Schema.Users.ActivitySetting do
|
||||
arg(:key, non_null(:string))
|
||||
arg(:method, non_null(:string))
|
||||
arg(:enabled, non_null(:boolean))
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: false,
|
||||
rule: :"write:user:setting:activity"
|
||||
)
|
||||
|
||||
resolve(&ActivitySettings.upsert_user_activity_setting/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -26,11 +26,25 @@ defmodule Mobilizon.GraphQL.Schema.Users.PushSubscription do
|
||||
arg(:endpoint, non_null(:string))
|
||||
arg(:auth, non_null(:string))
|
||||
arg(:p256dh, non_null(:string))
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: false,
|
||||
rule: :"write:user:setting:push"
|
||||
)
|
||||
|
||||
resolve(&PushSubscription.register_push_subscription/3)
|
||||
end
|
||||
|
||||
field :unregister_push, :string do
|
||||
arg(:endpoint, non_null(:string))
|
||||
|
||||
middleware(Rajska.QueryAuthorization,
|
||||
permit: :user,
|
||||
scope: false,
|
||||
rule: :"write:user:setting:push"
|
||||
)
|
||||
|
||||
resolve(&PushSubscription.unregister_push_subscription/3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,6 +12,7 @@ defmodule Mobilizon.Applications do
|
||||
defenum(ApplicationDeviceActivationStatus, [
|
||||
"success",
|
||||
"pending",
|
||||
"confirmed",
|
||||
"incorrect_device_code",
|
||||
"access_denied"
|
||||
])
|
||||
@@ -144,12 +145,15 @@ defmodule Mobilizon.Applications do
|
||||
|
||||
"""
|
||||
def list_application_tokens do
|
||||
Repo.all(ApplicationToken)
|
||||
ApplicationToken
|
||||
|> Repo.all()
|
||||
|> Repo.preload(:application)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the list of application tokens for a given user_id
|
||||
"""
|
||||
@spec list_application_tokens_for_user_id(number() | String.t()) :: list(ApplicationToken.t())
|
||||
def list_application_tokens_for_user_id(user_id) do
|
||||
ApplicationToken
|
||||
|> where(user_id: ^user_id)
|
||||
@@ -172,7 +176,11 @@ defmodule Mobilizon.Applications do
|
||||
** (Ecto.NoResultsError)
|
||||
|
||||
"""
|
||||
def get_application_token!(id), do: Repo.get!(ApplicationToken, id)
|
||||
def get_application_token!(id) do
|
||||
ApplicationToken
|
||||
|> Repo.get!(id)
|
||||
|> Repo.preload([:application])
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single application_token.
|
||||
@@ -211,6 +219,13 @@ defmodule Mobilizon.Applications do
|
||||
%ApplicationToken{}
|
||||
|> ApplicationToken.changeset(attrs)
|
||||
|> Repo.insert(on_conflict: :replace_all, conflict_target: [:user_id, :application_id])
|
||||
|> case do
|
||||
{:ok, application_token} ->
|
||||
{:ok, Repo.preload(application_token, :application)}
|
||||
|
||||
error ->
|
||||
error
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
@@ -303,10 +318,14 @@ defmodule Mobilizon.Applications do
|
||||
|
||||
def get_application_device_activation(id), do: Repo.get(ApplicationDeviceActivation, id)
|
||||
|
||||
def get_application_device_activation_by_user_code(user_code),
|
||||
do: Repo.get_by(ApplicationDeviceActivation, user_code: user_code)
|
||||
def get_application_device_activation_by_user_code(user_code) do
|
||||
ApplicationDeviceActivation
|
||||
|> where([ada], ada.user_code == ^user_code)
|
||||
|> preload(:application)
|
||||
|> Repo.one()
|
||||
end
|
||||
|
||||
def get_application_device_activation(client_id, device_code) do
|
||||
def get_application_device_activation_by_device_code(client_id, device_code) do
|
||||
ApplicationDeviceActivation
|
||||
|> join(:left, [ada], a in assoc(ada, :application))
|
||||
|> where([_, a], a.client_id == ^client_id)
|
||||
|
||||
@@ -6,16 +6,16 @@ defmodule Mobilizon.Applications.Application do
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
@required_attrs [:name, :client_id, :client_secret, :redirect_uris]
|
||||
@optional_attrs [:scopes, :website, :owner_type, :owner_id]
|
||||
@required_attrs [:name, :client_id, :client_secret, :redirect_uris, :scope]
|
||||
@optional_attrs [:website, :owner_type, :owner_id]
|
||||
@attrs @required_attrs ++ @optional_attrs
|
||||
|
||||
schema "applications" do
|
||||
field(:name, :string)
|
||||
field(:client_id, :string)
|
||||
field(:client_secret, :string)
|
||||
field(:redirect_uris, :string)
|
||||
field(:scopes, :string)
|
||||
field(:redirect_uris, {:array, :string})
|
||||
field(:scope, :string)
|
||||
field(:website, :string)
|
||||
field(:owner_type, :string)
|
||||
field(:owner_id, :integer)
|
||||
|
||||
@@ -19,7 +19,7 @@ defmodule Mobilizon.Applications.ApplicationDeviceActivation do
|
||||
timestamps()
|
||||
end
|
||||
|
||||
@required_attrs [:user_code, :device_code, :expires_in, :application_id]
|
||||
@required_attrs [:user_code, :device_code, :expires_in, :application_id, :scope]
|
||||
@optional_attrs [:status, :user_id]
|
||||
@attrs @required_attrs ++ @optional_attrs
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ defmodule Mobilizon.Applications.ApplicationToken do
|
||||
belongs_to(:user, User)
|
||||
belongs_to(:application, Application)
|
||||
field(:authorization_code, :string)
|
||||
field(:status, ApplicationTokenStatus)
|
||||
field(:status, ApplicationTokenStatus, default: :pending)
|
||||
field(:scope, :string)
|
||||
|
||||
timestamps()
|
||||
|
||||
@@ -4,9 +4,12 @@ defmodule Mobilizon.Service.Auth.Applications do
|
||||
"""
|
||||
alias Mobilizon.Applications
|
||||
alias Mobilizon.Applications.{Application, ApplicationDeviceActivation, ApplicationToken}
|
||||
alias Mobilizon.GraphQL.Authorization.AppScope
|
||||
alias Mobilizon.Service.Auth.Authenticator
|
||||
alias Mobilizon.Users.User
|
||||
alias Mobilizon.Web.Auth.Guardian
|
||||
alias Mobilizon.Web.Router.Helpers, as: Routes
|
||||
require Logger
|
||||
|
||||
@app_access_tokens_ttl {8, :hour}
|
||||
@app_refresh_tokens_ttl {26, :week}
|
||||
@@ -20,37 +23,43 @@ defmodule Mobilizon.Service.Auth.Applications do
|
||||
required(:token_type) => String.t()
|
||||
}
|
||||
|
||||
def create(name, redirect_uris, scopes, website) do
|
||||
client_id = :crypto.strong_rand_bytes(42) |> Base.encode64() |> binary_part(0, 42)
|
||||
client_secret = :crypto.strong_rand_bytes(42) |> Base.encode64() |> binary_part(0, 42)
|
||||
@spec create(String.t(), list(String.t()), String.t(), String.t() | nil) ::
|
||||
{:ok, Application.t()} | {:error, Ecto.Changeset.t()} | {:error, :invalid_scope}
|
||||
def create(name, redirect_uris, scope, website \\ nil) do
|
||||
if AppScope.scopes_valid?(scope) do
|
||||
client_id = :crypto.strong_rand_bytes(42) |> Base.encode64() |> binary_part(0, 42)
|
||||
client_secret = :crypto.strong_rand_bytes(42) |> Base.encode64() |> binary_part(0, 42)
|
||||
|
||||
Applications.create_application(%{
|
||||
name: name,
|
||||
redirect_uris: redirect_uris,
|
||||
scopes: scopes,
|
||||
website: website,
|
||||
client_id: client_id,
|
||||
client_secret: client_secret
|
||||
})
|
||||
Applications.create_application(%{
|
||||
name: name,
|
||||
redirect_uris: redirect_uris,
|
||||
scope: scope,
|
||||
website: website,
|
||||
client_id: client_id,
|
||||
client_secret: client_secret
|
||||
})
|
||||
else
|
||||
{:error, :invalid_scope}
|
||||
end
|
||||
end
|
||||
|
||||
@spec autorize(String.t(), String.t(), String.t(), integer()) ::
|
||||
{:ok, String.t()}
|
||||
{:ok, ApplicationToken.t()}
|
||||
| {:error, :application_not_found}
|
||||
| {:error, :redirect_uri_not_in_allowed}
|
||||
def autorize(client_id, redirect_uri, _scope, user_id) do
|
||||
| {:error, Ecto.Changeset.t()}
|
||||
def autorize(client_id, redirect_uri, scope, user_id) do
|
||||
with %Application{redirect_uris: redirect_uris, id: app_id} <-
|
||||
Applications.get_application_by_client_id(client_id),
|
||||
{:redirect_uri, true} <-
|
||||
{:redirect_uri, redirect_uri in String.split(redirect_uris, "\n")},
|
||||
code <- :crypto.strong_rand_bytes(16) |> Base.encode64() |> binary_part(0, 16),
|
||||
{:ok, %ApplicationToken{}} <-
|
||||
Applications.create_application_token(%{
|
||||
user_id: user_id,
|
||||
application_id: app_id,
|
||||
authorization_code: code
|
||||
}) do
|
||||
{:ok, code}
|
||||
{:redirect_uri, redirect_uri in redirect_uris},
|
||||
code <- :crypto.strong_rand_bytes(16) |> Base.encode64() |> binary_part(0, 16) do
|
||||
Applications.create_application_token(%{
|
||||
user_id: user_id,
|
||||
application_id: app_id,
|
||||
authorization_code: code,
|
||||
scope: scope
|
||||
})
|
||||
else
|
||||
nil ->
|
||||
{:error, :application_not_found}
|
||||
@@ -60,35 +69,62 @@ defmodule Mobilizon.Service.Auth.Applications do
|
||||
end
|
||||
end
|
||||
|
||||
@spec autorize_device_application(String.t(), String.t()) ::
|
||||
{:ok, ApplicationDeviceActivation.t()}
|
||||
| {:error, Ecto.Changeset.t()}
|
||||
| {:error, :expired}
|
||||
| {:error, :access_denied}
|
||||
| {:error, :not_found}
|
||||
def autorize_device_application(client_id, user_code) do
|
||||
case Applications.get_application_device_activation(client_id, user_code) do
|
||||
%ApplicationDeviceActivation{status: :confirmed} = app_device_activation ->
|
||||
Applications.update_application_device_activation(app_device_activation, %{
|
||||
status: :success
|
||||
})
|
||||
Logger.debug(
|
||||
"Authorizing device application client_id: #{client_id}, user_code: #{user_code}"
|
||||
)
|
||||
|
||||
case Applications.get_application_device_activation_by_user_code(user_code) do
|
||||
%ApplicationDeviceActivation{
|
||||
status: :confirmed,
|
||||
application: %Application{client_id: ^client_id}
|
||||
} = app_device_activation ->
|
||||
if device_activation_expired?(app_device_activation) do
|
||||
{:error, :expired}
|
||||
else
|
||||
Applications.update_application_device_activation(app_device_activation, %{
|
||||
status: :success
|
||||
})
|
||||
end
|
||||
|
||||
# The device activation is confirmed, but does not match the given app client_id, so we say it's not found
|
||||
%ApplicationDeviceActivation{status: :confirmed} ->
|
||||
{:error, :not_found}
|
||||
|
||||
%ApplicationDeviceActivation{} ->
|
||||
{:error, :not_confirmed}
|
||||
|
||||
nil ->
|
||||
{:error, :not_found}
|
||||
end
|
||||
end
|
||||
|
||||
@spec generate_access_token(String.t(), String.t(), String.t(), String.t()) ::
|
||||
@spec generate_access_token(String.t(), String.t(), String.t(), String.t(), String.t()) ::
|
||||
{:ok, access_token_details()}
|
||||
| {:error,
|
||||
:application_not_found
|
||||
| :redirect_uri_not_in_allowed
|
||||
| :provided_code_does_not_match
|
||||
| :invalid_client_secret
|
||||
| :app_token_not_found
|
||||
| :invalid_or_expired
|
||||
| any()}
|
||||
def generate_access_token(client_id, client_secret, code, redirect_uri) do
|
||||
def generate_access_token(client_id, client_secret, code, redirect_uri, scope) do
|
||||
with {:application,
|
||||
%Application{
|
||||
id: application_id,
|
||||
client_secret: app_client_secret,
|
||||
scopes: scopes,
|
||||
redirect_uris: redirect_uris
|
||||
}} <-
|
||||
{:application, Applications.get_application_by_client_id(client_id)},
|
||||
# TODO: check that app token scope still are acceptable
|
||||
{:redirect_uri, true} <-
|
||||
{:redirect_uri, redirect_uri in String.split(redirect_uris, "\n")},
|
||||
{:redirect_uri, redirect_uri in redirect_uris},
|
||||
{:app_token, %ApplicationToken{} = app_token} <-
|
||||
{:app_token, Applications.get_application_token_by_authorization_code(code)},
|
||||
{:ok, %ApplicationToken{application_id: application_id_from_token} = app_token} <-
|
||||
@@ -105,7 +141,7 @@ defmodule Mobilizon.Service.Auth.Applications do
|
||||
expires_in: ttl_to_seconds(@app_access_tokens_ttl),
|
||||
refresh_token: refresh_token,
|
||||
refresh_token_expires_in: ttl_to_seconds(@app_refresh_tokens_ttl),
|
||||
scope: scopes,
|
||||
scope: scope,
|
||||
token_type: "bearer"
|
||||
}}
|
||||
else
|
||||
@@ -122,15 +158,20 @@ defmodule Mobilizon.Service.Auth.Applications do
|
||||
{:error, :redirect_uri_not_in_allowed}
|
||||
|
||||
{:app_token, _} ->
|
||||
{:error, :app_token_not_found}
|
||||
{:error, :invalid_or_expired}
|
||||
|
||||
{:error, err} ->
|
||||
{:error, err}
|
||||
end
|
||||
end
|
||||
|
||||
def generate_access_token(client_id, device_code) do
|
||||
case Applications.get_application_device_activation(client_id, device_code) do
|
||||
def generate_access_token_for_device_flow(client_id, device_code) do
|
||||
Logger.debug("Generating access token for application device with",
|
||||
client_id: client_id,
|
||||
device_code: device_code
|
||||
)
|
||||
|
||||
case Applications.get_application_device_activation_by_device_code(client_id, device_code) do
|
||||
%ApplicationDeviceActivation{status: :success, scope: scope, user_id: user_id} =
|
||||
app_device_activation ->
|
||||
if device_activation_expired?(app_device_activation) do
|
||||
@@ -164,13 +205,17 @@ defmodule Mobilizon.Service.Auth.Applications do
|
||||
end
|
||||
|
||||
%ApplicationDeviceActivation{status: :incorrect_device_code} ->
|
||||
Logger.error("Incorrect device code set")
|
||||
{:error, :incorrect_device_code}
|
||||
|
||||
%ApplicationDeviceActivation{status: :access_denied} ->
|
||||
{:error, :access_denied}
|
||||
|
||||
nil ->
|
||||
Logger.error("nil returned")
|
||||
{:error, :incorrect_device_code}
|
||||
|
||||
err ->
|
||||
require Logger
|
||||
Logger.error(inspect(err))
|
||||
{:error, :incorrect_device_code}
|
||||
end
|
||||
@@ -191,35 +236,42 @@ defmodule Mobilizon.Service.Auth.Applications do
|
||||
|
||||
@spec register_device_code(String.t(), String.t() | nil) ::
|
||||
{:ok, ApplicationDeviceActivation.t()}
|
||||
| {:error, :application_not_found}
|
||||
| {:error, :scope_not_included}
|
||||
| {:error, Ecto.Changeset.t()}
|
||||
def register_device_code(client_id, scope) do
|
||||
%Application{} = application = Applications.get_application_by_client_id(client_id)
|
||||
device_code = string_of_length(40)
|
||||
user_code = string_of_length(8)
|
||||
verification_uri = Routes.page_url(Mobilizon.Web.Endpoint, :auth_device)
|
||||
expires_in = @expires_in
|
||||
interval = @interval
|
||||
|
||||
case Applications.create_application_device_activation(%{
|
||||
device_code: device_code,
|
||||
user_code: user_code,
|
||||
expires_in: expires_in,
|
||||
application_id: application.id,
|
||||
scope: scope
|
||||
}) do
|
||||
{:ok, %ApplicationDeviceActivation{} = application_device_activation} ->
|
||||
{:ok,
|
||||
application_device_activation
|
||||
|> Map.from_struct()
|
||||
|> Map.take([:device_code, :user_code, :expires_in])
|
||||
|> Map.update!(:user_code, &user_code_displayed/1)
|
||||
|> Map.merge(%{
|
||||
interval: interval,
|
||||
verification_uri: verification_uri
|
||||
})}
|
||||
|
||||
with {:app, %Application{scope: app_scope} = application} <-
|
||||
{:app, Applications.get_application_by_client_id(client_id)},
|
||||
{device_code, user_code, verification_uri} <-
|
||||
{string_of_length(40), string_of_length(8),
|
||||
Routes.page_url(Mobilizon.Web.Endpoint, :auth_device)},
|
||||
{:scope_included, true} <- {:scope_included, request_scope_valid?(app_scope, scope)},
|
||||
{:ok, %ApplicationDeviceActivation{} = application_device_activation} <-
|
||||
Applications.create_application_device_activation(%{
|
||||
device_code: device_code,
|
||||
user_code: user_code,
|
||||
expires_in: @expires_in,
|
||||
application_id: application.id,
|
||||
scope: scope
|
||||
}) do
|
||||
{:ok,
|
||||
application_device_activation
|
||||
|> Map.from_struct()
|
||||
|> Map.take([:device_code, :user_code, :expires_in])
|
||||
|> Map.update!(:user_code, &user_code_displayed/1)
|
||||
|> Map.merge(%{
|
||||
interval: @interval,
|
||||
verification_uri: verification_uri
|
||||
})}
|
||||
else
|
||||
{:error, %Ecto.Changeset{} = err} ->
|
||||
{:error, err}
|
||||
|
||||
{:app, nil} ->
|
||||
{:error, :application_not_found}
|
||||
|
||||
{:scope_included, false} ->
|
||||
{:error, :scope_not_included}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -245,6 +297,45 @@ defmodule Mobilizon.Service.Auth.Applications do
|
||||
end
|
||||
end
|
||||
|
||||
@spec refresh_tokens(String.t(), String.t(), String.t()) ::
|
||||
{:ok, access_token_details()}
|
||||
| {:error, :invalid_client_credentials}
|
||||
| {:error, :invalid_refresh_token}
|
||||
| {:error, any()}
|
||||
def refresh_tokens(refresh_token, user_client_id, user_client_secret) do
|
||||
with {:resource_from_token,
|
||||
{:ok,
|
||||
%ApplicationToken{
|
||||
application: %Application{client_id: app_client_id, client_secret: app_client_secret},
|
||||
scope: scope
|
||||
} = app_token,
|
||||
_claims}} <- {:resource_from_token, Guardian.resource_from_token(refresh_token)},
|
||||
{:valid_client_credentials, true} <-
|
||||
{:valid_client_credentials,
|
||||
app_client_id == user_client_id and app_client_secret == user_client_secret},
|
||||
{:ok, _old, {exchanged_token, _claims}} <-
|
||||
Guardian.exchange(refresh_token, "refresh", "access", ttl: @app_access_tokens_ttl),
|
||||
{:ok, new_refresh_token} <-
|
||||
Authenticator.generate_refresh_token(app_token, @app_refresh_tokens_ttl),
|
||||
{:ok, _claims} <- Guardian.revoke(refresh_token) do
|
||||
{:ok,
|
||||
%{
|
||||
access_token: exchanged_token,
|
||||
expires_in: ttl_to_seconds(@app_access_tokens_ttl),
|
||||
refresh_token: new_refresh_token,
|
||||
refresh_token_expires_in: ttl_to_seconds(@app_refresh_tokens_ttl),
|
||||
scope: scope,
|
||||
token_type: "bearer"
|
||||
}}
|
||||
else
|
||||
{:valid_client_credentials, false} ->
|
||||
{:error, :invalid_client_credentials}
|
||||
|
||||
{:resource_from_token, _} ->
|
||||
{:error, :invalid_refresh_token}
|
||||
end
|
||||
end
|
||||
|
||||
defp user_code_displayed(user_code) do
|
||||
String.slice(user_code, 0..3) <> "-" <> String.slice(user_code, 4..7)
|
||||
end
|
||||
@@ -265,6 +356,12 @@ defmodule Mobilizon.Service.Auth.Applications do
|
||||
expires_in: expires_in
|
||||
}) do
|
||||
NaiveDateTime.compare(NaiveDateTime.add(inserted_at, expires_in), NaiveDateTime.utc_now()) ==
|
||||
:gt
|
||||
:lt
|
||||
end
|
||||
|
||||
defp request_scope_valid?(app_scope, request_scope) do
|
||||
app_scopes = app_scope |> String.split(" ") |> MapSet.new()
|
||||
request_scopes = request_scope |> String.split(" ") |> MapSet.new()
|
||||
MapSet.subset?(request_scopes, app_scopes)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -38,7 +38,7 @@ defmodule Mobilizon.Web.Auth.Context do
|
||||
|> set_app_token_context(context, app_token)
|
||||
|> set_user_context(user)
|
||||
|
||||
nil ->
|
||||
_ ->
|
||||
{conn, context}
|
||||
end
|
||||
|
||||
|
||||
@@ -3,11 +3,12 @@ defmodule Mobilizon.Web.Auth.ErrorHandler do
|
||||
In case we have an auth error
|
||||
"""
|
||||
import Plug.Conn
|
||||
require Logger
|
||||
|
||||
# sobelow_skip ["XSS.SendResp"]
|
||||
@spec auth_error(Plug.Conn.t(), any(), any()) :: Plug.Conn.t()
|
||||
def auth_error(conn, {type, _reason}, _opts) do
|
||||
body = Jason.encode!(%{message: to_string(type)})
|
||||
def auth_error(conn, {type, reason}, _opts) do
|
||||
body = Jason.encode!(%{message: to_string(type), details: inspect(reason)})
|
||||
send_resp(conn, 401, body)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -43,7 +43,9 @@ defmodule Mobilizon.Web.Auth.Guardian do
|
||||
{:error, :invalid_id}
|
||||
end
|
||||
rescue
|
||||
Ecto.NoResultsError -> {:error, :no_result}
|
||||
e in Ecto.NoResultsError ->
|
||||
Logger.warn("Received token claim for non existing user: #{inspect(e)}")
|
||||
{:error, :no_result}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -62,7 +64,9 @@ defmodule Mobilizon.Web.Auth.Guardian do
|
||||
{:error, :invalid_id}
|
||||
end
|
||||
rescue
|
||||
Ecto.NoResultsError -> {:error, :no_result}
|
||||
e in Ecto.NoResultsError ->
|
||||
Logger.info("Received token claim for non existing app token: #{inspect(e.message)}")
|
||||
{:error, :no_result}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -79,6 +83,8 @@ defmodule Mobilizon.Web.Auth.Guardian do
|
||||
|
||||
@spec on_verify(any(), any(), any()) :: {:ok, map()} | {:error, :token_not_found}
|
||||
def on_verify(claims, token, _options) do
|
||||
Logger.debug("[Guardian] Called on_verify")
|
||||
|
||||
with {:ok, _} <- Guardian.DB.on_verify(claims, token) do
|
||||
{:ok, claims}
|
||||
end
|
||||
@@ -86,6 +92,8 @@ defmodule Mobilizon.Web.Auth.Guardian do
|
||||
|
||||
@spec on_revoke(any(), any(), any()) :: {:ok, map()} | {:error, :could_not_revoke_token}
|
||||
def on_revoke(claims, token, _options) do
|
||||
Logger.debug("[Guardian] Called on_revoke")
|
||||
|
||||
with {:ok, _} <- Guardian.DB.on_revoke(claims, token) do
|
||||
{:ok, claims}
|
||||
end
|
||||
@@ -94,6 +102,8 @@ defmodule Mobilizon.Web.Auth.Guardian do
|
||||
@spec on_refresh({any(), any()}, {any(), any()}, any()) ::
|
||||
{:ok, {String.t(), map()}, {String.t(), map()}} | {:error, any()}
|
||||
def on_refresh({old_token, old_claims}, {new_token, new_claims}, _options) do
|
||||
Logger.debug("[Guardian] Called on_refresh")
|
||||
|
||||
with {:ok, _, _} <- Guardian.DB.on_refresh({old_token, old_claims}, {new_token, new_claims}) do
|
||||
{:ok, {old_token, old_claims}, {new_token, new_claims}}
|
||||
end
|
||||
@@ -101,7 +111,10 @@ defmodule Mobilizon.Web.Auth.Guardian do
|
||||
|
||||
@spec on_exchange(any(), any(), any()) ::
|
||||
{:ok, {String.t(), map()}, {String.t(), map()}} | {:error, any()}
|
||||
def on_exchange(old_stuff, new_stuff, options), do: on_refresh(old_stuff, new_stuff, options)
|
||||
def on_exchange(old_stuff, new_stuff, options) do
|
||||
Logger.debug("[Guardian] Called on_exchange")
|
||||
on_refresh(old_stuff, new_stuff, options)
|
||||
end
|
||||
|
||||
# def build_claims(claims, _resource, opts) do
|
||||
# claims = claims
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
defmodule Mobilizon.Web.ApplicationController do
|
||||
use Mobilizon.Web, :controller
|
||||
|
||||
alias Mobilizon.Applications.{Application, ApplicationDeviceActivation}
|
||||
alias Mobilizon.Applications.Application
|
||||
alias Mobilizon.Service.Auth.Applications
|
||||
plug(:put_layout, false)
|
||||
import Mobilizon.Web.Gettext, only: [dgettext: 2]
|
||||
@@ -11,11 +11,14 @@ defmodule Mobilizon.Web.ApplicationController do
|
||||
Create an application
|
||||
"""
|
||||
@spec create_application(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
||||
def create_application(conn, %{"name" => name, "redirect_uris" => redirect_uris} = args) do
|
||||
def create_application(
|
||||
conn,
|
||||
%{"name" => name, "redirect_uris" => redirect_uris, "scope" => scope} = args
|
||||
) do
|
||||
case Applications.create(
|
||||
name,
|
||||
redirect_uris,
|
||||
Map.get(args, "scopes"),
|
||||
String.split(redirect_uris, "\n"),
|
||||
scope,
|
||||
Map.get(args, "website")
|
||||
) do
|
||||
{:ok, %Application{} = app} ->
|
||||
@@ -24,7 +27,19 @@ defmodule Mobilizon.Web.ApplicationController do
|
||||
Map.take(app, [:name, :website, :redirect_uris, :client_id, :client_secret, :scope])
|
||||
)
|
||||
|
||||
{:error, _error} ->
|
||||
{:error, :invalid_scope} ->
|
||||
send_resp(
|
||||
conn,
|
||||
400,
|
||||
dgettext(
|
||||
"errors",
|
||||
"The scope parameter is not a space separated list of valid scopes"
|
||||
)
|
||||
)
|
||||
|
||||
{:error, error} ->
|
||||
Logger.error(inspect(error))
|
||||
|
||||
send_resp(
|
||||
conn,
|
||||
500,
|
||||
@@ -42,7 +57,7 @@ defmodule Mobilizon.Web.ApplicationController do
|
||||
400,
|
||||
dgettext(
|
||||
"errors",
|
||||
"Both name and redirect_uri parameters are required to create an application"
|
||||
"All of name, scope and redirect_uri parameters are required to create an application"
|
||||
)
|
||||
)
|
||||
end
|
||||
@@ -60,14 +75,15 @@ defmodule Mobilizon.Web.ApplicationController do
|
||||
client_id = conn.query_params["client_id"]
|
||||
redirect_uri = conn.query_params["redirect_uri"]
|
||||
state = conn.query_params["state"]
|
||||
scope = conn.query_params["scope"]
|
||||
|
||||
if is_binary(client_id) and is_binary(redirect_uri) and is_binary(state) do
|
||||
if is_binary(client_id) and is_binary(redirect_uri) and is_binary(state) and is_binary(scope) do
|
||||
redirect(conn,
|
||||
to:
|
||||
Routes.page_path(conn, :authorize,
|
||||
client_id: client_id,
|
||||
redirect_uri: redirect_uri,
|
||||
scope: conn.query_params["scope"],
|
||||
scope: scope,
|
||||
state: state
|
||||
)
|
||||
)
|
||||
@@ -77,14 +93,14 @@ defmodule Mobilizon.Web.ApplicationController do
|
||||
400,
|
||||
dgettext(
|
||||
"errors",
|
||||
"You need to specify client_id, redirect_uri and state to autorize an application"
|
||||
"You need to specify client_id, redirect_uri, scope and state to autorize an application"
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def device_code(conn, %{"client_id" => client_id} = args) do
|
||||
case Applications.register_device_code(client_id, Map.get(args, "scope")) do
|
||||
def device_code(conn, %{"client_id" => client_id, "scope" => scope}) do
|
||||
case Applications.register_device_code(client_id, scope) do
|
||||
{:ok, res} when is_map(res) ->
|
||||
case get_format(conn) do
|
||||
"json" ->
|
||||
@@ -94,6 +110,12 @@ defmodule Mobilizon.Web.ApplicationController do
|
||||
send_resp(conn, 200, URI.encode_query(res))
|
||||
end
|
||||
|
||||
{:error, :scope_not_included} ->
|
||||
send_resp(conn, 400, "The given scope is not in the list of the app declared scopes")
|
||||
|
||||
{:error, :application_not_found} ->
|
||||
send_resp(conn, 400, "No application with this client_id was found")
|
||||
|
||||
{:error, %Ecto.Changeset{} = err} ->
|
||||
Logger.error(inspect(err))
|
||||
send_resp(conn, 500, "Unable to produce device code")
|
||||
@@ -101,7 +123,11 @@ defmodule Mobilizon.Web.ApplicationController do
|
||||
end
|
||||
|
||||
def device_code(conn, _args) do
|
||||
send_resp(conn, 400, "You need to send to send at least client_id to obtain a device code")
|
||||
send_resp(
|
||||
conn,
|
||||
400,
|
||||
"You need to pass both client_id and scope as parameters to obtain a device code"
|
||||
)
|
||||
end
|
||||
|
||||
@spec generate_access_token(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
||||
@@ -109,59 +135,106 @@ defmodule Mobilizon.Web.ApplicationController do
|
||||
"client_id" => client_id,
|
||||
"client_secret" => client_secret,
|
||||
"code" => code,
|
||||
"redirect_uri" => redirect_uri
|
||||
"redirect_uri" => redirect_uri,
|
||||
"scope" => scope,
|
||||
"grant_type" => "authorization_code"
|
||||
}) do
|
||||
case Applications.generate_access_token(client_id, client_secret, code, redirect_uri) do
|
||||
case do_generate_access_token(client_id, client_secret, code, redirect_uri, scope) do
|
||||
{:ok, token} ->
|
||||
redirect(conn, external: generate_redirect_with_query_params(redirect_uri, token))
|
||||
json(conn, token)
|
||||
|
||||
{:error, :application_not_found} ->
|
||||
send_resp(conn, 400, dgettext("errors", "No application was found with this client_id"))
|
||||
|
||||
{:error, :redirect_uri_not_in_allowed} ->
|
||||
send_resp(conn, 400, dgettext("errors", "This redirect URI is not allowed"))
|
||||
|
||||
{:error, :invalid_or_expired} ->
|
||||
send_resp(conn, 400, dgettext("errors", "The provided code is invalid or expired"))
|
||||
|
||||
{:error, :invalid_client_id} ->
|
||||
send_resp(
|
||||
conn,
|
||||
400,
|
||||
dgettext("errors", "The provided client_id does not match the provided code")
|
||||
)
|
||||
|
||||
{:error, :invalid_client_secret} ->
|
||||
send_resp(conn, 400, dgettext("errors", "The provided client_secret is invalid"))
|
||||
|
||||
{:error, :user_not_found} ->
|
||||
send_resp(conn, 400, dgettext("errors", "The user for this code was not found"))
|
||||
{:error, msg} ->
|
||||
Logger.debug(msg)
|
||||
json(conn, %{error: true, details: msg})
|
||||
end
|
||||
end
|
||||
|
||||
def generate_access_token(conn, %{
|
||||
"client_id" => client_id,
|
||||
"device_code" => device_code,
|
||||
"grant_type" => "urn:ietf:params:oauth:grant-type:device_code",
|
||||
"_format" => "json"
|
||||
}) do
|
||||
json(conn, Applications.generate_access_token(client_id, device_code))
|
||||
end
|
||||
|
||||
def generate_access_token(conn, %{
|
||||
"client_id" => client_id,
|
||||
"device_code" => device_code,
|
||||
"grant_type" => "urn:ietf:params:oauth:grant-type:device_code"
|
||||
}) do
|
||||
case Applications.generate_access_token_for_device_flow(client_id, device_code) do
|
||||
{:ok, res} ->
|
||||
case get_format(conn) do
|
||||
"json" ->
|
||||
json(conn, res)
|
||||
|
||||
_ ->
|
||||
send_resp(
|
||||
conn,
|
||||
200,
|
||||
URI.encode_query(res)
|
||||
)
|
||||
end
|
||||
|
||||
{:error, :incorrect_device_code} ->
|
||||
send_resp(conn, 400, "The client_id provided or the device_code associated is invalid")
|
||||
|
||||
{:error, :access_denied} ->
|
||||
send_resp(conn, 401, "The user rejected the requested authorization")
|
||||
|
||||
{:error, :expired} ->
|
||||
send_resp(conn, 400, "The given device_code has expired")
|
||||
end
|
||||
end
|
||||
|
||||
def generate_access_token(conn, %{
|
||||
"refresh_token" => refresh_token,
|
||||
"grant_type" => "refresh_token",
|
||||
"client_id" => client_id,
|
||||
"client_secret" => client_secret
|
||||
}) do
|
||||
case Applications.refresh_tokens(refresh_token, client_id, client_secret) do
|
||||
{:ok, res} ->
|
||||
json(conn, res)
|
||||
|
||||
{:error, :invalid_client_credentials} ->
|
||||
send_resp(conn, 400, "Invalid client credentials provided")
|
||||
|
||||
{:error, :invalid_refresh_token} ->
|
||||
send_resp(conn, 400, "Invalid refresh token provided")
|
||||
|
||||
{:error, err} when is_atom(err) ->
|
||||
send_resp(conn, 500, to_string(err))
|
||||
end
|
||||
end
|
||||
|
||||
def generate_access_token(conn, _args) do
|
||||
send_resp(
|
||||
conn,
|
||||
200,
|
||||
URI.encode_query(Applications.generate_access_token(client_id, device_code))
|
||||
400,
|
||||
"Incorrect parameters sent. You need to provide at least the grant_type and client_id parameters, depending on the grant type being used."
|
||||
)
|
||||
end
|
||||
|
||||
@spec generate_redirect_with_query_params(String.t(), map()) :: String.t()
|
||||
defp generate_redirect_with_query_params(redirect_uri, query_params) do
|
||||
redirect_uri |> URI.parse() |> URI.merge("?" <> URI.encode_query(query_params)) |> to_string()
|
||||
@spec do_generate_access_token(String.t(), String.t(), String.t(), String.t(), String.t()) ::
|
||||
{:ok, Applications.access_token_details()} | {:error, String.t()}
|
||||
defp do_generate_access_token(client_id, client_secret, code, redirect_uri, scope) do
|
||||
case Applications.generate_access_token(
|
||||
client_id,
|
||||
client_secret,
|
||||
code,
|
||||
redirect_uri,
|
||||
scope
|
||||
) do
|
||||
{:ok, token} ->
|
||||
{:ok, token}
|
||||
|
||||
{:error, :application_not_found} ->
|
||||
{:error, dgettext("errors", "No application was found with this client_id")}
|
||||
|
||||
{:error, :redirect_uri_not_in_allowed} ->
|
||||
{:error, dgettext("errors", "This redirect URI is not allowed")}
|
||||
|
||||
{:error, :invalid_or_expired} ->
|
||||
{:error, dgettext("errors", "The provided code is invalid or expired")}
|
||||
|
||||
{:error, :provided_code_does_not_match} ->
|
||||
{:error, dgettext("errors", "The provided client_id does not match the provided code")}
|
||||
|
||||
{:error, :invalid_client_secret} ->
|
||||
{:error, dgettext("errors", "The provided client_secret is invalid")}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -208,7 +208,6 @@ defmodule Mobilizon.Web.Router do
|
||||
|
||||
post("/apps", ApplicationController, :create_application)
|
||||
get("/oauth/authorize", ApplicationController, :authorize)
|
||||
post("/oauth/token", ApplicationController, :generate_access_token)
|
||||
get("/oauth/autorize_approve", PageController, :authorize)
|
||||
get("/login/device", PageController, :auth_device)
|
||||
end
|
||||
@@ -217,10 +216,11 @@ defmodule Mobilizon.Web.Router do
|
||||
plug(:accepts, ["html", "json"])
|
||||
end
|
||||
|
||||
scope "/login", Mobilizon.Web do
|
||||
scope "/", Mobilizon.Web do
|
||||
pipe_through(:login)
|
||||
|
||||
post("/device/code", ApplicationController, :device_code)
|
||||
post("/login/device/code", ApplicationController, :device_code)
|
||||
post("/oauth/token", ApplicationController, :generate_access_token)
|
||||
end
|
||||
|
||||
scope "/proxy/", Mobilizon.Web do
|
||||
|
||||
Reference in New Issue
Block a user