Skip to content

Commit 035cfe8

Browse files
[Feature]: Store user SSH key on the server #2053
Review: move `ssh_public_key` to `User` model (from `UserWithCreds`)
1 parent 1b6a7f4 commit 035cfe8

File tree

4 files changed

+23
-4
lines changed

4 files changed

+23
-4
lines changed

src/dstack/_internal/core/models/users.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class User(CoreModel):
3030
email: Optional[str]
3131
active: bool
3232
permissions: UserPermissions
33+
ssh_public_key: Optional[str] = None
3334

3435

3536
class UserTokenCreds(CoreModel):
@@ -38,5 +39,4 @@ class UserTokenCreds(CoreModel):
3839

3940
class UserWithCreds(User):
4041
creds: UserTokenCreds
41-
ssh_public_key: Optional[str] = None
4242
ssh_private_key: Optional[str] = None

src/dstack/_internal/server/services/users.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ def user_model_to_user(user_model: UserModel) -> User:
225225
email=user_model.email,
226226
active=user_model.active,
227227
permissions=get_user_permissions(user_model),
228+
ssh_public_key=user_model.ssh_public_key,
228229
)
229230

230231

@@ -237,8 +238,8 @@ def user_model_to_user_with_creds(user_model: UserModel) -> UserWithCreds:
237238
email=user_model.email,
238239
active=user_model.active,
239240
permissions=get_user_permissions(user_model),
240-
creds=UserTokenCreds(token=user_model.token.get_plaintext_or_error()),
241241
ssh_public_key=user_model.ssh_public_key,
242+
creds=UserTokenCreds(token=user_model.token.get_plaintext_or_error()),
242243
ssh_private_key=user_model.ssh_private_key,
243244
)
244245

src/tests/_internal/server/routers/test_projects.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ async def test_returns_projects(self, test_db, session: AsyncSession, client: As
7777
"permissions": {
7878
"can_create_projects": True,
7979
},
80+
"ssh_public_key": None,
8081
},
8182
"created_at": "2023-01-02T03:04:00+00:00",
8283
"backends": [],
@@ -244,6 +245,7 @@ async def test_creates_project(self, test_db, session: AsyncSession, client: Asy
244245
"permissions": {
245246
"can_create_projects": True,
246247
},
248+
"ssh_public_key": user.ssh_public_key,
247249
},
248250
"created_at": "2023-01-02T03:04:00+00:00",
249251
"backends": [],
@@ -259,6 +261,7 @@ async def test_creates_project(self, test_db, session: AsyncSession, client: Asy
259261
"permissions": {
260262
"can_create_projects": True,
261263
},
264+
"ssh_public_key": user.ssh_public_key,
262265
},
263266
"project_role": ProjectRole.ADMIN,
264267
"permissions": {
@@ -693,6 +696,7 @@ async def test_returns_project(self, test_db, session: AsyncSession, client: Asy
693696
"permissions": {
694697
"can_create_projects": True,
695698
},
699+
"ssh_public_key": None,
696700
},
697701
"created_at": "2023-01-02T03:04:00+00:00",
698702
"backends": [],
@@ -708,6 +712,7 @@ async def test_returns_project(self, test_db, session: AsyncSession, client: Asy
708712
"permissions": {
709713
"can_create_projects": True,
710714
},
715+
"ssh_public_key": None,
711716
},
712717
"project_role": ProjectRole.ADMIN,
713718
"permissions": {
@@ -937,6 +942,7 @@ async def test_sets_project_members(self, test_db, session: AsyncSession, client
937942
"permissions": {
938943
"can_create_projects": True,
939944
},
945+
"ssh_public_key": admin.ssh_public_key,
940946
},
941947
"project_role": ProjectRole.ADMIN,
942948
"permissions": {
@@ -954,6 +960,7 @@ async def test_sets_project_members(self, test_db, session: AsyncSession, client
954960
"permissions": {
955961
"can_create_projects": True,
956962
},
963+
"ssh_public_key": user1.ssh_public_key,
957964
},
958965
"project_role": ProjectRole.ADMIN,
959966
"permissions": {
@@ -971,6 +978,7 @@ async def test_sets_project_members(self, test_db, session: AsyncSession, client
971978
"permissions": {
972979
"can_create_projects": True,
973980
},
981+
"ssh_public_key": user2.ssh_public_key,
974982
},
975983
"project_role": ProjectRole.USER,
976984
"permissions": {
@@ -1027,6 +1035,7 @@ async def test_sets_project_members_by_email(
10271035
"permissions": {
10281036
"can_create_projects": True,
10291037
},
1038+
"ssh_public_key": user1.ssh_public_key,
10301039
},
10311040
"project_role": ProjectRole.ADMIN,
10321041
"permissions": {

src/tests/_internal/server/routers/test_users.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ async def test_admins_see_all_users(self, test_db, session: AsyncSession, client
4848
"permissions": {
4949
"can_create_projects": True,
5050
},
51+
"ssh_public_key": None,
5152
},
5253
{
5354
"id": str(other_user.id),
@@ -59,6 +60,7 @@ async def test_admins_see_all_users(self, test_db, session: AsyncSession, client
5960
"permissions": {
6061
"can_create_projects": True,
6162
},
63+
"ssh_public_key": None,
6264
},
6365
]
6466

@@ -92,6 +94,7 @@ async def test_non_admins_see_only_themselves(
9294
"permissions": {
9395
"can_create_projects": True,
9496
},
97+
"ssh_public_key": None,
9598
}
9699
]
97100

@@ -229,7 +232,9 @@ async def test_creates_user(self, test_db, session: AsyncSession, client: AsyncC
229232
},
230233
)
231234
assert response.status_code == 200
232-
assert response.json() == {
235+
user_data = response.json()
236+
ssh_public_key = user_data["ssh_public_key"]
237+
assert user_data == {
233238
"id": "1b0e1b45-2f8c-4ab6-8010-a0d1a3e44e0e",
234239
"username": "test",
235240
"created_at": "2023-01-02T03:04:00+00:00",
@@ -239,6 +244,7 @@ async def test_creates_user(self, test_db, session: AsyncSession, client: AsyncC
239244
"permissions": {
240245
"can_create_projects": True,
241246
},
247+
"ssh_public_key": ssh_public_key,
242248
}
243249
res = await session.execute(select(UserModel).where(UserModel.name == "test"))
244250
assert len(res.scalars().all()) == 1
@@ -264,7 +270,9 @@ async def test_return_400_if_username_taken(
264270
},
265271
)
266272
assert response.status_code == 200
267-
assert response.json() == {
273+
user_data = response.json()
274+
ssh_public_key = user_data["ssh_public_key"]
275+
assert user_data == {
268276
"id": "1b0e1b45-2f8c-4ab6-8010-a0d1a3e44e0e",
269277
"username": "Test",
270278
"created_at": "2023-01-02T03:04:00+00:00",
@@ -274,6 +282,7 @@ async def test_return_400_if_username_taken(
274282
"permissions": {
275283
"can_create_projects": True,
276284
},
285+
"ssh_public_key": ssh_public_key,
277286
}
278287
# Username uniqueness check should be case insensitive
279288
for username in ["test", "Test", "TesT"]:

0 commit comments

Comments
 (0)