diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2016-08-26 19:12:19 +0200 |
---|---|---|
committer | Eugen Rochko <eugen@zeonfederated.com> | 2016-08-26 19:12:19 +0200 |
commit | 92afd296509de82e7550f67064b032db916b1f63 (patch) | |
tree | 6d723210f723d0a74317805352e7912b70c54240 /app | |
parent | 44e57f64dd8b00900c31d7fd56fda94f4e69e986 (diff) |
The frontend will now be an OAuth app, auto-authorized. The frontend will use an access token for API requests
Adding better errors for the API controllers, posting a simple status works from the frontend now
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/components/actions/meta.jsx | 8 | ||||
-rw-r--r-- | app/assets/javascripts/components/actions/statuses.jsx | 56 | ||||
-rw-r--r-- | app/assets/javascripts/components/components/composer_drawer.jsx | 1 | ||||
-rw-r--r-- | app/assets/javascripts/components/containers/root.jsx | 11 | ||||
-rw-r--r-- | app/assets/javascripts/components/reducers/index.jsx | 4 | ||||
-rw-r--r-- | app/assets/javascripts/components/reducers/meta.jsx | 13 | ||||
-rw-r--r-- | app/controllers/api_controller.rb | 8 | ||||
-rw-r--r-- | app/controllers/home_controller.rb | 7 | ||||
-rw-r--r-- | app/views/home/index.html.haml | 2 |
9 files changed, 104 insertions, 6 deletions
diff --git a/app/assets/javascripts/components/actions/meta.jsx b/app/assets/javascripts/components/actions/meta.jsx new file mode 100644 index 000000000..1b64db1c2 --- /dev/null +++ b/app/assets/javascripts/components/actions/meta.jsx @@ -0,0 +1,8 @@ +export const SET_ACCESS_TOKEN = 'SET_ACCESS_TOKEN'; + +export function setAccessToken(token) { + return { + type: SET_ACCESS_TOKEN, + token: token + }; +} diff --git a/app/assets/javascripts/components/actions/statuses.jsx b/app/assets/javascripts/components/actions/statuses.jsx index fece257d5..45d62fab2 100644 --- a/app/assets/javascripts/components/actions/statuses.jsx +++ b/app/assets/javascripts/components/actions/statuses.jsx @@ -2,7 +2,11 @@ import fetch from 'isomorphic-fetch' export const SET_TIMELINE = 'SET_TIMELINE'; export const ADD_STATUS = 'ADD_STATUS'; -export const PUBLISH = 'PUBLISH'; + +export const PUBLISH = 'PUBLISH'; +export const PUBLISH_START = 'PUBLISH_START'; +export const PUBLISH_SUCC = 'PUBLISH_SUCC'; +export const PUBLISH_ERROR = 'PUBLISH_ERROR'; export function setTimeline(timeline, statuses) { return { @@ -20,14 +24,58 @@ export function addStatus(timeline, status) { }; } +export function publishStart() { + return { + type: PUBLISH_START + }; +} + +export function publishError(error) { + return { + type: PUBLISH_ERROR, + error: error + }; +} + +export function publishSucc(status) { + return { + type: PUBLISH_SUCC, + status: status + }; +} + export function publish(text, in_reply_to_id) { - return function (dispatch) { + return function (dispatch, getState) { + const access_token = getState().getIn(['meta', 'access_token']); + + var data = new FormData(); + + data.append('status', text); + + if (in_reply_to_id !== null) { + data.append('in_reply_to_id', in_reply_to_id); + } + + dispatch(publishStart()); + return fetch('/api/statuses', { - method: 'POST' + method: 'POST', + + headers: { + 'Authorization': `Bearer ${access_token}` + }, + + body: data }).then(function (response) { return response.json(); }).then(function (json) { - console.log(json); + if (json.error) { + dispatch(publishError(json.error)); + } else { + dispatch(publishSucc(json)); + } + }).catch(function (error) { + dispatch(publishError(error)); }); }; } diff --git a/app/assets/javascripts/components/components/composer_drawer.jsx b/app/assets/javascripts/components/components/composer_drawer.jsx index d33e28219..7b742f64e 100644 --- a/app/assets/javascripts/components/components/composer_drawer.jsx +++ b/app/assets/javascripts/components/components/composer_drawer.jsx @@ -26,6 +26,7 @@ const ComposerDrawer = React.createClass({ handleSubmit () { this.props.onSubmit(this.state.text, null); + this.setState({ text: '' }); }, render () { diff --git a/app/assets/javascripts/components/containers/root.jsx b/app/assets/javascripts/components/containers/root.jsx index 7da984d89..661ffb22c 100644 --- a/app/assets/javascripts/components/containers/root.jsx +++ b/app/assets/javascripts/components/containers/root.jsx @@ -2,12 +2,23 @@ import { Provider } from 'react-redux'; import configureStore from '../store/configureStore'; import Frontend from '../components/frontend'; import { setTimeline, addStatus } from '../actions/statuses'; +import { setAccessToken } from '../actions/meta'; +import PureRenderMixin from 'react-addons-pure-render-mixin'; const store = configureStore(); const Root = React.createClass({ + propTypes: { + token: React.PropTypes.string.isRequired, + timelines: React.PropTypes.array + }, + + mixins: [PureRenderMixin], + componentWillMount() { + store.dispatch(setAccessToken(this.props.token)); + for (var timelineType in this.props.timelines) { if (this.props.timelines.hasOwnProperty(timelineType)) { store.dispatch(setTimeline(timelineType, JSON.parse(this.props.timelines[timelineType]))); diff --git a/app/assets/javascripts/components/reducers/index.jsx b/app/assets/javascripts/components/reducers/index.jsx index c7e858f38..96c026c8c 100644 --- a/app/assets/javascripts/components/reducers/index.jsx +++ b/app/assets/javascripts/components/reducers/index.jsx @@ -1,6 +1,8 @@ import { combineReducers } from 'redux-immutable'; import statuses from './statuses'; +import meta from './meta'; export default combineReducers({ - statuses + statuses, + meta }); diff --git a/app/assets/javascripts/components/reducers/meta.jsx b/app/assets/javascripts/components/reducers/meta.jsx new file mode 100644 index 000000000..401be435d --- /dev/null +++ b/app/assets/javascripts/components/reducers/meta.jsx @@ -0,0 +1,13 @@ +import { SET_ACCESS_TOKEN } from '../actions/meta'; +import Immutable from 'immutable'; + +const initialState = Immutable.Map(); + +export default function meta(state = initialState, action) { + switch(action.type) { + case SET_ACCESS_TOKEN: + return state.set('access_token', action.token); + default: + return state; + } +} diff --git a/app/controllers/api_controller.rb b/app/controllers/api_controller.rb index 8a2712476..bacdd997b 100644 --- a/app/controllers/api_controller.rb +++ b/app/controllers/api_controller.rb @@ -2,6 +2,14 @@ class ApiController < ApplicationController protect_from_forgery with: :null_session skip_before_action :verify_authenticity_token + rescue_from ActiveRecord::RecordInvalid do + render json: { error: 'Record invalid' }, status: 422 + end + + rescue_from ActiveRecord::RecordNotFound do + render json: { error: 'Record not found' }, status: 404 + end + protected def current_resource_owner diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 57973ba49..f159c3df8 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -5,5 +5,12 @@ class HomeController < ApplicationController @body_classes = 'app-body' @home = Feed.new(:home, current_user.account).get(20) @mentions = Feed.new(:mentions, current_user.account).get(20) + @token = find_or_create_access_token.token + end + + private + + def find_or_create_access_token + Doorkeeper::AccessToken.find_or_create_for(Doorkeeper::Application.where(superapp: true).first, current_user.id, nil, Doorkeeper.configuration.access_token_expires_in, Doorkeeper.configuration.refresh_token_enabled?) end end diff --git a/app/views/home/index.html.haml b/app/views/home/index.html.haml index 941397384..9279ae9ae 100644 --- a/app/views/home/index.html.haml +++ b/app/views/home/index.html.haml @@ -1 +1 @@ -= react_component 'Root', { timelines: { home: render(file: 'api/statuses/home', locals: { statuses: @home }, formats: :json), mentions: render(file: 'api/statuses/mentions', locals: { statuses: @mentions }, formats: :json) }}, class: 'app-holder', prerender: false += react_component 'Root', { token: @token, timelines: { home: render(file: 'api/statuses/home', locals: { statuses: @home }, formats: :json), mentions: render(file: 'api/statuses/mentions', locals: { statuses: @mentions }, formats: :json) }}, class: 'app-holder', prerender: false |