So i wanted to check out Firebase and try connecting to Hackernews Firebase database.
I'm using the com.google.firebase:firebase-server-sdk:3.0.3 sdk.
But I am not sure why i am forced to enter a service account.
#Bean
fun firebase(): DatabaseReference {
val options = FirebaseOptions.Builder()
.setDatabaseUrl("https://hacker-news.firebaseio.com/")
.setServiceAccount(this.javaClass.getResourceAsStream("/account.json"))
.build()
val app = FirebaseApp.initializeApp(options)
val instance = FirebaseDatabase.getInstance(app)
return instance.reference
}
Why is setServiceAccount required in this case ? If i leave it out i get following exception:
Caused by: java.lang.IllegalStateException: Service Account must be provided.
at com.google.firebase.internal.Preconditions.checkState(Preconditions.java:173) ~[firebase-server-sdk-3.0.3.jar:na]
at com.google.firebase.FirebaseOptions.<init>(FirebaseOptions.java:129) ~[firebase-server-sdk-3.0.3.jar:na]
Is there a way to connect to Firebase anonymously with a Java client?
This JsFiddle works without a service account:
http://jsfiddle.net/firebase/cm8ne9nh/
If i connect to my own project, this work perfectly nice. I do have a proper service account for my own projects thought...
Thought i might be able to connect with Java the same way.
Any ideas ? Is there a way to connect to Hackernews with the Firebase Java API?
Unfortunately, the Java SDK is only available in two flavors. Java-Client-Android, and Java-Server. Which means, if you want pure client code, you can only really use it on android. This has always been a strange limitation of the available client libraries.
However, what you can do, is wrap the REST API that firebase provides with Java, using HTTP requests to perform everything like you would in any client library.
An example of a repository that has already implemented this is here: https://github.com/j-fischer/rest-on-fire
You could use that one, or you could use your own. But in order to use firebase without a service account, you will have to either use the REST Api or the official Client Libraries which are only writen for Android, iOS, and Web.
Although in the docs here it is not obvious
https://github.com/HackerNews/API
I found this REST API that does not need authentication:
https://hn.algolia.com/api
It can be used in many ways, including with Retrofit & Moshi and no authentication.
Just one example in Kotlin:
interface HackerNewsService {
#GET("search?tags=(story,show_hn,front_page)&hitsPerPage=500")
fun searchStories(#Query("query") q: String, #Query("numericFilters") filters: String, #Query("page") page: Int): Call<SearchResult>
}
val response = hackerNewsService.searchStories(keyword, "created_at_i>$after", 0).execute()
if (response.isSuccessful) {
val searchResult: SearchResult = response.body()!!
println("results! (${searchResult.hits.size}) $searchResult")
} else {
println("uh oh")
}
Related
I am trying to programmatically start Google Cloud virtual machine instances. It occurred to me that in order to have internet access, have to set an external IP address.
// Access Config
AccessConfig accessConfig = AccessConfig.newBuilder()
.setNatIP("foo")
.setType("ONE_TO_ONE_NAT")
.setName("External NAT")
.setExternalIpv6("bar")
.build();
// Use the network interface provided in the networkName argument.
NetworkInterface networkInterface = NetworkInterface.newBuilder()
.setName(networkName)
.setAccessConfigs(0, accessConfig)
.build();
That is my status quo. It is inspired by this article post. I hoped that would work in Java, too, but currently, I am stuck.
All I get is:
com.google.api.gax.rpc.InvalidArgumentException: Bad Request
Unfortunately, Google Cloud Compute Engine Docs doesn't really provide any further information, on how to set the external IP properly.
Thanks in advance.
I have encountered the answer. In the Google Cloud Compute Engine Docs it is explained for Windows Instances. It took me a while to recognize it because I've focused only Linux Instances' related questions.
The solution:
instanceResource = Instance.newBuilder()
.setName(instanceName)
.setMachineType(machineType)
.addDisks(disk)
// Add external internet to instance
.addNetworkInterfaces(NetworkInterface.newBuilder()
.addAccessConfigs(AccessConfig.newBuilder()
.setType("ONE_TO_ONE_NAT")
.setName("External NAT")
.build())
.setName("global/networks/default")
.build())
.setMetadata(buildMetadata())
.build();
I have the following rule in Firestore for read if true I recieve email that point anybody can read and my requests can be drained. I need some approach read action to be allowed only from my app.I don't have authentication in the app is accessible without registration.What can I do to restrict the access only from the app.I read can be set SHA1 key but not quite sure how to implement it.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
allow read: if true;
}
}
}
There is no way to do that but there is a way around just add Anonymously authentication with firebase Auth Ui this way users will not have to create an email and they will be authenticated
another way is: try to make some parts which doesn't require security public for anyone to read .
I‘m afraid there’s actually nothing you can do.
Since you are using a backend as a service provider you will have to use some sort of authentication if you want to prevent certain people to execute certain actions.
This could be classic username/password authentication or a more modern means like oauth.
If you only want your application code to be able to access the database, consider setting up Firebase App Check for your project.
In my current Java project, it's easy to track server-side user events in the "old" Google Analytics Universal Project with simple REST calls to Google Analytics. So that location tracking was working, i could override the server ip with the user ip, according to the parameter "&uip=1.2.3.4" (https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters?hl=de#uip).
As upgrading to GA4 is recommended, I was able to change all the REST parameters in my project and show my events in the new dashboard, except for the user location. I can't find any information about such a parameter. I tried using still "uip" but now all my requests are located to the country of my server.
Unfortunately it's not possible to track the event client side, because my project is a simple REST API, returning only JSON data.
Does anyone have an idea, if there's such a parameter like "uip" for ga4 or if this isn't possible anymore?
In the following way I setup my parameters:
private String getQueryParameters(MeasurementEvent event) {
StringBuilder body = new StringBuilder();
body.append("?v=").append(version);
body.append("&tid=").append(trackingId);
body.append("&cid=").append(event.getClientId());
body.append("&en=").append(eventName);
body.append("&aip=1");
if (StringUtils.hasText(event.getAction())) {
body.append("&ep.useraction=").append(event.getAction());
}
if (StringUtils.hasText(event.getCategory())) {
body.append("&ep.awsregion=").append(event.getCategory());
}
if (StringUtils.hasText(event.getLabel())) {
body.append("&ep.softwarename=").append(event.getLabel());
}
if (StringUtils.hasText(event.getRemoteAddress())) {
body.append("&uip=").append(event.getRemoteAddress());
}
if (StringUtils.hasText(event.getUrl())) {
body.append("&dl=").append(event.getUrl());
}
return body.toString();
}
I have data in Firestore that I update daily with server-side Java code. This has been going on for months without problems. The way I have created a Firestore instance is as follows.
(I have a service account in Firestore and its credentials in a json file.)
GoogleCredentials myCredentials = GoogleCredentials.fromStream(new FileInputStream("/myPath/myCredentials.json"));
FirestoreOptions firestoreOptions = FirestoreOptions.getDefaultInstance()
.toBuilder()
.setProjectId("myFirestoreProject")
.setCredentials(myCredentials)
.build();
Firestore db = firestoreOptions.getService();
Firestore security rules have not been an issue as client-side access to Firestore is not there yet, so I have had all Firestore collections involved unconditionally open for read and write operations. Now, as I only want the server-side access to Firestore, created from the credentials in myCredentials.json, to have permission to write, I set the Firestore security rules as follows.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /myCollection/{document=**}{
allow read;
allow write: if false;
}
}
}
These rules, however, block my access to Firestore as created above, and I also don't know how to set appropriate rules. I understood that it is possible to bypass any Firestore security rules if the Firestore instance is instead created by
FirebaseOptions options = FirebaseOptions.builder()
.setCredentials(myCredentials)
.setDatabaseUrl("https://myFirestoreProject.firebaseio.com")
.build();
FirebaseApp app = FirebaseApp.initializeApp(options, "myFirestoreApp");
Firestore db = FirestoreClient.getFirestore(app);
Now, when I create db like this and run my update code, I get the error message
java.lang.IllegalStateException: Firestore client has already been closed
I won't post the precise update code here, as it on the one hand is very long, and on the other hand runs smoothly with the first type of creation of Firestore instances. However, simpler toy code has worked just fine, so I have checked that the security rules have indeed been bypassed with the second type of creation of Firestore.
I use NetBeans, and in both cases above, the maven imports are these:
<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>libraries-bom</artifactId>
<version>8.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.google.firebase</groupId>
<artifactId>firebase-admin</artifactId>
<version>7.1.1</version>
</dependency>
</dependencies>>
This confusion over the difference between these two Firestore instances leads me to two questions:
If I use my initial creation of Firestore, can I set the security rules so as to grant this Firestore instance permission to write, while blocking any client-side write access - for instance from Android apps?
What is a common cause for the above error message concerning the second creation of Firestore, and is there a way to prevent the Firestore client from closing?
To answer your first question, as mentioned in the Note in the documentation:
"The server client libraries bypass all Cloud Firestore Security Rules and instead authenticate through Google Application Default Credentials. If you are using the server client libraries or the REST or RPC APIs, make sure to set up Identity and Access Management (IAM) for Cloud Firestore."
So the rules will only apply to the client side. You can deny all client side access by denying all access to the database.
As for your second question, check that your code doesn't initialize or close the database more than once and make sure it follows the example in the documentation.
If I create the Firestore instance by
FirestoreOptions firestoreOptions = FirestoreOptions.newBuilder()
.setCredentials(myCredentials)
.setProjectId("myFirestoreProject")
.build();
Firestore db = firestoreOptions.getService();
, the security rules are bypassed, and this instance does not close until all data has been written.
I am currently working on Agora.io services which give us
audio,video,one-to-one and broadcast communication
I have successfully implemented these with the help of there given samples, and successfully add signalling module.
Problem is that signalling call must be active to access all features of it now I want to access all features of signalling at the time when app is closed like whatsapp and other these type of application one solution is make a service of signalling class but this is not professional solution.
I want efficient one solution
This cannot be done with any 3rd party APIs. This is a system level functionality offered by Apple & Google. You will have to use CallKit (for iOS) or ConnectionService (for Android) to achieve this functionality.
I have done exactly the same thing a few days ago.
For iOS, you have use PushKit and CallKit in the following ways:-
.1. Enable background mode and also check voip.
Import Pushkit and implement PKPushRegistryDelegate functions.
Register pushkit like this :-
func registerPushkitToken() -> Void {
pushRegistry = PKPushRegistry.init(queue: DispatchQueue.main)
pushRegistry?.delegate = self
pushRegistry?.desiredPushTypes = [.voIP]
}
3.Implement the token fuction
func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials:
PKPushCredentials, for type: PKPushType) {
let tokenChars = pushCredentials.token.hexString()
}
Implement the following function for parsing notification
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) {
if let userInfo = payload.dictionaryPayload["userInfo"] as? [AnyHashable:Any]{
}
}
Implement provider delegate functions:
let providerConfiguration = CXProviderConfiguration(localizedName: appName)
providerConfiguration.supportsVideo = true
providerConfiguration.maximumCallsPerCallGroup = 1
providerConfiguration.maximumCallGroups = 1
providerConfiguration.supportedHandleTypes = [.generic]
Implement CXProviderDelegate functions
func providerDidReset(_ provider: CXProvider) {
print("Function: \(#function), line: \(#line)")
sessionPool.removeAll()
}
func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
print("Function: \(#function), line: \(#line)")
guard let session = pairedSession(of:action.callUUID) else {
action.fail()
return
}
let callUpdate = CXCallUpdate()
callUpdate.remoteHandle = action.handle
callUpdate.hasVideo = true
callUpdate.localizedCallerName = callDetails.dispalyName;
callUpdate.supportsDTMF = false
provider.reportCall(with: action.callUUID, updated: callUpdate)
delegate?.callCenter(self, startCall: session)
action.fulfill()
}
You can also refer to my post here. how to integrate Callkit with Agora VOiP in swift 4 iOS?