def _process(self):
        if "friend computer please build" not in self._message.lower():
            return

        if "cs61a" != self._course:
            return

        users = requests.get("https://slack.com/api/users.list",
                             params={
                                 "token": self._bot_token
                             }).json()

        for member in users["members"]:
            if member["id"] == self._event["user"]:
                sender_email = member["profile"].get("email")
                break

        if not sender_email or not is_admin(course="cs61a",
                                            email=sender_email):
            return

        match = re.search(REGEX_TEMPLATE, self._message)

        if not match:
            return

        try:
            pr = int(match.group("path"))
        except ValueError:
            return

        trigger_build_sync(pr_number=pr, noreply=True)
        self.reply = ":building_construction: Build triggered!"
Example #2
0
def index():
    if not is_staff("cs61a"):
        return login()
    email = get_user()["email"]
    if not is_admin(course="cs61a", email=email):
        abort(401)
    with connect_db() as db:
        apps = db("SELECT app FROM services WHERE pr_number=0", []).fetchall()
        pr_apps = db(
            "SELECT app, pr_number FROM services WHERE pr_number>0 ORDER BY pr_number DESC",
            [],
        ).fetchall()
    return html(
        f"""
        This service manages the deployment of the 61A website and various apps.
        {"".join(f'''
        <form action="/deploy_prod_app">
            <input type="submit" name="app" value="{app}" />
        </form>
        ''' for [app] in apps)}
        {"".join(f'''
        <form action="/trigger_build">
            <input type="hidden" name="app" value="{app}" />
            <input type="hidden" name="pr_number" value="{pr_number}" />
            <input type="submit" value="{app + "-pr" + str(pr_number)}" />
        </form>
        ''' for [app, pr_number] in pr_apps)}
        <form action="/delete_unused_services" method="post">
            <input type="submit" value="Delete unused services" />
       </form>
    """
    )
Example #3
0
def create_secret(service):
    if not is_staff("cs61a"):
        return login()
    email = get_user()["email"]
    if not is_admin(course="cs61a", email=email):
        abort(401)

    if service not in list_services():
        abort(404)

    out = reversed([
        entry["timestamp"] + " " + escape(entry["textPayload"])
        for entry in loads(
            sh(
                "gcloud",
                "logging",
                "read",
                f"projects/cs61a-140900/logs/run.googleapis.com AND resource.labels.service_name={service}",
                "--limit",
                "100",
                "--format",
                "json",
                capture_output=True,
            )) if "textPayload" in entry
    ])

    return "<pre>" + "\n".join(map(str, out)) + "</pre>"
Example #4
0
def delete_unused_services_handler():
    if not is_staff("cs61a"):
        return login()
    email = get_user()["email"]
    if not is_admin(course="cs61a", email=email):
        return login()
    delete_unused_services()
    return redirect(url_for("index"))
Example #5
0
def deploy_prod_app():
    if not is_staff("cs61a"):
        return login()
    email = get_user()["email"]
    if not is_admin(course="cs61a", email=email):
        abort(401)
    app = request.args["app"]
    deploy_prod_app_sync(target_app=app, noreply=True)
    return html(f"Deploying <code>{app}</code> from master!")
Example #6
0
def index():
    if not is_staff("cs61a"):
        return login()
    email = get_user()["email"]
    if not is_admin(course="cs61a", email=email):
        abort(401)

    service_list = "\n".join(
        f"<p /><a href={url_for('create_secret', service=service)}>{service}</a>"
        for service in list_services())

    return f"""
Example #7
0
def is_admin(email, course=None):
    """Returns whether or not an email address belongs to an admin
    for the given course, using :meth:`~common.rpc.auth.is_admin`.

    :param email: the email address in question
    :type email: str
    :param course: the course code, such as "cs61a", inferred using
        :meth:`~common.course_config.get_course` if omitted
    :type course: str

    :return: ``True`` if the user is an admin, ``False`` otherwise
    """
    if getenv("ENV") != "prod":
        return True
    if not course:
        course = get_course()
    return auth.is_admin(email=email, course=course, force_course=course)
Example #8
0
def trigger_build():
    if not is_staff("cs61a"):
        return login()
    email = get_user()["email"]
    if not is_admin(course="cs61a", email=email):
        abort(401)
    if "app" in request.args:
        target = request.args["app"]
    else:
        target = None

    pr_number = int(request.args["pr_number"])

    g = Github(get_secret(secret_name="GITHUB_ACCESS_TOKEN"))
    repo = g.get_repo(GITHUB_REPO)
    pr = repo.get_pull(pr_number)

    if DO_NOT_BUILD in [l.name for l in pr.labels]:
        return html(
            f"PR <code>{pr_number}</code> has a DO NOT BUILD label on it, so it cannot be built. Remove this label to build the PR."
        )

    trigger_build_sync(pr_number=pr_number, target_app=target, noreply=True)
    return html(f"Building PR <code>{pr_number}</code>!")
Example #9
0
 def wrapped(*args, **kwargs):
     if not (is_staff("cs61a") and is_admin(email=get_user()["email"])):
         return login()
     return func(*args, **kwargs)
Example #10
0
    def query():
        try:
            if is_logged_in():
                user = get_user()

                email = user["email"]
                target = request.args.get("target", None)
                admin = True if DEV else is_admin(course=get_course(),
                                                  email=email)

                if is_staff(get_course()):
                    if target:
                        email = target
                    else:
                        show_all_students = has_access_to_all_grades()
                        students = []
                        with connect_db() as db:
                            lookup = db(
                                "SELECT shortData FROM students WHERE courseCode=%s",
                                [get_course()],
                            ).fetchall()
                            for row in lookup:
                                parsed = json.loads(row[0])
                                if show_all_students or parsed.get("TA",
                                                                   "") in (
                                                                       "",
                                                                       email,
                                                                   ):
                                    students.append(parsed)
                        return jsonify({
                            "success": True,
                            "isStaff": True,
                            "isAdmin": admin,
                            "canExportGrades": show_all_students,
                            "allStudents": students,
                            "email": user["email"],
                            "name": user["name"],
                            "lastUpdated": last_updated(),
                        })

                with connect_db() as db:
                    [short_data, data] = db(
                        "SELECT shortData, data FROM students WHERE courseCode=%s AND email=%s",
                        [get_course(), email],
                    ).fetchone()
                    [header
                     ] = db("SELECT header FROM headers WHERE courseCode=%s",
                            [get_course()]).fetchone()
                    short_data = json.loads(short_data)
                    if not (email == user["email"] or admin or short_data.get(
                            "TA", "") in ("", user["email"])):
                        return jsonify({"success": False, "retry": False})
                    data = json.loads(data)
                    header = json.loads(header)
                    return jsonify({
                        "success": True,
                        "header": header,
                        "data": data,
                        "email": short_data["Email"],
                        "name": short_data["Name"],
                        "SID": short_data["SID"],
                        "ta": short_data.get("TA", ""),
                        "lastUpdated": last_updated(),
                    })
            else:
                return jsonify({"success": False, "retry": True})

        except Exception:
            pass
        return jsonify({"success": False, "retry": False})