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
This commit is contained in:
parent
44e57f64dd
commit
92afd29650
16 changed files with 127 additions and 25 deletions
8
app/assets/javascripts/components/actions/meta.jsx
Normal file
8
app/assets/javascripts/components/actions/meta.jsx
Normal file
|
@ -0,0 +1,8 @@
|
|||
export const SET_ACCESS_TOKEN = 'SET_ACCESS_TOKEN';
|
||||
|
||||
export function setAccessToken(token) {
|
||||
return {
|
||||
type: SET_ACCESS_TOKEN,
|
||||
token: token
|
||||
};
|
||||
}
|
|
@ -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));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ const ComposerDrawer = React.createClass({
|
|||
|
||||
handleSubmit () {
|
||||
this.props.onSubmit(this.state.text, null);
|
||||
this.setState({ text: '' });
|
||||
},
|
||||
|
||||
render () {
|
||||
|
|
|
@ -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])));
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { combineReducers } from 'redux-immutable';
|
||||
import statuses from './statuses';
|
||||
import meta from './meta';
|
||||
|
||||
export default combineReducers({
|
||||
statuses
|
||||
statuses,
|
||||
meta
|
||||
});
|
||||
|
|
13
app/assets/javascripts/components/reducers/meta.jsx
Normal file
13
app/assets/javascripts/components/reducers/meta.jsx
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue