AWS+Reactアプリ作成入門(Cognito編)
AWS+Reactアプリ作成入門(S3編)
AWS+Reactアプリ作成入門(DynamoDB編)
AWS+Reactアプリ作成入門(IAM Role編)
AWS+Reactアプリ作成入門(ログイン後のAdmin編)
今回作成したアプリ ==>久喜SNS
AWS+Reactアプリ作成入門は今回で最後です。書き残したことで重要なところを書きたいと思います。
今回特に難しかったところはCognitoの使い方でした。一通り「AWS+Reactアプリ作成入門(Cognito編)」に書きましたが、重要な点をまだ書いていません。Reactアプリは複数のComponentファイルから成り立っています。「AWS+Reactアプリ作成入門(Cognito編)」で示したApp Componentを参照してください。App.jsファイルがロードされたときに非ログインユーザとして権限を持ち、LoginView Componentでログインした時にログインユーザとしての権限を持つようになり、Admin ComponentでS3やDynamoDBに画像ファイルやドキュメントをputするわけです。明記しているドキュメントが見つからず、ログイン状態はAdmin.jsでもそのまま保持されるのかが疑問でした。いろいろ試行錯誤した結果、答えはYesです。
LoginView Componentで一度ログインすれば、その他のComponentのプログラムはログインユーザとして動作します。ユーザIDはAWS.config.credentials.identityIdでグローバルに参照できます。
1.Admin Component
Admin Componentはログイン後にメニューに現れる管理画面で、画像掲示板の投稿・編集・削除を行う場所です。ログインユーザとしての権限を最大限に発揮できる画面です。特にCognito認証関係のコードを書かずに権限を実行できます。
import AWS from "aws-sdk";
import React from 'react';
---
export default class Admin extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
---
_fetch(identityId) {
const _self = this;
var dynamo = new AWS.DynamoDB.DocumentClient();
var param = {
TableName : tablename,
ScanIndexForward: false, //queryには効くが、scanには効かない
KeyConditionExpression : "identityId = :identityId",
ExpressionAttributeValues : {":identityId" : identityId}
};
dynamo.query(param, function(err, data) {
if (err) {
console.log("### Error="+err);
} else {
//console.log("### data="+JSON.stringify(data.Items));
_self.setState({items: data.Items});
}
});
}
componentWillMount() {
const _self = this;
const email = localStorage.getItem('email');
const username = localStorage.getItem('username');
var identityId = AWS.config.credentials.identityId;
if( !email ) {
handleErrorFunc('エラー:ログインしていません');
return;
}
this.setState({identityId: identityId});
this.setState({email: email});
this.setState({username: username});
this._fetch(identityId);
}
---
postAdd() {
const _self = this;
const identityId = _self.state.identityId;
//-------------------------------
// Date
//-------------------------------
let uploadTime = 0;
let uploadDate = "";
let partitionYear = 0;
if( !this.state.updateItem ) { //新規投稿
const date = new Date() ;
uploadTime = date.getTime();
uploadDate = toLocaleString(date);
partitionYear = date.getFullYear();
} else { //編集投稿
uploadTime = _self.state.updateItem.uploadTime;
uploadDate = _self.state.updateItem.uploadDate;
partitionYear = _self.state.updateItem.partitionYear;
}
//-------------------------------
// S3 put
//-------------------------------
let filepath = noimage;
let thumbnail = noimage;
let fileType = noimage;
if( _self.state.imageOverwrite && !!_self.state.file) {
if (!_self.state.file.name.match(/^[0-9a-zA-Z\.\_\-]*$/)) {
handleErrorFunc('エラー:ファイル名は小文字の英数字と . - _ しか使えません: '+_self.state.file.name );
return;
}
filepath = 'contents/images/'+identityId+'/'+_self.state.file.name;
thumbnail = filepath.replace(/images/, 'thumbnail');
fileType = _self.state.file.type;
console.log("filepath="+filepath);
var params = {
Bucket: bucketname,
Key: filepath,
ContentType: _self.state.file.type,
Body: _self.state.file,
Metadata: {
data: JSON.stringify({
identityId: identityId,
uploadTime: uploadTime,
uploadDate: uploadDate
})
}
};
var s3 = new AWS.S3();
s3.putObject(params, function(err, data) {
if(err) {
console.log("Err: upload failed :" +err);
} else {
console.log("Success: upload ok");
let url = 'http://'+bucketname+'.s3-'+appConfig.region+'.amazonaws.com/'+filepath;
console.log("######11 imgurl="+url);
_self.setState({imgurl: url});
}
});
} else if ( _self.state.updateItem && !_self.state.imageOverwrite ) { //編集投稿で上書きアップロード無し
filepath = _self.state.updateItem.filename;
thumbnail = _self.state.updateItem.thumbnail;
fileType = _self.state.updateItem.fileType;;
}
//-------------------------------
// DynamoDB putItem
//-------------------------------
const title = escape_html(_self.state.title);
let story = escape_html(_self.state.story);
story = story.replace(/((http:|https:)\/\/[\x21-\x26\x28-\x7e]+)/gi, "<a href='$1'>$1</a>");
var docClient = new AWS.DynamoDB.DocumentClient();
var params = {
TableName: tablename,
Item:{
identityId: identityId, // ★prime partition key
email: _self.state.email,
username: _self.state.username,
filename: filepath,
thumbnail: thumbnail,
type: fileType,
title: title,
story: story,
imageOverwrite: _self.state.imageOverwrite,
mapUse: _self.state.mapUse,
position: _self.state.position,
uploadTime: uploadTime, // ★prime & secondary sort key
uploadDate: uploadDate,
partitionYear: partitionYear, //★secondary partition key
refCounter: 0
}
};
docClient.put(params, function(err, data) {
if(err) {
console.log("Err: table put :" +err);
} else {
console.log("Success: table put ok");
}
});
//-------------------------------
// Clear form
//-------------------------------
this.handlePostNew();
this._fetch(identityId);
}
---
LoginView Componentでログインしているので、このAdmin ComponentでもログインユーザとしてS3やDynamoDBにputする権限を持っています。一応念のためにcomponentWillMount()でログインしているかの確認をしています。localStorageにemailがセットされているか否かで判断しています。LoginView Componentの以下のコードが効いています。再掲載していきます。
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: appConfig.IdentityPoolId,
Logins : {
// Change the key below according to the specific region your user pool is in.
'cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_xxxxxx' : result.getIdToken().getJwtToken()
}
});
見直しや、修正を入れること張りますが、以上で「AWS+Reactアプリ作成入門」を終わります。