Help us understand the problem. What is going on with this article?

Lightning コンポーネントの実行環境や実行ユーザ種別を取得する

More than 1 year has passed since last update.

Lightning コンポーネントを開発していると、実行環境や実行ユーザの種類によって動作を変更させたい場合があります。
そこで Lightning コンポーネントで使える簡単なツールコンポーネントを作ってみました。

検知可能なコンテキスト

このコンポーネントは、自分が現在実行されている環境について以下の情報を取得出来ます。

  • 実行環境
    • コミュニティ
    • Lightning Experience
    • Salesforce モバイルアプリ
    • Lightning Experience ビルダー
    • コミュニティビルダー
    • コミュニティプレビュー
  • 実行ユーザ
    • ゲストユーザ
    • 外部ユーザ
    • 内部ユーザ

使い方

LightningContext のインスタンスを作成し getContext() を呼び出す事で、Thenable なコンテキストオブジェクトが取得できます。

HowToUseLightningContext.cmp
<aura:component access="global">
    <!-- Event Handler -->
    <aura:handler name="init" value="{!this}" action="{!c.onInit}" />

    <!-- Lightning Context -->
    <c:LightningContext aura:id="context" />
</aura:component>
HowToUseLightningContextController.js
({
    onInit: function(c, e, h) {        
        c.find("context").getContext()
        .then($A.getCallback(function(ctx) {

            // 実行環境を検知
            if (ctx.isCommunity) {
                // コミュニティ
            } else if (ctx.isLex) {
                // Lightning Experience
            } else if (ctx.isMobile) {
                // Salesforce モバイルアプリ
            } else if (ctx.isLexBuilder) {
                // Lightning Experience ビルダー 
            } else if (ctx.isCommunityBuilder) {
                // コミュニティビルダー
            } else if (ctx.isCommunityPreview) {
                // コミュニティプレビュー
            }

            // 実行ユーザを検知
            if (ctx.isGuestUser) {
                // ゲストユーザ
            } else if (ctx.isInternalUser) {
                // 内部ユーザ
            } else if (ctx.isExternalUser) {
                // 外部ユーザ
            }
        }));
    }
})

LightningContext の実装

LightningContext バンドルの実装例になります。
主に Apex で取得できる情報とクライアント上で取得できる情報を加味した上で、最終的なコンテキストの判断を行っています。
コンポーネントメソッドとして getContext を持っており、このメソッドが呼び出された際にコンテキストを検出し返します。ただし、パフォーマンス向上のため 2 度目以降の getContext 呼び出し時には、属性に保存されたコンテキストを直接返します。

LightningContext.cmp
<aura:component access="global" controller="LightningContextController">
    <!-- Private Attributes -->
    <aura:attribute access="private" type="Map"  name="context" />

    <!-- Global Method -->
    <aura:method access="global" name="getContext" action="{!c.onGetContext}" /> 
</aura:component>
LightningContextController.js
({
    onGetContext: function(c, e, h) {
        return c.get("v.context") ? Promise.resolve(c.get("v.context")) : h.getContext(c, h)
        .then($A.getCallback(function(ctx) {
            const containsLexBuilderURL = document.location.href.toLowerCase().indexOf("flexipageeditor") >= 0;
            const containsCommunityBuilderURL = document.location.href.toLowerCase().indexOf(".livepreview.salesforce-communities.com") >= 0;
            const containsCommunityPreviewURL = document.location.href.toLowerCase().indexOf(".preview.salesforce-communities.com") >= 0;

            const context = {
                isCommunity: ctx.isSite,
                isLex:       !ctx.isSite && ctx.uiThemeDisplayed === "Theme4d",
                isMobile:    ctx.uiThemeDisplayed === "Theme4t",

                isLexBuilder:       !ctx.isSite && ctx.uiThemeDisplayed === "Theme4d" && containsLexBuilderURL,
                isCommunityBuilder: ctx.isSite && containsCommunityBuilderURL,
                isCommunityPreview: ctx.isSite && containsCommunityPreviewURL, 

                isGuestUser:    ctx.isGuestUser,
                isInternalUser: ctx.isInternalUser,
                isExternalUser: !ctx.isInternalUser && !ctx.isGuestUser, 
            };
            c.set("v.context", context);
            return context;
        }))
        .catch($A.getCallback(function(reason) {
            console.error(reason);
        })); 
    },
})
LightningContextHelper.js
({
    getContext: function(c, h) {
        const action = c.get("c.getContext");
        return new Promise(function (resolve, reject) {
            action.setCallback(this, function(response) {
                const ret = response.getReturnValue();
                if (response.getState() === 'SUCCESS') ret.hasError ? reject(ret.message) : resolve(ret);
                else if (response.getState() === 'ERROR') reject(response.getError());
            });
            $A.enqueueAction(action);
        });
    },
})
LightningContextController.apxc
public class LightningContextController {
    public class Error {
        @AuraEnabled public String message;
        @AuraEnabled public Boolean hasError = true;
        public Error(String message){
            this.message = message;
        }
    } 

    @AuraEnabled
    public static Object getContext() {
        try {
            Map<String, Object> ctx = new Map<String, Object>();
            ctx.put('isSite', String.isNotBlank(Site.getSiteId()));
            ctx.put('uiThemeDisplayed', UserInfo.getUiThemeDisplayed());
            ctx.put('isInternalUser', Auth.CommunitiesUtil.isInternalUser());
            ctx.put('isGuestUser', Auth.CommunitiesUtil.isGuestUser());
            return ctx;
        } catch (Exception e) {
            return new Error(e.getMessage());
        }
    }  
}
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away