mirror of
https://github.com/zylon-ai/private-gpt.git
synced 2025-12-22 23:22:57 +01:00
Added fastapi-pagination and audit log download
This commit is contained in:
parent
97317b82e0
commit
3282d52bf2
23 changed files with 310 additions and 208 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
122
poetry.lock
generated
122
poetry.lock
generated
|
|
@ -1225,6 +1225,17 @@ files = [
|
||||||
dnspython = ">=2.0.0"
|
dnspython = ">=2.0.0"
|
||||||
idna = ">=2.0.0"
|
idna = ">=2.0.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "et-xmlfile"
|
||||||
|
version = "1.1.0"
|
||||||
|
description = "An implementation of lxml.xmlfile for the standard library"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
files = [
|
||||||
|
{file = "et_xmlfile-1.1.0-py3-none-any.whl", hash = "sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada"},
|
||||||
|
{file = "et_xmlfile-1.1.0.tar.gz", hash = "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastapi"
|
name = "fastapi"
|
||||||
version = "0.110.0"
|
version = "0.110.0"
|
||||||
|
|
@ -1276,6 +1287,39 @@ all = ["SQLAlchemy (>=1.4.36,<2.1.0)", "mongoengine (>=0.24.1,<0.28.0)"]
|
||||||
mongoengine = ["mongoengine (>=0.24.1,<0.28.0)"]
|
mongoengine = ["mongoengine (>=0.24.1,<0.28.0)"]
|
||||||
sqlalchemy = ["SQLAlchemy (>=1.4.36,<2.1.0)"]
|
sqlalchemy = ["SQLAlchemy (>=1.4.36,<2.1.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastapi-pagination"
|
||||||
|
version = "0.12.23"
|
||||||
|
description = "FastAPI pagination"
|
||||||
|
optional = false
|
||||||
|
python-versions = "<4.0,>=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "fastapi_pagination-0.12.23-py3-none-any.whl", hash = "sha256:a20a05b375bb4ed01355373ae6749e9a61b8bd8248c672d3402840f0f81de7f6"},
|
||||||
|
{file = "fastapi_pagination-0.12.23.tar.gz", hash = "sha256:c7804e1d02fcb678a43be81e974f88994226099f7e74b70b279b8e79bd8689ef"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
fastapi = ">=0.93.0"
|
||||||
|
pydantic = ">=1.9.1"
|
||||||
|
typing-extensions = ">=4.8.0,<5.0.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
all = ["SQLAlchemy (>=1.3.20)", "asyncpg (>=0.24.0)", "beanie (>=1.25.0)", "bunnet (>=1.1.0,<2.0.0)", "databases (>=0.6.0)", "django (<5.0.0)", "mongoengine (>=0.23.1,<0.29.0)", "motor (>=2.5.1,<4.0.0)", "orm (>=0.3.1)", "ormar (>=0.11.2)", "piccolo (>=0.89,<0.122)", "pony (>=0.7.16,<0.8.0)", "scylla-driver (>=3.25.6,<4.0.0)", "sqlakeyset (>=2.0.1680321678,<3.0.0)", "sqlmodel (>=0.0.8,<0.0.15)", "tortoise-orm (>=0.16.18,<0.21.0)"]
|
||||||
|
asyncpg = ["SQLAlchemy (>=1.3.20)", "asyncpg (>=0.24.0)"]
|
||||||
|
beanie = ["beanie (>=1.25.0)"]
|
||||||
|
bunnet = ["bunnet (>=1.1.0,<2.0.0)"]
|
||||||
|
databases = ["databases (>=0.6.0)"]
|
||||||
|
django = ["databases (>=0.6.0)", "django (<5.0.0)"]
|
||||||
|
mongoengine = ["mongoengine (>=0.23.1,<0.29.0)"]
|
||||||
|
motor = ["motor (>=2.5.1,<4.0.0)"]
|
||||||
|
orm = ["databases (>=0.6.0)", "orm (>=0.3.1)"]
|
||||||
|
ormar = ["ormar (>=0.11.2)"]
|
||||||
|
piccolo = ["piccolo (>=0.89,<0.122)"]
|
||||||
|
scylla-driver = ["scylla-driver (>=3.25.6,<4.0.0)"]
|
||||||
|
sqlalchemy = ["SQLAlchemy (>=1.3.20)", "sqlakeyset (>=2.0.1680321678,<3.0.0)"]
|
||||||
|
sqlmodel = ["sqlakeyset (>=2.0.1680321678,<3.0.0)", "sqlmodel (>=0.0.8,<0.0.15)"]
|
||||||
|
tortoise = ["tortoise-orm (>=0.16.18,<0.21.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ffmpy"
|
name = "ffmpy"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
|
|
@ -3596,6 +3640,20 @@ files = [
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
numpy = {version = ">=1.23.5", markers = "python_version >= \"3.11\""}
|
numpy = {version = ">=1.23.5", markers = "python_version >= \"3.11\""}
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openpyxl"
|
||||||
|
version = "3.1.2"
|
||||||
|
description = "A Python library to read/write Excel 2010 xlsx/xlsm files"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
files = [
|
||||||
|
{file = "openpyxl-3.1.2-py2.py3-none-any.whl", hash = "sha256:f91456ead12ab3c6c2e9491cf33ba6d08357d802192379bb482f1033ade496f5"},
|
||||||
|
{file = "openpyxl-3.1.2.tar.gz", hash = "sha256:a6f5977418eff3b2d5500d54d9db50c8277a368436f4e4f8ddb1be3422870184"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
et-xmlfile = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opentelemetry-api"
|
name = "opentelemetry-api"
|
||||||
version = "1.23.0"
|
version = "1.23.0"
|
||||||
|
|
@ -3843,44 +3901,44 @@ files = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pandas"
|
name = "pandas"
|
||||||
version = "2.2.1"
|
version = "2.2.2"
|
||||||
description = "Powerful data structures for data analysis, time series, and statistics"
|
description = "Powerful data structures for data analysis, time series, and statistics"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.9"
|
||||||
files = [
|
files = [
|
||||||
{file = "pandas-2.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8df8612be9cd1c7797c93e1c5df861b2ddda0b48b08f2c3eaa0702cf88fb5f88"},
|
{file = "pandas-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce"},
|
||||||
{file = "pandas-2.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0f573ab277252ed9aaf38240f3b54cfc90fff8e5cab70411ee1d03f5d51f3944"},
|
{file = "pandas-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238"},
|
||||||
{file = "pandas-2.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f02a3a6c83df4026e55b63c1f06476c9aa3ed6af3d89b4f04ea656ccdaaaa359"},
|
{file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08"},
|
||||||
{file = "pandas-2.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c38ce92cb22a4bea4e3929429aa1067a454dcc9c335799af93ba9be21b6beb51"},
|
{file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0"},
|
||||||
{file = "pandas-2.2.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c2ce852e1cf2509a69e98358e8458775f89599566ac3775e70419b98615f4b06"},
|
{file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51"},
|
||||||
{file = "pandas-2.2.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:53680dc9b2519cbf609c62db3ed7c0b499077c7fefda564e330286e619ff0dd9"},
|
{file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e5a0b00e1e56a842f922e7fae8ae4077aee4af0acb5ae3622bd4b4c30aedf99"},
|
||||||
{file = "pandas-2.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:94e714a1cca63e4f5939cdce5f29ba8d415d85166be3441165edd427dc9f6bc0"},
|
{file = "pandas-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:ddf818e4e6c7c6f4f7c8a12709696d193976b591cc7dc50588d3d1a6b5dc8772"},
|
||||||
{file = "pandas-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f821213d48f4ab353d20ebc24e4faf94ba40d76680642fb7ce2ea31a3ad94f9b"},
|
{file = "pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288"},
|
||||||
{file = "pandas-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c70e00c2d894cb230e5c15e4b1e1e6b2b478e09cf27cc593a11ef955b9ecc81a"},
|
{file = "pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151"},
|
||||||
{file = "pandas-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e97fbb5387c69209f134893abc788a6486dbf2f9e511070ca05eed4b930b1b02"},
|
{file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b"},
|
||||||
{file = "pandas-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101d0eb9c5361aa0146f500773395a03839a5e6ecde4d4b6ced88b7e5a1a6403"},
|
{file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee"},
|
||||||
{file = "pandas-2.2.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7d2ed41c319c9fb4fd454fe25372028dfa417aacb9790f68171b2e3f06eae8cd"},
|
{file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2925720037f06e89af896c70bca73459d7e6a4be96f9de79e2d440bd499fe0db"},
|
||||||
{file = "pandas-2.2.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:af5d3c00557d657c8773ef9ee702c61dd13b9d7426794c9dfeb1dc4a0bf0ebc7"},
|
{file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1"},
|
||||||
{file = "pandas-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:06cf591dbaefb6da9de8472535b185cba556d0ce2e6ed28e21d919704fef1a9e"},
|
{file = "pandas-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24"},
|
||||||
{file = "pandas-2.2.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:88ecb5c01bb9ca927ebc4098136038519aa5d66b44671861ffab754cae75102c"},
|
{file = "pandas-2.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef"},
|
||||||
{file = "pandas-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:04f6ec3baec203c13e3f8b139fb0f9f86cd8c0b94603ae3ae8ce9a422e9f5bee"},
|
{file = "pandas-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce"},
|
||||||
{file = "pandas-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a935a90a76c44fe170d01e90a3594beef9e9a6220021acfb26053d01426f7dc2"},
|
{file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad"},
|
||||||
{file = "pandas-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c391f594aae2fd9f679d419e9a4d5ba4bce5bb13f6a989195656e7dc4b95c8f0"},
|
{file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad"},
|
||||||
{file = "pandas-2.2.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9d1265545f579edf3f8f0cb6f89f234f5e44ba725a34d86535b1a1d38decbccc"},
|
{file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76"},
|
||||||
{file = "pandas-2.2.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:11940e9e3056576ac3244baef2fedade891977bcc1cb7e5cc8f8cc7d603edc89"},
|
{file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32"},
|
||||||
{file = "pandas-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:4acf681325ee1c7f950d058b05a820441075b0dd9a2adf5c4835b9bc056bf4fb"},
|
{file = "pandas-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23"},
|
||||||
{file = "pandas-2.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9bd8a40f47080825af4317d0340c656744f2bfdb6819f818e6ba3cd24c0e1397"},
|
{file = "pandas-2.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2"},
|
||||||
{file = "pandas-2.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:df0c37ebd19e11d089ceba66eba59a168242fc6b7155cba4ffffa6eccdfb8f16"},
|
{file = "pandas-2.2.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd"},
|
||||||
{file = "pandas-2.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:739cc70eaf17d57608639e74d63387b0d8594ce02f69e7a0b046f117974b3019"},
|
{file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863"},
|
||||||
{file = "pandas-2.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9d3558d263073ed95e46f4650becff0c5e1ffe0fc3a015de3c79283dfbdb3df"},
|
{file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921"},
|
||||||
{file = "pandas-2.2.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4aa1d8707812a658debf03824016bf5ea0d516afdea29b7dc14cf687bc4d4ec6"},
|
{file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a"},
|
||||||
{file = "pandas-2.2.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:76f27a809cda87e07f192f001d11adc2b930e93a2b0c4a236fde5429527423be"},
|
{file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92fd6b027924a7e178ac202cfbe25e53368db90d56872d20ffae94b96c7acc57"},
|
||||||
{file = "pandas-2.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:1ba21b1d5c0e43416218db63037dbe1a01fc101dc6e6024bcad08123e48004ab"},
|
{file = "pandas-2.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:640cef9aa381b60e296db324337a554aeeb883ead99dc8f6c18e81a93942f5f4"},
|
||||||
{file = "pandas-2.2.1.tar.gz", hash = "sha256:0ab90f87093c13f3e8fa45b48ba9f39181046e8f3317d3aadb2fffbb1b978572"},
|
{file = "pandas-2.2.2.tar.gz", hash = "sha256:9e79019aba43cb4fda9e4d983f8e88ca0373adbb697ae9c6c43093218de28b54"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
numpy = {version = ">=1.23.2,<2", markers = "python_version == \"3.11\""}
|
numpy = {version = ">=1.23.2", markers = "python_version == \"3.11\""}
|
||||||
python-dateutil = ">=2.8.2"
|
python-dateutil = ">=2.8.2"
|
||||||
pytz = ">=2020.1"
|
pytz = ">=2020.1"
|
||||||
tzdata = ">=2022.7"
|
tzdata = ">=2022.7"
|
||||||
|
|
@ -7157,4 +7215,4 @@ vector-stores-qdrant = ["llama-index-vector-stores-qdrant"]
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = ">=3.11,<3.12"
|
python-versions = ">=3.11,<3.12"
|
||||||
content-hash = "57d64e26ba5f7100c0f6d61135808b190a9f6b8c95a6407b984b7cbea244d5f5"
|
content-hash = "d7f6a81832b4a41ebd23b4e2041beb53bc26437212204254c87e33d1a4e68b8d"
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
import uvicorn
|
import uvicorn
|
||||||
|
|
||||||
from private_gpt.main import app
|
from private_gpt.main import app
|
||||||
|
from fastapi_pagination import add_pagination
|
||||||
|
|
||||||
from private_gpt.settings.settings import settings
|
from private_gpt.settings.settings import settings
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
from private_gpt.constants import UPLOAD_DIR
|
from private_gpt.constants import UPLOAD_DIR
|
||||||
|
|
@ -12,5 +14,5 @@ from private_gpt.constants import UPLOAD_DIR
|
||||||
# https://github.com/tiangolo/fastapi/discussions/7457#discussioncomment-5141108
|
# https://github.com/tiangolo/fastapi/discussions/7457#discussioncomment-5141108
|
||||||
|
|
||||||
app.mount("/static", StaticFiles(directory=UPLOAD_DIR), name="static")
|
app.mount("/static", StaticFiles(directory=UPLOAD_DIR), name="static")
|
||||||
|
add_pagination(app)
|
||||||
uvicorn.run(app, host="0.0.0.0", port=settings().server.port, log_config=None)
|
uvicorn.run(app, host="0.0.0.0", port=settings().server.port, log_config=None)
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ def create_app(root_injector: Injector) -> FastAPI:
|
||||||
"http://192.168.1.98", "http://192.168.1.98:3000", "http://localhost:3000","https://globaldocquery.gibl.com.np/", "http://127.0.0.1/", "http://localhost/",
|
"http://192.168.1.98", "http://192.168.1.98:3000", "http://localhost:3000","https://globaldocquery.gibl.com.np/", "http://127.0.0.1/", "http://localhost/",
|
||||||
"http://localhost:80", "http://192.168.1.131", 'http://192.168.1.131:3000'
|
"http://localhost:80", "http://192.168.1.131", 'http://192.168.1.131:3000'
|
||||||
, "http://192.168.1.127", 'http://192.168.1.127:3000'
|
, "http://192.168.1.127", 'http://192.168.1.127:3000'
|
||||||
, "http://192.168.1.70", 'http://192.168.1.70:3000'
|
, "http://192.168.1.89", 'http://192.168.1.89:3000'
|
||||||
],
|
],
|
||||||
allow_methods=["DELETE", "GET", "POST", "PUT", "OPTIONS", "PATCH"],
|
allow_methods=["DELETE", "GET", "POST", "PUT", "OPTIONS", "PATCH"],
|
||||||
allow_headers=["*"],
|
allow_headers=["*"],
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,6 @@ async def create_documents(
|
||||||
`Document Department Association` table with the departments ids for the documents.
|
`Document Department Association` table with the departments ids for the documents.
|
||||||
"""
|
"""
|
||||||
department_ids = departments.departments_ids
|
department_ids = departments.departments_ids
|
||||||
print("Department ids: ", department_ids)
|
|
||||||
file_ingested = crud.documents.get_by_filename(
|
file_ingested = crud.documents.get_by_filename(
|
||||||
db, file_name=file_name)
|
db, file_name=file_name)
|
||||||
if file_ingested:
|
if file_ingested:
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,31 @@
|
||||||
from typing import Any, List
|
from typing import Any, List
|
||||||
|
from fastapi.responses import StreamingResponse
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
from fastapi import APIRouter, Depends, HTTPException, Security, Request
|
from fastapi import APIRouter, Depends, Security
|
||||||
|
from private_gpt.users import crud, models, schemas
|
||||||
from private_gpt.users.api import deps
|
from private_gpt.users.api import deps
|
||||||
from private_gpt.users.constants.role import Role
|
from private_gpt.users.constants.role import Role
|
||||||
from private_gpt.users import crud, models, schemas
|
from private_gpt.users.utils.export import generate_audit_log_report
|
||||||
|
|
||||||
|
router = APIRouter(prefix="/audit", tags=["Audit"])
|
||||||
|
|
||||||
router = APIRouter(prefix="/audit", tags=["Companies"])
|
def get_fullname(db: Session, id: int) -> str:
|
||||||
|
user = crud.user.get_by_id(db, id=id)
|
||||||
|
return user.username if user else ""
|
||||||
|
|
||||||
|
def convert_audit_logs(db: Session, logs: List[Any], username: str = None) -> List[schemas.Audit]:
|
||||||
|
return [
|
||||||
|
schemas.Audit(
|
||||||
|
id=dep.id,
|
||||||
|
model=dep.model,
|
||||||
|
username=get_fullname(db, dep.user_id),
|
||||||
|
details=dep.details,
|
||||||
|
action=dep.action,
|
||||||
|
timestamp=dep.timestamp,
|
||||||
|
ip_address=dep.ip_address,
|
||||||
|
)
|
||||||
|
for dep in logs
|
||||||
|
]
|
||||||
|
|
||||||
@router.get("", response_model=List[schemas.Audit])
|
@router.get("", response_model=List[schemas.Audit])
|
||||||
def list_auditlog(
|
def list_auditlog(
|
||||||
|
|
@ -21,30 +37,8 @@ def list_auditlog(
|
||||||
scopes=[Role.SUPER_ADMIN["name"]],
|
scopes=[Role.SUPER_ADMIN["name"]],
|
||||||
),
|
),
|
||||||
) -> List[schemas.Audit]:
|
) -> List[schemas.Audit]:
|
||||||
"""
|
|
||||||
Retrieve a list of audit logs with pagination support.
|
|
||||||
"""
|
|
||||||
def get_fullname(id):
|
|
||||||
user = crud.user.get_by_id(db, id=id)
|
|
||||||
if user:
|
|
||||||
return user.username
|
|
||||||
return ""
|
|
||||||
|
|
||||||
logs = crud.audit.get_multi_desc(db, skip=skip, limit=limit)
|
logs = crud.audit.get_multi_desc(db, skip=skip, limit=limit)
|
||||||
logs = [
|
return convert_audit_logs(db, logs)
|
||||||
schemas.Audit(
|
|
||||||
id=dep.id,
|
|
||||||
model=dep.model,
|
|
||||||
username=get_fullname(dep.user_id),
|
|
||||||
details=dep.details,
|
|
||||||
action=dep.action,
|
|
||||||
timestamp=dep.timestamp,
|
|
||||||
ip_address=dep.ip_address,
|
|
||||||
)
|
|
||||||
for dep in logs
|
|
||||||
]
|
|
||||||
return logs
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("filter/", response_model=List[schemas.Audit])
|
@router.get("filter/", response_model=List[schemas.Audit])
|
||||||
def filter_auditlog(
|
def filter_auditlog(
|
||||||
|
|
@ -55,30 +49,27 @@ def filter_auditlog(
|
||||||
scopes=[Role.SUPER_ADMIN["name"]],
|
scopes=[Role.SUPER_ADMIN["name"]],
|
||||||
),
|
),
|
||||||
) -> List[schemas.Audit]:
|
) -> List[schemas.Audit]:
|
||||||
"""
|
|
||||||
Retrieve a list of audit logs with pagination support.
|
|
||||||
"""
|
|
||||||
def get_fullname(id):
|
|
||||||
user = crud.user.get_by_id(db, id=id)
|
|
||||||
if user:
|
|
||||||
return user.username
|
|
||||||
return ""
|
|
||||||
|
|
||||||
logs = crud.audit.filter(db, obj_in=filter_in)
|
logs = crud.audit.filter(db, obj_in=filter_in)
|
||||||
logs = [
|
return convert_audit_logs(db, logs)
|
||||||
schemas.Audit(
|
|
||||||
id=dep.id,
|
|
||||||
model=dep.model,
|
|
||||||
username=get_fullname(dep.user_id),
|
|
||||||
details=dep.details,
|
|
||||||
action=dep.action,
|
|
||||||
timestamp=dep.timestamp,
|
|
||||||
ip_address=dep.ip_address,
|
|
||||||
)
|
|
||||||
for dep in logs
|
|
||||||
]
|
|
||||||
return logs
|
|
||||||
|
|
||||||
|
@router.get("download/")
|
||||||
|
def download_auditlog(
|
||||||
|
db: Session = Depends(deps.get_db),
|
||||||
|
filter_in= Depends(schemas.ExcelFilter),
|
||||||
|
current_user: models.User = Security(
|
||||||
|
deps.get_current_user,
|
||||||
|
scopes=[Role.SUPER_ADMIN["name"]],
|
||||||
|
),
|
||||||
|
):
|
||||||
|
logs = crud.audit.excel_filter(db, obj_in=filter_in)
|
||||||
|
username = filter_in.username if filter_in.username else None
|
||||||
|
logs = convert_audit_logs(db, logs, username)
|
||||||
|
excel_buffer = generate_audit_log_report(logs, username)
|
||||||
|
return StreamingResponse(
|
||||||
|
iter([excel_buffer.getvalue()]),
|
||||||
|
media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||||
|
headers={"Content-Disposition": "attachment;filename=audit_logs.xlsx"},
|
||||||
|
)
|
||||||
|
|
||||||
@router.post("", response_model=schemas.Audit)
|
@router.post("", response_model=schemas.Audit)
|
||||||
def get_auditlog(
|
def get_auditlog(
|
||||||
|
|
@ -89,23 +80,5 @@ def get_auditlog(
|
||||||
scopes=[Role.SUPER_ADMIN["name"]],
|
scopes=[Role.SUPER_ADMIN["name"]],
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
"""
|
|
||||||
Retrieve a single audit log.
|
|
||||||
"""
|
|
||||||
def get_fullname(id):
|
|
||||||
user = crud.user.get_by_id(db, id=id)
|
|
||||||
if user:
|
|
||||||
return user.username
|
|
||||||
return ""
|
|
||||||
|
|
||||||
logs = crud.audit.get_by_id(db, id=audit.id)
|
logs = crud.audit.get_by_id(db, id=audit.id)
|
||||||
logs = schemas.Audit(
|
return convert_audit_logs(db, [logs])[0]
|
||||||
id=logs.id,
|
|
||||||
model=logs.model,
|
|
||||||
username=get_fullname(logs.user_id),
|
|
||||||
details=logs.details,
|
|
||||||
action=logs.action,
|
|
||||||
timestamp=logs.timestamp,
|
|
||||||
ip_address=logs.ip_address,
|
|
||||||
)
|
|
||||||
return logs
|
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,6 @@ router = APIRouter(prefix="/c", tags=["Chat Histories"])
|
||||||
@router.get("", response_model=list[schemas.ChatHistory])
|
@router.get("", response_model=list[schemas.ChatHistory])
|
||||||
def list_chat_histories(
|
def list_chat_histories(
|
||||||
db: Session = Depends(deps.get_db),
|
db: Session = Depends(deps.get_db),
|
||||||
skip: int = 0,
|
|
||||||
limit: int = 100,
|
|
||||||
current_user: models.User = Security(
|
current_user: models.User = Security(
|
||||||
deps.get_current_user,
|
deps.get_current_user,
|
||||||
),
|
),
|
||||||
|
|
@ -26,7 +24,7 @@ def list_chat_histories(
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
chat_histories = crud.chat.get_chat_history(
|
chat_histories = crud.chat.get_chat_history(
|
||||||
db, user_id=current_user.id, skip=skip, limit=limit)
|
db, user_id=current_user.id)
|
||||||
return chat_histories
|
return chat_histories
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ from sqlalchemy.orm import Session
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
from fastapi.encoders import jsonable_encoder
|
from fastapi.encoders import jsonable_encoder
|
||||||
from fastapi import APIRouter, Depends, HTTPException, status, Security
|
from fastapi import APIRouter, Depends, HTTPException, status, Security
|
||||||
|
from fastapi_pagination import Page, paginate
|
||||||
|
|
||||||
from private_gpt.users.api import deps
|
from private_gpt.users.api import deps
|
||||||
from private_gpt.users.constants.role import Role
|
from private_gpt.users.constants.role import Role
|
||||||
|
|
@ -13,21 +14,19 @@ from private_gpt.users import crud, models, schemas
|
||||||
router = APIRouter(prefix="/companies", tags=["Companies"])
|
router = APIRouter(prefix="/companies", tags=["Companies"])
|
||||||
|
|
||||||
|
|
||||||
@router.get("", response_model=List[schemas.Company])
|
@router.get("", response_model=Page[schemas.Company])
|
||||||
def list_companies(
|
def list_companies(
|
||||||
db: Session = Depends(deps.get_db),
|
db: Session = Depends(deps.get_db),
|
||||||
skip: int = 0,
|
|
||||||
limit: int = 100,
|
|
||||||
current_user: models.User = Security(
|
current_user: models.User = Security(
|
||||||
deps.get_current_user,
|
deps.get_current_user,
|
||||||
scopes=[Role.SUPER_ADMIN["name"]],
|
scopes=[Role.SUPER_ADMIN["name"]],
|
||||||
),
|
),
|
||||||
) -> List[schemas.Company]:
|
) -> Page[schemas.Company]:
|
||||||
"""
|
"""
|
||||||
Retrieve a list of companies with pagination support.
|
Retrieve a list of companies with pagination support.
|
||||||
"""
|
"""
|
||||||
companies = crud.company.get_multi(db, skip=skip, limit=limit)
|
companies = crud.company.get_multi(db)
|
||||||
return companies
|
return paginate(companies)
|
||||||
|
|
||||||
|
|
||||||
@router.post("/create", response_model=schemas.Company)
|
@router.post("/create", response_model=schemas.Company)
|
||||||
|
|
@ -54,21 +53,19 @@ def create_company(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.get("", response_model=List[schemas.Company])
|
@router.get("", response_model=Page[schemas.Company])
|
||||||
def list_companies(
|
def list_companies(
|
||||||
db: Session = Depends(deps.get_db),
|
db: Session = Depends(deps.get_db),
|
||||||
skip: int = 0,
|
|
||||||
limit: int = 100,
|
|
||||||
current_user: models.User = Security(
|
current_user: models.User = Security(
|
||||||
deps.get_current_user,
|
deps.get_current_user,
|
||||||
scopes=[Role.SUPER_ADMIN["name"]],
|
scopes=[Role.SUPER_ADMIN["name"]],
|
||||||
),
|
),
|
||||||
) -> List[schemas.Company]:
|
) -> Page[schemas.Company]:
|
||||||
"""
|
"""
|
||||||
Retrieve a list of companies with pagination support.
|
Retrieve a list of companies with pagination support.
|
||||||
"""
|
"""
|
||||||
companies = crud.company.get_multi(db, skip=skip, limit=limit)
|
companies = crud.company.get_multi(db)
|
||||||
return companies
|
return paginate(companies)
|
||||||
|
|
||||||
@router.get("/{company_id}", response_model=schemas.Company)
|
@router.get("/{company_id}", response_model=schemas.Company)
|
||||||
def read_company(
|
def read_company(
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import traceback
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
from fastapi.encoders import jsonable_encoder
|
from fastapi.encoders import jsonable_encoder
|
||||||
|
from fastapi_pagination import Page, paginate
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException, status, Security, Request
|
from fastapi import APIRouter, Depends, HTTPException, status, Security, Request
|
||||||
|
|
||||||
from private_gpt.users.api import deps
|
from private_gpt.users.api import deps
|
||||||
|
|
@ -35,25 +37,23 @@ def log_audit_department(
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
|
|
||||||
|
|
||||||
@router.get("", response_model=list[schemas.Department])
|
@router.get("", response_model=Page[schemas.Department])
|
||||||
def list_departments(
|
def list_departments(
|
||||||
db: Session = Depends(deps.get_db),
|
db: Session = Depends(deps.get_db),
|
||||||
skip: int = 0,
|
|
||||||
limit: int = 100,
|
|
||||||
current_user: models.User = Security(
|
current_user: models.User = Security(
|
||||||
deps.get_current_user,
|
deps.get_current_user,
|
||||||
),
|
),
|
||||||
) -> list[schemas.Department]:
|
) -> Page[schemas.Department]:
|
||||||
"""
|
"""
|
||||||
Retrieve a list of departments with pagination support.
|
Retrieve a list of departments with pagination support.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
role = current_user.user_role.role.name if current_user.user_role else None
|
role = current_user.user_role.role.name if current_user.user_role else None
|
||||||
if role == "SUPER_ADMIN":
|
if role == "SUPER_ADMIN":
|
||||||
deps = crud.department.get_multi(db, skip=skip, limit=limit)
|
deps = crud.department.get_multi(db)
|
||||||
else:
|
else:
|
||||||
deps = crud.department.get_multi_department(
|
deps = crud.department.get_multi_department(
|
||||||
db, department_id=current_user.department_id, skip=skip, limit=limit)
|
db, department_id=current_user.department_id)
|
||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
schemas.Department(
|
schemas.Department(
|
||||||
|
|
@ -64,7 +64,7 @@ def list_departments(
|
||||||
)
|
)
|
||||||
for dep in deps
|
for dep in deps
|
||||||
]
|
]
|
||||||
return deps
|
return paginate(deps)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
logger.error(f"There was an error listing the file(s).")
|
logger.error(f"There was an error listing the file(s).")
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ from datetime import datetime
|
||||||
from typing import Any, List
|
from typing import Any, List
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
|
from fastapi_pagination import Page, paginate
|
||||||
from fastapi import APIRouter, Depends, HTTPException, status, Security, Request, File, UploadFile
|
from fastapi import APIRouter, Depends, HTTPException, status, Security, Request, File, UploadFile
|
||||||
|
|
||||||
from private_gpt.users.api import deps
|
from private_gpt.users.api import deps
|
||||||
|
|
@ -17,28 +18,28 @@ from private_gpt.users import crud, models, schemas
|
||||||
from private_gpt.server.ingest.ingest_router import create_documents, ingest
|
from private_gpt.server.ingest.ingest_router import create_documents, ingest
|
||||||
from private_gpt.users.models.document import MakerCheckerActionType, MakerCheckerStatus
|
from private_gpt.users.models.document import MakerCheckerActionType, MakerCheckerStatus
|
||||||
from private_gpt.components.ocr_components.table_ocr_api import process_both_ocr, process_ocr
|
from private_gpt.components.ocr_components.table_ocr_api import process_both_ocr, process_ocr
|
||||||
from fastapi_filter import FilterDepends, with_prefix
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
router = APIRouter(prefix='/documents', tags=['Documents'])
|
router = APIRouter(prefix='/documents', tags=['Documents'])
|
||||||
|
|
||||||
|
|
||||||
|
CHECKER = False
|
||||||
|
ENABLE_MAKER = False
|
||||||
|
|
||||||
def get_username(db, id):
|
def get_username(db, id):
|
||||||
user = crud.user.get_by_id(db=db, id=id)
|
user = crud.user.get_by_id(db=db, id=id)
|
||||||
return user.username
|
return user.username
|
||||||
|
|
||||||
CHECKER = True
|
|
||||||
|
|
||||||
@router.get("", response_model=List[schemas.DocumentView])
|
@router.get("")
|
||||||
def list_files(
|
def list_files(
|
||||||
request: Request,
|
request: Request,
|
||||||
db: Session = Depends(deps.get_db),
|
db: Session = Depends(deps.get_db),
|
||||||
skip: int = 0,
|
|
||||||
limit: int = 100,
|
|
||||||
current_user: models.User = Security(
|
current_user: models.User = Security(
|
||||||
deps.get_current_user,
|
deps.get_current_user,
|
||||||
scopes=[Role.ADMIN["name"], Role.SUPER_ADMIN["name"], Role.OPERATOR["name"]],
|
scopes=[Role.ADMIN["name"], Role.SUPER_ADMIN["name"], Role.OPERATOR["name"]],
|
||||||
)
|
)
|
||||||
):
|
)-> Page[schemas.DocumentView]:
|
||||||
"""
|
"""
|
||||||
List the documents based on the role.
|
List the documents based on the role.
|
||||||
"""
|
"""
|
||||||
|
|
@ -47,10 +48,10 @@ def list_files(
|
||||||
role = current_user.user_role.role.name if current_user.user_role else None
|
role = current_user.user_role.role.name if current_user.user_role else None
|
||||||
if (role == "SUPER_ADMIN") or (role == "OPERATOR"):
|
if (role == "SUPER_ADMIN") or (role == "OPERATOR"):
|
||||||
docs = crud.documents.get_multi_documents(
|
docs = crud.documents.get_multi_documents(
|
||||||
db, skip=skip, limit=limit)
|
db)
|
||||||
else:
|
else:
|
||||||
docs = crud.documents.get_documents_by_departments(
|
docs = crud.documents.get_documents_by_departments(
|
||||||
db, department_id=current_user.department_id, skip=skip, limit=limit)
|
db, department_id=current_user.department_id)
|
||||||
|
|
||||||
documents = [
|
documents = [
|
||||||
schemas.DocumentView(
|
schemas.DocumentView(
|
||||||
|
|
@ -68,7 +69,7 @@ def list_files(
|
||||||
)
|
)
|
||||||
for doc in docs
|
for doc in docs
|
||||||
]
|
]
|
||||||
return documents
|
return paginate(documents)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
logger.error(f"There was an error listing the file(s).")
|
logger.error(f"There was an error listing the file(s).")
|
||||||
|
|
@ -78,12 +79,10 @@ def list_files(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/pending", response_model=List[schemas.DocumentVerify])
|
@router.get("/pending", response_model=Page[schemas.DocumentVerify])
|
||||||
def list_pending_files(
|
def list_pending_files(
|
||||||
request: Request,
|
request: Request,
|
||||||
db: Session = Depends(deps.get_db),
|
db: Session = Depends(deps.get_db),
|
||||||
skip: int = 0,
|
|
||||||
limit: int = 100,
|
|
||||||
current_user: models.User = Security(
|
current_user: models.User = Security(
|
||||||
deps.get_current_user,
|
deps.get_current_user,
|
||||||
scopes=[Role.SUPER_ADMIN["name"], Role.OPERATOR["name"]],
|
scopes=[Role.SUPER_ADMIN["name"], Role.OPERATOR["name"]],
|
||||||
|
|
@ -98,7 +97,8 @@ def list_pending_files(
|
||||||
|
|
||||||
try:
|
try:
|
||||||
docs = crud.documents.get_files_to_verify(
|
docs = crud.documents.get_files_to_verify(
|
||||||
db, department_id=current_user.department_id, skip=skip, limit=limit)
|
db
|
||||||
|
)
|
||||||
|
|
||||||
documents = [
|
documents = [
|
||||||
schemas.DocumentVerify(
|
schemas.DocumentVerify(
|
||||||
|
|
@ -114,7 +114,7 @@ def list_pending_files(
|
||||||
)
|
)
|
||||||
for doc in docs
|
for doc in docs
|
||||||
]
|
]
|
||||||
return documents
|
return paginate(documents)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
logger.error(f"There was an error listing the file(s).")
|
logger.error(f"There was an error listing the file(s).")
|
||||||
|
|
@ -123,13 +123,11 @@ def list_pending_files(
|
||||||
detail="Internal Server Error",
|
detail="Internal Server Error",
|
||||||
)
|
)
|
||||||
|
|
||||||
@router.get('{department_id}', response_model=List[schemas.DocumentList])
|
@router.get('{department_id}', response_model=Page[schemas.DocumentList])
|
||||||
def list_files_by_department(
|
def list_files_by_department(
|
||||||
request: Request,
|
request: Request,
|
||||||
department_id: int,
|
department_id: int,
|
||||||
db: Session = Depends(deps.get_db),
|
db: Session = Depends(deps.get_db),
|
||||||
skip: int = 0,
|
|
||||||
limit: int = 100,
|
|
||||||
current_user: models.User = Security(
|
current_user: models.User = Security(
|
||||||
deps.get_current_user,
|
deps.get_current_user,
|
||||||
scopes=[Role.SUPER_ADMIN["name"]],
|
scopes=[Role.SUPER_ADMIN["name"]],
|
||||||
|
|
@ -140,8 +138,8 @@ def list_files_by_department(
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
docs = crud.documents.get_documents_by_departments(
|
docs = crud.documents.get_documents_by_departments(
|
||||||
db, department_id=department_id, skip=skip, limit=limit)
|
db, department_id=department_id)
|
||||||
return docs
|
return paginate(docs)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
logger.error(f"There was an error listing the file(s).")
|
logger.error(f"There was an error listing the file(s).")
|
||||||
|
|
@ -151,12 +149,10 @@ def list_files_by_department(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.get('/files', response_model=List[schemas.DocumentList])
|
@router.get('/files', response_model=Page[schemas.DocumentList])
|
||||||
def list_files_by_department(
|
def list_files_by_department(
|
||||||
request: Request,
|
request: Request,
|
||||||
db: Session = Depends(deps.get_db),
|
db: Session = Depends(deps.get_db),
|
||||||
skip: int = 0,
|
|
||||||
limit: int = 100,
|
|
||||||
current_user: models.User = Security(
|
current_user: models.User = Security(
|
||||||
deps.get_current_user,
|
deps.get_current_user,
|
||||||
scopes=[Role.ADMIN["name"], Role.SUPER_ADMIN["name"], Role.OPERATOR["name"]],
|
scopes=[Role.ADMIN["name"], Role.SUPER_ADMIN["name"], Role.OPERATOR["name"]],
|
||||||
|
|
@ -168,8 +164,8 @@ def list_files_by_department(
|
||||||
try:
|
try:
|
||||||
department_id = current_user.department_id
|
department_id = current_user.department_id
|
||||||
docs = crud.documents.get_documents_by_departments(
|
docs = crud.documents.get_documents_by_departments(
|
||||||
db, department_id=department_id, skip=skip, limit=limit)
|
db, department_id=department_id)
|
||||||
return docs
|
return paginate(docs)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
logger.error(f"There was an error listing the file(s).")
|
logger.error(f"There was an error listing the file(s).")
|
||||||
|
|
@ -293,6 +289,7 @@ async def upload_documents(
|
||||||
contents = await file.read()
|
contents = await file.read()
|
||||||
async with aiofiles.open(upload_path, 'wb') as f:
|
async with aiofiles.open(upload_path, 'wb') as f:
|
||||||
await f.write(contents)
|
await f.write(contents)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
|
@ -301,6 +298,13 @@ async def upload_documents(
|
||||||
document = await create_documents(db, original_filename, current_user, departments, log_audit)
|
document = await create_documents(db, original_filename, current_user, departments, log_audit)
|
||||||
logger.info(
|
logger.info(
|
||||||
f"{original_filename} is uploaded by {current_user.username} in {departments.departments_ids}")
|
f"{original_filename} is uploaded by {current_user.username} in {departments.departments_ids}")
|
||||||
|
|
||||||
|
if not ENABLE_MAKER:
|
||||||
|
checker_in = schemas.DocumentUpdate(
|
||||||
|
id=document.id,
|
||||||
|
status=MakerCheckerStatus.APPROVED.value
|
||||||
|
)
|
||||||
|
await verify_documents(request=request, checker_in=checker_in, db=db, log_audit=log_audit, current_user=current_user)
|
||||||
return document
|
return document
|
||||||
|
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
|
|
@ -338,24 +342,25 @@ async def verify_documents(
|
||||||
detail="Document not found!",
|
detail="Document not found!",
|
||||||
)
|
)
|
||||||
|
|
||||||
if document.verified:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
|
||||||
detail="Document already verified!",
|
|
||||||
)
|
|
||||||
if CHECKER:
|
if CHECKER:
|
||||||
print("Current user is checker: ", current_user.checker)
|
if document.verified:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail="Document already verified!",
|
||||||
|
)
|
||||||
|
|
||||||
if not current_user.checker:
|
if not current_user.checker:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
detail="You are not the checker!",
|
detail="You are not the checker!",
|
||||||
)
|
)
|
||||||
|
|
||||||
if document.uploaded_by == current_user.id:
|
if document.uploaded_by == current_user.id:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
detail="Cannot verify by same user!",
|
detail="Cannot verify by same user!",
|
||||||
)
|
)
|
||||||
|
|
||||||
unchecked_path = Path(f"{UNCHECKED_DIR}/{document.filename}")
|
unchecked_path = Path(f"{UNCHECKED_DIR}/{document.filename}")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ from typing import Any, List
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
from fastapi.encoders import jsonable_encoder
|
from fastapi.encoders import jsonable_encoder
|
||||||
|
from fastapi_pagination import Page, paginate
|
||||||
from fastapi import APIRouter, Body, Depends, HTTPException, Security, status, Path, Request
|
from fastapi import APIRouter, Body, Depends, HTTPException, Security, status, Path, Request
|
||||||
|
|
||||||
from private_gpt.users.api import deps
|
from private_gpt.users.api import deps
|
||||||
|
|
@ -36,10 +37,8 @@ def log_audit_user(
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
|
|
||||||
|
|
||||||
@router.get("", response_model=List[schemas.User])
|
@router.get("", response_model=Page[schemas.User])
|
||||||
def read_users(
|
def read_users(
|
||||||
skip: int = 0,
|
|
||||||
limit: int = 100,
|
|
||||||
db: Session = Depends(deps.get_db),
|
db: Session = Depends(deps.get_db),
|
||||||
current_user: models.User = Security(
|
current_user: models.User = Security(
|
||||||
deps.get_current_user,
|
deps.get_current_user,
|
||||||
|
|
@ -53,11 +52,11 @@ def read_users(
|
||||||
if role == "ADMIN":
|
if role == "ADMIN":
|
||||||
users = crud.user.get_by_department_id(db=db, department_id=current_user.department_id, skip=skip, limit=limit)
|
users = crud.user.get_by_department_id(db=db, department_id=current_user.department_id, skip=skip, limit=limit)
|
||||||
else:
|
else:
|
||||||
users = crud.user.get_multi(db, skip=skip, limit=limit)
|
users = crud.user.get_multi(db)
|
||||||
return users
|
return paginate(users)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/company/{company_id}", response_model=List[schemas.User])
|
@router.get("/company/{company_id}", response_model=Page[schemas.User])
|
||||||
def read_users_by_company(
|
def read_users_by_company(
|
||||||
company_id: int = Path(..., title="Company ID",
|
company_id: int = Path(..., title="Company ID",
|
||||||
description="Only for company admin"),
|
description="Only for company admin"),
|
||||||
|
|
@ -77,7 +76,7 @@ def read_users_by_company(
|
||||||
)
|
)
|
||||||
|
|
||||||
users = crud.user.get_multi_by_company_id(db, company_id=company.id)
|
users = crud.user.get_multi_by_company_id(db, company_id=company.id)
|
||||||
return users
|
return paginate(users)
|
||||||
|
|
||||||
|
|
||||||
@router.post("", response_model=schemas.User)
|
@router.post("", response_model=schemas.User)
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,31 @@ class CRUDAudit(CRUDBase[Audit, AuditCreate, AuditUpdate]):
|
||||||
|
|
||||||
return query.order_by(desc(self.model.timestamp)).offset(obj_in.skip).limit(obj_in.limit).all()
|
return query.order_by(desc(self.model.timestamp)).offset(obj_in.skip).limit(obj_in.limit).all()
|
||||||
|
|
||||||
|
|
||||||
|
def excel_filter(
|
||||||
|
self, db: Session, *, obj_in : AuditFilter
|
||||||
|
) -> List[Audit]:
|
||||||
|
|
||||||
|
def get_id(username):
|
||||||
|
user = crud.user.get_by_name(db, name=username)
|
||||||
|
if user:
|
||||||
|
return user.id
|
||||||
|
return None
|
||||||
|
query = db.query(Audit)
|
||||||
|
if obj_in.model:
|
||||||
|
query = query.filter(Audit.model == obj_in.model)
|
||||||
|
if obj_in.username:
|
||||||
|
query = query.filter(Audit.user_id == get_id(obj_in.username))
|
||||||
|
if obj_in.action:
|
||||||
|
query = query.filter(Audit.action == obj_in.action)
|
||||||
|
if obj_in.start_date:
|
||||||
|
query = query.filter(Audit.timestamp >= obj_in.start_date)
|
||||||
|
if obj_in.end_date:
|
||||||
|
query = query.filter(Audit.timestamp <= obj_in.end_date)
|
||||||
|
|
||||||
|
return query.order_by(desc(self.model.timestamp)).all()
|
||||||
|
|
||||||
|
|
||||||
def get_by_id(self, db: Session, *, id: str) -> Optional[Audit]:
|
def get_by_id(self, db: Session, *, id: str) -> Optional[Audit]:
|
||||||
return db.query(self.model).filter(Audit.id == id).first()
|
return db.query(self.model).filter(Audit.id == id).first()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,9 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
|
||||||
self.model = model
|
self.model = model
|
||||||
|
|
||||||
def get_multi(
|
def get_multi(
|
||||||
self, db: Session, *, skip: int = 0, limit: int = 100
|
self, db: Session,
|
||||||
) -> List[ModelType]:
|
) -> List[ModelType]:
|
||||||
return db.query(self.model).offset(skip).limit(limit).all()
|
return db.query(self.model).all()
|
||||||
|
|
||||||
def get(self, db: Session, id: int) -> Optional[ModelType]:
|
def get(self, db: Session, id: int) -> Optional[ModelType]:
|
||||||
return db.query(self.model).filter(self.model.id == id).first()
|
return db.query(self.model).filter(self.model.id == id).first()
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,12 @@ class CRUDChat(CRUDBase[ChatHistory, ChatHistoryCreate, ChatHistoryCreate]):
|
||||||
return chat_history
|
return chat_history
|
||||||
|
|
||||||
def get_chat_history(
|
def get_chat_history(
|
||||||
self, db: Session, *,user_id:int, skip: int = 0, limit: int = 100
|
self, db: Session, *,user_id:int
|
||||||
) -> List[ChatHistory]:
|
) -> List[ChatHistory]:
|
||||||
return (
|
return (
|
||||||
db.query(self.model)
|
db.query(self.model)
|
||||||
.filter(ChatHistory.user_id == user_id)
|
.filter(ChatHistory.user_id == user_id)
|
||||||
.order_by(desc(getattr(ChatHistory, 'created_at')))
|
.order_by(desc(getattr(ChatHistory, 'created_at')))
|
||||||
.offset(skip)
|
|
||||||
.limit(limit)
|
|
||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,11 @@ class CRUDDepartments(CRUDBase[Department, DepartmentCreate, DepartmentUpdate]):
|
||||||
return db.query(self.model).filter(Department.name == name).first()
|
return db.query(self.model).filter(Department.name == name).first()
|
||||||
|
|
||||||
def get_multi_department(
|
def get_multi_department(
|
||||||
self, db: Session, *, department_id: int, skip: int = 0, limit: int = 100
|
self, db: Session, *, department_id: int
|
||||||
) -> List[Department]:
|
) -> List[Department]:
|
||||||
return (
|
return (
|
||||||
db.query(self.model)
|
db.query(self.model)
|
||||||
.filter(Department.id == department_id)
|
.filter(Department.id == department_id)
|
||||||
.offset(skip)
|
|
||||||
.limit(limit)
|
|
||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
department = CRUDDepartments(Department)
|
department = CRUDDepartments(Department)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ from private_gpt.users.models.department import Department
|
||||||
from private_gpt.users.models.document_department import document_department_association
|
from private_gpt.users.models.document_department import document_department_association
|
||||||
from private_gpt.users.crud.base import CRUDBase
|
from private_gpt.users.crud.base import CRUDBase
|
||||||
from typing import Optional, List
|
from typing import Optional, List
|
||||||
|
from fastapi_pagination import Page, paginate
|
||||||
|
|
||||||
|
|
||||||
class CRUDDocuments(CRUDBase[Document, DocumentCreate, DocumentUpdate]):
|
class CRUDDocuments(CRUDBase[Document, DocumentCreate, DocumentUpdate]):
|
||||||
|
|
@ -17,18 +18,16 @@ class CRUDDocuments(CRUDBase[Document, DocumentCreate, DocumentUpdate]):
|
||||||
return db.query(self.model).filter(Document.filename == file_name).first()
|
return db.query(self.model).filter(Document.filename == file_name).first()
|
||||||
|
|
||||||
def get_multi_documents(
|
def get_multi_documents(
|
||||||
self, db: Session, *, skip: int = 0, limit: int = 100
|
self, db: Session,
|
||||||
) -> List[Document]:
|
) -> List[Document]:
|
||||||
return (
|
return (
|
||||||
db.query(self.model)
|
db.query(self.model)
|
||||||
.order_by(desc(getattr(Document, 'uploaded_at')))
|
.order_by(desc(getattr(Document, 'uploaded_at')))
|
||||||
.offset(skip)
|
|
||||||
.limit(limit)
|
|
||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_documents_by_departments(
|
def get_documents_by_departments(
|
||||||
self, db: Session, *, department_id: int, skip: int = 0, limit: int = 100
|
self, db: Session, *, department_id: int
|
||||||
) -> List[Document]:
|
) -> List[Document]:
|
||||||
return (
|
return (
|
||||||
db.query(self.model)
|
db.query(self.model)
|
||||||
|
|
@ -36,24 +35,20 @@ class CRUDDocuments(CRUDBase[Document, DocumentCreate, DocumentUpdate]):
|
||||||
.join(Department)
|
.join(Department)
|
||||||
.filter(document_department_association.c.department_id == department_id)
|
.filter(document_department_association.c.department_id == department_id)
|
||||||
.order_by(desc(getattr(Document, 'uploaded_at')))
|
.order_by(desc(getattr(Document, 'uploaded_at')))
|
||||||
.offset(skip)
|
|
||||||
.limit(limit)
|
|
||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_files_to_verify(
|
def get_files_to_verify(
|
||||||
self, db: Session, *, skip: int = 0, limit: int = 100
|
self, db: Session,
|
||||||
) -> List[Document]:
|
) -> List[Document]:
|
||||||
return (
|
return (
|
||||||
db.query(self.model)
|
db.query(self.model)
|
||||||
.filter(Document.status == 'PENDING')
|
.filter(Document.status == 'PENDING')
|
||||||
.offset(skip)
|
|
||||||
.limit(limit)
|
|
||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_enabled_documents_by_departments(
|
def get_enabled_documents_by_departments(
|
||||||
self, db: Session, *, department_id: int, skip: int = 0, limit: int = 100
|
self, db: Session, *, department_id: int
|
||||||
) -> List[Document]:
|
) -> List[Document]:
|
||||||
all_department_id = 1 # department ID for "ALL" is 1
|
all_department_id = 1 # department ID for "ALL" is 1
|
||||||
|
|
||||||
|
|
@ -73,8 +68,6 @@ class CRUDDocuments(CRUDBase[Document, DocumentCreate, DocumentUpdate]):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.offset(skip)
|
|
||||||
.limit(limit)
|
|
||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -85,8 +78,6 @@ class CRUDDocuments(CRUDBase[Document, DocumentCreate, DocumentUpdate]):
|
||||||
action_type: Optional[str] = None,
|
action_type: Optional[str] = None,
|
||||||
status: Optional[str] = None,
|
status: Optional[str] = None,
|
||||||
order_by: Optional[str] = None,
|
order_by: Optional[str] = None,
|
||||||
skip: int = 0,
|
|
||||||
limit: int = 100
|
|
||||||
) -> List[Document]:
|
) -> List[Document]:
|
||||||
query = db.query(Document)
|
query = db.query(Document)
|
||||||
if filename:
|
if filename:
|
||||||
|
|
@ -105,6 +96,6 @@ class CRUDDocuments(CRUDBase[Document, DocumentCreate, DocumentUpdate]):
|
||||||
else:
|
else:
|
||||||
query = query.order_by(asc(getattr(Document, 'uploaded_at')))
|
query = query.order_by(asc(getattr(Document, 'uploaded_at')))
|
||||||
|
|
||||||
return query.offset(skip).limit(limit).all()
|
return query.all()
|
||||||
|
|
||||||
documents = CRUDDocuments(Document)
|
documents = CRUDDocuments(Document)
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,9 @@ class CRUDUser(CRUDBase[User, UserCreate, UserUpdate]):
|
||||||
return super().update(db, db_obj=db_obj, obj_in=update_data)
|
return super().update(db, db_obj=db_obj, obj_in=update_data)
|
||||||
|
|
||||||
def get_multi(
|
def get_multi(
|
||||||
self, db: Session, *, skip: int = 0, limit: int = 100,
|
self, db: Session,
|
||||||
) -> List[User]:
|
) -> List[User]:
|
||||||
return db.query(self.model).offset(skip).limit(limit).all()
|
return db.query(self.model).all()
|
||||||
|
|
||||||
def authenticate(
|
def authenticate(
|
||||||
self, db: Session, *, email: str, password: str
|
self, db: Session, *, email: str, password: str
|
||||||
|
|
@ -67,27 +67,21 @@ class CRUDUser(CRUDBase[User, UserCreate, UserUpdate]):
|
||||||
db: Session,
|
db: Session,
|
||||||
*,
|
*,
|
||||||
account_id: int,
|
account_id: int,
|
||||||
skip: int = 0,
|
|
||||||
limit: int = 100,
|
|
||||||
) -> List[User]:
|
) -> List[User]:
|
||||||
return (
|
return (
|
||||||
db.query(self.model)
|
db.query(self.model)
|
||||||
.filter(User.account_id == account_id)
|
.filter(User.account_id == account_id)
|
||||||
.offset(skip)
|
|
||||||
.limit(limit)
|
|
||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_multi_by_company_id(
|
def get_multi_by_company_id(
|
||||||
self, db: Session, *, company_id: str, skip: int = 0, limit: int = 100
|
self, db: Session, *, company_id: str
|
||||||
) -> List[User]:
|
) -> List[User]:
|
||||||
return (
|
return (
|
||||||
db.query(self.model)
|
db.query(self.model)
|
||||||
.join(User.user_role)
|
.join(User.user_role)
|
||||||
.filter(UserRole.company_id == company_id)
|
.filter(UserRole.company_id == company_id)
|
||||||
.options(joinedload(User.user_role).joinedload(UserRole.role))
|
.options(joinedload(User.user_role).joinedload(UserRole.role))
|
||||||
.offset(skip)
|
|
||||||
.limit(limit)
|
|
||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -95,13 +89,11 @@ class CRUDUser(CRUDBase[User, UserCreate, UserUpdate]):
|
||||||
return db.query(self.model).filter(User.username == name).first()
|
return db.query(self.model).filter(User.username == name).first()
|
||||||
|
|
||||||
def get_by_department_id(
|
def get_by_department_id(
|
||||||
self, db: Session, *, department_id: int, skip: int = 0, limit: int = 100
|
self, db: Session, *, department_id: int
|
||||||
) -> List[User]:
|
) -> List[User]:
|
||||||
return (
|
return (
|
||||||
db.query(self.model)
|
db.query(self.model)
|
||||||
.filter(User.department_id == department_id)
|
.filter(User.department_id == department_id)
|
||||||
.offset(skip)
|
|
||||||
.limit(limit)
|
|
||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ from .documents import (
|
||||||
from .department import (
|
from .department import (
|
||||||
Department, DepartmentCreate, DepartmentUpdate, DepartmentAdminCreate, DepartmentDelete
|
Department, DepartmentCreate, DepartmentUpdate, DepartmentAdminCreate, DepartmentDelete
|
||||||
)
|
)
|
||||||
from .audit import AuditBase, AuditCreate, AuditUpdate, Audit, GetAudit, AuditFilter
|
from .audit import AuditBase, AuditCreate, AuditUpdate, Audit, GetAudit, AuditFilter, ExcelFilter
|
||||||
from .chat import (
|
from .chat import (
|
||||||
ChatHistory, ChatHistoryBase, ChatHistoryCreate, ChatHistoryUpdate, ChatDelete,
|
ChatHistory, ChatHistoryBase, ChatHistoryCreate, ChatHistoryUpdate, ChatDelete,
|
||||||
ChatItem, ChatItemBase, ChatItemCreate, ChatItemUpdate, CreateChatHistory
|
ChatItem, ChatItemBase, ChatItemCreate, ChatItemUpdate, CreateChatHistory
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,15 @@ class GetAudit(BaseModel):
|
||||||
|
|
||||||
|
|
||||||
class AuditFilter(BaseModel):
|
class AuditFilter(BaseModel):
|
||||||
skip: Optional[int],
|
skip: int = 0,
|
||||||
limit: Optional[int],
|
limit: int = 100,
|
||||||
|
model: Optional[str] = None
|
||||||
|
username: Optional[str] = None
|
||||||
|
action: Optional[str] = None
|
||||||
|
start_date: Optional[datetime] = None
|
||||||
|
end_date: Optional[datetime] = None
|
||||||
|
|
||||||
|
class ExcelFilter(BaseModel):
|
||||||
model: Optional[str] = None
|
model: Optional[str] = None
|
||||||
username: Optional[str] = None
|
username: Optional[str] = None
|
||||||
action: Optional[str] = None
|
action: Optional[str] = None
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
import io
|
||||||
|
import pandas as pd
|
||||||
|
from typing import List, Optional
|
||||||
|
from private_gpt.users import schemas
|
||||||
|
|
||||||
|
def generate_audit_log_report(audit_logs: List[schemas.Audit], username: Optional[str] = None) -> io.BytesIO:
|
||||||
|
"""
|
||||||
|
Generate an Excel report of the QuickGPT audit logs.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
audit_logs (List[schemas.Audit]): List of audit logs to include in the report.
|
||||||
|
username (str): Username for whom the audit log report is generated.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
io.BytesIO: In-memory Excel file buffer containing the report.
|
||||||
|
"""
|
||||||
|
intro_data = [
|
||||||
|
["Audit Log Report"],
|
||||||
|
["Date:", pd.Timestamp.now().strftime("%Y-%m-%d %H:%M:%S")],
|
||||||
|
[" "],
|
||||||
|
]
|
||||||
|
intro_df = pd.DataFrame(intro_data)
|
||||||
|
|
||||||
|
if username:
|
||||||
|
total_login_counts = get_total_login_counts(audit_logs, username)
|
||||||
|
intro_data.extend([
|
||||||
|
["Username:", username],
|
||||||
|
["Total Login Counts:", total_login_counts],
|
||||||
|
[" "],
|
||||||
|
])
|
||||||
|
|
||||||
|
audit_df = pd.DataFrame([log.dict() for log in audit_logs])
|
||||||
|
excel_buffer = io.BytesIO()
|
||||||
|
|
||||||
|
with pd.ExcelWriter(excel_buffer, engine='xlsxwriter') as writer:
|
||||||
|
intro_df.to_excel(writer, index=False, header=False)
|
||||||
|
if username:
|
||||||
|
audit_df.to_excel(writer, index=False, startrow=len(intro_data) + 2)
|
||||||
|
else:
|
||||||
|
audit_df.to_excel(writer, index=False, startrow=len(intro_data))
|
||||||
|
|
||||||
|
excel_buffer.seek(0)
|
||||||
|
return excel_buffer
|
||||||
|
|
||||||
|
def get_total_login_counts(audit_logs: List[schemas.Audit], username: str) -> int:
|
||||||
|
"""
|
||||||
|
Get the total login counts for the given username.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
audit_logs (List[schemas.Audit]): List of audit logs to search for login events.
|
||||||
|
username (str): Username to get the login counts for.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: Total number of login events for the given username.
|
||||||
|
"""
|
||||||
|
login_events = [log for log in audit_logs if log.model == "login" and log.user == username]
|
||||||
|
return len(login_events)
|
||||||
|
|
@ -54,6 +54,9 @@ aiofiles = "^23.2.1"
|
||||||
timm = "^0.9.16"
|
timm = "^0.9.16"
|
||||||
fastapi-filter = {extras = ["sqlalchemy"], version = "^1.1.0"}
|
fastapi-filter = {extras = ["sqlalchemy"], version = "^1.1.0"}
|
||||||
uuid = "^1.30"
|
uuid = "^1.30"
|
||||||
|
openpyxl = "^3.1.2"
|
||||||
|
pandas = "^2.2.2"
|
||||||
|
fastapi-pagination = "^0.12.23"
|
||||||
|
|
||||||
[tool.poetry.extras]
|
[tool.poetry.extras]
|
||||||
ui = ["gradio"]
|
ui = ["gradio"]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue