Skip to content
This repository has been archived by the owner on Feb 23, 2022. It is now read-only.

Commit

Permalink
Merge pull request #422 from multinet-app/user-search
Browse files Browse the repository at this point in the history
  • Loading branch information
jjnesbitt committed Jul 30, 2020
2 parents 2640898 + f116cd2 commit b786307
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 3 deletions.
15 changes: 15 additions & 0 deletions multinet/auth/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@
from flask.blueprints import Blueprint
import json
from werkzeug.wrappers import Response as ResponseWrapper
from webargs import fields
from webargs.flaskparser import use_kwargs

from multinet.user import (
MULTINET_COOKIE,
user_from_cookie,
filtered_user,
delete_user_cookie,
search_user,
)

from multinet.util import stream
from multinet.auth.util import require_login

bp = Blueprint("user", "user")


Expand Down Expand Up @@ -49,3 +55,12 @@ def logout() -> ResponseWrapper:
delete_user_cookie(user)

return make_response("", 200)


@bp.route("/search", methods=["GET"])
@require_login
@use_kwargs({"query": fields.Str()})
@swag_from("swagger/user/search.yaml")
def search(query: str) -> ResponseWrapper:
"""Search for users given a partial string."""
return stream(search_user(query))
17 changes: 17 additions & 0 deletions multinet/auth/swagger/user/search.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Search for users
---
consumes:
- text/plain
parameters:
- name: query
description: Query to search for users with
in: query

responses:
200:
description: List of matching users
401:
description: Not logged in

tags:
- user
6 changes: 4 additions & 2 deletions multinet/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,10 +453,12 @@ def delete_table(workspace: str, table: str) -> str:
return table


def _run_aql_query(aql: AQL, query: str) -> Cursor:
def _run_aql_query(
aql: AQL, query: str, bind_vars: Optional[Dict[str, Any]] = None
) -> Cursor:
try:
aql.validate(query)
cursor = aql.execute(query)
cursor = aql.execute(query, bind_vars=bind_vars)
except AQLQueryValidateError as e:
raise AQLValidationError(str(e))
except AQLQueryExecuteError as e:
Expand Down
22 changes: 21 additions & 1 deletion multinet/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
import dataclasses
from uuid import uuid4
from arango.collection import StandardCollection
from arango.cursor import Cursor
from dacite import from_dict
from flask import session

from multinet.db import db
from multinet.db import db, read_only_db, _run_aql_query
from multinet.errors import InternalServerError
from multinet.auth.types import (
GoogleUserInfo,
Expand Down Expand Up @@ -137,3 +138,22 @@ def filtered_user(user: User) -> FilteredUser:
def copy_user(user: User) -> User:
"""Create and return a new instance of User."""
return from_dict(User, dataclasses.asdict(user))


def search_user(query: str) -> Cursor:
"""Search for users given a partial string."""

coll = user_collection()
aql = read_only_db("_system").aql

bind_vars = {"@users": coll.name, "query": query}
query = """
FOR doc in @@users
FILTER CONTAINS(LOWER(doc.name), LOWER(@query))
OR CONTAINS(LOWER(doc.email), LOWER(@query))
LIMIT 50
RETURN doc
"""

return _run_aql_query(aql, query, bind_vars)
2 changes: 2 additions & 0 deletions mypy_stubs/arango/collection.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class Collection:
def random(self) -> Dict: ...

class StandardCollection(Collection):
name: str

def insert(
self,
document: Any,
Expand Down

0 comments on commit b786307

Please sign in to comment.