I have an application that has only the POST method, and every time I make a request in that application, it saves some data for me in my postgres database..
locally my application works properly, but when I deploy and try to test it through the azure function app it returns a 500 error and says that it was not possible to store my information in the database..
here are some code snippets
go code:
func (h handler) sendgridWeb(c *gin.Context) {
data, _ := io.ReadAll(c.Request.Body)
var ListaEventoEmail []Email
if err := json.Unmarshal(data, &ListaEventoEmail); err != nil {
log.Fatal("Error when unrealizing content contained in Body")
}
for _, email := range ListaEventoEmail {
email.SgMessageId = email.SgMessageId[:strings.IndexByte(email.SgMessageId, '.')]
//-- PROCESSED --//
if email.Event == "processed" {
inserting := `insert into email (email_destinatario, enviado, id_sendgrid) values ($1, $2, $3)`
_, err := h.DB.Exec(inserting, email.Email, true, email.SgMessageId)
if err != nil {
log.Fatal("Error inserting data into email table")
}
}
//-- DELIVERED --//
if email.Event == "delivered" {
_, err := h.DB.Exec(`UPDATE email SET recebido=true WHERE id_sendgrid=$1`, email.SgMessageId)
if err != nil {
log.Fatal("Error when uploading email with DELIVERED event")
}
//-- OPEN --//
} else if email.Event == "open" {
_, err := h.DB.Exec(`UPDATE email SET recebido=true, aberto=true WHERE id_sendgrid=$1`, email.SgMessageId)
if err != nil {
log.Fatal("Error when uploading email with OPEN event")
}
} else if email.Event == "click" {
_, err := h.DB.Exec(`UPDATE email SET click = click + 1 WHERE id_sendgrid=$1`, email.SgMessageId)
if err != nil {
log.Fatal("Error when uploading email with CLICK event")
}
}
my connection string is stored in a toml file..
connection string:
# filename: config.toml
[postgres]
host = "132.168.0.22"
port = 5432
user = "postgres"
password = "ivaneteJC"
dbname = "webhook"
you can see that, in the HOST field I put my IP (fictitious ip)..
in my logic, when deploying to azure, my connection string should point to my machine, so I used the ip, thus performing the necessary operations on my database, but this does not happen .. when making a POST request by the postman (using the endpoint that o was provided when deploying to the azure function app, I get a 500 error and in my logs I get the message "Error inserting data into the email table" which is an error described in my go app, I believe I made a mistake somewhere that has a connection to the database, can someone help me?
function.json:
{
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
host.json:
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[3.*, 4.0.0)"
},
"customHandler": {
"description": {
"defaultExecutablePath": "main.exe",
"workingDirectory": "",
"arguments": []
},
"enableForwardingHttpRequest": true
}
}
local.settings.json:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "custom"
}
}
I did as mentioned in a comment, I treated the error in an original way .. and the following error appeared:
"connectex: An attempt was made to access a socket in a way prohibited by its access permissions."
db:
type handler struct {
DB *sql.DB
}
type PostgreConfig struct {
Host string
Port int
User string
Password string
Dbname string
}
type MyConfig struct {
Postgres *PostgreConfig
}
func Init() *sql.DB {
doc, err := os.ReadFile("config.toml")
if err != nil {
panic(err)
}
var cfg MyConfig
err = toml.Unmarshal(doc, &cfg)
if err != nil {
panic(err)
}
stringConn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", cfg.Postgres.Host, cfg.Postgres.Port, cfg.Postgres.User, cfg.Postgres.Password, cfg.Postgres.Dbname)
db, err := sql.Open("postgres", stringConn)
if err != nil {
log.Fatal("Erro ao realizar conexão")
} else {
fmt.Println("Conectado")
}
fmt.Println(stringConn)
db.Ping()
return db
}
func OpenDB(DB *sql.DB) handler {
return handler{DB}
}
The database structure is like so:
suppliers(collection)>user_email(document)
customers(collection)>user_email(document)>foo(field)
And the current firestore.rules is like so:
match /databases/{database}/documents {
//Base rule - fully restrictive
match /{document=**} {
allow read, write: if false;
}
//Checks if user is registered in the suppliers section
function isSupplierTeam(request) {
return exists(/suppliers/$(request.auth.token.email));
}
// Supplier self-data access
match /suppliers/{email} {
allow read, write: if request.auth.token.email == email;
}
match /suppliers/{email}/{document=**} {
allow read, write: if request.auth.token.email == email;
}
// Checking the Customer Sub-Section
match /customers/{email} {
allow read, write: if request.auth.token.email == email || isSupplierTeam(request);
}
match /customers/{email}/{document=**} {
allow read, write: if request.auth.token.email == email || isSupplierTeam(request);
}
}
And the query run in javascript, when logged in as a "supplier" is:
db.collection("customers").get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
console.log(doc.id);
console.log(doc.data());
});
})
.catch((error) => {
console.log("Error getting documents: ", error);
});
It doesn't seem to work and instead triggers a missing/insufficient permission error. How should I tweak my firestore.rules to allow suppliers to access the customer data?
So this works:
//Checks if user is registered in the suppliers section
function isSupplierTeam(request) {
return exists(/databases/$(database)/documents/suppliers/$(request.auth.token.email));
}
It seems like the full "URL" is needed to access the relevant firestore document.
This is the error in the console
Unable to get latest value for query FQuerySpec (path: /Oeuvres/13, params: {
}), client offline with no active listeners and no matching disk cache entries
[Firebase/Database][I-RDB082010] Got data message: {
b = {
d = "Permission denied";
s = "permission_denied";
};
r = 3; }
When I run my code
var ref: DatabaseReference!
ref = Database.database().reference()
ref.child("Oeuvres").child(id).getData(completion: { error, snapshot in
guard error == nil else {
print("\(error!.localizedDescription)")
return;
}
print(snapshot.value)
});
Here's my rules on firebase realtime database
{
"rules": {
".read": true,
".write": "auth !== null"
}
}
Anyone can help me please ?
I have a NSFW system where it checks the document if it is NSFW and if it is it updates the document field isNSFW to true. That works just fine but now I wanted to not show those documents to all users via settings a rule instead of querying it out.
This is what I have but it's not working...
javascript
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth.uid != null;
}
}
match /users/{user} {
allow read: if true;
}
match /docs/{doc} { // THIS HERE
allow read: if resource.data.isNSFW == false;
}
}
I tried adding request. before the resource and it still didn't work.
UPDATE:
javascript
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// match /{document=**} {
// allow read, write: if request.auth.uid != null;
// }
match /users/{user} {
allow read: if currentUser().uid != null;
}
match /docs {
allow read: if existingData().users[currentUser().uid] == false;
}
match /docs/{doc} {
allow write: if currentUser().uid != null;
}
}
// MARK - Funcs ---------------
function existingData() {
return resource.data
}
function incomingData() {
return request.resource.data
}
function currentUser() {
return request.auth
}
function isSignedIn() {
return request.auth != null;
}
}
Getting error:
Listen for Query(docs where users.`40S88coPQObEWSeiYMZIJlIKJkI2` == false order by __name__) failed: Status{code=PERMISSION_DENIED, description=Missing or insufficient permissions., cause=null}
If you are using Firebase Datastore, you can simply query 1
your data:
var myDB = db.collection("YOUR-DB-COLLECTION");
var query = myDB.where("isNSFW", "==", false);
If you are using GCP datastore, you do it this other way 2:
const query = datastore
.createQuery('YOUR-COLLECTION')
.filter('isNSFW', '=', false);
Your matches are not nested correctly. They should be inside the block that starts with match /databases/{database}/documents. Also, you should strongly consider removing the match on /{document=**} because that will let everyone read any document in the database if they're logged in, ignoring all other rules.
Within Firebase, I've implemented a rule to restrict access to a node to the user that's currently logged on. The node looks like this:
{
"app": {
"my_team": {
"a_really_long_uid_string": {
"Lionel_Messi" = true,
"Christiano_Ronaldo" = true
}
}
}
}
and I've created the following rule (based on the online Firebase documentation), which should mean a logged in user can see only their own data (i.e. no other user's data).
{
"rules": {
"my_team": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid"
}
}
}
}
My client environment is in Swift and I've made a simple test routine,
func testAuthentication() {
print("test: \(uid)")
FirebaseRef.child("my_team").observe(.value, with: { (snapshot) in
let snapshot = snapshot.value as! [String: AnyObject]
print("test2: \(snapshot)")
}) { (error) in
print(error.localizedDescription)
}
}
When I run the code, I get the first print in the console ("test: a_really_long_uid_string") but don't get the second print statement.
If I change the rule to restrict access to any logged in users, I get both print statements in the XCode console.
{
"rules": {
"my_team": {
"$uid": {
".read": "auth != null",
".write": "auth != null"
}
}
}
}
Does anyone know what's up or how I can troubleshoot this? I'm wondering if either auth.uid or $uid are nil or something on the server, which could be a reason for access being denied.