Skip to content

LTI: поддержка протокола LTI 1.3 для интеграции с внешними инструментами.#655

Open
KirillBorisovich wants to merge 28 commits intoInteIIigeNET:masterfrom
KirillBorisovich:feat/lti-development
Open

LTI: поддержка протокола LTI 1.3 для интеграции с внешними инструментами.#655
KirillBorisovich wants to merge 28 commits intoInteIIigeNET:masterfrom
KirillBorisovich:feat/lti-development

Conversation

@KirillBorisovich
Copy link
Copy Markdown
Contributor

Реализация поддержки протокола LTI 1.3 для интеграции с внешними инструментами.

KirillBorisovich and others added 23 commits November 30, 2025 16:01
…porting from an external tool, and also made validating jwt tokens
…pLinkingReturnController, added a check for matching toolId and course.LtiToolId
@DedSec256 DedSec256 changed the title LTI LTI: поддержки протокола LTI 1.3 для интеграции с внешними инструментами. Mar 7, 2026
@DedSec256 DedSec256 changed the title LTI: поддержки протокола LTI 1.3 для интеграции с внешними инструментами. LTI: поддержка протокола LTI 1.3 для интеграции с внешними инструментами. Mar 7, 2026
Comment on lines +9 to +14
string clientId,
string toolId,
string courseId,
string targetLinkUri,
string userId,
string nonce);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

я бы сделал класс с get/init пропертями

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

это метод, случайно не дописал public

}

string tokenString = form["JWT"]!;
var handler = new JwtSecurityTokenHandler();
Copy link
Copy Markdown
Contributor

@DedSec256 DedSec256 Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

точно мы должны его пересоздавать? Можно ли инжектить?


var resultList = new List<object>();

if (unverifiedToken.Payload.TryGetValue(itemsClaimName, out var itemsObject))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Действительно ли структура такая жидкая?

<body>
<p>Задача выбрана. Возвращаемся в HwProj...</p>
<script>
var payload = {responsePayloadJson};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Потенциальная инжекция

Copy link
Copy Markdown
Contributor

@DedSec256 DedSec256 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Крутая работа!
Вот основные замечания сейчас


if (keycMemoryCache.TryGetValue(jwksUrl, out JsonWebKeySet? keySet))
{
return keySet!.Keys;
Copy link
Copy Markdown
Contributor

@DedSec256 DedSec256 Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return keySet!.Keys;
return keySet?.Keys;

var json = await response.Content.ReadAsStringAsync();
keySet = new JsonWebKeySet(json);

if (response.Headers.CacheControl?.NoCache == true ||
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

response.Headers.CacheControl можно вынести

return keySet.Keys;
}

const int ageByDefault = 24;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

вынести в поле

if (taskViewModel.LtiLaunchData != null && !string.IsNullOrEmpty(taskViewModel.LtiLaunchData.LtiLaunchUrl))
{
await _tasksRepository.AddOrUpdateLtiLaunchDataAsync(taskId, taskViewModel.LtiLaunchData.ToLtiLaunchData()!);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Переопределить AddAsync можно, перенести логику с добавлением туда.

Comment on lines +48 to +50
var taskViewModel = task.ToHomeworkTaskViewModel();
await _tasksService.FillTaskViewModelWithLtiLaunchDataAsync(taskViewModel, taskId);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

давай _tasksService.GetTaskAsync будет возвращать HomeworkTaskViewModel, и эта логику будет скрыта там

Comment on lines +33 to +35
var responseViewModel = newHomework.ToHomeworkViewModel();

await FillLtiLaunchDataForTasks(responseViewModel);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

давай лучше спрячем в IHomeworksService

Task<HomeworkTask> GetTaskAsync(long taskId, bool withCriteria = false);
Task<HomeworkTask> GetForEditingTaskAsync(long taskId);
Task<LtiLaunchData?> GetTaskLtiDataAsync(long taskId);
Task<Dictionary<long, LtiLaunchData>> GetLtiDataForTasksAsync(long[] taskIds);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

не нужен, скорее всего

Comment on lines +84 to +85
LecturerComment = score.Comment,
Rating = (int)Math.Round(score.ScoreGiven)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Давай добавим оценку в комментарий

Comment on lines +89 to +97
var solutionId = await solutionsClient.PostSolutionForLti(taskId, postSolutionModel);

var rate = new RateSolutionModel
{
Rating = (int)Math.Round(score.ScoreGiven),
LecturerComment = score.Comment
};

await solutionsClient.RateSolutionForLti(solutionId, rate);
Copy link
Copy Markdown
Contributor

@DedSec256 DedSec256 Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можно объединить в один запрос/метод

Task<Solution> GetSolutionById(long solutionId);
Task<Solution[]> GetUserSolutions(long taskId, string studentId);
Task<long> PostSolution(long taskId, PostSolutionModel model);
Task<long> PostSolutionForLti(long taskId, PostSolutionModel model);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

не нужен

Task<long> PostSolutionForLti(long taskId, PostSolutionModel model);
Task PostEmptySolutionWithRate(long taskId, SolutionViewModel solution);
Task RateSolution(long solutionId, RateSolutionModel rateSolutionModel);
Task RateSolutionForLti(long solutionId, RateSolutionModel rateSolutionModel);
Copy link
Copy Markdown
Contributor

@DedSec256 DedSec256 Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

не должен отправлять уведомления преподавателям

например, во внутреннем вызове PostEmptySolution можно передать флаг

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants