cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Dynatrace App Current user information

Hey,

We are trying to build an app. We need the current user information, like name, login id/email, user groups, for further processing. Is there any SDK available that can return me this kind of information?

 

Thanks.

Stephen

20 REPLIES 20

Iplinsky
Advisor

I am not shure, but you can do it by APIs

Dynatrace Certified

sinisa_zubic
Dynatrace Champion
Dynatrace Champion

Hi @StephenLHChan 

The team is currently working on an SDK which should give you such kind of information. Unfortunately I can't give you an ETA for it.


Best,
Sini

jellypuno
Dynatrace Organizer
Dynatrace Organizer

following this thread... 👀

sw
Dynatrace Helper
Dynatrace Helper

Hi @StephenLHChan, the SDK package is planned for 23CQ3.

In the meanwhile, you could use the service documented in the swagger spec:

https://{environmentid}.apps.dynatrace.com/platform/swagger-ui/index.html?urls.primaryName=Identity%20and%20Access%20Management

 

Hi @sw and @sinisa_zubic ,

Are you guys talking the same SDK?

Apologize if there is any misleading at my question.

@sw gave the url which is the endpoint get all users' information but what I am looking for is if there is a way to get the current user information who use the app.

For example, userA click on the app and the SDK will return userA's information to me. And, I will know userA had used the app. I may then ingest logs/ custom events to Dynatrace after userA triggered certain actions.

It is to fulfil some audit requirements at my company.

 

Thanks!

Yes we are talking about the same SDK. @sw should know more details

sw
Dynatrace Helper
Dynatrace Helper

Hi @StephenLHChan 

Sorry for the confusion.
Yes, the SDK package will provide information as:

  • currently logged in user
  • Environment ID and URL
  • App ID, name, version

May I ask for your use case, why do you need the user groups too?

hi @sw 

it is for access right control. If I know the user group of the users, I can limited certain pages of the app only to some users.

 

sw
Dynatrace Helper
Dynatrace Helper

Thanks @StephenLHChan  for the insights! This won't be part of this package for now, but I'll discuss this with the team.

Hi @sw ,

Has there been any update on the SDK yet?

There is a problem with the permission scope for this API that can't be assigned to an oauth client.

sw
Dynatrace Helper
Dynatrace Helper

The package providing this information (except user groups) is now available: https://developer.dynatrace.com/develop/sdks/app-environment/

DaveOps
Contributor

I also have the same use case to shield of pages for default users; I would like to be able to access the user groups through the SDK.

Hi @DaveOps, a new SDK will soon be available to access the user groups. I'll let you know when it's out.

Best, Edu.

DaveOps
Contributor

It seems this API is not available any more:

import { effectivePermissionsClient } from '@dynatrace-sdk/client-platform-management-service';

Outdated docs:
https://developer.dynatrace.com/develop/security/query-user-permissions/

Is there a workaround for this?

Hi @DaveOps, what do you mean it's not available? Here's the NPM package https://www.npmjs.com/package/@dynatrace-sdk/client-platform-management-service. Additionally I tried what's in our documentation and it works as expected. What issue are you having?

I am using and older version 1.0.1; that could be the issue.

DaveOps
Contributor

Is there a way to get the user account_id ?

DaveOps
Contributor

I created a solution to address the user permission problem and will share some of the important parts.
The approach involves checking if a user is part of an admin group returning a boolean. This is a simple way of differentiating between 2 types of users.

Created an appFunction that fetches user groups with the getUserGroupsV2 function. This function checks if a user belongs to an admin group.

 

 

export const getUserGroupsV2 = async (accountUuid: string, userEmail: string, bearerToken: string) => {
  const url = `https://api.dynatrace.com/iam/v1/accounts/${accountUuid}/users/${userEmail}`;

  try {
    const response = await fetch(`${url}`, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${bearerToken}`
      }
    });

    if (!response.ok) {
      const errorText = await response.text();
      console.error('Error response:', errorText);
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    return await response.json(); 
  } catch (error) {
    console.error('Error fetching groups:', error);
    throw error;
  }
};

 

 

Make an oauth request to get the bearer token:

 

export const getOAuth2Token = async (client_id: string, client_secret: string, scope: string, resource: string) => {
  const url = 'https://sso.dynatrace.com/sso/oauth2/token';

  const params = new URLSearchParams({
    grant_type: 'client_credentials',
    scope: scope,
    client_id: client_id,
    client_secret: client_secret,
    resource: resource,
  });

  try {
    const response = await fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      body: params.toString()
    });

    if (!response.ok) {
      const errorText = await response.text();
      console.error('Error response:', errorText);
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json(); 
    return data;
  } catch (error) {
    console.error('Error fetching OAuth2 token:', error);
    throw error;
  }
};

 


With a couple of helper functions:

 

const belongsToGroup = (user: User, groupName: string) => {
    if (user && user.groups && Array.isArray(user.groups)) {
        return user.groups.some(group => group.groupName.toLocaleLowerCase() === groupName.toLocaleLowerCase());
    }
    return false;
}

export const isSecurityAdmin = (user: User) => {
    return belongsToGroup(user, 'Security Admin');
}

 


You can store the oauth credentials in a .env for development purposes however I would recommend adding additional features to fetch and update the settings using the client-app-settings from the sdk.

 

// example

import { appSettingsObjectsClient, EffectiveAppSettingsValuesList, AppSettingsObjectResponse } from '@dynatrace-sdk/client-app-settings';

export const fetchConfig = async (schemaId: string): Promise<any[] | null> => {
    try {
        const response: EffectiveAppSettingsValuesList = await appSettingsObjectsClient.getEffectiveAppSettingsValues({
            schemaIds: schemaId,
        });

        if (response.items.length === 0) {
            console.warn(`No configuration found for ${schemaId}.`);
            return null;
        }

        console.log(`fetchConfig for schemaId: ${schemaId}`, response.items);

        return response.items;
    } catch (error) {
        console.error(`Error fetching configuration for schemaId: ${schemaId}`, error);
        return null;
    }
};

export const updateAppSettings = async (
    objectId: string,
    value: { [key: string]: any },
    optimisticLockingVersion: string
): Promise<boolean> => {
    let result = false;

    console.log('updateAppSettings', objectId, value);

    try {
        const putResponse: any = await appSettingsObjectsClient.putAppSettingsObjectByObjectId({
            objectId: objectId,
            optimisticLockingVersion: optimisticLockingVersion,
            body: {
                value: value
            }
        });

        if (putResponse) {
            console.log('Configuration updated:', putResponse);
            result = true;
        } else {
            console.warn('No response received from PUT request.');
        }
    } catch (putError) {
        console.error('Error during PUT:', putError);
    }

    return result;
};

 


The front-end parts:

 

// .... snippet

import React, { useEffect, useState } from 'react';
import { getCurrentUserDetails } from "@dynatrace-sdk/app-environment";
import { useAppFunction } from '@dynatrace-sdk/react-hooks';

// .... snippet
const [loading, setLoading] = useState(true);
const [userEmail, setUserEmail] = useState<string | null>(null);
const { setPermissions } = useAppState(); // custom hook to store state 

// .... snippet
// implement your own appFunction to fetch permissions that uses the getUserGroupsV2 function.
const fetchPermissions = useAppFunction({
    name: "backend",
    data: { query: "fetch-permissions", blob: userEmail },
  }, { autoFetch: false, autoFetchOnUpdate: true });

// .... snippet
useEffect(() => {
    const fetchUserData = async () => {
      try {
        const userDetails = await getCurrentUserDetails();
        console.log('User details:', userDetails);
        if (userDetails.email) {
          setUserEmail(userDetails.email);
          fetchPermissions.refetch();
        }
      } catch (error) {
        console.error('Failed to fetch data', error);
      } finally {
        setLoading(false);
      }
    }
    fetchUserData();
  }, []);

  useEffect(() => {
    if (fetchPermissions.data) {
      const { permissions } = fetchPermissions.data as PermissionsResponse;
      setPermissions(permissions);
    }
  }, [fetchPermissions]);

 

 

 

 

Based on the permissions you can toggle menu items:

 

{permissions?.admin && (
          <AppHeader.ActionItemGroup>
            <AppHeader.ActionButton
              prefixIcon={<SettingIcon />}
              showLabel={true}
              onClick={() => navigate('/settings')}
              aria-label="App Settings"
            >
              Settings
            </AppHeader.ActionButton>
          </AppHeader.ActionItemGroup>
)}

 

 

Featured Posts