Docfield confirm and datestamp password entry

I am trying to add a feature that forces password entry into a doctype field and records the date of successful password entry. I would like the the py and js files to confirm the password against the User’s password in the db and then enter the verified date as a read only field (see attached image). I am stuck on how to take the User from the docfield and verify the password. Could anyone give me some guidance how to accomplish this?

I’m not sure I understand your question, so let me try to restate it:
The user enters (or a value is stored, coming from somewhere else?) a password into the column “password” in this child table. You want a read-only date to show up with the date the password was entered. It sounds like you’re accessing this child table just as you would any other:

parent_doc.attendees[0].password or parent_doc.attendees[0].verified_date

Because it’s a child table, you’ll almost always want to iterate through the list in a loop. Is this what you’re looking for? There’s a lot of child doc questions on the forum because they’re confusing for people just getting acclimated to Frappe and a little bit hard to use from the parent doctype. When I’m getting stuck with it, I try to bring it back to the abstracted structure of nearly all Frappe doctypes:

{"doctype": "doctypes_are_objects", "child_table": [{"child": "tables", "are": "lists", "of": "objects"}, {"child": "tables", "are": "lists", "of": "objects"}]

In the database, they are separate tables, but there’s a link (column) from a child doctype to a parent "parent": "doctypes_are_objects"}, {... , and from a parent to child as a list of links (blob) ["Charles", "Olivia", "Hugo", ...

Hope that helps.

Thank you for your response. You are correct in your understanding. I want to have each user listed in the child table enter their password as confirmation / acknowledgement of some document. I think I have a basic understanding of the parent/child table from the tutorials.

My problem is now how to get and compare the password they enter with their system password. I have a python function like this:

def check_password(user, pwd, doctype='User', fieldname='password'):
'''Checks if user and password are correct, else raises frappe.AuthenticationError'''

auth = frappe.db.sql("""select name, `password` from `__Auth`
	where doctype=%(doctype)s and name=%(name)s and fieldname=%(fieldname)s and encrypted=0""",
	{'doctype': doctype, 'name': user, 'fieldname': fieldname}, as_dict=True)

if not auth or not passlibctx.verify(pwd, auth[0].password):
	raise frappe.AuthenticationError(_('Incorrect User or Password'))

# lettercase agnostic
user = auth[0].name

if not passlibctx.needs_update(auth[0].password):
	update_password(user, pwd, doctype, fieldname)

return user

Then I have a .js file that calls the python function, if the function returns confirms the password, it puts the datetime stamp in the child table. The code doesn’t show anything about handling a date, I am just trying to work out how to confirm the password at this point.

frm.call({
			method: "meeting.meeting.doctype.meeting.meeting.check_password", 
			args: {
				user: attendee.attendee,
				pwd: attendee.pwd
			},
			callback: function(r) {
				frappe.model.set_value(cdt, cdn, "verified_date", r.message);
			}
		});

You add @frappe.whitelist() and try your code again.

@frappe.whitelist()
def check_password(user, pwd, doctype=‘User’, fieldname=‘password’):

Edit:
Should be frappe.call instead of frm.call

1 Like

I’m still catching up to your use case; this is like an attendance signature sheet.

So I think your problem lies in implementing the client side table triggers. I think you want to activate your password-checking callback when the user leaves the password cell. You’ll want to put the child table trigger code in the parent.js file. Consider below where parent is the parent doctype and attendees is the name of the table and Attendee is the name of the child doctype. Here’s the cheatsheet. This should get you started with some ideas.

frappe.ui.form.on("Attendee", {
	attendee_remove: function(frm) {
	    // validation logic
        frappe.throw("You cannot remove a signed row");
	},
 	pwd: function(frm, cdt, cdn) {
        // if not undefined or ""
		frappe.call({...
	}
});