firebase docs

https://firebase.google.com/docs/database/security/rules-conditions#java

https://firebase.google.com/docs/rules/insecure-rules

https://firebase.google.com/docs/database/security/rules-conditions#using_variables_to_capture_path_segments 경로key를 이용 가변적으로 rule을 적용하는 경우


자세한 내용은 wasent 개발일지를 참고할것

.

.

참고자료) 

https://youtu.be/ezMSo4yOquY

.

참고자료)

https://www.youtube.com/watch?v=b7PUm7LmAOw

https://youtu.be/b7PUm7LmAOw?t=2m15s     작업종류 read, wright (get,list,create,update,delete)

https://youtu.be/b7PUm7LmAOw?t=3m52s     user가 auth를 거친 경우 접근가능하게 (request obj를 이용 request.auth)

https://youtu.be/b7PUm7LmAOw?t=4m12s     custom func 만들어 사용

https://youtu.be/b7PUm7LmAOw?t=4m40s     특정 document의 작성자만이 그 document에 접근 가능하게 하는 경우 ( request.auth.uid )

https://youtu.be/b7PUm7LmAOw?t=6m     if && 를 이용 rule을 여러개 적용가능하다. 확인된 email의 경우에 접근 가능하게 하는 경우 ( request.auth.token.email_verified )

https://youtu.be/b7PUm7LmAOw?t=6m21s     resource는 두종류인데 existing resource와 imcoming resource두종류가 있다. ( resource.data 와 request.resource.data )

https://youtu.be/b7PUm7LmAOw?t=7m45s     roll based rules

https://youtu.be/b7PUm7LmAOw?t=8m55s     시간을 이용한 rule 적용

플레이 리스트 : https://www.youtube.com/playlist?list=PLl-K7zZEsYLmnJ_FpMOZgyg6XcIGBu2OX


주요 동영상 : https://youtu.be/LOeioOKUKI8

위) firebase-tools 글로벌로 설치

image
image
image
image

위) firebase.json 수정을 통해 header를 넣을수도 있고 reroute도 할수있다.

image

위) timestamp로 접속하는 경우 firebase functions app으로 reroute하는 경우

image

위) firebase functions https 모든 요청을 express app이 처리하게 만든 경우

image

위) localhost로 확인

image

위) cache를 이용 사용속도를 올리는 방법

image

위) 모든 http 접근을 firebase functions app이 처리하게 하는 경우

image

위) cache를 설정한경우

image

위) firebase cloud functions에 deploy하는 경우

image

위) html template 화일은 functions folder내의 views안에 한다.

image
image

위) template hbs를 사용하는 경우

image

위) statics화일의 경우 public에 넣어놓으면 html에서는 화일명 만으로도 접근 가능하게 된다.

image

.

.

.

.

참고사항)

예제코드 : https://github.com/firebase/functions-samples

original source : https://medium.com/@GaryHarrower/working-with-stripe-webhooks-firebase-cloud-functions-5366c206c6c

firebase functions 와 stripe webhook연결

Now lets head over to our terminal and create a new directory for our project.

$ mkdir stripe-webhooks
$ cd stripe-webhooks

We then need to install the firebase-tools package globally using NPM.

(아래는 firebase-tool설치)

$ npm install -g firebase-tools

Now we have firebase-tools installed, we should login to our firebase account and initiate a new project in our project directory. You will get a choice of which services you would like to use — you only need to select ‘Functions’ here for now.

(아래는 firebase 사용전 초기 작업)

$ firebase login
$ firebase init

Let’s move into the functions folder (created with firebase init) and make sure we have the latest version of firebase-functions and firebase-admin installed. firebase-functions is used for running the actual cloud functions and firebase-admin is used to access the Realtime Database.

$ cd functions/
$ npm install firebase-functions@latest firebase-admin@latest --save

Let’s create a new function called events to handle our endpoint. We’ll start off simple with a basic function that returns a string to let us generate the URL we need to supply our Stripe account with.

const functions = require('firebase-functions');exports.events = functions.https.onRequest((request, response) => {
 response.send("Endpoint for Stripe Webhooks!");
});

We can then deploy our function and get our endpoint (Function URL in output in screenshot).

firebase deploy --only functions

(아래는 stripe에 webhook 만드는 과정)

Now we have our Cloud Function URL, we can head over to the webhooks section of the Stripe dashboard. We then want to + Add Endpoint, and enter our URL into the URL field. You can select the types of events to be sent, but for now we will just stick to all event types.

Once you create the endpoint, take note of your ‘Signing secret’ — we’ll need that to verify the request send to our function.

While we’re in our Stripe Dashboard, let’s head over to the API Keys section to generate and take not of the API key we’re going to use.

You should create a restricted API key and only assign permissions you’re going to need in your firebase project. For example, if you’re only going to read customer objects, you can specify only Customers when creating the key.

Now we have our signing secret and our API key, let’s add them to our Firebase project as environment variables so we don’t need to check them in to any source control.

$ firebase functions:config:set 
   keys.webhooks="your_restricted_key"
   keys.signing="your_signing_key"

That’s our setup complete — We’re now ready to write some code! I’m going to be using examples from Firebase and Stripe, so if there’s anything you would like to dive deeper into, you can use the following links:

To start with, we’re going to need the Stripe NPM package, so let’s go ahead and install that:

(stripe 라이브러리 설치)

$ npm install --save stripe

We added our API keys to our Firebase config, so we can access them using functions.config() (For example: functions.config().keys.webhooks will return our keys.webhooks string we added).

We will then require the Stripe package in our functions index.js. We will also bring in our Signing key to our application (endpointSecret).

const functions = require(‘firebase-functions’);
const stripe = require(‘stripe’)(functions.config().keys.webhooks);
const endpointSecret = functions.config().keys.signing;exports.events = functions.https.onRequest((request, response) => {
 response.send(“Endpoint for Stripe Webhooks!”);
});

Note: Stripe marks a webhook as successful only when your function returns a success (2xx) response. If it receives anything else, such as a 400 or 500, then it marks it as failed, and will try again.

We can use our signing key to verify that a request has actually come from Stripe, and not an unauthorized attacker. The stripe package has a method (stripe.webhooks.constructEvent) which we can use to verify the request. We can also use a Try Catch to return an error if the request fails verification.

// Get the signature from the request header
let sig = request.headers["stripe-signature"];// Verify the request against our endpointSecret
let event = stripe.webhooks.constructEvent(request.rawBody, sig, endpointSecret);

Note: We need to use the original request body otherwise the verification will fail, so we must use Firebase Function’s request.rawBody, instead of the usual request.body.

As mentioned, we can wrap this in a Try Catch to catch any failed requests.

let sig = request.headers["stripe-signature"];try {
 let event = stripe.webhooks.constructEvent(request.rawBody, sig, endpointSecret);
} catch (err) {
 return response.status(400).end();
}

Now we have our valid events, let’s save them to our Firebase Realtime Database.

We can do this by using the firebase-admin database methods. We’re going to be using the .push() method to create a new entry in our database.

const admin = require('firebase-admin');
admin.initializeApp();...return admin.database().ref('/events').push(event)
 .then((snapshot) => {
   return response.json({ received: true, ref: snapshot.ref.toString() });
 })
 .catch((err) => {
   console.error(err);
   return response.status(500).end();
 });

Let’s break this code down a bit.

  • Ref is the path in the database we would like to save our new entry to. This can be whatever you like — i’ve chosen so save my events in the /events ref.
  • Push(event)- event is the variable we’re saving the response from the constructEvent method we called. This is an object with all of our event info
  • Response.json — We respond with a valid json object — this tells Stripe that the webhook event was received and we’re happy we’ve processed it, so mark it as complete.
  • Catch — In case something goes wrong while we’re saving the event to the database, we return an error 500 to tell Stripe that something went wrong. Stripe will then retry sending the event. There are ways you could incorporate this into the Try Catch we have, although I like having the differentiation of errors.

Now we should deploy our function again, then we can test it out.

$ firebase deploy --only functions

Let’s head back over to the Stripe Dashboard Webhooks area, select our endpoint where we can now ‘Send test webhook’.

Select an event type and hit ‘Send test webhook’ — all going well, we get a successful response, and our event is now saved in our database!

That’s it in terms of saving. Now you have endless possibilities of cool things to do with your data. For further reading, you could explore the different triggers Cloud Functions can use. You can run another function whenever anything is added to your database. The example below would run any time a new event is saved to our database. We could now check the event type, and if it’s a successful charge, update our Realtime database to increase our daily revenue on our live dashboard…

You can read more about database events here: https://firebase.google.com/docs/functions/database-events

I hope this was useful. Please leave any feedback or questions – I’m always learning and really appreciate any comments you may have.

You can find the completed code over on Github — https://github.com/GaryH21/Stripe-Webhooks-Tutorial

Happy building!

wasent개발하면서 알게 된점

  • addListenerForSingleValueEvent 를 통해서 snapshot을 얻어올수도 있지만 최초로 addCildEventListener를 node에 연결할때 되돌아 오는 snapshot을 이용할수 있다. 단 addCildEventListener 의 경우 listener가 연결된 지점이하 child 들의 snapshot이 한번에 오는 것이 아니고 순차적으로 하나씩오게 된다. 
  • node의 key, value개념과 child개념을 혼동하면 안된다. 
  • children을 통해 child들을 통으로 가져오려는 경우 children의 parent node에 listener를 연결한다. 때때로 wrapper parent를 만들어야 하는경우도 있다.
  • getValue()사용시 collection형태로 data를 가져오려는 경우 GenericTypeIndicator를 이용한다. 
val type = object : GenericTypeIndicator<HashMap<String,String>>() {}

            val precios : HashMap<String,String>  = dataSnapshot.getValue(type!!)
            liveData.postValue(precios)

ref)kotlin https://stackoverflow.com/a/52684990/3151712

ref)official docs  https://firebase.google.com/docs/reference/android/com/google/firebase/database/GenericTypeIndicator

.

.

.

.

.

google firebase realtime database official docs
https://firebase.google.com/docs/database/android/start

To make your app data update in realtime, you should add a ValueEventListener to the reference you just created. (ChildEventListerner는 현 node아래 child를 관찰하는 것이고 ValueEventListener는 현재node 및 child를 관찰하는 것이다)

The onDataChange() method in this class is triggered once when the listener is attached and again every time the data changes, including the children.

All Firebase Realtime Database data is stored as JSON objects. 그러므로 json으로 표현되기 쉬운 형태로 database구성을 생각한다. 

jacob.body.head.eyes.pupil 이런식으로 저장된다고 생각하고 jacob body head eyes pupil은 key이름이며 이안에 다양한 타입의 data가 들어있다. 또 jacob boddy head eyes pupil 은 각각 node이다. 

t’s best to keep your data structure as flat as possible. 너무 많이 nested되지 않게 하며 각 node의 데이터를 가져온다는 이야기는 하부의 모든 데이터도 같이 가져온다는 이야기가 되기 때문에 염두에 둔다.

https://firebase.google.com/docs/database/android/read-and-write

각 node의 reference에서 setValue()를 통해 값을 쓰고 교환하고 지우기(null을 설정)를 할수 있다.

저장가능한 데이터 형태는 아래와 같다.

Pass types that correspond to the available JSON types as follows:

  • String
  • Long
  • Double
  • Boolean
  • Map<String, Object>
  • List<Object>

Pass a custom Java object, 

  • if the class that defines it has a default constructor that takes no arguments and has public getters for the properties to be assigned.

To read data at a path and listen for changes, use the  addValueEventListener()  or  addListenerForSingleValueEvent()  method to add a ValueEventListener to a DatabaseReference. (addValueEventListener 나 addListenerForSingleValueEvent 둘다 ValueEventListener를 사용하는 것은 같다.  다만addListenerForSingleValueEvent는 한번 데이터 snapshot을 가져오고 listener 스스로 삭제된다)

image

위 그림에서 ValueEventListener also defines the onCancelled() method that is called if the read is canceled. For example, a read can be canceled if the client doesn’t have permission to read from a Firebase database location.

updateChildren()을 이용 해당 node의 여러 child node의 데이터를 하나의 작업으로 수정가능하다. (update만 가능한게 아니라 create도 가능하다.)

image

Simultaneous updates made this way are atomic: either all updates succeed or all updates fail.

setValue() and updateChildren() 작업에는 아래와 같이 listener를 달아서 바로 결과를 확인할수 있다. (setValue()로 create, delete,update작업을 할수 있으므로 모든 작업에 listener를 아래와 같이 달아서 확인 가능) 

image

특정 node에 덧붙여진 listener를 removeEventListener() 를 통해 제거해야 하며 덧붙여진 갯수 만큼 제거 해야 하고 . child node에 있는 것이 자동으로 제거되는 건 아니므로 child node에 따로 접근 제거해야 한다.

https://firebase.google.com/docs/database/android/lists-of-data

collection 형태의 자료를 가지고 있는 node의 경우 node에 ChildEventListener를 붙이면 onChildAdded, onChildChanged, onChildRemoved 을 통해 돌아 오는 snapshot이 각각 하나의 element가 된다. ValueEventListener를 사용하는 경우는 snapshot이 collection전체를 가지고 있게 된다. 이때    for (postSnapshot in dataSnapshot.children) {}    이런 형태로 접근하게 된다.

image

데이터 정렬방법은 위와 같으며 단 한개만 설정할수 있다.

image

위그림은 먼저 정렬된 상태에서 ChildEventListener를 붙이는 모습을 보여준다.

image

위그림은 nested child를 경로 지정으로 정렬기준을 조정하는 방법

image

위 query method는 여러개를 사용할수 있다.

query 성능 개선을 위해서는 index를 이용할수 있다. ( https://firebase.google.com/docs/database/security/indexing-data )

.

.

.

.

original source : https://www.youtube.com/playlist?list=PLk7v1Z2rk4hg3cbALQuTQOTgpZ9e9T8bi

image

.

.

image

.

.

image

addListenerForSingleValueEvent 현재 상태에서 snapshot가져오는 함수

addValueEventListener 하나의 노드 실시간 감시 

addCildEventListener 자식노드까지 실시간 감시

.

.

image

.

.

image
image

.

.

image
image

.

.

image
image

.

.

image
image
image

.

.

firebase realtime database

에는 두가지조건을 동시에 검색하는것이 없다.

image

이런것을 불가능하고

또한 두테이블의 relation 도 만들수 없다.

Convert Firebase Firestore Timestamp to Date (Swift)?

Convert Firebase Firestore Timestamp to Date (Swift)?