Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
chenpangpang
open-webui
Commits
8f6f7668
Unverified
Commit
8f6f7668
authored
Jul 05, 2024
by
Timothy Jaeryang Baek
Committed by
GitHub
Jul 05, 2024
Browse files
Merge pull request #3595 from open-webui/dev-migration
feat: db migration
parents
97a84918
4e751501
Changes
44
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
375 additions
and
0 deletions
+375
-0
backend/test/apps/webui/routers/test_users.py
backend/test/apps/webui/routers/test_users.py
+168
-0
backend/test/util/abstract_integration_test.py
backend/test/util/abstract_integration_test.py
+161
-0
backend/test/util/mock_user.py
backend/test/util/mock_user.py
+45
-0
backend/utils/utils.py
backend/utils/utils.py
+1
-0
No files found.
backend/test/apps/webui/routers/test_users.py
0 → 100644
View file @
8f6f7668
from
test.util.abstract_integration_test
import
AbstractPostgresTest
from
test.util.mock_user
import
mock_webui_user
def
_get_user_by_id
(
data
,
param
):
return
next
((
item
for
item
in
data
if
item
[
"id"
]
==
param
),
None
)
def
_assert_user
(
data
,
id
,
**
kwargs
):
user
=
_get_user_by_id
(
data
,
id
)
assert
user
is
not
None
comparison_data
=
{
"name"
:
f
"user
{
id
}
"
,
"email"
:
f
"user
{
id
}
@openwebui.com"
,
"profile_image_url"
:
f
"/user
{
id
}
.png"
,
"role"
:
"user"
,
**
kwargs
,
}
for
key
,
value
in
comparison_data
.
items
():
assert
user
[
key
]
==
value
class
TestUsers
(
AbstractPostgresTest
):
BASE_PATH
=
"/api/v1/users"
def
setup_class
(
cls
):
super
().
setup_class
()
from
apps.webui.models.users
import
Users
cls
.
users
=
Users
def
setup_method
(
self
):
super
().
setup_method
()
self
.
users
.
insert_new_user
(
id
=
"1"
,
name
=
"user 1"
,
email
=
"user1@openwebui.com"
,
profile_image_url
=
"/user1.png"
,
role
=
"user"
,
)
self
.
users
.
insert_new_user
(
id
=
"2"
,
name
=
"user 2"
,
email
=
"user2@openwebui.com"
,
profile_image_url
=
"/user2.png"
,
role
=
"user"
,
)
def
test_users
(
self
):
# Get all users
with
mock_webui_user
(
id
=
"3"
):
response
=
self
.
fast_api_client
.
get
(
self
.
create_url
(
""
))
assert
response
.
status_code
==
200
assert
len
(
response
.
json
())
==
2
data
=
response
.
json
()
_assert_user
(
data
,
"1"
)
_assert_user
(
data
,
"2"
)
# update role
with
mock_webui_user
(
id
=
"3"
):
response
=
self
.
fast_api_client
.
post
(
self
.
create_url
(
"/update/role"
),
json
=
{
"id"
:
"2"
,
"role"
:
"admin"
}
)
assert
response
.
status_code
==
200
_assert_user
([
response
.
json
()],
"2"
,
role
=
"admin"
)
# Get all users
with
mock_webui_user
(
id
=
"3"
):
response
=
self
.
fast_api_client
.
get
(
self
.
create_url
(
""
))
assert
response
.
status_code
==
200
assert
len
(
response
.
json
())
==
2
data
=
response
.
json
()
_assert_user
(
data
,
"1"
)
_assert_user
(
data
,
"2"
,
role
=
"admin"
)
# Get (empty) user settings
with
mock_webui_user
(
id
=
"2"
):
response
=
self
.
fast_api_client
.
get
(
self
.
create_url
(
"/user/settings"
))
assert
response
.
status_code
==
200
assert
response
.
json
()
is
None
# Update user settings
with
mock_webui_user
(
id
=
"2"
):
response
=
self
.
fast_api_client
.
post
(
self
.
create_url
(
"/user/settings/update"
),
json
=
{
"ui"
:
{
"attr1"
:
"value1"
,
"attr2"
:
"value2"
},
"model_config"
:
{
"attr3"
:
"value3"
,
"attr4"
:
"value4"
},
},
)
assert
response
.
status_code
==
200
# Get user settings
with
mock_webui_user
(
id
=
"2"
):
response
=
self
.
fast_api_client
.
get
(
self
.
create_url
(
"/user/settings"
))
assert
response
.
status_code
==
200
assert
response
.
json
()
==
{
"ui"
:
{
"attr1"
:
"value1"
,
"attr2"
:
"value2"
},
"model_config"
:
{
"attr3"
:
"value3"
,
"attr4"
:
"value4"
},
}
# Get (empty) user info
with
mock_webui_user
(
id
=
"1"
):
response
=
self
.
fast_api_client
.
get
(
self
.
create_url
(
"/user/info"
))
assert
response
.
status_code
==
200
assert
response
.
json
()
is
None
# Update user info
with
mock_webui_user
(
id
=
"1"
):
response
=
self
.
fast_api_client
.
post
(
self
.
create_url
(
"/user/info/update"
),
json
=
{
"attr1"
:
"value1"
,
"attr2"
:
"value2"
},
)
assert
response
.
status_code
==
200
# Get user info
with
mock_webui_user
(
id
=
"1"
):
response
=
self
.
fast_api_client
.
get
(
self
.
create_url
(
"/user/info"
))
assert
response
.
status_code
==
200
assert
response
.
json
()
==
{
"attr1"
:
"value1"
,
"attr2"
:
"value2"
}
# Get user by id
with
mock_webui_user
(
id
=
"1"
):
response
=
self
.
fast_api_client
.
get
(
self
.
create_url
(
"/2"
))
assert
response
.
status_code
==
200
assert
response
.
json
()
==
{
"name"
:
"user 2"
,
"profile_image_url"
:
"/user2.png"
}
# Update user by id
with
mock_webui_user
(
id
=
"1"
):
response
=
self
.
fast_api_client
.
post
(
self
.
create_url
(
"/2/update"
),
json
=
{
"name"
:
"user 2 updated"
,
"email"
:
"user2-updated@openwebui.com"
,
"profile_image_url"
:
"/user2-updated.png"
,
},
)
assert
response
.
status_code
==
200
# Get all users
with
mock_webui_user
(
id
=
"3"
):
response
=
self
.
fast_api_client
.
get
(
self
.
create_url
(
""
))
assert
response
.
status_code
==
200
assert
len
(
response
.
json
())
==
2
data
=
response
.
json
()
_assert_user
(
data
,
"1"
)
_assert_user
(
data
,
"2"
,
role
=
"admin"
,
name
=
"user 2 updated"
,
email
=
"user2-updated@openwebui.com"
,
profile_image_url
=
"/user2-updated.png"
,
)
# Delete user by id
with
mock_webui_user
(
id
=
"1"
):
response
=
self
.
fast_api_client
.
delete
(
self
.
create_url
(
"/2"
))
assert
response
.
status_code
==
200
# Get all users
with
mock_webui_user
(
id
=
"3"
):
response
=
self
.
fast_api_client
.
get
(
self
.
create_url
(
""
))
assert
response
.
status_code
==
200
assert
len
(
response
.
json
())
==
1
data
=
response
.
json
()
_assert_user
(
data
,
"1"
)
backend/test/util/abstract_integration_test.py
0 → 100644
View file @
8f6f7668
import
logging
import
os
import
time
import
docker
import
pytest
from
docker
import
DockerClient
from
pytest_docker.plugin
import
get_docker_ip
from
fastapi.testclient
import
TestClient
from
sqlalchemy
import
text
,
create_engine
log
=
logging
.
getLogger
(
__name__
)
def
get_fast_api_client
():
from
main
import
app
with
TestClient
(
app
)
as
c
:
return
c
class
AbstractIntegrationTest
:
BASE_PATH
=
None
def
create_url
(
self
,
path
=
""
,
query_params
=
None
):
if
self
.
BASE_PATH
is
None
:
raise
Exception
(
"BASE_PATH is not set"
)
parts
=
self
.
BASE_PATH
.
split
(
"/"
)
parts
=
[
part
.
strip
()
for
part
in
parts
if
part
.
strip
()
!=
""
]
path_parts
=
path
.
split
(
"/"
)
path_parts
=
[
part
.
strip
()
for
part
in
path_parts
if
part
.
strip
()
!=
""
]
query_parts
=
""
if
query_params
:
query_parts
=
"&"
.
join
(
[
f
"
{
key
}
=
{
value
}
"
for
key
,
value
in
query_params
.
items
()]
)
query_parts
=
f
"?
{
query_parts
}
"
return
"/"
.
join
(
parts
+
path_parts
)
+
query_parts
@
classmethod
def
setup_class
(
cls
):
pass
def
setup_method
(
self
):
pass
@
classmethod
def
teardown_class
(
cls
):
pass
def
teardown_method
(
self
):
pass
class
AbstractPostgresTest
(
AbstractIntegrationTest
):
DOCKER_CONTAINER_NAME
=
"postgres-test-container-will-get-deleted"
docker_client
:
DockerClient
@
classmethod
def
_create_db_url
(
cls
,
env_vars_postgres
:
dict
)
->
str
:
host
=
get_docker_ip
()
user
=
env_vars_postgres
[
"POSTGRES_USER"
]
pw
=
env_vars_postgres
[
"POSTGRES_PASSWORD"
]
port
=
8081
db
=
env_vars_postgres
[
"POSTGRES_DB"
]
return
f
"postgresql://
{
user
}
:
{
pw
}
@
{
host
}
:
{
port
}
/
{
db
}
"
@
classmethod
def
setup_class
(
cls
):
super
().
setup_class
()
try
:
env_vars_postgres
=
{
"POSTGRES_USER"
:
"user"
,
"POSTGRES_PASSWORD"
:
"example"
,
"POSTGRES_DB"
:
"openwebui"
,
}
cls
.
docker_client
=
docker
.
from_env
()
cls
.
docker_client
.
containers
.
run
(
"postgres:16.2"
,
detach
=
True
,
environment
=
env_vars_postgres
,
name
=
cls
.
DOCKER_CONTAINER_NAME
,
ports
=
{
5432
:
(
"0.0.0.0"
,
8081
)},
command
=
"postgres -c log_statement=all"
,
)
time
.
sleep
(
0.5
)
database_url
=
cls
.
_create_db_url
(
env_vars_postgres
)
os
.
environ
[
"DATABASE_URL"
]
=
database_url
retries
=
10
db
=
None
while
retries
>
0
:
try
:
from
config
import
BACKEND_DIR
db
=
create_engine
(
database_url
,
pool_pre_ping
=
True
)
db
=
db
.
connect
()
log
.
info
(
"postgres is ready!"
)
break
except
Exception
as
e
:
log
.
warning
(
e
)
time
.
sleep
(
3
)
retries
-=
1
if
db
:
# import must be after setting env!
cls
.
fast_api_client
=
get_fast_api_client
()
db
.
close
()
else
:
raise
Exception
(
"Could not connect to Postgres"
)
except
Exception
as
ex
:
log
.
error
(
ex
)
cls
.
teardown_class
()
pytest
.
fail
(
f
"Could not setup test environment:
{
ex
}
"
)
def
_check_db_connection
(
self
):
from
apps.webui.internal.db
import
Session
retries
=
10
while
retries
>
0
:
try
:
Session
.
execute
(
text
(
"SELECT 1"
))
Session
.
commit
()
break
except
Exception
as
e
:
Session
.
rollback
()
log
.
warning
(
e
)
time
.
sleep
(
3
)
retries
-=
1
def
setup_method
(
self
):
super
().
setup_method
()
self
.
_check_db_connection
()
@
classmethod
def
teardown_class
(
cls
)
->
None
:
super
().
teardown_class
()
cls
.
docker_client
.
containers
.
get
(
cls
.
DOCKER_CONTAINER_NAME
).
remove
(
force
=
True
)
def
teardown_method
(
self
):
from
apps.webui.internal.db
import
Session
# rollback everything not yet committed
Session
.
commit
()
# truncate all tables
tables
=
[
"auth"
,
"chat"
,
"chatidtag"
,
"document"
,
"memory"
,
"model"
,
"prompt"
,
"tag"
,
'"user"'
,
]
for
table
in
tables
:
Session
.
execute
(
text
(
f
"TRUNCATE TABLE
{
table
}
"
))
Session
.
commit
()
backend/test/util/mock_user.py
0 → 100644
View file @
8f6f7668
from
contextlib
import
contextmanager
from
fastapi
import
FastAPI
@
contextmanager
def
mock_webui_user
(
**
kwargs
):
from
apps.webui.main
import
app
with
mock_user
(
app
,
**
kwargs
):
yield
@
contextmanager
def
mock_user
(
app
:
FastAPI
,
**
kwargs
):
from
utils.utils
import
(
get_current_user
,
get_verified_user
,
get_admin_user
,
get_current_user_by_api_key
,
)
from
apps.webui.models.users
import
User
def
create_user
():
user_parameters
=
{
"id"
:
"1"
,
"name"
:
"John Doe"
,
"email"
:
"john.doe@openwebui.com"
,
"role"
:
"user"
,
"profile_image_url"
:
"/user.png"
,
"last_active_at"
:
1627351200
,
"updated_at"
:
1627351200
,
"created_at"
:
162735120
,
**
kwargs
,
}
return
User
(
**
user_parameters
)
app
.
dependency_overrides
=
{
get_current_user
:
create_user
,
get_verified_user
:
create_user
,
get_admin_user
:
create_user
,
get_current_user_by_api_key
:
create_user
,
}
yield
app
.
dependency_overrides
=
{}
backend/utils/utils.py
View file @
8f6f7668
from
fastapi.security
import
HTTPBearer
,
HTTPAuthorizationCredentials
from
fastapi
import
HTTPException
,
status
,
Depends
,
Request
from
sqlalchemy.orm
import
Session
from
apps.webui.models.users
import
Users
...
...
Prev
1
2
3
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment