示例#1
0
def route_create():
    """ Add a vendor [ADMIN ONLY] """

    # only accept form data
    if request.method != 'POST':
        return redirect(url_for('vendors.route_list_admin'))

    if not 'group_id' in request.form:
        return _error_internal('Unable to add vendor as no data')
    if db.session.query(Vendor).filter(Vendor.group_id == request.form['group_id']).first():
        flash('Failed to add vendor: Group ID already exists', 'warning')
        return redirect(url_for('vendors.route_list_admin'), 302)
    if len(request.form['group_id']) > 80:
        flash('Failed to add vendor: Group ID is too long', 'warning')
        return redirect(url_for('vendors.route_list_admin'), 302)
    r = Remote(name='embargo-%s' % request.form['group_id'])
    db.session.add(r)
    db.session.commit()
    v = Vendor(group_id=request.form['group_id'], remote_id=r.remote_id)
    db.session.add(v)
    db.session.commit()
    flash('Added vendor %s' % request.form['group_id'], 'info')

    # asynchronously rebuilt
    _async_regenerate_remote.apply_async(args=(r.remote_id,), queue='metadata')

    return redirect(url_for('vendors.route_show', vendor_id=v.vendor_id), 302)
示例#2
0
def _demote_back_to_testing(fw):

    # from the server admin
    user = db.session.query(User).filter(User.username == '*****@*****.**').first()
    if not user:
        return

    # send email to uploading user
    if fw.user.get_action('notify-demote-failures'):
        send_email("[LVFS] Firmware has been demoted",
                   fw.user.email_address,
                   render_template('email-firmware-demote.txt',
                                   user=fw.user, fw=fw))

    fw.mark_dirty()
    remote = db.session.query(Remote).filter(Remote.name == 'testing').first()
    remote.is_dirty = True

    # asynchronously sign straight away, even public remotes
    for r in set([remote, fw.remote]):
        r.is_dirty = True
        _async_regenerate_remote.apply_async(args=(r.remote_id,), queue='metadata', countdown=1)

    fw.remote_id = remote.remote_id
    fw.events.append(FirmwareEvent(remote_id=fw.remote_id, user_id=user.user_id))
    db.session.commit()
    _event_log('Demoted firmware {} as reported success {}%'.format(fw.firmware_id, fw.success))
示例#3
0
def route_limit_delete(firmware_limit_id):

    # get details about the firmware
    fl = db.session.query(FirmwareLimit).\
            filter(FirmwareLimit.firmware_limit_id == firmware_limit_id).first()
    if not fl:
        flash('No firmware limit matched!', 'danger')
        return redirect(url_for('firmware.route_firmware'))

    # security check
    if not fl.fw.check_acl('delete-limit'):
        flash('Permission denied: Insufficient permissions to delete limits',
              'danger')
        return redirect(url_for('firmware.route_firmware'))

    firmware_id = fl.firmware_id
    fl.fw.mark_dirty()
    db.session.delete(fl)
    db.session.commit()
    flash('Deleted limit', 'info')

    # asynchronously sign
    _async_regenerate_remote.apply_async(args=(fl.fw.remote.remote_id, ),
                                         queue='metadata')

    return redirect(url_for('firmware.route_limits', firmware_id=firmware_id))
示例#4
0
def route_limit_create():

    # get details about the firmware
    fw = db.session.query(Firmware).\
            filter(Firmware.firmware_id == request.form['firmware_id']).first()
    if not fw:
        flash('No firmware matched!', 'danger')
        return redirect(url_for('firmware.route_firmware'))

    # security check
    if not fw.check_acl('@modify-limit'):
        flash('Permission denied: Unable to add restriction', 'danger')
        return redirect(url_for('firmware.route_show', firmware_id=fw.firmware_id))

    # ensure has enough data
    for key in ['value', 'firmware_id']:
        if key not in request.form:
            return _error_internal('No %s form data found!', key)

    # add restriction
    fl = FirmwareLimit(firmware_id=request.form['firmware_id'],
                       value=request.form['value'],
                       user_agent_glob=request.form['user_agent_glob'],
                       response=request.form['response'])
    db.session.add(fl)
    db.session.commit()
    fl.fw.mark_dirty()
    db.session.commit()
    flash('Added limit', 'info')

    # asynchronously sign
    _async_regenerate_remote.apply_async(args=(fl.fw.remote.remote_id,), queue='metadata')

    return redirect(url_for('firmware.route_limits', firmware_id=fl.firmware_id))
示例#5
0
def route_retoken(vendor_id):
    """ Removes a vendor [ADMIN ONLY] """
    vendor = db.session.query(Vendor).filter(
        Vendor.vendor_id == vendor_id).first()
    if not vendor:
        flash('Failed to delete vendor: No a vendor with that group ID',
              'warning')
        return redirect(url_for('vendors.route_list_admin'), 302)

    # delete files with the old access token
    fns = glob(
        os.path.join(app.config['DOWNLOAD_DIR'],
                     'firmware-*-{}.*'.format(vendor.remote.access_token)))
    for fn in fns:
        os.remove(fn)

    # a random string
    vendor.remote.access_token = secrets.token_hex(nbytes=32)
    vendor.remote.is_dirty = True
    db.session.commit()

    # asynchronously rebuilt
    _async_regenerate_remote.apply_async(args=(vendor.remote.remote_id, ),
                                         queue='metadata')

    flash('Regenerated vendor access token', 'info')
    return redirect(url_for('vendors.route_list_admin'), 302)
示例#6
0
def route_affiliation_change(firmware_id):
    """ Changes the assigned vendor ID for the firmware """

    # change the vendor
    if 'vendor_id' not in request.form:
        return _error_internal('No vendor ID specified')

    # find firmware
    fw = db.session.query(Firmware).filter(
        Firmware.firmware_id == firmware_id).first()
    if not fw:
        flash('No firmware matched!', 'danger')
        return redirect(url_for('firmware.route_firmware'))

    # security check
    if not fw.check_acl('@modify-affiliation'):
        flash(
            'Permission denied: Insufficient permissions to change affiliation',
            'danger')
        return redirect(url_for('firmware.route_show',
                                firmware_id=firmware_id))

    vendor_id = int(request.form['vendor_id'])
    if vendor_id == fw.vendor_id:
        flash('No affiliation change required', 'info')
        return redirect(
            url_for('firmware.route_affiliation', firmware_id=fw.firmware_id))
    if not g.user.check_acl('@admin') and \
        not g.user.vendor.is_affiliate_for(vendor_id) and \
        vendor_id != g.user.vendor_id:
        flash(
            'Insufficient permissions to change affiliation to {}'.format(
                vendor_id), 'danger')
        return redirect(url_for('firmware.route_show',
                                firmware_id=firmware_id))
    old_vendor = fw.vendor
    fw.vendor_id = vendor_id
    db.session.commit()

    # do we need to regenerate remotes?
    if fw.remote.name.startswith('embargo'):
        fw.vendor.remote.is_dirty = True
        fw.user.vendor.remote.is_dirty = True
        old_vendor.remote.is_dirty = True
        fw.remote_id = fw.vendor.remote.remote_id
        fw.events.append(
            FirmwareEvent(remote_id=fw.remote_id, user_id=g.user.user_id))
        fw.mark_dirty()
        db.session.commit()

    flash('Changed firmware vendor', 'info')

    # asynchronously sign
    _async_regenerate_remote.apply_async(args=(fw.remote.remote_id, ),
                                         queue='metadata')

    return redirect(url_for('firmware.route_show', firmware_id=fw.firmware_id))
示例#7
0
def route_restriction_create(vendor_id):
    """ Allows changing a vendor [ADMIN ONLY] """

    # check exists
    vendor = db.session.query(Vendor).filter(Vendor.vendor_id == vendor_id).first()
    if not vendor:
        flash('Failed to get vendor details: No a vendor with that group ID', 'warning')
        return redirect(url_for('vendors.route_list_admin'), 302)
    if not 'value' in request.form:
        return _error_internal('No value')
    vendor.restrictions.append(Restriction(value=request.form['value']))
    db.session.commit()
    flash('Added restriction', 'info')

    # asynchronously rebuilt
    _async_regenerate_remote.apply_async(args=(vendor.remote.remote_id,), queue='metadata')

    return redirect(url_for('vendors.route_restrictions', vendor_id=vendor_id), 302)
示例#8
0
def route_restriction_delete(vendor_id, restriction_id):
    """ Allows changing a vendor [ADMIN ONLY] """

    # check exists
    vendor = db.session.query(Vendor).filter(Vendor.vendor_id == vendor_id).first()
    if not vendor:
        flash('Failed to get vendor details: No a vendor with that group ID', 'warning')
        return redirect(url_for('vendors.route_list_admin'), 302)
    for res in vendor.restrictions:
        if res.restriction_id == restriction_id:
            db.session.delete(res)
            db.session.commit()
            break
    flash('Deleted restriction', 'info')

    # asynchronously rebuilt
    _async_regenerate_remote.apply_async(args=(vendor.remote.remote_id,), queue='metadata')

    return redirect(url_for('vendors.route_restrictions', vendor_id=vendor_id), 302)
示例#9
0
def route_create():
    """ Add a vendor [ADMIN ONLY] """

    # only accept form data
    if request.method != 'POST':
        return redirect(url_for('vendors.route_list_admin'))

    if not 'group_id' in request.form:
        return _error_internal('Unable to add vendor as no data')
    if db.session.query(Vendor).filter(
            Vendor.group_id == request.form['group_id']).first():
        flash('Failed to add vendor: Group ID already exists', 'warning')
        return redirect(url_for('vendors.route_list_admin'), 302)
    if len(request.form['group_id']) > 80:
        flash('Failed to add vendor: Group ID is too long', 'warning')
        return redirect(url_for('vendors.route_list_admin'), 302)

    # use a random access token, unless running in debug mode
    if app.config.get('DEBUG', None):
        access_token = request.form['group_id'].replace('-', '_')
    else:
        access_token = secrets.token_hex(nbytes=32)

    r = Remote(name='embargo-%s' % request.form['group_id'],
               access_token=access_token,
               is_dirty=True)
    db.session.add(r)
    db.session.commit()
    v = Vendor(group_id=request.form['group_id'], remote_id=r.remote_id)
    db.session.add(v)
    db.session.commit()
    flash('Added vendor %s' % request.form['group_id'], 'info')

    # asynchronously rebuilt
    _async_regenerate_remote.apply_async(args=(r.remote_id, ),
                                         queue='metadata')

    return redirect(url_for('vendors.route_show', vendor_id=v.vendor_id), 302)
示例#10
0
def _firmware_delete(fw):

    # find private remote
    remote = db.session.query(Remote).filter(Remote.name == 'deleted').first()
    if not remote:
        _event_log('No deleted remote')
        return

    # move file so it's no longer downloadable
    path = os.path.join(app.config['DOWNLOAD_DIR'], fw.filename)
    if os.path.exists(path):
        path_new = os.path.join(app.config['RESTORE_DIR'], fw.filename)
        shutil.move(path, path_new)

    # generate next cron run
    fw.mark_dirty()

    # asynchronously sign
    _async_regenerate_remote.apply_async(args=(fw.remote.remote_id,), queue='metadata')

    # mark as invalid
    fw.remote_id = remote.remote_id
    fw.events.append(FirmwareEvent(remote_id=fw.remote_id, user_id=g.user.user_id))
示例#11
0
def route_promote(firmware_id, target):
    """
    Promote or demote a firmware file from one target to another,
    for example from testing to stable, or stable to testing.
     """

    # check valid
    if target not in ['stable', 'testing', 'private', 'embargo']:
        return _error_internal("Target %s invalid" % target)

    # check firmware exists in database
    fw = db.session.query(Firmware).filter(
        Firmware.firmware_id == firmware_id).first()
    if not fw:
        flash('No firmware {} exists'.format(firmware_id), 'danger')
        return redirect(url_for('firmware.route_firmware'))

    # security check
    if not fw.check_acl('@promote-' + target):
        flash('Permission denied: No QA access to {}'.format(firmware_id),
              'danger')
        return redirect(url_for('firmware.route_show',
                                firmware_id=firmware_id))

    # vendor has to fix the problems first
    if target in ['stable', 'testing'] and fw.problems:
        probs = []
        for problem in fw.problems:
            if problem.kind not in probs:
                probs.append(problem.kind)
        flash(
            'Firmware has problems that must be fixed first: %s' %
            ','.join(probs), 'warning')
        return redirect(
            url_for('firmware.route_problems', firmware_id=firmware_id))

    # set new remote
    if target == 'embargo':
        remote = fw.vendor.remote
    else:
        remote = db.session.query(Remote).filter(Remote.name == target).first()
    if not remote:
        return _error_internal('No remote for target %s' % target)

    # same as before
    if fw.remote.remote_id == remote.remote_id:
        flash('Cannot move firmware: Firmware already in that target', 'info')
        return redirect(
            url_for('firmware.route_target', firmware_id=firmware_id))

    # invalidate both the remote it "came from", the one it's "going to" and
    # also the remote of the vendor that uploaded it
    remote.is_dirty = True
    fw.remote.is_dirty = True
    fw.vendor_odm.remote.is_dirty = True

    # invalidate the firmware as we're waiting for the metadata generation
    fw.mark_dirty()
    db.session.commit()

    # asynchronously sign
    for r in set([remote, fw.remote, fw.vendor_odm.remote]):
        r.is_dirty = True
        _async_regenerate_remote.apply_async(args=(r.remote_id, ),
                                             queue='metadata',
                                             countdown=1)

    # some tests only run when the firmware is in stable
    ploader.ensure_test_for_fw(fw)

    # sync everything we added
    db.session.commit()

    # asynchronously run
    _async_test_run_for_firmware.apply_async(args=(fw.firmware_id, ))

    # also dirty any ODM remote if uploading on behalf of an OEM
    if target == 'embargo' and fw.vendor != fw.user.vendor:
        fw.user.vendor.remote.is_dirty = True

    # all okay
    fw.remote_id = remote.remote_id
    fw.events.append(
        FirmwareEvent(remote_id=fw.remote_id, user_id=g.user.user_id))
    db.session.commit()

    # send email
    for u in fw.get_possible_users_to_email:
        if u == g.user:
            continue
        if u.get_action('notify-promote'):
            send_email(
                "[LVFS] Firmware has been promoted", u.email_address,
                render_template('email-firmware-promoted.txt',
                                user=g.user,
                                fw=fw))

    flash('Moved firmware', 'info')

    return redirect(url_for('firmware.route_target', firmware_id=firmware_id))