예제 #1
0
def _subscriptions_view_POST(request):
  form = NewSubscriptionForm(request.POST)
  if not form.is_valid():
    return bad_request('Invalid subscription data.', errors=form.errors)

  email = form.cleaned_data.get('email')
  my_email = form.cleaned_data.get('my_email')
  slack_url = form.cleaned_data.get('slack_url')
  slack_channel_name = form.cleaned_data.get('slack_channel_name')

  sub = None
  if email:
    sub = appstore_sales_report_subscriptions.create_email_subscription(request.user, email)
  elif my_email:
    sub = appstore_sales_report_subscriptions.create_my_email_subscription(request.user)
  elif slack_channel_name:
    sub = appstore_sales_report_subscriptions.create_slack_channel_subscription(request.user, slack_channel_name)
  elif slack_url:
    sub = appstore_sales_report_subscriptions.create_slack_subscription(request.user, slack_url)

  if not sub:
    return bad_request('Subscription already exists.')

  new_flags = []
  if not request.user.flags.has_sales_monitor:
    new_flags.append('has_sales_monitor')

  if new_flags:
    request.user.set_flags(new_flags)

  return api_response({
    'subscription': sub.to_dict(),
  })
예제 #2
0
def get_sales_metrics_view(request):
  requested_date = request.GET.get('requested_date')
  if requested_date:
    try:
      requested_date = float(requested_date)
      requested_date = date.fromtimestamp(requested_date)
    except ValueError:
      return bad_request('Invalid `requsted_date`')

  if not requested_date:
    requested_date = itunes_connect.get_freshest_sales_report_date()

  vendor = itunes_connect.get_chosen_vendor_for_user(request.user)
  if not vendor:
    return bad_request('No iTunes vendor chosen for this user yet.')

  status = itunes_connect.report_status_for_vendor_date(vendor, requested_date)
  if status == itunes_connect.REPORT_STATUS_AVAILABLE:
    app_sales_metrics, total_sales_metrics = itunes_connect.get_sales_metrics(vendor, requested_date)
    for app_metrics in app_sales_metrics:
      app_metrics['app'] = app_metrics['app'].to_dict()

  else:
    app_sales_metrics, total_sales_metrics = None, None

  return api_response({
    'status': status,

    'appSalesMetrics': app_sales_metrics,
    'totalSalesMetrics': total_sales_metrics,

    'date': APIModel.date_to_api_date(requested_date),
    'vendor': vendor.to_dict(),
  })
예제 #3
0
def screenshot_set_add_shot_view(request, set_id=None):
  my_set = screenshots.get_set_by_encrypted_id(request.user, set_id)
  if not my_set:
    return not_found()

  if my_set.shot_count >= 5:
    return bad_request('Maximum number of shots in this set already.')

  form = CreateUpdateShotForm(request.POST)
  if not form.is_valid():
    logging.warn('Invalid shot data: %s', dict(form.errors))
    return bad_request('Invalid shot data.', errors=form.errors)

  if not form.cleaned_data.get('screenshot_image_id'):
    return bad_request('Please supply `screenshot_image_id`.')

  fields = form.cleaned_data
  post_keys = set(request.POST.keys())
  for key in fields.keys():
    if key not in post_keys:
      # default from the form
      del fields[key]

  fields['screenshot_image'] = fields['screenshot_image_id']
  del fields['screenshot_image_id']

  if 'background_image_id' in fields:
    fields['background_image'] = fields['background_image_id']
    del fields['background_image_id']

  shot = screenshots.create_shot_in_set(request.user, my_set, **fields)
  return api_response({
    'shot': shot.to_dict(),
  })
예제 #4
0
파일: auth.py 프로젝트: yutaza/LaunchKit
def signup(request):
    if request.user.is_authenticated():
        return bad_request('You are already signed in.')

    user_form = UserSignupForm(request.POST)
    if not user_form.is_valid():
        return bad_request(message='Invalid user signup data',
                           errors=user_form.errors)

    email = user_form.cleaned_data.get('email')

    password = user_form.cleaned_data['password']
    user = users.create_user(user_form.cleaned_data['first_name'],
                             user_form.cleaned_data['last_name'],
                             email=email,
                             password=password)

    if not user:
        logging.warn('Unaccounted for signup error with signup data: %r',
                     user_form.cleaned_data)
        return bad_request(
            'Could not create a user with the given credentials.')

    return api_response({
        'user': user.to_dict(),
    })
예제 #5
0
def config_rule_view(request, rule_id):
    rule = RuntimeConfigRule.objects.filter(
        id=RuntimeConfigRule.decrypt_id(rule_id),
        user_id=request.user.id).first()
    if not rule:
        return not_found()

    if request.method == 'POST':
        target_form = EditRuleForm(request.POST)
        if not target_form.is_valid():
            return bad_request('Invalid edit config values.',
                               errors=target_form.errors)

        cleaned_data = target_form.cleaned_data

        if 'value' in request.POST:
            value_form = ValueForm(rule.kind, request.POST)
            if not value_form.is_valid():
                return bad_request('Invalid edit config values.',
                                   errors=value_form.errors)
            cleaned_data.update(value_form.cleaned_data)

        # strip out arguments that were not present in the actual POSTbody.
        cleaned_data = {
            k: v
            for k, v in cleaned_data.items() if k in request.POST
        }

        runtime_config.update_rule(rule, **cleaned_data)

    return api_response({
        'rule': rule.to_dict(),
    })
예제 #6
0
def request_verification_email(request):
  email = None
  if 'email' in request.POST or not request.user.is_authenticated():
    # Should this be a separate form? Meh.
    form = ResetPasswordForm(request.POST)
    if not form.is_valid():
      return bad_request('Bad email verification request',
          errors=form.errors)
    email = form.cleaned_data['email']

  if request.user.is_authenticated():
    unverified_emails = users.get_unverified_emails(request.user)
    if not unverified_emails:
      return bad_request('No unverified emails for this account.')

    if not email:
      email = unverified_emails[0]
    elif email not in unverified_emails:
      return bad_request('Could not find this unverified email address.')

  success = users.request_verification_email(email)
  if not success:
    return bad_request('Could not request a verification email. Has the email already been verified?')

  return ok_response()
예제 #7
0
파일: itunes.py 프로젝트: yutaza/LaunchKit
def get_sales_metrics_view(request):
    requested_date = request.GET.get('requested_date')
    if requested_date:
        try:
            requested_date = float(requested_date)
            requested_date = date.fromtimestamp(requested_date)
        except ValueError:
            return bad_request('Invalid `requsted_date`')

    if not requested_date:
        requested_date = itunes_connect.get_freshest_sales_report_date()

    vendor = itunes_connect.get_chosen_vendor_for_user(request.user)
    if not vendor:
        return bad_request('No iTunes vendor chosen for this user yet.')

    status = itunes_connect.report_status_for_vendor_date(
        vendor, requested_date)
    if status == itunes_connect.REPORT_STATUS_AVAILABLE:
        app_sales_metrics, total_sales_metrics = itunes_connect.get_sales_metrics(
            vendor, requested_date)
        for app_metrics in app_sales_metrics:
            app_metrics['app'] = app_metrics['app'].to_dict()

    else:
        app_sales_metrics, total_sales_metrics = None, None

    return api_response({
        'status': status,
        'appSalesMetrics': app_sales_metrics,
        'totalSalesMetrics': total_sales_metrics,
        'date': APIModel.date_to_api_date(requested_date),
        'vendor': vendor.to_dict(),
    })
예제 #8
0
def screenshot_set_create_bundle_view(request, set_id=None):
  my_set, shots = screenshots.get_set_and_shots_by_encrypted_id(request.user, set_id,
      enable_logged_out=False)
  if not my_set:
    return not_found()

  upload_ids = request.POST.getlist('upload_id') or []
  try:
    upload_ids = [long(i) for i in upload_ids]
  except (ValueError, TypeError):
    logging.info('invalid upload_ids: %s (set id: %s)', upload_ids, set_id)
    return bad_request('Invalid `upload_id`, each should be long integer.')

  if not upload_ids:
    logging.info('upload ids: %s body: %s %s %s', upload_ids, request.body, request.POST, request.method)
    return bad_request('Invalid `upload_id`, each should be a GAE upload ID.')

  upload_names = filter(lambda n: n and n.strip(), request.POST.getlist('upload_name') or [])
  if len(upload_ids) != len(upload_names):
    logging.info('invalid upload_names: %s upload_ids: %s (set id: %s)', upload_ids, upload_names, set_id)
    return bad_request('Invalid `upload_name`, each should be an upload filename corresponding to the `upload_id` provided.')

  hq = request.POST.get('hq') == '1'
  bundle = screenshot_bundler.build_screenshot_bundle(my_set, request.user, upload_ids, upload_names, hq=hq)
  if not bundle:
    return unavailable_response()

  return api_response({
    'bundleId': bundle.encrypted_id,
  })
예제 #9
0
def emails_view(request):
  user_emails = list(request.user.emails_set.all())
  if request.method == 'GET':
    return api_response({
      'emails': [email.to_dict() for email in user_emails],
    })

  if len([e for e in user_emails if not e.verified]) > 3:
    return bad_request('Cannot add another unverified email address.',
        errors={'email': ['Too many unverified email addresses.']})

  form = EmailForm(request.POST)
  if not form.is_valid():
    return bad_request('Invalid email address.', errors=form.errors)

  new_email = form.cleaned_data['email']
  if new_email in [e.email for e in user_emails]:
    return bad_request('Cannot add an email you already have.',
        errors={'email': ['Account already associated with that address.']})

  email = users.associate_user_with_email(request.user,
      new_email, verified=False)
  if not email:
    return bad_request('Email is already in use.',
        errors={'email': ['Sorry, that email is already in use.']},
        status=409)

  return api_response({
    'email': email.to_dict(),
  })
예제 #10
0
def config_rule_view(request, rule_id):
  rule = RuntimeConfigRule.objects.filter(
      id=RuntimeConfigRule.decrypt_id(rule_id),
      user_id=request.user.id).first()
  if not rule:
    return not_found()

  if request.method == 'POST':
    target_form = EditRuleForm(request.POST)
    if not target_form.is_valid():
      return bad_request('Invalid edit config values.', errors=target_form.errors)

    cleaned_data = target_form.cleaned_data

    if 'value' in request.POST:
      value_form = ValueForm(rule.kind, request.POST)
      if not value_form.is_valid():
        return bad_request('Invalid edit config values.', errors=value_form.errors)
      cleaned_data.update(value_form.cleaned_data)

    # strip out arguments that were not present in the actual POSTbody.
    cleaned_data = {k: v for k, v in cleaned_data.items() if k in request.POST}

    runtime_config.update_rule(rule, **cleaned_data)

  return api_response({
    'rule': rule.to_dict(),
  })
예제 #11
0
  def _create_image_view(request):
    if settings.IS_PRODUCTION:
      referer = request.META.get('HTTP_REFERER', '')
      if not any(referer.startswith(ap) for ap in ACCEPTABLE_PREFIXES):
        logging.info('Blocked request with missing referer')
        return bad_request()

    try:
      gae_id = int(request.POST['upload_id'])
    except (KeyError, ValueError, TypeError):
      gae_id = None

    if not gae_id:
      return bad_request('Please include `upload_id`.')

    user = None
    if request.user.is_authenticated():
      user = request.user

    image_result = fn(gae_id, user)
    if image_result.bad_request:
      return bad_request('Invalid image provided.')

    if image_result.server_error:
      return unavailable_response()

    image = image_result.image
    return api_response({
      'image': image.to_dict()
    })
예제 #12
0
파일: auth.py 프로젝트: yutaza/LaunchKit
def request_verification_email(request):
    email = None
    if 'email' in request.POST or not request.user.is_authenticated():
        # Should this be a separate form? Meh.
        form = ResetPasswordForm(request.POST)
        if not form.is_valid():
            return bad_request('Bad email verification request',
                               errors=form.errors)
        email = form.cleaned_data['email']

    if request.user.is_authenticated():
        unverified_emails = users.get_unverified_emails(request.user)
        if not unverified_emails:
            return bad_request('No unverified emails for this account.')

        if not email:
            email = unverified_emails[0]
        elif email not in unverified_emails:
            return bad_request('Could not find this unverified email address.')

    success = users.request_verification_email(email)
    if not success:
        return bad_request(
            'Could not request a verification email. Has the email already been verified?'
        )

    return ok_response()
예제 #13
0
def _websites_view_POST(request):
  itunes_id = request.POST.get('itunes_id')
  country = request.POST.get('country', 'us')
  if itunes_id and country:
    itunes_app = appstore.get_app_by_itunes_id(itunes_id, country)
  else:
    itunes_app = None

  post_data = {
    'template': '1',
    'frame_screenshots': 'white',
  }

  # Create website from iTunes info.
  if itunes_app:
    name, tagline = text.app_name_tagline(itunes_app.name)

    post_data.update({
      'itunes_id': itunes_app.itunes_id,
      'country': itunes_app.country,

      'app_name': name,
      'tagline': tagline,
      'long_description': itunes_app.description,
    })

  for k, v in request.POST.items():
    post_data[k] = v or post_data.get(k, '')

  form = AppWebsiteForm(post_data)
  if not form.is_valid():
    logging.info('Website creation problem: %s', dict(form.errors))
    return bad_request('Invalid website data.', errors=form.errors)

  domain = form.cleaned_data.get('domain')
  if domain:
    in_use_website = AppWebsite.objects.filter(domain=domain).count()
    if in_use_website:
      return bad_request('Invalid website data', errors={'domain': ['Domain already in use.']})

  screenshots_form = AppWebsiteScreenshotsForm(request.POST)
  if not screenshots_form.is_valid():
    return bad_request('Invalid screenshots provided.')

  new_website = AppWebsite(user=request.user)
  _assign_properties_from_dict(new_website, form.cleaned_model_data())
  new_website.save()

  # ADD ASSOCIATED SCREENSHOTS

  iphone_screenshots = screenshots_form.cleaned_data.get('iphone_screenshot_ids', [])
  if iphone_screenshots:
    websites.update_website_screenshots(new_website, iphone_screenshots, 'iPhone')

  request.user.set_flags(['has_websites'])

  return api_response({
    'website': new_website.to_dict(),
  })
예제 #14
0
def _website_view_POST(request, website_id):
    website = AppWebsite.find_by_encrypted_id(website_id,
                                              user_id=request.user.id,
                                              for_update=True)
    if not website or website.delete_time:
        return not_found()

    # FORM VALIDATION

    form = EditAppWebsiteForm(request.POST)
    if not form.is_valid():
        logging.info('Website edit problem (id=%s): %s', website.encrypted_id,
                     dict(form.errors))
        return bad_request('Invalid website data.', errors=form.errors)

    domain = form.cleaned_data.get('domain')
    if domain:
        in_use_website = AppWebsite.objects.filter(domain=domain).exclude(
            id=website.id).count()
        if in_use_website:
            return bad_request('Invalid website data',
                               errors={'domain': ['Domain already in use.']})

    screenshots_form = AppWebsiteScreenshotsForm(request.POST)
    if not screenshots_form.is_valid():
        logging.info('Website screenshots problem (id=%s): %s',
                     website.encrypted_id, dict(screenshots_form.errors))
        return bad_request('Invalid screenshots provided.',
                           errors=screenshots_form.errors)

    # ASSIGN MODIFIED PROPERTIES

    # Only assign values that were actually passed in the POSTbody.
    _assign_properties_from_dict(
        website, form.cleaned_model_data(filter_values=request.POST))

    # UPDATE ASSOCIATED SCREENSHOTS

    iphone_screenshots = screenshots_form.cleaned_data.get(
        'iphone_screenshot_ids', [])
    if iphone_screenshots:
        websites.update_website_screenshots(website, iphone_screenshots,
                                            'iPhone')

    # UPDATE HOSTED PAGES
    hosted_pages = EditPageForm(request.POST)
    if not hosted_pages.is_valid():
        return bad_request('Invalid website data.', errors=hosted_pages.errors)

    for field in hosted_pages:
        # Check if this field was actually included in the POSTdata with this request.
        if field.name in request.POST:
            websites.create_or_update_hosted_page(website, field.name,
                                                  field.value())

    website.save()
    return api_response({'website': website.to_dict()})
예제 #15
0
파일: auth.py 프로젝트: yutaza/LaunchKit
def reset_password_view(request):
    form = ResetPasswordForm(request.POST)
    if not form.is_valid():
        return bad_request('Bad reset password request', errors=form.errors)

    success = users.request_reset_password_email(form.cleaned_data['email'])
    if not success:
        return bad_request('Could not find a user with that email address')

    return ok_response()
예제 #16
0
def email_set_primary_view(request):
  form = EmailForm(request.POST)
  if not form.is_valid():
    return bad_request('Invalid email provided.', errors=form.errors)

  if not users.make_email_primary(request.user, form.cleaned_data['email']):
    return bad_request('Could not promote email address to primary.')

  return api_response({
    'emails': [e.to_dict() for e in request.user.emails_set.all()],
  })
예제 #17
0
def email_delete_view(request):
  form = EmailForm(request.POST)
  if not form.is_valid():
    return bad_request('Invalid email provided.', errors=form.errors)

  if not users.disassociate_user_with_email(request.user, form.cleaned_data['email']):
    return bad_request('Could not disassociate that email address.')

  return api_response({
    'emails': [e.to_dict() for e in request.user.emails_set.all()],
  })
예제 #18
0
def reset_password_view(request):
  form = ResetPasswordForm(request.POST)
  if not form.is_valid():
    return bad_request('Bad reset password request',
        errors=form.errors)

  success = users.request_reset_password_email(form.cleaned_data['email'])
  if not success:
    return bad_request('Could not find a user with that email address')

  return ok_response()
예제 #19
0
파일: auth.py 프로젝트: yutaza/LaunchKit
def email_set_primary_view(request):
    form = EmailForm(request.POST)
    if not form.is_valid():
        return bad_request('Invalid email provided.', errors=form.errors)

    if not users.make_email_primary(request.user, form.cleaned_data['email']):
        return bad_request('Could not promote email address to primary.')

    return api_response({
        'emails': [e.to_dict() for e in request.user.emails_set.all()],
    })
예제 #20
0
def choose_vendor_view(request):
  vendor_id = request.POST.get('vendor_id')
  if not vendor_id:
    return bad_request()

  vendor = ItunesConnectVendor.find_by_encrypted_id(vendor_id)
  if not vendor or vendor.user_id != request.user.id:
    return bad_request()

  itunes_connect.choose_vendor(request.user, vendor)

  return ok_response()
예제 #21
0
def unsubscribe_view(request):
  form = UnsubscribeForm(request.POST)
  if not form.is_valid():
    return bad_request('Bad unsub request', errors=form.errors)

  token = form.cleaned_data['token']

  success = users.unsubscribe_with_token(token)
  if not success:
    return bad_request('Invalid token data.')

  return ok_response()
예제 #22
0
파일: itunes.py 프로젝트: yutaza/LaunchKit
def choose_vendor_view(request):
    vendor_id = request.POST.get('vendor_id')
    if not vendor_id:
        return bad_request()

    vendor = ItunesConnectVendor.find_by_encrypted_id(vendor_id)
    if not vendor or vendor.user_id != request.user.id:
        return bad_request()

    itunes_connect.choose_vendor(request.user, vendor)

    return ok_response()
예제 #23
0
def verify_email_view(request):
  form = VerifyEmailForm(request.POST)
  if not form.is_valid():
    return bad_request('Bad verification request', errors=form.errors)

  token = form.cleaned_data['token']

  success = users.verify_email_from_token(token)
  if not success:
    return bad_request('Invalid token data.')

  return ok_response()
예제 #24
0
파일: auth.py 프로젝트: yutaza/LaunchKit
def email_delete_view(request):
    form = EmailForm(request.POST)
    if not form.is_valid():
        return bad_request('Invalid email provided.', errors=form.errors)

    if not users.disassociate_user_with_email(request.user,
                                              form.cleaned_data['email']):
        return bad_request('Could not disassociate that email address.')

    return api_response({
        'emails': [e.to_dict() for e in request.user.emails_set.all()],
    })
예제 #25
0
파일: auth.py 프로젝트: yutaza/LaunchKit
def verify_email_view(request):
    form = VerifyEmailForm(request.POST)
    if not form.is_valid():
        return bad_request('Bad verification request', errors=form.errors)

    token = form.cleaned_data['token']

    success = users.verify_email_from_token(token)
    if not success:
        return bad_request('Invalid token data.')

    return ok_response()
예제 #26
0
파일: auth.py 프로젝트: yutaza/LaunchKit
def unsubscribe_view(request):
    form = UnsubscribeForm(request.POST)
    if not form.is_valid():
        return bad_request('Bad unsub request', errors=form.errors)

    token = form.cleaned_data['token']

    success = users.unsubscribe_with_token(token)
    if not success:
        return bad_request('Invalid token data.')

    return ok_response()
예제 #27
0
파일: auth.py 프로젝트: yutaza/LaunchKit
def user_details(request):
    def _build_response():
        user = User.get_cached(request.user.id)

        flags = {}
        for flag in users.USER_EDITABLE_USER_FLAGS:
            flags[flag] = bool(getattr(user.flags, flag))

        return api_response({
            'user':
            user.to_dict(),
            'emails': [email.to_dict() for email in user.emails_set.all()],
            'settings':
            flags
        })

    if request.method != 'POST':
        return _build_response()

    # Get an exclusive lock on this user.
    user = User.objects.select_for_update().get(pk=request.user.id)

    # Edit details.
    flag_updates = {}
    for flag in users.USER_EDITABLE_USER_FLAGS:
        if flag in request.POST:
            flag_value = request.POST[flag]
            if flag_value not in ('1', '0'):
                return bad_request(
                    message='Bad flag value.',
                    errors={flag: 'Provided value should be "1" or "0"'})
            flag_updates[flag] = (flag_value == '1')

    if flag_updates:
        users.update_user_flags(user, flag_updates)

    form = UserDetailsEditForm(request.POST)
    if not form.is_valid():
        return bad_request(message='Invalid edit fields.', errors=form.errors)

    update_fields = []
    if 'first_name' in request.POST:
        user.first_name = form.cleaned_data['first_name']
        update_fields.append('first_name')
    if 'last_name' in request.POST:
        user.last_name = form.cleaned_data['last_name']
        update_fields.append('last_name')

    if update_fields:
        user.save(update_fields=update_fields)

    return _build_response()
예제 #28
0
def reset_password_finish_view(request):
  form = SetNewPasswordForm(request.POST)
  if not form.is_valid():
    return bad_request('Bad reset password request', errors=form.errors)

  token = form.cleaned_data['token']
  password = form.cleaned_data['password']

  success = users.reset_password_with_email_token(token, password)
  if not success:
    return bad_request('Invalid token data.')

  return ok_response()
예제 #29
0
파일: auth.py 프로젝트: yutaza/LaunchKit
def reset_password_finish_view(request):
    form = SetNewPasswordForm(request.POST)
    if not form.is_valid():
        return bad_request('Bad reset password request', errors=form.errors)

    token = form.cleaned_data['token']
    password = form.cleaned_data['password']

    success = users.reset_password_with_email_token(token, password)
    if not success:
        return bad_request('Invalid token data.')

    return ok_response()
예제 #30
0
def screenshot_set_duplicate_view(request, set_id=None):
  my_set, _ = screenshots.get_set_and_shots_by_encrypted_id(request.user, set_id)
  if not my_set or request.user.id != my_set.user.id:
    return bad_request('You dont have premissions.')

  form = NewSetForm(request.POST)
  if not form.is_valid():
    return bad_request('Invalid new set.', errors=form.errors)

  new_set = screenshots.duplicate_set(my_set, form.cleaned_data['name'], form.cleaned_data['version'], form.cleaned_data['platform'])

  return api_response({
    'set': new_set.to_dict()
  })
예제 #31
0
def _configs_view_POST(request):
    form = CreateRuleForm(request.POST)

    if not form.is_valid():
        logging.info('Invalid rules: %s POST: %s', dict(form.errors),
                     dict(request.POST))
        return bad_request(message='Invalid rule parameters.',
                           errors=form.errors)

    key = form.cleaned_data['key']
    del form.cleaned_data['key']

    bundle_id = form.cleaned_data['bundle_id']
    # Create the app row if it doesn't exist so we can populate the "my apps" dropdown.
    app = sdk_apps.decorated_app_by_bundle_id(request.user, bundle_id)
    if not app.config:
        app.config = True
        app.save(update_fields=['products'])

    rules = runtime_config.rules_for_user_key(request.user, key, bundle_id)

    kind = None
    if 'kind' in form.cleaned_data:
        kind = form.cleaned_data['kind']
        del form.cleaned_data['kind']
        if rules and rules[0].kind != kind:
            return bad_request(
                'Key already exists as a different `kind`; cannot change type.'
            )
    elif rules:
        kind = rules[0].kind

    if not kind:
        return bad_request('Please provide a `kind` for this key.')

    value_form = ValueForm(kind, request.POST)
    if not value_form.is_valid():
        return bad_request(message='Invalid rule `value`.', errors=form.errors)

    value = value_form.cleaned_data['value']

    rule = runtime_config.create_rule(request.user, key, kind, value,
                                      **form.cleaned_data)

    if not request.user.flags.has_config:
        request.user.set_flags(['has_config'])

    return api_response({
        'rule': rule.to_dict(),
    })
예제 #32
0
파일: slack.py 프로젝트: yutaza/LaunchKit
def connect_slack_view(request):
    code = request.POST.get('code')
    service = request.POST.get('service')
    onboarding = request.POST.get('onboarding') == '1'
    if not (code and service):
        return bad_request(
            'Please provide a `code` from the Slack OAuth2 endpoint, LK `service` to connect, and `onboarding` status.'
        )

    success = slack.associate_user_with_slack(request.user, code, service,
                                              onboarding)
    if not success:
        return bad_request('Could not fetch a slack token with that `code`.')

    return ok_response()
예제 #33
0
def user_details(request):
  def _build_response():
    user = User.get_cached(request.user.id)

    flags = {}
    for flag in users.USER_EDITABLE_USER_FLAGS:
      flags[flag] = bool(getattr(user.flags, flag))

    return api_response({
      'user': user.to_dict(),
      'emails': [email.to_dict() for email in user.emails_set.all()],
      'settings': flags
    })

  if request.method != 'POST':
    return _build_response()

  # Get an exclusive lock on this user.
  user = User.objects.select_for_update().get(pk=request.user.id)

  # Edit details.
  flag_updates = {}
  for flag in users.USER_EDITABLE_USER_FLAGS:
    if flag in request.POST:
      flag_value = request.POST[flag]
      if flag_value not in ('1', '0'):
        return bad_request(message='Bad flag value.', errors={flag: 'Provided value should be "1" or "0"'})
      flag_updates[flag] = (flag_value == '1')

  if flag_updates:
    users.update_user_flags(user, flag_updates)

  form = UserDetailsEditForm(request.POST)
  if not form.is_valid():
    return bad_request(message='Invalid edit fields.', errors=form.errors)

  update_fields = []
  if 'first_name' in request.POST:
    user.first_name = form.cleaned_data['first_name']
    update_fields.append('first_name')
  if 'last_name' in request.POST:
    user.last_name = form.cleaned_data['last_name']
    update_fields.append('last_name')

  if update_fields:
    user.save(update_fields=update_fields)

  return _build_response()
예제 #34
0
def config_interpolated_view(request):
    token_id = request.GET.get('token')

    if token_id:
        user = tokens.user_by_token(token_id)
    else:
        user = request.user

    if not (user and user.is_authenticated()):
        return unauthorized_request(
            'Please provide `token` or `access_token`.')

    form = GetConfigForm(request.GET)
    if not form.is_valid():
        return bad_request('Invalid options for config interpolation',
                           errors=form.errors)

    user_labels = form.cleaned_data.get('sdk_user_labels')
    if user_labels:
        user_labels = ','.split(user_labels)

    config = runtime_config.interpolated_config_for_user(
        user,
        form.cleaned_data['namespace'],
        form.cleaned_data['bundle_id'],
        version=form.cleaned_data['version'],
        build=form.cleaned_data['build'],
        ios_version=form.cleaned_data['ios_version'],
        debug=form.cleaned_data['debug'],
        sdk_user_labels=user_labels)

    return api_response({
        'config': config,
    })
예제 #35
0
def config_interpolated_view(request):
  token_id = request.GET.get('token')

  if token_id:
    user = tokens.user_by_token(token_id)
  else:
    user = request.user

  if not (user and user.is_authenticated()):
    return unauthorized_request('Please provide `token` or `access_token`.')

  form = GetConfigForm(request.GET)
  if not form.is_valid():
    return bad_request('Invalid options for config interpolation', errors=form.errors)

  user_labels = form.cleaned_data.get('sdk_user_labels')
  if user_labels:
    user_labels = ','.split(user_labels)

  config = runtime_config.interpolated_config_for_user(
      user,
      form.cleaned_data['namespace'],
      form.cleaned_data['bundle_id'],
      version=form.cleaned_data['version'],
      build=form.cleaned_data['build'],
      ios_version=form.cleaned_data['ios_version'],
      debug=form.cleaned_data['debug'],
      sdk_user_labels=user_labels)

  return api_response({
    'config': config,
  })
예제 #36
0
def _app_view_POST(request, app):
    form = EditSDKAppForm(request.POST)
    if not form.is_valid():
        return bad_request('Invalid edits provided.', errors=form.errors)

    if form.cleaned_data.get('itunes_country'):
        itunes_id, country = form.cleaned_data.get(
            'itunes_id'), form.cleaned_data.get('itunes_country')
        appstore_app = appstore.get_app_by_itunes_id(itunes_id, country)
        if not appstore_app:
            return bad_request(
                'Invalid `itunes_id` or `itunes_country` provided.')

        if app.appstore_app and app.appstore_app.id != appstore_app.id:
            return bad_request('Cannot change `itunes_id` once it is set.')

        app.itunes_country = country
        app.save(update_fields=['itunes_county'])

    display_name = form.cleaned_data.get('display_name') or None
    if 'display_name' in request.POST:
        # Allow removing this field to default to appstore info / bundle id.
        app.display_name = display_name
        app.save(update_fields=['display_name'])

    super_freq, super_time = form.cleaned_data.get(
        'super_freq'), form.cleaned_data.get('super_time')
    if super_freq:
        session_user_labels.set_super_config(app, super_freq, super_time)

        # TODO(Taylor): Figure out a better place to set this.
        if not request.user.flags.has_super_users:
            request.user.set_flags(['has_super_users'])

    if 'config_parent_id' in request.POST:
        # can also be None if removing parent.
        app.config_parent = form.cleaned_data.get('config_parent_id')
        app.save(update_fields=['config_parent'])

    for sdk_product in SDKProduct.kinds():
        if sdk_product in request.POST:
            setattr(app, sdk_product, form.cleaned_data[sdk_product])
            app.save(update_fields=['products'])

    return api_response({
        'app': app.to_dict(),
    })
예제 #37
0
def subscription_unsubscribe_token_view(request):
  sub = itunes_connect.subscription_from_unsubscribe_token(request.POST.get('token', ''))
  if not sub:
    return bad_request('Could not find subscription with that `token`.')

  appstore_sales_report_subscriptions.disable_subscription(sub)

  return ok_response()
예제 #38
0
def subscription_unsubscribe_token_view(request):
  sub = appstore_review_notify.subscription_from_unsubscribe_token(request.POST.get('token', ''))
  if not sub:
    return bad_request('Could not find subscription with that `token`.')

  appstore_review_subscriptions.disable_subscription(sub)

  return ok_response()
예제 #39
0
def delete_account_view(request):
  email = request.POST.get('email')
  if email != request.user.email:
    return bad_request('Please provide the current account email address, `email`.')

  destructive.delete_account(request.user)

  return ok_response()
예제 #40
0
def disconnect_itunes_view(request):
  connected_email = itunes_connect.itunes_credentials_email_for_user_id(request.user.id)
  if not connected_email:
    return bad_request('No connection to remove.')

  destructive.delete_itunes_connection_and_imports(request.user)

  return ok_response()
예제 #41
0
def _website_view_POST(request, website_id):
  website = AppWebsite.find_by_encrypted_id(website_id, user_id=request.user.id, for_update=True)
  if not website or website.delete_time:
    return not_found()

  # FORM VALIDATION

  form = EditAppWebsiteForm(request.POST)
  if not form.is_valid():
    logging.info('Website edit problem (id=%s): %s', website.encrypted_id, dict(form.errors))
    return bad_request('Invalid website data.', errors=form.errors)

  domain = form.cleaned_data.get('domain')
  if domain:
    in_use_website = AppWebsite.objects.filter(domain=domain).exclude(id=website.id).count()
    if in_use_website:
      return bad_request('Invalid website data', errors={'domain': ['Domain already in use.']})

  screenshots_form = AppWebsiteScreenshotsForm(request.POST)
  if not screenshots_form.is_valid():
    logging.info('Website screenshots problem (id=%s): %s', website.encrypted_id, dict(screenshots_form.errors))
    return bad_request('Invalid screenshots provided.', errors=screenshots_form.errors)

  # ASSIGN MODIFIED PROPERTIES

  # Only assign values that were actually passed in the POSTbody.
  _assign_properties_from_dict(website, form.cleaned_model_data(filter_values=request.POST))

  # UPDATE ASSOCIATED SCREENSHOTS

  iphone_screenshots = screenshots_form.cleaned_data.get('iphone_screenshot_ids', [])
  if iphone_screenshots:
    websites.update_website_screenshots(website, iphone_screenshots, 'iPhone')

  # UPDATE HOSTED PAGES
  hosted_pages = EditPageForm(request.POST)
  if not hosted_pages.is_valid():
    return bad_request('Invalid website data.', errors=hosted_pages.errors)

  for field in hosted_pages:
    # Check if this field was actually included in the POSTdata with this request.
    if field.name in request.POST:
      websites.create_or_update_hosted_page(website, field.name, field.value())

  website.save()
  return api_response({'website': website.to_dict()})
예제 #42
0
def _subscriptions_view_POST(request):
  form = NewSubscriptionForm(request.POST)
  if not form.is_valid():
    return bad_request('Invalid subscription data.', errors=form.errors)

  email = form.cleaned_data.get('email')
  my_email = form.cleaned_data.get('my_email')
  slack_url = form.cleaned_data.get('slack_url')
  slack_channel_name = form.cleaned_data.get('slack_channel_name')
  twitter_app_connection = form.cleaned_data.get('twitter_app_connection_id')

  app = form.cleaned_data.get('app_id')
  if app and not twitter_app_connection:
    try:
      twitter_app_connection = TwitterAppConnection.objects.get(user=request.user, app=app, enabled=True)
    except TwitterAppConnection.DoesNotExist:
      return bad_request('Invalid `app_id`, not already connected to twitter.')

  sub = None
  if email:
    sub = appstore_review_subscriptions.create_email_subscription(request.user, email)
  elif my_email:
    sub = appstore_review_subscriptions.create_my_email_subscription(request.user)
  elif slack_channel_name:
    sub = appstore_review_subscriptions.create_slack_channel_subscription(request.user, slack_channel_name)
  elif slack_url:
    sub = appstore_review_subscriptions.create_slack_subscription(request.user, slack_url)
  elif twitter_app_connection:
    sub = appstore_review_subscriptions.create_twitter_subscription_from_connection(twitter_app_connection)

  if not sub:
    return bad_request('Subscription already exists.')


  new_flags = []
  if not request.user.flags.has_review_monitor:
    new_flags.append('has_review_monitor')
  if sub.twitter_connection_id and not request.user.flags.has_review_monitor_tweets:
    new_flags.append('has_review_monitor_tweets')

  if new_flags:
    request.user.set_flags(new_flags)

  return api_response({
    'subscription': sub.to_dict(),
  })
예제 #43
0
def _configs_view_POST(request):
  form = CreateRuleForm(request.POST)

  if not form.is_valid():
    logging.info('Invalid rules: %s POST: %s', dict(form.errors), dict(request.POST))
    return bad_request(message='Invalid rule parameters.', errors=form.errors)

  key = form.cleaned_data['key']
  del form.cleaned_data['key']

  bundle_id = form.cleaned_data['bundle_id']
  # Create the app row if it doesn't exist so we can populate the "my apps" dropdown.
  app = sdk_apps.decorated_app_by_bundle_id(request.user, bundle_id)
  if not app.config:
    app.config = True
    app.save(update_fields=['products'])

  rules = runtime_config.rules_for_user_key(request.user, key, bundle_id)

  kind = None
  if 'kind' in form.cleaned_data:
    kind = form.cleaned_data['kind']
    del form.cleaned_data['kind']
    if rules and rules[0].kind != kind:
      return bad_request('Key already exists as a different `kind`; cannot change type.')
  elif rules:
    kind = rules[0].kind

  if not kind:
    return bad_request('Please provide a `kind` for this key.')

  value_form = ValueForm(kind, request.POST)
  if not value_form.is_valid():
    return bad_request(message='Invalid rule `value`.', errors=form.errors)

  value = value_form.cleaned_data['value']

  rule = runtime_config.create_rule(request.user, key, kind, value, **form.cleaned_data)

  if not request.user.flags.has_config:
    request.user.set_flags(['has_config'])

  return api_response({
    'rule': rule.to_dict(),
  })
예제 #44
0
파일: itunes.py 프로젝트: yutaza/LaunchKit
def disconnect_itunes_view(request):
    connected_email = itunes_connect.itunes_credentials_email_for_user_id(
        request.user.id)
    if not connected_email:
        return bad_request('No connection to remove.')

    destructive.delete_itunes_connection_and_imports(request.user)

    return ok_response()
예제 #45
0
파일: itunes.py 프로젝트: yutaza/LaunchKit
def subscription_unsubscribe_token_view(request):
    sub = itunes_connect.subscription_from_unsubscribe_token(
        request.POST.get('token', ''))
    if not sub:
        return bad_request('Could not find subscription with that `token`.')

    appstore_sales_report_subscriptions.disable_subscription(sub)

    return ok_response()
예제 #46
0
파일: auth.py 프로젝트: yutaza/LaunchKit
def delete_account_view(request):
    email = request.POST.get('email')
    if email != request.user.email:
        return bad_request(
            'Please provide the current account email address, `email`.')

    destructive.delete_account(request.user)

    return ok_response()
예제 #47
0
def _app_view_POST(request, app):
  form = EditSDKAppForm(request.POST)
  if not form.is_valid():
    return bad_request('Invalid edits provided.', errors=form.errors)

  if form.cleaned_data.get('itunes_country'):
    itunes_id, country = form.cleaned_data.get('itunes_id'), form.cleaned_data.get('itunes_country')
    appstore_app = appstore.get_app_by_itunes_id(itunes_id, country)
    if not appstore_app:
      return bad_request('Invalid `itunes_id` or `itunes_country` provided.')

    if app.appstore_app and app.appstore_app.id != appstore_app.id:
      return bad_request('Cannot change `itunes_id` once it is set.')

    app.itunes_country = country
    app.save(update_fields=['itunes_county'])

  display_name = form.cleaned_data.get('display_name') or None
  if 'display_name' in request.POST:
    # Allow removing this field to default to appstore info / bundle id.
    app.display_name = display_name
    app.save(update_fields=['display_name'])

  super_freq, super_time = form.cleaned_data.get('super_freq'), form.cleaned_data.get('super_time')
  if super_freq:
    session_user_labels.set_super_config(app, super_freq, super_time)

    # TODO(Taylor): Figure out a better place to set this.
    if not request.user.flags.has_super_users:
      request.user.set_flags(['has_super_users'])

  if 'config_parent_id' in request.POST:
    # can also be None if removing parent.
    app.config_parent = form.cleaned_data.get('config_parent_id')
    app.save(update_fields=['config_parent'])

  for sdk_product in SDKProduct.kinds():
    if sdk_product in request.POST:
      setattr(app, sdk_product, form.cleaned_data[sdk_product])
      app.save(update_fields=['products'])

  return api_response({
    'app': app.to_dict(),
  })
예제 #48
0
def _apps_view_POST(request):
    form = CreateSDKAppForm(request.POST)
    if not form.is_valid():
        return bad_request('Invalid create app parameters.',
                           errors=form.errors)

    bundle_id = form.cleaned_data.get('bundle_id')
    if bundle_id:
        app = sdk_apps.create_or_fetch_sdk_app_with_bundle_id(
            request.user, bundle_id)
        if app.appstore_app:
            # Edge case: Creating app store app again later, from bundle ID
            appstore_app_info.decorate_app(app.appstore_app,
                                           app.appstore_app_country)

    else:
        itunes_id, country = form.cleaned_data.get(
            'itunes_id'), form.cleaned_data.get('itunes_country')
        appstore_app = appstore.get_app_by_itunes_id(itunes_id, country)
        if not appstore_app:
            return bad_request(
                'Invalid `itunes_id` or `itunes_country` provided.')
        app = sdk_apps.create_or_decorate_sdk_app_with_appstore_app(
            request.user, appstore_app)

    display_name = form.cleaned_data.get('display_name')
    if display_name:
        app.display_name = display_name
        app.save(update_fields=['display_name'])

    config_parent_app = form.cleaned_data.get('config_parent_id')
    if config_parent_app:
        app.config_parent = config_parent_app
        app.save(update_fields=['config_parent'])

    for sdk_product in SDKProduct.kinds():
        if sdk_product in request.POST:
            setattr(app, sdk_product, form.cleaned_data[sdk_product])
            app.save(update_fields=['products'])

    return api_response({
        'app': app.to_dict(),
    })
예제 #49
0
def screenshot_set_download_bundle_view(request, set_id=None):
  set_id = ScreenshotSet.decrypt_id(set_id)
  if not set_id:
    return not_found()

  bundle_id = request.GET.get('bundle_id')
  bundle = ScreenshotBundle.find_by_encrypted_id(bundle_id, screenshot_set_id=set_id)
  if not bundle:
    return bad_request('Could not find that bundle.')

  # Enable logged-out user access by token.
  if not (request.user.is_authenticated() and request.user.id == bundle.user_id):
    token = request.GET.get('token')
    user = users.get_user_by_email_token(token)
    if (not user) or user.id != bundle.user_id:
      return bad_request('Invalid token for this bundle.')

  return api_response({
    'downloadUrl': screenshot_bundler.build_download_url(bundle),
  })
예제 #50
0
def _apps_view_GET(request):
  form = ListAppsForm(request.GET)
  if not form.is_valid():
    return bad_request('Invalid list parameters.', errors=form.errors)

  cleaned_data = {k: v for k, v in form.cleaned_data.items() if k in request.GET}
  apps = sdk_apps.my_decorated_apps(request.user, **cleaned_data)

  return api_response({
    'apps': [a.to_dict() for a in apps],
  })
예제 #51
0
def tweet_review(request):
  twitter_handle = request.POST['twitter_handle']
  review_id = request.POST['review_id']
  review = AppStoreReview.find_by_encrypted_id(review_id)
  tweet_text = request.POST['tweet_text']

  if twitter_handle and review and tweet_text:
    success = twitter.tweet_review(request.user, twitter_handle, review, tweet_text)
    if success:
      return ok_response()

  return bad_request()
예제 #52
0
파일: twitter.py 프로젝트: yutaza/LaunchKit
def tweet_review(request):
    twitter_handle = request.POST['twitter_handle']
    review_id = request.POST['review_id']
    review = AppStoreReview.find_by_encrypted_id(review_id)
    tweet_text = request.POST['tweet_text']

    if twitter_handle and review and tweet_text:
        success = twitter.tweet_review(request.user, twitter_handle, review,
                                       tweet_text)
        if success:
            return ok_response()

    return bad_request()
예제 #53
0
def _apps_view_POST(request):
    itunes_id = request.POST.get('itunes_id')

    country = request.POST.get('country')
    if not country or country not in appstore.APPSTORE_COUNTRIES_BY_CODE:
        return bad_request('Provide a valid `country`')

    if request.POST.get('include_related') == '1':
        apps = appstore.get_app_and_related_by_itunes_id(itunes_id, country)
        if not apps:
            return bad_request('Invalid `itunes_id` provided.')

    else:
        app = appstore.get_app_by_itunes_id(itunes_id, country)
        if not app:
            return bad_request('Invalid `itunes_id` provided.')

        apps = [app]

    appstore.mark_interested_in_apps(request.user, apps, country)

    return api_response({'apps': [a.to_dict() for a in apps]})