diff options
Diffstat (limited to 'animism-align')
14 files changed, 63 insertions, 58 deletions
diff --git a/animism-align/cli/app/controllers/auth_controller.py b/animism-align/cli/app/controllers/auth_controller.py new file mode 100644 index 0000000..9ed0ac3 --- /dev/null +++ b/animism-align/cli/app/controllers/auth_controller.py @@ -0,0 +1,22 @@ +from flask import request, jsonify +from flask_classful import FlaskView, route +from flask_jwt_extended import create_access_token + +from app.settings import app_cfg +from app.sql.common import db, Session +from app.sql.models.user import User + +from app.utils.auth_utils import authenticate + +class AuthView(FlaskView): + @route('/login', methods=['POST']) + def login(self): + username = request.json.get('username', None) + password = request.json.get('password', None) + + user = authenticate(username, password) + + response = { + 'token': create_access_token(identity=user.toJSON()) + } + return jsonify(response), 200 diff --git a/animism-align/cli/app/controllers/crud_controller.py b/animism-align/cli/app/controllers/crud_controller.py index 4fcb77d..78bff2d 100644 --- a/animism-align/cli/app/controllers/crud_controller.py +++ b/animism-align/cli/app/controllers/crud_controller.py @@ -1,7 +1,7 @@ from flask import request, jsonify from flask_classful import FlaskView, route from werkzeug.datastructures import MultiDict -from flask_jwt import jwt_required +from flask_jwt_extended import jwt_required from app.sql.common import db, Session from app.server.helpers import parse_search_args, parse_sort_args @@ -114,10 +114,10 @@ class CrudView(FlaskView): item = session.query(self.model).get(id) if item: raw_form = MultiDict(request.json) if request.json is not None else request.form - form = self.form(raw_form, obj=item) - # print(item.toJSON()) + form = self.form(obj=item) + print(item.toJSON()) + form.populate_obj(item) if form.validate(): - form.populate_obj(item) self.on_update(session, raw_form, item) session.add(item) session.commit() @@ -126,6 +126,7 @@ class CrudView(FlaskView): 'res': item.toJSON(), } else: + print(form.errors) res = { 'status': 'error', 'error': form.errors, diff --git a/animism-align/cli/app/controllers/upload_controller.py b/animism-align/cli/app/controllers/upload_controller.py index f363b0d..a81312d 100644 --- a/animism-align/cli/app/controllers/upload_controller.py +++ b/animism-align/cli/app/controllers/upload_controller.py @@ -1,6 +1,6 @@ from flask import request, jsonify from flask_classful import FlaskView, route -from flask_jwt import jwt_required +from flask_jwt_extended import jwt_required from werkzeug.datastructures import MultiDict from werkzeug.utils import secure_filename import os diff --git a/animism-align/cli/app/controllers/user_controller.py b/animism-align/cli/app/controllers/user_controller.py index 54b39ab..26aa656 100644 --- a/animism-align/cli/app/controllers/user_controller.py +++ b/animism-align/cli/app/controllers/user_controller.py @@ -7,14 +7,15 @@ from app.sql.models.user import User, UserForm from app.controllers.crud_controller import CrudView from app.utils.auth_utils import encrypt_password -from flask_jwt import current_identity +from flask_jwt_extended import get_jwt_identity class UserView(CrudView): model = User form = UserForm def on_create(self, session, form, item): - if not current_identity.is_admin: + current_user = get_jwt_identity() + if not current_user['is_admin']: raise ValueError("Unauthorized") if 'password' in form: item.password = encrypt_password(form['password']) @@ -24,10 +25,10 @@ class UserView(CrudView): item.settings = form['settings'] def on_update(self, session, form, item): - if not current_identity.is_admin: - if item.id != current_identity.id: + if not current_user['is_admin']: + if item.id != current_user['id']: raise ValueError("Unauthorized") - if current_identity.is_admin != item.is_admin: + if current_user['is_admin'] != item.is_admin: raise ValueError("Unauthorized") if 'password' in form: item.password = encrypt_password(form['password']) @@ -35,7 +36,7 @@ class UserView(CrudView): item.settings = form['settings'] def on_destroy(self, session, item): - if not current_identity.is_admin: + if not current_user['is_admin']: raise ValueError("Unauthorized") - if item.id == current_identity.id: + if item.id == current_user['id']: raise ValueError("Unauthorized") diff --git a/animism-align/cli/app/server/web.py b/animism-align/cli/app/server/web.py index 3f2136a..af0c2d9 100644 --- a/animism-align/cli/app/server/web.py +++ b/animism-align/cli/app/server/web.py @@ -25,6 +25,7 @@ from app.controllers.media_controller import MediaView from app.controllers.episode_controller import EpisodeView from app.controllers.venue_controller import VenueView from app.controllers.user_controller import UserView +from app.controllers.auth_controller import AuthView def create_app(script_info=None): """ @@ -36,7 +37,7 @@ def create_app(script_info=None): app.config['SQLALCHEMY_DATABASE_URI'] = connection_url app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SERVER_NAME'] = app_cfg.SERVER_NAME - app.config['SECRET_KEY'] = app_cfg.TOKEN_SECRET + app.config['JWT_SECRET_KEY'] = app_cfg.TOKEN_SECRET app.config['JWT_AUTH_URL_RULE'] = '/api/v1/auth/login' # app.config['JWT_VERIFY_EXPIRATION'] = False app.config['EXPIRATION_DELTA'] = timedelta(days=365 * 10) @@ -52,6 +53,7 @@ def create_app(script_info=None): EpisodeView.register(app, route_prefix='/api/v1/') VenueView.register(app, route_prefix='/api/v1/') UserView.register(app, route_prefix='/api/v1/') + AuthView.register(app, route_prefix='/api/v1/') index_html = 'index.html' diff --git a/animism-align/cli/app/sql/models/user.py b/animism-align/cli/app/sql/models/user.py index 41ac917..4bbb739 100644 --- a/animism-align/cli/app/sql/models/user.py +++ b/animism-align/cli/app/sql/models/user.py @@ -28,6 +28,7 @@ class User(Base): class UserForm(ModelForm): class Meta: model = User + unique_validator = None exclude = ['password','settings'] def get_session(): return Session() diff --git a/animism-align/cli/app/utils/auth_utils.py b/animism-align/cli/app/utils/auth_utils.py index 71974e3..1ee8c68 100644 --- a/animism-align/cli/app/utils/auth_utils.py +++ b/animism-align/cli/app/utils/auth_utils.py @@ -1,4 +1,4 @@ -from flask_jwt import JWT +from flask_jwt_extended import JWTManager import hmac import hashlib @@ -28,4 +28,5 @@ def identity(payload): return user def setup_jwt(app): - return JWT(app, authenticate, identity) + # return JWT(app, authenticate, identity) + jwt = JWTManager(app) diff --git a/animism-align/frontend/app/api/crud.fetch.js b/animism-align/frontend/app/api/crud.fetch.js index a8d4a0d..ddcd80b 100644 --- a/animism-align/frontend/app/api/crud.fetch.js +++ b/animism-align/frontend/app/api/crud.fetch.js @@ -55,7 +55,7 @@ export function _get_headers() { credentials: 'same-origin', headers: { 'Accept': 'application/json', - 'Authorization': "JWT " + session.get("access_token"), + 'Authorization': "Bearer " + session.get("access_token"), }, } } @@ -66,7 +66,7 @@ export function post(data) { credentials: 'same-origin', headers: { 'Accept': 'application/json', - 'Authorization': "JWT " + session.get("access_token"), + 'Authorization': "Bearer " + session.get("access_token"), 'Content-Type': 'application/json' }, } @@ -78,7 +78,7 @@ export function postBody(data) { credentials: 'same-origin', headers: { 'Accept': 'application/json', - 'Authorization': "JWT " + session.get("access_token"), + 'Authorization': "Bearer " + session.get("access_token"), }, } } @@ -89,7 +89,7 @@ export function put(data) { credentials: 'same-origin', headers: { 'Accept': 'application/json', - 'Authorization': "JWT " + session.get("access_token"), + 'Authorization': "Bearer " + session.get("access_token"), 'Content-Type': 'application/json' }, } @@ -101,7 +101,7 @@ export function destroy(data) { credentials: 'same-origin', headers: { 'Accept': 'application/json', - 'Authorization': "JWT " + session.get("access_token"), + 'Authorization': "Bearer " + session.get("access_token"), 'Content-Type': 'application/json' }, } diff --git a/animism-align/frontend/app/views/auth/auth.actions.js b/animism-align/frontend/app/views/auth/auth.actions.js index fc2a2aa..7eabacc 100644 --- a/animism-align/frontend/app/views/auth/auth.actions.js +++ b/animism-align/frontend/app/views/auth/auth.actions.js @@ -20,10 +20,10 @@ export const login = data => dispatch => ( }) .then(req => req.json()) .then(res => { - if (!res.access_token) { + if (!res.token) { throw new Error(res.description) } - session.set('access_token', res.access_token) + session.set('access_token', res.token) load_access_token()(dispatch) }) ) @@ -32,8 +32,7 @@ export const load_access_token = () => dispatch => { const access_token = session.get('access_token') || null if (access_token) { const creds = jsonwebtoken.decode(access_token) - const user_id = creds.identity - return dispatch({ type: types.auth.logged_in, user_id }) + return dispatch({ type: types.auth.logged_in, user: creds.sub }) } else { return dispatch({ type: types.auth.logged_out }) } diff --git a/animism-align/frontend/app/views/auth/auth.gate.js b/animism-align/frontend/app/views/auth/auth.gate.js index ba69256..36d4af8 100644 --- a/animism-align/frontend/app/views/auth/auth.gate.js +++ b/animism-align/frontend/app/views/auth/auth.gate.js @@ -14,23 +14,14 @@ class AuthGate extends Component { } componentDidUpdate(prevProps) { - if (this.props.user_id !== prevProps.user_id) { + if (this.props.user.id !== prevProps.user.id) { this.load() } } load() { - if (!this.props.user_id) return - actions.user.show(this.props.user_id) - .then(() => { - actions.site.loadProject() - }).catch(error => { - if (error.status_code === 401) { - actions.auth.logout() - } else { - console.error(error) - } - }) + if (!this.props.user.id) return + actions.site.loadProject() } render() { diff --git a/animism-align/frontend/app/views/auth/auth.reducer.js b/animism-align/frontend/app/views/auth/auth.reducer.js index 05741f3..8c652ff 100644 --- a/animism-align/frontend/app/views/auth/auth.reducer.js +++ b/animism-align/frontend/app/views/auth/auth.reducer.js @@ -3,8 +3,7 @@ import { getDefault } from 'app/session' const initialState = { logged_in: !!getDefault('access_token', false), - user_id: null, - user: null, + user: {}, } export default function authReducer(state = initialState, action) { @@ -14,25 +13,13 @@ export default function authReducer(state = initialState, action) { return { ...state, logged_in: true, - user_id: action.user_id, - user: null, + user: action.user, } case types.auth.logged_out: return { ...state, logged_in: false, - user_id: null, - user: null, - } - case types.user.show: - if (action.data.res.id !== state.user_id) { - return state - } - return { - ...state, - user: { - ...action.data.res, - } + user: {}, } default: return state diff --git a/animism-align/frontend/app/views/nav/header.component.js b/animism-align/frontend/app/views/nav/header.component.js index b264f4d..28be4a7 100644 --- a/animism-align/frontend/app/views/nav/header.component.js +++ b/animism-align/frontend/app/views/nav/header.component.js @@ -22,7 +22,7 @@ function Header(props) { <Link to="/episode">Episodes</Link> <Link to="/venue">Venues</Link> <Link to="/viewer">Viewer</Link> - {props.currentUser.is_admin && <Link to="/user">Users</Link>} + {props.currentUser.is_admin && <Link to="/users">Users</Link>} <a href="#" onClick={actions.auth.logout}> Logout </a> diff --git a/animism-align/frontend/app/views/user/containers/user.edit.js b/animism-align/frontend/app/views/user/containers/user.edit.js index 5d51792..5ae1fe5 100644 --- a/animism-align/frontend/app/views/user/containers/user.edit.js +++ b/animism-align/frontend/app/views/user/containers/user.edit.js @@ -56,6 +56,7 @@ class UserEdit extends Component { <UserMenu userActions={this.props.userActions} /> <UserForm data={show.res} + currentUser={this.props.currentUser} onSubmit={this.handleSubmit.bind(this)} /> </div> @@ -65,6 +66,7 @@ class UserEdit extends Component { const mapStateToProps = state => ({ user: state.user, + currentUser: state.auth.user, }) export default connect(mapStateToProps)(UserEdit) diff --git a/animism-align/frontend/app/views/user/containers/user.new.js b/animism-align/frontend/app/views/user/containers/user.new.js index 9d80e0a..01fe1e1 100644 --- a/animism-align/frontend/app/views/user/containers/user.new.js +++ b/animism-align/frontend/app/views/user/containers/user.new.js @@ -58,6 +58,7 @@ class UserNew extends Component { <UserForm isNew data={this.state.initialData} + currentUser={this.props.currentUser} onSubmit={this.handleSubmit.bind(this)} /> </div> @@ -67,10 +68,7 @@ class UserNew extends Component { const mapStateToProps = state => ({ user: state.user, + currentUser: state.auth.user, }) -const mapDispatchToProps = dispatch => ({ - // uploadActions: bindActionCreators({ ...uploadActions }, dispatch), -}) - -export default connect(mapStateToProps, mapDispatchToProps)(UserNew) +export default connect(mapStateToProps)(UserNew) |
