Add Mastodon frontend.

This commit is contained in:
Roger Braun 2017-11-12 14:23:05 +01:00
parent 414c52509b
commit d293ceb1b5
170 changed files with 206601 additions and 5 deletions

View File

@ -10,8 +10,12 @@ defmodule Pleroma.Plugs.OAuthPlug do
def call(%{assigns: %{user: %User{}}} = conn, _), do: conn def call(%{assigns: %{user: %User{}}} = conn, _), do: conn
def call(conn, opts) do def call(conn, opts) do
with ["Bearer " <> header] <- get_req_header(conn, "authorization"), token = case get_req_header(conn, "authorization") do
%Token{user_id: user_id} <- Repo.get_by(Token, token: header), ["Bearer " <> header] -> header
_ -> get_session(conn, :oauth_token)
end
with token when not is_nil(token) <- token,
%Token{user_id: user_id} <- Repo.get_by(Token, token: token),
%User{} = user <- Repo.get(User, user_id) do %User{} = user <- Repo.get(User, user_id) do
conn conn
|> assign(:user, user) |> assign(:user, user)

View File

@ -12,7 +12,7 @@ defmodule Pleroma.Web.Endpoint do
at: "/media", from: "uploads", gzip: false at: "/media", from: "uploads", gzip: false
plug Plug.Static, plug Plug.Static,
at: "/", from: :pleroma, at: "/", from: :pleroma,
only: ~w(index.html static finmoji emoji) only: ~w(index.html static finmoji emoji packs sounds sw.js)
# Code reloading can be explicitly enabled under the # Code reloading can be explicitly enabled under the
# :code_reloader configuration of your endpoint. # :code_reloader configuration of your endpoint.

View File

@ -1,12 +1,13 @@
defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
use Pleroma.Web, :controller use Pleroma.Web, :controller
alias Pleroma.{Repo, Activity, User, Notification} alias Pleroma.{Repo, Activity, User, Notification}
alias Pleroma.Web.OAuth.App
alias Pleroma.Web alias Pleroma.Web
alias Pleroma.Web.MastodonAPI.{StatusView, AccountView} alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView}
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.TwitterAPI.TwitterAPI alias Pleroma.Web.TwitterAPI.TwitterAPI
alias Pleroma.Web.{CommonAPI, OStatus} alias Pleroma.Web.{CommonAPI, OStatus}
alias Pleroma.Web.OAuth.{Authorization, Token, App}
alias Comeonin.Pbkdf2
import Ecto.Query import Ecto.Query
import Logger import Logger
@ -405,6 +406,116 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity}) |> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity})
end end
def index(%{assigns: %{user: user}} = conn, _params) do
token = conn
|> get_session(:oauth_token)
if user && token do
accounts = Map.put(%{}, user.id, AccountView.render("account.json", %{user: user}))
initial_state = %{
meta: %{
streaming_api_base_url: String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws"),
access_token: token,
locale: "en",
domain: Pleroma.Web.Endpoint.host(),
admin: "1",
me: "#{user.id}",
unfollow_modal: false,
boost_modal: false,
delete_modal: true,
auto_play_gif: false,
reduce_motion: false
},
compose: %{
me: "#{user.id}",
default_privacy: "public",
default_sensitive: false
},
media_attachments: %{
accept_content_types: [
".jpg",
".jpeg",
".png",
".gif",
".webm",
".mp4",
".m4v",
"image\/jpeg",
"image\/png",
"image\/gif",
"video\/webm",
"video\/mp4"
]
},
settings: %{
onboarded: true,
home: %{
shows: %{
reblog: true,
reply: true
}
},
notifications: %{
alerts: %{
follow: true,
favourite: true,
reblog: true,
mention: true
},
shows: %{
follow: true,
favourite: true,
reblog: true,
mention: true
},
sounds: %{
follow: true,
favourite: true,
reblog: true,
mention: true
}
}
},
push_subscription: nil,
accounts: accounts,
custom_emojis: %{}
} |> Poison.encode!
conn
|> put_layout(false)
|> render(MastodonView, "index.html", %{initial_state: initial_state})
else
conn
|> redirect(to: "/web/login")
end
end
def login(conn, params) do
conn
|> render(MastodonView, "login.html")
end
defp get_or_make_app() do
with %App{} = app <- Repo.get_by(App, client_name: "Mastodon-Local") do
{:ok, app}
else
_e ->
cs = App.register_changeset(%App{}, %{client_name: "Mastodon-Local", redirect_uris: ".", scopes: "read,write,follow"})
Repo.insert(cs)
end
end
def login_post(conn, %{"authorization" => %{ "name" => name, "password" => password}}) do
with %User{} = user <- User.get_cached_by_nickname(name),
true <- Pbkdf2.checkpw(password, user.password_hash),
{:ok, app} <- get_or_make_app(),
{:ok, auth} <- Authorization.create_authorization(app, user),
{:ok, token} <- Token.exchange_token(app, auth) do
conn
|> put_session(:oauth_token, token.token)
|> redirect(to: "/web/timelines/public")
end
end
def relationship_noop(%{assigns: %{user: user}} = conn, %{"id" => id}) do def relationship_noop(%{assigns: %{user: user}} = conn, %{"id" => id}) do
Logger.debug("Unimplemented, returning unmodified relationship") Logger.debug("Unimplemented, returning unmodified relationship")
with %User{} = target <- Repo.get(User, id) do with %User{} = target <- Repo.get(User, id) do

View File

@ -0,0 +1,5 @@
defmodule Pleroma.Web.MastodonAPI.MastodonView do
use Pleroma.Web, :view
import Phoenix.HTML
import Phoenix.HTML.Form
end

View File

@ -21,6 +21,13 @@ defmodule Pleroma.Web.Router do
plug Pleroma.Plugs.AuthenticationPlug, %{fetcher: &Router.user_fetcher/1} plug Pleroma.Plugs.AuthenticationPlug, %{fetcher: &Router.user_fetcher/1}
end end
pipeline :mastodon_html do
plug :accepts, ["html"]
plug :fetch_session
plug Pleroma.Plugs.OAuthPlug
plug Pleroma.Plugs.AuthenticationPlug, %{fetcher: &Router.user_fetcher/1, optional: true}
end
pipeline :well_known do pipeline :well_known do
plug :accepts, ["xml", "xrd+xml"] plug :accepts, ["xml", "xrd+xml"]
end end
@ -207,6 +214,14 @@ defmodule Pleroma.Web.Router do
get "/webfinger", WebFinger.WebFingerController, :webfinger get "/webfinger", WebFinger.WebFingerController, :webfinger
end end
scope "/web", Pleroma.Web.MastodonAPI do
pipe_through :mastodon_html
get "/login", MastodonAPIController, :login
post "/login", MastodonAPIController, :login_post
get "/*path", MastodonAPIController, :index
end
scope "/", Fallback do scope "/", Fallback do
get "/*path", RedirectController, :redirector get "/*path", RedirectController, :redirector
end end

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,10 @@
<h2>Login in to Mastodon Frontend</h2>
<%= form_for @conn, mastodon_api_path(@conn, :login), [as: "authorization"], fn f -> %>
<%= label f, :name, "Name" %>
<%= text_input f, :name %>
<br>
<%= label f, :password, "Password" %>
<%= password_input f, :password %>
<br>
<%= submit "Authorize" %>
<% end %>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
webpackJsonp([64],{622:function(e,c,t){"use strict";function o(e){var c=e.detail,t=c[0],o=document.querySelector('[data-id="'+t.id+'"]');o&&o.parentNode.removeChild(o)}Object.defineProperty(c,"__esModule",{value:!0});var a=t(146);t.n(a);[].forEach.call(document.querySelectorAll(".trash-button"),function(e){e.addEventListener("ajax:success",o)});Object(a.delegate)(document,"#batch_checkbox_all","change",function(e){var c=e.target;[].forEach.call(document.querySelectorAll('.batch-checkbox input[type="checkbox"]'),function(e){e.checked=c.checked})}),Object(a.delegate)(document,'.batch-checkbox input[type="checkbox"]',"change",function(){var e=document.querySelector("#batch_checkbox_all");e&&(e.checked=[].every.call(document.querySelectorAll('.batch-checkbox input[type="checkbox"]'),function(e){return e.checked}))}),Object(a.delegate)(document,".media-spoiler-show-button","click",function(){[].forEach.call(document.querySelectorAll(".activity-stream .media-spoiler-wrapper"),function(e){e.classList.add("media-spoiler-wrapper__visible")})}),Object(a.delegate)(document,".media-spoiler-hide-button","click",function(){[].forEach.call(document.querySelectorAll(".activity-stream .media-spoiler-wrapper"),function(e){e.classList.remove("media-spoiler-wrapper__visible")})})}},[622]);
//# sourceMappingURL=admin-1bab981afc4fd0d71402.js.map

View File

@ -0,0 +1,43 @@
CACHE MANIFEST
#ver:11/12/2017, 12:40:57 PM
#plugin:4.8.4
CACHE:
/packs/features/compose-4617f6e912b5bfa71c43.js
/packs/modals/onboarding_modal-399f44a19ddd0ddc4e9c.js
/packs/features/public_timeline-d6e6bc704f49ebf922be.js
/packs/features/community_timeline-20bc8a94c08809c127d0.js
/packs/features/hashtag_timeline-3ed7e7bf18fd2fc04c9e.js
/packs/emoji_picker-9cf581d158c1cefc73c9.js
/packs/features/notifications-99d27ff7a90c7f701400.js
/packs/features/home_timeline-c146f32b0118845677ee.js
/packs/features/account_timeline-cad2550e777d3958eca4.js
/packs/features/pinned_statuses-fc56dd5916a37286e823.js
/packs/features/favourited_statuses-b15a9a6cc711cca1eb76.js
/packs/features/status-1f1807fdb4d1fd6daf40.js
/packs/features/following-9060b3726e6ad25f3621.js
/packs/features/followers-6716b8606f70dfa12ed7.js
/packs/features/account_gallery-b13924812f8dd47200c2.js
/packs/modals/report_modal-7a2950f40d4867b9cbb0.js
/packs/features/follow_requests-281e5b40331385149920.js
/packs/features/mutes-60c139f123f8d11ed903.js
/packs/features/blocks-e9605338ea941de78465.js
/packs/features/reblogs-e284a8647e830c151a40.js
/packs/features/favourites-083fedd11007764f7fad.js
/packs/features/getting_started-b65f1e917d66a972f2bf.js
/packs/features/generic_not_found-dc757b4cfe00489a06fb.js
/packs/modals/embed_modal-c776fd6a0ea581675783.js
/packs/status/media_gallery-7642f779bf4243e58b78.js
/packs/application-1b1f37dff2aac402336b.js
/packs/share-914b479bea45d0f6d4aa.js
/packs/about-d6275c885cd0e28a1186.js
/packs/public-88b87539fc95f07f2721.js
/packs/default-99ffdcf166b2dedef105.js
/packs/admin-1bab981afc4fd0d71402.js
/packs/common-1789b98651001ef10c0b.js
/packs/common-daadaac9454e7d14470e7954e3143dca.css
/packs/default-818c1287ac3c764905d81e549d5e0160.css
/packs/manifest.json
NETWORK:
*

View File

@ -0,0 +1,2 @@
<!doctype html>
<html manifest="manifest.appcache"></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
webpackJsonp([63],{748:function(n,c){}},[748]);
//# sourceMappingURL=default-99ffdcf166b2dedef105.js.map

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
webpackJsonp([24],{150:function(n,e,t){"use strict";t.d(e,"a",function(){return f});var i=t(2),r=t.n(i),o=t(1),a=t.n(o),c=t(3),l=t.n(c),u=t(4),s=t.n(u),d=t(0),p=t.n(d),f=function(n){function e(){var t,i,r;a()(this,e);for(var o=arguments.length,c=Array(o),u=0;u<o;u++)c[u]=arguments[u];return t=i=l()(this,n.call.apply(n,[this].concat(c))),i.handleClick=function(){i.props.onClick()},r=t,l()(i,r)}return s()(e,n),e.prototype.render=function(){var n=this.props,e=n.type,t=n.active,i=n.columnHeaderId,o="";return this.props.icon&&(o=r()("i",{className:"fa fa-fw fa-"+this.props.icon+" column-header__icon"})),r()("div",{role:"heading",tabIndex:"0",className:"column-header "+(t?"active":""),onClick:this.handleClick,id:i||null},void 0,o,e)},e}(p.a.PureComponent)},259:function(n,e,t){"use strict";t.d(e,"a",function(){return y});var i=t(2),r=t.n(i),o=t(1),a=t.n(o),c=t(3),l=t.n(c),u=t(4),s=t.n(u),d=t(42),p=t.n(d),f=t(0),h=t.n(f),v=t(150),m=t(91),b=t(33),y=function(n){function e(){var t,i,r;a()(this,e);for(var o=arguments.length,c=Array(o),u=0;u<o;u++)c[u]=arguments[u];return t=i=l()(this,n.call.apply(n,[this].concat(c))),i.handleHeaderClick=function(){var n=i.node.querySelector(".scrollable");n&&(i._interruptScrollAnimation=Object(m.b)(n))},i.handleScroll=p()(function(){void 0!==i._interruptScrollAnimation&&i._interruptScrollAnimation()},200),i.setRef=function(n){i.node=n},r=t,l()(i,r)}return s()(e,n),e.prototype.scrollTop=function(){var n=this.node.querySelector(".scrollable");n&&(this._interruptScrollAnimation=Object(m.b)(n))},e.prototype.render=function(){var n=this.props,e=n.heading,t=n.icon,i=n.children,o=n.active,a=n.hideHeadingOnMobile,c=e&&(!a||a&&!Object(b.b)(window.innerWidth)),l=c&&e.replace(/ /g,"-"),u=c&&r()(v.a,{icon:t,active:o,type:e,onClick:this.handleHeaderClick,columnHeaderId:l});return h.a.createElement("div",{ref:this.setRef,role:"region","aria-labelledby":l,className:"column",onScroll:this.handleScroll},u,i)},e}(h.a.PureComponent)},768:function(n,e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var i=t(2),r=t.n(i),o=t(0),a=(t.n(o),t(259)),c=t(780),l=function(){return r()(a.a,{},void 0,r()(c.a,{}))};e.default=l},780:function(n,e,t){"use strict";var i=t(2),r=t.n(i),o=t(0),a=(t.n(o),t(6)),c=function(){return r()("div",{className:"missing-indicator"},void 0,r()("div",{},void 0,r()(a.b,{id:"missing_indicator.label",defaultMessage:"Not found"})))};e.a=c}});
//# sourceMappingURL=generic_not_found-dc757b4cfe00489a06fb.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 434 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More