how to update a field that is an object in mongo db using node js

So I have a schema right now for a users profile and I want to update the media related to that profile and store it mongodb the way we identify a user is through their username as they are unique on the site I tried the push method but it doesn’t seem to work, the profile is found correctly just trying to update the existing field object we don’t want to override what is stored at that object either just add to what is already there.

here is the schema:

const mongoose = require("mongoose");


const medallionProfileSchema = new mongoose.Schema({
  firstName: {
    type: String,
    required: true,
    unique: false,
  },
  middleName: {
    type: String,
    required: false,
    unique: false,
  },
  lastName: {
    type: String,
    required: true,
    unique: false,
  },
  title: {
    type: String,
    required: false,
    unique: false,
  },
  relationship: {
    type: String,
    required: false,
    unique: false,
  },
  media: {
    title: {
      type: String,
      required: false,
    },
    description: {
      type: String,
      required: false,
    },
    mediaType: {
      type: String,
      required: false,
    },
    mediaLink: {
      type: String,
      required: false,
    },
  },
});

const profileSchema = new mongoose.Schema({
  username: {
    type: String,
    required: true,
    unique: true,
  },
  email: {
    type: String,
    required: true,
    unique: true,
  },
  dateCreated: {
    type: Date,
    required: false,
    unique: false,
  },
  bio: String,
  // Add other profile-related fields as needed
  medallionProfile: medallionProfileSchema, // Embed MedallionProfile schema


});


const Profile = mongoose.model("Profile", profileSchema);

module.exports = Profile;

here is the function to carry out the update the req.body params are present and correct:

const uploadProfileMedia = async (req, res) => {
  try {
    // Extract data from the request body
    const { username, title, description, mediaType, mediaLink } = req.body;

    // Find the profile document associated with the provided username
    const profile = await Profile.findOne({ username });
    console.log("profile in uploading media ", profile);

    // If the profile doesn't exist, return an error
    if (!profile) {
      return res.status(404).json({ error: "Profile not found" });
    }

    // Add the new media to the profile
    profile.medallionProfile.media.push({
      title,
      description,
      mediaType,
      mediaLink,
    });

    // Save the updated profile document
    await profile.save();

    // Respond with a success message
    res.status(200).json({ message: "Media uploaded successfully" });
  } catch (error) {
    // Handle errors
    console.error("Error uploading profile media:", error);
    res.status(500).json({ error: "Internal server error" });
  }
};

Document Upload Inside a Form

I have several tabs in the HTML, and all those tabs are contained within one form. On the save button click, which is outside all tabs, it serializes all the data in all forms fields in the tabs and sends it to the database. All the tabs contain normal textbox and checkboxes.

   <div id="TabBtns" class="col-12 p-0">
   <button type="button" class="btn btn-secondary  mt-3">Tab1 </button>
   <button type="button" class="btn btn-secondary  mt-3">Tab2</button>
   <button type="button" class="btn btn-secondary  mt-3">Tab3</button>
   ...   

In one of the tabs, I need to add functionality so that the user can upload a document and display the success message that the file is uploaded along with the file name. so, I have created this form –

 <div class="card mb-2">
 <a class="collapsed card-link" data-toggle="collapse" id="uploadDocs" href="#Documents">
     <div class="card-header">
         Documents
         <em class="fa pull-right fa-chevron-up"></em>
     </div>
 </a>
 <div id="Documents" class="collapse">
     <div class="card-body">
         <input type="hidden" asp-for="@Model.UploadedBy" />
        
         <input type="hidden" asp-for="@Model.Uri" />
       
         <form id="uploadDocs">
             <div class="col-12">
                 <div class="row">

                     <div class="col-sm-6 col-lg-4">
                         <label asp-for="@Model.documentViewModel.DocumentName">Document Name*</label>
                         <input asp-for="@Model.documentViewModel.DocumentName" type="text" class="form-control" />
                         <span asp-validation-for="@Model.documentViewModel.DocumentName" class="text-danger field-validation-error"></span>
                     </div>
                    


                     <div class="col-sm-6 col-lg-4">
                     </div>
                     <div class="col-sm-6 col-lg-4">
                         <label>Document</label>
                         <div class="custom-file">
                             <input type="file" class="custom-file-input" asp-for="@Model.documentViewModel.FileName">
                             <span asp-validation-for="@Model.documentViewModel.FileName"></span>
                             <label class="custom-file-label" for="FileName" id="lblFileName">Choose file</label>
                         </div>
                     </div>

                 </div>
             </div>


             <div class="mt-2 mb-3">
                 <div class="col-12 text-right">

                     <button type="button" class="btn btn-primary float-right" id="UploadDoc" title="">Upload</button>
                     <button type="button" class="btn btn-outline-primary mr-3" id="ClearDoc">Clear</button>
                 </div>
             </div>



             

             <div class="mt-3">
                 <div class="col">
                     <div class="table-responsive">
                         <table id="tblfileDoc" class="table table-sm table-hover display" width="100%" cellspacing="0">
                             <thead>
                                 <tr>
                                     <th>Id</th>
                                     <th>Document Name</th>
                                     <th>Updated Date</th>
                                     <th class="text-center" width="100">Action</th>
                                 </tr>
                             </thead>

                         </table>
                     </div>
                 </div>
             </div>
         </form>
     </div>
 </div>

I am trying to write the code in JQuery to do Ajax call to the controller that will process file, upload file to cloud as a blob and return filename. But, since I cannot use form within a form to upload a document by user, I use FormData in JQuery. But I am failling to load resource Error 500 when I check the console log while running the app. And the controller action method is not hit through the Ajax call. What am I doing wrong here?

JQuery method –

$('body').on('click', '#UploadDoc', function (e) {
e.preventDefault();
debugger;
//console.log('Upload button clicked');
var btnCaption = $(this).text();
if (btnCaption == "Upload") {

    $('#FileName').rules("add", {
        required: true,
        messages: {
            required: "Please choose document to upload.",

        }
    });
}
else {

    $("#FileName").rules("remove");
}


var fileData = $("#documentViewModel_FileName").prop('files')[0];
var formData = new FormData();
formData.append('file', fileData);
formData.append('documentName', $("#documentViewModel_DocumentName").val());

formData.append('DocumentType', $("#documentViewModel_DocumentType").val());
formData.append('UploadedBy', $("#documentViewModel_DocumentType").val());
debugger;
console.log(formData);

for (var key of formData.entries()) {
    console.log(key[0] + ', ' + key[1]);
}




$.ajax({
    url: "/Controller/SaveDoc",
    type: "POST",
    processData: false,
    beforeSend: function () {
        $(".page-loader").css("display", "block");
    },
    data: formData,
    success: function () {
        console.log('success data file');
    },
    error: function (jqXHR, textStatus, errorThrown) {
        if (jqXHR.status == 400) {
            LogoutForSessionExpiration();
        } else {
            $(".page-loader").css("display", "none");
            toastr.error("Error Occurred");
        }
    }
});
});

controller method –

 [HttpPost]
 public JsonResult SaveDoc(DocumentViewModel DocumentViewModel)
 {
     JsonResponse jsonResponse;
     bool result;
     try
 {
     DocumentViewModel model = new DocumentViewModel();

     if (DocumentViewModel.DocumentId == Guid.Empty)
     {
         var file = Request.Form.Files[0];
         var fileExtension = Path.GetExtension(file.FileName);
         DocumentViewModel.FileName = Path.GetFileNameWithoutExtension(file.FileName) + "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + fileExtension;
         DocumentViewModel.DocumentByte = ConvertToBytes(file);

         var blob = _userService.UploadDocs(DocumentViewModel).Result;

         if (blob.Uri != null)
         {
             DocumentViewModel.Uri = blob.Uri.ToString();
             result = _userService.AddDocs(DocumentViewModel);
             if (result)
             {
                 jsonResponse = new JsonResponse();
                 jsonResponse.Status = ResponseStatus.OK.ToString();
                 jsonResponse.Message = "Document uploaded successfully.";
                 return Json(jsonResponse);
             }
             else
             {
                 jsonResponse = new JsonResponse();
                 jsonResponse.Status = ResponseStatus.ERROR.ToString();
                 jsonResponse.Message = "Error in uploading document.";
                 return Json(jsonResponse);
             }
         }
         else
         {
             jsonResponse = new JsonResponse();
             jsonResponse.Status = ResponseStatus.ERROR.ToString();
             jsonResponse.Message = "Error in uploading document.";
             return Json(jsonResponse);
         }
     }
     else
     {
         if (Request.Form.Files.Count > 0)
         {
             var file = Request.Form.Files[0];
             _userService.RemoveDocs(DocumentViewModel);
             var fileExtension = Path.GetExtension(file.FileName);
             DocumentViewModel.FileName = Path.GetFileNameWithoutExtension(file.FileName) + "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + fileExtension;
             DocumentViewModel.DocumentByte = ConvertToBytes(file);
             var blob = _userService.UploadDocs(DocumentViewModel).Result;
             if (blob.Uri != null)
             {
                 DocumentViewModel.Uri = blob.Uri.ToString();
                 result = _userService.UpdateDocs(DocumentViewModel, true);
                 if (result)
                 {
                     jsonResponse = new JsonResponse();
                     jsonResponse.Status = ResponseStatus.OK.ToString();
                     jsonResponse.Message = "Document uploaded successfully";
                     return Json(jsonResponse);
                 }
                 else
                 {
                     jsonResponse = new JsonResponse();
                     jsonResponse.Status = ResponseStatus.ERROR.ToString();
                     jsonResponse.Message = "Error in uploading document.";
                     return Json(jsonResponse);
                 }
             }
             else
             {
                 jsonResponse = new JsonResponse();
                 jsonResponse.Status = ResponseStatus.ERROR.ToString();
                 jsonResponse.Message = "Error in uploading document.";
                 return Json(jsonResponse);
             }
         }
         else
         {
             //with no doc attched
             result = _userService.UpdateDocs(documentViewModel, false);
             if (result)
             {
                 jsonResponse = new JsonResponse();
                 jsonResponse.Status = ResponseStatus.OK.ToString();
                 jsonResponse.Message = "Signed doc. info updated successfully";
                 return Json(jsonResponse);
             }
             else
             {
                 jsonResponse = new JsonResponse();
                 jsonResponse.Status = ResponseStatus.ERROR.ToString();
                 jsonResponse.Message = "Error in updating signed doc. info.";
                 return Json(jsonResponse);
             }
         }
     }
 }
 catch (Exception ex)
 {
     _logger.LogError(ex.Message);
     jsonResponse = new JsonResponse();
     jsonResponse.Status = ResponseStatus.ERROR.ToString();
     jsonResponse.Message = "Error in uploading document";
     return Json(jsonResponse);
 }

}

viewmodel for document tab is nested inside the viewmodel of parent page.

ViewModel class –

using Microsoft.AspNetCore.Mvc.Rendering;
using System;
using System.Collections.Generic;
using System.Text;

namespace App
{
    public class DocumentViewModel
    {
    public Guid DocumentId { get; set; }
   
   
    public string DocumentName { get; set; }
    public string DocumentType { get; set; }
    
    public string UploadedBy { get; set; }
    public string FileName { get; set; }
    public string Uri { get; set; }
    public byte[] DocumentByte { get; set; }
      
}

}

hi could anyone help me with some JavaScript explanations and answers ? it’s regarding function parameters

In order to purchase an item online we need to check that the user’s password is correct and that they have enough money to afford it. Use what you’ve learned about logic and comparison operators to complete the code.

Assign an expression to isPasswordCorrect that checks that secret is the correct password, ‘hunter2’.
Assign an expression to isAffordable that checks their funds are at least 10.99.
Assign an expression to isPurchasable that checks that both isPasswordCorrect and isAffordable are true.

function canWeBuyIt(secret, funds) {
const isPasswordCorrect = secret
const isAffordable funds => 10.99
const isPurchasable = secret && funds

return { isPasswordCorrect, isAffordable, isPurchasable };

}

simple javascript frontend for node.js backend

I am preparing a curriculum for a JavaScript course for a local in-person class hosted by a local non-profit. I have been given an outline of the course that is apparently approved by the Dept of Education. The outline simply has the topics and subtopics listed, but no actual substance. It is my job to create presentations and projects off this outline.

The outline includes coverage of Node.js. It does not include any JavaScript frameworks such as Vue, React or Angular. I don’t know view but am somewhat familiar with React and Angular, though I don’t know if I know enough to teach it. Moreover, I don’t think I would have course time available to teach those, given what else needs to be covered.

Moreover, I learned Node.js back in 2019 in college but have not used it since. I definitely need to brush up on it, which I don’t think will be too difficult.

But here’s the problem. I need to create a Node project for the students to do. I’m sure I could come up with a fairly simple idea that I could flesh out on the backend. But I don’t know what to do about a frontend, since we wouldn’t be using React, Vue or Angular. In college we used Angular as a frontend.

Can a frontend for a Node.js app be created from just HTML, CSS and vanilla JavaScript? What would that look like? Or do I need some sort of framework for a frontend? And if so, what would be some simple frontend JavaScript frameworks that I could maybe figure out quickly and then teach to students relatively quickly? (Side question: can Vue be picked up easily and quickly so I could wedge it in without taking too much time from the official course outline?)

If this question belongs on another board, please tell me the board and I will move it.

Thanks!

Next-Auth authentication to Django Rest Framework with JWT and App Router

I have a Django project, for which I’ve decided to add Next.JS frontend. I set-up DRF authentication with JWT:

$ curl -XPOST -H "Content-type: application/json" -d '{
      "username": "user1",
      "password": "strongpassword"
  }' 'http://0.0.0.0:8000/api/auth/login/'
{"access":"eyJhbG...","refresh":"eyJhbG...","user":{"pk":1,"username":"user1","email":"","first_name":"John","last_name":"Doe"}}

I’ve configured Next-Auth in my frontend:

// frontend/auth.ts

import type {
  GetServerSidePropsContext,
  NextApiRequest,
  NextApiResponse,
} from "next";
import type { NextAuthOptions } from "next-auth";
import { getServerSession } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import axios from "axios";

const BACKEND_ACCESS_TOKEN_LIFETIME = 45 * 60; // 45 minutes
const BACKEND_REFRESH_TOKEN_LIFETIME = 6 * 24 * 60 * 60; // 6 days

const getCurrentEpochTime = () => {
  return Math.floor(new Date().getTime() / 1000);
};

export const authOptions = {
  pages: {
    signIn: "/login",
  },
  secret: process.env.AUTH_SECRET,
  session: {
    strategy: "jwt",
    maxAge: BACKEND_REFRESH_TOKEN_LIFETIME,
  },
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {},
      async authorize(credentials, req) {
        try {
          const response = await axios({
            url: process.env.NEXTAUTH_BACKEND_URL + "auth/login/",
            method: "post",
            data: credentials,
          });
          const data = response.data;
          if (data) return data;
        } catch (error) {
          console.error(error);
        }
        return null;
      },
    }),
  ],
  callbacks: {
    async jwt({ user, token, account }) {
      // If `user` and `account` are set that means it is a login event
      if (user && account) {
        let backendResponse: any =
          account.provider === "credentials" ? user : account.meta;
        token["user"] = backendResponse.user;
        token["access_token"] = backendResponse.access;
        token["refresh_token"] = backendResponse.refresh;
        token["ref"] = getCurrentEpochTime() + BACKEND_ACCESS_TOKEN_LIFETIME;
        return token;
      }
      // Refresh the backend token if necessary
      if (getCurrentEpochTime() > token["ref"]) {
        const response = await axios({
          method: "post",
          url: process.env.NEXTAUTH_BACKEND_URL + "auth/token/refresh/",
          data: {
            refresh: token["refresh_token"],
          },
        });
        token["access_token"] = response.data.access;
        token["refresh_token"] = response.data.refresh;
        token["ref"] = getCurrentEpochTime() + BACKEND_ACCESS_TOKEN_LIFETIME;
      }
      return token;
    },

    async session({ token }) {
      return token;
    },
  },
} satisfies NextAuthOptions;

export function auth(
  ...args:
    | [GetServerSidePropsContext["req"], GetServerSidePropsContext["res"]]
    | [NextApiRequest, NextApiResponse]
    | []
) {
  return getServerSession(...args, authOptions);
}

Added routes:

//  frontend/app/api/auth/[...nextauth]/route.ts

import NextAuth from "next-auth";
import { authOptions } from "@/auth";
const handler = NextAuth(authOptions);

export { handler as GET, handler as POST };

And middleware:

// frontend/middleware.ts

import { withAuth } from "next-auth/middleware";

export default withAuth(
  function middleware(req) {
    console.log(req.nextauth.token);
  },
  {
    callbacks: {
      authorized: ({ token }) => !!token,
    },
  }
);

export const config = { matcher: ["/dashboard/:path*"] };

Created a login form:

// frontend/app/ui/login-form.tsx

"use client";

import { useFormState, useFormStatus } from "react-dom";
import { authenticate } from "../lib/actions";

export default function LoginForm() {
  const [errorMessage, dispatch] = useFormState(authenticate, undefined);

  return (
    <form action={dispatch}>
      <input              
        id="username"
        type="text"
        name="username"
        placeholder="Username"
        required
      />
      <input               
          id="password"
          type="password"
          name="password"
          placeholder="Enter password"
          required
          minLength={6}
        /> 
      <LoginButton />  
    </form>
  );
}

function LoginButton() {
  const { pending } = useFormStatus();

  return (
    <Button aria-disabled={pending}>
      Log in
    </Button>
  );
}

And defined authenticate function to access /api/auth/signin endpoint:

// frontend/app/lib/actions.ts

export async function authenticate(
  prevState: string | undefined,
  formData: FormData
) {
  try {
    const res = await fetch(`/api/auth/signin`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        username: formData.get("username"),
        password: formData.get("password"),
      }),
    });
  } catch (error) {
    if (error) {
      return "Something went wrong.";
    }
    throw error;
  }
}

But when I click login button, nothing happens. Am I using the app router the wrong way?

Firebase Cloud Messaging not showing notification in browser

So I have succesfully created a service-worker and recieve a auth token when user enabled notifications permissions, and I confirmed it my Chrome browser.

I recieve the message from POSTman but I get no visible message in my browser, only in console (F12) why?

[firebase-messaging-sw.js] Received background message

firebase-messaging-sw.js:

importScripts('https://www.gstatic.com/firebasejs/10.7.1/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/10.7.1/firebase-messaging-compat.js');

const firebaseConfig = {
    "placeholder"
};

firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();

messaging.onBackgroundMessage((payload) => {
    console.log('[firebase-messaging-sw.js] Received background message ', payload);
    // Customize notification here
    const notificationTitle = payload.data.title;
    const notificationOptions = {
        body: payload.data.body,
        icon: '/firebase-logo.png'
    };

    self.registration.showNotification(notificationTitle,
        notificationOptions);
});

notifications.js:

import { initializeApp } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-app.js";
import { getMessaging, getToken } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-messaging.js";

const firebaseConfig = {
"placeholder"
};

const app = initializeApp(firebaseConfig);
const messaging = getMessaging(app);

var notify = document.getElementById('dropdownMenuButton');
var timeAgoTextElement = document.getElementById('timeAgoText');

async function requestPermissionAndToken() {
  if ('serviceWorker' in navigator) {
    try {
      const registration = await navigator.serviceWorker.register('/firebase-messaging-sw.js');
      console.log('Service Worker registered:', registration);
    } catch (error) {
      console.error('Service Worker registration failed:', error);
    }
  }
  try {
    // Request permission for notifications
    await Notification.requestPermission();
    console.log('Notification permission granted.');

    // Retrieve the device token
    const token = await getToken(messaging);
    getToken(messaging, { vapidKey: ""})
    .then((currentToken) => {
      if (currentToken) {
        console.log('current token for client: ', currentToken);
      } else {
        console.log('No registration token available. Request permission to generate one.');
      }
    });
  } catch (error) {
    console.error('Error requesting permission or obtaining token:', error);
  }
}

// Function to mark the notification as clicked and save the current time in cookies
function markNotificationClicked() {
    sessionStorage.setItem('notificationClicked', 'true');
    sessionStorage.setItem('notificationTime', new Date().toString());
}

// Function to check if the notification has been clicked in the current session using cookies
function isNotificationClicked() {
    return sessionStorage.getItem('notificationClicked') === 'true';
}

// Function to update the notification count
function updateNotificationCount() {
    var addNumbClass = !isNotificationClicked();
    notify.classList.toggle('add-numb', addNumbClass);
}

// Function to format time difference as "just nu," "1 dag sedan," etc.
function formatTimeDifference(timeDiff) {
    if (timeDiff < 1) {
        return "just nu";
    } else if (timeDiff === 1) {
        return "1 dag sedan";
    } else {
        return timeDiff + " dagar sedan";
    }
}

// Function to update the time display
function updateTimeAgo() {
    var notificationTime = new Date(sessionStorage.getItem('notificationTime')) || new Date();
    var now = new Date();
    var timeDiff = Math.floor((now - notificationTime) / (1000 * 60 * 60 * 24));

    timeAgoTextElement.textContent = formatTimeDifference(timeDiff);
}

// Add an event listener to the dropdown button
notify.addEventListener('click', function() {
    notify.setAttribute('data-count', '0');
    markNotificationClicked();
    updateNotificationCount();
    updateTimeAgo(); // Call the function immediately after clicking

    // Update the time every hour
    setInterval(updateTimeAgo, 1000 * 60 * 60);
});

// Initialize Bootstrap Dropdown
var dropdownElement = document.querySelector('#dropdownMenuButton');
var dropdown = new bootstrap.Dropdown(dropdownElement, {
    popperConfig: function(popperConfig) {
        popperConfig.modifiers = [
            { name: 'flip', enabled: false, options: { padding: 10 } },
            { name: 'offset', options: { offset: [0, 10] } },
            { name: 'computeStyles', options: { adaptive: false } },
            { name: 'preventOverflow', options: { padding: 10 } }
        ];
        return popperConfig;
    }
});

// Update the time immediately
updateTimeAgo();
// Update the notification count initially
updateNotificationCount();

document.addEventListener('DOMContentLoaded', function () {
  // Get the checkbox element
  const mailCheckbox = document.getElementById('dmNotification');

  // Check if the checkbox element exists
  if (mailCheckbox) {
    // Add a change event listener to the checkbox
    mailCheckbox.addEventListener('change', function () {
      handleCheckboxChange(mailCheckbox);
    });
  } else {
    console.warn('Checkbox element not found on this page.');
  }
});

function handleCheckboxChange(checkbox) {
  // Check if notifications are supported by the browser
  if ('Notification' in window) {
    // Check if the user has granted permission for notifications
    if (Notification.permission === 'granted') {
      // If the checkbox is checked, show a notification
      if (checkbox.checked) {
        showNotification('Notification Title', 'Du kommer nu att få aviseringar för privata meddelanden.');
        requestPermissionAndToken();
      } else {
        // If the checkbox is unchecked, show a different notification
        showNotification('Notification Title', 'Du har inaktiverat aviseringar för privata meddelanden.');
      }
    } else {
      // If permission is not granted, request permission
      Notification.requestPermission().then(function (permission) {
        // If permission is granted, show a notification
        if (permission === 'granted' && checkbox.checked) {
          showNotification('Notification Title', 'Du kommer nu att få aviseringar för privata meddelanden.');
        }
      });
    }
  } else {
    // Browser does not support notifications
    console.error('Notifications not supported in this browser.');
  }
}

function showNotification(title, message) {
  // Implement your notification logic here
  console.log('Notification:', title, message);
}

Calling Firebase Function from Angular gives “bad request” error, but works fine called from URL

I am very new to Firebase Functions. I created a Function called getQuizById(). The function returns the Quiz in JSON format. If I call the function directly via a URL, it returns the JSON data as expected. e.g.:

https://us-central1-example-f1afa.cloudfunctions.net/getQuizById?id=ef8GwUuHt8X4XQJBIgZf

Since that is working, I need to call that same function from my Angular 17 app, here is the code I am using for that:

import { Functions, httpsCallable } from '@angular/fire/functions';

  private functions: Functions = inject(Functions);

  constructor(private route: ActivatedRoute) {
    // get the id fdrom the url
    const id = this.route.snapshot.params['id'];

    const getQuizById = httpsCallable(this.functions, 'getQuizById');

    getQuizById({ id: 'ef8GwUuHt8X4XQJBIgZf' }) // <- HARD CODED ID JUST FOR TESTING
      .then((result) => { // <- ERROR HERE
        console.log(result);
      });
  }

I took this code example straight from the docs on the Firebase website, so I assume I’m doing it correctly. Still, the Function itself is not receiving the passed in ID parameter, so it is failing with code 400 (“Quiz ID is required”).

Here is the code from the Function itself, in case it helps.

// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
const { logger } = require("firebase-functions");
const { onRequest } = require("firebase-functions/v2/https");
const { cors } = require("cors")({ origin: true });

// The Firebase Admin SDK to access Firestore.
const { initializeApp, applicationDefault, cert } = require("firebase-admin/app");
const { getFirestore, Timestamp, FieldValue, Filter } = require("firebase-admin/firestore");

initializeApp();

const db = getFirestore();

exports.getQuizById = onRequest({ cors: true }, async (request, response) => {
    const quizId = request.query.id;

    if (!quizId) {
        response.status(400).send("Quiz ID is required");
        return;
    }

    try {
        const quizDocref = db.collection("quizzes").doc(quizId);
        const quizDoc = await quizDocref.get();

        if (!quizDoc.exists) {
            response.status(404).send("Quiz not found. ID: " + quizId);
            return;
        }

        response.status(200).json(quizDoc.data());
    } catch (error) {
        console.error("Error getting quiz document:", error);
        response.status(500).send("Internal Server Error");
    }
});

The Node.js interface passed the Set-Cookie parameter, but since the browser made an HTTP request, document.cookie cannot retrieve the data

Background:

My server is using Node.js, Express, and includes tools such as CORS, express-session, and connect-mongo. It utilizes HTTP requests. However, the browser is unable to retrieve cookies from the Set-Cookie response in the interface.

I am currently learning to use Node.js, and I want to implement cookie + session login session control. However, I have been troubled by the browser cookie issue for a long time. Thank you very much for your answer.

Additionally: My English is not good.

相关背景:

我的服务器使用了nodejs, express, 并且使用了工具: cors, express-session, connect-mongo, 使用http请求, 但是我在接口响应的Set-Cookie, 浏览器无法获取

我正在学习使用nodejs, 我想实现一个cookie + session的登录会话控制, 但是我被浏览器cookie这个问题困扰很久, 感谢您解答


Image One: My Node.js interface has already returned the cookie.

图片1: 我的接口返回了cookie了
enter image description here

Image Two: My browser cannot obtain the cookie, and document.cookie also cannot retrieve it.


图片2: 但是我浏览器无法获取cookie

enter image description here

=============================================

The solution I tried:

  1. Cookie settings: httpOnly: false, sameSite: ‘None’.
    enter image description here

  2. I attempted to obtain an HTTPS certificate using SSL, but I am using a local server with 127.0.0.1. I tried to apply for HTTPS, but without success.
    (我本地服务器, 尝试获取https证书不成功)

  3. I set withCredentials: true, but encountered an error. I attempted to use the request header Access-Control-Allow-Origin: http://127.0.0.1, but it still didn’t work.
    (设置withCredentials: true, 但是报错, 我尝试使用请求头Access-Control-Allow-Origin: http://127.0.0.1, 但还是不行)
    enter image description here

=============================================

The above are some of the solutions I tried, but I still can’t retrieve cookies in the browser.

Additionally, my browser is running at 127.0.0.1:80, while the Node server is at 127.0.0.1:3000.

(以上是我采取的部分解决办法, 但我还是无法在浏览器中获取cookie,
再补充一点, 我的浏览器是127.0.0.1:80, node服务器是127.0.0.1:3000, )

Thank you once again.

Issue with variable storing in js function [closed]

I’m trying to use a button to get seven random objects and put them as elements in HTML. I want it to be able to be used multiple times in succession. The function always works the first time, but when I try to use it a second time the variables still have the same value as they did in the end of the function. Excuse any bad coding practices I’m self-taught and just recently started. This project is an attempt at something slightly higher level.

//Test Meals
addMeal('test1','this is a test','testing');
addMeal('test2','this is a test','testing');
addMeal('test3','this is a test','testing');
addMeal('test4','this is a test','testing');
addMeal('test5','this is a test','testing');
addMeal('test6','this is a test','testing');
addMeal('test7','this is a test','testing');

Meals is an array of these test objects.

//Function to pick a meal for each day of the week
function getWeek () {
    let tempMeals = meals;
    let total = meals.length;
    let tempPicked;
    let picked = [];
    for (let i=0; i < 7; i++) {
        tempPicked = tempMeals[Math.floor(Math.random() * total)];
        picked.push(tempPicked);
        index = tempMeals.indexOf(tempPicked);
        tempMeals.splice(index,1);
        total -= 1;
    }
    return picked;
}

//Function to get meals on button click
function pushMeals () {
    let picked = getWeek();
    for (i=0;i<1;i++) {
        for (let j=0;j<3;j++){
            if (j === 0) {
                days[i][j].innerHTML = picked[i].name;
            }
            else if (j === 1) {
                days[i][j].innerHTML = picked[i].ingredients;
            }
            else if (j === 2) {
                days[i][j].innerHTML = picked[i].directions;
            }
            else {
                days[i][j].innerHTML = 'There is an error. Try again.'
            }
        }
    }
}
getMeals.addEventListener('click',pushMeals);

How to make a long column out of a html table

I am trying to make my timetable made in html look alright on mobile devices.
Thas how the table looks:
desktop view

I want to splice it into columns and make a long table from those columns, without displaying the hour column. I have succeded only to do it row wise, but not collumn wise.
Here how it should look, except its missing name of the day before displaying classes for that day.
mobile view

I used this js script:

function transformTable() {
var originalTable = document.getElementById("desktopTable");
var transformedTable = document.getElementById("mobileTable");

for (var i = 1; i < originalTable.rows.length; i++) {
    var row = originalTable.rows[i];
    for (var j = 0; j < row.cells.length; j++) {
        var cell = row.cells[j];
        var newRow = transformedTable.insertRow();
        var newCell = newRow.insertCell();

        // Clone attributes from original cell to the new cell
        for (var k = 0; k < cell.attributes.length; k++) {
            var attr = cell.attributes[k];
            newCell.setAttribute(attr.name, attr.value);
        }

        // Clone nested elements
        var cellContents = cell.cloneNode(true);
        // Remove the cloned <td> element and append its children
        while (cellContents.firstChild) {
            newCell.appendChild(cellContents.removeChild(cellContents.firstChild));
        }
    }
}

}

Why does my onchange function for disabling form fields not work properly?

I have the two form select menu “transactionSelection” and “categorySelection”. My goal is to disable “categorySelection” if the value of “transactionSelection” is “income”. Therefore I have the function “disableSelection()”. The menu “categorySelected” should by default be disabled.

<label for="transactionSelection" class="form-label mb-0">Transaktionsart</label>
<select class="form-select" id="transactionSelection" onchange="disableSelection()" aria-label="Transaction selection">
    <option value="income">Einnahme</option>
    <option value="spendings">Ausgabe</option>
<label for="categorySelection" class="form-label mb-0">Kategorie</label>
<select class="form-select" id="categorySelection" aria-label="Category selection" disabled>
    <option value="income">Einnahmen</option>
    <option value="mobility">Mobilität</option>
    <option value="home-entertainment">Heimunterhaltung</option>
    <option value="going-out">Ausgehen</option>
    <option value="sport-activities">Sportaktivitäten</option>
    <option value="real-estate">Wohnen</option>
    <option value="insurance">Versicherungen</option> 
    <option value="cost-of-living">Lebenshaltungskosten</option>
    <option value="investing">Investments</option>
    <option value="telecommunication">Telekommunikation</option>
    <option value="media-subscription">Medienabos</option>
    <option value="philanthropy">Philantropie</option>
    <option value="financial-cost">Finanzkosten</option>
    <option value="vacation">Urlaub</option>
    <option value="education">Bildung</option>
    <option value="emigration">Auswanderung</option>
    <option value="other">Sonstiges</option>
</select>
<script>
    function disableSelection() {
        if (this.value == 'income') {
            document.getElementById('categorySelection').disabled = true;
        }
        else {
            document.getElementById('categorySelection').disabled = false;
        }
    }
</script>

However, this is only working once. After selecting the other value of “transactionSelection”, the disabled attribute of “categorySelection” disappears and will not set again. When I remove the disabled attribute, it will never set at all, so it seems that the function does not get called. Other js (like several chart.js charts) are working fine.

What am I doing wrong here?

Rotating GLB in threejs

I am attempting to make my 3d object rotate around the Y axis by itself and without disabling the user ability to scale and custom rotate the object with his mouse.

What I did is something like this:

import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

var canvasOfDesk = document.getElementById("desk")

const scene = new THREE.Scene();
scene.position.y = -13
scene.add(new THREE.AxesHelper(0))

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.01, 1000);
const initialCameraPosition = new THREE.Vector3(
    -23, 17, 36)
camera.position.x = initialCameraPosition.x
camera.position.y = initialCameraPosition.y
camera.position.z = initialCameraPosition.z

const renderer = new THREE.WebGLRenderer({ canvas: canvasOfDesk, alpha: true });
renderer.shadowMap.enabled = true
renderer.setPixelRatio(10 * window.devicePixelRatio)

const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true

const loader = new GLTFLoader();

const lightCandle = new THREE.SpotLight(0xffffff, 2000)
lightCandle.position.set(8, 40, -15)
scene.add(lightCandle)

const lightLaptop = new THREE.SpotLight(0xffffff, 2000)
lightLaptop.position.set(-10, 40, -15)
scene.add(lightLaptop)

loader.load(
    '/desk.glb',
    function(gltf) {
        var obj = gltf.scene
        scene.add(obj)
        obj.castShadow = true
        obj.receiveShadow = true
        obj.traverse(function(child) {
            if (child.isMesh) {
                child.castShadow = true
                child.receiveShadow = true
            }
        })
    },
    (xhr) => {
        console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
    },
    (error) => {
        console.log(error)
    }
)

window.addEventListener('resize', onWindowResize, false)
function onWindowResize() {
    camera.updateProjectionMatrix()
    render()
}

const target = new THREE.Vector3(-0.5, 1.2, 0)
const rotSpeed = 100
function animate() {

    requestAnimationFrame(animate)

    const p = camera.position
    camera.position.y = p.y
    camera.position.x =
        p.x * Math.cos(rotSpeed) + p.z * Math.sin(rotSpeed)
    camera.position.z =
        p.z * Math.cos(rotSpeed) - p.x * Math.sin(rotSpeed)
    camera.lookAt(target)

    render()

}

function render() {
    renderer.render(scene, camera)
}

animate()

The object is rotating like I want but for only 20 seconds. After that I notice the object is zooming (scaling up) by itself…

I suspect it is due to error of calculation in my animate function but I don’t know how to fix it.

Is there maybe a way to achieve the same effect without using the rotation formula ? (with tailwind css or just css maybe ?)

Simulate a hover over a span and extract text that appears on hover Selenium

There is a span with alt-text that will be displayed on hover. I’m trying to simulate a hover over this and trying to retreive the text that appeares on hover. This is the element.

<span aria-label-{"batman"} className="tooltip">
<img src-(Nocheck) alt-"Non-check issuing branch" data-testid="non-check-issuing-branch">
 </span>

I have tried the following script.

String script = "var event = new MouseEvent('mouseover', {" +
                        "    'view': window," +
                        "    'bubbles': true," +
                        "    'cancelable': true" +
                        "});" +
                        "arguments[0].dispatchEvent(event);";

        ((JavascriptExecutor) driver).executeScript(script, elementToHoverOver);

I have also tried using Actions to directly perform the hover action. None of them seem to work. This is the xpath of the element.

//span[@aria-label='batman']

Am I not accessing the right xpath for the hover? Any help is appreciated.

Google Recaptcha on explicit render for mulitple forms it returns “Invalid key type” error

I’m having some issues on implementing Google recaptcha validation on a single page having multiple forms.
Reading many posts on the argument has led me to this design, that includes the possibility of using html5 validations before submitting the recaptcha validAtion:

HTML side

<head>
....
<script src="https://www.google.com/recaptcha/enterprise.js?onload=CaptchaCallback&render=explicit" async defer></script>
</head>
<body>
...
<form id="contactFrm1">
...
<div id="RecaptchaField1" class="g-recaptcha" data-callback="formSubmit1"></div>
...
</form>
...
...
<form id="contactFrm2">
...
<div id="RecaptchaField2" class="g-recaptcha" data-callback="formSubmit2"></div>
...
</form>
..
</body>

Javascript Side

<script>
var CaptchaCallback = function() {
    jQuery('.g-recaptcha').each(function(index, el) {
            var widgetId = grecaptcha.enterprise.render(el, {'sitekey' : SITE_KEY});
        jQuery(this).attr('data-widget-id', widgetId);
    });
};
    
$(document).ready(function() {      
    $("#submit").click(function(){
    $('#contactFrm1').submit(function(event) {
    if (!grecaptcha.enterprise.getResponse(jQuery('#RecaptchaField1').attr('data-widget-id'))){
        event.preventDefault(); //prevent form submit
        grecaptcha.enterprise.execute(jQuery('#RecaptchaField1').attr('data-widget-id'));
                }
    });
    formSubmit = function() {
    $('#contactFrm1').submit();
            }
    }); 
});

//same logic for the second form
</script>

On rendering the page shows, for both of captcha widgets, “Note for site owner: Invalid key type”.

I’m sure about the validity of the key, due to the fact that using the “not explicit” rendering do not return any kind of error and, at last, the key is valid from the Google administration settings.

Can you please help me to understand what is wrong with this solution?
Thanks in advance

Some posts showed that the problem should be on the execute methods, that it’s expecting the widget_id, in a first version I didn’t provide it, but after introducing it the result hasn’t changed.
Google documentation is not really exhaustive…

How to remove Ref before leaving the screen in React / React native?

I would like to to remove Ref before leaving the screen in React / React native because it causes keyboard flickering on navigating back.

My code is:

 // To focus on the input field when the page loads
    const privateNotesInput = useRef<AnimatedTextInputRef | null>(null);
    const focusTimeoutRef = useRef<NodeJS.Timeout | null>(null);

    useHtmlPaste(privateNotesInput);

    useFocusEffect(
        useCallback(() => {
            focusTimeoutRef.current = setTimeout(() => {
                if (privateNotesInput.current) {
                    privateNotesInput.current.focus();
                }
                return () => {
                    if (!focusTimeoutRef.current) {
                        return;
                    }
                    clearTimeout(focusTimeoutRef.current);
                };
            }, CONST.ANIMATED_TRANSITION);
        }, []),
    );
    
    
     <InputWrapper
                        InputComponent={TextInput}
                        role={CONST.ROLE.PRESENTATION}
                        inputID={INPUT_IDS.PRIVATE_NOTES}
                        label={translate('privateNotes.composerLabel')}
                        accessibilityLabel={translate('privateNotes.title')}
                        autoCompleteType="off"
                        maxLength={CONST.MAX_COMMENT_LENGTH}
                        autoCorrect={false}
                        autoGrowHeight
                        containerStyles={[styles.autoGrowHeightMultilineInput]}
                        defaultValue={privateNote}
                        value={privateNote}
                        onChangeText={(text: string) => {
                            debouncedSaveNote(text);
                            setNote(text);
                        }}
                        ref={(el: AnimatedTextInputRef) => {
                            if (!el) {
                                return;
                            }
                            privateNotesInput.current = el;
                            updateMultilineInputRange(privateNotesInput.current);
                        }}
                    />

If someone knows how to solve it then please let me know. Thanks