Beispiel #1
0
        /// <summary>
        /// Synchronize an app from the tenant app catalog with the teams app catalog
        /// </summary>
        /// <param name="appMetadata">The app metadata object of the app to remove.</param>
        /// <returns></returns>
        public async Task <bool> SyncToTeamsAsync(AppMetadata appMetadata)
        {
            if (appMetadata == null || appMetadata.Id == Guid.Empty)
            {
                throw new ArgumentException(nameof(appMetadata));
            }

            await new SynchronizationContextRemover();

            return(await SyncToTeamsImplementation(appMetadata.Id));
        }
Beispiel #2
0
#pragma warning restore CA2000

        private static async Task <AppMetadata> GetAppMetaData(AppCatalogScope scope, ClientContext context, string accessToken, PnPHttpProvider httpClient, string requestDigest, string id)
        {
            AppMetadata returnValue = null;
            int         retryCount  = 0;
            int         waitTime    = 10; // seconds

            var metadataRequestUrl = $"{context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/AvailableApps/GetById('{id}')";

            using (var metadataRequest = new HttpRequestMessage(HttpMethod.Get, metadataRequestUrl))
            {
                metadataRequest.Headers.Add("accept", "application/json;odata=nometadata");
                if (!string.IsNullOrEmpty(accessToken))
                {
                    metadataRequest.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
                }
                if (!string.IsNullOrEmpty(requestDigest))
                {
                    metadataRequest.Headers.Add("X-RequestDigest", requestDigest);
                }

                while (returnValue == null && retryCount < 5)
                {
                    // Perform actual post operation
                    HttpResponseMessage metadataResponse = await httpClient.SendAsync(metadataRequest, new System.Threading.CancellationToken());

                    if (metadataResponse.IsSuccessStatusCode)
                    {
                        // If value empty, URL is taken
                        var metadataResponseString = await metadataResponse.Content.ReadAsStringAsync();

                        if (metadataResponseString != null)
                        {
                            returnValue = JsonSerializer.Deserialize <AppMetadata>(metadataResponseString);
                        }
                    }
                    else if (metadataResponse.StatusCode != HttpStatusCode.NotFound)
                    {
                        // Something went wrong...
                        throw new Exception(await metadataResponse.Content.ReadAsStringAsync());
                    }
                    if (returnValue == null)
                    {
                        // try again
                        retryCount++;
                        Thread.Sleep(waitTime * 1000); // wait 10 seconds
                    }
                }
                return(returnValue);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Removes an app from the app catalog
        /// </summary>
        /// <param name="appMetadata">The app metadata object of the app to remove.</param>
        /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
        /// <returns></returns>
        public async Task <bool> RemoveAsync(AppMetadata appMetadata, AppCatalogScope scope = AppCatalogScope.Tenant)
        {
            if (appMetadata == null)
            {
                throw new ArgumentException(nameof(appMetadata));
            }
            if (appMetadata.Id == Guid.Empty)
            {
                throw new ArgumentException(nameof(appMetadata.Id));
            }

            await new SynchronizationContextRemover();

            return(await BaseRequest(appMetadata.Id, AppManagerAction.Remove, true, null, scope));
        }
Beispiel #4
0
        /// <summary>
        /// Upgrades an app in a site
        /// </summary>
        /// <param name="appMetadata">The app metadata object of the app to upgrade.</param>
        /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
        /// <returns></returns>
        public async Task <bool> UpgradeAsync(AppMetadata appMetadata, AppCatalogScope scope = AppCatalogScope.Tenant)
        {
            if (appMetadata == null)
            {
                throw new ArgumentException(nameof(appMetadata));
            }
            if (appMetadata.Id == Guid.Empty)
            {
                throw new ArgumentException(nameof(appMetadata.Id));
            }

            await new SynchronizationContextRemover();

            return(await UpgradeAsync(appMetadata.Id, scope));
        }
Beispiel #5
0
        private static async Task <AppMetadata> GetAppMetaData(AppCatalogScope scope, ClientContext context, string id)
        {
            AppMetadata returnValue = null;
            int         retryCount  = 0;
            int         waitTime    = 10; // seconds

#pragma warning disable CA2000            // Dispose objects before losing scope
            var httpClient = PnPHttpClient.Instance.GetHttpClient(context);
#pragma warning restore CA2000            // Dispose objects before losing scope

            var metadataRequestUrl = $"{context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/AvailableApps/GetById('{id}')";

            using (var metadataRequest = new HttpRequestMessage(HttpMethod.Get, metadataRequestUrl))
            {
                metadataRequest.Headers.Add("accept", "application/json;odata=nometadata");

                await PnPHttpClient.AuthenticateRequestAsync(metadataRequest, context).ConfigureAwait(false);

                while (returnValue == null && retryCount < 5)
                {
                    // Perform actual post operation
                    HttpResponseMessage metadataResponse = await httpClient.SendAsync(metadataRequest, new System.Threading.CancellationToken());

                    if (metadataResponse.IsSuccessStatusCode)
                    {
                        // If value empty, URL is taken
                        var metadataResponseString = await metadataResponse.Content.ReadAsStringAsync();

                        if (metadataResponseString != null)
                        {
                            returnValue = JsonSerializer.Deserialize <AppMetadata>(metadataResponseString);
                        }
                    }
                    else if (metadataResponse.StatusCode != HttpStatusCode.NotFound)
                    {
                        // Something went wrong...
                        throw new Exception(await metadataResponse.Content.ReadAsStringAsync());
                    }
                    if (returnValue == null)
                    {
                        // try again
                        retryCount++;
                        await Task.Delay(waitTime * 1000); // wait 10 seconds
                    }
                }
                return(returnValue);
            }
        }
Beispiel #6
0
        /// <summary>
        /// Deploys/trusts an app in the app catalog
        /// </summary>
        /// <param name="appMetadata">The app metadata object of the app to deploy.</param>
        /// <param name="skipFeatureDeployment">If set to true will skip the feature deployed for tenant scoped apps.</param>
        /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
        /// <returns></returns>
        public async Task <bool> DeployAsync(AppMetadata appMetadata, bool skipFeatureDeployment = true, AppCatalogScope scope = AppCatalogScope.Tenant)
        {
            if (appMetadata == null)
            {
                throw new ArgumentException(nameof(appMetadata));
            }
            if (appMetadata.Id == Guid.Empty)
            {
                throw new ArgumentException(nameof(appMetadata.Id));
            }
            var postObj = new Dictionary <string, object>
            {
                { "skipFeatureDeployment", skipFeatureDeployment }
            };

            await new SynchronizationContextRemover();

            return(await BaseRequest(appMetadata.Id, AppManagerAction.Deploy, true, postObj, scope));
        }
Beispiel #7
0
        private async Task <AppMetadata> BaseAddRequest(byte[] file, string filename, bool overwrite, int timeoutSeconds, AppCatalogScope scope)
        {
            AppMetadata returnValue = null;
            var         isCloned    = false;
            var         context     = _context;

            if (scope == AppCatalogScope.Tenant)
            {
                // switch context to appcatalog
                var appcatalogUri = _context.Web.GetAppCatalog();
#pragma warning disable CA2000 // Dispose objects before losing scope
                context = context.Clone(appcatalogUri);
#pragma warning restore CA2000 // Dispose objects before losing scope
                isCloned = true;
            }

            context.Web.EnsureProperty(w => w.Url);

#pragma warning disable CA2000 // Dispose objects before losing scope
            var httpClient = PnPHttpClient.Instance.GetHttpClient(context);
#pragma warning restore CA2000 // Dispose objects before losing scope

            string requestUrl = $"{context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/Add(overwrite={(overwrite.ToString().ToLower())}, url='{filename}')";

            var requestDigest = string.Empty;

            using (var request = new HttpRequestMessage(HttpMethod.Post, requestUrl))
            {
                request.Headers.Add("accept", "application/json;odata=nometadata");

                await PnPHttpClient.AuthenticateRequestAsync(request, context).ConfigureAwait(false);

                request.Headers.Add("binaryStringRequestBody", "true");
                request.Content    = new ByteArrayContent(file);
                httpClient.Timeout = new TimeSpan(0, 0, timeoutSeconds);

                // Perform actual post operation
                HttpResponseMessage response = await httpClient.SendAsync(request, new CancellationToken());

                if (response.IsSuccessStatusCode)
                {
                    // If value empty, URL is taken
                    var responseString = await response.Content.ReadAsStringAsync();

                    if (responseString != null)
                    {
                        using (var jsonDocument = JsonDocument.Parse(responseString))
                        {
                            if (jsonDocument.RootElement.TryGetProperty("UniqueId", out JsonElement uniqueIdElement))
                            {
                                var id = uniqueIdElement.GetString();
                                returnValue = await GetAppMetaData(scope, context, id);
                            }
                        }
                    }
                }
                else
                {
                    // Something went wrong...
                    throw new Exception(await response.Content.ReadAsStringAsync());
                }
            }
            if (isCloned)
            {
                context.Dispose();
            }
            return(await Task.Run(() => returnValue));
        }
Beispiel #8
0
 /// <summary>
 /// Synchronize an app from the tenant app catalog with the teams app catalog
 /// </summary>
 /// <param name="appMetadata">The app metadata object of the app to remove.</param>
 /// <returns></returns>
 public bool SyncToTeams(AppMetadata appMetadata)
 {
     return(Task.Run(() => SyncToTeamsAsync(appMetadata)).GetAwaiter().GetResult());
 }
Beispiel #9
0
 /// <summary>
 /// Removes an app from the app catalog
 /// </summary>
 /// <param name="appMetadata">The app metadata object of the app to remove.</param>
 /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
 /// <returns></returns>
 public bool Remove(AppMetadata appMetadata, AppCatalogScope scope = AppCatalogScope.Tenant)
 {
     return(Task.Run(() => RemoveAsync(appMetadata, scope)).GetAwaiter().GetResult());
 }
Beispiel #10
0
 /// <summary>
 /// Deploys/trusts an app in the app catalog
 /// </summary>
 /// <param name="appMetadata">The app metadata object of the app to deploy.</param>
 /// <param name="skipFeatureDeployment">If set to true will skip the feature deployed for tenant scoped apps.</param>
 /// <param name="scope">Specifies the app catalog to work with. Defaults to Tenant</param>
 /// <returns></returns>
 public bool Deploy(AppMetadata appMetadata, bool skipFeatureDeployment = true, AppCatalogScope scope = AppCatalogScope.Tenant)
 {
     return(Task.Run(() => DeployAsync(appMetadata, skipFeatureDeployment, scope)).GetAwaiter().GetResult());
 }
Beispiel #11
0
#pragma warning disable CA2000
        private async Task <AppMetadata> BaseAddRequest(byte[] file, string filename, bool overwrite, int timeoutSeconds, AppCatalogScope scope)
        {
            AppMetadata returnValue = null;
            var         isCloned    = false;
            var         context     = _context;

            if (scope == AppCatalogScope.Tenant)
            {
                // switch context to appcatalog
                var appcatalogUri = _context.Web.GetAppCatalog();
                context  = context.Clone(appcatalogUri);
                isCloned = true;
            }

            var accessToken = context.GetAccessToken();

            using (var handler = new HttpClientHandler())
            {
                context.Web.EnsureProperty(w => w.Url);

                if (string.IsNullOrEmpty(accessToken))
                {
                    context.SetAuthenticationCookiesForHandler(handler);
                }

                using (var httpClient = new PnPHttpProvider(handler))
                {
                    string requestUrl = $"{context.Web.Url}/_api/web/{(scope == AppCatalogScope.Tenant ? "tenant" : "sitecollection")}appcatalog/Add(overwrite={(overwrite.ToString().ToLower())}, url='{filename}')";

                    var requestDigest = string.Empty;
                    if (!string.IsNullOrEmpty(accessToken))
                    {
                        requestDigest = await context.GetRequestDigestAsync().ConfigureAwait(false);
                    }
                    else
                    {
                        requestDigest = await context.GetRequestDigestAsync(handler.CookieContainer).ConfigureAwait(false);
                    }
                    using (var request = new HttpRequestMessage(HttpMethod.Post, requestUrl))
                    {
                        request.Headers.Add("accept", "application/json;odata=nometadata");
                        if (!string.IsNullOrEmpty(accessToken))
                        {
                            request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
                        }
                        else
                        {
                            if (context.Credentials is NetworkCredential networkCredential)
                            {
                                handler.Credentials = networkCredential;
                            }
                        }
                        if (!string.IsNullOrEmpty(requestDigest))
                        {
                            request.Headers.Add("X-RequestDigest", requestDigest);
                        }
                        request.Headers.Add("binaryStringRequestBody", "true");
                        request.Content    = new ByteArrayContent(file);
                        httpClient.Timeout = new TimeSpan(0, 0, timeoutSeconds);
                        // Perform actual post operation
                        HttpResponseMessage response = await httpClient.SendAsync(request, new System.Threading.CancellationToken());

                        if (response.IsSuccessStatusCode)
                        {
                            // If value empty, URL is taken
                            var responseString = await response.Content.ReadAsStringAsync();

                            if (responseString != null)
                            {
                                using (var jsonDocument = JsonDocument.Parse(responseString))
                                {
                                    if (jsonDocument.RootElement.TryGetProperty("UniqueId", out JsonElement uniqueIdElement))
                                    {
                                        var id = uniqueIdElement.GetString();
                                        returnValue = await GetAppMetaData(scope, context, accessToken, httpClient, requestDigest, id);
                                    }
                                }
                            }
                        }
                        else
                        {
                            // Something went wrong...
                            throw new Exception(await response.Content.ReadAsStringAsync());
                        }
                    }
                }
            }
            if (isCloned)
            {
                context.Dispose();
            }
            return(await Task.Run(() => returnValue));
        }