はじめに
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