Just a second...

Example: Update the system authentication store

The following examples use the SystemAuthenticationControl feature in the Diffusion™ API to update the system authentication store.

.NET
/**
 * Copyright © 2021, 2022 Push Technology Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using PushTechnology.ClientInterface.Client.Factories;
using PushTechnology.ClientInterface.Client.Session;
using PushTechnology.ClientInterface.Client.Types;
using static System.Console;

namespace PushTechnology.ClientInterface.Example {
    /// <summary>
    /// Client implementation that demonstrates how to update the system authentication store.
    /// </summary>
    public sealed class SystemAuthenticationControl
    {
        public async Task SystemAuthenticationControlExample(string serverUrl)
        {
            // Connect as an admin session
            var session = Diffusion.Sessions.Principal("admin").Password("password")
                .CertificateValidation((cert, chain, errors) => CertificateValidationResult.ACCEPT)
                .Open(serverUrl);

            string testPrincipal = "TestPrincipal";

            // Create a new principal

            try
            {
                WriteLine($"Creating principal '{testPrincipal}'.");

                string storeScript = session.SystemAuthenticationControl.Script
                    .AddPrincipal(testPrincipal, "password", new List<string>())
                    .TrustClientProposedPropertyIn("Foo", new List<string> { "value1", "value2" })
                    .TrustClientProposedPropertyMatches("Bar", "regex1")
                    .ToScript();

                await session.SystemAuthenticationControl.UpdateStoreAsync(storeScript);

                WriteLine($"'{testPrincipal}' has been created.");
            }
            catch (Exception ex)
            {
                WriteLine($"Failed to create principal : {ex}.");
            }

            //Assign roles to the principal

            try
            {
                WriteLine($"Adding the roles of Administrator and Modify Session to '{testPrincipal}'.");

                string script1 = session.SystemAuthenticationControl.Script
                    .AssignRoles(testPrincipal, new[] { "ADMINISTRATOR", "MODIFY_SESSION" })
                    .ToScript();

                await session.SystemAuthenticationControl.UpdateStoreAsync(script1);

                WriteLine($"Roles have been added.");
            }
            catch (Exception ex)
            {
                WriteLine($"Failed to assign roles : {ex}.");
            }
            finally
            {
                session.Close();
            }
        }
    }
}
Java and Android
package com.pushtechnology.diffusion.examples;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.pushtechnology.diffusion.client.Diffusion;
import com.pushtechnology.diffusion.client.features.control.clients.SystemAuthenticationControl;
import com.pushtechnology.diffusion.client.features.control.clients.SystemAuthenticationControl.ScriptBuilder;
import com.pushtechnology.diffusion.client.session.Session;

/**
 * An example of using a control client to alter the system authentication
 * configuration.
 * <P>
 * This uses the {@link SystemAuthenticationControl} feature only.
 *
 * @author Push Technology Limited
 * @since 5.2
 */
public class ControlClientChangingSystemAuthentication {

    private static final Logger LOG =
        LoggerFactory.getLogger(
            ControlClientChangingSystemAuthentication.class);

    private final SystemAuthenticationControl systemAuthenticationControl;
    private final ScriptBuilder emptyScript;

    /**
     * Constructor.
     */
    public ControlClientChangingSystemAuthentication() {

        final Session session = Diffusion.sessions()
            // Authenticate with a user that has the VIEW_SECURITY and
            // MODIFY_SECURITY permissions.
            .principal("admin").password("password")
            // Use a secure channel because we're transferring sensitive
            // information.
            .open("wss://diffusion.example.com:80");

        systemAuthenticationControl =
            session.feature(SystemAuthenticationControl.class);
        emptyScript = systemAuthenticationControl.scriptBuilder();
    }

    /**
     * For all system users, update the assigned roles to replace the
     * "SUPERUSER" role and with "ADMINISTRATOR".
     *
     * @return a CompletableFuture that completes when the operation succeeds or
     *         fails.
     *
     *         <p>
     *         If the operation was successful, the CompletableFuture will
     *         complete successfully.
     *
     *         <p>
     *         Otherwise, the CompletableFuture will complete exceptionally with
     *         an {@link ExecutionException}. See
     *         {@link SystemAuthenticationControl#getSystemAuthentication()} and
     *         {@link SystemAuthenticationControl#updateStore(String)} for
     *         common failure reasons.
     */
    public CompletableFuture<Void> changeSuperUsersToAdministrators() {

        return systemAuthenticationControl
            .getSystemAuthentication()
            .thenCompose(configuration -> {

                final String script = configuration

                    // For each principal ...
                    .getPrincipals().stream()

                    // ... that has the SUPERUSER assigned role ...
                    .filter(p -> p.getAssignedRoles().contains("SUPERUSER"))

                    // ... create a script that updates the assigned roles to
                    // replace SUPERUSER with ADMINISTRATOR ...
                    .map(p -> {
                        final Set<String> newRoles =
                            new HashSet<>(p.getAssignedRoles());
                        newRoles.remove("SUPERUSER");
                        newRoles.add("ADMINISTRATOR");
                        return emptyScript.assignRoles(p.getName(), newRoles);
                    })

                    // ... create a single combined script.
                    .reduce(emptyScript, (sb1, sb2) -> sb1.append(sb2))
                    .script();

                LOG.info("Sending the following script to the server:\n{}",
                    script);

                return systemAuthenticationControl.updateStore(script)
                    // Convert CompletableFuture<?> to
                    // CompletableFuture<Void>.
                    .thenAccept(ignored -> { });
            });
    }

    /**
     * Close the session.
     */
    public void close() {
        systemAuthenticationControl.getSession().close();
    }
}
                    
C
/**
 * Copyright © 2021 Push Technology Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <stdio.h>
#include <stdlib.h>

#ifndef WIN32
        #include <unistd.h>
#else
        #define sleep(x) Sleep(1000 * x)
#endif

#include "diffusion.h"

/*
 * This callback is invoked when the system authentication store is
 * received, and prints the contents of the store.
 */
int on_get_system_authentication_store(
        SESSION_T *session,
        const SYSTEM_AUTHENTICATION_STORE_T store,
        void *context)
{
        printf("Received %ld principals\n", store.system_principals->size);

        char **names = get_principal_names(store);
        for(char **name = names; *name != NULL; name++) {
                printf("Principal: %s\n", *name);

                char **roles = get_roles_for_principal(store, *name);
                for(char **role = roles; *role != NULL; role++) {
                    printf("  |- Role: %s\n", *role);
                }
                free(roles);
        }
        free(names);

        switch(store.anonymous_connection_action) {
        case ANONYMOUS_CONNECTION_ACTION_ALLOW:
                printf("Allow anonymous connections\n");
                break;
        case ANONYMOUS_CONNECTION_ACTION_DENY:
                printf("Deny anonymous connections\n");
                break;
        case ANONYMOUS_CONNECTION_ACTION_ABSTAIN:
                printf("Abstain from making anonymous connection decision\n");
                break;
        }

        printf("Anonymous connection roles:\n");
        char **roles = get_anonymous_roles(store);
        for(char **role = roles; *role != NULL; role++) {
                printf("  |- Role: %s\n", *role);
        }
        free(roles);

        return HANDLER_SUCCESS;
}


int main(int argc, char **argv)
{
        const char *url = "ws://localhost:8080";
        const char *principal = "admin";
        const char *password = "password";

        CREDENTIALS_T *credentials = credentials_create_password(password);

        // Create a session, synchronously
        SESSION_T *session;
        DIFFUSION_ERROR_T error = { 0 };
        session = session_create(url, principal, credentials, NULL, NULL, &error);
        if(session == NULL) {
                fprintf(stderr, "TEST: Failed to create session\n");
                fprintf(stderr, "ERR : %s\n", error.message);
                return EXIT_FAILURE;
        }

        // Request the system authentication store
        const GET_SYSTEM_AUTHENTICATION_STORE_PARAMS_T params = {
                .on_get = on_get_system_authentication_store
        };
        get_system_authentication_store(session, params);

        // Sleep for a while
        sleep(5);

        // Close the session, and release resources and memory
        session_close(session, NULL);
        session_free(session);

        credentials_free(credentials);

        return EXIT_SUCCESS;
}

Change the URL from that provided in the example to the URL of the Diffusion server.