-
Notifications
You must be signed in to change notification settings - Fork 83
Expand file tree
/
Copy pathai_assistant_controller.ex
More file actions
163 lines (134 loc) · 4.54 KB
/
Copy pathai_assistant_controller.ex
File metadata and controls
163 lines (134 loc) · 4.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
defmodule LightningWeb.API.AiAssistantController do
@moduledoc """
API endpoints for AI Assistant functionality.
"""
use LightningWeb, :controller
alias Lightning.AiAssistant
alias Lightning.Jobs
alias Lightning.Policies.Permissions
alias Lightning.Projects
alias Lightning.Workflows
alias LightningWeb.API.Helpers
alias LightningWeb.Channels.AiAssistantJSON
action_fallback LightningWeb.FallbackController
@doc """
List AI Assistant sessions for a given context (job or project).
## Parameters
- `session_type`: "job_code" or "workflow_template" (required)
- `job_id`: Job ID (required if session_type is "job_code")
- `project_id`: Project ID (required if session_type is "workflow_template")
- `offset`: Pagination offset (optional, default: 0)
- `limit`: Pagination limit (optional, default: 20)
## Examples
- GET /api/ai_assistant/sessions?session_type=job_code&job_id=123
- GET /api/ai_assistant/sessions?session_type=workflow_template&project_id=456
"""
def list_sessions(conn, params) do
user = conn.assigns[:current_user]
with {:ok, session_type} <- validate_session_type(params),
{:ok, resource} <- get_resource(session_type, params),
:ok <- authorize_access(session_type, resource, user) do
offset = Map.get(params, "offset", "0") |> String.to_integer()
limit = Map.get(params, "limit", "20") |> String.to_integer()
opts = [offset: offset, limit: limit]
opts =
if session_type == "workflow_template" do
workflow =
case params["workflow_id"] do
nil -> nil
workflow_id -> Workflows.get_workflow(workflow_id)
end
Keyword.put(opts, :workflow, workflow)
else
opts
end
%{sessions: sessions, pagination: pagination} =
AiAssistant.list_sessions(resource, :desc, opts)
json(conn, %{
sessions: AiAssistantJSON.format_sessions(sessions),
pagination: %{
total_count: pagination.total_count,
has_next_page: pagination.has_next_page,
has_prev_page: pagination.has_prev_page
}
})
end
end
defp validate_session_type(%{"session_type" => session_type})
when session_type in ["job_code", "workflow_template"] do
{:ok, session_type}
end
defp validate_session_type(_params) do
{:error, :bad_request}
end
defp get_resource("job_code", %{"job_id" => job_id}) do
with :ok <- Helpers.validate_uuid(job_id) do
{:ok, job_id}
end
end
defp get_resource("job_code", _params) do
{:error, :bad_request}
end
defp get_resource("workflow_template", %{"project_id" => project_id}) do
with :ok <- Helpers.validate_uuid(project_id) do
case Projects.get_project(project_id) do
nil -> {:error, :not_found}
project -> {:ok, project}
end
end
end
defp get_resource("workflow_template", _params) do
{:error, :bad_request}
end
defp authorize_access("job_code", job_id, user) when is_binary(job_id) do
alias Lightning.AiAssistant.ChatSession
alias Lightning.Repo
import Ecto.Query
case Jobs.get_job(job_id,
include: [workflow: [project: :project_users]]
) do
{:ok, job} ->
check_job_access(job, user)
{:error, :not_found} ->
session =
from(s in ChatSession,
where: s.session_type == "job_code",
where:
s.job_id == ^job_id or
fragment("? -> 'unsaved_job' ->> 'id' = ?", s.meta, ^job_id),
limit: 1
)
|> Repo.one()
check_unsaved_job_access(session, user)
end
end
defp authorize_access("workflow_template", project, user) do
case Permissions.can(:workflows, :access_read, user, project) do
:ok -> :ok
{:error, _reason} -> {:error, :forbidden}
end
end
defp check_job_access(job, user) do
check_workflow_access(job.workflow, user)
end
defp check_unsaved_job_access(nil, _user) do
:ok
end
defp check_unsaved_job_access(
%{meta: %{"unsaved_job" => %{"workflow_id" => workflow_id}}},
user
) do
alias Lightning.Repo
workflow =
Workflows.get_workflow(workflow_id)
|> Repo.preload(project: [:project_users])
check_workflow_access(workflow, user)
end
defp check_unsaved_job_access(_, _user), do: :ok
defp check_workflow_access(workflow, user) do
case Permissions.can(:workflows, :access_read, user, workflow.project) do
:ok -> :ok
{:error, _reason} -> {:error, :forbidden}
end
end
end