コード例 #1
0
ファイル: rules.py プロジェクト: mozmark/balrog
    def _delete(self, rule_id, transaction, changed_by):
        # Verify that the rule_id exists.
        rule = dbo.rules.getRuleById(rule_id, transaction=transaction)
        if not rule:
            return Response(status=404)

        # Bodies are ignored for DELETE requests, so we need to force WTForms
        # to look at the arguments instead.
        # Even though we aren't going to use most of the form fields (just
        # rule_id and data_version), we still want to create and validate the
        # form to make sure that the CSRF token is checked.
        form = DbEditableForm(request.args)

        if not dbo.permissions.hasUrlPermission(
                changed_by,
                '/rules/:id',
                'DELETE',
                urlOptions={'product': rule['product']}):
            msg = "%s is not allowed to alter rules that affect %s" % (
                changed_by, rule['product'])
            cef_event('Unauthorized access attempt', CEF_ALERT, msg=msg)
            return Response(status=401, response=msg)

        dbo.rules.deleteRule(changed_by=changed_by,
                             rule_id=rule_id,
                             old_data_version=form.data_version.data,
                             transaction=transaction)

        return Response(status=200)
コード例 #2
0
ファイル: releases.py プロジェクト: mozmark/balrog
    def _delete(self, release, changed_by, transaction):
        releases = dbo.releases.getReleases(name=release)
        if not releases:
            return Response(status=404, response='bad release')
        release = releases[0]
        if not dbo.permissions.hasUrlPermission(
                changed_by,
                '/releases/:name',
                'DELETE',
                urlOptions={'product': release['product']}):
            msg = "%s is not allowed to delete %s releases" % (
                changed_by, release['product'])
            cef_event('Unauthorized access attempt', CEF_ALERT, msg=msg)
            return Response(status=401, response=msg)

        # Bodies are ignored for DELETE requests, so we need to force WTForms
        # to look at the arguments instead.
        # We only need the release name (which comes through the URL) and the
        # data version to process this request. Because of that, we can just
        # use this form to validate, because we're only validating CSRF
        # and data version.
        form = DbEditableForm(request.args)
        if not form.validate():
            cef_event("Bad input", CEF_WARN, errors=form.errors)
            return Response(status=400, response=form.errors)

        dbo.releases.deleteRelease(changed_by=changed_by,
                                   name=release['name'],
                                   old_data_version=form.data_version.data,
                                   transaction=transaction)

        return Response(status=200)
コード例 #3
0
ファイル: releases.py プロジェクト: rwood-moz/balrog
    def _post(self, changed_by, transaction):
        form = CompleteReleaseForm()
        if not form.validate():
            cef_event("Bad input", CEF_WARN, errors=form.errors)
            return Response(status=400, response=json.dumps(form.errors))

        try:
            blob = createBlob(form.blob.data)
            name = dbo.releases.addRelease(
                name=form.name.data, product=form.product.data,
                version=form.version.data, blob=blob,
                changed_by=changed_by, transaction=transaction
            )
        except ValueError as e:
            msg = "Couldn't update release: %s" % e
            cef_event("Bad input", CEF_WARN, errors=msg)
            return Response(status=400, response=msg)

        release = dbo.releases.getReleases(
            name=name, transaction=transaction, limit=1
        )[0]
        new_data_version = release['data_version']
        response = make_response(
            json.dumps(dict(new_data_version=new_data_version)),
            201
        )
        response.headers['Content-Type'] = 'application/json'
        return response
コード例 #4
0
ファイル: base.py プロジェクト: aybuke/balrog
 def decorated(*args, **kwargs):
     try:
         return f(*args, **kwargs)
     except OutdatedDataError as e:
         msg = "Couldn't perform the request %s. Outdated Data Version. old_data_version doesn't match current data_version: %s" % (messages, e)
         cef_event("Bad input", CEF_WARN, errors=msg)
         return Response(status=400, response=json.dumps({"data": e.args}))
コード例 #5
0
ファイル: rules.py プロジェクト: andreja-cliqz/balrog
    def _delete(self, rule_id, transaction, changed_by):
        # Verify that the rule_id exists.
        rule = dbo.rules.getRuleById(rule_id, transaction=transaction)
        if not rule:
            return Response(status=404)

        # Bodies are ignored for DELETE requests, so we need to force WTForms
        # to look at the arguments instead.
        # Even though we aren't going to use most of the form fields (just
        # rule_id and data_version), we still want to create and validate the
        # form to make sure that the CSRF token is checked.
        form = DbEditableForm(request.args)

        if not dbo.permissions.hasUrlPermission(
            changed_by, "/rules/:id", "DELETE", urlOptions={"product": rule["product"]}
        ):
            msg = "%s is not allowed to alter rules that affect %s" % (changed_by, rule["product"])
            cef_event("Unauthorized access attempt", CEF_ALERT, msg=msg)
            return Response(status=401, response=msg)

        dbo.rules.deleteRule(
            changed_by=changed_by, rule_id=rule_id, old_data_version=form.data_version.data, transaction=transaction
        )

        return Response(status=200)
コード例 #6
0
ファイル: rules.py プロジェクト: MikeLing/balrog
    def _post(self, transaction, changed_by):
        # a Post here creates a new rule
        form = RuleForm()
        releaseNames = dbo.releases.getReleaseNames()
        form.mapping.choices = [(item['name'], item['name']) for item in releaseNames]
        form.mapping.choices.insert(0, ('', 'NULL'))

        if not form.validate():
            cef_event("Bad input", CEF_WARN, errors=form.errors)
            return Response(status=400, response=json.dumps(form.errors))

        what = dict(backgroundRate=form.backgroundRate.data,
                    mapping=form.mapping.data,
                    priority=form.priority.data,
                    alias=form.alias.data,
                    product=form.product.data,
                    version=form.version.data,
                    buildID=form.buildID.data,
                    channel=form.channel.data,
                    locale=form.locale.data,
                    distribution=form.distribution.data,
                    buildTarget=form.buildTarget.data,
                    osVersion=form.osVersion.data,
                    distVersion=form.distVersion.data,
                    whitelist=form.whitelist.data,
                    comment=form.comment.data,
                    update_type=form.update_type.data,
                    headerArchitecture=form.headerArchitecture.data)
        rule_id = dbo.rules.addRule(changed_by=changed_by, what=what,
                                    transaction=transaction)
        return Response(status=200, response=str(rule_id))
コード例 #7
0
ファイル: releases.py プロジェクト: mozmark/balrog
    def _delete(self, release, changed_by, transaction):
        releases = dbo.releases.getReleases(name=release)
        if not releases:
            return Response(status=404, response='bad release')
        release = releases[0]
        if not dbo.permissions.hasUrlPermission(changed_by, '/releases/:name', 'DELETE', urlOptions={'product': release['product']}):
            msg = "%s is not allowed to delete %s releases" % (changed_by, release['product'])
            cef_event('Unauthorized access attempt', CEF_ALERT, msg=msg)
            return Response(status=401, response=msg)

        # Bodies are ignored for DELETE requests, so we need to force WTForms
        # to look at the arguments instead.
        # We only need the release name (which comes through the URL) and the
        # data version to process this request. Because of that, we can just
        # use this form to validate, because we're only validating CSRF
        # and data version.
        form = DbEditableForm(request.args)
        if not form.validate():
            cef_event("Bad input", CEF_WARN, errors=form.errors)
            return Response(status=400, response=form.errors)

        dbo.releases.deleteRelease(changed_by=changed_by, name=release['name'],
            old_data_version=form.data_version.data, transaction=transaction)

        return Response(status=200)
コード例 #8
0
ファイル: rules.py プロジェクト: mozmark/balrog
    def _post(self, transaction, changed_by):
        # a Post here creates a new rule
        form = RuleForm()
        releaseNames = dbo.releases.getReleaseNames()
        form.mapping.choices = [(item['name'], item['name'])
                                for item in releaseNames]
        form.mapping.choices.insert(0, ('', 'NULL'))

        if not form.validate():
            cef_event("Bad input", CEF_WARN, errors=form.errors)
            return Response(status=400, response=json.dumps(form.errors))

        what = dict(backgroundRate=form.backgroundRate.data,
                    mapping=form.mapping.data,
                    priority=form.priority.data,
                    product=form.product.data,
                    version=form.version.data,
                    buildID=form.buildID.data,
                    channel=form.channel.data,
                    locale=form.locale.data,
                    distribution=form.distribution.data,
                    buildTarget=form.buildTarget.data,
                    osVersion=form.osVersion.data,
                    distVersion=form.distVersion.data,
                    comment=form.comment.data,
                    update_type=form.update_type.data,
                    headerArchitecture=form.headerArchitecture.data)
        rule_id = dbo.rules.addRule(changed_by=changed_by,
                                    what=what,
                                    transaction=transaction)
        return Response(status=200, response=str(rule_id))
コード例 #9
0
ファイル: rules.py プロジェクト: aybuke/balrog
    def _post(self, id_or_alias, transaction, changed_by):
        # Verify that the rule_id or alias exists.
        rule = dbo.rules.getRule(id_or_alias, transaction=transaction)
        if not rule:
            return Response(status=404)
        form = EditRuleForm()

        # Verify that the user has permission for the existing rule _and_ what the rule would become.
        toCheck = [rule['product']]
        # Rules can be partially updated - if product is null/None, we won't update that field, so
        # we shouldn't check its permission.
        if form.product.data:
            toCheck.append(form.product.data)
        for product in toCheck:
            if not dbo.permissions.hasUrlPermission(changed_by, '/rules/:id', 'POST', urlOptions={'product': product}):
                msg = "%s is not allowed to alter rules that affect %s" % (changed_by, product)
                cef_event('Unauthorized access attempt', CEF_ALERT, msg=msg)
                return Response(status=401, response=msg)
        releaseNames = dbo.releases.getReleaseNames()

        form.mapping.choices = [(item['name'], item['name']) for item in releaseNames]
        form.mapping.choices.insert(0, ('', 'NULL'))

        if not form.validate():
            cef_event("Bad input", CEF_WARN, errors=form.errors)
            return Response(status=400, response=json.dumps(form.errors))

        what = dict()
        # We need to be able to support changing AND removing parts of a rule,
        # and because of how Flask's request object and WTForm's defaults work
        # this gets a little hary.
        for k, v in form.data.iteritems():
            # data_version is a "special" column, in that it's not part of the
            # primary data, and shouldn't be updatable by the user.
            if k == "data_version":
                continue
            # We need to check for each column in both the JSON style post
            # and the regular multipart form data. If the key is not present in
            # either of these data structures. We treat this cases as no-op
            # and shouldn't modify the data for that key.
            # If the key is present we should modify the data as requested.
            # If a value is an empty string, we should remove that restriction
            # from the rule (aka, set as NULL in the db). The underlying Form
            # will have already converted it to None, so we can treat it the
            # same as a modification here.
            if (request.json and k in request.json) or k in request.form:
                what[k] = v

        dbo.rules.updateRule(changed_by=changed_by, id_or_alias=id_or_alias, what=what,
                             old_data_version=form.data_version.data, transaction=transaction)

        # find out what the next data version is
        rule = dbo.rules.getRule(id_or_alias, transaction=transaction)
        new_data_version = rule['data_version']
        response = make_response(json.dumps(dict(new_data_version=new_data_version)))
        response.headers['Content-Type'] = 'application/json'
        return response
コード例 #10
0
ファイル: base.py プロジェクト: aybuke/balrog
 def decorated(*args, **kwargs):
     try:
         return f(*args, **kwargs)
     except OutdatedDataError as e:
         msg = "Couldn't perform the request %s. Outdated Data Version. old_data_version doesn't match current data_version: %s" % (
             messages, e)
         cef_event("Bad input", CEF_WARN, errors=msg)
         return Response(status=400,
                         response=json.dumps({"data": e.args}))
コード例 #11
0
ファイル: rules.py プロジェクト: aybuke/balrog
    def _post(self, rule_id, transaction, changed_by):
        change_id = None
        if request.json:
            change_id = request.json.get('change_id')
        if not change_id:
            cef_event("Bad input", CEF_WARN, errors="no change_id")
            return Response(status=400, response='no change_id')
        change = dbo.rules.history.getChange(change_id=change_id)
        if change is None:
            return Response(status=404, response='bad change_id')
        if change['rule_id'] != rule_id:
            return Response(status=404, response='bad rule_id')
        rule = dbo.rules.getRule(rule_id)
        if rule is None:
            return Response(status=404, response='bad rule_id')
        # Verify that the user has permission for the existing rule _and_ what the rule would become.
        for product in (rule['product'], change['product']):
            if not dbo.permissions.hasUrlPermission(
                    changed_by,
                    '/rules/:id',
                    'POST',
                    urlOptions={'product': product}):
                msg = "%s is not allowed to alter rules that affect %s" % (
                    changed_by, product)
                cef_event('Unauthorized access attempt', CEF_ALERT, msg=msg)
                return Response(status=401, response=msg)
        old_data_version = rule['data_version']

        # now we're going to make a new insert based on this
        what = dict(
            backgroundRate=change['backgroundRate'],
            mapping=change['mapping'],
            priority=change['priority'],
            alias=change['alias'],
            product=change['product'],
            version=change['version'],
            buildID=change['buildID'],
            channel=change['channel'],
            locale=change['locale'],
            distribution=change['distribution'],
            buildTarget=change['buildTarget'],
            osVersion=change['osVersion'],
            distVersion=change['distVersion'],
            whitelist=change['whitelist'],
            comment=change['comment'],
            update_type=change['update_type'],
            headerArchitecture=change['headerArchitecture'],
        )

        dbo.rules.updateRule(changed_by=changed_by,
                             id_or_alias=rule_id,
                             what=what,
                             old_data_version=old_data_version,
                             transaction=transaction)

        return Response("Excellent!")
コード例 #12
0
ファイル: history.py プロジェクト: escapewindow/balrog
 def get(self, type_, change_id, field):
     try:
         value = self.get_value(type_, change_id, field)
     except KeyError as msg:
         cef_event("Bad input", CEF_WARN, errors=str(msg), field=field)
         return Response(status=400, response=str(msg))
     except ValueError as msg:
         return Response(status=404, response=str(msg))
     value = self.format_value(value)
     return Response(value, content_type='text/plain')
コード例 #13
0
 def get(self, type_, change_id, field):
     try:
         value = self.get_value(type_, change_id, field)
     except KeyError as msg:
         cef_event("Bad input", CEF_WARN, errors=str(msg), field=field)
         return Response(status=400, response=str(msg))
     except ValueError as msg:
         return Response(status=404, response=str(msg))
     value = self.format_value(value)
     return Response(value, content_type='text/plain')
コード例 #14
0
 def _post(self, username, permission, changed_by, transaction):
     if not dbo.permissions.getUserPermissions(username, transaction=transaction).get(permission):
         return Response(status=404)
     try:
         form = ExistingPermissionForm()
         dbo.permissions.updatePermission(changed_by, username, permission, form.data_version.data, form.options.data, transaction=transaction)
         new_data_version = dbo.permissions.getPermission(username=username, permission=permission, transaction=transaction)['data_version']
         return make_response(json.dumps(dict(new_data_version=new_data_version)), 200)
     except ValueError, e:
         cef_event("Bad input", CEF_WARN, errors=e.args)
         return Response(status=400, response=e.args)
コード例 #15
0
ファイル: permissions.py プロジェクト: MDTsai/balrog
 def _post(self, username, permission, changed_by, transaction):
     if not dbo.permissions.getUserPermissions(username, transaction=transaction).get(permission):
         return Response(status=404)
     try:
         form = ExistingPermissionForm()
         dbo.permissions.updatePermission(changed_by, username, permission, form.data_version.data, form.options.data, transaction=transaction)
         new_data_version = dbo.permissions.getPermission(username=username, permission=permission, transaction=transaction)['data_version']
         return make_response(json.dumps(dict(new_data_version=new_data_version)), 200)
     except ValueError, e:
         cef_event("Bad input", CEF_WARN, errors=e.args)
         return Response(status=400, response=e.args)
コード例 #16
0
 def _delete(self, username, permission, changed_by, transaction):
     if not dbo.permissions.getUserPermissions(username, transaction=transaction).get(permission):
         return Response(status=404)
     try:
         # For practical purposes, DELETE can't have a request body, which means the Form
         # won't find data where it's expecting it. Instead, we have to tell it to look at
         # the query string, which Flask puts in request.args.
         form = ExistingPermissionForm(request.args)
         dbo.permissions.revokePermission(changed_by, username, permission, form.data_version.data, transaction=transaction)
         return Response(status=200)
     except ValueError, e:
         cef_event("Bad input", CEF_WARN, errors=e.args)
         return Response(status=400, response=e.args)
コード例 #17
0
ファイル: permissions.py プロジェクト: MDTsai/balrog
 def _delete(self, username, permission, changed_by, transaction):
     if not dbo.permissions.getUserPermissions(username, transaction=transaction).get(permission):
         return Response(status=404)
     try:
         # For practical purposes, DELETE can't have a request body, which means the Form
         # won't find data where it's expecting it. Instead, we have to tell it to look at
         # the query string, which Flask puts in request.args.
         form = ExistingPermissionForm(request.args)
         dbo.permissions.revokePermission(changed_by, username, permission, form.data_version.data, transaction=transaction)
         return Response(status=200)
     except ValueError, e:
         cef_event("Bad input", CEF_WARN, errors=e.args)
         return Response(status=400, response=e.args)
コード例 #18
0
ファイル: rules.py プロジェクト: andreja-cliqz/balrog
    def _post(self, rule_id, transaction, changed_by):
        rule_id = int(rule_id)

        change_id = request.form.get("change_id")
        if not change_id:
            cef_event("Bad input", CEF_WARN, errors="no change_id")
            return Response(status=400, response="no change_id")
        change = dbo.rules.history.getChange(change_id=change_id)
        if change is None:
            return Response(status=404, response="bad change_id")
        if change["rule_id"] != rule_id:
            return Response(status=404, response="bad rule_id")
        rule = dbo.rules.getRuleById(rule_id=rule_id)
        if rule is None:
            return Response(status=404, response="bad rule_id")
        # Verify that the user has permission for the existing rule _and_ what the rule would become.
        for product in (rule["product"], change["product"]):
            if not dbo.permissions.hasUrlPermission(changed_by, "/rules/:id", "POST", urlOptions={"product": product}):
                msg = "%s is not allowed to alter rules that affect %s" % (changed_by, product)
                cef_event("Unauthorized access attempt", CEF_ALERT, msg=msg)
                return Response(status=401, response=msg)
        old_data_version = rule["data_version"]

        # now we're going to make a new insert based on this
        what = dict(
            backgroundRate=change["backgroundRate"],
            mapping=change["mapping"],
            priority=change["priority"],
            product=change["product"],
            version=change["version"],
            buildID=change["buildID"],
            channel=change["channel"],
            locale=change["locale"],
            distribution=change["distribution"],
            buildTarget=change["buildTarget"],
            osVersion=change["osVersion"],
            distVersion=change["distVersion"],
            comment=change["comment"],
            update_type=change["update_type"],
            headerArchitecture=change["headerArchitecture"],
        )

        dbo.rules.updateRule(
            changed_by=changed_by,
            rule_id=rule_id,
            what=what,
            old_data_version=old_data_version,
            transaction=transaction,
        )

        return Response("Excellent!")
コード例 #19
0
ファイル: rules.py プロジェクト: andreja-cliqz/balrog
    def get(self, rule_id):
        rule = dbo.rules.getRuleById(rule_id=rule_id)
        if not rule:
            return Response(status=404, response="Requested rule does not exist")

        table = dbo.rules.history

        try:
            page = int(request.args.get("page", 1))
            limit = int(request.args.get("limit", 100))
            assert page >= 1
        except (ValueError, AssertionError), msg:
            cef_event("Bad input", CEF_WARN, errors=msg)
            return Response(status=400, response=str(msg))
コード例 #20
0
ファイル: rules.py プロジェクト: mozmark/balrog
    def get(self, rule_id):
        rule = dbo.rules.getRuleById(rule_id=rule_id)
        if not rule:
            return Response(status=404,
                            response='Requested rule does not exist')

        table = dbo.rules.history

        try:
            page = int(request.args.get('page', 1))
            limit = int(request.args.get('limit', 100))
            assert page >= 1
        except (ValueError, AssertionError), msg:
            cef_event("Bad input", CEF_WARN, errors=msg)
            return Response(status=400, response=str(msg))
コード例 #21
0
ファイル: releases.py プロジェクト: mozmark/balrog
    def get(self, release):
        releases = dbo.releases.getReleases(name=release, limit=1)
        if not releases:
            return Response(status=404,
                            response='Requested release does not exist')
        release = releases[0]
        table = dbo.releases.history

        try:
            page = int(request.args.get('page', 1))
            limit = int(request.args.get('limit', 10))
            assert page >= 1
        except (ValueError, AssertionError), msg:
            cef_event("Bad input", CEF_WARN, errors=msg)
            return Response(status=400, response=str(msg))
コード例 #22
0
ファイル: releases.py プロジェクト: mozmark/balrog
    def _put(self, release, changed_by, transaction):
        form = NewReleaseForm()
        if not form.validate():
            cef_event("Bad input", CEF_WARN, errors=form.errors)
            return Response(status=400, response=form.errors)

        try:
            blob = createBlob(form.blob.data)
            dbo.releases.addRelease(name=release, product=form.product.data,
                version=form.version.data, blob=blob,
                changed_by=changed_by, transaction=transaction)
        except ValueError, e:
            msg = "Couldn't update release: %s" % e
            cef_event("Bad input", CEF_WARN, errors=msg)
            return Response(status=400, response=msg)
コード例 #23
0
ファイル: releases.py プロジェクト: mozmark/balrog
    def get(self, release):
        releases = dbo.releases.getReleases(name=release, limit=1)
        if not releases:
            return Response(status=404,
                            response='Requested release does not exist')
        release = releases[0]
        table = dbo.releases.history

        try:
            page = int(request.args.get('page', 1))
            limit = int(request.args.get('limit', 10))
            assert page >= 1
        except (ValueError, AssertionError), msg:
            cef_event("Bad input", CEF_WARN, errors=msg)
            return Response(status=400, response=str(msg))
コード例 #24
0
ファイル: rules.py プロジェクト: MikeLing/balrog
    def _post(self, rule_id, transaction, changed_by):
        change_id = None
        if request.json:
            change_id = request.json.get('change_id')
        if not change_id:
            cef_event("Bad input", CEF_WARN, errors="no change_id")
            return Response(status=400, response='no change_id')
        change = dbo.rules.history.getChange(change_id=change_id)
        if change is None:
            return Response(status=404, response='bad change_id')
        if change['rule_id'] != rule_id:
            return Response(status=404, response='bad rule_id')
        rule = dbo.rules.getRule(rule_id)
        if rule is None:
            return Response(status=404, response='bad rule_id')
        # Verify that the user has permission for the existing rule _and_ what the rule would become.
        for product in (rule['product'], change['product']):
            if not dbo.permissions.hasUrlPermission(changed_by, '/rules/:id', 'POST', urlOptions={'product': product}):
                msg = "%s is not allowed to alter rules that affect %s" % (changed_by, product)
                cef_event('Unauthorized access attempt', CEF_ALERT, msg=msg)
                return Response(status=401, response=msg)
        old_data_version = rule['data_version']

        # now we're going to make a new insert based on this
        what = dict(
            backgroundRate=change['backgroundRate'],
            mapping=change['mapping'],
            priority=change['priority'],
            alias=change['alias'],
            product=change['product'],
            version=change['version'],
            buildID=change['buildID'],
            channel=change['channel'],
            locale=change['locale'],
            distribution=change['distribution'],
            buildTarget=change['buildTarget'],
            osVersion=change['osVersion'],
            distVersion=change['distVersion'],
            whitelist=change['whitelist'],
            comment=change['comment'],
            update_type=change['update_type'],
            headerArchitecture=change['headerArchitecture'],
        )

        dbo.rules.updateRule(changed_by=changed_by, id_or_alias=rule_id, what=what,
                             old_data_version=old_data_version, transaction=transaction)

        return Response("Excellent!")
コード例 #25
0
 def _put(self, username, permission, changed_by, transaction):
     try:
         if dbo.permissions.getUserPermissions(username, transaction).get(permission):
             form = ExistingPermissionForm()
             if not form.data_version.data:
                 raise ValueError("Must provide the data version when updating an existing permission.")
             dbo.permissions.updatePermission(changed_by, username, permission, form.data_version.data, form.options.data, transaction=transaction)
             new_data_version = dbo.permissions.getPermission(username=username, permission=permission, transaction=transaction)['data_version']
             return make_response(json.dumps(dict(new_data_version=new_data_version)), 200)
         else:
             form = NewPermissionForm()
             dbo.permissions.grantPermission(changed_by, username, permission, form.options.data, transaction=transaction)
             return make_response(json.dumps(dict(new_data_version=1)), 201)
     except ValueError, e:
         cef_event("Bad input", CEF_WARN, errors=e.args)
         return Response(status=400, response=e.args)
コード例 #26
0
ファイル: permissions.py プロジェクト: MDTsai/balrog
 def _put(self, username, permission, changed_by, transaction):
     try:
         if dbo.permissions.getUserPermissions(username, transaction).get(permission):
             form = ExistingPermissionForm()
             if not form.data_version.data:
                 raise ValueError("Must provide the data version when updating an existing permission.")
             dbo.permissions.updatePermission(changed_by, username, permission, form.data_version.data, form.options.data, transaction=transaction)
             new_data_version = dbo.permissions.getPermission(username=username, permission=permission, transaction=transaction)['data_version']
             return make_response(json.dumps(dict(new_data_version=new_data_version)), 200)
         else:
             form = NewPermissionForm()
             dbo.permissions.grantPermission(changed_by, username, permission, form.options.data, transaction=transaction)
             return make_response(json.dumps(dict(new_data_version=1)), 201)
     except ValueError, e:
         cef_event("Bad input", CEF_WARN, errors=e.args)
         return Response(status=400, response=e.args)
コード例 #27
0
ファイル: releases.py プロジェクト: aybuke/balrog
    def _put(self, release, changed_by, transaction):
        form = CompleteReleaseForm()
        if not form.validate():
            cef_event("Bad input", CEF_WARN, errors=form.errors)
            return Response(status=400, response=json.dumps(form.errors))

        blob = createBlob(form.blob.data)
        if dbo.releases.getReleases(name=release, limit=1):
            data_version = form.data_version.data
            try:
                dbo.releases.updateRelease(name=release,
                                           blob=blob,
                                           product=form.product.data,
                                           changed_by=changed_by,
                                           old_data_version=data_version,
                                           transaction=transaction)
            except BlobValidationError as e:
                msg = "Couldn't update release: %s" % e
                cef_event("Bad input", CEF_WARN, errors=msg)
                return Response(status=400,
                                response=json.dumps({"data": e.errors}))
            except ValueError as e:
                msg = "Couldn't update release: %s" % e
                cef_event("Bad input", CEF_WARN, errors=msg)
                return Response(status=400,
                                response=json.dumps({"data": e.args}))
            data_version += 1
            return Response(json.dumps(dict(new_data_version=data_version)),
                            status=200)
        else:
            try:
                dbo.releases.addRelease(name=release,
                                        product=form.product.data,
                                        blob=blob,
                                        changed_by=changed_by,
                                        transaction=transaction)
            except BlobValidationError as e:
                msg = "Couldn't update release: %s" % e
                cef_event("Bad input", CEF_WARN, errors=msg)
                return Response(status=400,
                                response=json.dumps({"data": e.errors}))
            except ValueError as e:
                msg = "Couldn't update release: %s" % e
                cef_event("Bad input", CEF_WARN, errors=msg)
                return Response(status=400,
                                response=json.dumps({"data": e.args}))
            return Response(status=201)
コード例 #28
0
ファイル: releases.py プロジェクト: andreja-cliqz/balrog
    def _post(self, changed_by, transaction):
        form = CompleteReleaseForm()
        if not form.validate():
            cef_event("Bad input", CEF_WARN, errors=form.errors)
            return Response(status=400, response=json.dumps(form.errors))

        try:
            blob = createBlob(form.blob.data)
            name = dbo.releases.addRelease(
                name=form.name.data, product=form.product.data,
                version=form.version.data, blob=blob,
                changed_by=changed_by, transaction=transaction
            )
        except ValueError, e:
            msg = "Couldn't update release: %s" % e
            cef_event("Bad input", CEF_WARN, errors=msg)
            return Response(status=400, response=msg)
コード例 #29
0
ファイル: base.py プロジェクト: MDTsai/balrog
 def decorated(*args, **kwargs):
     username = request.environ.get('REMOTE_USER')
     method = request.method
     extra = dict()
     for opt in options:
         if opt in request.form:
             extra[opt] = request.form[opt]
         elif request.get_json() and opt in request.json:
             extra[opt] = request.json[opt]
         else:
             msg = "Couldn't find required option %s in form" % opt
             cef_event("Bad input", CEF_WARN, msg=msg)
             return Response(status=400, response=msg)
     if not dbo.permissions.hasUrlPermission(username, url, method, urlOptions=extra):
         msg = "%s is not allowed to access %s by %s" % (username, url, method)
         cef_event('Unauthorized access attempt', CEF_ALERT, msg=msg)
         return Response(status=401, response=msg)
     return f(*args, **kwargs)
コード例 #30
0
ファイル: releases.py プロジェクト: andreja-cliqz/balrog
    def _put(self, release, changed_by, transaction):
        form = CompleteReleaseForm()
        if not form.validate():
            cef_event("Bad input", CEF_WARN, errors=form.errors)
            return Response(status=400, response=form.errors)

        blob = createBlob(form.blob.data)
        if dbo.releases.getReleases(name=release, limit=1):
            data_version = form.data_version.data
            try:
                dbo.releases.updateRelease(name=release, blob=blob, version=form.version.data,
                    product=form.product.data, changed_by=changed_by,
                    old_data_version=data_version, transaction=transaction)
            except ValueError, e:
                msg = "Couldn't update release: %s" % e
                cef_event("Bad input", CEF_WARN, errors=msg)
                return Response(status=400, response=msg)
            data_version += 1
            return Response(json.dumps(dict(new_data_version=data_version)), status=200)
コード例 #31
0
ファイル: base.py プロジェクト: mozmark/balrog
 def decorated(*args, **kwargs):
     username = request.environ.get('REMOTE_USER')
     method = request.method
     extra = dict()
     for opt in options:
         if opt in request.form:
             extra[opt] = request.form[opt]
         elif request.get_json() and opt in request.json:
             extra[opt] = request.json[opt]
         else:
             msg = "Couldn't find required option %s in form" % opt
             cef_event("Bad input", CEF_WARN, msg=msg)
             return Response(status=400, response=msg)
     if not dbo.permissions.hasUrlPermission(
             username, url, method, urlOptions=extra):
         msg = "%s is not allowed to access %s by %s" % (username, url,
                                                         method)
         cef_event('Unauthorized access attempt', CEF_ALERT, msg=msg)
         return Response(status=401, response=msg)
     return f(*args, **kwargs)
コード例 #32
0
ファイル: releases.py プロジェクト: mozmark/balrog
    def _post(self, release, transaction, changed_by):
        change_id = request.form.get('change_id')
        if not change_id:
            cef_event("Bad input", CEF_WARN, errors="no change id", release=release)
            return Response(status=400, response='no change_id')
        change = dbo.releases.history.getChange(change_id=change_id)
        if change is None:
            return Response(status=404, response='bad change_id')
        if change['name'] != release:
            return Response(status=404, response='bad release')
        releases = dbo.releases.getReleases(name=release)
        if not releases:
            return Response(status=404, response='bad release')
        release = releases[0]
        if not dbo.permissions.hasUrlPermission(changed_by, '/releases/:name', 'POST', urlOptions={'product': release['product']}):
            msg = "%s is not allowed to alter %s releases" % (changed_by, release['product'])
            cef_event('Unauthorized access attempt', CEF_ALERT, msg=msg)
            return Response(status=401, response=msg)
        old_data_version = release['data_version']

        # now we're going to make a new update based on this change
        blob = createBlob(change['data'])

        try:
            dbo.releases.updateRelease(changed_by=changed_by, name=change['name'],
                version=change['version'], blob=blob,
                old_data_version=old_data_version, transaction=transaction)
        except ValueError, e:
            cef_event("Bad input", CEF_WARN, errors=e.args)
            return Response(status=400, response=e.args)
コード例 #33
0
ファイル: releases.py プロジェクト: aybuke/balrog
    def _post(self, changed_by, transaction):
        form = CompleteReleaseForm()
        if not form.validate():
            cef_event("Bad input", CEF_WARN, errors=form.errors)
            return Response(status=400, response=json.dumps(form.errors))

        try:
            blob = createBlob(form.blob.data)
            name = dbo.releases.addRelease(name=form.name.data,
                                           product=form.product.data,
                                           blob=blob,
                                           changed_by=changed_by,
                                           transaction=transaction)
        except BlobValidationError as e:
            msg = "Couldn't update release: %s" % e
            cef_event("Bad input", CEF_WARN, errors=msg)
            return Response(status=400,
                            response=json.dumps({"data": e.errors}))
        except ValueError as e:
            msg = "Couldn't update release: %s" % e
            cef_event("Bad input", CEF_WARN, errors=msg)
            return Response(status=400, response=json.dumps({"data": e.args}))

        release = dbo.releases.getReleases(name=name,
                                           transaction=transaction,
                                           limit=1)[0]
        new_data_version = release['data_version']
        response = make_response(
            json.dumps(dict(new_data_version=new_data_version)), 201)
        response.headers['Content-Type'] = 'application/json'
        return response
コード例 #34
0
ファイル: releases.py プロジェクト: andreja-cliqz/balrog
    def _post(self, release, transaction, changed_by):
        change_id = request.form.get('change_id')
        if not change_id:
            cef_event("Bad input", CEF_WARN, errors="no change id", release=release)
            return Response(status=400, response='no change_id')
        change = dbo.releases.history.getChange(change_id=change_id)
        if change is None:
            return Response(status=404, response='bad change_id')
        if change['name'] != release:
            return Response(status=404, response='bad release')
        releases = dbo.releases.getReleases(name=release)
        if not releases:
            return Response(status=404, response='bad release')
        release = releases[0]
        if not dbo.permissions.hasUrlPermission(changed_by, '/releases/:name', 'POST', urlOptions={'product': release['product']}):
            msg = "%s is not allowed to alter %s releases" % (changed_by, release['product'])
            cef_event('Unauthorized access attempt', CEF_ALERT, msg=msg)
            return Response(status=401, response=msg)
        old_data_version = release['data_version']

        # now we're going to make a new update based on this change
        blob = createBlob(change['data'])

        try:
            dbo.releases.updateRelease(changed_by=changed_by, name=change['name'],
                version=change['version'], blob=blob,
                old_data_version=old_data_version, transaction=transaction)
        except ValueError, e:
            cef_event("Bad input", CEF_WARN, errors=e.args)
            return Response(status=400, response=e.args)
コード例 #35
0
ファイル: releases.py プロジェクト: escapewindow/balrog
    def get(self, release):
        releases = dbo.releases.getReleases(name=release, limit=1)
        if not releases:
            return Response(status=404,
                            response='Requested release does not exist')
        release = releases[0]
        table = dbo.releases.history

        try:
            page = int(request.args.get('page', 1))
            limit = int(request.args.get('limit', 10))
            assert page >= 1
        except (ValueError, AssertionError) as e:
            cef_event("Bad input", CEF_WARN, errors=json.dumps(e.args))
            return Response(status=400, response=json.dumps({"data": e.args}))
        offset = limit * (page - 1)
        total_count = table.t.count()\
            .where(table.name == release['name'])\
            .where(table.data_version != null())\
            .execute()\
            .fetchone()[0]

        revisions = table.select(
            where=[
                table.name == release['name'],
                table.data_version != null()
            ],
            limit=limit,
            offset=offset,
            order_by=[table.timestamp.asc()],
        )

        self.annotateRevisionDifferences(revisions)

        return jsonify({
            'revisions': revisions,
            'count': total_count,
        })
コード例 #36
0
ファイル: releases.py プロジェクト: aybuke/balrog
    def get(self, release):
        releases = dbo.releases.getReleases(name=release, limit=1)
        if not releases:
            return Response(status=404,
                            response='Requested release does not exist')
        release = releases[0]
        table = dbo.releases.history

        try:
            page = int(request.args.get('page', 1))
            limit = int(request.args.get('limit', 10))
            assert page >= 1
        except (ValueError, AssertionError) as e:
            cef_event("Bad input", CEF_WARN, errors=json.dumps(e.args))
            return Response(status=400, response=json.dumps({"data": e.args}))
        offset = limit * (page - 1)
        total_count = table.t.count()\
            .where(table.name == release['name'])\
            .where(table.data_version != null())\
            .execute()\
            .fetchone()[0]

        revisions = table.select(
            where=[
                table.name == release['name'], table.data_version != null()
            ],
            limit=limit,
            offset=offset,
            order_by=[table.timestamp.asc()],
        )

        self.annotateRevisionDifferences(revisions)

        return jsonify({
            'revisions': revisions,
            'count': total_count,
        })
コード例 #37
0
ファイル: base.py プロジェクト: MDTsai/balrog
 def decorated(*args, **kwargs):
     username = request.environ.get('REMOTE_USER')
     if not username:
         cef_event('Login Required', CEF_WARN)
         return Response(status=401)
     return f(*args, changed_by=username, **kwargs)
コード例 #38
0
ファイル: base.py プロジェクト: mozmark/balrog
 def decorated(*args, **kwargs):
     username = request.environ.get('REMOTE_USER')
     if not username:
         cef_event('Login Required', CEF_WARN)
         return Response(status=401)
     return f(*args, changed_by=username, **kwargs)
コード例 #39
0
ファイル: releases.py プロジェクト: mozmark/balrog
def changeRelease(release, changed_by, transaction, existsCallback,
                  commitCallback, log):
    """Generic function to change an aspect of a release. It relies on a
       ReleaseForm existing and does some upfront work and checks before
       doing anything. It will, for the named release and any found in the
       'copyTo' field of the ReleaseForm:
        - Create the release if it doesn't already exist.
        - return a 400 Response if the release exists and old_data_version doesn't.
        - return a 400 Response if the product name in the form doesn't match the existing one.
        - update the version column of the release table if the one in the form doesn't match it.
        - if the release already exists, 'existsCallback' will be called. If
          that function returns True, a 201 Response will be returned upon
          successful completion. If that function returns False, a 200 Response
          will be returned instead.

      @type  release: string
      @param release: The primary release to update. Additional releases found
                      in the 'copyTo' field of the ReleaseForm will also be
                      updated.
      @type  changed_by: string
      @param changed_by: The username making the change.
      @type  transaction: AUSTransaction object
      @param transaction: The transaction object to be used for all database
                          operations.
      @type  existsCallback: callable
      @param existsCallback: The callable to call to determine whether to
                             consider this a "new" change or not. It must
                             receive 3 positional arguments:
                              - the name of the release
                              - the product name from the ReleaseForm
                              - the version from the ReleaseForm
      @type  commitCallback: callable
      @param commitCallback: The callable to call after all prerequisite checks
                             and updates are done. It must receive 6 positional
                             arguments:
                              - the name of the release
                              - the product name from the ReleaseForm
                              - the version from the ReleaseForm
                              - the data from the ReleaseForm
                              - the most recent version of the data for the
                                release from the database
                              - the old_data_version from the ReleaseForm
    """
    new = True
    form = ReleaseForm()
    if not form.validate():
        cef_event("Bad input", CEF_WARN, errors=form.errors)
        return Response(status=400, response=json.dumps(form.errors))
    product = form.product.data
    version = form.version.data
    incomingData = form.data.data
    copyTo = form.copyTo.data
    alias = form.alias.data
    old_data_version = form.data_version.data

    # schema_version is an attribute at the root level of a blob.
    # Endpoints that receive an entire blob can find it there.
    # Those that don't have to pass it as a form element instead.
    if getattr(form.schema_version, "data", None):
        schema_version = form.schema_version.data
    elif incomingData.get("schema_version"):
        schema_version = incomingData.get("schema_version")
    else:
        return Response(status=400, response="schema_version is required")

    if getattr(form.hashFunction, "data", None):
        hashFunction = form.hashFunction.data
    elif incomingData.get("hashFunction"):
        hashFunction = incomingData.get("hashFunction")
    else:
        hashFunction = None

    allReleases = [release]
    if copyTo:
        allReleases += copyTo
    for rel in allReleases:
        try:
            releaseInfo = dbo.releases.getReleases(name=rel,
                                                   transaction=transaction)[0]
            if existsCallback(rel, product, version):
                new = False
            # "release" is the one named in the URL (as opposed to the
            # ones that can be provided in copyTo), and we treat it as
            # the "primary" one
            if rel == release:
                # Make sure that old_data_version is provided, because we need to verify it when updating.
                if not old_data_version:
                    msg = "Release exists, data_version must be provided"
                    cef_event("Bad input", CEF_WARN, errors=msg, release=rel)
                    return Response(status=400, response=msg)
                # If the product we're given doesn't match the one in the DB, panic.
                if product != releaseInfo['product']:
                    msg = "Product name '%s' doesn't match the one on the release object ('%s') for release '%s'" % (
                        product, releaseInfo['product'], rel)
                    cef_event("Bad input", CEF_WARN, errors=msg, release=rel)
                    return Response(status=400, response=msg)
                if 'hashFunction' in releaseInfo[
                        'data'] and hashFunction and hashFunction != releaseInfo[
                            'data']['hashFunction']:
                    msg = "hashFunction '%s' doesn't match the one on the release object ('%s') for release '%s'" % (
                        hashFunction, releaseInfo['data']['hashFunction'], rel)
                    cef_event("Bad input", CEF_WARN, errors=msg, release=rel)
                    return Response(status=400, response=msg)
            # If this isn't the release in the URL...
            else:
                # Use the data_version we just grabbed from the dbo.
                old_data_version = releaseInfo['data_version']
        except IndexError:
            # If the release doesn't already exist, create it, and set old_data_version appropriately.
            newReleaseData = dict(name=rel, schema_version=schema_version)
            if hashFunction:
                newReleaseData['hashFunction'] = hashFunction
            try:
                releaseInfo = createRelease(rel, product, version, changed_by,
                                            transaction, newReleaseData)
            except ValueError, e:
                msg = "Couldn't create release: %s" % e
                cef_event("Bad input", CEF_WARN, errors=msg, release=rel)
                return Response(status=400, response=msg)
            old_data_version = 1

        # If the version doesn't match, just update it. This will be the case for nightlies
        # every time there's a version bump.
        if version != releaseInfo['version']:
            log.debug("database version for %s is %s, updating it to %s", rel,
                      releaseInfo['version'], version)
            try:
                dbo.releases.updateRelease(name=rel,
                                           version=version,
                                           changed_by=changed_by,
                                           old_data_version=old_data_version,
                                           transaction=transaction)
            except ValueError, e:
                msg = "Couldn't update release: %s" % e
                cef_event("Bad input", CEF_WARN, errors=msg, release=rel)
                return Response(status=400, response=msg)
            old_data_version += 1
コード例 #40
0
ファイル: rules.py プロジェクト: MikeLing/balrog
    def get(self, rule_id):
        rule = dbo.rules.getRule(rule_id)
        if not rule:
            return Response(status=404,
                            response='Requested rule does not exist')

        table = dbo.rules.history

        try:
            page = int(request.args.get('page', 1))
            limit = int(request.args.get('limit', 100))
            assert page >= 1
        except (ValueError, AssertionError) as msg:
            cef_event("Bad input", CEF_WARN, errors=msg)
            return Response(status=400, response=str(msg))
        offset = limit * (page - 1)
        total_count = table.t.count()\
            .where(table.rule_id == rule_id)\
            .where(table.data_version != null())\
            .execute()\
            .fetchone()[0]

        revisions = table.select(
            where=[table.rule_id == rule_id,
                   table.data_version != null()],
            limit=limit,
            offset=offset,
            order_by=[table.timestamp.asc()],
        )
        _rules = []
        _mapping = {
            # return : db name
            'id': 'rule_id',
            'mapping': 'mapping',
            'priority': 'priority',
            'alias': 'alias',
            'product': 'product',
            'version': 'version',
            'background_rate': 'backgroundRate',
            'buildID': 'buildID',
            'channel': 'channel',
            'locale': 'locale',
            'distribution': 'distribution',
            'buildTarget': 'buildTarget',
            'osVersion': 'osVersion',
            'distVersion': 'distVersion',
            'whitelist': 'whitelist',
            'comment': 'comment',
            'update_type': 'update_type',
            'headerArchitecture': 'headerArchitecture',
            'data_version': 'data_version',
            # specific to revisions
            'change_id': 'change_id',
            'timestamp': 'timestamp',
            'changed_by': 'changed_by',
        }
        for rule in revisions:
            _rules.append(dict(
                (key, rule[db_key])
                for key, db_key in _mapping.items()
            ))

        ret = {
            'count': total_count,
            'rules': _rules,
        }
        return Response(response=json.dumps(ret), mimetype="application/json")
コード例 #41
0
ファイル: AUS.py プロジェクト: mozmark/balrog
def isForbiddenUrl(url, whitelistedDomains):
    domain = urlparse(url)[1]
    if domain not in whitelistedDomains:
        cef_event("Forbidden domain", CEF_ALERT, domain=domain)
        return True
    return False
コード例 #42
0
ファイル: releases.py プロジェクト: mozmark/balrog
                    changed_by=changed_by, old_data_version=old_data_version,
                    transaction=transaction)
            except ValueError, e:
                msg = "Couldn't update release: %s" % e
                cef_event("Bad input", CEF_WARN, errors=msg, release=rel)
                return Response(status=400, response=msg)
            old_data_version += 1

        extraArgs = {}
        if alias:
            extraArgs['alias'] = alias
        try:
            commitCallback(rel, product, version, incomingData, releaseInfo['data'], old_data_version, extraArgs)
        except (OutdatedDataError, ValueError), e:
            msg = "Couldn't update release: %s" % e
            cef_event("Bad input", CEF_WARN, errors=msg, release=rel)
            return Response(status=400, response=msg)

    new_data_version = dbo.releases.getReleases(name=release, transaction=transaction)[0]['data_version']
    if new:
        status = 201
    else:
        status = 200
    return make_response(json.dumps(dict(new_data_version=new_data_version)), status)


class SingleLocaleView(AdminView):
    """/releases/[release]/builds/[platform]/[locale]"""
    def get(self, release, platform, locale):
        try:
            locale = dbo.releases.getLocale(release, platform, locale)
コード例 #43
0
ファイル: rules.py プロジェクト: MDTsai/balrog
    def _post(self, rule_id, transaction, changed_by):
        # Verify that the rule_id exists.
        rule = dbo.rules.getRuleById(rule_id, transaction=transaction)
        if not rule:
            return Response(status=404)
        form = EditRuleForm()

        # Verify that the user has permission for the existing rule _and_ what the rule would become.
        toCheck = [rule['product']]
        # Rules can be partially updated - if product is null/None, we won't update that field, so
        # we shouldn't check its permission.
        if form.product.data:
            toCheck.append(form.product.data)
        for product in toCheck:
            if not dbo.permissions.hasUrlPermission(changed_by, '/rules/:id', 'POST', urlOptions={'product': product}):
                msg = "%s is not allowed to alter rules that affect %s" % (changed_by, product)
                cef_event('Unauthorized access attempt', CEF_ALERT, msg=msg)
                return Response(status=401, response=msg)
        releaseNames = dbo.releases.getReleaseNames()

        form.mapping.choices = [(item['name'],item['name']) for item in releaseNames]
        form.mapping.choices.insert(0, ('', 'NULL' ))

        if not form.validate():
            cef_event("Bad input", CEF_WARN, errors=form.errors)
            return Response(status=400, response=json.dumps(form.errors))

        what = dict()
        if form.backgroundRate.data:
            what['backgroundRate'] = form.backgroundRate.data
        if form.mapping.data:
            what['mapping'] = form.mapping.data
        if form.priority.data:
            what['priority'] = form.priority.data
        if form.product.data:
            what['product'] = form.product.data
        if form.version.data:
            what['version'] = form.version.data
        if form.build_id.data:
            what['buildID'] = form.build_id.data
        if form.channel.data:
            what['channel'] = form.channel.data
        if form.locale.data:
            what['locale'] = form.locale.data
        if form.distribution.data:
            what['distribution'] = form.distribution.data
        if form.build_target.data:
            what['buildTarget'] = form.build_target.data
        if form.os_version.data:
            what['osVersion'] = form.os_version.data
        if form.dist_version.data:
            what['distVersion'] = form.dist_version.data
        if form.comment.data:
            what['comment'] = form.comment.data
        if form.update_type.data:
            what['update_type'] = form.update_type.data
        if form.header_arch.data:
            what['headerArchitecture'] = form.header_arch.data

        dbo.rules.updateRule(changed_by=changed_by, rule_id=rule_id, what=what,
            old_data_version=form.data_version.data, transaction=transaction)
        # find out what the next data version is
        rule = dbo.rules.getRuleById(rule_id, transaction=transaction)
        new_data_version = rule['data_version']
        response = make_response(json.dumps(dict(new_data_version=new_data_version)))
        response.headers['Content-Type'] = 'application/json'
        return response
コード例 #44
0
ファイル: releases.py プロジェクト: mozmark/balrog
def changeRelease(release, changed_by, transaction, existsCallback, commitCallback, log):
    """Generic function to change an aspect of a release. It relies on a
       ReleaseForm existing and does some upfront work and checks before
       doing anything. It will, for the named release and any found in the
       'copyTo' field of the ReleaseForm:
        - Create the release if it doesn't already exist.
        - return a 400 Response if the release exists and old_data_version doesn't.
        - return a 400 Response if the product name in the form doesn't match the existing one.
        - update the version column of the release table if the one in the form doesn't match it.
        - if the release already exists, 'existsCallback' will be called. If
          that function returns True, a 201 Response will be returned upon
          successful completion. If that function returns False, a 200 Response
          will be returned instead.

      @type  release: string
      @param release: The primary release to update. Additional releases found
                      in the 'copyTo' field of the ReleaseForm will also be
                      updated.
      @type  changed_by: string
      @param changed_by: The username making the change.
      @type  transaction: AUSTransaction object
      @param transaction: The transaction object to be used for all database
                          operations.
      @type  existsCallback: callable
      @param existsCallback: The callable to call to determine whether to
                             consider this a "new" change or not. It must
                             receive 3 positional arguments:
                              - the name of the release
                              - the product name from the ReleaseForm
                              - the version from the ReleaseForm
      @type  commitCallback: callable
      @param commitCallback: The callable to call after all prerequisite checks
                             and updates are done. It must receive 6 positional
                             arguments:
                              - the name of the release
                              - the product name from the ReleaseForm
                              - the version from the ReleaseForm
                              - the data from the ReleaseForm
                              - the most recent version of the data for the
                                release from the database
                              - the old_data_version from the ReleaseForm
    """
    new = True
    form = ReleaseForm()
    if not form.validate():
        cef_event("Bad input", CEF_WARN, errors=form.errors)
        return Response(status=400, response=json.dumps(form.errors))
    product = form.product.data
    version = form.version.data
    incomingData = form.data.data
    copyTo = form.copyTo.data
    alias = form.alias.data
    old_data_version = form.data_version.data

    # schema_version is an attribute at the root level of a blob.
    # Endpoints that receive an entire blob can find it there.
    # Those that don't have to pass it as a form element instead.
    if getattr(form.schema_version, "data", None):
        schema_version = form.schema_version.data
    elif incomingData.get("schema_version"):
        schema_version = incomingData.get("schema_version")
    else:
        return Response(status=400, response="schema_version is required")

    if getattr(form.hashFunction, "data", None):
        hashFunction = form.hashFunction.data
    elif incomingData.get("hashFunction"):
        hashFunction = incomingData.get("hashFunction")
    else:
        hashFunction = None

    allReleases = [release]
    if copyTo:
        allReleases += copyTo
    for rel in allReleases:
        try:
            releaseInfo = dbo.releases.getReleases(name=rel, transaction=transaction)[0]
            if existsCallback(rel, product, version):
                new = False
            # "release" is the one named in the URL (as opposed to the
            # ones that can be provided in copyTo), and we treat it as
            # the "primary" one
            if rel == release:
                # Make sure that old_data_version is provided, because we need to verify it when updating.
                if not old_data_version:
                    msg = "Release exists, data_version must be provided"
                    cef_event("Bad input", CEF_WARN, errors=msg, release=rel)
                    return Response(status=400, response=msg)
                # If the product we're given doesn't match the one in the DB, panic.
                if product != releaseInfo['product']:
                    msg = "Product name '%s' doesn't match the one on the release object ('%s') for release '%s'" % (product, releaseInfo['product'], rel)
                    cef_event("Bad input", CEF_WARN, errors=msg, release=rel)
                    return Response(status=400, response=msg)
                if 'hashFunction' in releaseInfo['data'] and hashFunction and hashFunction != releaseInfo['data']['hashFunction']:
                    msg = "hashFunction '%s' doesn't match the one on the release object ('%s') for release '%s'" % (hashFunction, releaseInfo['data']['hashFunction'], rel)
                    cef_event("Bad input", CEF_WARN, errors=msg, release=rel)
                    return Response(status=400, response=msg)
            # If this isn't the release in the URL...
            else:
                # Use the data_version we just grabbed from the dbo.
                old_data_version = releaseInfo['data_version']
        except IndexError:
            # If the release doesn't already exist, create it, and set old_data_version appropriately.
            newReleaseData = dict(name=rel, schema_version=schema_version)
            if hashFunction:
                newReleaseData['hashFunction'] = hashFunction
            try:
                releaseInfo = createRelease(rel, product, version, changed_by, transaction, newReleaseData)
            except ValueError, e:
                msg = "Couldn't create release: %s" % e
                cef_event("Bad input", CEF_WARN, errors=msg, release=rel)
                return Response(status=400, response=msg)
            old_data_version = 1

        # If the version doesn't match, just update it. This will be the case for nightlies
        # every time there's a version bump.
        if version != releaseInfo['version']:
            log.debug("database version for %s is %s, updating it to %s", rel, releaseInfo['version'], version)
            try:
                dbo.releases.updateRelease(name=rel, version=version,
                    changed_by=changed_by, old_data_version=old_data_version,
                    transaction=transaction)
            except ValueError, e:
                msg = "Couldn't update release: %s" % e
                cef_event("Bad input", CEF_WARN, errors=msg, release=rel)
                return Response(status=400, response=msg)
            old_data_version += 1
コード例 #45
0
 def get(self, type_, change_id, field):
     try:
         value = self.get_value(type_, change_id, field)
     except KeyError, msg:
         cef_event("Bad input", CEF_WARN, errors=str(msg), field=field)
         return Response(status=400, response=str(msg))
コード例 #46
0
ファイル: releases.py プロジェクト: mozmark/balrog
                                           transaction=transaction)
            except ValueError, e:
                msg = "Couldn't update release: %s" % e
                cef_event("Bad input", CEF_WARN, errors=msg, release=rel)
                return Response(status=400, response=msg)
            old_data_version += 1

        extraArgs = {}
        if alias:
            extraArgs['alias'] = alias
        try:
            commitCallback(rel, product, version, incomingData,
                           releaseInfo['data'], old_data_version, extraArgs)
        except (OutdatedDataError, ValueError), e:
            msg = "Couldn't update release: %s" % e
            cef_event("Bad input", CEF_WARN, errors=msg, release=rel)
            return Response(status=400, response=msg)

    new_data_version = dbo.releases.getReleases(
        name=release, transaction=transaction)[0]['data_version']
    if new:
        status = 201
    else:
        status = 200
    return make_response(json.dumps(dict(new_data_version=new_data_version)),
                         status)


class SingleLocaleView(AdminView):
    """/releases/[release]/builds/[platform]/[locale]"""
    def get(self, release, platform, locale):
コード例 #47
0
ファイル: rules.py プロジェクト: aybuke/balrog
    def get(self, rule_id):
        rule = dbo.rules.getRule(rule_id)
        if not rule:
            return Response(status=404,
                            response='Requested rule does not exist')

        table = dbo.rules.history

        try:
            page = int(request.args.get('page', 1))
            limit = int(request.args.get('limit', 100))
            assert page >= 1
        except (ValueError, AssertionError) as msg:
            cef_event("Bad input", CEF_WARN, errors=msg)
            return Response(status=400, response=str(msg))
        offset = limit * (page - 1)
        total_count = table.t.count()\
            .where(table.rule_id == rule_id)\
            .where(table.data_version != null())\
            .execute()\
            .fetchone()[0]

        revisions = table.select(
            where=[table.rule_id == rule_id, table.data_version != null()],
            limit=limit,
            offset=offset,
            order_by=[table.timestamp.asc()],
        )
        _rules = []
        _mapping = {
            # return : db name
            'id': 'rule_id',
            'mapping': 'mapping',
            'priority': 'priority',
            'alias': 'alias',
            'product': 'product',
            'version': 'version',
            'background_rate': 'backgroundRate',
            'buildID': 'buildID',
            'channel': 'channel',
            'locale': 'locale',
            'distribution': 'distribution',
            'buildTarget': 'buildTarget',
            'osVersion': 'osVersion',
            'distVersion': 'distVersion',
            'whitelist': 'whitelist',
            'comment': 'comment',
            'update_type': 'update_type',
            'headerArchitecture': 'headerArchitecture',
            'data_version': 'data_version',
            # specific to revisions
            'change_id': 'change_id',
            'timestamp': 'timestamp',
            'changed_by': 'changed_by',
        }
        for rule in revisions:
            _rules.append(
                dict((key, rule[db_key]) for key, db_key in _mapping.items()))

        ret = {
            'count': total_count,
            'rules': _rules,
        }
        return Response(response=json.dumps(ret), mimetype="application/json")
コード例 #48
0
ファイル: history.py プロジェクト: MDTsai/balrog
 def get(self, type_, change_id, field):
     try:
         value = self.get_value(type_, change_id, field)
     except KeyError, msg:
         cef_event("Bad input", CEF_WARN, errors=str(msg), field=field)
         return Response(status=400, response=str(msg))
コード例 #49
0
ファイル: rules.py プロジェクト: mozmark/balrog
    def _post(self, rule_id, transaction, changed_by):
        # Verify that the rule_id exists.
        rule = dbo.rules.getRuleById(rule_id, transaction=transaction)
        if not rule:
            return Response(status=404)
        form = EditRuleForm()

        # Verify that the user has permission for the existing rule _and_ what the rule would become.
        toCheck = [rule['product']]
        # Rules can be partially updated - if product is null/None, we won't update that field, so
        # we shouldn't check its permission.
        if form.product.data:
            toCheck.append(form.product.data)
        for product in toCheck:
            if not dbo.permissions.hasUrlPermission(
                    changed_by,
                    '/rules/:id',
                    'POST',
                    urlOptions={'product': product}):
                msg = "%s is not allowed to alter rules that affect %s" % (
                    changed_by, product)
                cef_event('Unauthorized access attempt', CEF_ALERT, msg=msg)
                return Response(status=401, response=msg)
        releaseNames = dbo.releases.getReleaseNames()

        form.mapping.choices = [(item['name'], item['name'])
                                for item in releaseNames]
        form.mapping.choices.insert(0, ('', 'NULL'))

        if not form.validate():
            cef_event("Bad input", CEF_WARN, errors=form.errors)
            return Response(status=400, response=json.dumps(form.errors))

        what = dict()
        # We need to be able to support changing AND removing parts of a rule,
        # and because of how Flask's request object and WTForm's defaults work
        # this gets a little hary.
        for k, v in form.data.iteritems():
            # data_version is a "special" column, in that it's not part of the
            # primary data, and shouldn't be updatable by the user.
            if k == "data_version":
                continue
            # We need to check for each column in both the JSON style post
            # and the regular multipart form data. If the key is not present in
            # either of these data structures. We treat this cases as no-op
            # and shouldn't modify the data for that key.
            # If the key is present we should modify the data as requested.
            # If a value is an empty string, we should remove that restriction
            # from the rule (aka, set as NULL in the db). The underlying Form
            # will have already converted it to None, so we can treat it the
            # same as a modification here.
            if (request.json and k in request.json) or k in request.form:
                what[k] = v

        dbo.rules.updateRule(changed_by=changed_by,
                             rule_id=rule_id,
                             what=what,
                             old_data_version=form.data_version.data,
                             transaction=transaction)
        # find out what the next data version is
        rule = dbo.rules.getRuleById(rule_id, transaction=transaction)
        new_data_version = rule['data_version']
        response = make_response(
            json.dumps(dict(new_data_version=new_data_version)))
        response.headers['Content-Type'] = 'application/json'
        return response