Skip to content

Commit b00931d

Browse files
authored
Merge pull request #29 from nebulabroadcast/develop
Nebula 6.0.1
2 parents de90902 + 8eef292 commit b00931d

File tree

25 files changed

+704
-197
lines changed

25 files changed

+704
-197
lines changed

backend/api/auth.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from fastapi import Depends, Header, Response
1+
from fastapi import Depends, Header, Response, Request
22
from pydantic import Field
33

44
import nebula
@@ -18,7 +18,7 @@ class LoginRequestModel(RequestModel):
1818
...,
1919
title="Username",
2020
example="admin",
21-
regex=r"^[a-zA-Z0-9_\-\.]{3,}$",
21+
regex=r"^[a-zA-Z0-9_\-\.]{2,}$",
2222
)
2323
password: str = Field(
2424
...,
@@ -53,9 +53,13 @@ class LoginRequest(APIRequest):
5353
name: str = "login"
5454
response_model = LoginResponseModel
5555

56-
async def handle(self, request: LoginRequestModel) -> LoginResponseModel:
57-
user = await nebula.User.login(request.username, request.password)
58-
session = await Session.create(user)
56+
async def handle(
57+
self,
58+
request: Request,
59+
payload: LoginRequestModel,
60+
) -> LoginResponseModel:
61+
user = await nebula.User.login(payload.username, payload.password)
62+
session = await Session.create(user, request)
5963
return LoginResponseModel(access_token=session.token)
6064

6165

backend/api/browse.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"ctime",
2727
"mtime",
2828
"video/fps_f",
29+
"subclips",
2930
]
3031

3132
#
@@ -221,6 +222,10 @@ def build_query(
221222
c2 = f"meta->'assignees' @> '[{user.id}]'::JSONB"
222223
cond_list.append(f"({c1} OR {c2})")
223224

225+
if can_view := user["can/asset_view"]:
226+
if type(can_view) is list:
227+
cond_list.append(f"id_folder IN {sql_list(can_view)}")
228+
224229
# Build conditions
225230

226231
if cond_list:

backend/api/jobs/jobs.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ class JobsRequestModel(ResponseModel):
5252
title="Restart",
5353
description="Restart job with given id",
5454
)
55+
priority: tuple[int, int] | None = Field(
56+
None,
57+
title="Priority",
58+
descriprion="Set priority of job with given id. "
59+
"First value is job id, second is priority",
60+
example=[42, 3],
61+
)
5562

5663

5764
class JobsItemModel(RequestModel):
@@ -66,7 +73,8 @@ class JobsItemModel(RequestModel):
6673
title="User ID",
6774
description="ID of the user who started the job",
6875
)
69-
message: str = Field(None, title="Status description", example="Encoding 24%")
76+
priority: int = Field(3, title="Priority", example=3)
77+
message: str = Field(..., title="Status description", example="Encoding 24%")
7078
ctime: int | None = Field(None, title="Created at", example=f"{int(time.time())}")
7179
stime: int | None = Field(None, title="Started at", example=f"{int(time.time())}")
7280
etime: int | None = Field(None, title="Finished at", example=f"{int(time.time())}")
@@ -161,6 +169,18 @@ async def abort_job(id_job: int, user: nebula.User) -> None:
161169
)
162170

163171

172+
async def set_priority(id_job: int, priority: int, user: nebula.User) -> None:
173+
if not await can_user_control_job(user, id_job):
174+
raise nebula.ForbiddenException("You cannot set priority of this job")
175+
nebula.log.info(f"Setting priority of job {id_job} to {priority}", user=user.name)
176+
query = """
177+
UPDATE jobs SET
178+
priority = $1
179+
WHERE id = $2
180+
"""
181+
await nebula.db.execute(query, priority, id_job)
182+
183+
164184
class JobsRequest(APIRequest):
165185
"""List and control jobs"""
166186

@@ -180,6 +200,9 @@ async def handle(
180200
if request.restart:
181201
await restart_job(request.restart, user)
182202

203+
if request.priority is not None:
204+
await set_priority(request.priority[0], request.priority[1], user)
205+
183206
# Return a list of jobs if requested
184207

185208
conds = []
@@ -223,6 +246,7 @@ async def handle(
223246
j.id_user AS id_user,
224247
j.status AS status,
225248
j.progress AS progress,
249+
j.priority AS priority,
226250
j.message AS message,
227251
j.creation_time AS ctime,
228252
j.start_time AS stime,

backend/api/rundown/models.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class RundownRow(ResponseModel):
1717
id: int = Field(...)
1818
type: Literal["item", "event"] = Field(...)
1919
id_bin: int = Field(...)
20+
id_event: int = Field(...)
2021
scheduled_time: float = Field(...)
2122
broadcast_time: float = Field(...)
2223
meta: dict[str, Any] | None = Field(None)
@@ -35,6 +36,7 @@ class RundownRow(ResponseModel):
3536
loop: bool | None = Field(None)
3637
item_role: ItemMode | None = Field(None)
3738
is_empty: bool = Field(True)
39+
is_primary: bool = Field(False)
3840

3941

4042
class RundownResponseModel(ResponseModel):

backend/api/rundown/rundown.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ async def get_rundown(request: RundownRequestModel) -> RundownResponseModel:
8282
subtitle=event.get("subtitle"),
8383
id_asset=event.get("id_asset"),
8484
id_bin=id_bin,
85+
id_event=id_event,
8586
meta=emeta,
8687
)
8788

@@ -151,10 +152,21 @@ async def get_rundown(request: RundownRequestModel) -> RundownResponseModel:
151152
if asset:
152153
for key in channel.rundown_columns:
153154
if (key in asset.meta) and (
154-
key not in ["title", "subtitle", "id_asset", "duration", "status"]
155+
key
156+
not in [
157+
"title",
158+
"subtitle",
159+
"id_asset",
160+
"duration",
161+
"status",
162+
"mark_in",
163+
"mark_out",
164+
]
155165
):
156166
meta[key] = asset.meta[key]
157167

168+
id_asset = imeta.get("id_asset")
169+
primary = bool(event.get("id_asset") and (event["id_asset"] == id_asset))
158170
row = RundownRow(
159171
id=id_item,
160172
row_number=len(rows),
@@ -166,15 +178,17 @@ async def get_rundown(request: RundownRequestModel) -> RundownResponseModel:
166178
item_role=imeta.get("item_role"),
167179
title=item["title"],
168180
subtitle=item["subtitle"],
169-
id_asset=imeta.get("id_asset"),
181+
id_asset=id_asset,
170182
id_bin=id_bin,
183+
id_event=id_event,
171184
duration=duration,
172185
status=istatus,
173186
transfer_progress=transfer_progress,
174187
asset_mtime=ameta.get("mtime", 0),
175188
mark_in=mark_in,
176189
mark_out=mark_out,
177190
is_empty=False,
191+
is_primary=primary,
178192
meta=meta,
179193
)
180194

backend/api/scheduler/scheduler.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,9 @@ async def scheduler(
156156
# update the event
157157
event_at_position["id_asset"] = event_data.id_asset
158158
for field in channel.fields:
159-
if field.name in asset.meta:
160-
event_at_position[field.name] = asset.meta[field.name]
159+
if field.name in ["color", "start", "stop", "promoted"]:
160+
continue
161+
event_at_position[field.name] = asset[field.name]
161162
affected_events.append(event_at_position.id)
162163
await ex_bin.save()
163164
await event_at_position.save()

backend/api/sessions.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import nebula
2+
3+
from fastapi import Query
4+
from server.session import SessionModel, Session
5+
from server.dependencies import CurrentUser
6+
from server.request import APIRequest
7+
from server.models import RequestModel
8+
9+
class SessionsRequest(RequestModel):
10+
id_user: int = Query(..., example=1)
11+
12+
13+
class Sessions(APIRequest):
14+
name = "sessions"
15+
title = "List sessions"
16+
response_model = list[SessionModel]
17+
18+
async def handle(
19+
self,
20+
request: SessionsRequest,
21+
user: CurrentUser,
22+
) -> list[SessionModel]:
23+
"""Create or update an object."""
24+
25+
id_user = request.id_user
26+
27+
if id_user != user.id and (not user.is_admin):
28+
raise nebula.ForbiddenException()
29+
30+
result = []
31+
async for session in Session.list():
32+
33+
if (id_user is not None) and (id_user != session.user["id"]):
34+
continue
35+
36+
if (not user.is_admin) and (id_user != session.user["id"]):
37+
continue
38+
39+
result.append(session)
40+
41+
return result

0 commit comments

Comments
 (0)