Created
August 20, 2018 18:46
-
-
Save asciimike/f18b1991f74f7a266e0d15f31d46d637 to your computer and use it in GitHub Desktop.
Firebase Pro Series "Pro Chat" secure chat app (from http://youtu.be/oFlHzF5U-HA)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function isChatMessage(message) { | |
return message.size() == 4 | |
&& message.username is string | |
&& message.userId is string | |
&& message.createdAt is timestamp | |
&& message.messageText is string | |
&& message.messageText.size() <= 160; | |
} | |
function isUser(user) { | |
return user.size() == 1 | |
&& (user.role == 'editor' || user.role == 'reader'); | |
} | |
function isAdminUser(user) { | |
return user.size() == 1 | |
&& user.role == 'admin'; | |
} | |
service cloud.firestore { | |
match /databases/{database}/documents { | |
match /rooms/{roomId} { | |
function getRoleForUser(userId) { | |
return get(/databases/$(database)/documents/rooms/$(roomId)/users/$(userId)).data.role; | |
} | |
function roomExists(roomId) { | |
return exists(/databases/$(database)/documents/rooms/$(roomId)); | |
} | |
match /messages/{messageId} { | |
allow create: if isChatMessage(request.resource.data) | |
&& request.resource.data.userId == request.auth.uid | |
&& getRoleForUser(request.auth.uid) == 'editor'; | |
allow get, list: if getRoleForUser(request.auth.uid) in ['editor', 'reader']; | |
} | |
match /users/{userId} { | |
allow create: if (!roomExists(roomId) | |
&& isAdminUser(request.resource.data) | |
&& request.auth.uid == userId) | |
|| (getRoleForUser(request.auth.uid) == 'admin' | |
&& isUser(request.resource.data) | |
&& request.auth.uid != userId); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<title>Firebase Pro Series Chat App</title> | |
<script src="https://www.gstatic.com/firebasejs/4.9.0/firebase.js"></script> | |
<script src="https://www.gstatic.com/firebasejs/4.9.0/firebase-firestore.js"></script> | |
<script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js'></script> | |
</head> | |
<body> | |
<div id="stream"> | |
<h1>Pro Chat</h1> | |
<input type="text" id="usernameInput" placeholder="Provide a username"/> | |
<input type="text" id="msgInput" placeholder="Add message"/> | |
<button type="submit" id="submit">Submit</button> | |
</br> | |
</br> | |
<div id="msg-box"></div> | |
</div> | |
<script> | |
// STEP 0: Configure Firebase | |
// TODO: Replace with your own config | |
var config = { | |
apiKey: ..., | |
authDomain: ..., | |
databaseURL: ..., | |
projectId: ..., | |
storageBucket: ..., | |
messagingSenderId: ... | |
}; | |
firebase.initializeApp(config); | |
//STEP 1: Create references | |
var firestore = firebase.firestore(); | |
var auth = firebase.auth(); | |
var uid; | |
// STEP 2: Log a user in | |
auth.signInAnonymously().then(user => { | |
uid = user.uid; | |
console.log(uid); | |
// STEP 3: Listen for new messages | |
firestore.collection('rooms') | |
.doc('public') | |
.collection('messages') | |
.orderBy('createdAt') | |
.onSnapshot(docs => { | |
$('#msg-box').empty(); | |
docs.forEach(function (doc) { | |
var message = doc.data(); | |
$('#msg-box').append($("<div class='msg-text'>").text(message.username).append('<br/>').append($('<span/>').text(message.messageText))).append('<br/>'); | |
}); | |
}, error => { | |
alert(error); | |
}); | |
}); | |
//STEP 2: Store messages in Cloud Firestore | |
$('#submit').on('click', function () { | |
if (uid !== null) { | |
var username = $('#usernameInput').val(); | |
var message = $('#msgInput').val(); | |
firestore.collection('rooms') | |
.doc('public') | |
.collection('messages') | |
.add({ | |
'username': username, | |
'userId': uid, | |
'createdAt': new Date(), | |
'messageText': message | |
}).catch(error => { | |
alert(error); | |
}); | |
$('#msgInput').val(''); | |
} else { | |
alert('You must log in to post!'); | |
} | |
}); | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"username": "Mike McDonald", | |
"userId": "7199732f-ec7a-46bd-8949-71cd323a21fd", | |
"createdAt": "2018-01-29T01:23:45Z", | |
"messageText": "Hello, World!" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"role": "editor" // or "reader" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
When should one use this approach and not Custom Claims? https://firebase.google.com/docs/auth/admin/custom-claims