A clojure library to make working with firebase easier
- Authentication, email verification and password resets are tedious and hard.
- Auth0 gets pricey as you scale
- Firebase auth has a fixed cost of 0 (for now)
[alekcz/charmander "1.0.3"]
;; In your ns statement:
(ns my.ns
(:require [charmander.core :as charm]
[charmander.admin :as charm-admin]
[charmander.firestore :as charm-firestore]))
-
Token API
validate-token
-
Admin API
init
create-user
delete-user
get-user
get-user-by-email
get-user-by-phone-number
set-user-email
set-user-password
set-user-phone-number
set-user-display-name
set-user-photo-url
generate-email-verification-link
generate-password-reset-link
-
Firestore API
create-document
add-document-to-collection
get-document
get-document-and-subcollections
get-collection
set-document
update-document
delete-document
Validates firebase tokens. Validating tokens doesn't require an admin or service account.
(charm/validate-token "firebase-project-id" fresh-token)
;;{
;; :projectid "firebase-project-id",
;; :uid "uid",
;; :email "[email protected]",
;; :email_verified false,
;; :sign_in_provider "password",
;; :exp 0000000000,
;; :auth_time 0000000000
;;}
(charm/validate-token "firebase-project-id" stale-token)
;; nil
(charm/validate-token "wrong-firebase-project-id" fresh-token)
;; nil
(charm/validate-token "(.*)-project-ids" fresh-token)
;;{
;; :projectid "multiple-project-ids",
;; :uid "uid",
;; :email "[email protected]",
;; :email_verified false,
;; :sign_in_provider "password",
;; :exp 0000000000,
;; :auth_time 0000000000
;;}
Manages user data and authentication using your firebase admin or service account credentials using the email/password sign-in provider. At the moment only one firebase app can be used at a time.
The Admin API is based on the Java Firebase Admin SDK v6.8.0
-
Get the
json
file containing your creditials by following the instruction here https://firebase.google.com/docs/admin/setup -
Enable the email/password sign-in provider.
-
Set the GOOGLE_CLOUD_PROJECT environment to the id of your project
-
Set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the contents of your
json
key file. (Sometimes it may be necessary to wrap the key contents in single quotes to escape all the special characters within it. e.g. GOOGLE_APPLICATION_CREDENTIALS='contents-of-json
') -
initialize the admin sdk in
charmander
(charm-admin/init)
The admin api only allows the creating of users using the email/password sign-in provider.
(charm-admin/create-user "[email protected]" "superstrong6characterpassword")
;;{
;; :email [email protected]
;; :email-verified false
;; :uid vMnMJvS28kWr5pb6sByHULMLelJ3
;; :provider-id firebase
;; :photo-url nil
;; :phone-number nil
;; :display-name nil
;; :disabled false
;;}
(charm-admin/create-user "[email protected]" "superstrong6characterpassword" "my-very-own-custom-uuid")
;;{
;; :email [email protected]
;; :email-verified false
;; :uid my-very-own-custom-uuid
;; :provider-id firebase
;; :photo-url nil
;; :phone-number nil
;; :display-name nil
;; :disabled false
;;}
(charm-admin/get-user "vMnMJvS28kWr5pb6sByHULMLelJ3")
;;{
;; :email [email protected]
;; :email-verified true
;; :uid vMnMJvS28kWr5pb6sByHULMLelJ3
;; :provider-id firebase
;; :photo-url https://avatars0.githubusercontent.com/u/11717556?s=460&v=4
;; :phone-number nil
;; :display-name emailer
;; :disabled false
;;}
(charm-admin/get-user-by-email "[email protected]")
;;{
;; :email [email protected]
;; :email-verified true
;; :uid vMnMJvS28kWr5pb6sByHULMLelJ3
;; :provider-id firebase
;; :photo-url https://avatars0.githubusercontent.com/u/11717556?s=460&v=4
;; :phone-number nil
;; :display-name emailer
;; :disabled false
;;}
(charm-admin/set-user-email "vMnMJvS28kWr5pb6sByHULMLelJ3" "[email protected]")
;;{
;; :email [email protected]
;; :email-verified false
;; :uid vMnMJvS28kWr5pb6sByHULMLelJ3
;; :provider-id firebase
;; :photo-url https://avatars0.githubusercontent.com/u/11717556?s=460&v=4
;; :phone-number nil
;; :display-name emailer
;; :disabled false
;;}
(charm-admin/set-user-password "vMnMJvS28kWr5pb6sByHULMLelJ3" "5tr0ngp455w0rd")
;;{
;; :email [email protected]
;; :email-verified false
;; :uid vMnMJvS28kWr5pb6sByHULMLelJ3
;; :provider-id firebase
;; :photo-url https://avatars0.githubusercontent.com/u/11717556?s=460&v=4
;; :phone-number nil
;; :display-name emailer
;; :disabled false
;;}
(charm-admin/set-user-phone-number "vMnMJvS28kWr5pb6sByHULMLelJ3" "0800123123")
;;{
;; :email [email protected]
;; :email-verified false
;; :uid vMnMJvS28kWr5pb6sByHULMLelJ3
;; :provider-id firebase
;; :photo-url https://avatars0.githubusercontent.com/u/11717556?s=460&v=4
;; :phone-number 0800123123
;; :display-name emailer
;; :disabled false
;;}
(charm-admin/set-user-display-name "vMnMJvS28kWr5pb6sByHULMLelJ3" "Tony Hawk")
;;{
;; :email [email protected]
;; :email-verified false
;; :uid vMnMJvS28kWr5pb6sByHULMLelJ3
;; :provider-id firebase
;; :photo-url https://avatars0.githubusercontent.com/u/11717556?s=460&v=4
;; :phone-number nil
;; :display-name Tony Hawk
;; :disabled false
;;}
(charm-admin/set-user-photo-url "vMnMJvS28kWr5pb6sByHULMLelJ3" "https://en.wikipedia.org/wiki/Tony_Hawk#/media/File:Skater_Tony_Hawk.jpg")
;;{
;; :email [email protected]
;; :email-verified false
;; :uid vMnMJvS28kWr5pb6sByHULMLelJ3
;; :provider-id firebase
;; :photo-url https://en.wikipedia.org/wiki/Tony_Hawk#/media/File:Skater_Tony_Hawk.jpg
;; :phone-number nil
;; :display-name Tony Hawk
;; :disabled false
;;}
(charm-admin/generate-email-verification-link "[email protected]")
;; https://alekcz-dev.firebaseapp.com/__/auth/action?mode=verifyEmail&oobCode=d6uX0gzOuvnZLAwfk8HKxLYrRUCUaBnrzwDgFdzfDhgAAAFprFHVmQ&apiKey=AIz0000yaVaaa512312YL_lffaf311da333211TBp_QPFqvda2e1daw&lang=en
(charm-admin/generate-password-reset-link "[email protected]")
;; https://alekcz-dev.firebaseapp.com/__/auth/action?mode=resetPassword&oobCode=viRcZqjCqxN6eYYmkQGY2fCZjU4RDKuNhysok83ghSEAAAFprFVwJg&apiKey=AIz0000yaVaaa512312YL_lffaf311da333211TBp_QPFqvda2e1daww&lang=en
The API allows for CRUD operation on firestore.
(charm-firestore/create-document "collection" "document" {:field1 "field1" :field2 "field2"})
;;nil
(charm-firestore/add-document-to-collection "path/to/collection" {:field1 "field1" :field2 "field2"})
;; { :id "document",
;; :data {
;; :name "Document",
;; :subcollections ()
;; }
;; }
(charm-firestore/push-document-to-collection "path/to/collection" {:field1 "field1" :field2 "field2"})
;; nil
;; To allow increased through put this writes to firebase but gives not feedback.
(charm-firestore/get-document "path/to/collection" "document")
;; { :id "document",
;; :data {
;; :name "Document",
;; :subcollections
;; ({:id "subcollection1", :path "collection/document/subcollection1"}
;; {:id "subcollection2", :path "collection/document/subcollection2"}
;; {:id "subcollection3", :path "collection/document/subcollection2"})
;; }
;; }
(charm-firestore/get-document-and-subcollections "path/to/collection" "document")
;; { :id "document",
;; :data {
;; :name "Document",
;; :subcollections
;; ({:id "subcollection1",
;; :path "collection/document/subcollection1"
;; :data ({:id "9AMN2yNG3J9GvtTPMxxy", :data {:name "SubdocumentA"}})}
;; {:id "subcollection2",
;; :path "collection/document/subcollection1"
;; :data ({:id "6223N2yNG3J9GvtTPMxxy", :data {:name "SubdocumentB"}})})
;;
;; }
;; }
(charm-firestore/get-collection "path/to/collection")
;; ({:id "collectionA",
;; :path "collection/document/collectionA"
;; :data ({:id "6223N2yNG3J9GvtTPMxxy", :data {:name "SubdocumentP"}}
;; {:id "6223N2yNG3J9GvtTPMxxy", :data {:name "SubdocumentQ"}}))})
(charm-firestore/set-document "path/to/document-to-be-overwritten" {:field1 "field1" :field2 "field2"})
;;nil
(charm-firestore/update-document "path/to/document-to-be-updated" {:field1 "field1" :field2 "field2"})
;;nil
(charm-firestore/delete-document "path/to/document-to-be-delete")
;;nil
- Increase efficiency
- Look into core.async for public key refresh
- Build up API
Copyright © 2019 Alexander Oloo
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.