예제 #1
0
def choose_template(service_id, template_type='all'):
    templates = service_api_client.get_service_templates(service_id)['data']

    letters_available = ('letter' in current_service['permissions']
                         and current_user.has_permissions('view_activity'))

    available_template_types = list(
        filter(None, (
            'email',
            'sms',
            'letter' if letters_available else None,
        )))

    templates = [
        template for template in templates
        if template['template_type'] in available_template_types
    ]

    has_multiple_template_types = len(
        {template['template_type']
         for template in templates}) > 1

    template_nav_items = [
        (label, key,
         url_for('.choose_template',
                 service_id=current_service['id'],
                 template_type=key), '')
        for label, key in filter(None, [
            ('All', 'all'),
            ('Text message', 'sms'),
            ('Email', 'email'),
            ('Letter', 'letter') if letters_available else None,
        ])
    ]

    templates_on_page = [
        template for template in templates
        if (template_type in ['all', template['template_type']]
            and template['template_type'] in available_template_types)
    ]

    if current_user.has_permissions('view_activity'):
        page_title = 'Templates'
    else:
        page_title = 'Choose a template'

    return render_template(
        'views/templates/choose.html',
        page_title=page_title,
        templates=templates_on_page,
        show_search_box=(len(templates_on_page) > 7),
        show_template_nav=has_multiple_template_types and (len(templates) > 2),
        template_nav_items=template_nav_items,
        template_type=template_type,
        search_form=SearchTemplatesForm(),
    )
예제 #2
0
        def decorated(*args, **kwargs):
            has_permissions = current_user.has_permissions(self.permissions)

            if has_permissions:
                return fn(*args, **kwargs)
            else:
                abort(403)
예제 #3
0
def update_category(challenge_category_id: str):
    update_dict = request.json
    if current_user.has_permissions(["admin"]):
        updated = update_challenge_category(challenge_category_id, update_dict)
        return jsonify(updated.to_dict())
    else:
        raise BadPermissionException(error_code=19)
예제 #4
0
def add_release(body):
    # we must require scope which depends on XPI type
    xpi_type = _xpi_type(body["revision"], body["xpi_name"])
    required_permission = f"{SCOPE_PREFIX}/add_release/xpi/{xpi_type}"
    if not current_user.has_permissions(required_permission):
        user_permissions = ", ".join(current_user.get_permissions())
        abort(401, f"required permission: {required_permission}, user permissions: {user_permissions}")
    session = current_app.db.session
    xpi = XPI(name=body["xpi_name"], revision=body["xpi_revision"], version=body["xpi_version"])
    # project name used in the TC routes and matches the repo name
    project = current_app.config.get("XPI_MANIFEST_REPO")
    release = XPIRelease(revision=body["revision"], xpi=xpi, build_number=body["build_number"], status="scheduled", xpi_type=xpi_type, project=project)
    try:
        common_input = {"build_number": release.build_number, "xpi_name": release.xpi_name, "revision": release.xpi_revision, "version": release.xpi_version}
        release.phases = generate_phases(release, common_input, verify_supported_flavors=False)
        session.add(release)
        session.commit()
    except UnsupportedFlavor as e:
        raise BadRequest(description=e.description)
    except (IntegrityError, TaskclusterRestFailure) as e:
        # Report back Taskcluster and SQL failures for better visibility of the
        # actual issue. Usually it happens when we cannot find the indexed
        # task or a duplicate release request accordingly.
        abort(400, str(e))

    logger.info("New release of %s", release.name)
    notify_via_matrix("xpi", f"New release of {release.name}")
    return release.json, 201
예제 #5
0
def create_category():
    insert_dict = request.json
    if current_user.has_permissions(["admin"]):
        inserted = insert_challenge_category(insert_dict)
        return jsonify(inserted.to_dict())
    else:
        raise BadPermissionException(error_code=21)
예제 #6
0
def view_jobs(service_id):
    jobs = current_service.get_page_of_jobs(page=request.args.get('page'))

    prev_page = None
    if jobs.prev_page:
        prev_page = generate_previous_dict('main.view_jobs', service_id,
                                           jobs.current_page)
    next_page = None
    if jobs.next_page:
        next_page = generate_next_dict('main.view_jobs', service_id,
                                       jobs.current_page)

    scheduled_jobs = ''
    if not current_user.has_permissions(
            'view_activity') and jobs.current_page == 1:
        scheduled_jobs = render_template(
            'views/dashboard/_upcoming.html',
            hide_heading=True,
        )

    return render_template(
        'views/jobs/jobs.html',
        jobs=jobs,
        prev_page=prev_page,
        next_page=next_page,
        scheduled_jobs=scheduled_jobs,
    )
예제 #7
0
def schedule_phase(name, phase):
    session = current_app.db.session
    phase = session.query(XPIPhase).filter(
        XPIRelease.id == XPIPhase.release_id).filter(
            XPIRelease.name == name).filter(
                XPIPhase.name == phase).first_or_404()

    # we must require scope which depends on XPI type
    xpi_type = _xpi_type(phase.release.revision, phase.release.xpi_name)
    required_permission = f"{SCOPE_PREFIX}/schedule_phase/xpi/{xpi_type}/{phase.name}"
    if not current_user.has_permissions(required_permission):
        user_permissions = ", ".join(current_user.get_permissions())
        abort(
            401,
            f"required permission: {required_permission}, user permissions: {user_permissions}"
        )

    phase = do_schedule_phase(session, phase)
    url = taskcluster_urls.ui(get_root_url(), f"/tasks/groups/{phase.task_id}")
    logger.info("Phase %s of %s started by %s. - %s", phase.name,
                phase.release.name, phase.completed_by, url)
    notify_via_matrix(
        "xpi",
        f"Phase {phase.name} of {phase.release.name} started by {phase.completed_by}. - {url}"
    )
    return phase.json
예제 #8
0
def get_back_link(service_id, template_id, step_index):
    if get_help_argument():
        # if we're on the check page, redirect back to the beginning. anywhere else, don't return the back link
        if request.endpoint == 'main.check_notification':
            return url_for('main.send_test',
                           service_id=service_id,
                           template_id=template_id,
                           help=get_help_argument())
        else:
            return None
    elif step_index == 0:
        if current_user.has_permissions('view_activity'):
            return url_for(
                '.view_template',
                service_id=service_id,
                template_id=template_id,
            )
        else:
            return url_for(
                '.choose_template',
                service_id=service_id,
            )
    else:
        return url_for(
            'main.send_one_off_step',
            service_id=service_id,
            template_id=template_id,
            step_index=step_index - 1,
        )
예제 #9
0
파일: api.py 프로젝트: MihaiTabara/shipit
def abandon_release(name):
    session = current_app.db.session
    try:
        release = session.query(Release).filter(Release.name == name).one()

        # we must require scope which depends on product
        required_permission = f"{SCOPE_PREFIX}/abandon_release/{release.product}"
        if not current_user.has_permissions(required_permission):
            user_permissions = ", ".join(current_user.get_permissions())
            abort(
                401,
                f"required permission: {required_permission}, user permissions: {user_permissions}"
            )

        # Cancel all submitted task groups first
        for phase in filter(lambda x: x.submitted and not x.skipped,
                            release.phases):
            try:
                actions = fetch_artifact(phase.task_id, "public/actions.json")
                parameters = fetch_artifact(phase.task_id,
                                            "public/parameters.yml")
            except ArtifactNotFound:
                logger.info("Ignoring not completed action task %s",
                            phase.task_id)
                continue

            hook = generate_action_hook(task_group_id=phase.task_id,
                                        action_name="cancel-all",
                                        actions=actions,
                                        parameters=parameters,
                                        input_={})
            hooks = get_service("hooks")
            client_id = hooks.options["credentials"]["clientId"].decode(
                "utf-8")
            hook["context"]["clientId"] = client_id
            hook_payload_rendered = render_action_hook(
                payload=hook["hook_payload"],
                context=hook["context"],
                delete_params=[
                    "existing_tasks", "release_history",
                    "release_partner_config"
                ])
            logger.info("Cancel phase %s by hook %s with payload: %s",
                        phase.name, hook["hook_id"], hook_payload_rendered)
            res = hooks.triggerHook(hook["hook_group_id"], hook["hook_id"],
                                    hook_payload_rendered)
            logger.debug("Done: %s", res)

        release.status = "aborted"
        session.commit()
        release_json = release.json
    except NoResultFound:
        abort(404)

    notify_via_irc(
        release.product,
        f"Release {release.product} {release.version} build{release.build_number} was just canceled."
    )

    return release_json
예제 #10
0
def add_release(body):
    # we must require scope which depends on product
    required_permission = f'{SCOPE_PREFIX}/add_release/{body["product"]}'
    if not current_user.has_permissions(required_permission):
        user_permissions = ', '.join(current_user.get_permissions())
        abort(401, f'required permission: {required_permission}, user permissions: {user_permissions}')

    session = current_app.db.session
    product = body['product']
    r = Release(
        product=product,
        version=body['version'],
        branch=body['branch'],
        revision=body['revision'],
        build_number=body['build_number'],
        release_eta=body.get('release_eta'),
        status='scheduled',
        partial_updates=body.get('partial_updates'),
        product_key=body.get('product_key'),
    )
    try:
        r.generate_phases(
            partner_urls=current_app.config.get('PARTNERS_URL'),
            github_token=current_app.config.get('GITHUB_TOKEN'),
        )
        session.add(r)
        session.commit()
        release = r.json
    except UnsupportedFlavor as e:
        raise BadRequest(description=e.description)

    notify_via_irc(product, f'New release ({product} {r.version} build{r.build_number}) was just created.')

    return release, 201
예제 #11
0
def manage_template_folder(service_id, template_folder_id):
    template_folder = current_service.get_template_folder_with_user_permission_or_403(template_folder_id, current_user)
    form = TemplateFolderForm(
        name=template_folder['name'],
        users_with_permission=template_folder.get('users_with_permission', None),
        all_service_users=[user for user in current_service.active_users if user.id != current_user.id]
    )
    if form.validate_on_submit():
        if current_user.has_permissions("manage_service") and form.users_with_permission.all_service_users:
            users_with_permission = form.users_with_permission.data + [current_user.id]
        else:
            users_with_permission = None
        template_folder_api_client.update_template_folder(
            current_service.id,
            template_folder_id,
            name=form.name.data,
            users_with_permission=users_with_permission
        )
        return redirect(
            url_for('.choose_template', service_id=service_id, template_folder_id=template_folder_id)
        )

    return render_template(
        'views/templates/manage-template-folder.html',
        form=form,
        template_folder_path=current_service.get_template_folder_path(template_folder_id),
        current_service_id=current_service.id,
        template_folder_id=template_folder_id,
        template_type="all",
    )
예제 #12
0
        def decorated(*args, **kwargs):
            has_permissions = current_user.has_permissions(self.permissions)

            if has_permissions:
                return fn(*args, **kwargs)
            else:
                abort(403)
예제 #13
0
def view_template(service_id, template_id):
    if not current_user.has_permissions('view_activity'):
        return redirect(
            url_for('.send_one_off',
                    service_id=service_id,
                    template_id=template_id))
    template = service_api_client.get_service_template(
        service_id, str(template_id))['data']
    if template["template_type"] == "letter":
        letter_contact_details = service_api_client.get_letter_contacts(
            service_id)
        default_letter_contact_block_id = next(
            (x['id'] for x in letter_contact_details if x['is_default']), None)
    else:
        default_letter_contact_block_id = None
    return render_template(
        'views/templates/template.html',
        template=get_template(
            template,
            current_service,
            expand_emails=True,
            letter_preview_url=url_for(
                '.view_letter_template_preview',
                service_id=service_id,
                template_id=template_id,
                filetype='png',
            ),
            show_recipient=True,
            page_count=get_page_count_for_letter(template),
        ),
        default_letter_contact_block_id=default_letter_contact_block_id,
    )
예제 #14
0
def view_jobs(service_id):
    page = int(request.args.get('page', 1))
    jobs_response = job_api_client.get_page_of_jobs(service_id, page=page)
    jobs = [add_rate_to_job(job) for job in jobs_response['data']]

    prev_page = None
    if jobs_response['links'].get('prev', None):
        prev_page = generate_previous_dict('main.view_jobs', service_id, page)
    next_page = None
    if jobs_response['links'].get('next', None):
        next_page = generate_next_dict('main.view_jobs', service_id, page)

    scheduled_jobs = ''
    if not current_user.has_permissions('view_activity') and page == 1:
        scheduled_jobs = render_template(
            'views/dashboard/_upcoming.html',
            scheduled_jobs=job_api_client.get_scheduled_jobs(service_id),
            hide_heading=True,
        )

    return render_template(
        'views/jobs/jobs.html',
        jobs=jobs,
        page=page,
        prev_page=prev_page,
        next_page=next_page,
        scheduled_jobs=scheduled_jobs,
    )
예제 #15
0
 def wrap_func(*args, **kwargs):
     if not current_user.is_authenticated:
         return current_app.login_manager.unauthorized()
     if not current_user.has_permissions(*permissions, **
                                         permission_kwargs):
         abort(403)
     return func(*args, **kwargs)
예제 #16
0
 def wrap_func(*args, **kwargs):
     from flask_login import current_user
     if current_user and current_user.has_permissions(permissions=permissions,
                                                      admin_override=admin_override, any_=any_):
         return func(*args, **kwargs)
     else:
         abort(403)
예제 #17
0
def abandon_release(name):
    session = current_app.db.session
    try:
        release = session.query(Release).filter(Release.name == name).one()

        # we must require scope which depends on product
        required_permission = f'{SCOPE_PREFIX}/abandon_release/{release.product}'
        if not current_user.has_permissions(required_permission):
            user_permissions = ', '.join(current_user.get_permissions())
            abort(
                401,
                f'required permission: {required_permission}, user permissions: {user_permissions}'
            )

        # Cancel all submitted task groups first
        for phase in filter(lambda x: x.submitted, release.phases):
            try:
                actions = fetch_actions_json(phase.task_id)
            except ActionsJsonNotFound:
                logger.info('Ignoring not completed action task %s',
                            phase.task_id)
                continue

            hook = generate_action_hook(
                task_group_id=phase.task_id,
                action_name='cancel-all',
                actions=actions,
                input_={},
            )
            hooks = get_service('hooks')
            client_id = hooks.options['credentials']['clientId'].decode(
                'utf-8')
            hook['context']['clientId'] = client_id
            hook_payload_rendered = render_action_hook(
                payload=hook['hook_payload'],
                context=hook['context'],
                delete_params=[
                    'existing_tasks', 'release_history',
                    'release_partner_config'
                ],
            )
            logger.info('Cancel phase %s by hook %s with payload: %s',
                        phase.name, hook['hook_id'], hook_payload_rendered)
            res = hooks.triggerHook(hook['hook_group_id'], hook['hook_id'],
                                    hook_payload_rendered)
            logger.debug('Done: %s', res)

        release.status = 'aborted'
        session.commit()
        release_json = release.json
    except NoResultFound:
        abort(404)

    notify_via_irc(
        release.product,
        f'Release {release.product} {release.version} build{release.build_number} was just canceled.'
    )

    return release_json
예제 #18
0
def abandon_release(name):
    session = current_app.db.session
    release = session.query(Release).filter(
        Release.name == name).first_or_404()

    # we must require scope which depends on product
    required_permission = f"{SCOPE_PREFIX}/abandon_release/{release.product}"
    if not current_user.has_permissions(required_permission):
        user_permissions = ", ".join(current_user.get_permissions())
        abort(
            401,
            f"required permission: {required_permission}, user permissions: {user_permissions}"
        )

    # Cancel all submitted task groups first
    for phase in filter(lambda x: x.submitted and not x.skipped,
                        release.phases):
        try:
            actions = get_actions(phase.task_id)
            parameters = get_parameters(phase.task_id)
            cancel_action = find_action("cancel-all", actions)
            if not cancel_action:
                logger.info(
                    "%s %s does not have `cancel-all` action, skipping...",
                    release.name, phase.name)
                continue
        except ArtifactNotFound:
            logger.info("Ignoring not completed action task %s", phase.task_id)
            continue

        hook = generate_action_hook(task_group_id=phase.task_id,
                                    action_name="cancel-all",
                                    actions=actions,
                                    parameters=parameters,
                                    input_={})
        hooks = get_service("hooks")
        client_id = hooks.options["credentials"]["clientId"].decode("utf-8")
        hook["context"]["clientId"] = client_id
        hook_payload_rendered = render_action_hook(
            payload=hook["hook_payload"],
            context=hook["context"],
            delete_params=[
                "existing_tasks", "release_history", "release_partner_config"
            ])
        logger.info("Cancel phase %s by hook %s with payload: %s", phase.name,
                    hook["hook_id"], hook_payload_rendered)
        try:
            result = hooks.triggerHook(hook["hook_group_id"], hook["hook_id"],
                                       hook_payload_rendered)
            logger.debug("Done: %s", result)
        except TaskclusterRestFailure as e:
            abort(400, str(e))

    release.status = "aborted"
    session.commit()
    logger.info("Canceled release %s", release.name)
    notify_via_matrix(release.product,
                      f"Release {release.name} was just canceled.")
    return release.json
예제 #19
0
파일: api.py 프로젝트: tp-tc/shipit
def schedule_phase(name, phase):
    session = current_app.db.session
    try:
        phase = session.query(Phase).filter(
            Release.id == Phase.release_id).filter(
                Release.name == name).filter(Phase.name == phase).one()
    except NoResultFound:
        abort(404)

    # we must require scope which depends on product
    required_permission = f"{SCOPE_PREFIX}/schedule_phase/{phase.release.product}/{phase.name}"
    if not current_user.has_permissions(required_permission):
        user_permissions = ", ".join(current_user.get_permissions())
        abort(
            401,
            f"required permission: {required_permission}, user permissions: {user_permissions}"
        )

    if phase.submitted:
        abort(409, "Already submitted!")

    for signoff in phase.signoffs:
        if not signoff.signed:
            abort(400, "Pending signoffs")

    hook = phase.task_json

    if "hook_payload" not in hook:
        raise ValueError("Action tasks are not supported")

    hooks = get_service("hooks")
    client_id = hooks.options["credentials"]["clientId"].decode("utf-8")
    extra_context = {"clientId": client_id}
    result = hooks.triggerHook(
        hook["hook_group_id"], hook["hook_id"],
        phase.rendered_hook_payload(extra_context=extra_context))
    phase.task_id = result["status"]["taskId"]

    phase.submitted = True
    phase.completed_by = current_user.get_id()
    completed = datetime.datetime.utcnow()
    phase.completed = completed
    if all([ph.submitted for ph in phase.release.phases]):
        phase.release.status = "shipped"
        phase.release.completed = completed
    session.commit()

    root_url = hooks.options["rootUrl"]
    url = f"{root_url}/tasks/groups/{phase.task_id}"
    # TODO: Remove the condition after migration
    if root_url == "https://taskcluster.net":
        url = "https://tools.taskcluster.net/groups/{phase.task_id}"

    notify_via_irc(
        phase.release.product,
        f"Phase {phase.name} was just scheduled for release {phase.release.product} {phase.release.version} build{phase.release.build_number} - {url}",
    )

    return phase.json
예제 #20
0
def _require_auth():
    required_permission = f"{SCOPE_PREFIX}/github"
    if not current_user.has_permissions(required_permission):
        user_permissions = ", ".join(current_user.get_permissions())
        abort(
            401,
            f"required permission: {required_permission}, user permissions: {user_permissions}"
        )
예제 #21
0
def choose_template(service_id, template_type="all", template_folder_id=None):
    template_folder = current_service.get_template_folder(template_folder_id)

    user_has_template_folder_permission = current_user.has_template_folder_permission(
        template_folder)

    template_list = TemplateList(current_service, template_type,
                                 template_folder_id, current_user)

    templates_and_folders_form = TemplateAndFoldersSelectionForm(
        all_template_folders=current_service.get_user_template_folders(
            current_user),
        template_list=template_list,
        template_type=template_type,
        allow_adding_letter_template=current_service.has_permission("letter"),
        allow_adding_copy_of_template=(current_service.all_templates
                                       or len(current_user.service_ids) > 1),
    )
    option_hints = {template_folder_id: "current folder"}

    if request.method == "POST" and templates_and_folders_form.validate_on_submit(
    ):
        if not current_user.has_permissions("manage_templates"):
            abort(403)
        try:
            return process_folder_management_form(templates_and_folders_form,
                                                  template_folder_id)
        except HTTPError as e:
            flash(e.message)

    if "templates_and_folders" in templates_and_folders_form.errors:
        flash(_("Select at least one template or folder"))

    initial_state = request.args.get("initial_state")
    if request.method == "GET" and initial_state:
        templates_and_folders_form.op = initial_state

    sending_view = request.args.get("view") == "sending"

    return render_template(
        "views/templates/choose.html",
        current_template_folder_id=template_folder_id,
        template_folder_path=current_service.get_template_folder_path(
            template_folder_id),
        template_list=template_list,
        show_search_box=current_service.count_of_templates_and_folders > 7,
        show_template_nav=(current_service.has_multiple_template_types
                           and (len(current_service.all_templates) > 2)),
        sending_view=sending_view,
        template_nav_items=get_template_nav_items(template_folder_id,
                                                  sending_view),
        template_type=template_type,
        search_form=SearchByNameForm(),
        templates_and_folders_form=templates_and_folders_form,
        move_to_children=templates_and_folders_form.move_to.children(),
        user_has_template_folder_permission=user_has_template_folder_permission,
        option_hints=option_hints,
    )
예제 #22
0
 def wrap_func(*args, **kwargs):
     if current_user and current_user.is_authenticated:
         if current_user.has_permissions(*permissions,
                                         **permission_kwargs):
             return func(*args, **kwargs)
         else:
             abort(403)
     else:
         abort(401)
예제 #23
0
def schedule_phase(name, phase):
    session = current_app.db.session
    try:
        phase = session.query(Phase) \
            .filter(Release.id == Phase.release_id) \
            .filter(Release.name == name) \
            .filter(Phase.name == phase).one()
    except NoResultFound:
        abort(404)

    # we must require scope which depends on product
    required_permission = f'{SCOPE_PREFIX}/schedule_phase/{phase.release.product}/{phase.name}'
    if not current_user.has_permissions(required_permission):
        user_permissions = ', '.join(current_user.get_permissions())
        abort(
            401,
            f'required permission: {required_permission}, user permissions: {user_permissions}'
        )

    if phase.submitted:
        abort(409, 'Already submitted!')

    for signoff in phase.signoffs:
        if not signoff.signed:
            abort(400, 'Pending signoffs')

    hook = phase.task_json

    if 'hook_payload' not in hook:
        raise ValueError('Action tasks are not supported')

    hooks = get_service('hooks')
    client_id = hooks.options['credentials']['clientId'].decode('utf-8')
    extra_context = {'clientId': client_id}
    result = hooks.triggerHook(
        hook['hook_group_id'],
        hook['hook_id'],
        phase.rendered_hook_payload(extra_context=extra_context),
    )
    phase.task_id = result['status']['taskId']

    phase.submitted = True
    phase.completed_by = current_user.get_id()
    completed = datetime.datetime.utcnow()
    phase.completed = completed
    if all([ph.submitted for ph in phase.release.phases]):
        phase.release.status = 'shipped'
        phase.release.completed = completed
    session.commit()

    notify_via_irc(
        phase.release.product, f'Phase {phase.name} was just scheduled '
        f'for release {phase.release.product} {phase.release.version} '
        f'build{phase.release.build_number} - '
        f'(https://tools.taskcluster.net/groups/{phase.task_id})')

    return phase.json
예제 #24
0
def phase_signoff(name, phase, body):
    session = current_app.db.session
    signoff = session.query(XPISignoff).filter(
        XPISignoff.uid == body).first_or_404()

    if signoff.signed:
        abort(409, "Already signed off")

    phase_obj = (session.query(XPIPhase).filter(
        XPIRelease.id == XPIPhase.release_id).filter(
            XPIRelease.name == name).filter(
                XPIPhase.name == phase).first_or_404())
    # we must require scope which depends on product and phase name
    xpi_type = _xpi_type(phase_obj.release.revision,
                         phase_obj.release.xpi_name)
    required_permission = f"{SCOPE_PREFIX}/phase_signoff/xpi/{xpi_type}/{signoff.phase.name}"
    if not current_user.has_permissions(
            required_permission) and not XPI_LAX_SIGN_OFF:
        user_permissions = ", ".join(current_user.get_permissions())
        abort(
            401,
            f"required permission: {required_permission}, user permissions: {user_permissions}"
        )

    # Prevent the same user signing off for multiple signoffs
    users_ldap = current_user.get_ldap_groups()
    users_email = current_user.get_id()
    if users_email in [s.completed_by
                       for s in phase_obj.signoffs] and not XPI_LAX_SIGN_OFF:
        abort(409, f"Already signed off by {users_email}")

    # signoff.permissions corresponds to the group in settings.py
    ldap_groups = current_app.config.get("LDAP_GROUPS", {})
    ldap_group = ldap_groups.get(signoff.permissions, [])
    if not set(users_ldap).intersection(
            set(ldap_group)) and not XPI_LAX_SIGN_OFF:
        abort(401,
              f"User `{users_email}` is not in the `{signoff.permissions}`")

    signoff.completed = datetime.datetime.utcnow()
    signoff.signed = True
    signoff.completed_by = users_email

    session.commit()
    signoffs = [s.json for s in phase_obj.signoffs]

    # Schedule the phase when all signoffs are done
    if all([s.signed for s in phase_obj.signoffs]):
        schedule_phase(name, phase)

    release = phase_obj.release
    logger.info("Phase %s of %s signed off by %s", phase, release.name,
                users_email)
    notify_via_matrix(
        "xpi", f"Phase {phase} of {release.name} signed off by {users_email}")

    return dict(signoffs=signoffs)
예제 #25
0
def get_all_challenges():
    challenges = ChallengeManager().get_all()
    if current_user.is_anonymous or not current_user.has_permissions(["admin"]):
        for challenge in challenges:
            for flag in challenge.flags:
                flag["secret"] = ""
            if challenge.hints is not None:
                for hint in challenge.hints:
                    hint["text"] = ""
    return challenges
예제 #26
0
 def wrap_func(*args, **kwargs):
     if current_user and current_user.is_authenticated:
         if current_user.has_permissions(permissions=permissions,
                                         admin_override=admin_override,
                                         any_=any_):
             return func(*args, **kwargs)
         else:
             abort(403)
     else:
         abort(401)
예제 #27
0
 def wrapped(*args, **kwargs):
     if __WITH_USERS__:
         if not current_user.is_authenticated:
             emit("auth_required")
         elif current_user.has_permissions(*perms):
             return f(*args, **kwargs)
         else:
             raise Exception(
                 f"You don't have the required permissions. \n These are your permissions: {current_user.permissions}"
             )
     else:
         return f(*args, **kwargs)
예제 #28
0
 def wrap_func(*args, **kwargs):
     if current_user and current_user.is_authenticated:
         if current_user.has_permissions(
             permissions=permissions,
             admin_override=admin_override,
             any_=any_
         ):
             return func(*args, **kwargs)
         else:
             abort(403)
     else:
         abort(401)
예제 #29
0
def add_release(body):
    # we must require scope which depends on product
    required_permission = f'{SCOPE_PREFIX}/add_release/{body["product"]}'
    if not current_user.has_permissions(required_permission):
        user_permissions = ", ".join(current_user.get_permissions())
        abort(
            401,
            f"required permission: {required_permission}, user permissions: {user_permissions}"
        )

    product = body["product"]
    branch = body["branch"]

    product_disabled = branch in get_disabled_products().get(product, [])
    if current_user.type == AuthType.TASKCLUSTER and product_disabled:
        abort(401, "Taskcluster based submissions are disabled")

    session = current_app.db.session
    partial_updates = body.get("partial_updates")
    if partial_updates == "auto":
        if product not in [
                Product.FIREFOX.value, Product.DEVEDITION.value
        ] or branch not in ["try", "releases/mozilla-beta", "projects/maple"]:
            abort(400, "Partial suggestion works for automated betas only")

        partial_updates = _suggest_partials(product=product, branch=branch)
    release = Release(
        branch=branch,
        build_number=body["build_number"],
        partial_updates=partial_updates,
        product_key=body.get("product_key"),
        product=product,
        release_eta=body.get("release_eta"),
        repo_url=body.get("repo_url", ""),
        revision=body["revision"],
        status="scheduled",
        version=body["version"],
    )
    try:
        release.generate_phases()
        session.add(release)
        session.commit()
    except UnsupportedFlavor as e:
        raise BadRequest(description=e.description)
    except TaskclusterRestFailure as e:
        # Report back Taskcluster failure for better visibility of the actual
        # issue. Usually it happens when we cannot find the indexed task.
        abort(400, str(e))

    logger.info("New release of %s", release.name)
    notify_via_irc(product, f"New release of {release.name}")

    return release.json, 201
예제 #30
0
        def decorated(*args, **kwargs):
            # TODO: WORKAROUND:
            # when it is an API key, always allow it
            if current_user.is_api_user:
                has_permissions = True
            else:
                has_permissions = current_user.has_permissions(self.permissions)

            if has_permissions:
                return fn(*args, **kwargs)
            else:
                abort(403)
예제 #31
0
def get_skip_link(step_index, template):
    if (
        request.endpoint == 'main.send_one_off_step'
        and step_index == 0
        and template.template_type in ("sms", "email")
        and not (template.template_type == 'sms' and current_user.mobile_number is None)
        and current_user.has_permissions('manage_templates', 'manage_service')
    ):
        return (
            'Use my {}'.format(first_column_headings[template.template_type][0]),
            url_for('.send_one_off_to_myself', service_id=current_service.id, template_id=template.id),
        )
예제 #32
0
파일: api.py 프로젝트: MihaiTabara/shipit
def add_release(body):
    # we must require scope which depends on product
    required_permission = f'{SCOPE_PREFIX}/add_release/{body["product"]}'
    if not current_user.has_permissions(required_permission):
        user_permissions = ", ".join(current_user.get_permissions())
        abort(
            401,
            f"required permission: {required_permission}, user permissions: {user_permissions}"
        )

    product = body["product"]
    branch = body["branch"]

    product_disabled = branch in get_disabled_products().get(product, [])
    if current_user.type == AuthType.TASKCLUSTER and product_disabled:
        abort(401, "Taskcluster based submissions are disabled")

    session = current_app.db.session
    partial_updates = body.get("partial_updates")
    if partial_updates == "auto":
        if product not in [
                Product.FIREFOX.value, Product.DEVEDITION.value
        ] or branch not in ["try", "releases/mozilla-beta", "projects/maple"]:
            abort(400, "Partial suggestion works for automated betas only")

        partial_updates = _suggest_partials(product=product, branch=branch)
    r = Release(
        product=product,
        version=body["version"],
        branch=branch,
        revision=body["revision"],
        build_number=body["build_number"],
        release_eta=body.get("release_eta"),
        status="scheduled",
        partial_updates=partial_updates,
        product_key=body.get("product_key"),
    )
    try:
        r.generate_phases(partner_urls=current_app.config.get("PARTNERS_URL"),
                          github_token=current_app.config.get("GITHUB_TOKEN"))
        session.add(r)
        session.commit()
        release = r.json
    except UnsupportedFlavor as e:
        raise BadRequest(description=e.description)

    notify_via_irc(
        product,
        f"New release ({product} {r.version} build{r.build_number}) was just created."
    )

    return release, 201
예제 #33
0
def service_dashboard(service_id):

    if session.get('invited_user'):
        session.pop('invited_user', None)
        session['service_id'] = service_id

    if not current_user.has_permissions('view_activity'):
        return redirect(url_for('main.choose_template', service_id=service_id))

    return render_template('views/dashboard/dashboard.html',
                           updates_url=url_for(".service_dashboard_updates",
                                               service_id=service_id),
                           partials=get_dashboard_partials(service_id))
예제 #34
0
def serialize_contributor(contributor, link=None):
    '''
    Helper to serialize a contributor & its role
    '''
    assert isinstance(contributor, Contributor)

    out = {
        'id': contributor.id,
        'email': contributor.email,
        'name': contributor.name,
        'avatar': contributor.avatar_url,
        'karma': contributor.karma or 0,
        'comment_public': contributor.comment_public or '',
    }
    if current_user.has_permissions(SCOPES_ADMIN):
        # Only admins can see/edit the private comment
        out['comment_private'] = contributor.comment_private or ''

    if link is not None:
        assert isinstance(link, BugContributor)
        out['roles'] = link.roles.split(',')

    return out
예제 #35
0
파일: auth.py 프로젝트: level12/keg-bouncer
 def wrapper(fn, instance, args, kwargs):
     if not (current_user and current_user.is_authenticated):
         return flask.abort(401)
     elif not current_user.has_permissions(*tokens):
         return flask.abort(403)
     return fn(*args, **kwargs)
예제 #36
0
파일: auth.py 프로젝트: level12/keg-bouncer
def current_user_has_permissions(*tokens):
    """Returns True IFF the current session belongs to an authenticated user who has all of the
    given permission tokens."""
    return (current_user
            and current_user.is_authenticated
            and current_user.has_permissions(*tokens))
예제 #37
0
파일: auth.py 프로젝트: x20080406/theblog
 def __call__(self):
     return self.permissions <= current_user.has_permissions()