Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue of user not being able to submit assignment when logged in root account #2976

Closed
wants to merge 9 commits into from
4 changes: 4 additions & 0 deletions Core/Core/Contexts/Tab.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ public class Tab: NSManagedObject {
set { visibilityRaw = newValue.rawValue }
}

public var apiInstanceHost: String? {
return fullURL?.host()
}

public var name: TabName {
TabName(rawValue: id) ?? .custom
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,48 @@ public class FileSubmissionSubmitter {
self.context = context
}

public func submitFiles(fileSubmissionID: NSManagedObjectID) -> Future<APISubmission, FileSubmissionErrors.Submission> {
Future<APISubmission, FileSubmissionErrors.Submission> { self.sendRequest(fileSubmissionID: fileSubmissionID, promise: $0) }
public func submitFiles(fileSubmissionID: NSManagedObjectID) -> AnyPublisher<APISubmission, FileSubmissionErrors.Submission> {
return fetchDestinationBaseURL(fileSubmissionID: fileSubmissionID)
.flatMap { baseURL in
Future { [weak self] promise in
guard let self else { return promise(.failure(.submissionFailed)) }

sendRequest(
baseURL: baseURL,
fileSubmissionID: fileSubmissionID,
promise: promise
)
}
}
.eraseToAnyPublisher()
}

/** Fetching the proper base URL for submission, by investigating course tabs full_url property. */
private func fetchDestinationBaseURL(fileSubmissionID: NSManagedObjectID) -> Future<URL?, Never> {

return Future<URL?, Never> { [weak self] promise in
guard let self else { return promise(.success(nil)) }

guard let submission = try? context.performAndWait({
return try self.context.existingObject(with: fileSubmissionID) as? FileSubmission
}) else { return promise(.success(nil)) }

let request = GetContextTabs(context: .course(submission.courseID)).request
api.makeRequest(request) { response, _, _ in
guard let baseUrl = response?.first?.full_url?.apiBaseURL else {
return promise(.success(nil))
}
return promise(.success(baseUrl))
}
}
}

/** The result of the request is also written into the underlying `FileSubmission` object. */
private func sendRequest(fileSubmissionID: NSManagedObjectID, promise: @escaping Future<APISubmission, FileSubmissionErrors.Submission>.Promise) {
private func sendRequest(
baseURL: URL?,
fileSubmissionID: NSManagedObjectID,
promise: @escaping Future<APISubmission, FileSubmissionErrors.Submission>.Promise
) {
context.performAndWait {
guard let submission = try? context.existingObject(with: fileSubmissionID) as? FileSubmission else { return }
let fileIDs = submission.files.compactMap { $0.apiID }
Expand All @@ -46,12 +82,15 @@ public class FileSubmissionSubmitter {
submission_type: .online_upload,
file_ids: fileIDs
)
let request = CreateSubmissionRequest(context: .course(submission.courseID),
assignmentID: submission.assignmentID,
body: .init(submission: requestedSubmission))
api.makeRequest(request) { [self] response, _, error in
handleResponse(response, error: error, fileSubmissionID: fileSubmissionID, promise: promise)
}
let request = CreateSubmissionRequest(
context: .course(submission.courseID),
assignmentID: submission.assignmentID,
body: .init(submission: requestedSubmission)
)
API(self.api.loginSession, baseURL: baseURL)
.makeRequest(request) { [self] response, _, error in
handleResponse(response, error: error, fileSubmissionID: fileSubmissionID, promise: promise)
}
}
}

Expand Down
64 changes: 37 additions & 27 deletions Core/Core/Files/Model/API/UploadFileComment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,35 +21,36 @@ import CoreData

public class UploadFileComment {
let env = AppEnvironment.shared
let assignmentID: String
let destination: SubmissionDestination
var callback: (SubmissionComment?, Error?) -> Void = { _, _ in }
let courseID: String
let isGroup: Bool
let batchID: String
var files: UploadManager.Store?
var placeholderID: String?
let userID: String
let attempt: Int?
var task: APITask?
lazy var context = env.database.newBackgroundContext()

var uploadContext: FileUploadContext {
return .submissionComment(courseID: courseID, assignmentID: assignmentID, userID: userID)
return .submissionComment(
courseID: destination.courseID,
assignmentID: destination.assignmentID,
userID: destination.userID
)
}

var apiCoordinator: SubmissionApiCoordinator = DefaultSubmissionApiCoordinator()

private static var placeholderSuffix = 1

public init(
courseID: String,
assignmentID: String,
userID: String,
destination: SubmissionDestination,
isGroup: Bool,
batchID: String,
attempt: Int?
) {
self.assignmentID = assignmentID
self.courseID = courseID
self.destination = destination
self.isGroup = isGroup
self.userID = userID
self.batchID = batchID
self.attempt = attempt
}
Expand Down Expand Up @@ -85,14 +86,14 @@ public class UploadFileComment {
}
context.performAndWait {
let placeholder: SubmissionComment = self.context.insert()
placeholder.assignmentID = self.assignmentID
placeholder.assignmentID = self.destination.assignmentID
placeholder.authorAvatarURL = session.userAvatarURL
placeholder.authorID = session.userID
placeholder.authorName = session.userName
placeholder.comment = String(localized: "See attached files.", bundle: .core)
placeholder.createdAt = Date()
placeholder.id = "placeholder-\(UploadFileComment.placeholderSuffix)"
placeholder.userID = self.userID
placeholder.userID = self.destination.userID
if let attempt = self.attempt {
placeholder.attemptFromAPI = NSNumber(value: attempt)
}
Expand All @@ -104,26 +105,35 @@ public class UploadFileComment {
self.callback(nil, error)
}
}
UploadManager.shared.upload(batch: batchID, to: uploadContext)
UploadManager.shared.upload(batch: batchID, to: uploadContext, baseURL: destination.baseURL(in: env))
}

func putComment(fileIDs: [String]) {
let body = PutSubmissionGradeRequest.Body(comment: .init(fileIDs: fileIDs, forGroup: isGroup, attempt: attempt))
task = env.api.makeRequest(PutSubmissionGradeRequest(courseID: courseID, assignmentID: assignmentID, userID: userID, body: body)) { data, _, error in
self.task = nil
guard error == nil, let submission = data, let comment = submission.submission_comments?.last else {
return self.callback(nil, error)
}
self.context.performAndWait {
let comment = SubmissionComment.save(comment, for: submission, replacing: self.placeholderID, in: self.context)
var e: Error?
defer { self.callback(comment, e) }
do {
try self.context.save()
} catch {
e = error
let request = PutSubmissionGradeRequest(
courseID: destination.courseID,
assignmentID: destination.assignmentID,
userID: destination.userID,
body: body
)

task = apiCoordinator
.api(for: destination, in: env)
.makeRequest(request) { data, _, error in
self.task = nil
guard error == nil, let submission = data, let comment = submission.submission_comments?.last else {
return self.callback(nil, error)
}
self.context.performAndWait {
let comment = SubmissionComment.save(comment, for: submission, replacing: self.placeholderID, in: self.context)
var e: Error?
defer { self.callback(comment, e) }
do {
try self.context.save()
} catch {
e = error
}
}
}
}
}
}
4 changes: 4 additions & 0 deletions Core/Core/Files/Model/Entities/File.swift
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ final public class File: NSManagedObject {
}
}

var baseURL: URL? {
return url?.apiBaseURL
}

@objc // For NSFileProviderItem
public var isUploading: Bool {
return taskID != nil
Expand Down
15 changes: 10 additions & 5 deletions Core/Core/Files/Model/UploadManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,16 @@ open class UploadManager: NSObject, URLSessionDelegate, URLSessionTaskDelegate,
}
}

open func upload(batch batchID: String, to uploadContext: FileUploadContext, callback: (() -> Void)? = nil) {
open func upload(
batch batchID: String,
to uploadContext: FileUploadContext,
baseURL: URL?,
callback: (() -> Void)? = nil
) {
context.performAndWait {
let files: [File] = context.fetch(filesPredicate(batchID: batchID))
for file in files {
upload(file: file, to: uploadContext, callback: callback)
upload(file: file, to: uploadContext, baseURL: baseURL, callback: callback)
}
}
}
Expand Down Expand Up @@ -177,8 +182,7 @@ open class UploadManager: NSObject, URLSessionDelegate, URLSessionTaskDelegate,

let api: API = {
if let baseURL {
return API(environment.currentSession,
baseURL: baseURL)
return API(environment.currentSession, baseURL: baseURL)
} else {
return environment.api
}
Expand Down Expand Up @@ -336,12 +340,13 @@ open class UploadManager: NSObject, URLSessionDelegate, URLSessionTaskDelegate,
// This is to make the background task wait until we receive the submission response from the API.
let semaphore = DispatchSemaphore(value: 0)
let objectID = file.objectID
let baseURL = file.baseURL
process.performExpiringActivity(reason: "submit assignment") { expired in
if expired {
task?.cancel()
}
self.submissionsStatus.addTasks(fileIDs: fileIDs)
task = API(session).makeRequest(requestable) { response, _, error in
task = API(session, baseURL: baseURL).makeRequest(requestable) { response, _, error in
self.context.performAndWait {
defer {
self.submissionsStatus.removeTasks(fileIDs: fileIDs)
Expand Down
18 changes: 17 additions & 1 deletion Core/Core/Files/View/FileList/FileListViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public class FileListViewController: ScreenViewTrackableViewController, ColoredN
var path = ""
var searchTerm: String?
var results: [APIFile] = []
var apiInstanceHost: String?

public lazy var screenViewTrackingParameters: ScreenViewTrackingParameters = {
var eventName = "\(context == .currentUser ? "" : context.pathComponent)/files"
Expand All @@ -71,6 +72,9 @@ public class FileListViewController: ScreenViewTrackableViewController, ColoredN
lazy var uploads = UploadManager.shared.subscribe(batchID: batchID) { [weak self] in
self?.updateUploads()
}
lazy var tabs = env.subscribe(GetContextTabs(context: .course(context.id))) { [weak self] in
self?.updateApiInstanceHost()
}

private var offlineFileInteractor: OfflineFileInteractor?

Expand Down Expand Up @@ -219,6 +223,10 @@ public class FileListViewController: ScreenViewTrackableViewController, ColoredN
alert.addAction(AlertAction(String(localized: "Delete", bundle: .core), style: .default, handler: handler))
env.router.show(alert, from: self, options: .modal())
}

private func updateApiInstanceHost() {
apiInstanceHost = tabs.first?.apiInstanceHost
}
}

extension FileListViewController: UISearchBarDelegate {
Expand Down Expand Up @@ -351,6 +359,14 @@ extension FileListViewController: FilePickerDelegate {
CreateFolder(context: context, name: name, parentFolderID: folderID).fetch()
}

var baseURL: URL? {
guard let host = apiInstanceHost else { return nil }
var urlComps = URLComponents()
urlComps.host = host
urlComps.scheme = env.api.baseURL.scheme
return urlComps.url
}

public func filePicker(didPick url: URL) {
guard let folderID = folder.first?.id else { return }
UploadManager.shared.upload(url: url, batchID: batchID, to: .context(Context(.folder, id: folderID)))
Expand All @@ -359,7 +375,7 @@ extension FileListViewController: FilePickerDelegate {

public func filePicker(didRetry file: File) {
guard let folderID = folder.first?.id else { return }
UploadManager.shared.upload(file: file, to: .context(Context(.folder, id: folderID)))
UploadManager.shared.upload(file: file, to: .context(Context(.folder, id: folderID)), baseURL: baseURL)
}

func updateUploads() {
Expand Down
Loading