Beispiel #1
0
    def create(self, request, *args, **kwargs):
        try:
            tel = request.data['tel']
            code = request.data['code']
            data = request.data.copy()
            if is_tel(tel):
                check_sms_verify(tel, 1, code)
                # 以手机号码注册
                serializer = UserCreateSerializer(data=data)
            else:
                return error_response(3, '请输入合法的手机号码')

            if serializer.is_valid():
                # 注册一个真实用户
                user = serializer.create(serializer.validated_data)
                user.refresh_im_token()
                data = {
                    'id': user.id,
                    'token': user.get_token(),
                    'im_token': user.get_im_token(),
                    'name': user.get_full_name(),
                    'portal': request.build_absolute_uri(user.get_portrait())
                }
                return success_response(data)
            else:
                return error_response(1, self.humanize_errors(serializer))
        except VerifyError as e:
            return error_response(2, e.message)
        except KeyError as e:
            return error_response(1, '获取参数{}失败'.format(e.__context__))
        except Exception as e:
            return error_response(1, str(e))
Beispiel #2
0
def verify_phone_number(request):
    """
    Given a phone number (e.164 format) and an active verification code, this endpoint
    generates a new user account capable of owning access and refresh tokens.

    An initial set of refresh and access tokens for the new account are returned on
    success.
    """
    request_data = get_request_data(request.body)
    if request_data is None:
        return error_response("Missing or invalid data")

    current_time = get_current_utc_time()
    active_codes = get_active_verification_codes_for_phone_number(
        request_data.phone_number, current_time)
    is_valid_code = request_data.verification_code in active_codes
    if not is_valid_code:
        return error_response("Invalid verification code")

    invalidate_verification_code(request_data.verification_code)
    user, created = get_or_create_user(phone_number=request_data.phone_number)
    if not created:
        logger.info(
            f"Generating refresh token for existing user {user.user_id}")

    refresh_token = generate_and_record_refresh_token(user, current_time)
    access_token, token_payload = generate_access_token_for_user(
        user.user_id, current_time)
    expiry_time = from_timestamp(token_payload["exp"])
    response_data = ResponseData(refresh_token=refresh_token,
                                 access_token=access_token,
                                 expiry_time=expiry_time)

    return success_response(response_data)
def send_verification_code(request) -> HttpResponse:
    request_data = get_request_data(request.body)
    if request_data is None:
        return error_response()

    phone_number = get_e164_phone_number(request_data.phone_number, request_data.region)
    if phone_number is None:
        return error_response("invalid phone_number")

    current_time = get_current_utc_time()
    verification_code_expiry_time = current_time + timedelta(
        seconds=VERIFICATION_CODE_LIFETIME_SECONDS
    )

    provider = get_communication_provider()
    message_status_callback = settings.TWILIO_MESSAGE_STATUS_CALLBACK
    success, verification_code = send_verification_code_sms(
        provider=provider,
        phone_number=phone_number,
        verification_code_population=VERIFICATION_CODE_ALPHABET,
        verification_code_length=VERIFICATION_CODE_LENGTH,
        verification_code_expiry_time=verification_code_expiry_time,
        callback=message_status_callback,
        max_retries=3,
    )
    if success is False:
        invalidate_verification_code(verification_code)
        return error_response("failed to send verification token", status=503)

    return success_response({"phone_number": phone_number})
def send_verification_code(request) -> HttpResponse:
    """
    Validates, formats and requests an SMS from the configured provider.
    The requested phone_number received a temporary verification code which should be
    supplied to the verify_phone_number endpoint.
    """
    request_data = get_request_data(request.body)
    if request_data is None:
        return error_response()

    phone_number = get_e164_phone_number(request_data.phone_number,
                                         request_data.region)
    if phone_number is None:
        return error_response("Invalid phone_number")

    current_time = get_current_utc_time()
    verification_code_expiry_time = current_time + timedelta(
        seconds=VERIFICATION_CODE_LIFETIME_SECONDS)

    provider = get_communication_provider()
    message_status_callback = settings.TWILIO_MESSAGE_STATUS_CALLBACK
    success, verification_code = send_verification_code_sms(
        provider=provider,
        phone_number=phone_number,
        verification_code_population=VERIFICATION_CODE_ALPHABET,
        verification_code_length=VERIFICATION_CODE_LENGTH,
        verification_code_expiry_time=verification_code_expiry_time,
        callback=message_status_callback,
    )
    if success is False:
        invalidate_verification_code(verification_code.code)
        return error_response("Failed to send verification SMS", status=503)

    return success_response({"phone_number": phone_number})
def verify_phone_number(request):
    request_data = get_request_data(request.body)
    if request_data is None:
        return error_response("missing or invalid data")

    current_time = get_current_utc_time()
    active_codes = get_active_verification_codes_for_phone_number(
        request_data.phone_number, current_time
    )
    is_valid_code = request_data.verification_code in active_codes
    if not is_valid_code:
        return error_response("invalid verification code")

    current_time = get_current_utc_time()

    user, created = get_or_create_user(phone_number=request_data.phone_number)
    if not created:
        return error_response("phone number has already been verified")
    refresh_token = generate_and_record_refresh_token(user, current_time)
    access_token, token_payload = generate_access_token_for_user(
        user.user_id, current_time
    )
    expiry_time = from_timestamp(token_payload["exp"])
    response_data = ResponseData(
        refresh_token=refresh_token, access_token=access_token, expiry_time=expiry_time
    )

    return success_response(response_data)
        def wrapper(request, *args, **kwargs):
            if settings.IS_TEST_ENVIRONMENT:
                user = get_user_from_test_user_header(request.META)
                if user is not None:
                    request.user = user
                    return func(request, *args, **kwargs)

            auth_header = get_authorization_header(request.META)
            if auth_header is None:
                return error_response(status=401,
                                      message="Missing authorization header")

            token = get_token_from_authorization_header(auth_header)

            try:
                claims = decode(token,
                                public_key,
                                algorithms="RS256",
                                audience=AUDIENCE_NAME)
                user, created = get_or_create_user(claims["sub"])
            except (InvalidTokenError, KeyError) as e:
                logger.info("Failed to decode authorization token: %s", e)
                return error_response(status=401,
                                      message="Invalid authorization token")

            if created:
                logger.info(
                    "First time user with external_id '%s' has authenticated",
                    claims["sub"],
                )

            request.user = user
            return func(request, *args, **kwargs)
Beispiel #7
0
 def create(self, request, *args, **kwargs):
     try:
         to_user = User.objects.get(id=request.data['to_user'])
         # 我->他人 关系处理
         friend_from, is_created_from = self.get_queryset().get_or_create(
             from_user=request.user, to_user=to_user)
         if not is_created_from:
             if friend_from.is_block:
                 # 若已拉黑则解除拉黑
                 friend_from.is_block = False
             else:
                 if friend_from.state == FriendState.Agree:
                     return error_response(3, '不可重复添加好友')
         friend_from.state = 1
         friend_from.say_hi = request.data['say_hi']
         if 'remark' in request.data:
             friend_from.remark = request.data['remark']
         else:
             friend_from.remark = to_user.get_full_name()
         friend_from.save()
         # TODO 向他人推送我请求加他为好友
         try:
             jpush.audience(
                 to_user.id, '好友请求',
                 '用户{}请求添加您为好友'.format(request.user.get_full_name()),
                 {'operation': 'friend_add'})
         except PushError as e:
             logging.error('{} {}'.format(e.code, e.message))
         return success_response('请求已发送')
     except User.DoesNotExist:
         return error_response(2, '该用户不存在')
     except Exception as e:
         return error_response(1, str(e))
Beispiel #8
0
def delete_move_handler(request, move_id):
    uuid_move_id = parse_move_id_as_uuid(move_id)
    if uuid_move_id is None:
        return error_response(status=404)

    move = get_move_by_move_id(request.user, uuid_move_id)
    if move is None:
        return error_response(status=404)

    delete_move(move)
    return success_response(status=204)
Beispiel #9
0
 def check(self, request):
     try:
         instance = self.get_queryset().get(user=self.request.user,
                                            version=request.data['version'])
         return success_response(instance.is_agree)
     except ObjectDoesNotExist:
         return success_response(False)
     except MultipleObjectsReturned:
         return success_response(False)
     except KeyError as e:
         return error_response(1, '获取参数{}失败'.format(e.__context__))
     except Exception as e:
         return error_response(1, str(e))
Beispiel #10
0
def update_trip_handler(request, trip_id):
    db_trip = get_trip_by_id(request.user, trip_id)
    if not db_trip:
        return error_response(status=404)

    parsed_body = safe_parse_json(request.body)
    if parsed_body is None:
        return error_response(message="Could not parse JSON body")
    try:
        updated_trip = update_trip(request.user, db_trip, **parsed_body)
    except UpdateNotAllowed:
        return validation_error_response(
            ["Cannot update one or more requested fields"])
    return success_response(data=Trip.from_db_model(updated_trip))
Beispiel #11
0
    def find_pwd(self, request):
        try:
            tel = request.data['tel']
            code = request.data['code']
            # 防止输入空用户名试图登陆
            if not tel or tel == '':
                return error_response(2, '无此用户')

            if is_tel(tel):
                check_sms_verify(tel, 2, code)
                user = User.objects.get(tel=tel)
            else:
                return error_response(4, '请使用合法号码找回密码')

            if user.is_active:
                user.set_password(request.data['pwd_new'])
                user.save()
                return success_response('找回密码成功。')
            else:
                return error_response(6, '该账号未激活')
        except VerifyError as e:
            return error_response(3, e.message)
        except User.DoesNotExist:
            return error_response(2, '无此用户')
        except User.MultipleObjectsReturned:
            return error_response(5, '用户登陆凭证冲突')
        except KeyError as e:
            return error_response(1, '获取参数{}失败'.format(e.__context__))
        except Exception as e:
            return error_response(1, str(e))
Beispiel #12
0
 def exist(self, request):
     try:
         username = request.data['username']
         User.objects.get(
             Q(username=username) | Q(tel=username) | Q(email=username))
         return success_response(True)
     except ObjectDoesNotExist:
         return success_response(False)
     except MultipleObjectsReturned:
         return success_response(False)
     except KeyError as e:
         return error_response(1, '获取参数{}失败'.format(e.__context__))
     except Exception as e:
         return error_response(1, str(e))
Beispiel #13
0
def trip_id_endpoint(request, *args, **kwargs):
    if request.method == "GET":
        return get_trip_handler(request, *args, **kwargs)
    if request.method == "PATCH":
        return update_trip_handler(request, *args, **kwargs)

    return error_response(status=404)
Beispiel #14
0
def get_trip_handler(request, trip_id):
    db_trip = get_trip_by_id(request.user, trip_id)
    if not db_trip:
        return error_response(status=404)

    trip = get_response_trip(db_trip)
    return success_response(data=trip)
Beispiel #15
0
def revoke_refresh_token(request):
    request_data = get_request_data(request.body)
    if request_data is None:
        return error_response("Invalid or malformed request data")

    payload = get_refresh_token_payload_if_active(request_data.refresh_token)
    if payload is None:
        return error_response("Refresh token is invalid")

    success = delete_refresh_token(token_id=payload["jti"])
    if not success:
        logger.info(
            f"Attempt to delete non-existent token: sub={payload['sub']}, jti={payload['jti']}"
        )

    return success_response(status=204)
Beispiel #16
0
def root_endpoint(request, *args, **kwargs):
    if request.method == "GET":
        return list_trips_handler(request, *args, **kwargs)
    if request.method == "POST":
        return create_trip_handler(request, *args, **kwargs)

    return error_response(status=404)
Beispiel #17
0
    def nearby_posts(self, request, *args, **kwargs):
        serializer = PostNearBySerializer(data=request.data)
        if serializer.is_valid():
            data = serializer.validated_data
            longitude = float(data['longitude'])
            latitude = float(data['latitude'])
            distance = float(data['distance'])
            lon_min, lon_max, lat_min, lat_max = bounding_box(longitude, latitude, distance)
            # 正方形内帖子
            box_queryset = self.get_queryset().filter(longitude__gte=lon_min, longitude__lte=lon_max,
                                                      latitude__gte=lat_min, latitude__lte=lat_max)
            # 正方形内筛选圆形区域
            ids = []
            for x in box_queryset:
                if haversine(longitude, latitude, x.longitude, x.latitude) <= distance:
                    ids.append(x.id)
            queryset = box_queryset.filter(id__in=ids)
            # list部分
            queryset = self.filter_queryset(queryset)
            context = self.get_serializer_context()
            context.update({'longitude': longitude, 'latitude': latitude})

            page = self.paginate_queryset(queryset)
            if page is not None:
                serializer = PostDistanceListSerializer(page, context=context, many=True)
                return self.get_paginated_response(serializer.data)

            serializer = self.get_serializer(queryset, context=context, many=True)
            return success_response(serializer.data)
        else:
            return error_response(1, self.humanize_errors(serializer))
Beispiel #18
0
 def destroy(self, request, *args, **kwargs):
     instance = self.get_object()
     if request.user == instance.from_user:
         self.perform_destroy(instance)
         return success_response('删除成功')
     else:
         return error_response(1, '无此权限')
Beispiel #19
0
 def push(self, request):
     try:
         jpush.audience(request.user.id, 'Hello', 'hello python jpush api',
                        {})
         return success_response('推送成功')
     except PushError as e:
         return error_response(e.code, e.message)
Beispiel #20
0
    def login(self, request):
        try:
            username = request.data['username']
            try:
                instance = User.objects.get(
                    Q(username=username) | Q(tel=username))
            except ObjectDoesNotExist:
                return error_response(2, '用户名或密码错误')
            except MultipleObjectsReturned:
                return error_response(3, '用户登陆凭证冲突')

            if 'password' in request.data:
                # 密码登陆
                user = authenticate(username=instance.username,
                                    password=request.data['password'])
            elif 'code' in request.data:
                # 验证码登陆
                if is_tel(username):
                    try:
                        check_sms_verify(username, 4, request.data['code'])
                        user = instance
                    except VerifyError as e:
                        return error_response(5, e.message)
                else:
                    return error_response(6, '请输入合法号码')
            else:
                return error_response(5, '未提供登陆凭证')

            if user is not None:
                if user.is_active:
                    # 登陆系统
                    login(request, user)
                    # 更新登陆时间
                    user.last_login = timezone.now()
                    user.save()
                    data = {
                        'id': user.id,
                        'token': user.get_token(),
                        'im_token': user.get_im_token(),
                        'name': user.get_full_name(),
                        'portal':
                        request.build_absolute_uri(user.get_portrait())
                    }
                    return success_response(data)
                else:
                    return error_response(4, '该账号未激活')
            else:
                return error_response(2, '用户名或密码错误')
        except KeyError as e:
            return error_response(1, '获取参数{}失败'.format(e.__context__))
        except Exception as e:
            return error_response(1, str(e))
Beispiel #21
0
def message_status_webhook(request):
    request_data = get_request_data(request.POST)
    if request_data is None:
        logger.error("got invalid webhook request")
        return error_response()

    logger.info(f"message status updated: {request_data}")
    return success_response()
Beispiel #22
0
 def change_pwd(self, request):
     try:
         user = authenticate(username=request.user.username,
                             password=request.data['pwd_old'])
         if user is not None:
             if user.is_active:
                 user.set_password(request.data['pwd_new'])
                 user.save()
                 return success_response('修改成功。')
             else:
                 return error_response(3, '该账号未激活')
         else:
             return error_response(2, '旧密码错误')
     except KeyError as e:
         return error_response(1, '获取参数{}失败'.format(e.__context__))
     except Exception as e:
         return error_response(1, str(e))
Beispiel #23
0
 def create(self, request, *args, **kwargs):
     data = request.data.copy()
     data['user'] = request.user.id
     serializer = self.get_serializer(data=data)
     if serializer.is_valid():
         serializer.save()
         return success_response('设置成功')
     else:
         return error_response(1, self.humanize_errors(serializer))
Beispiel #24
0
 def create(self, request, *args, **kwargs):
     self.before_create()
     serializer = self.get_serializer(data=request.data)
     if serializer.is_valid():
         instance = self.perform_create(serializer)
         return success_response(self.serializer_classes['retrieve'](
             instance, context=self.get_serializer_context()).data)
     else:
         return error_response(1, self.humanize_errors(serializer))
Beispiel #25
0
def create_location_handler(request, trip_id):
    db_trip = get_trip_by_id(request.user, trip_id)
    if not db_trip:
        return error_response(status=404)

    event = parse_location_from_request_body(request.body)
    if not event.is_valid:
        return validation_error_response(event.validation_errors)

    location = persist_location(db_trip, event)
    return success_response(status=201, data=location)
Beispiel #26
0
def retrieve_access_token(request):
    request_data = get_request_data(request.body)
    if request_data is None:
        return error_response("Invalid or missing fields in request body")

    refresh_token_payload = get_refresh_token_payload_if_active(
        request_data.refresh_token
    )
    if refresh_token_payload is None:
        return error_response("Refresh token is invalid")

    current_time = get_current_utc_time()
    access_token, access_token_payload = generate_access_token_for_user(
        refresh_token_payload["sub"], current_time
    )
    response_data = ResponseData(
        access_token=access_token,
        expiry_time=from_timestamp(access_token_payload["exp"]),
    )
    return success_response(response_data)
Beispiel #27
0
    def send_verify(self, request):
        try:
            purpose = int(request.data['purpose'])
            tel = request.data['tel']
            if is_tel(tel):
                if purpose == 1 and User.objects.filter(tel=tel).exists():
                    return error_response(2, '该用户已注册,请直接登陆')
                elif purpose == 2 and not User.objects.filter(
                        tel=tel).exists():
                    return error_response(3, '该用户未注册,无法找回密码')

                # 发送短信验证码
                tel_verify, create = TelVerify.objects.get_or_create(
                    tel=tel, purpose=purpose)
                # 未创建则更新
                if not create:
                    tel_verify.update()
                # 更新发送时间
                tel_verify.send_time = timezone.now()
                tel_verify.save()
                # 发送短信
                is_success, message = tel_verify.send_sms()
                if is_success:
                    return success_response('发送成功')
                else:
                    logger.error('短信发送失败 原因:{}'.format(message))
                    return error_response(5, message)
            else:
                return error_response(4, '请输入合法号码')
        except KeyError as e:
            return error_response(1, '获取参数{}失败'.format(e.__context__))
        except Exception as e:
            return error_response(1, str(e))
Beispiel #28
0
 def operate(self, request):
     serializer = FavoritesOperateSerializer(
         data=request.data, context=self.get_serializer_context())
     if serializer.is_valid():
         data = serializer.validated_data
         if data['operate'] == 0:
             data['favorites'].posts.add(data['post'])
             return success_response('收藏成功')
         else:
             # 取消收藏
             data['favorites'].posts.remove(data['post'])
             return success_response('取消收藏成功')
     else:
         return error_response(1, self.humanize_errors(serializer))
Beispiel #29
0
def revoke_refresh_token(request):
    """
    Revokes a refresh token. This revokes the tokens ability to generate new access
    tokens.

    Note: Existing access tokens generated by the revoked refresh token will continue to
    be valid until they expire.
    """
    request_data = get_request_data(request.body)
    if request_data is None:
        return error_response("Invalid or malformed request data")

    payload = get_refresh_token_payload_if_active(request_data.refresh_token)
    if payload is None:
        return error_response("Refresh token is invalid")

    success = delete_refresh_token(token_id=payload["jti"])
    if not success:
        logger.info(
            f"Attempt to delete non-existent token: sub={payload['sub']}, jti={payload['jti']}"
        )

    return success_response(status=204)
Beispiel #30
0
def itinerary_handler(request, trip_id):
    trip = get_trip_by_id(request.user, trip_id)
    if trip is None:
        return error_response(status=404)

    locations = get_locations_for_trip(trip)

    logger.info(
        "constructing itinerary for trip '%s' with %d locations",
        trip.trip_id,
        len(locations),
    )
    itinerary = get_itinerary_events_by_day_for_locations(locations)
    return success_response(data={"itinerary": to_response_shape(itinerary)})