« 2014年5月 | メイン | 2014年7月 »

2014年6月に作成された記事

2014年6月 9日 (月)

OpenID Connectを使用したシングルサインオン

エンジニアの木下です。

今回はWinter'14でサポートされたOpenID Connectを使用したSSOを試してみましたので設定方法をまとめてみました。

1. [Google]OAuthクライアントの登録

まずはOAuthクライアントIDを作成します。

Google Developers Console から"APIs & Auth" > "Credentials Oath"と進み、"Create new Client ID"をクリックします。

101createoauthclient

ApplicationTypeは"Web application"を選択します。
AUTHORIZED JAVASCRIPT ORIGINS、AUTHORIZED REDIRECT URIは後ほど設定します。

02settingapplicationtype

Client IDを作成後、作成されたClient IDとClient Secretなどが表示されます。
これをSalesforceへ設定します。

103createdclientid

"APIs & Auth" > "Consent screen"にある"PRODUCT NAME"で最初のログイン時に表示される名前を設定します。

104consentscreensetting

2. [Salesforce]認証プロバイダの設定

Salesforceにログイン後、"設定" > "セキュリティのコントロール" > "認証プロバイダ"と進み、新規ボタンをクリックし以下を設定します。
プロバイダタイプ:Open ID Connect
コンシューマ鍵:1で作成したClient ID
コンシューマの秘密:1で作成したClient Secret
承認エンドポイント URL:https://accounts.google.com/o/oauth2/auth
トークンエンドポイント URL:https://accounts.google.com/o/oauth2/token
ユーザ情報エンドポイント URL:https://www.googleapis.com/oauth2/v3/userinfo

保存するとクライアント設定が表示されるので1で作成したOAuthクライアントを編集します。AUTHORIZED REDIRECT URIにコールバック URLを設定します。AUTHORIZED JAVASCRIPT ORIGINSは空で良いようです。

106createdauthprovider

3. [Salesforce]登録ハンドラの実装

登録ハンドラはAuth.RegistrationHandlerインターフェースを実装する必要があります。実装するメソッドはcreateUserとupdateUserの二つです。

createUserは初回ログイン時に、updateUserは二回目以降のログイン時に呼ばれるメソッドです。Auth.UserDataにはidentifier(GoogleのID)やemail(メールアドレス)などのプロパティがあるのでcreateUserではそれらの情報をもとにユーザを特定します。

updateUserではここでは特になにもしていませんが、Auth.UserData dataからユーザの情報を更新などできそうです。

public class GoogleHandler implements Auth.RegistrationHandler{
    public User createUser(Id portalId, Auth.UserData data){
        User u = [SELECT Id FROM User WHERE Username = :data.email];
        return u;
    }

    public void updateUser(Id userId, Id portalId, Auth.UserData data){
    }
}

4. [Salesforce]ログイン

最後にログインページの設定です。シングルサインオン初期化 URLからでもSSOできますが、今回はドメインを作成し、ログインページのSSOのボタンからログインしてみます。

"ドメイン" > "私のドメイン"からドメインを作成し、ログインページのブランド設定で認証サービスに2で設定した認証プロバイダ名「Google Login」を追加します。

20140609_63331

通常のログインボタンの下に「Google Login」が表示されました。このボタンからSSOでログインができます。

設定も簡単でログインの手間も省けて嬉しい限りです。

2014年6月 1日 (日)

Visualforce Remote Objectsを使ったデータ更新

エンジニアの谷隈です。

Spring'14からパイロットリリースされている新機能「Visualforce Remote Objects」でのデータ取得について前回検証しました。
今回は更新処理について検証します。

ちなみに「Visualforce Remote Objects」というのはVisualforce上からJavaScript経由でセールスフォース上のオブジェクトデータを操作(取得・作成・更新・削除)する仕組みです。

○使い方

「Visualforce Remote Objects」を使用する際の大まかな手順は次の2ステップになります。
データ更新をする場合でも大まかな手順はデータ取得の場合と同じです。

Step

まずはイメージを掴むための、簡単なサンプルから。

コード例:Visualforce

<apex:remoteObjects >
  <apex:remoteObjectModel name="Test__c" fields="Id, Name, DateField__c, DateTimeField__c, CreatedDate"/>
</apex:remoteObjects>

「Visualforce Remote Objects」でオブジェクトのデータを操作する場合には、どのオブジェクトのどのフィールドを使用するかどうかをapexタグで宣言する必要があります。
上のコードはVisualforceページにTest__cオブジェクトを使用するためのタグを記載したコード例です。
Test__cオブジェクトのId, Name, DateField__c, DateTimeField__c, CreatedDateフィールドへの使用を宣言しています。
apexのタグの使い方はデータ取得の場合と同じです。

apexタグのドキュメントは下記です。
apex:remoteObjects
http://www.salesforce.com/us/developer/docs/pages/Content/pages_compref_remoteObjects.htm
apex:remoteObjectModel
http://www.salesforce.com/us/developer/docs/pages/Content/pages_compref_remoteObjectModel.htm
apex:remoteObjectField
http://www.salesforce.com/us/developer/docs/pages/Content/pages_compref_remoteObjectField.htm

コード例 JavaScript

var obj = new SObjectModel.Test__c();
obj.set('Id', 'a00U0000006eU8fIAE');
obj.set('DateField__c', new Date());

obj.update(function(error, result, event){
    // 更新完了後の処理
});

JavaScript側のコードは、apexタグにより生成されたモデルを利用してデータの操作を行います。
データの更新には「update」functionを使用します。
上の例は最も使うであろう呼び出し方で書いていますが、「update」function にはいくつか呼び出し方にバリエーションがあります。

○JavaScriptコードについての詳細

「Visualforce Remote Objects」利用時のJavaScriptコードの基本的な流れは次の2ステップです。

1. apexタグにより生成されたモデルのオブジェクトを生成
2. 生成したオブジェクトのメソッドを呼び出す。

データの更新にはapexタグで生成されたモデルの「update」functionを使います。

Updating Records with Remote Objects
https://www.salesforce.com/us/developer/docs/pages/Content/pages_remote_objects_using_update.htm

パターン① シンプルなupdate

「update」functionの一番シンプルな呼び出し方は、引数無しでfunctionを呼び出すだけの形になります。

var obj = new SObjectModel.Test__c();
obj.set('Id', 'a00U0000006eU8fIAE');
obj.set('DateField__c', new Date());

obj.update();

ドキュメントには上の形の変形パターンとして引数でセットする値をオブジェクトで渡す形の説明がありましたが、実際に試してみたところこちらは正しく動作しませんでした。
何か試し方が悪かったのかもしれません。

var obj = new SObjectModel.Test__c();
obj.update({
	Id: 'a00U0000006eU8fIAE',
	DateField__c: new Date()
});

いずれにしろ、シンプルな呼び出しのパターンではupdate処理が成功したかどうかが確認できないので使うケースはあまり無さそうです。

パターン② updateの結果をコールバックfunctionで処理する

「update」functionは引数に実行結果を処理するコールバックfunctionを指定して呼び出すこともできます。

var obj = new SObjectModel.Test__c();
obj.set('Id', 'a00U0000006eU8fIAE');
obj.set('DateField__c', new Date());

obj.update(function(error, result, event){
    // 更新完了後の処理
});

使うとしたらこれが一番活躍するパターンだと思われます。
引数にコールバックfunctionを指定します。

更新処理完了後、ここで指定したfunctionが呼び出されるので、処理結果に応じた後処理を行うことができます。

function callback(error, results, event) { // ... }

基本、retrieveの時と同じですが一部格納されるデータに違いがあります。

コールバックfunctionの引数

引数説明
error エラーメッセージが格納されます。正常終了時はnullです。
results 更新処理で影響を受けたオブジェクトのIDが配列で返されます。
event DML操作の詳細情報が格納されます。

Remote Objects Callback Functions
http://www.salesforce.com/us/developer/docs/pages/Content/pages_remote_objects_callback_functions.htm

パターン③ 複数レコードを一括で更新する

最後は複数レコードを一括で更新する呼び出し方です。
第1引数に更新するオブジェクトのIDの配列、第2引数に更新する値を指定したオブジェクト、第3引数にコールバックfunctionを指定します。

var obj = new SObjectModel.Test__c();
obj.update(
    ['a00U0000006eU8fIAE','a00U0000006eU8eIAE']
    ,{DateField__c: new Date(2020,8,1)}
    ,function(error, result, event){
        // 更新完了後の処理
    }
);

この一括更新は指定した全オブジェクトを同じ値に更新することしかできないので、使いどころは限られてくると思います。

○その他気になるポイント

・バリデーションエラー

バリデーションエラー発生時の動きは必須項目設定、入力規則、その他の場合、すべて同じです。
コールバックfunctionのerrorオブジェクトにエラーメッセージが設定されて帰ってきます。

function callback(error, results, event) { // ... }

簡易にチェックするならerrorがnullでないかで確認が可能です。

また、同様な情報はeventオブジェクトにも含まれています。

・トランザクション

トランザクションはDML操作のfunction呼び出し単位になります。
トランザクションを考慮した処理を実装したい場合は別の方式を考える必要がありそうです。

Best Practices for Using Remote Objects
https://www.salesforce.com/us/developer/docs/pages/Content/pages_remote_objects_considerations.htm

・オブジェクト権限と項目レベルセキュリティ

オブジェクト権限に読み取りしかない場合、updateの呼び出し結果はエラーになります。
項目レベルセキュリティについては読み取りのみの項目の場合も更新できました。
これは裏側の実装がapexだからということなのかもしれません。

Visualforce Remote Objects
http://www.salesforce.com/us/developer/docs/pages/Content/pages_remote_objects.htm

・日付/日時型の扱い

日付/日時型の値は取得時にはローカルタイムゾーンでDate型に変換されて表示されます。
ここまでは問題ありません。
ところが保存時はJavaScript上のDateの時間がGMT+0000扱いされている様で、SF上で9時間加算されます。
結果、日本環境だと取得してそのまま保存するだけで9時間加算されてしまいます。
今がパイロットだからということであれば良いのですが、修正されない様であれば注意が必要です。

○おまけ

Summer'14のリリースでVisualforce Remote Objectsに機能追加がされる様です。
主な追加機能。
・検索処理時に指定できる条件の追加(lte, gte, ne, order by)
・upsert()操作の追加
・デフォルトの処理のオーバーライドが可能になる

Visualforce Remote Objects Enhancements
https://developer.salesforce.com/releases/release/Summer14/Visualforce+Remote+Objects+Improvements

採用情報

株式会社フレクトでは、事業拡大のため、
・Salesforce/Force.comのアプリケーション開発
・HerokuやAWSなどのクラウドプラットフォーム上
でのWebアプリケーション開発
エンジニア、マネージャーを募集中です。

未経験でも、これからクラウドをやってみたい方、
是非ご応募下さい。

フレクト採用ページへ

会社紹介

  • 株式会社フレクトは、
      ・認定コンサルタント
      ・認定上級デベロッパー
      ・認定デベロッパー
    が在籍している、セールスフォースパートナーです。
    また、heroku partnersにも登録されています。
    herokuパートナー
    株式会社フレクト
    Salesforce/Force.com
    導入支援サービス
    弊社の認定プロフェッショナルが支援致します。
    ・Visualforce/Apexによるアプリ開発
    ・Salesforceと連携するWebアプリ開発
    も承っております。
    セールスフォースご検討の際は、
    お気軽にお問合せください。

Twitter

リファレンス

■Developer's Guide(リファレンス)
・Apex  HTML | PDF | 日本語PDF | ガバナ制限
・Visualforce  HTML | PDF
・Web Services API  HTML | PDF | 日本語PDF
・Bulk API  HTML | PDF
・REST API  HTML | PDF | 日本語PDF
・Metadata API  HTML | PDF
・Migration Tool  HTML | PDF
・AJAX Toolkit  HTML | PDF
・Data Loader PDF | 日本語PDF

■早見表 (日本語)
数式
Apex
Visualforce
Web Services API
Chatter