public async Task AppInstalled([FromQuery] string userAccountId, [FromBody] AtlModel.ClientRegistrationData data)
        {
            _logger.LogInformation($"AppInstalled client: {data.ClientKey}");

            /* as stated
             *  https://developer.atlassian.com/cloud/confluence/security-for-connect-apps/
             *  First install after being uninstalled:
             *  The shared secret sent in the preceding installed callback. This allows apps to allow the new installation to access previous tenant data (if any exists).
             *  A valid signature demonstrates that the sender is in possession of the shared secret from when the old tenant data was accessed.
             */
            ClientRegistration registration = null;

            // new clients should have _client.RegistrationData set to null
            if (null == _client.RegistrationData)
            {
                registration = await _dbContext.ClientRegistration.Where(c => c.Key == _client.AtlassianAppKey && c.ClientKey == data.ClientKey).FirstOrDefaultAsync();

                if (default(ClientRegistration) != registration)
                {
                    throw new ArgumentException($"Client {data.ClientKey} already registered but no token was provided");
                }
            }
            if (null != _client.AuthException)
            {
                throw new ControllerException(message: $"Exception occired during token validation: {_client.AuthException.Message}", innerException: _client.AuthException);
            }

            // we have checked that either client is new client (no token provided) or already registered (token provided, verified, _client.RegistrationData filled
            //foreach (var r in _dbContext.ClientRegistration.Where(c => c.Key == _client.AtlassianAppKey && c.ClientKey == data.ClientKey))
            //    _dbContext.ClientRegistration.Remove(r);

            if (null != _client.RegistrationData)
            {
                registration = await _dbContext.ClientRegistration.Where(c => c.Id == _client.RegistrationData.Id)
                               .FirstOrDefaultAsync();

                registration.Update(data);
            }
            else
            {
                registration = ClientRegistration.From(data);
                registration.UserAccountId = userAccountId;
                _dbContext.ClientRegistration.Add(registration);
            }
            registration.ClientStateId = (int)AtlConnect.Enum.eRegTypes.AppInstalled;
            await _dbContext.SaveChangesAsync();

            _client.RegistrationData = registration;
            await ReportSetupEvent(registration, "installed", true);
        }
Пример #2
0
        public async Task <IActionResult> ExportIssues([FromForm(Name = "issues")] List <string> issuesList, [FromForm(Name = "includeqr")] bool includeQRCode
                                                       , [FromHeader(Name = "Referer")] string referer, [FromHeader(Name = "x-real-ip")] string realIp, [FromHeader(Name = "User-Agent")] string userAgent
                                                       , [FromHeader(Name = "x-forwarded-for")] string forwardedFor)
        {
            IActionResult result          = null;
            DateTime      requestDateTime = DateTime.Now;
            TaskMeasurer  taskMeasurer    = new TaskMeasurer();
            string        extension       = "pdf";

            Model.ClientRegistration registrationData = _client.RegistrationData;
            string fileId         = Guid.NewGuid().ToString();
            string reportFileName = $"{_configuration.GetValue<string>("Settings:StorageRoot", "clients_jiracloud")}/{registrationData.ClientKey}/{fileId}.{extension}";

            JArray  fields = null;
            JObject issues = null;
            Dictionary <string, JArray> epicStories = new Dictionary <string, JArray>();

            Report.Model.Document      document             = null;
            Model.ReportFile           reportFile           = null;
            ReportJiraCloudModel       reportJiraCloudModel = null;
            List <StatisticalDocument> statItems            = new List <StatisticalDocument>();

            try
            {
                _logger.LogInformation($"{requestDateTime} New job ClientKey {registrationData.ClientKey}, issues {String.Join(", ", issuesList)}");
                HttpClient httpCli = _clientFactory.CreateClient("jira_client");
                httpCli.BaseAddress = new Uri(registrationData.BaseUrl);
                RestApiClient cli = new RestApiClient(registrationData.Key, registrationData.SharedSecret, registrationData.ClientKey, httpCli);

                fields = (JArray)JsonConvert.DeserializeObject(await taskMeasurer.Run(() => cli.Get($"/rest/api/3/field"), "000_FetchFields"));
                var EpicNameField = getField(fields, "com.pyxis.greenhopper.jira:gh-epic-label");


                string[] responses = await taskMeasurer.Run(() => Task.WhenAll(issuesList.Select(i => cli.Get($"/rest/api/3/issue/{i}"))), "111_FetchIssuesData");

                PdfReport pdfReport = new PdfReport(filePath: reportFileName, storageName: _configuration.GetValue <string>("Settings:StorageName"), debug: _hostEnvironment.IsDevelopment());
                await pdfReport.Configure(_client.PdfApi, _client.BarcodeApi);

                issues = JToken.FromObject(new
                {
                    issues = responses.Select(JsonConvert.DeserializeObject).ToList()
                }) as JObject;

                // get stories for epics
                epicStories = new Dictionary <string, JArray>();
                if (!string.IsNullOrEmpty(EpicNameField))
                {
                    var issuesArr = await Task.WhenAll(issues["issues"]
                                                       .Where(i => !string.IsNullOrEmpty(i.SelectToken($"$.fields.{EpicNameField}")?.ToString()))
                                                       .Select(async i => KeyValuePair.Create(i.SelectToken($"$.key")?.ToString(), await getSubtasksForEpic(cli, i.SelectToken($"$.key")?.ToString()))
                                                               ));

                    epicStories = issuesArr.ToDictionary(t => t.Key, t => t.Value);
                }

                document = taskMeasurer.RunSync(() =>
                {
                    reportJiraCloudModel = new ReportJiraCloudModel(System.IO.File.ReadAllText(
                                                                        _configuration.GetValue("Templates:ReportIssuesModel",
                                                                                                "template/Report-Issues.Mustache")))
                    {
                        EpicLinkField  = getField(fields, "com.pyxis.greenhopper.jira:gh-epic-link"),
                        EpicNameField  = EpicNameField,
                        GenerateQRCode = includeQRCode
                    };
                    return(reportJiraCloudModel.CreateReportModel(reportJiraCloudModel.issuesModel(issues, epicStories)));
                }, "112_PrepareReportModel");

                if (null == document.Options)
                {
                    document.Options = new Report.Model.DocumentOptions();
                }
                await pdfReport.Report(document);


                DateTime current = DateTime.Now;
                reportFile = new Model.ReportFile
                {
                    UniqueId        = $"{Guid.NewGuid()}",
                    ReportType      = extension,
                    ContentType     = "application/pdf",
                    FileName        = issuesList.Count == 1 ? $"{issuesList.First()}.{extension}" : $"Issues.{extension}",
                    StorageFileName = reportFileName,
                    ClientId        = registrationData.Id,
                    Created         = current,
                    Expired         = current.AddHours(_configuration.GetValue("Settings:FileExpirationHours", 24)),
                };
                _dbContext.ReportFile.Add(reportFile);
                statItems = taskMeasurer.Stat.Concat(pdfReport.Stat).ToList();

                await _dbContext.SaveChangesAsync();

                _logger.LogInformation($"{current} Finished {registrationData.ClientKey} in {DateTime.Now - requestDateTime}");
                return(result = new OkObjectResult(new {
                    fileid = reportFile.UniqueId
                    , downloadlink = _basePathReplacement.ReplaceBaseUrl(Url.Link("GetDownload", new { id = reportFile.UniqueId }))
                    , expText = TimeSpan.FromHours(_configuration.GetValue("Settings:FileExpirationHours", 24)).ToReadableString()
                    , exp = reportFile.Expired
                }));
            }
            catch (Exception ex)
            {
                ZipFileArchive archive = new ZipFileArchive().AddFile("010_request_params.json", new
                {
                    RequestId = _client.RequestId,
                    FileId    = fileId,
                    FileName  = reportFileName,
                    includeQRCode, referer, realIp, userAgent, forwardedFor,
                    issues = issuesList
                });
                foreach (var f in new Dictionary <string, object> {
                    { "020_registration.json", registrationData },
                    { "030_fields.json", fields },
                    { "040_issues.json", issues },
                    { "050_epic_stories.json", epicStories },
                    { "051_RenderedDocument.yaml", reportJiraCloudModel?.RenderedYamlDocument },
                    { "052_RenderedJsonDocument.yaml", reportJiraCloudModel?.RenderedJsonDocument },
                    { "060_document.json", document },
                    { "070_report_file.json", reportFile },
                    { "080_result.json", result },
                }.ToArray())
                {
                    archive.AddFile(f.Key, f.Value);
                }
                throw new ControllerException($"Error generating {reportFileName}", innerException: ex, customData: await archive.Archive());
            }
            finally
            {
                _client.Stat = statItems;
            }
        }