Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
353 changes: 144 additions & 209 deletions api/resources/api_manager.py

Large diffs are not rendered by default.

103 changes: 57 additions & 46 deletions api/resources/gene_annotation.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from flask_restx import Namespace, Resource
from markupsafe import escape
from sqlalchemy.exc import OperationalError
from api.models.eplant_poplar import GeneAnnotation as eplant_poplar_annotation
from api.models.eplant_tomato import GeneAnnotation as eplant_tomato_annotation
from api.models.eplant_poplar import GeneAnnotation as EplantPoplarAnnotation
from api.models.eplant_tomato import GeneAnnotation as EplantTomatoAnnotation
from api.models.eplant2 import AgiAnnotation, TAIR10, GeneRIFs
from api.utils.bar_utils import BARUtils

Expand All @@ -20,71 +20,82 @@ def get(self, query=""):
Endpoint returns gene locus for given gene keywords
"""
annotation_db_list = {
"tomato": eplant_tomato_annotation,
"poplar": eplant_poplar_annotation,
"tomato": EplantTomatoAnnotation,
"poplar": EplantPoplarAnnotation,
"arabidopsis": [AgiAnnotation, TAIR10, GeneRIFs],
}

query = escape(query)

res = []
for species, db in annotation_db_list.items():
try:
if species == "arabidopsis":

if species == "arabidopsis":
try:
agi_info = AgiAnnotation.query.filter(
AgiAnnotation.annotation.op("regexp")(query)
).all()

tair10_curator_info = TAIR10.query.filter(
TAIR10.Curator_summary.op("regexp")(query)
).all()

tair10_computational_info = TAIR10.query.filter(
TAIR10.Computational_description.op("regexp")(query)
).all()

RIFs_info = GeneRIFs.query.filter(
GeneRIFs.RIF.op("regexp")(query)
).all()

res += [
{
"gene": i.agi,
"species": species,
"gene_annotation": i.annotation,
}
for i in agi_info
]
res += [
{
"gene": i.Model_name,
"species": species,
"gene_annotation": i.Curator_summary,
}
for i in tair10_curator_info
]
res += [
{
"gene": i.Model_name,
"species": species,
"gene_annotation": i.Computational_description,
}
for i in tair10_computational_info
]
res += [
{"gene": i.gene, "species": species, "gene_annotation": i.RIF}
for i in RIFs_info
]
else:
except OperationalError:
return BARUtils.error_exit("An internal error has occurred"), 500

res += [
{
"gene": i.agi,
"species": species,
"gene_annotation": i.annotation,
}
for i in agi_info
]

res += [
{
"gene": i.Model_name,
"species": species,
"gene_annotation": i.Curator_summary,
}
for i in tair10_curator_info
]

res += [
{
"gene": i.Model_name,
"species": species,
"gene_annotation": i.Computational_description,
}
for i in tair10_computational_info
]

res += [
{"gene": i.gene, "species": species, "gene_annotation": i.RIF}
for i in RIFs_info
]

else:
try:
rows = db.query.filter(db.annotation.op("regexp")(query)).all()
res += [
{
"gene": i.gene,
"species": species,
"gene_annotation": i.annotation,
}
for i in rows
]
except OperationalError:
return BARUtils.error_exit("An internal error has occurred"), 500
except OperationalError:
return BARUtils.error_exit("An internal error has occurred"), 500

res += [
{
"gene": i.gene,
"species": species,
"gene_annotation": i.annotation,
}
for i in rows
]

if len(res) == 0:
return (
Expand Down
85 changes: 12 additions & 73 deletions api/resources/summarization_gene_expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import json as jsonlib
import tempfile
import os
import re
import pandas
from api import summarization_db as db
from api import limiter
Expand All @@ -14,6 +13,9 @@
from sqlalchemy.inspection import inspect
from scour.scour import scourString
from cryptography.fernet import Fernet
from api.utils.summarization_gene_expression_utils import (
SummarizationGeneExpressionUtils,
)


DATA_FOLDER = "/home/bpereira/data/summarization-data"
Expand All @@ -33,73 +35,6 @@
)


class SummarizationGeneExpressionUtils:
@staticmethod
def get_table_object(table_name):
metadata = db.MetaData()
table_object = db.Table(
table_name,
metadata,
autoload=True,
autoload_with=db.get_engine(bind="summarization"),
)
return table_object

@staticmethod
def is_valid(string):
"""Checks if a given string only contains alphanumeric characters
:param string: The string to be checked
"""
if re.search(r"([^_0-9A-Za-z])+", string):
return False
else:
return True

@staticmethod
def validate_api_key(key):
"""Checks if a given API key is in the Users database
:param key: The API key to be checked
"""
tbl = SummarizationGeneExpressionUtils.get_table_object("users")
con = db.get_engine(bind="summarization")
try:
row = con.execute(
db.select([tbl.c.uses_left]).where(tbl.c.api_key == key)
).first()
except SQLAlchemyError as e:
error = str(e.__dict__["orig"])
return error
if row is None:
return False
else:
if row.uses_left > 0:
return True
else:
return False

@staticmethod
def decrement_uses(key):
"""Subtracts 1 from the uses_left column of the user whose key matches the given string
:param key: The user's API key
"""
if SummarizationGeneExpressionUtils.validate_api_key(key):
tbl = SummarizationGeneExpressionUtils.get_table_object("users")
con = db.get_engine(bind="summarization")
try:
con.execute(
db.update(tbl)
.where(tbl.c.api_key == key)
.values(uses_left=(tbl.c.uses_left - 1))
)
db.session.commit()
except SQLAlchemyError as e:
error = str(e.__dict__["orig"])
return error
return True
else:
return False


@summarization_gene_expression.route("/summarize", methods=["POST"])
class SummarizationGeneExpressionSummarize(Resource):
decorators = [
Expand Down Expand Up @@ -340,7 +275,11 @@ def post(self):
db_id = request.get_json()["uid"]
df = pandas.read_csv(csv)
db_id = db_id.split(".")[0]
df = df.melt(id_vars=["data_probeset_id"], var_name="data_bot_id", value_name="data_signal")
df = df.melt(
id_vars=["data_probeset_id"],
var_name="data_bot_id",
value_name="data_signal",
)
db_id = db_id.split("/")[len(db_id.split("/")) - 1]
con = db.get_engine(bind="summarization")
df.to_sql(db_id, con, if_exists="append", index=True)
Expand Down Expand Up @@ -372,7 +311,9 @@ def get(self, table_id, sample, gene):
values = {}
try:
rows = con.execute(
tbl.select(tbl.c.data_signal).where(tbl.c.data_probeset_id == gene)
tbl.select(tbl.c.data_signal).where(
tbl.c.data_probeset_id == gene
)
)
except SQLAlchemyError:
return BARUtils.error_exit("Internal server error"), 500
Expand Down Expand Up @@ -494,9 +435,7 @@ def post(self):
else:
return BARUtils.error_exit("Invalid file type"), 400
dirName = os.path.join(DATA_FOLDER, api_key)
filename = os.path.join(
dirName, file.filename + extension
)
filename = os.path.join(dirName, file.filename + extension)
if not os.path.exists(dirName):
os.makedirs(dirName)
file.save(filename)
Expand Down
86 changes: 86 additions & 0 deletions api/utils/api_manager_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import os
import requests
from cryptography.fernet import Fernet
from smtplib import SMTP_SSL
from ssl import create_default_context
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

CAPTCHA_KEY_FILE = "/home/bpereira/data/bar.summarization/key"


class ApiManagerUtils:
@staticmethod
def check_admin_pass(password):
# Replace below with key from script in /home/bpereira/dev/pw-key
key = os.environ.get("ADMIN_ENCRYPT_KEY")
cipher_suite = Fernet(key)

with open(os.environ.get("ADMIN_PASSWORD_FILE"), "rb") as f:
for line in f:
encrypted_key = line

decipher_text = cipher_suite.decrypt(encrypted_key)
plain_text_encrypted_password = bytes(decipher_text).decode("utf-8")

if password == plain_text_encrypted_password:
return True
else:
return False

@staticmethod
def validate_captcha(value):
"""Validates a reCaptcha value using our secret token"""
if os.environ.get("BAR"):
with open(CAPTCHA_KEY_FILE, "rb") as f:
for line in f:
key = line

if key:
ret = requests.post(
"https://www.google.com/recaptcha/api/siteverify",
data={"secret": key, "response": value},
)
return ret.json()["success"]
else:
return False
else:
return True

@staticmethod
def send_email_notification():
if os.environ.get("BAR"):
with open(os.environ.get("ADMIN_EMAIL"), "r") as f:
for line in f:
recipient = line

port = 465
key = os.environ.get("EMAIL_PASS_KEY")
cipher_suite = Fernet(key)

with open(os.environ.get("EMAIL_PASS_FILE"), "rb") as f:
for line in f:
encrypted_key = line

decipher_text = cipher_suite.decrypt(encrypted_key)
password = bytes(decipher_text).decode("utf-8")
context = create_default_context()
smtp_server = "smtp.gmail.com"

sender_email = "bar.summarization@gmail.com"
subject = "[Bio-Analytic Resource] New API key request"
text = """\
There is a new API key request.
You can approve or reject it at http://bar.utoronto.ca/~bpereira/webservices/bar-request-manager/build/index.html
"""

m_text = MIMEText(text, _subtype="plain", _charset="UTF-8")
msg = MIMEMultipart()
msg["From"] = sender_email
msg["To"] = recipient
msg["Subject"] = subject
msg.attach(m_text)

with SMTP_SSL(smtp_server, port, context=context) as server:
server.login("bar.summarization@gmail.com", password)
server.sendmail(sender_email, recipient, msg.as_string())
Loading