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
from fastapi import APIRouter
from fastapi import APIRouter, Depends
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.mongo import documents as mongo
from bsition.backend.postgres import relations as postgres
router = APIRouter()
@ -17,14 +19,14 @@ def create(aux: Document):
@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:
return elastic.search("test-index", query)
return mongo.get_documents()
return elastic.search("test-index", query, user[0])
return mongo.get_documents(user[0])
@router.get("/{id}")
def get_by_id(id: str):
def get_document(id: str):
return mongo.get_document_by_id(id)
@ -37,3 +39,26 @@ def edit_data(aux: DocumentUpdate, id: str):
if aux.name is not None:
mongo.edit_name(id, aux.name)
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 bsition.api.models.document import Access
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.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()
@ -27,13 +30,13 @@ def edit_table(aux: Table, name: str):
@router.post("/{name}/sort")
def create_sort(name: str):
postgres.create_sort()
postgres_t.create_sort()
return JSONResponse(content={"detail": "Sort created."}, status_code=201)
@router.put("/{name}/sort")
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)
@ -44,17 +47,39 @@ def sort(name: str):
@router.post("/{name}/filter")
def create_filter(name: str):
postgres.create_filter()
# postgres.add_filter_trigger(name)
postgres_t.create_filter()
return JSONResponse(content={"detail": "Filter created."}, status_code=201)
@router.put("/{name}/filter")
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)
@router.get("/{name}/filter")
def filter(name: str):
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.",
)
token, expire = write_token({"sub": form.username})
token, expire = write_token({"sub": form.username + ":" + str(user[0])})
add_token(token, form.username, expire)
clean_tokens(form.username)
return JSONResponse(
@ -34,7 +34,6 @@ def login(form: OAuth2PasswordRequestForm = Depends()):
@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)
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")
def get_logged_user(user: User = Depends(get_current_user)):
def get_logged_user(user: tuple = Depends(get_current_user)):
return user

View File

@ -1,9 +1,18 @@
from dotenv import load_dotenv
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from bsition.api.api import router
app = FastAPI(title="BSition 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()

View File

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

View File

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

View File

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

View File

@ -1,25 +1,22 @@
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()
acc_doc = postgres.get_accesible_documents(user_id)
resp = client.search(
index=index,
size=100,
query={
# "query_string": {
# "query": "*puan*",
# "default_field": "data"
# }
"bool": {
"must": [
{"query_string": {"query": query, "default_field": "data"}},
# {
# "match": {
# "id": "1",
# }
# }
],
"filter": [
{"terms": {"_id": acc_doc}}
]
}
},
@ -31,5 +28,6 @@ def search(index, query):
hits.append(
str(hit["highlight"]) + " ---- " + "%(name)s: %(data)s" % hit["_source"]
)
print(hit['_id'], hit['_source'])
return hits

View File

@ -1,13 +1,18 @@
from bson import ObjectId
from bsition.backend.elastic import utils as elastic
from bsition.backend.postgres import relations as postgres
from bsition.backend.mongo.utils import get_database
def get_documents():
def get_documents(user_id):
dbname = get_database()
docs_coll = dbname["docs"]
docs = postgres.get_accesible_documents(user_id)
pipeline = [
{"$match": {"_id": {"$in": [ObjectId(doc) for doc in docs]}}},
{
"$project": {
"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()
@ -92,6 +101,43 @@ def has_access(user_id, id, destination):
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):
return deny_access(user_id, table_id, "table")
@ -127,4 +173,8 @@ def get_accesible_documents(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):
client = get_client()
tokens = client.zrangebyscore(username, -inf, inf)
for aux in tokens:
if aux.decode("utf-8") == token:
client.zrem(username, token)
client.zrem(username, token)
# Puede correr en un cron o, por ejemplo, cada vez que el usuario hace login (o logout)