Fix lots of bugs

Co-authored-by: Ezequiel Bellver <ebellver@itba.edu.ar>
Co-authored-by: Juan Barmasch <jbarmasch@itba.edu.ar>
This commit is contained in:
Santiago Lo Coco 2022-12-19 12:12:22 -03:00
parent 90fffcfcb3
commit 0a04060527
12 changed files with 149 additions and 35 deletions

View File

@ -1,11 +1,13 @@
import json import json
from fastapi import APIRouter from fastapi import APIRouter, Depends
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from bsition.api.models.document import Document, DocumentUpdate from bsition.api.models.document import Document, DocumentUpdate, Access
from bsition.api.utils.security import get_current_user
from bsition.backend.elastic import search as elastic from bsition.backend.elastic import search as elastic
from bsition.backend.mongo import documents as mongo from bsition.backend.mongo import documents as mongo
from bsition.backend.postgres import relations as postgres
router = APIRouter() router = APIRouter()
@ -17,14 +19,14 @@ def create(aux: Document):
@router.get("") @router.get("")
def get_documents(query: str = None): def get_documents(query: str = None, user: tuple = Depends(get_current_user)):
if query is not None: if query is not None:
return elastic.search("test-index", query) return elastic.search("test-index", query, user[0])
return mongo.get_documents() return mongo.get_documents(user[0])
@router.get("/{id}") @router.get("/{id}")
def get_by_id(id: str): def get_document(id: str):
return mongo.get_document_by_id(id) return mongo.get_document_by_id(id)
@ -37,3 +39,26 @@ def edit_data(aux: DocumentUpdate, id: str):
if aux.name is not None: if aux.name is not None:
mongo.edit_name(id, aux.name) mongo.edit_name(id, aux.name)
return JSONResponse(content={"detail": "Document updated."}, status_code=202) return JSONResponse(content={"detail": "Document updated."}, status_code=202)
@router.get("/{id}/access")
def get_access(id: str, user: tuple = Depends(get_current_user)):
return postgres.has_access_doc(user[0], id)
@router.post("/{id}/access")
def give_access(id: str, access_type: Access, user: tuple = Depends(get_current_user)):
postgres.give_access_doc(user[0], id, access_type.access_type)
return JSONResponse(content={"detail": "Access created"}, status_code=201)
@router.put("/{id}/access")
def update_access(id: str, access_type: Access, user: tuple = Depends(get_current_user)):
postgres.give_access_doc(user[0], id, access_type.access_type)
return JSONResponse(content={"detail": "Access updated"}, status_code=202)
@router.delete("/{id}/access")
def deny_access(id: str, user: tuple = Depends(get_current_user)):
postgres.deny_access_doc(user[0], id)
return JSONResponse(content={"detail": "Access deleted"}, status_code=201)

View File

@ -1,9 +1,12 @@
from fastapi import APIRouter from fastapi import APIRouter, Depends
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from bsition.api.models.document import Access
from bsition.api.models.table import Filter, Sort, Table from bsition.api.models.table import Filter, Sort, Table
from bsition.api.utils.security import get_current_user
from bsition.backend.mongo import tables as mongo from bsition.backend.mongo import tables as mongo
from bsition.backend.postgres import tables as postgres from bsition.backend.postgres import tables as postgres_t
from bsition.backend.postgres import relations as postgres_r
router = APIRouter() router = APIRouter()
@ -27,13 +30,13 @@ def edit_table(aux: Table, name: str):
@router.post("/{name}/sort") @router.post("/{name}/sort")
def create_sort(name: str): def create_sort(name: str):
postgres.create_sort() postgres_t.create_sort()
return JSONResponse(content={"detail": "Sort created."}, status_code=201) return JSONResponse(content={"detail": "Sort created."}, status_code=201)
@router.put("/{name}/sort") @router.put("/{name}/sort")
def add_sort(aux: Sort, name: str): def add_sort(aux: Sort, name: str):
postgres.add_sort(name, aux.property, aux.order, aux.priority) postgres_t.add_sort(name, aux.property, aux.order, aux.priority)
return JSONResponse(content={"detail": "Sort updated."}, status_code=202) return JSONResponse(content={"detail": "Sort updated."}, status_code=202)
@ -44,17 +47,39 @@ def sort(name: str):
@router.post("/{name}/filter") @router.post("/{name}/filter")
def create_filter(name: str): def create_filter(name: str):
postgres.create_filter() postgres_t.create_filter()
# postgres.add_filter_trigger(name)
return JSONResponse(content={"detail": "Filter created."}, status_code=201) return JSONResponse(content={"detail": "Filter created."}, status_code=201)
@router.put("/{name}/filter") @router.put("/{name}/filter")
def add_filter(aux: Filter, name: str): def add_filter(aux: Filter, name: str):
postgres.add_filter(name, aux.property, aux.value, aux.function) postgres_t.add_filter(name, aux.property, aux.value, aux.function)
return JSONResponse(content={"detail": "Filter updated."}, status_code=202) return JSONResponse(content={"detail": "Filter updated."}, status_code=202)
@router.get("/{name}/filter") @router.get("/{name}/filter")
def filter(name: str): def filter(name: str):
return mongo.filter(name) return mongo.filter(name)
@router.get("/{id}/access")
def get_access(id: str, user: tuple = Depends(get_current_user)):
return postgres_r.has_access_table(user[0], id)
@router.post("/{id}/access")
def give_access(id: str, access_type: Access, user: tuple = Depends(get_current_user)):
postgres_r.give_access_table(user[0], id, access_type.access_type)
return JSONResponse(content={"detail": "Access created"}, status_code=201)
@router.put("/{id}/access")
def update_access(id: str, access_type: Access, user: tuple = Depends(get_current_user)):
postgres_r.give_access_table(user[0], id, access_type.access_type)
return JSONResponse(content={"detail": "Access updated"}, status_code=202)
@router.delete("/{id}/access")
def deny_access(id: str, user: tuple = Depends(get_current_user)):
postgres_r.deny_access_table(user[0], id)
return JSONResponse(content={"detail": "Access deleted"}, status_code=201)

View File

@ -21,7 +21,7 @@ def login(form: OAuth2PasswordRequestForm = Depends()):
detail="User not found.", detail="User not found.",
) )
token, expire = write_token({"sub": form.username}) token, expire = write_token({"sub": form.username + ":" + str(user[0])})
add_token(token, form.username, expire) add_token(token, form.username, expire)
clean_tokens(form.username) clean_tokens(form.username)
return JSONResponse( return JSONResponse(
@ -34,7 +34,6 @@ def login(form: OAuth2PasswordRequestForm = Depends()):
@router.delete("/token") @router.delete("/token")
def logout(token: str = Depends(oauth2_scheme), user: User = Depends(get_current_user)): def logout(token: str = Depends(oauth2_scheme), user: tuple = Depends(get_current_user)):
remove_token(user[1], token) remove_token(user[1], token)
return JSONResponse(content={"detail": "Token deleted."}, status_code=201) return JSONResponse(content={"detail": "Token deleted."}, status_code=202)

View File

@ -24,7 +24,7 @@ def create_user(user: User):
@router.get("/me") @router.get("/me")
def get_logged_user(user: User = Depends(get_current_user)): def get_logged_user(user: tuple = Depends(get_current_user)):
return user return user

View File

@ -1,9 +1,18 @@
from dotenv import load_dotenv from dotenv import load_dotenv
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from bsition.api.api import router from bsition.api.api import router
app = FastAPI(title="BSition API") app = FastAPI(title="BSition API")
app.include_router(router, prefix="/api") app.include_router(router, prefix="/api")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["POST", "GET", "PUT", "DELETE", "OPTIONS"],
allow_headers=["*"],
max_age=3600,
)
load_dotenv() load_dotenv()

View File

@ -13,3 +13,7 @@ class DocumentUpdate(BaseModel):
name: Optional[str] name: Optional[str]
access: Optional[list] access: Optional[list]
data: Optional[str] data: Optional[str]
class Access(BaseModel):
access_type: int

View File

@ -3,5 +3,6 @@ from pydantic.types import Optional
class User(BaseModel): class User(BaseModel):
id: Optional[str]
username: str username: str
password: Optional[str] password: Optional[str]

View File

@ -3,6 +3,7 @@ from fastapi.security import OAuth2PasswordBearer
from jwt import exceptions from jwt import exceptions
from starlette import status from starlette import status
from bsition.api.models.user import User
from bsition.api.utils.jwt import validate_token from bsition.api.utils.jwt import validate_token
from bsition.backend.postgres.users import get_user_by_username from bsition.backend.postgres.users import get_user_by_username
from bsition.backend.redis.tokens import valid_token from bsition.backend.redis.tokens import valid_token
@ -19,7 +20,7 @@ async def get_current_user(token: str = Depends(oauth2_scheme)):
try: try:
payload = validate_token(token) payload = validate_token(token)
username: str = payload.get("sub") username: str = payload.get("sub").split(":")[0]
if username is None: if username is None:
raise credentials_exception raise credentials_exception
except exceptions.DecodeError: except exceptions.DecodeError:

View File

@ -1,25 +1,22 @@
from bsition.backend.elastic.utils import get_client from bsition.backend.elastic.utils import get_client
from bsition.backend.postgres import relations as postgres
def search(index, query): def search(index, query, user_id):
client = get_client() client = get_client()
acc_doc = postgres.get_accesible_documents(user_id)
resp = client.search( resp = client.search(
index=index, index=index,
size=100, size=100,
query={ query={
# "query_string": {
# "query": "*puan*",
# "default_field": "data"
# }
"bool": { "bool": {
"must": [ "must": [
{"query_string": {"query": query, "default_field": "data"}}, {"query_string": {"query": query, "default_field": "data"}},
# { ],
# "match": { "filter": [
# "id": "1", {"terms": {"_id": acc_doc}}
# }
# }
] ]
} }
}, },
@ -31,5 +28,6 @@ def search(index, query):
hits.append( hits.append(
str(hit["highlight"]) + " ---- " + "%(name)s: %(data)s" % hit["_source"] str(hit["highlight"]) + " ---- " + "%(name)s: %(data)s" % hit["_source"]
) )
print(hit['_id'], hit['_source'])
return hits return hits

View File

@ -1,13 +1,18 @@
from bson import ObjectId from bson import ObjectId
from bsition.backend.elastic import utils as elastic from bsition.backend.elastic import utils as elastic
from bsition.backend.postgres import relations as postgres
from bsition.backend.mongo.utils import get_database from bsition.backend.mongo.utils import get_database
def get_documents(): def get_documents(user_id):
dbname = get_database() dbname = get_database()
docs_coll = dbname["docs"] docs_coll = dbname["docs"]
docs = postgres.get_accesible_documents(user_id)
pipeline = [ pipeline = [
{"$match": {"_id": {"$in": [ObjectId(doc) for doc in docs]}}},
{ {
"$project": { "$project": {
"id": {"$toString": "$_id"}, "id": {"$toString": "$_id"},

View File

@ -30,6 +30,15 @@ def create_relations_tables():
""" """
) )
) )
cur.execute(
sql.SQL(
"""
CREATE TABLE public_docs (
doc_id INTEGER PRIMARY KEY
)
"""
)
)
conn.commit() conn.commit()
@ -92,6 +101,43 @@ def has_access(user_id, id, destination):
return list(cur.fetchall()) return list(cur.fetchall())
def is_public(doc_id):
conn = get_connection()
cur = conn.cursor()
cur.execute(
sql.SQL(
"SELECT doc_id FROM public_docs WHERE doc_id = {doc_id}"
).format(
doc_id=sql.Literal(doc_id),
)
)
return cur.rowcount > 0
def make_public(doc_id):
conn = get_connection()
cur = conn.cursor()
cur.execute(
sql.SQL(
"INSERT INTO public_docs VALUES {doc_id} ON CONFLICT DO NOTHING"
).format(
doc_id=sql.Literal(doc_id),
)
)
def make_private(doc_id):
conn = get_connection()
cur = conn.cursor()
cur.execute(
sql.SQL(
"DELETE FROM public_docs WHERE doc_id = {doc_id} ON CONFLICT DO NOTHING"
).format(
doc_id=sql.Literal(doc_id),
)
)
def deny_access_table(user_id, table_id): def deny_access_table(user_id, table_id):
return deny_access(user_id, table_id, "table") return deny_access(user_id, table_id, "table")
@ -127,4 +173,8 @@ def get_accesible_documents(user_id):
user_id=sql.Literal(user_id) user_id=sql.Literal(user_id)
) )
) )
return list(cur.fetchall())
docs = []
for doc in cur.fetchall():
docs.append(doc[0])
return docs

View File

@ -18,10 +18,7 @@ def remove_tokens(username):
def remove_token(username, token): def remove_token(username, token):
client = get_client() client = get_client()
tokens = client.zrangebyscore(username, -inf, inf) client.zrem(username, token)
for aux in tokens:
if aux.decode("utf-8") == token:
client.zrem(username, token)
# Puede correr en un cron o, por ejemplo, cada vez que el usuario hace login (o logout) # Puede correr en un cron o, por ejemplo, cada vez que el usuario hace login (o logout)