/// <summary> /// Returns SF project id of created project. /// </summary> public async Task <string> CreateProjectAsync(string curUserId, SFProjectCreateSettings settings) { Attempt <UserSecret> userSecretAttempt = await _userSecrets.TryGetAsync(curUserId); if (!userSecretAttempt.TryResult(out UserSecret userSecret)) { throw new DataNotFoundException("The user does not exist."); } IReadOnlyList <ParatextProject> ptProjects = await _paratextService.GetProjectsAsync(userSecret); ParatextProject ptProject = ptProjects.SingleOrDefault(p => p.ParatextId == settings.ParatextId); if (ptProject == null) { throw new DataNotFoundException("The paratext project does not exist."); } var project = new SFProject { ParatextId = settings.ParatextId, Name = ptProject.Name, ShortName = ptProject.ShortName, WritingSystem = new WritingSystem { Tag = ptProject.LanguageTag }, TranslateConfig = new TranslateConfig { TranslationSuggestionsEnabled = settings.TranslationSuggestionsEnabled }, CheckingConfig = new CheckingConfig { CheckingEnabled = settings.CheckingEnabled } }; Attempt <string> attempt = await TryGetProjectRoleAsync(project, curUserId); if (!attempt.TryResult(out string projectRole) || projectRole != SFProjectRole.Administrator) { throw new ForbiddenException(); } string projectId = ObjectId.GenerateNewId().ToString(); using (IConnection conn = await RealtimeService.ConnectAsync(curUserId)) { if (this.RealtimeService.QuerySnapshots <SFProject>().Any( (SFProject sfProject) => sfProject.ParatextId == project.ParatextId)) { throw new InvalidOperationException(ErrorAlreadyConnectedKey); } IDocument <SFProject> projectDoc = await conn.CreateAsync <SFProject>(projectId, project); await ProjectSecrets.InsertAsync(new SFProjectSecret { Id = projectDoc.Id }); IDocument <User> userDoc = await conn.FetchAsync <User>(curUserId); await AddUserToProjectAsync(conn, projectDoc, userDoc, SFProjectRole.Administrator, false); // Add the source after the project has been created // This will make the source project appear after the target, if it needs to be created if (settings.SourceParatextId != null && settings.SourceParatextId != settings.ParatextId) { TranslateSource source = await this.GetTranslateSourceAsync( curUserId, userSecret, settings.SourceParatextId, ptProjects); await projectDoc.SubmitJson0OpAsync(op => { UpdateSetting(op, p => p.TranslateConfig.Source, source); }); } if (projectDoc.Data.TranslateConfig.TranslationSuggestionsEnabled) { var machineProject = new MachineProject { Id = projectDoc.Id, SourceLanguageTag = projectDoc.Data.TranslateConfig.Source.WritingSystem.Tag, TargetLanguageTag = projectDoc.Data.WritingSystem.Tag }; await _engineService.AddProjectAsync(machineProject); } } await _syncService.SyncAsync(curUserId, projectId, true); return(projectId); }
public async Task DeleteProjectAsync(string curUserId, string projectId) { string ptProjectId; using (IConnection conn = await RealtimeService.ConnectAsync(curUserId)) { IDocument <SFProject> projectDoc = await conn.FetchAsync <SFProject>(projectId); if (!projectDoc.IsLoaded) { throw new DataNotFoundException("The project does not exist."); } if (!IsProjectAdmin(projectDoc.Data, curUserId)) { throw new ForbiddenException(); } ptProjectId = projectDoc.Data.ParatextId; // delete the project first, so that users get notified about the deletion string[] projectUserIds = projectDoc.Data.UserRoles.Keys.ToArray(); await projectDoc.DeleteAsync(); async Task removeUser(string projectUserId) { IDocument <User> userDoc = await conn.FetchAsync <User>(projectUserId); await RemoveUserFromProjectAsync(conn, projectDoc, userDoc); } var tasks = new List <Task>(); foreach (string projectUserId in projectUserIds) { tasks.Add(removeUser(projectUserId)); } string[] referringProjects = GetProjectWithReferenceToSource(projectId); async Task removeSourceReference(string projectId) { IDocument <SFProject> doc = await conn.FetchAsync <SFProject>(projectId); await doc.SubmitJson0OpAsync(op => op.Unset(d => d.TranslateConfig.Source)); } foreach (string projId in referringProjects) { tasks.Add(removeSourceReference(projId)); } await Task.WhenAll(tasks); } await ProjectSecrets.DeleteAsync(projectId); await RealtimeService.DeleteProjectAsync(projectId); await _engineService.RemoveProjectAsync(projectId); string projectDir = Path.Combine(SiteOptions.Value.SiteDir, "sync", ptProjectId); if (FileSystemService.DirectoryExists(projectDir)) { FileSystemService.DeleteDirectory(projectDir); } string audioDir = GetAudioDir(projectId); if (FileSystemService.DirectoryExists(audioDir)) { FileSystemService.DeleteDirectory(audioDir); } }
public async Task UpdateSettingsAsync(string curUserId, string projectId, SFProjectSettings settings) { using (IConnection conn = await RealtimeService.ConnectAsync(curUserId)) { IDocument <SFProject> projectDoc = await conn.FetchAsync <SFProject>(projectId); if (!projectDoc.IsLoaded) { throw new DataNotFoundException("The project does not exist."); } if (!IsProjectAdmin(projectDoc.Data, curUserId)) { throw new ForbiddenException(); } // Get the source - any creation or permission updates are handled in GetTranslateSourceAsync TranslateSource source = null; if (settings.SourceParatextId != null) { Attempt <UserSecret> userSecretAttempt = await _userSecrets.TryGetAsync(curUserId); if (!userSecretAttempt.TryResult(out UserSecret userSecret)) { throw new DataNotFoundException("The user does not exist."); } IReadOnlyList <ParatextProject> ptProjects = await _paratextService.GetProjectsAsync(userSecret); source = await GetTranslateSourceAsync(curUserId, userSecret, settings.SourceParatextId, ptProjects, projectDoc.Data.UserRoles); if (source.ProjectRef == projectId) { // A project cannot reference itself source = null; } } await projectDoc.SubmitJson0OpAsync(op => { UpdateSetting(op, p => p.TranslateConfig.TranslationSuggestionsEnabled, settings.TranslationSuggestionsEnabled); UpdateSetting(op, p => p.TranslateConfig.Source, source); UpdateSetting(op, p => p.CheckingConfig.CheckingEnabled, settings.CheckingEnabled); UpdateSetting(op, p => p.CheckingConfig.UsersSeeEachOthersResponses, settings.UsersSeeEachOthersResponses); UpdateSetting(op, p => p.CheckingConfig.ShareEnabled, settings.ShareEnabled); UpdateSetting(op, p => p.CheckingConfig.ShareLevel, settings.ShareLevel); }); bool suggestionsEnabledSet = settings.TranslationSuggestionsEnabled != null; bool sourceParatextIdSet = settings.SourceParatextId != null; bool checkingEnabledSet = settings.CheckingEnabled != null; // check if a sync needs to be run if (suggestionsEnabledSet || sourceParatextIdSet || checkingEnabledSet) { bool trainEngine = false; if (suggestionsEnabledSet || sourceParatextIdSet) { if (projectDoc.Data.TranslateConfig.TranslationSuggestionsEnabled && projectDoc.Data.TranslateConfig.Source != null) { // translate task was enabled or source project changed // recreate Machine project only if source project changed if (!suggestionsEnabledSet && sourceParatextIdSet) { await _engineService.RemoveProjectAsync(projectId); } var machineProject = new MachineProject { Id = projectId, SourceLanguageTag = projectDoc.Data.TranslateConfig.Source.WritingSystem.Tag, TargetLanguageTag = projectDoc.Data.WritingSystem.Tag }; await _engineService.AddProjectAsync(machineProject); trainEngine = true; } else { // translate task was disabled or source project set to null await _engineService.RemoveProjectAsync(projectId); } } await _syncService.SyncAsync(curUserId, projectId, trainEngine); } } }