Do what you want to do

プログラミングとかとか

Nexus 5の画面が割れたので修理に出してみた

先日、外出中にポケットに入れていたNexus 5を地面に落としてしまいました。
落とした瞬間、ペチっと音がしましたがこれまでスマホの画面を割ったことはなかったので大丈夫だろうと拾い上げてみると…



f:id:katoj:20150326134932j:image

見事に割れてしまいました。。。
ショッーっく!!!(TдT)

すぐに修理してくれるお店を探したところ、
スマホステーションなるものを発見。

仕事場の近くにも店舗があったので出勤前にでも寄ろうかなと思っていたところ、Twitterでこんなリプライが。
f:id:katoj:20150326140002j:image


どうやらTwitterでのつぶやきを見て連絡してきたようです。

ちょっと怪しいなと思いながらも
対応が早そうだったことと、他より価格も若干安そうだったので思い切ってお願いすることにしました。

こちらの指定した場所、時間に端末を受け取りに来てもらい、その場で本人立会いのもと簡単な動作チェック。(近接センサが機能するかなど。)
その後端末を預け、1時間半たたないくらいで修理完了の連絡がありました。
早いですね!

元通りの綺麗な画面になってよかったーと思っていたのですが、触ってもいないのに画面がちらつく現象が。。。

電話で問い合わせたところ、
「メイン基盤と画面をつなぐ端子の一部分に接触不良があると思われる」とのことでした。
無料でまた見てくれるということだったのですが預けるにもこちらの都合が悪かったのでダメ元でとりあえず以下を試してみました。

  • 端末再起動
  • SIMカードの抜き差し
  • 画面に保護フィルムを貼る
上記を試して以降、今のところ画面のチラツキは起きていません。
とりあえず様子見ですねー。

その後、もう割りたくないのでケースも買い、今はこんな感じになっています。

f:id:katoj:20150326142459j:image 

以上、レポでした~。







【検証】Office 365アカウントの状態とYammerアクセストークンの有効・無効

前回はOffice 365アカウントでYammerにログインできるようにするとYammer REST APIのアクセストークンが無効になるという話でしたが、
これに関連してOffice 365アカウントの状態変化がYammerのアクセストークンにどのように影響するかを調べてみました。
※トークンはあらかじめ発行してREST APIが実行できる状態にしておきます。


結果は下記の通りです。

Office 365のアカウントに対する操作 Yammerトークンの有効・無効
パスワードを変更
無効化
有効化
削除 未検証

○・・・アクセストークンが有効のまま
×・・・アクセストークンが無効になる


パスワードを変更しても、アカウントを無効化/有効化しても操作前に取得したアクセストークンは無効にならずにそのまま使えることがわかりました。
Office 365アカウントの状態を変更してもYammerのユーザー情報には影響しないからでしょうか?
ただし、アカウントを完全削除した場合は諸事情により試せてません。
(誰か試して orz)

Office 365アカウントでYammerにログインできるようにするとREST APIのアクセストークンが無効になるので注意


上記記事にもある通りOffice365アカウントでYammerにログインさせることが可能ですが、これを行うとこれまで使えていたYammer REST APIのアクセストークンが無効になってしまうのでご注意ください。(APIをコールしても401が返ってくるようになります)
一度無効になってしまったらトークンを再取得すれば再びAPIをコールできます。

Yammer .NET SDKのサンプルプログラムを動かしてみた

今回はdotnet-yammersdkのサンプルプログラムを動かしてみました。
ダウンロードしたソリューションにはWindows Phone8用のプロジェクトも含まれていますが、私の環境では正常にプロジェクトが読み込めなかったので確認したのはYammer.Activities.ModernAppというWindows8用のプロジェクトです。

実行するに当たっての注意点

ダウンロードしたサンプルプログラムをそのまま実行しても最初のログイン画面でうまくログインできません。
原因はYammer側に登録したアプリ情報とプログラム側の設定が合っていないためです。

App.xamlを覗いてみると、アプリケーションリソースとしてアプリの情報を設定する箇所がありました。
以下の赤枠部分とYammer側に登録した情報を合わせる必要があります。

f:id:katoj:20150202110022p:plain

もともと設定されているms-app://で始まるRedirectUriは起動するWindows8アプリのURLです。
ログイン画面で認証に成功するとここで設定したURIにリダイレクトされアクセストークンを使用してYammerのデータを色々操作できるようになります。
なのでClientIdとClientSecretだけでなく、RedirectUriも忘れずにYammer側に設定するようにしましょう。

実行してみる

実行してみるとまずは起動画面が表示されます。(なぜ虎w)
f:id:katoj:20150202111135p:plain

次にログイン画面が表示されます。
f:id:katoj:20150202111312p:plain

メールアドレス、パスワードを入力してログインに成功するとMy contracts画面が表示されます。

f:id:katoj:20150202112920p:plain

まとめ

今回はYammer .NET SDKのサンプルプログラムを動かしてみました。
重要なことはApp.xamlでログインに必要な情報を全て設定することです。
認証で躓く、あるいはログインできないといった場合はまずYammer側に登録したアプリの情報とApp.xamlに設定した情報とが合っているかどうかを確認してください。

なお、認証はADFSあり/なしの環境両方で試しましたがどちらも正常に動作することを確認しました。
.NETで開発する場合はSDKを利用することで開発工数の削減や生産性向上が期待されます。
試してみてはいかがでしょうか。

Azure SDK 2.5のWADでカスタムログが転送されない問題

2015/07/14 追記:SDK 2.6ではrelativePathでログ転送できるようになったようです。

今回はAzureネタです。
親切な方がこちらのブログでAzure SDK 2.5のDiagnosticsへの移行方法をまとめて下さっています。

私もSDK2.5にアップグレードしてWADの動作を確認してみたところ、
ローカルストレージに出力したアプリケーションのログファイルだけが
BLOBに転送されない!!!なぜだ???

ちなみにdiagnostics.wadcfgxの設定はこんな感じになっています。(該当部分のみ抜粋)

<DataSources>
  <DirectoryConfiguration containerName="customlog">
    <LocalResource name="LogStore" relativePath="."/>
  </DirectoryConfiguration>
</DataSources>

LocalResource指定の方法はVisual StudioGUIからは設定できないのですが、wadcfgxを直接編集することで設定できるんですよね~。(参考)

自分だけかと思って他の方にも確認していただいたところ、同じように転送できないそうなのでSDK2.5のバグかもしれません。。

現時点での対応としてはVisual StudioGUIから設定できる絶対パスで設定するしかないようです。

<DataSources>
  <DirectoryConfiguration containerName="customlog">
    <Absolute path="C:\Resources\directory\<ロールのデプロイID>.<ロール名>.<ローカルストレージ名>" expandEnvironment="false"/>
  </DirectoryConfiguration>
</DataSources>

ちなみにAbsoluteの方法では環境変数が使えないバグ?があるみたいなので注意が必要です。
普通、Absoluteの方法では環境変数の値を使ってC:\Resources\Directory\%RoleDeploymentID%.%RoleName%.<ローカルストレージ名>のように設定すると思いますがこれだとうまく転送されません。ロールのデプロイIDやロール名をハードコードする必要があります。

2015年12月9日の対応期限までにこれらのおかしな問題が修正されれば良いのですが。

目的別!yammer REST APIまとめ ~Group編~

公式ドキュメントにこういうリクエスト送ればこういうことできるみたいなことは書いてあるのですが正直これだけだと不足していると思います。
そこで今回はこれまに調査したGroupに関連するAPIを備忘録も兼ねてまとめてみたいと思います。
※yammerのREST APIはHTTPのAuthorizationヘッダに設定したトークン(≠ユーザー)のコンテキストで実行されます。
偽装を使って別ユーザーのコンテキストで実行したい場合はyammer REST APIのユーザー偽装について - Jun's blogを参考にしてください。

Privateグループを作りたい

POST https://www.yammer.com/api/v1/groups.json?name=<グループ名>&private=<1 or 0 もしくは true or false>
201 Created
{
    "type": "group",
    "id": xxx,
    "full_name": "xxx",
    "network_id": xxx,
    "name": "xxx",
    "description": null,
    "privacy": "private",
    "url": "xxx",
    "web_url": "xxx",
    "mugshot_url": "xxx",
    "mugshot_url_template": "xxx",
    "mugshot_id": null,
    "show_in_directory": "true",
    "office365_url": null,
    "created_at": "2014/12/25 06:20:46 +0000",
    "creator_type": "user",
    "creator_id": xxx,
    "state": "active",
    "stats": {
        "members": 1,
        "updates": 0,
        "last_message_id": null,
        "last_message_at": null
    }
}

※private=1:Privateグループ = true
 private=0:Publicグループ = false

既存グループのPrivateとPublicを切り替えたい

PUT https://www.yammer.com/api/v1/groups/<グループID>.json?private=<1 or 0 もしくは true or false>
200 OK

Privateグループ作成時に、"グループ一覧に公開する"を指定したい

POST https://www.yammer.com/api/v1/groups.json?name=<グループ名>&private=1&show_in_directory=<1 or 0 もしくは true or false>
201 Created

※show_in_directory=1:グループ一覧に公開する = true
 show_in_directory=0:グループ一覧に公開しない = false

既存Privateグループの"グループ一覧に公開する"を切り替えたい

PUT https://www.yammer.com/api/v1/groups/<グループID>.json?show_in_directory=<1 or 0 もしくは true or false>
200 OK

グループに登録されているユーザーを取得したい

GET https://www.yammer.com/api/v1/users/in_group/<グループID>.json

200 OK
{
    "users": [
        {
            "type": "user",
            "id": xxx,
            "name": "xxx",
            "state": "active",
            "full_name": "xxx",
            "job_title": null,
            "network_id": xxx,
            "mugshot_url": "xxx",
            "mugshot_url_template": "xxx",
            "url": "xxx",
            "web_url": "xxx",
            "activated_at": "2013/12/02 05:04:51 +0000",
            "stats": {
                "following": 2,
                "followers": 3,
                "updates": 0
            }
        },
        {
            "type": "user",
            "id": yyy,
            "name": "yyy",
            "state": "active",
            "full_name": "yyy",
            "job_title": "",
            "network_id": xxx,
            "mugshot_url": "xxx",
            "mugshot_url_template": "xxx",
            "url": "yyy",
            "web_url": "yyy",
            "activated_at": "2014/05/19 06:16:53 +0000",
            "stats": {
                "following": 1,
                "followers": 0,
                "updates": 0
            }
        }
    ],
    "more_available": false,
    "meta": {
        "followed_user_ids": []
    }
}

グループにTopicを紐づけたメッセージを投稿したい

POST https://www.yammer.com/api/v1/messages.json?body=<メッセージ>&group_id=<グループID>&topic1=<トピック名>
201 Created
{
    "threaded_extended": {},
    "messages": [
        {
            "id": xxx,
            "sender_id": xxx,
            "replied_to_id": null,
            "created_at": "2014/12/05 01:47:24 +0000",
            "network_id": xxx,
            "message_type": "update",
            "sender_type": "user",
            "url": "xxx",
            "web_url": "xxx",
            "group_id": xxx,
            "body": {
                "parsed": "投稿します",
                "plain": "投稿します",
                "rich": "投稿します"
            },
            "thread_id": xxx,
            "client_type": "xxx",
            "client_url": "xxx",
            "system_message": false,
            "direct_message": false,
            "chat_client_sequence": null,
            "content_excerpt": "投稿します",
            "language": null,
            "notified_user_ids": [],
            "privacy": "public",
            "attachments": [],
            "liked_by": {
                "count": 0,
                "names": []
            },
            "group_created_id": xxx
        }
    ],
    "references": [
        {
            "type": "user",
            "id": xxx,
            "name": "xxx",
            "state": "active",
            "full_name": "xxx",
            "job_title": "xxx",
            "network_id": xxx,
            "mugshot_url": "xxx",
            "mugshot_url_template": "xxx",
            "url": "xxx",
            "web_url": "xxx",
            "activated_at": "2014/03/25 00:23:50 +0000",
            "stats": {
                "following": 24,
                "followers": 24,
                "updates": 0
            }
        },
        {
            "url": "xxx",
            "web_url": "xxx",
            "type": "thread",
            "id": xxx,
            "network_id": xxx,
            "thread_starter_id": xxx,
            "group_id": xxx,
            "topics": [
                {
                    "id": xxx,
                    "type": "topic"
                }
            ],
            "privacy": "public",
            "direct_message": false,
            "has_attachments": false,
            "stats": {
                "updates": 0,
                "shares": 0,
                "first_reply_id": null,
                "first_reply_at": null,
                "latest_reply_id": xxx,
                "latest_reply_at": "2014/12/05 01:47:24 +0000"
            },
            "invited_user_ids": []
        },
        {
            "type": "group",
            "id": xxx,
            "full_name": "xxx",
            "network_id": xxx,
            "name": "xxx",
            "description": null,
            "privacy": "public",
            "url": "xxx",
            "web_url": "xxx",
            "mugshot_url": "xxx",
            "mugshot_url_template": "xxx",
            "mugshot_id": null,
            "show_in_directory": "true",
            "office365_url": null,
            "created_at": "2014/12/05 01:31:31 +0000"
        },
        {
            "type": "topic",
            "id": xxx,
            "name": "テストトピック",
            "normalized_name": "テストトピック",
            "permalink": "テストトピック",
            "url": "xxx",
            "web_url": "xxx"
        }
    ],
    "external_references": [],
    "meta": {
        "requested_poll_interval": 60,
        "last_seen_message_id": null,
        "current_user_id": xxx,
        "followed_references": [],
        "ymodules": [],
        "newest_message_details": null,
        "feed_name": "xxx",
        "feed_desc": "xxx",
        "direct_from_body": false
    }
}

※Topicはtopic1からtopic20まで指定可能

まとめ

以上、これまでに調べたGroup関連のAPIでした。
これやりたいけど公式ドキュメントに載っていない!
どういうリクエスト投げればいいかわからない!!っていう人の参考になればと思います。

yammer REST APIのユーザー偽装について

前回はアプリの登録からアクセストークンを取得してAPIを実行するところまで書きました。
通常のREST API利用方法は確かにその通りなのですが、特にSharePointや外部システムと連携してyammerのREST APIを実行する場合は以下のようなニーズもあることでしょう。

  • ユーザー毎にアプリの認可をさせたくない
  • yammerの画面を操作するのは管理者だけで一般ユーザーにはなるべくyammerを意識させたくない

そのような場合、Verified Adminという権限を使えばユーザーを偽装できます。

Verified Adminとは

日本語では「認証管理者」と言い、以下の特徴を持つ特別な権限です。

  • データのエクスポート、プライベートグループのメッセージ読み取りやセキュリティ設定の構成が可能であるなどネットワーク管理者よりも強い権限
  • 有償版Yammerのみに存在
  • Office365全体管理者は自動的にVerifiedAdminの権限が与えられる

ネットワーク管理者との比較については下記公式管理ガイドをご覧ください。
管理アクセス特権 - Yammer Success Center

ユーザー偽装手順

ではこのVerified Adminを使用してユーザーを偽装してみましょう。
ここでは偽装対象ユーザーのメールアドレスがわかっている前提でユーザーを偽装してのグループ作成を行ってみたいと思います。

  1. まず、前回のアクセストークン取得と同じ手順でVerified Admin権限を持つユーザーのアクセストークンを取得します。ここでは最低でも1回はアプリの認可が必要になります。
  2. 次に以下のリクエストを実行して偽装対象ユーザーのIDを取得します。

    GET https://www.yammer.com/api/v1/users/by_email.json?email=<追加対象ユーザーのメールアドレス>

  3. [
        {
            "type": "user",
            "id": xxxxxxxxxx,
            "network_id": xxxxxxx,
            以下省略・・・
      }
    ]
    

  4. 次に以下のリクエストを実行して偽装対象ユーザーのアクセストークンを取得します。

    GET https://www.yammer.com/api/v1/oauth/tokens.json?user_id=<偽装対象ユーザーのID>&consumer_key=<クライアントID>

    このリクエストはVerified Adminで行う必要があるため、HTTPのAuthorizationヘッダにVerified Adminのトークンを指定してください。
    ※consumer_keyは登録したアプリのクライアントIDです。

  5. [
        {
            "user_id": ユーザーID,
            "network_id": ネットワークID,
            途中省略・・・
            "token": "xxxxxxxxxxxxxxxxxxxxx",
            以下省略・・・
        }
    ]
    

  6. 最後に偽装対象ユーザーのトークンをAuthorizationヘッダに指定してグループ作成リクエストを実行します。

    POST https://www.yammer.com/api/v1/groups.json?name=<グループ名>

    正常に処理が終了すれば以下のような作成したグループの情報が返ります。

    {
        "type": "group",
        "id": グループID,
        "full_name": グループフルネーム,
        "network_id": ネットワークID,
      以下省略・・・
    }

    ユーザーを偽装してグループを作成したのでグループ管理者が偽装したユーザーになっていると思います。

まとめ

今回はVerified Adminを使用してユーザー偽装を行いました。
アプリ認可がVerified Adminの1回だけで偽装対象ユーザーのアプリ認可をスキップできていることがお分かりいただけたかと思います。
Verified Adminはユーザーに割り当てることができる管理用制御の最高レベルなので他にもいろいろできそうです。
有償版Yammerをご利用の方は試してみてはいかがでしょうか。