4
4

More than 3 years have passed since last update.

ユーザーごとに表示する画面を切り替えるアクセス制御の実装(Google Apps Script + Vue.js + Bootstrap)

Last updated at Posted at 2020-01-07

はじめに

Google Apps ScriptのHTMLサービスを利用して簡易なワークフローツールを開発したい。
今回の記事ではアクセス制限の実装をする。

実現したいこと

アクセスしたユーザーの権限に応じて、表示する画面を切り替える。
例えば、Aというユーザーがアクセスした場合には入力フォームが表示されるが、
Bというユーザーがアクセスした場合には権限がありませんというメッセージを表示して登録できないようにする。

実装方針

  • スプレッドシートに、メールアドレスをキーにした権限テーブルを作成。
  • HTMLにアクセスした際にその権限テーブル(スプレッドシート)を読み込んで、アクセスしたユーザーのアクセス権限を取得。
  • ユーザーのアクセス権限に応じて表示するテンプレートを切り替える。
    • アクセス権限あり:入力フォームを表示
    • アクセス権限なし:アクセス権限がありませんというメッセージのみ表示し、入力フォームを表示しない。

データ

Spreadsheet(権限テーブル)

ID Role
Login User Email allow

IDにユーザーのメールアドレス、Roleにはそのユーザーの役割などを記入し一覧にする。
※今回は、Roleには”allow”という文字列。

コード(Google Apps Script)

コードはGoogleのSpreadsheetなどを起動し、ツール→スクリプトエディタを開いて作成。
参考までにスクリプトエディタを使ってHTML表示させるまでの手順についてまとめた記事を以下に記載

コード.js

コード.js
function doGet() {
  var html = HtmlService.createTemplateFromFile("index").evaluate().addMetaTag('viewport','width=device-width,initial-scale=1,minimal-ui');
  return html;
}


function getUser() {
  var email = Session.getActiveUser().getEmail();
  var mapData = getAccessList();

  return filterdData = mapData.filter(function(item, index){
    if (item.ID == email ) return true;
  });
}


function getAccessList(){
  var spreadSheetID = "yourSpreadsheetID";
  var sheetName = "yourSheetName";

  var res = SpreadsheetApp.openById(spreadSheetID)
    .getSheetByName(sheetName).getDataRange().getValues();

  var keys = res.splice(0, 1)[0];

  return res.map(function(row) {
    var obj = {}
    row.map(function(item, index) {
      obj[keys[index]] = item;
    });
    return obj;
  });
}

  • getUser()...アクセス権限テーブルを読み込んで、その中からアクセスしたユーザーに一致する権限を取得し返却

vue.html

vue.html
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>

<script>  
  var vm = new Vue({
    el: '#app',
    data: {
      changeTemplate:'loading',
    },
    computed: {         
    },
    watch: {
    },
    methods:{
      checkRole: function(loginUser){
        if (loginUser[0].Role == 'allow') {
          this.changeTemplate = 'allowAccess';          
        }else{
          this.changeTemplate = 'accessDeny';
        }
      }
    },
    created: function(){
      google.script.run
        .withSuccessHandler(this.checkRole).getUser();
    },
  })
</script>
  • changeTemplate...アクセス権の確認処理には若干の時間がかかるため、HTML表示時のtemplateの値をdataに定義しておく。
  • checkRole()...コード.jsのgetUser()によって返却されたデータを引数にとり、Roleの値が”allow”であれば"allowAccess"にtemplateを切り替え、そうでない場合は"accessDeny"にtemplateを切り替える。

index.html

index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <?!= HtmlService.createHtmlOutputFromFile('css').getContent(); ?>

  </head>
  <body>

  <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>

  <div class="collapse navbar-collapse" id="navbarsExampleDefault">
    <ul class="navbar-nav mr-auto">
      <li class="nav-item active">
        <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Link</a>
      </li>
      <li class="nav-item">
        <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
      </li>
      <li class="nav-item dropdown">
        <a class="nav-link dropdown-toggle" href="#" id="dropdown01" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a>
        <div class="dropdown-menu" aria-labelledby="dropdown01">
          <a class="dropdown-item" href="#">Action</a>
          <a class="dropdown-item" href="#">Another action</a>
          <a class="dropdown-item" href="#">Something else here</a>
        </div>
      </li>
    </ul>
    <form class="form-inline my-2 my-lg-0">
      <input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search">
      <button class="btn btn-secondary my-2 my-sm-0" type="submit">Search</button>
    </form>
  </div>
  </nav>

  <main role="main" class="container">
  <div id="app">

    <template v-if="changeTemplate == 'loading'">
      <div class="col-sm-12">
        <ul class="list">
          <li>アクセス権の有無を確認しています。</li>
        </ul>
      </div>
    </template>


    <template v-if="changeTemplate == 'allowAccess'">

      <div class="col-sm-12">
        <ul class="list">
          <li>Hello, world!</li>
          <li>アクセスが許可されました。</li>
        </ul>  
      </div>
    </template>


    <template v-if="changeTemplate == 'accessDeny'">
      <div class="col-sm-12">
        <ul class="list">
          <li>アクセスが拒否されました。</li>
        </ul>
      </div>
    </template>


  </div><!-- /.vue.el.app -->
  </main><!-- /.container -->

  <?!= HtmlService.createHtmlOutputFromFile('js').getContent(); ?>
  <?!= HtmlService.createHtmlOutputFromFile('vue').getContent(); ?>
  </body>
</html>
  • template v-if="changeTemplate == ''"...changeTemplateの値によりtemplateを切り替える。状態に合わせてtemplateを3つ用意。
  • HTML表示時〜checkRole()...loadingを表示
  • chechRole()後...Roleが”allow”なら許可用のtemplateを、それ以外は不許可用のtemplateを表示。

css.html

css.html
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<style>
  body {
    padding-top: 5rem;
  }
  .starter-template {
    padding: 3rem 1.5rem;
    text-align: center;
  }     
  .bd-placeholder-img {
    font-size: 1.125rem;
    text-anchor: middle;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
  }
  @media (min-width: 768px) {
    .bd-placeholder-img-lg {
    font-size: 3.5rem;
     }
  }
</style>

js.html

js.jtml
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

デザイン

BootstrapのExamplesをもとに作成。
Bootstrap starter template

技術要素

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4