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
6 changes: 3 additions & 3 deletions api/resources/api_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ def check_admin_pass(password):
@staticmethod
def validate_captcha(value):
"""Validates a reCaptcha value using our secret token"""
if(os.environ.get("BAR")):
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}
data={"secret": key, "response": value},
)
return ret.json()["success"]
else:
Expand Down Expand Up @@ -128,7 +128,7 @@ class ApiManagerRequest(Resource):
def post(self):
if request.method == "POST":
captchaVal = request.headers.get("captchaVal")
if(ApiManagerUtils.validate_captcha(captchaVal)):
if ApiManagerUtils.validate_captcha(captchaVal):
response_json = request.get_json()
df = pandas.DataFrame.from_records([response_json])
con = db.get_engine(bind="summarization")
Expand Down
65 changes: 27 additions & 38 deletions api/resources/efp_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
import re
import requests
import random
import redis.connection
import os
import time
import redis.exceptions
from flask_restx import Namespace, Resource
from markupsafe import escape
from flask import send_from_directory
from api.utils.bar_utils import BARUtils
from api.utils.efp_utils import eFPUtils

efp_image = Namespace(
"eFP Image", description="eFP Image generation service", path="/efp_image"
Expand All @@ -18,8 +21,14 @@ class eFPImageList(Resource):
def get(self):
"""This end point returns the list of species available"""
# This are the only species available so far
# If this is updated, update get request and test as well
species = ["efp_arabidopsis"]
# If this is updated, update efp_utils.py and unit tests as well
species = [
"efp_arabidopsis",
"efp_cannabis",
"efp_arachis",
"efp_soybean",
"efp_maize",
]
return BARUtils.success_exit(species)


Expand All @@ -29,63 +38,43 @@ def get(self):
doc=False,
)
class eFPImage(Resource):
@staticmethod
def is_efp_mode(efp_mode):
"""This function checks if the eFP mode is valid
:param efp_mode: string eFP Mode
:return: True or False
"""
# This are case sensitive
valid_modes = ["Absolute", "Relative", "Compare"]
if efp_mode in valid_modes:
return True
else:
return False

@efp_image.param("efp", _in="path", default="efp_arabidopsis")
@efp_image.param("view", _in="path", default="Developmental_Map")
@efp_image.param("mode", _in="path", default="Absolute")
@efp_image.param("gene_1", _in="path", default="At1g01010")
@efp_image.param("gene_2", _in="path", default="At3g27340")
def get(self, efp="", view="", mode="", gene_1="", gene_2=""):
"""This end point returns eFP images."""
# list of allowed eFPs
# See endpoint able
species = ["efp_arabidopsis"]

# Escape input data
efp = escape(efp)
view = escape(view)
mode = escape(mode)
gene_1 = escape(gene_1)
gene_2 = escape(gene_2)

# Validate values
if efp not in species:
return BARUtils.error_exit("Invalid eFP."), 400

# Validate view
if not BARUtils.is_efp_view_name(view):
return BARUtils.error_exit("Invalid eFP View name."), 400

# Validate mode
if not self.is_efp_mode(mode):
return BARUtils.error_exit("Invalid eFP mode."), 400
validation = eFPUtils.is_efp_input_valid(efp, view, mode, gene_1, gene_2)
if validation[0] is False:
return BARUtils.error_exit(validation[1]), 400

# Validate gene ids
if not BARUtils.is_arabidopsis_gene_valid(gene_1):
return BARUtils.error_exit("Gene 1 is invalid."), 400
# Data are valid. Clear directory before running
for file in os.listdir("output"):
# Full file name is required at this point
file = os.path.join("output", file)

if mode == "Compare":
if not BARUtils.is_arabidopsis_gene_valid(gene_2):
return BARUtils.error_exit("Gene 2 is invalid."), 400
# Check if it is a png file and is greater than 5 minutes old
if (
os.path.isfile(file)
and (os.path.splitext(file)[1] == ".png")
and (os.stat(file).st_mtime < (time.time() - 5 * 60))
):
os.remove(file)

# Check if request is cached
try:
r = BARUtils.connect_redis()
key = "BAR_API_efp_image_" + "_".join([efp, view, mode, gene_1, gene_2])
efp_image_base64 = r.get(key)
except redis.connection.ConnectionError:
except redis.exceptions.ConnectionError:
# Failed redis connection
r = None
key = None
Expand Down
63 changes: 52 additions & 11 deletions api/utils/bar_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,58 @@ def is_tomato_gene_valid(gene, isoform_id=False):
else:
return False

@staticmethod
def is_cannabis_gene_valid(gene):
"""This function verifies if cannabis gene is valid: AGQN03000001
:param gene:
:return: True if valid
"""
if gene and re.search(r"^AGQN\d{0,10}$", gene, re.I):
return True
else:
return False

@staticmethod
def is_arachis_gene_valid(gene):
"""This function verifies if arachis gene is valid: Adur10000_comp0_c0_seq1
:param gene:
:return: True if valid
"""
if gene and re.search(
r"Adur\d{1,10}_comp\d{1,3}_\D{1,3}\d{1,3}_seq\d{1,5}", gene, re.I
):
return True
else:
return False

@staticmethod
def is_soybean_gene_valid(gene):
"""This function verifies if soybean gene is valid: Glyma06g47400
:param gene:
:return: True if valid
"""
if gene and re.search(
r"^((Glyma\d{1,3}g\d{1,6}\.?\d?)|(Glyma\.\d{1,3}g\d{1,8}))$", gene, re.I
):
return True
else:
return False

@staticmethod
def is_maize_gene_valid(gene):
"""This function verifies if maize gene is valid: Zm00001d046170
:param gene:
:return: True if valid
"""
if gene and re.search(
r"^(AC[0-9]{6}\.[0-9]{1}_FG[0-9]{3})|(AC[0-9]{6}\.[0-9]{1}_FGT[0-9]{3})|(GRMZM(2|5)G[0-9]{6})|(GRMZM(2|5)G[0-9]{6}_T[0-9]{2})|(Zm\d+d\d+)$",
gene,
re.I,
):
return True
else:
return False

@staticmethod
def is_integer(data):
"""Check if the input is at max ten figure number.
Expand All @@ -91,17 +143,6 @@ def format_poplar(poplar_gene):
"""
return poplar_gene.translate(str.maketrans("pOTRIg", "PotriG"))

@staticmethod
def is_efp_view_name(efp_view):
"""This function is used for validated eFP View names for eFP service
:param efp_view: string view name
:return: True if valid
"""
if efp_view and re.search(r"^[a-z1-9_]{1,20}$", efp_view, re.I):
return True
else:
return False

@staticmethod
def connect_redis():
"""This function connects to redis
Expand Down
106 changes: 106 additions & 0 deletions api/utils/efp_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import re
from api.utils.bar_utils import BARUtils


class eFPUtils:
@staticmethod
def is_efp_view_name(efp_view):
"""This function is used for validated eFP View names for eFP service
:param efp_view: string view name
:return: True if valid
"""
if efp_view and re.search(r"^[a-z1-9_]{1,50}$", efp_view, re.I):
return True
else:
return False

@staticmethod
def is_efp_mode(efp_mode):
"""This function checks if the eFP mode is valid
:param efp_mode: string eFP Mode
:return: True or False
"""
# These are case-sensitive
valid_modes = ["Absolute", "Relative", "Compare"]
if efp_mode in valid_modes:
return True
else:
return False

@staticmethod
def is_efp_input_valid(efp, view, mode, gene_1, gene_2=None):
"""Test if eFP input is valid
:return: List with boolean and string
"""
species = [
"efp_arabidopsis",
"efp_cannabis",
"efp_arachis",
"efp_soybean",
"efp_maize",
]

# Validate values
if efp not in species:
return False, "Invalid eFP."

# Validate view
if not eFPUtils.is_efp_view_name(view):
return False, "Invalid eFP View name."

# Validate mode
if not eFPUtils.is_efp_mode(mode):
return False, "Invalid eFP mode."

# Maybe this part could be improved
if efp == "efp_arabidopsis":
# Validate gene ids
if not BARUtils.is_arabidopsis_gene_valid(gene_1):
return False, "Gene 1 is invalid."

if mode == "Compare":
if not BARUtils.is_arabidopsis_gene_valid(gene_2):
return False, "Gene 2 is invalid."

if efp == "efp_cannabis":
# Validate gene ids
if not BARUtils.is_cannabis_gene_valid(gene_1):
return False, "Gene 1 is invalid."

if mode == "Compare":
if not BARUtils.is_cannabis_gene_valid(gene_2):
return False, "Gene 2 is invalid."

if efp == "efp_arachis":
# Validate gene ids
if not BARUtils.is_arachis_gene_valid(gene_1):
return False, "Gene 1 is invalid."

if mode == "Compare":
if not BARUtils.is_arachis_gene_valid(gene_2):
return False, "Gene 2 is invalid."

if efp == "efp_soybean":
# Validate gene ids
if not BARUtils.is_soybean_gene_valid(gene_1):
return False, "Gene 1 is invalid."

if mode == "Compare":
if not BARUtils.is_soybean_gene_valid(gene_2):
return False, "Gene 2 is invalid."

if efp == "efp_maize":
# Validate gene ids
if not BARUtils.is_maize_gene_valid(gene_1):
return False, "Gene 1 is invalid."

if mode == "Compare":
if not BARUtils.is_maize_gene_valid(gene_2):
return False, "Gene 2 is invalid."

# In compare mode gene1 != gene2
if mode == "Compare" and gene_1 == gene_2:
return False, "In compare mode, both genes should be different."

# Assuming all check have passed
return True, None
18 changes: 9 additions & 9 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
aniso8601==9.0.1
appdirs==1.4.4
attrs==21.2.0
attrs==21.4.0
black==20.8b1
certifi==2021.10.8
cffi==1.15.0
chardet==4.0.0
charset-normalizer==2.0.9
click==8.0.3
coverage==6.2
cryptography==36.0.0
cryptography==36.0.1
Deprecated==1.2.13
docopt==0.6.2
flake8==4.0.1
Flask==2.0.2
Flask-Caching==1.10.1
Flask-Cors==3.0.10
Flask-Limiter==2.0.2
Flask-Limiter==2.0.4
flask-marshmallow==0.14.0
flask-restx==0.5.1
Flask-SQLAlchemy==2.5.1
Expand All @@ -24,17 +24,17 @@ idna==3.3
iniconfig==1.1.1
itsdangerous==2.0.1
Jinja2==3.0.3
jsonschema==4.2.1
limits==2.0.3
jsonschema==4.3.2
limits==2.1.0
MarkupSafe==2.0.1
marshmallow==3.14.1
mccabe==0.6.1
more-itertools==8.12.0
mypy-extensions==0.4.3
mysqlclient==2.1.0
numpy==1.21.4
numpy==1.21.5
packaging==21.3
pandas==1.3.4
pandas==1.3.5
pathspec==0.9.0
pluggy==1.0.0
py==1.11.0
Expand All @@ -46,12 +46,12 @@ pyrsistent==0.18.0
pytest==6.2.5
python-dateutil==2.8.2
pytz==2021.3
redis==4.0.2
redis==4.1.0
regex==2021.11.10
requests==2.26.0
scour==0.38.2
six==1.16.0
SQLAlchemy==1.4.28
SQLAlchemy==1.4.29
toml==0.10.2
typed-ast==1.5.1
typing_extensions==4.0.1
Expand Down
Loading