def _get_user_require_auth(user_id=None): """Return the requested user only if authenticated and authorized. Defaults to the current user if no user_id given. Guaranteed to return a user object. """ current_user = view_helpers.get_current_user() if not current_user: raise api_util.ApiBadRequestError('Must authenticate as a user.') if not user_id: return current_user try: user_id_bson = bson.ObjectId(user_id) except bson.errors.InvalidId: raise api_util.ApiBadRequestError( 'User ID %s is not a valid BSON ObjectId.' % user_id) # Does the the current user have permission to get info about this user? if (user_id_bson == current_user.id or user_id_bson in current_user.friend_ids): user = m.User.objects.with_id(user_id_bson) if user: return user raise api_util.ApiForbiddenError( 'Not authorized to get info about this user.')
def signup_email(): """Create a new account using data encoded in the POST body. Expects the following form data: first_name: E.g. 'Taylor' last_name: E.g. 'Swift' email: E.g. '*****@*****.**' password: E.g. 'iknewyouweretrouble' Responds with the session cookie via the `set-cookie` header on success. Send the associated cookie for all subsequent API requests that accept user authentication. """ # Prevent a CSRF attack from replacing a logged-in user's account with # a new account with known credentials current_user = view_helpers.get_current_user() if current_user: return api_util.jsonify({'message': 'A user is already logged in.'}) params = flask.request.form.copy() # Don't log the password password = params.pop('password', None) rmclogger.log_event( rmclogger.LOG_CATEGORY_API, rmclogger.LOG_EVENT_SIGNUP, { 'params': params, 'type': rmclogger.LOGIN_TYPE_STRING_EMAIL, }, ) first_name = params.get('first_name') last_name = params.get('last_name') email = params.get('email') if not first_name: raise api_util.ApiBadRequestError('Must provide first name.') if not last_name: raise api_util.ApiBadRequestError('Must provide last name.') if not email: raise api_util.ApiBadRequestError('Must provide email.') if not password: raise api_util.ApiBadRequestError('Must provide password.') try: user = m.User.create_new_user_from_email(first_name, last_name, email, password) except m.User.UserCreationError as e: raise api_util.ApiBadRequestError(e.message) view_helpers.login_as_user(user) return api_util.jsonify( {'message': 'Created and logged in user %s' % user.name})
def add_gcm_course_alert(): """Adds an alert to notify when a seat opens up in a course/section via GCM. GCM is used to send push notifications to our Android app. Requires the following parameters: registration_id: Provided by GCM to identify the device-app pair course_id: ID of the course to alert on Optional parameters: created_date: Timestamp in millis expiry_date: Timestamp in millis. Defaults to 1 year later term_id: e.g. "2014_01" section_type: e.g. "LEC" section_num: e.g. "001" user_id: ID of the logged in user """ params = flask.request.form created_date = datetime.datetime.now() expiry_date_param = params.get('expiry_date') if expiry_date_param: expiry_date = datetime.datetime.fromtimestamp(int(expiry_date_param)) else: expiry_date = created_date + datetime.timedelta(days=365) try: alert_dict = { 'registration_id': params['registration_id'], 'course_id': params['course_id'], 'created_date': created_date, 'expiry_date': expiry_date, 'term_id': params.get('term_id'), 'section_type': params.get('section_type'), 'section_num': params.get('section_num'), 'user_id': params.get('user_id'), } except KeyError as e: raise api_util.ApiBadRequestError('Missing required parameter: %s' % e.message) alert = m.GcmCourseAlert(**alert_dict) try: alert.save() except me.NotUniqueError as e: raise api_util.ApiBadRequestError( 'Alert with the given parameters already exists.') return api_util.jsonify({ 'gcm_course_alert': alert.to_dict(), })
def login_email(): """Attempt to log in a user with the credentials encoded in the POST body. Expects the following form data: email: E.g. '*****@*****.**' password: E.g. 'iknewyouweretrouble' Responds with the session cookie via the `set-cookie` header on success. Send the associated cookie for all subsequent API requests that accept user authentication. """ # Prevent a CSRF attack from replacing a logged-in user's account with the # attacker's. current_user = view_helpers.get_current_user() if current_user: return api_util.jsonify({'message': 'A user is already logged in.'}) params = flask.request.form.copy() # Don't log the password password = params.pop('password', None) rmclogger.log_event( rmclogger.LOG_CATEGORY_API, rmclogger.LOG_EVENT_LOGIN, { 'params': params, 'type': rmclogger.LOGIN_TYPE_STRING_EMAIL, }, ) email = params.get('email') if not email: raise api_util.ApiBadRequestError('Must provide email.') if not password: raise api_util.ApiBadRequestError('Must provide password.') user = m.User.auth_user(email, password) if not user: raise api_util.ApiNotFoundError('Incorrect email or password.') view_helpers.login_as_user(user) return api_util.jsonify({'message': 'Logged in user %s' % user.name})
def add_course_to_shortlist(course_id): """Adds the given course to the user's shortlist. Idempotent. """ user = _get_user_require_auth() user_course = user.add_course(course_id, m.Term.SHORTLIST_TERM_ID) if user_course is None: raise api_util.ApiBadRequestError( 'Could not add course %s to shortlist. :(' % course_id) return api_util.jsonify({ 'user_course': user_course.to_dict(), })
def get_access_token_info(access_token): """Returns info about the given Facebook access token. Verifies that the access token was issued for Flow. This prevents an attacker from hijacking a user's Flow account by providing a valid access token issued for another FB app. For return data, see (https://developers.facebook.com/docs/facebook-login /manually-build-a-login-flow/#confirm) """ res = requests.get('https://graph.facebook.com/debug_token' '?input_token=%s&access_token=%s|%s' % ( access_token, app.config['FB_APP_ID'], app.config['FB_APP_SECRET'])) if not res.ok or not res.json.get('data'): logging.error('Failed verifying FB access token. FB response: %s' % res.json) raise api_util.ApiBadRequestError('Failed verifying FB access token.') return res.json['data']