Ejemplo n.º 1
0
 def fix_users(field):
     log.debug(field)
     if is_undefined(field):
         return undefined
     if not field:
         return undefined
     if isinstance(field, basestring):
         return set([build_user_key(id) for id in re.split("[\\s,;]+", field) if len(id) > 0])
     return [build_user_key(user) for user in field]
Ejemplo n.º 2
0
 def fix_users(field):
     log.debug(field)
     if is_undefined(field):
         return undefined
     if not field:
         return undefined
     if isinstance(field, basestring):
         return set([
             build_user_key(id) for id in re.split("[\\s,;]+", field)
             if len(id) > 0
         ])
     return [build_user_key(user) for user in field]
Ejemplo n.º 3
0
def issue_search(viewer, simple=None, query=None, complex=None):
    permission_verify(viewer, "issue", "read")

    if not complex:
        if query:
            complex = query_to_complex_search(query)
        else:
            # Status is open and assigned to me, or closing and verified by me.
            complex = { "boolean" : "or",
                        "sub"     : [ { "boolean" : "and",
                                        "sub"     : [ { "field"    : "status",
                                                        "operator" : "in",
                                                        "value"    : [ "triage", "assigned", "working" ] },
                                                      { "field"    : "assignees",
                                                        "operator" : "==",
                                                        "value"    : [ viewer ] } ] },
                                      { "boolean" : "and",
                                        "sub"     : [ { "field"    : "status",
                                                        "operator" : "in",
                                                        "value"    : [ "fixed", "rejected" ] },
                                                      { "field"    : "verifiers",
                                                        "operator" : "==",
                                                        "value"    : [ viewer ] } ] } ] }

    result = []
    ndb_query, first_sort = complex_search_to_ndb_query(complex)
    if permission_is_root(viewer):
        if ndb_query:
            dataset = Issue.query().filter(ndb_query)
        else:
            dataset = Issue.query().filter()
    else:
        privacy_query = ndb.OR(Issue.privacy == "public",
                               Issue.assignees == build_user_key(viewer),
                               Issue.reporters == build_user_key(viewer),
                               Issue.verifiers == build_user_key(viewer),
                               Issue.cc == build_user_key(viewer))
        if ndb_query:
            dataset = Issue.query().filter(ndb.AND(ndb_query, privacy_query))
        else:
            dataset = Issue.query().filter(privacy_query)

    if first_sort:
        dataset = dataset.order(first_sort)
    else:
        dataset = dataset.order(-Issue.score, -Issue.created)

    for issue in dataset:
        issue.history = []
        result.append(to_model(viewer, issue))

    return result
Ejemplo n.º 4
0
def task_create(actor, key=None, task_ids=None, name=undefined, active=True, **kwargs):
    key = key or task_key(task_ids or name)
    task = Task(key=key)
    task.name = task_ids[-1]
    task.parent = key.parent()
    task.created_by = build_user_key(actor)
    return task_update(actor, task=task, active=True, name=name, **kwargs)
Ejemplo n.º 5
0
def tag_create(actor, key=None, tag_ids=None, name=undefined, active=True, **kwargs):
    key = key or tag_key(tag_ids or name)
    tag = Tag(key=key)
    tag.name = tag_ids[-1]
    tag.parent = key.parent()
    tag.created_by = build_user_key(actor)
    return tag_update(actor, tag=tag, active=True, name=name, **kwargs)
Ejemplo n.º 6
0
def project_create(actor, key=None, client_id=None, project_ids=None, name=undefined, active=True, **kwargs):
    key = key or project_key(client_id, project_ids or name)
    project = Project(key=key)
    project.name = project_ids[-1]
    project.parent = key.parent()
    project.created_by = build_user_key(actor)
    return project_update(actor, project=project, active=True, name=name, **kwargs)
Ejemplo n.º 7
0
def check_out(actor,
              asset=None,
              asset_key=None,
              asset_id=None,
              checked_out_to=undefined,
              project=undefined,
              expected=undefined,
              timezoneoffset=None,
              **ignored):
    asset = asset or get(actor, asset_key=asset_key, asset_id=asset_id)
    if asset.checkout:
        raise IllegalError("Asset is already checked out")

    checkout = AssetCheckout(parent=asset.key)
    checkout.checked_out_by = build_user_key(actor)
    checkout.checked_out_to = build_user_key(actor)
    checkout.condition_out = asset.condition

    if is_defined(expected):
        if expected == "":
            expected = None
        else:
            if timezoneoffset:
                offset = timedelta(minutes=int(timezoneoffset))
                client_time = datetime.utcnow() - offset
                parsed_time = lib.parsedatetime.Calendar().parse(
                    expected, client_time)
            else:
                offset = datetime.timedelta(0)
                parsed_time = lib.parsedatetime.Calendar().parse(expected)

            if parsed_time[1] == 1:
                checkout.expected = datetime(*parsed_time[0][:3]) + offset
            else:
                checkout.expected = datetime(*parsed_time[0][:6]) + offset

    if is_defined(checked_out_to) and checked_out_to:
        checkout.checked_out_to = build_user_key(checked_out_to)
    if is_defined(project) and project: checkout.project = project
    checkout.put()

    asset.checkout = checkout.key
    asset.put()

    return checkout
Ejemplo n.º 8
0
def project_deactivate(actor,
                       client_id=None,
                       project_ids=None,
                       key=None,
                       project=None,
                       **ignored):
    project = project_get(client_id, project_ids, key, project)
    project.updated_by = build_user_key(actor)
    project.active = False
    project.put()
Ejemplo n.º 9
0
def task_create(actor,
                key=None,
                task_ids=None,
                name=undefined,
                active=True,
                **kwargs):
    key = key or task_key(task_ids or name)
    task = Task(key=key)
    task.name = task_ids[-1]
    task.parent = key.parent()
    task.created_by = build_user_key(actor)
    return task_update(actor, task=task, active=True, name=name, **kwargs)
Ejemplo n.º 10
0
def issue_create(actor, key=None, issue_id=None, name=undefined, active=True, **kwargs):
    if "status"   not in kwargs: kwargs["status"]   = "triage"
    if "priority" not in kwargs: kwargs["priority"] = 2
    if "severity" not in kwargs: kwargs["severity"] = 2

    if "reporters" not in kwargs or not kwargs["reporters"]: kwargs["reporters"] = [ actor ]
    if "assignees" not in kwargs or not kwargs["assignees"]: kwargs["assignees"] = [ actor ]
    if "verifiers" not in kwargs or not kwargs["verifiers"]: kwargs["verifiers"] = [ actor ]

    issue = Issue()
    issue.created_by = build_user_key(actor)
    issue.privacy = "public"
    return issue_update(actor, issue=issue, active=True, name=name, **kwargs)
Ejemplo n.º 11
0
def client_update(actor, client_id=None, key=None, client=None, name=undefined, active=undefined, **ignored):
    client = client or (key or client_key(client_id)).get()

    if is_defined(name):
        client.name = name

    if is_defined(active):
        client.active = active

    client.updated_by = build_user_key(actor)
    client.put()

    return to_model(client)
Ejemplo n.º 12
0
def project_update(actor, client_id=None, project_ids=None, key=None, project=None, name=undefined, active=undefined, **ignored):
    project = project or (key or project_key(client_id, project_ids)).get()

    if is_defined(name):
        project.name = name

    if is_defined(active):
        project.active = active

    project.updated_by = build_user_key(actor)
    project.put()

    return to_model(project)
Ejemplo n.º 13
0
def remark_create(actor, target_key, text, subtext=None, blobs=[]):
    remark = Remark(parent=target_key)
    remark.target = target_key
    remark.text = text
    remark.subtext = subtext
    remark.blobs = blobs or []
    remark.created_by = build_user_key(actor)
    remark.put()

    for blob in remark.blobs:
        blob_claim(actor, blob_key=blob, target=remark.key)

    return to_model(actor, remark)
Ejemplo n.º 14
0
def task_update(actor, task_ids=None, key=None, task=None, name=undefined, active=undefined, **ignored):
    task = task or (key or task_key(task_ids)).get()

    if is_defined(name):
        task.name = name

    if is_defined(active):
        task.active = active

    task.updated_by = build_user_key(actor)
    task.put()

    return to_model(task)
Ejemplo n.º 15
0
def tag_update(actor, tag_ids=None, key=None, tag=None, name=undefined, active=undefined, **ignored):
    tag = tag or (key or tag_key(tag_ids)).get()

    if is_defined(name):
        tag.name = name

    if is_defined(active):
        tag.active = active

    tag.updated_by = build_user_key(actor)
    tag.put()

    return to_model(tag)
Ejemplo n.º 16
0
def check_out(actor, asset=None, asset_key=None, asset_id=None, checked_out_to=undefined,
              project=undefined, expected=undefined, timezoneoffset=None, **ignored):
    asset = asset or get(actor, asset_key=asset_key, asset_id=asset_id)
    if asset.checkout:
        raise IllegalError("Asset is already checked out")

    checkout = AssetCheckout(parent=asset.key)
    checkout.checked_out_by = build_user_key(actor)
    checkout.checked_out_to = build_user_key(actor)
    checkout.condition_out = asset.condition

    if is_defined(expected):
        if expected == "":
            expected = None
        else:
            if timezoneoffset:
                offset = timedelta(minutes=int(timezoneoffset))
                client_time = datetime.utcnow() - offset
                parsed_time = lib.parsedatetime.Calendar().parse(expected, client_time)
            else:
                offset = datetime.timedelta(0)
                parsed_time = lib.parsedatetime.Calendar().parse(expected)

            if parsed_time[1] == 1:
                checkout.expected = datetime(*parsed_time[0][:3]) + offset
            else:
                checkout.expected = datetime(*parsed_time[0][:6]) + offset

    if is_defined(checked_out_to) and checked_out_to: checkout.checked_out_to = build_user_key(checked_out_to)
    if is_defined(project) and project:               checkout.project = project
    checkout.put()

    asset.checkout = checkout.key
    asset.put()

    return checkout
Ejemplo n.º 17
0
def tag_apply(viewer, target, tag, **ignored):
    if permission_check(viewer, "tag", "apply") or permission_is_root(viewer):
        key = tag_key(tag)
        if not AppliedTag.query(AppliedTag.tag == key, AppliedTag.target == target, ancestor=target).get():
            new_tag = AppliedTag(parent=target)
            new_tag.applied_by = build_user_key(viewer)
            new_tag.tag = key
            new_tag.target = target
            new_tag.put()
            log.debug("Tag %s applied" % key)
            return "/tags/%s" % "/".join(tag)
        else:
            log.debug("Tag already applied")
    else:
        log.debug("Not allowed")
Ejemplo n.º 18
0
def issue_get(viewer, issue_id=None, key=None, issue=None, silent=False):
    result = issue or (key or issue_key(issue_id)).get()
    if result:
        if result.privacy == "public" or \
                build_user_key(viewer) in result.cc + result.assignees + result.reporters + result.verifiers or \
                permission_is_root(viewer):
            result.history = remark_list(viewer, result.key)
            return result
        elif silent:
            return None
        else:
            raise NotAllowedError()
    elif silent:
        return None
    else:
        raise NotFoundError()
Ejemplo n.º 19
0
def issue_get(viewer, issue_id=None, key=None, issue=None, silent=False):
    result = issue or (key or issue_key(issue_id)).get()
    if result:
        if result.privacy == "public" or \
                build_user_key(viewer) in result.cc + result.assignees + result.reporters + result.verifiers or \
                permission_is_root(viewer):
            result.history = remark_list(viewer, result.key)
            return result
        elif silent:
            return None
        else:
            raise NotAllowedError()
    elif silent:
        return None
    else:
        raise NotFoundError()
Ejemplo n.º 20
0
def project_create(actor,
                   key=None,
                   client_id=None,
                   project_ids=None,
                   name=undefined,
                   active=True,
                   **kwargs):
    key = key or project_key(client_id, project_ids or name)
    project = Project(key=key)
    project.name = project_ids[-1]
    project.parent = key.parent()
    project.created_by = build_user_key(actor)
    return project_update(actor,
                          project=project,
                          active=True,
                          name=name,
                          **kwargs)
Ejemplo n.º 21
0
def check_in(actor, asset=None, asset_key=None, asset_id=None, condition=undefined, **ignored):
    asset = asset or get(actor, asset_key=asset_key, asset_id=asset_id)
    if not asset.checkout:
        raise IllegalError("Asset is not checked out")

    checkout = asset.checkout.get()
    checkout.checked_in_by = build_user_key(actor)
    checkout.checked_in = datetime.now()
    checkout.condition_in = asset.condition

    if is_defined(condition): checkout.condition_in = condition
    checkout.put()

    asset.checkout = None
    asset.condition = checkout.condition_in
    asset.put()

    return checkout
Ejemplo n.º 22
0
def project_update(actor,
                   client_id=None,
                   project_ids=None,
                   key=None,
                   project=None,
                   name=undefined,
                   active=undefined,
                   **ignored):
    project = project or (key or project_key(client_id, project_ids)).get()

    if is_defined(name):
        project.name = name

    if is_defined(active):
        project.active = active

    project.updated_by = build_user_key(actor)
    project.put()

    return to_model(project)
Ejemplo n.º 23
0
def issue_create(actor,
                 key=None,
                 issue_id=None,
                 name=undefined,
                 active=True,
                 **kwargs):
    if "status" not in kwargs: kwargs["status"] = "triage"
    if "priority" not in kwargs: kwargs["priority"] = 2
    if "severity" not in kwargs: kwargs["severity"] = 2

    if "reporters" not in kwargs or not kwargs["reporters"]:
        kwargs["reporters"] = [actor]
    if "assignees" not in kwargs or not kwargs["assignees"]:
        kwargs["assignees"] = [actor]
    if "verifiers" not in kwargs or not kwargs["verifiers"]:
        kwargs["verifiers"] = [actor]

    issue = Issue()
    issue.created_by = build_user_key(actor)
    issue.privacy = "public"
    return issue_update(actor, issue=issue, active=True, name=name, **kwargs)
Ejemplo n.º 24
0
def check_in(actor,
             asset=None,
             asset_key=None,
             asset_id=None,
             condition=undefined,
             **ignored):
    asset = asset or get(actor, asset_key=asset_key, asset_id=asset_id)
    if not asset.checkout:
        raise IllegalError("Asset is not checked out")

    checkout = asset.checkout.get()
    checkout.checked_in_by = build_user_key(actor)
    checkout.checked_in = datetime.now()
    checkout.condition_in = asset.condition

    if is_defined(condition): checkout.condition_in = condition
    checkout.put()

    asset.checkout = None
    asset.condition = checkout.condition_in
    asset.put()

    return checkout
Ejemplo n.º 25
0
def tag_deactivate(actor, tag_ids=None, key=None, tag=None, **ignored):
    tag = tag_get(tag_ids, key, tag)
    tag.updated_by = build_user_key(actor)
    tag.active = False
    tag.put()
Ejemplo n.º 26
0
def issue_update(actor,
                 issue_id=None,
                 key=None,
                 issue=None,
                 summary=undefined,
                 project=undefined,
                 status=undefined,
                 priority=undefined,
                 severity=undefined,
                 reporters=undefined,
                 assignees=undefined,
                 verifiers=undefined,
                 cc=undefined,
                 depends_on=undefined,
                 blocking=undefined,
                 privacy=undefined,
                 due_date=undefined,
                 body="",
                 send_mail=True,
                 blobs=undefined,
                 **args):
    issue = issue or (key or issue_key(issue_id)).get()
    header = ""

    is_root = permission_is_root(actor)

    if not is_root and issue.privacy != "public" and \
            build_user_key(actor) not in issue.cc + issue.assignees + issue.reporters + issue.verifiers:
        raise NotAllowedError()

    blob_list = None
    to_recipients = set([])
    if issue.assignees:
        to_recipients.update(issue.assignees)
    if issue.reporters:
        to_recipients.update(issue.reporters)
    if issue.verifiers:
        to_recipients.update(issue.verifiers)

    cc_recipients = set(issue.cc)

    if is_root or issue.privacy != "secure" or build_user_key(
            actor) in issue.assignees + issue.verifiers:
        # Rewrite input types if necessary
        def fix_users(field):
            log.debug(field)
            if is_undefined(field):
                return undefined
            if not field:
                return undefined
            if isinstance(field, basestring):
                return set([
                    build_user_key(id) for id in re.split("[\\s,;]+", field)
                    if len(id) > 0
                ])
            return [build_user_key(user) for user in field]

        reporters = fix_users(reporters)
        assignees = fix_users(assignees)
        verifiers = fix_users(verifiers)
        cc = fix_users(cc)

        if is_defined(depends_on):
            depends_on = set([
                issue_key(id) for id in re.split("[\\s,;]+", depends_on)
                if len(id) > 0
            ])

        if is_defined(blocking):
            blocking = set([
                issue_key(id) for id in re.split("[\\s,;]+", blocking)
                if len(id) > 0
            ])

        if is_defined(due_date):
            if due_date == "":
                due_date = None
            else:
                if "timezoneoffset" in args:
                    offset = datetime.timedelta(
                        minutes=int(args["timezoneoffset"]))
                    client_time = datetime.datetime.utcnow() - offset
                    parsed_time = lib.parsedatetime.Calendar().parse(
                        due_date, client_time)
                    log.debug("client_time = %s" % client_time)
                else:
                    offset = datetime.timedelta(0)
                    parsed_time = lib.parsedatetime.Calendar().parse(due_date)

                if parsed_time[1] == 1:
                    due_date = datetime.datetime(*parsed_time[0][:3]) + offset
                else:
                    due_date = datetime.datetime(*parsed_time[0][:6]) + offset

        # Update all fields
        if is_defined(summary) and summary != issue.summary:
            header = header + "**Summary:** " + summary + "  \n"
            issue.summary = summary
            issue.summary_index = set(re.split("[^\\w\\d]+", summary.lower()))

        if is_defined(project) and project != issue.project:
            header = header + "**Project:** " + project + "  \n"
            issue.project = project

        if is_defined(status) and status != issue.status:
            if not status in issue_transitions:
                raise IllegalError("Status not recognized")
            if not status in issue_transitions[issue.status]:
                raise IllegalError("Status transition not allowed")
            header = header + "**Status:** " + status + "  \n"
            issue.status = status

        if is_defined(priority) and int(priority) != issue.priority:
            header = header + "**Priority:** " + str(priority) + "  \n"
            issue.priority = int(priority)

        if is_defined(severity) and int(severity) != issue.severity:
            header = header + "**Severity:** " + str(severity) + "  \n"
            issue.severity = int(severity)

        if is_defined(reporters) and reporters != set(issue.reporters):
            log.debug("Reporters: %s" % reporters)
            header = header + "**Reporters:** " + ", ".join(
                [user.id() for user in reporters]) + "  \n"
            issue.reporters = reporters

        if is_defined(assignees) and assignees != set(issue.assignees):
            header = header + "**Assignees:** " + ", ".join(
                [user.id() for user in assignees]) + "  \n"
            issue.assignees = assignees

        if is_defined(verifiers) and verifiers != set(issue.verifiers):
            header = header + "**Verifiers:** " + ", ".join(
                [user.id() for user in verifiers]) + "  \n"
            issue.verifiers = verifiers

        if is_defined(cc) and cc != set(issue.cc):
            header = header + "**CC:** " + ", ".join(
                [user.id() for user in cc]) + "  \n"
            issue.cc = list(cc)

        if is_defined(depends_on) and depends_on != set(issue.depends_on):
            header = header + "**Depends On:** " + ", ".join(
                [str(iss.id()) for iss in depends_on]) + "  \n"
            issue.depends_on = list(depends_on)

        if is_defined(blocking) and blocking != set(issue.blocking):
            header = header + "**Blocking:** " + ", ".join(
                [str(iss.id()) for iss in blocking]) + "  \n"
            issue.blocking = list(blocking)

        if is_defined(privacy) and privacy != issue.privacy:
            header = header + "**Privacy:** " + privacy + "  \n"
            issue.privacy = privacy

        if is_defined(due_date) and due_date != issue.due_date:
            header = header + "**Due Date:** " + str(due_date) + " UTC  \n"
            issue.due_date = due_date

        if is_defined(blobs) and blobs:
            blob_list = build_blob_keys(blobs)
            header = header + "**Attachments:** %s File(s)  \n" % len(
                blob_list)

        # Fix up missing stuff

        if not issue.reporters: issue.reporters = [build_user_key(actor)]
        if not issue.verifiers: issue.verifiers = [build_user_key(actor)]
        if not issue.assignees: issue.assignees = [build_user_key(actor)]

        to_recipients.update(issue.assignees)
        to_recipients.update(issue.reporters)
        to_recipients.update(issue.verifiers)
        cc_recipients.update(issue.cc)

    issue.score, issue.score_description = calculate_issue_score(issue)

    issue.text_index = set(issue.text_index) | \
                       set(issue.summary_index) | \
                       set(re.split("[^\\w\\d]+", body.lower()))

    issue.updated_by = build_user_key(actor)
    issue.put()

    issue.history = [
        remark_create(actor,
                      issue.key,
                      body.strip(),
                      header.strip(),
                      blobs=blob_list)
    ]

    if send_mail:
        settings = get_system_settings()
        if "host" in settings and settings["host"] and settings["host"] != "":
            host = settings["host"]
        else:
            host = "%s.appspot.com" % app_identity.get_application_id()
        message_id = "<issue-%s@%s>" % (issue.key.id(),
                                        app_identity.get_application_id())
        url = "http://%s/issues/%s" % (host, issue.key.id())
        text = "%s\n\n%s\n\n%s" % (header, body, url)
        html = "<div style='font-size: 0.8em'>%s</div><div>%s</div><div>%s</div>" % \
                    (lib.markdown.markdown(header), lib.markdown.markdown(body), url)
        try:
            if len(cc_recipients) > 0:
                mail.send_mail(sender=actor.user.email(),
                               to=[user.id() for user in to_recipients],
                               cc=[user.id() for user in cc_recipients],
                               reply_to=actor.user.email(),
                               subject="[" + str(issue.key.id()) + "] " +
                               issue.summary,
                               body=text,
                               html=html,
                               headers={
                                   "In-Reply-To": message_id,
                                   "References": message_id
                               })
            else:
                mail.send_mail(sender=actor.user.email(),
                               to=[user.id() for user in to_recipients],
                               reply_to=actor.user.email(),
                               subject="[" + str(issue.key.id()) + "] " +
                               issue.summary,
                               body=text,
                               html=html,
                               headers={
                                   "In-Reply-To": message_id,
                                   "References": message_id
                               })
            log.debug("Email sent to %s" % (to_recipients | cc_recipients))
        except:
            log.warn("Email quota exceeded, email not sent")
        log.debug(text)

    return to_model(actor, issue)
Ejemplo n.º 27
0
def complex_search_to_ndb_query(query):
    if not query:
        return None, None

    sort_order = None
    phrases = []
    for phrase in query["sub"]:
        if "boolean" in phrase:
            new_phrase, new_order = complex_search_to_ndb_query(phrase)
            if new_phrase:
                phrases.append(new_phrase)
                sort_order = sort_order or new_order
        elif phrase["field"] == "text":
            pass
        else:
            if phrase["field"] in ["priority", "severity"]:
                values = [int(value) for value in phrase["value"]]
            elif phrase["field"] in ["created", "updated"]:
                values = []
            elif phrase["field"] in [
                    "updated_by", "created_by", "assignees", "reporters",
                    "verifiers", "cc"
            ]:
                values = [build_user_key(value) for value in phrase["value"]]
            elif phrase["field"] in ["summary_index", "text_index"]:
                values = [value.lower() for value in phrase["value"]]
            else:
                values = phrase["value"]

            field = getattr(Issue, phrase["field"])
            subphrases = []
            if phrase["operator"] == "=" or phrase[
                    "operator"] == "==" or phrase["operator"] == "in":
                for value in values:
                    subphrases.append(field == value)
                if len(subphrases) > 0:
                    phrases.append(ndb.OR(*subphrases))

            elif phrase["operator"] == "!=":
                sort_order = field
                for value in values:
                    subphrases.append(field != value)
                if len(subphrases) > 0:
                    phrases.append(ndb.AND(*subphrases))

            elif phrase["operator"] == ">":
                sort_order = field
                for value in values:
                    subphrases.append(field > value)
                if len(subphrases) > 0:
                    phrases.append(ndb.AND(*subphrases))

            elif phrase["operator"] == ">=":
                sort_order = field
                for value in values:
                    subphrases.append(field >= value)
                if len(subphrases) > 0:
                    phrases.append(ndb.AND(*subphrases))

            elif phrase["operator"] == "<":
                sort_order = field
                for value in values:
                    subphrases.append(field < value)
                if len(subphrases) > 0:
                    phrases.append(ndb.AND(*subphrases))

            elif phrase["operator"] == "<=":
                sort_order = field
                for value in values:
                    subphrases.append(field <= value)
                if len(subphrases) > 0:
                    phrases.append(ndb.AND(*subphrases))

    if len(phrases) > 0:
        if query["boolean"] == "or":
            return ndb.OR(*phrases), sort_order
        else:
            return ndb.AND(*phrases), sort_order
    else:
        return None, None
Ejemplo n.º 28
0
def issue_search(viewer, simple=None, query=None, complex=None):
    permission_verify(viewer, "issue", "read")

    if not complex:
        if query:
            complex = query_to_complex_search(query)
        else:
            # Status is open and assigned to me, or closing and verified by me.
            complex = {
                "boolean":
                "or",
                "sub": [{
                    "boolean":
                    "and",
                    "sub": [{
                        "field": "status",
                        "operator": "in",
                        "value": ["triage", "assigned", "working"]
                    }, {
                        "field": "assignees",
                        "operator": "==",
                        "value": [viewer]
                    }]
                }, {
                    "boolean":
                    "and",
                    "sub": [{
                        "field": "status",
                        "operator": "in",
                        "value": ["fixed", "rejected"]
                    }, {
                        "field": "verifiers",
                        "operator": "==",
                        "value": [viewer]
                    }]
                }]
            }

    result = []
    ndb_query, first_sort = complex_search_to_ndb_query(complex)
    if permission_is_root(viewer):
        if ndb_query:
            dataset = Issue.query().filter(ndb_query)
        else:
            dataset = Issue.query().filter()
    else:
        privacy_query = ndb.OR(Issue.privacy == "public",
                               Issue.assignees == build_user_key(viewer),
                               Issue.reporters == build_user_key(viewer),
                               Issue.verifiers == build_user_key(viewer),
                               Issue.cc == build_user_key(viewer))
        if ndb_query:
            dataset = Issue.query().filter(ndb.AND(ndb_query, privacy_query))
        else:
            dataset = Issue.query().filter(privacy_query)

    if first_sort:
        dataset = dataset.order(first_sort)
    else:
        dataset = dataset.order(-Issue.score, -Issue.created)

    for issue in dataset:
        issue.history = []
        result.append(to_model(viewer, issue))

    return result
Ejemplo n.º 29
0
def issue_deactivate(actor, issue_id=None, key=None, issue=None, **ignored):
    issue = issue_get(actor, issue_id, key, issue)
    issue.updated_by = build_user_key(actor)
    issue.active = False
    issue.put()
Ejemplo n.º 30
0
def create(actor, asset_id=None, asset_key=None, **kwargs):
    asset = Asset(key=asset_key or key(asset_id))
    asset.created_by = build_user_key(actor)
    asset.condition = "new"
    return update(actor, asset=asset, **kwargs)
Ejemplo n.º 31
0
def client_deactivate(actor, client_id=None, key=None, client=None, **ignored):
    client = client_get(client_id, key, client)
    client.updated_by = build_user_key(actor)
    client.active = False
    client.put()
Ejemplo n.º 32
0
def complex_search_to_ndb_query(query):
    if not query:
        return None, None

    sort_order = None
    phrases = []
    for phrase in query["sub"]:
        if "boolean" in phrase:
            new_phrase, new_order = complex_search_to_ndb_query(phrase)
            if new_phrase:
                phrases.append(new_phrase)
                sort_order = sort_order or new_order
        elif phrase["field"] == "text":
            pass
        else:
            if phrase["field"] in [ "priority", "severity" ]:
                values = [ int(value) for value in phrase["value"] ]
            elif phrase["field"] in [ "created", "updated" ]:
                values = []
            elif phrase["field"] in [ "updated_by", "created_by", "assignees", "reporters", "verifiers", "cc" ]:
                values = [ build_user_key(value) for value in phrase["value"] ]
            elif phrase["field"] in [ "summary_index", "text_index" ]:
                values = [ value.lower() for value in phrase["value"] ]
            else:
                values = phrase["value"]

            field = getattr(Issue, phrase["field"])
            subphrases = []
            if phrase["operator"] == "=" or phrase["operator"] == "==" or phrase["operator"] == "in":
                for value in values:
                    subphrases.append(field == value)
                if len(subphrases) > 0:
                    phrases.append(ndb.OR(*subphrases))

            elif phrase["operator"] == "!=":
                sort_order = field
                for value in values:
                    subphrases.append(field != value)
                if len(subphrases) > 0:
                    phrases.append(ndb.AND(*subphrases))

            elif phrase["operator"] == ">":
                sort_order = field
                for value in values:
                    subphrases.append(field > value)
                if len(subphrases) > 0:
                    phrases.append(ndb.AND(*subphrases))

            elif phrase["operator"] == ">=":
                sort_order = field
                for value in values:
                    subphrases.append(field >= value)
                if len(subphrases) > 0:
                    phrases.append(ndb.AND(*subphrases))

            elif phrase["operator"] == "<":
                sort_order = field
                for value in values:
                    subphrases.append(field < value)
                if len(subphrases) > 0:
                    phrases.append(ndb.AND(*subphrases))

            elif phrase["operator"] == "<=":
                sort_order = field
                for value in values:
                    subphrases.append(field <= value)
                if len(subphrases) > 0:
                    phrases.append(ndb.AND(*subphrases))

    if len(phrases) > 0:
        if query["boolean"] == "or":
            return ndb.OR(*phrases), sort_order
        else:
            return ndb.AND(*phrases), sort_order
    else:
        return None, None
Ejemplo n.º 33
0
def task_deactivate(actor, task_ids=None, key=None, task=None, **ignored):
    task = task_get(task_ids, key, task)
    task.updated_by = build_user_key(actor)
    task.active = False
    task.put()
Ejemplo n.º 34
0
def task_deactivate(actor, task_ids=None, key=None, task=None, **ignored):
    task = task_get(task_ids, key, task)
    task.updated_by = build_user_key(actor)
    task.active = False
    task.put()
Ejemplo n.º 35
0
def issue_deactivate(actor, issue_id=None, key=None, issue=None, **ignored):
    issue = issue_get(actor, issue_id, key, issue)
    issue.updated_by = build_user_key(actor)
    issue.active = False
    issue.put()
Ejemplo n.º 36
0
def client_create(actor, key=None, client_id=None, name=undefined, active=True, **kwargs):
    key = key or client_key(client_id or name)
    client = Client(key=key)
    client.name = client_id
    client.created_by = build_user_key(actor)
    return client_update(actor, client=client, active=True, name=name, **kwargs)
Ejemplo n.º 37
0
def create(actor, asset_id=None, asset_key=None, **kwargs):
    asset = Asset(key=asset_key or key(asset_id))
    asset.created_by = build_user_key(actor)
    asset.condition = "new"
    return update(actor, asset=asset, **kwargs)
Ejemplo n.º 38
0
def project_deactivate(actor, client_id=None, project_ids=None, key=None, project=None, **ignored):
    project = project_get(client_id, project_ids, key, project)
    project.updated_by = build_user_key(actor)
    project.active = False
    project.put()
Ejemplo n.º 39
0
def issue_update(actor, issue_id=None, key=None, issue=None, summary=undefined, project=undefined, 
                 status=undefined, priority=undefined, severity=undefined, reporters=undefined, 
                 assignees=undefined, verifiers=undefined, cc=undefined, depends_on=undefined, 
                 blocking=undefined, privacy=undefined, due_date=undefined, body="", send_mail=True, 
                 blobs=undefined, **args):
    issue = issue or (key or issue_key(issue_id)).get()
    header = ""

    is_root = permission_is_root(actor)

    if not is_root and issue.privacy != "public" and \
            build_user_key(actor) not in issue.cc + issue.assignees + issue.reporters + issue.verifiers:
        raise NotAllowedError()

    blob_list = None
    to_recipients = set([])
    if issue.assignees:
        to_recipients.update(issue.assignees)
    if issue.reporters:
        to_recipients.update(issue.reporters)
    if issue.verifiers:
        to_recipients.update(issue.verifiers)

    cc_recipients = set(issue.cc)

    if is_root or issue.privacy != "secure" or build_user_key(actor) in issue.assignees + issue.verifiers:
        # Rewrite input types if necessary
        def fix_users(field):
            log.debug(field)
            if is_undefined(field):
                return undefined
            if not field:
                return undefined
            if isinstance(field, basestring):
                return set([build_user_key(id) for id in re.split("[\\s,;]+", field) if len(id) > 0])
            return [build_user_key(user) for user in field]
    
        reporters = fix_users(reporters)
        assignees = fix_users(assignees)
        verifiers = fix_users(verifiers)
        cc = fix_users(cc)

        if is_defined(depends_on):
            depends_on = set([issue_key(id) for id in re.split("[\\s,;]+", depends_on) if len(id) > 0])
    
        if is_defined(blocking):
            blocking = set([issue_key(id) for id in re.split("[\\s,;]+", blocking) if len(id) > 0])

        if is_defined(due_date):
            if due_date == "":
                due_date = None
            else:
                if "timezoneoffset" in args:
                    offset = datetime.timedelta(minutes=int(args["timezoneoffset"]))
                    client_time = datetime.datetime.utcnow() - offset
                    parsed_time = lib.parsedatetime.Calendar().parse(due_date, client_time)
                    log.debug("client_time = %s" % client_time)
                else:
                    offset = datetime.timedelta(0)
                    parsed_time = lib.parsedatetime.Calendar().parse(due_date)

                if parsed_time[1] == 1:
                    due_date = datetime.datetime(*parsed_time[0][:3]) + offset
                else:
                    due_date = datetime.datetime(*parsed_time[0][:6]) + offset

        # Update all fields
        if is_defined(summary) and summary != issue.summary:
            header = header + "**Summary:** " + summary + "  \n"
            issue.summary = summary
            issue.summary_index = set(re.split("[^\\w\\d]+", summary.lower()))
    
        if is_defined(project) and project != issue.project:
            header = header + "**Project:** " + project + "  \n"
            issue.project = project

        if is_defined(status) and status != issue.status:
            if not status in issue_transitions:
                raise IllegalError("Status not recognized")
            if not status in issue_transitions[issue.status]:
                raise IllegalError("Status transition not allowed")
            header = header + "**Status:** " + status + "  \n"
            issue.status = status
    
        if is_defined(priority) and int(priority) != issue.priority:
            header = header + "**Priority:** " + str(priority) + "  \n"
            issue.priority = int(priority)
    
        if is_defined(severity) and int(severity) != issue.severity:
            header = header + "**Severity:** " + str(severity) + "  \n"
            issue.severity = int(severity)
    
        if is_defined(reporters) and reporters != set(issue.reporters):
            log.debug("Reporters: %s" % reporters)
            header = header + "**Reporters:** " + ", ".join([user.id() for user in reporters]) + "  \n"
            issue.reporters = reporters
    
        if is_defined(assignees) and assignees != set(issue.assignees):
            header = header + "**Assignees:** " + ", ".join([user.id() for user in assignees]) + "  \n"
            issue.assignees = assignees
    
        if is_defined(verifiers) and verifiers != set(issue.verifiers):
            header = header + "**Verifiers:** " + ", ".join([user.id() for user in verifiers]) + "  \n"
            issue.verifiers = verifiers
    
        if is_defined(cc) and cc != set(issue.cc):
            header = header + "**CC:** " + ", ".join([user.id() for user in cc]) + "  \n"
            issue.cc = list(cc)
    
        if is_defined(depends_on) and depends_on != set(issue.depends_on):
            header = header + "**Depends On:** " + ", ".join([str(iss.id()) for iss in depends_on]) + "  \n"
            issue.depends_on = list(depends_on)
    
        if is_defined(blocking) and blocking != set(issue.blocking):
            header = header + "**Blocking:** " + ", ".join([str(iss.id()) for iss in blocking]) + "  \n"
            issue.blocking = list(blocking)
    
        if is_defined(privacy) and privacy != issue.privacy:
            header = header + "**Privacy:** " + privacy + "  \n"
            issue.privacy = privacy

        if is_defined(due_date) and due_date != issue.due_date:
            header = header + "**Due Date:** " + str(due_date) + " UTC  \n"
            issue.due_date = due_date

        if is_defined(blobs) and blobs:
            blob_list = build_blob_keys(blobs)
            header = header + "**Attachments:** %s File(s)  \n" % len(blob_list)

        # Fix up missing stuff

        if not issue.reporters: issue.reporters = [ build_user_key(actor) ]
        if not issue.verifiers: issue.verifiers = [ build_user_key(actor) ]
        if not issue.assignees: issue.assignees = [ build_user_key(actor) ]

        to_recipients.update(issue.assignees)
        to_recipients.update(issue.reporters)
        to_recipients.update(issue.verifiers)
        cc_recipients.update(issue.cc)

    issue.score, issue.score_description = calculate_issue_score(issue)

    issue.text_index = set(issue.text_index) | \
                       set(issue.summary_index) | \
                       set(re.split("[^\\w\\d]+", body.lower()))

    issue.updated_by = build_user_key(actor)
    issue.put()

    issue.history = [ remark_create(actor, issue.key, body.strip(), header.strip(), blobs=blob_list) ]

    if send_mail:
        settings = get_system_settings()
        if "host" in settings and settings["host"] and settings["host"] != "":
            host = settings["host"]
        else:
            host = "%s.appspot.com" % app_identity.get_application_id()
        message_id = "<issue-%s@%s>" % (issue.key.id(), app_identity.get_application_id())
        url = "http://%s/issues/%s" % (host, issue.key.id())
        text = "%s\n\n%s\n\n%s" % (header, body, url)
        html = "<div style='font-size: 0.8em'>%s</div><div>%s</div><div>%s</div>" % \
                    (lib.markdown.markdown(header), lib.markdown.markdown(body), url)
        try:
            if len(cc_recipients) > 0:
                mail.send_mail(sender=actor.user.email(),
                               to=[user.id() for user in to_recipients],
                               cc=[user.id() for user in cc_recipients],
                               reply_to=actor.user.email(),
                               subject="[" + str(issue.key.id()) + "] " + issue.summary,
                               body=text,
                               html=html,
                               headers={"In-Reply-To": message_id, "References":  message_id })
            else:
                mail.send_mail(sender=actor.user.email(),
                               to=[user.id() for user in to_recipients],
                               reply_to=actor.user.email(),
                               subject="[" + str(issue.key.id()) + "] " + issue.summary,
                               body=text,
                               html=html,
                               headers={"In-Reply-To": message_id, "References":  message_id })
            log.debug("Email sent to %s" % (to_recipients | cc_recipients))
        except:
            log.warn("Email quota exceeded, email not sent")
        log.debug(text)

    return to_model(actor, issue)