Api invitation link (#107)
* feat(api): invitation token to add team members * feat(api): invitation link change password * feat(db): changed base_auth structure * feat(api): invitation link - regenerate/reset * feat(api): invitation link - restore deleted user * feat(api): invitation link for forget password * feat(api): changed email body for invite user and reset password * feat(api): invitation link, expired invitation and has joined in the list of members * feat(api): invitation link for EE
This commit is contained in:
parent
42884550df
commit
44992e85a6
7 changed files with 179 additions and 90 deletions
|
|
@ -53,7 +53,7 @@
|
|||
"S3_KEY": "",
|
||||
"S3_SECRET": "",
|
||||
"invitation_link": "/api/users/invitation?token=%s",
|
||||
"change_password_link": "/changepassword?invitation=%s&&pass=%s",
|
||||
"change_password_link": "/reset-password?invitation=%s&&pass=%s",
|
||||
"version_number": "1.2.0"
|
||||
},
|
||||
"lambda_timeout": 150,
|
||||
|
|
|
|||
|
|
@ -364,7 +364,7 @@ def process_invitation_link():
|
|||
user = users.get_by_invitation_token(params["token"])
|
||||
if user is None:
|
||||
return {"errors": ["invitation not found"]}
|
||||
if user["expired"]:
|
||||
if user["expiredInvitation"]:
|
||||
return {"errors": ["expired invitation, please ask your admin to send a new one"]}
|
||||
pass_token = users.allow_password_change(user_id=user["userId"])
|
||||
return Response(
|
||||
|
|
|
|||
|
|
@ -16,10 +16,6 @@ def __generate_invitation_token():
|
|||
return secrets.token_urlsafe(64)
|
||||
|
||||
|
||||
def __is_authorized_to_manage_users():
|
||||
pass
|
||||
|
||||
|
||||
def create_new_member(email, invitation_token, admin, name, owner=False):
|
||||
with pg_client.PostgresClient() as cur:
|
||||
query = cur.mogrify(f"""\
|
||||
|
|
@ -42,8 +38,7 @@ def create_new_member(email, invitation_token, admin, name, owner=False):
|
|||
(CASE WHEN u.role = 'member' THEN TRUE ELSE FALSE END) AS member,
|
||||
au.invitation_token
|
||||
FROM u,au;""",
|
||||
{"email": email, "password": invitation_token,
|
||||
"role": "owner" if owner else "admin" if admin else "member", "name": name,
|
||||
{"email": email, "role": "owner" if owner else "admin" if admin else "member", "name": name,
|
||||
"data": json.dumps({"lastAnnouncementView": TimeUTC.now()}),
|
||||
"invitation_token": invitation_token})
|
||||
cur.execute(
|
||||
|
|
@ -112,6 +107,7 @@ def generate_new_invitation(user_id):
|
|||
return __get_invitation_link(cur.fetchone().pop("invitation_token"))
|
||||
|
||||
|
||||
|
||||
def reset_member(tenant_id, editor_id, user_id_to_update):
|
||||
admin = get(tenant_id=tenant_id, user_id=editor_id)
|
||||
if not admin["admin"] and not admin["superAdmin"]:
|
||||
|
|
@ -368,7 +364,10 @@ def get_members(tenant_id):
|
|||
basic_authentication.generated_password,
|
||||
(CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin,
|
||||
(CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin,
|
||||
(CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member
|
||||
(CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member,
|
||||
DATE_PART('day',timezone('utc'::text, now()) \
|
||||
- COALESCE(basic_authentication.invited_at,'2000-01-01'::timestamp ))>=1 AS expired_invitation,
|
||||
basic_authentication.password IS NOT NULL AS joined
|
||||
FROM public.users LEFT JOIN public.basic_authentication ON users.user_id=basic_authentication.user_id
|
||||
WHERE users.deleted_at IS NULL
|
||||
ORDER BY name, id"""
|
||||
|
|
@ -475,7 +474,8 @@ def get_by_invitation_token(token, pass_token=None):
|
|||
cur.mogrify(
|
||||
f"""SELECT
|
||||
*,
|
||||
DATE_PART('day',timezone('utc'::text, now())- invited_at)>=1 AS expired,
|
||||
DATE_PART('day',timezone('utc'::text, now()) \
|
||||
- COALESCE(basic_authentication.invited_at,'2000-01-01'::timestamp ))>=1 AS expired_invitation,
|
||||
change_pwd_expire_at <= timezone('utc'::text, now()) AS expired_change
|
||||
FROM public.users INNER JOIN public.basic_authentication USING(user_id)
|
||||
WHERE invitation_token = %(token)s {"AND change_pwd_token = %(pass_token)s" if pass_token else ""}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,9 @@
|
|||
"idp_entityId": "",
|
||||
"idp_sso_url": "",
|
||||
"idp_x509cert": "",
|
||||
"idp_sls_url": ""
|
||||
"idp_sls_url": "",
|
||||
"invitation_link": "/api/users/invitation?token=%s",
|
||||
"change_password_link": "/reset-password?invitation=%s&&pass=%s"
|
||||
},
|
||||
"lambda_timeout": 150,
|
||||
"lambda_memory_size": 400,
|
||||
|
|
|
|||
|
|
@ -362,6 +362,38 @@ def add_member(context):
|
|||
return users.create_member(tenant_id=context['tenantId'], user_id=context['userId'], data=data)
|
||||
|
||||
|
||||
@app.route('/users/invitation', methods=['GET'], authorizer=None)
|
||||
def process_invitation_link():
|
||||
params = app.current_request.query_params
|
||||
if params is None or len(params.get("token", "")) < 64:
|
||||
return {"errors": ["please provide a valid invitation"]}
|
||||
user = users.get_by_invitation_token(params["token"])
|
||||
if user is None:
|
||||
return {"errors": ["invitation not found"]}
|
||||
if user["expiredInvitation"]:
|
||||
return {"errors": ["expired invitation, please ask your admin to send a new one"]}
|
||||
pass_token = users.allow_password_change(user_id=user["userId"])
|
||||
return Response(
|
||||
status_code=307,
|
||||
body='',
|
||||
headers={'Location': environ["SITE_URL"] + environ["change_password_link"] % (params["token"], pass_token),
|
||||
'Content-Type': 'text/plain'})
|
||||
|
||||
|
||||
@app.route('/users/invitation/password', methods=['POST', 'PUT'], authorizer=None)
|
||||
def change_password_by_invitation():
|
||||
data = app.current_request.json_body
|
||||
if data is None or len(data.get("invitation", "")) < 64 or len(data.get("pass", "")) < 8:
|
||||
return {"errors": ["please provide a valid invitation & pass"]}
|
||||
user = users.get_by_invitation_token(token=data["token"], pass_token=data["pass"])
|
||||
if user is None:
|
||||
return {"errors": ["invitation not found"]}
|
||||
if user["expiredChange"]:
|
||||
return {"errors": ["expired change, please re-use the invitation link"]}
|
||||
|
||||
return users.set_password_invitation(new_password=data["password"], user_id=user["userId"])
|
||||
|
||||
|
||||
@app.route('/client/members/{memberId}', methods=['PUT', 'POST'])
|
||||
def edit_member(memberId, context):
|
||||
data = app.current_request.json_body
|
||||
|
|
@ -369,6 +401,11 @@ def edit_member(memberId, context):
|
|||
user_id_to_update=memberId)
|
||||
|
||||
|
||||
@app.route('/client/members/{memberId}/reset', methods=['GET'])
|
||||
def reset_reinvite_member(memberId, context):
|
||||
return users.reset_member(tenant_id=context['tenantId'], editor_id=context['userId'], user_id_to_update=memberId)
|
||||
|
||||
|
||||
@app.route('/client/members/{memberId}', methods=['DELETE'])
|
||||
def delete_member(memberId, context):
|
||||
return users.delete_member(tenant_id=context["tenantId"], user_id=context['userId'], id_to_delete=memberId)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
import chalicelib.utils.TimeUTC
|
||||
from chalicelib.utils import email_helper, captcha, helper
|
||||
import secrets
|
||||
from chalicelib.utils import pg_client
|
||||
|
||||
from chalicelib.core import users
|
||||
|
||||
|
||||
|
|
@ -18,49 +14,23 @@ def step1(data):
|
|||
a_users = users.get_by_email_only(data["email"])
|
||||
if len(a_users) > 1:
|
||||
print(f"multiple users found for [{data['email']}] please contact our support")
|
||||
return {"errors": ["please contact our support"]}
|
||||
return {"errors": ["multiple users, please contact our support"]}
|
||||
elif len(a_users) == 1:
|
||||
a_users = a_users[0]
|
||||
reset_token = secrets.token_urlsafe(6)
|
||||
users.update(tenant_id=a_users["tenantId"], user_id=a_users["id"],
|
||||
changes={"token": reset_token})
|
||||
email_helper.send_reset_code(recipient=data["email"], reset_code=reset_token)
|
||||
invitation_link = users.generate_new_invitation(user_id=a_users["id"])
|
||||
email_helper.send_forgot_password(recipient=data["email"], invitation_link=invitation_link)
|
||||
else:
|
||||
print(f"invalid email address [{data['email']}]")
|
||||
return {"errors": ["invalid email address"]}
|
||||
return {"data": {"state": "success"}}
|
||||
|
||||
|
||||
def step2(data):
|
||||
print("====================== change password 2 ===============")
|
||||
user = users.get_by_email_reset(data["email"], data["code"])
|
||||
if not user:
|
||||
print("error: wrong email or reset code")
|
||||
return {"errors": ["wrong email or reset code"]}
|
||||
users.update(tenant_id=user["tenantId"], user_id=user["id"],
|
||||
changes={"token": None, "password": data["password"], "generatedPassword": False,
|
||||
"verifiedEmail": True})
|
||||
return {"data": {"state": "success"}}
|
||||
|
||||
|
||||
def cron():
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute(
|
||||
cur.mogrify("""\
|
||||
SELECT user_id
|
||||
FROM public.basic_authentication
|
||||
WHERE token notnull
|
||||
AND (token_requested_at isnull or (EXTRACT(EPOCH FROM token_requested_at)*1000)::BIGINT < %(time)s);""",
|
||||
{"time": chalicelib.utils.TimeUTC.TimeUTC.now(delta_days=-1)})
|
||||
)
|
||||
results = cur.fetchall()
|
||||
if len(results) == 0:
|
||||
return
|
||||
results = tuple([r["user_id"] for r in results])
|
||||
cur.execute(
|
||||
cur.mogrify("""\
|
||||
UPDATE public.basic_authentication
|
||||
SET token = NULL, token_requested_at = NULL
|
||||
WHERE user_id in %(ids)s;""",
|
||||
{"ids": results})
|
||||
)
|
||||
# def step2(data):
|
||||
# print("====================== change password 2 ===============")
|
||||
# user = users.get_by_email_reset(data["email"], data["code"])
|
||||
# if not user:
|
||||
# print("error: wrong email or reset code")
|
||||
# return {"errors": ["wrong email or reset code"]}
|
||||
# users.update(tenant_id=user["tenantId"], user_id=user["id"],
|
||||
# changes={"token": None, "password": data["password"], "generatedPassword": False,
|
||||
# "verifiedEmail": True})
|
||||
# return {"data": {"state": "success"}}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,17 @@ from chalicelib.core import authorizers
|
|||
from chalicelib.core import tenants
|
||||
from chalicelib.utils import helper
|
||||
from chalicelib.utils import pg_client
|
||||
from chalicelib.utils import dev
|
||||
from chalicelib.utils.TimeUTC import TimeUTC
|
||||
from chalicelib.utils.helper import environ
|
||||
import secrets
|
||||
|
||||
|
||||
def create_new_member(tenant_id, email, password, admin, name, owner=False):
|
||||
def __generate_invitation_token():
|
||||
return secrets.token_urlsafe(64)
|
||||
|
||||
|
||||
def create_new_member(tenant_id, email, invitation_token, admin, name, owner=False):
|
||||
with pg_client.PostgresClient() as cur:
|
||||
query = cur.mogrify(f"""\
|
||||
WITH u AS (
|
||||
|
|
@ -16,10 +22,12 @@ def create_new_member(tenant_id, email, password, admin, name, owner=False):
|
|||
VALUES (%(tenantId)s, %(email)s, %(role)s, %(name)s, %(data)s)
|
||||
RETURNING user_id,email,role,name,appearance
|
||||
),
|
||||
au AS (INSERT
|
||||
INTO public.basic_authentication (user_id, password, generated_password)
|
||||
VALUES ((SELECT user_id FROM u), crypt(%(password)s, gen_salt('bf', 12)), TRUE))
|
||||
au AS (INSERT INTO public.basic_authentication (user_id, generated_password, invitation_token, invited_at)
|
||||
VALUES ((SELECT user_id FROM u), TRUE, %(invitation_token)s, timezone('utc'::text, now()))
|
||||
RETURNING invitation_token
|
||||
)
|
||||
SELECT u.user_id AS id,
|
||||
u.user_id,
|
||||
u.email,
|
||||
u.role,
|
||||
u.name,
|
||||
|
|
@ -27,18 +35,19 @@ def create_new_member(tenant_id, email, password, admin, name, owner=False):
|
|||
(CASE WHEN u.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin,
|
||||
(CASE WHEN u.role = 'admin' THEN TRUE ELSE FALSE END) AS admin,
|
||||
(CASE WHEN u.role = 'member' THEN TRUE ELSE FALSE END) AS member,
|
||||
u.appearance
|
||||
FROM u;""",
|
||||
{"tenantId": tenant_id, "email": email, "password": password,
|
||||
au.invitation_token
|
||||
FROM u,au;""",
|
||||
{"tenantId": tenant_id, "email": email,
|
||||
"role": "owner" if owner else "admin" if admin else "member", "name": name,
|
||||
"data": json.dumps({"lastAnnouncementView": TimeUTC.now()})})
|
||||
"data": json.dumps({"lastAnnouncementView": TimeUTC.now()}),
|
||||
"invitation_token": invitation_token})
|
||||
cur.execute(
|
||||
query
|
||||
)
|
||||
return helper.dict_to_camel_case(cur.fetchone())
|
||||
|
||||
|
||||
def restore_member(tenant_id, user_id, email, password, admin, name, owner=False):
|
||||
def restore_member(tenant_id, user_id, email, invitation_token, admin, name, owner=False):
|
||||
with pg_client.PostgresClient() as cur:
|
||||
query = cur.mogrify(f"""\
|
||||
UPDATE public.users
|
||||
|
|
@ -56,31 +65,61 @@ def restore_member(tenant_id, user_id, email, password, admin, name, owner=False
|
|||
TRUE AS change_password,
|
||||
(CASE WHEN role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin,
|
||||
(CASE WHEN role = 'admin' THEN TRUE ELSE FALSE END) AS admin,
|
||||
(CASE WHEN role = 'member' THEN TRUE ELSE FALSE END) AS member,
|
||||
appearance;""",
|
||||
(CASE WHEN role = 'member' THEN TRUE ELSE FALSE END) AS member;""",
|
||||
{"tenant_id": tenant_id, "user_id": user_id, "email": email,
|
||||
"role": "owner" if owner else "admin" if admin else "member", "name": name})
|
||||
cur.execute(
|
||||
query
|
||||
)
|
||||
result = helper.dict_to_camel_case(cur.fetchone())
|
||||
result = cur.fetchone()
|
||||
query = cur.mogrify("""\
|
||||
UPDATE public.basic_authentication
|
||||
SET password= crypt(%(password)s, gen_salt('bf', 12)),
|
||||
generated_password= TRUE,
|
||||
token=NULL,
|
||||
token_requested_at=NULL
|
||||
WHERE user_id=%(user_id)s;""",
|
||||
{"user_id": user_id, "password": password})
|
||||
SET generated_password = TRUE,
|
||||
invitation_token = %(invitation_token)s,
|
||||
invited_at = timezone('utc'::text, now()),
|
||||
change_pwd_expire_at = NULL,
|
||||
change_pwd_token = NULL
|
||||
WHERE user_id=%(user_id)s
|
||||
RETURNING invitation_token;""",
|
||||
{"user_id": user_id, "invitation_token": invitation_token})
|
||||
cur.execute(
|
||||
query
|
||||
)
|
||||
result["invitation_token"] = cur.fetchone()["invitation_token"]
|
||||
|
||||
return result
|
||||
return helper.dict_to_camel_case(result)
|
||||
|
||||
|
||||
def generate_new_invitation(user_id):
|
||||
invitation_token = __generate_invitation_token()
|
||||
with pg_client.PostgresClient() as cur:
|
||||
query = cur.mogrify("""\
|
||||
UPDATE public.basic_authentication
|
||||
SET invitation_token = %(invitation_token)s,
|
||||
invited_at = timezone('utc'::text, now()),
|
||||
change_pwd_expire_at = NULL,
|
||||
change_pwd_token = NULL
|
||||
WHERE user_id=%(user_id)s
|
||||
RETURNING invitation_token;""",
|
||||
{"user_id": user_id, "invitation_token": invitation_token})
|
||||
cur.execute(
|
||||
query
|
||||
)
|
||||
return __get_invitation_link(cur.fetchone().pop("invitation_token"))
|
||||
|
||||
|
||||
def reset_member(tenant_id, editor_id, user_id_to_update):
|
||||
admin = get(tenant_id=tenant_id, user_id=editor_id)
|
||||
if not admin["admin"] and not admin["superAdmin"]:
|
||||
return {"errors": ["unauthorized"]}
|
||||
user = get(tenant_id=tenant_id, user_id=user_id_to_update)
|
||||
if not user:
|
||||
return {"errors": ["user not found"]}
|
||||
return {"data": {"invitationLink": generate_new_invitation(user_id_to_update)}}
|
||||
|
||||
|
||||
def update(tenant_id, user_id, changes):
|
||||
AUTH_KEYS = ["password", "generatedPassword", "token"]
|
||||
AUTH_KEYS = ["password", "generatedPassword", "invitationToken", "invitedAt", "changePwdExpireAt", "changePwdToken"]
|
||||
if len(changes.keys()) == 0:
|
||||
return None
|
||||
|
||||
|
|
@ -91,13 +130,6 @@ def update(tenant_id, user_id, changes):
|
|||
if key == "password":
|
||||
sub_query_bauth.append("password = crypt(%(password)s, gen_salt('bf', 12))")
|
||||
sub_query_bauth.append("changed_at = timezone('utc'::text, now())")
|
||||
elif key == "token":
|
||||
if changes[key] is not None:
|
||||
sub_query_bauth.append("token = %(token)s")
|
||||
sub_query_bauth.append("token_requested_at = timezone('utc'::text, now())")
|
||||
else:
|
||||
sub_query_bauth.append("token = NULL")
|
||||
sub_query_bauth.append("token_requested_at = NULL")
|
||||
else:
|
||||
sub_query_bauth.append(f"{helper.key_to_snake_case(key)} = %({key})s")
|
||||
else:
|
||||
|
|
@ -166,26 +198,43 @@ def create_member(tenant_id, user_id, data):
|
|||
return {"errors": ["invalid user name"]}
|
||||
if name is None:
|
||||
name = data["email"]
|
||||
temp_pass = helper.generate_salt()[:8]
|
||||
invitation_token = __generate_invitation_token()
|
||||
user = get_deleted_user_by_email(email=data["email"])
|
||||
if user is not None:
|
||||
new_member = restore_member(tenant_id=tenant_id, email=data["email"], password=temp_pass,
|
||||
new_member = restore_member(tenant_id=tenant_id, email=data["email"], invitation_token=invitation_token,
|
||||
admin=data.get("admin", False), name=name, user_id=user["userId"])
|
||||
else:
|
||||
new_member = create_new_member(tenant_id=tenant_id, email=data["email"], password=temp_pass,
|
||||
new_member = create_new_member(tenant_id=tenant_id, email=data["email"], invitation_token=invitation_token,
|
||||
admin=data.get("admin", False), name=name)
|
||||
|
||||
new_member["invitationLink"] = __get_invitation_link(new_member.pop("invitationToken"))
|
||||
helper.async_post(environ['email_basic'] % 'member_invitation',
|
||||
{
|
||||
"email": data["email"],
|
||||
"userName": data["email"],
|
||||
"tempPassword": temp_pass,
|
||||
"invitationLink": new_member["invitationLink"],
|
||||
"clientId": tenants.get_by_tenant_id(tenant_id)["name"],
|
||||
"senderName": admin["name"]
|
||||
})
|
||||
return {"data": new_member}
|
||||
|
||||
|
||||
def __get_invitation_link(invitation_token):
|
||||
return environ["SITE_URL"] + environ["invitation_link"] % invitation_token
|
||||
|
||||
|
||||
def allow_password_change(user_id, delta_min=10):
|
||||
pass_token = secrets.token_urlsafe(8)
|
||||
with pg_client.PostgresClient() as cur:
|
||||
query = cur.mogrify(f"""UPDATE public.basic_authentication
|
||||
SET change_pwd_expire_at = timezone('utc'::text, now()+INTERVAL '%(delta)s MINUTES'),
|
||||
change_pwd_token = %(pass_token)s
|
||||
WHERE user_id = %(user_id)s""",
|
||||
{"user_id": user_id, "delta": delta_min, "pass_token": pass_token})
|
||||
cur.execute(
|
||||
query
|
||||
)
|
||||
return pass_token
|
||||
|
||||
|
||||
def get(user_id, tenant_id):
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute(
|
||||
|
|
@ -321,7 +370,10 @@ def get_members(tenant_id):
|
|||
basic_authentication.generated_password,
|
||||
(CASE WHEN users.role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin,
|
||||
(CASE WHEN users.role = 'admin' THEN TRUE ELSE FALSE END) AS admin,
|
||||
(CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member
|
||||
(CASE WHEN users.role = 'member' THEN TRUE ELSE FALSE END) AS member,
|
||||
DATE_PART('day',timezone('utc'::text, now()) \
|
||||
- COALESCE(basic_authentication.invited_at,'2000-01-01'::timestamp ))>=1 AS expired_invitation,
|
||||
basic_authentication.password IS NOT NULL AS joined
|
||||
FROM public.users LEFT JOIN public.basic_authentication ON users.user_id=basic_authentication.user_id
|
||||
WHERE users.tenant_id = %(tenantId)s AND users.deleted_at IS NULL
|
||||
ORDER BY name, id""",
|
||||
|
|
@ -374,6 +426,15 @@ def change_password(tenant_id, user_id, email, old_password, new_password):
|
|||
"jwt": authenticate(email, new_password)["jwt"]}
|
||||
|
||||
|
||||
def set_password_invitation(user_id, new_password):
|
||||
changes = {"password": new_password, "generatedPassword": False,
|
||||
"invitationToken": None, "invitedAt": None,
|
||||
"changePwdExpireAt": None, "changePwdToken": None}
|
||||
user = update(tenant_id=-1, user_id=user_id, changes=changes)
|
||||
return {"data": user,
|
||||
"jwt": authenticate(user["email"], new_password)["jwt"]}
|
||||
|
||||
|
||||
def count_members(tenant_id):
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute(
|
||||
|
|
@ -393,7 +454,7 @@ def email_exists(email):
|
|||
cur.mogrify(
|
||||
f"""SELECT
|
||||
count(user_id)
|
||||
FROM public.users
|
||||
FROM public.users
|
||||
WHERE
|
||||
email = %(email)s
|
||||
AND deleted_at IS NULL
|
||||
|
|
@ -410,7 +471,7 @@ def get_deleted_user_by_email(email):
|
|||
cur.mogrify(
|
||||
f"""SELECT
|
||||
*
|
||||
FROM public.users
|
||||
FROM public.users
|
||||
WHERE
|
||||
email = %(email)s
|
||||
AND deleted_at NOTNULL
|
||||
|
|
@ -421,6 +482,24 @@ def get_deleted_user_by_email(email):
|
|||
return helper.dict_to_camel_case(r)
|
||||
|
||||
|
||||
def get_by_invitation_token(token, pass_token=None):
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute(
|
||||
cur.mogrify(
|
||||
f"""SELECT
|
||||
*,
|
||||
DATE_PART('day',timezone('utc'::text, now()) \
|
||||
- COALESCE(basic_authentication.invited_at,'2000-01-01'::timestamp ))>=1 AS expired_invitation,
|
||||
change_pwd_expire_at <= timezone('utc'::text, now()) AS expired_change
|
||||
FROM public.users INNER JOIN public.basic_authentication USING(user_id)
|
||||
WHERE invitation_token = %(token)s {"AND change_pwd_token = %(pass_token)s" if pass_token else ""}
|
||||
LIMIT 1;""",
|
||||
{"token": token, "pass_token": token})
|
||||
)
|
||||
r = cur.fetchone()
|
||||
return helper.dict_to_camel_case(r)
|
||||
|
||||
|
||||
def auth_exists(user_id, tenant_id, jwt_iat, jwt_aud):
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute(
|
||||
|
|
@ -450,6 +529,7 @@ def change_jwt_iat(user_id):
|
|||
return cur.fetchone().get("jwt_iat")
|
||||
|
||||
|
||||
@dev.timed
|
||||
def authenticate(email, password, for_change_password=False, for_plugin=False):
|
||||
with pg_client.PostgresClient() as cur:
|
||||
query = cur.mogrify(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue