Api changes (#161)
* fix(api): EE set password after invitation * feat(api): FOS&EE return tracker version with the list of projects * feat(api): FOS&EE signup changes * feat(api): EE signup email existance error message
This commit is contained in:
parent
1f3394f508
commit
10629a6b4f
9 changed files with 48 additions and 140 deletions
|
|
@ -22,13 +22,6 @@ app = Blueprint(__name__)
|
|||
_overrides.chalice_app(app)
|
||||
|
||||
|
||||
@app.route('/signedups', methods=['GET'], authorizer=None)
|
||||
def signed_ups():
|
||||
return {
|
||||
'data': tenants.get_tenants()
|
||||
}
|
||||
|
||||
|
||||
@app.route('/login', methods=['POST'], authorizer=None)
|
||||
def login():
|
||||
data = app.current_request.json_body
|
||||
|
|
@ -52,7 +45,7 @@ def login():
|
|||
c = tenants.get_by_tenant_id(tenant_id)
|
||||
c.pop("createdAt")
|
||||
c["projects"] = projects.get_projects(tenant_id=tenant_id, recording_state=True, recorded=True,
|
||||
stack_integrations=True)
|
||||
stack_integrations=True, version=True)
|
||||
c["smtp"] = helper.has_smtp()
|
||||
return {
|
||||
'jwt': r.pop('jwt'),
|
||||
|
|
@ -83,7 +76,7 @@ def get_account(context):
|
|||
@app.route('/projects', methods=['GET'])
|
||||
def get_projects(context):
|
||||
return {"data": projects.get_projects(tenant_id=context["tenantId"], recording_state=True, gdpr=True, recorded=True,
|
||||
stack_integrations=True)}
|
||||
stack_integrations=True, version=True)}
|
||||
|
||||
|
||||
@app.route('/projects', methods=['POST', 'PUT'])
|
||||
|
|
@ -127,7 +120,7 @@ def get_client(context):
|
|||
if r is not None:
|
||||
r.pop("createdAt")
|
||||
r["projects"] = projects.get_projects(tenant_id=context['tenantId'], recording_state=True, recorded=True,
|
||||
stack_integrations=True)
|
||||
stack_integrations=True, version=True)
|
||||
return {
|
||||
'data': r
|
||||
}
|
||||
|
|
@ -148,7 +141,7 @@ def put_client(context):
|
|||
|
||||
@app.route('/signup', methods=['GET'], authorizer=None)
|
||||
def get_all_signup():
|
||||
return {"data": signup.get_signed_ups()}
|
||||
return {"data": tenants.tenants_exists()}
|
||||
|
||||
|
||||
@app.route('/signup', methods=['POST', 'PUT'], authorizer=None)
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ def __create(tenant_id, name):
|
|||
|
||||
|
||||
@dev.timed
|
||||
def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, stack_integrations=False):
|
||||
def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, stack_integrations=False,version=False):
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute(f"""\
|
||||
SELECT
|
||||
|
|
@ -49,6 +49,7 @@ def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, st
|
|||
{',s.gdpr' if gdpr else ''}
|
||||
{',COALESCE((SELECT TRUE FROM public.sessions WHERE sessions.project_id = s.project_id LIMIT 1), FALSE) AS recorded' if recorded else ''}
|
||||
{',stack_integrations.count>0 AS stack_integrations' if stack_integrations else ''}
|
||||
{',(SELECT tracker_version FROM public.sessions WHERE sessions.project_id = s.project_id ORDER BY start_ts DESC LIMIT 1) AS tracker_version' if version else ''}
|
||||
FROM public.projects AS s
|
||||
{'LEFT JOIN LATERAL (SELECT COUNT(*) AS count FROM public.integrations WHERE s.project_id = integrations.project_id LIMIT 1) AS stack_integrations ON TRUE' if stack_integrations else ''}
|
||||
where s.deleted_at IS NULL
|
||||
|
|
|
|||
|
|
@ -1,39 +1,31 @@
|
|||
from chalicelib.utils import helper
|
||||
from chalicelib.utils import pg_client
|
||||
from chalicelib.core import users, telemetry
|
||||
from chalicelib.core import users, telemetry, tenants
|
||||
from chalicelib.utils import captcha
|
||||
import json
|
||||
from chalicelib.utils.TimeUTC import TimeUTC
|
||||
from chalicelib.utils.helper import environ
|
||||
|
||||
|
||||
def get_signed_ups():
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute("SELECT tenant_id, name FROM public.tenants;")
|
||||
rows = cur.fetchall()
|
||||
return helper.list_to_camel_case(rows)
|
||||
|
||||
|
||||
def create_step1(data):
|
||||
print(f"===================== SIGNUP STEP 1 AT {TimeUTC.to_human_readable(TimeUTC.now())} UTC")
|
||||
errors = []
|
||||
if tenants.tenants_exists():
|
||||
return {"errors": ["tenants already registered"]}
|
||||
|
||||
email = data.get("email")
|
||||
print(f"=====================> {email}")
|
||||
password = data.get("password")
|
||||
|
||||
print("Verifying email validity")
|
||||
email_exists = False
|
||||
if email is None or len(email) < 5 or not helper.is_valid_email(email):
|
||||
errors.append("Invalid email address.")
|
||||
else:
|
||||
print("Verifying email existance")
|
||||
if users.email_exists(email):
|
||||
# errors.append("Email address already in use.")
|
||||
email_exists = True
|
||||
errors.append("Email address already in use.")
|
||||
if users.get_deleted_user_by_email(email) is not None:
|
||||
# errors.append("Email address previously deleted.")
|
||||
email_exists = True
|
||||
errors.append("Email address previously deleted.")
|
||||
|
||||
print("Verifying captcha")
|
||||
if helper.allow_captcha() and not captcha.is_valid(data["g-recaptcha-response"]):
|
||||
|
|
@ -57,12 +49,6 @@ def create_step1(data):
|
|||
project_name = data.get("projectName")
|
||||
if project_name is None or len(project_name) < 1:
|
||||
project_name = "my first project"
|
||||
signed_ups = get_signed_ups()
|
||||
if len(signed_ups) > 0 and data.get("tenantId") is None:
|
||||
errors.append("Tenant already exists, please select it from dropdown")
|
||||
elif len(signed_ups) == 0 and data.get("tenantId") is not None \
|
||||
or len(signed_ups) > 0 and data.get("tenantId") not in [t['tenantId'] for t in signed_ups]:
|
||||
errors.append("Tenant not found")
|
||||
|
||||
if len(errors) > 0:
|
||||
print("==> error")
|
||||
|
|
@ -77,41 +63,7 @@ def create_step1(data):
|
|||
"organizationName": company_name,
|
||||
"versionNumber": environ["version_number"]
|
||||
}
|
||||
if data.get("tenantId") is not None:
|
||||
update_user = """
|
||||
u AS (
|
||||
UPDATE public.users
|
||||
SET name = %(fullname)s, deleted_at=NULL
|
||||
WHERE email=%(email)s
|
||||
RETURNING user_id,email, role, name
|
||||
)
|
||||
UPDATE public.basic_authentication
|
||||
SET password= crypt(%(password)s, gen_salt('bf', 12))
|
||||
WHERE user_id = (SELECT user_id FROM u)"""
|
||||
insert_user = """
|
||||
a AS (
|
||||
UPDATE public.users
|
||||
SET role='admin'
|
||||
WHERE role ='owner'
|
||||
),
|
||||
u AS (
|
||||
INSERT INTO public.users (email, role, name, data)
|
||||
VALUES (%(email)s, 'owner', %(fullname)s,%(data)s)
|
||||
RETURNING user_id,email,role,name
|
||||
)
|
||||
INSERT INTO public.basic_authentication (user_id, password, generated_password)
|
||||
VALUES ((SELECT user_id FROM u), crypt(%(password)s, gen_salt('bf', 12)), FALSE)"""
|
||||
query = f"""\
|
||||
WITH t AS (
|
||||
UPDATE public.tenants
|
||||
SET name = %(organizationName)s,
|
||||
version_number = %(versionNumber)s
|
||||
RETURNING api_key
|
||||
),
|
||||
{update_user if email_exists else insert_user}
|
||||
RETURNING (SELECT api_key FROM t) AS api_key,(SELECT project_id FROM projects LIMIT 1) AS project_id;"""
|
||||
else:
|
||||
query = f"""\
|
||||
query = f"""\
|
||||
WITH t AS (
|
||||
INSERT INTO public.tenants (name, version_number, edition)
|
||||
VALUES (%(organizationName)s, %(versionNumber)s, 'fos')
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ def update(tenant_id, user_id, data):
|
|||
return edit_client(tenant_id=tenant_id, changes=changes)
|
||||
|
||||
|
||||
def get_tenants():
|
||||
def tenants_exists():
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute(f"SELECT name FROM public.tenants")
|
||||
return helper.list_to_camel_case(cur.fetchall())
|
||||
cur.execute(f"SELECT EXISTS(SELECT 1 FROM public.tenants)")
|
||||
return cur.fetchone()["exists"]
|
||||
|
|
|
|||
|
|
@ -22,13 +22,6 @@ app = Blueprint(__name__)
|
|||
_overrides.chalice_app(app)
|
||||
|
||||
|
||||
@app.route('/signedups', methods=['GET'], authorizer=None)
|
||||
def signed_ups():
|
||||
return {
|
||||
'data': tenants.get_tenants()
|
||||
}
|
||||
|
||||
|
||||
@app.route('/login', methods=['POST'], authorizer=None)
|
||||
def login():
|
||||
data = app.current_request.json_body
|
||||
|
|
@ -54,7 +47,7 @@ def login():
|
|||
c = tenants.get_by_tenant_id(tenant_id)
|
||||
c.pop("createdAt")
|
||||
c["projects"] = projects.get_projects(tenant_id=tenant_id, recording_state=True, recorded=True,
|
||||
stack_integrations=True)
|
||||
stack_integrations=True, version=True)
|
||||
return {
|
||||
'jwt': r.pop('jwt'),
|
||||
'data': {
|
||||
|
|
@ -85,7 +78,7 @@ def get_account(context):
|
|||
@app.route('/projects', methods=['GET'])
|
||||
def get_projects(context):
|
||||
return {"data": projects.get_projects(tenant_id=context["tenantId"], recording_state=True, gdpr=True, recorded=True,
|
||||
stack_integrations=True)}
|
||||
stack_integrations=True, version=True)}
|
||||
|
||||
|
||||
@app.route('/projects', methods=['POST', 'PUT'])
|
||||
|
|
@ -129,7 +122,7 @@ def get_client(context):
|
|||
if r is not None:
|
||||
r.pop("createdAt")
|
||||
r["projects"] = projects.get_projects(tenant_id=context['tenantId'], recording_state=True, recorded=True,
|
||||
stack_integrations=True)
|
||||
stack_integrations=True, version=True)
|
||||
return {
|
||||
'data': r
|
||||
}
|
||||
|
|
@ -148,10 +141,9 @@ def put_client(context):
|
|||
return tenants.update(tenant_id=context["tenantId"], user_id=context["userId"], data=data)
|
||||
|
||||
|
||||
# TODO: delete this for production; it is used for dev only
|
||||
@app.route('/signup', methods=['GET'], authorizer=None)
|
||||
def get_all_signup():
|
||||
return {"data": signup.get_signed_ups()}
|
||||
return {"data": tenants.tenants_exists()}
|
||||
|
||||
|
||||
@app.route('/signup', methods=['POST', 'PUT'], authorizer=None)
|
||||
|
|
@ -391,7 +383,8 @@ def change_password_by_invitation():
|
|||
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"])
|
||||
return users.set_password_invitation(new_password=data["password"], user_id=user["userId"],
|
||||
tenant_id=user["tenantId"])
|
||||
|
||||
|
||||
@app.route('/client/members/{memberId}', methods=['PUT', 'POST'])
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ def __create(tenant_id, name):
|
|||
return get_project(tenant_id=tenant_id, project_id=project_id, include_gdpr=True)
|
||||
|
||||
|
||||
def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, stack_integrations=False):
|
||||
def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, stack_integrations=False, version=False):
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute(
|
||||
cur.mogrify(f"""\
|
||||
|
|
@ -49,6 +49,7 @@ def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, st
|
|||
{',s.gdpr' if gdpr else ''}
|
||||
{',COALESCE((SELECT TRUE FROM public.sessions WHERE sessions.project_id = s.project_id LIMIT 1), FALSE) AS recorded' if recorded else ''}
|
||||
{',stack_integrations.count>0 AS stack_integrations' if stack_integrations else ''}
|
||||
{',(SELECT tracker_version FROM public.sessions WHERE sessions.project_id = s.project_id ORDER BY start_ts DESC LIMIT 1) AS tracker_version' if version else ''}
|
||||
FROM public.projects AS s
|
||||
{'LEFT JOIN LATERAL (SELECT COUNT(*) AS count FROM public.integrations WHERE s.project_id = integrations.project_id LIMIT 1) AS stack_integrations ON TRUE' if stack_integrations else ''}
|
||||
where s.tenant_id =%(tenant_id)s
|
||||
|
|
|
|||
|
|
@ -1,22 +1,17 @@
|
|||
from chalicelib.utils import helper
|
||||
from chalicelib.utils import pg_client
|
||||
from chalicelib.core import users, telemetry
|
||||
from chalicelib.core import users, telemetry, tenants
|
||||
from chalicelib.utils import captcha
|
||||
import json
|
||||
from chalicelib.utils.TimeUTC import TimeUTC
|
||||
from chalicelib.utils.helper import environ
|
||||
|
||||
|
||||
def get_signed_ups():
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute("SELECT tenant_id, name FROM public.tenants;")
|
||||
rows = cur.fetchall()
|
||||
return helper.list_to_camel_case(rows)
|
||||
|
||||
|
||||
def create_step1(data):
|
||||
print(f"===================== SIGNUP STEP 1 AT {TimeUTC.to_human_readable(TimeUTC.now())} UTC")
|
||||
errors = []
|
||||
if tenants.tenants_exists():
|
||||
return {"errors":["tenants already registered"]}
|
||||
|
||||
email = data.get("email")
|
||||
print(f"=====================> {email}")
|
||||
|
|
@ -54,64 +49,37 @@ def create_step1(data):
|
|||
project_name = data.get("projectName")
|
||||
if project_name is None or len(project_name) < 1:
|
||||
project_name = "my first project"
|
||||
signed_ups = get_signed_ups()
|
||||
|
||||
if len(signed_ups) == 0 and data.get("tenantId") is not None \
|
||||
or len(signed_ups) > 0 and data.get("tenantId") is not None\
|
||||
and data.get("tenantId") not in [t['tenantId'] for t in signed_ups]:
|
||||
errors.append("Tenant not found")
|
||||
if len(errors) > 0:
|
||||
print("==> error")
|
||||
print(errors)
|
||||
return {"errors": errors}
|
||||
print("No errors detected")
|
||||
print("Decomposed infos")
|
||||
tenant_id = data.get("tenantId")
|
||||
|
||||
params = {"email": email, "password": password,
|
||||
"fullname": fullname, "companyName": company_name,
|
||||
"projectName": project_name,
|
||||
"versionNumber": environ["version_number"],
|
||||
"data": json.dumps({"lastAnnouncementView": TimeUTC.now()})}
|
||||
if tenant_id is not None:
|
||||
query = """\
|
||||
WITH t AS (
|
||||
UPDATE public.tenants
|
||||
SET name = %(companyName)s,
|
||||
version_number = %(versionNumber)s
|
||||
WHERE tenant_id=%(tenant_id)s
|
||||
query = """\
|
||||
WITH t AS (
|
||||
INSERT INTO public.tenants (name, version_number, edition)
|
||||
VALUES (%(companyName)s, %(versionNumber)s, 'ee')
|
||||
RETURNING tenant_id, api_key
|
||||
),
|
||||
u AS (
|
||||
UPDATE public.users
|
||||
SET email = %(email)s,
|
||||
name = %(fullname)s,
|
||||
WHERE role ='owner' AND tenant_id=%(tenant_id)s
|
||||
RETURNING user_id,email, role, name
|
||||
)
|
||||
UPDATE public.basic_authentication
|
||||
SET password= crypt(%(password)s, gen_salt('bf', 12))
|
||||
WHERE user_id = (SELECT user_id FROM u)
|
||||
RETURNING %(tenant_id)s AS tenant_id"""
|
||||
else:
|
||||
query = """\
|
||||
WITH t AS (
|
||||
INSERT INTO public.tenants (name, version_number, edition)
|
||||
VALUES (%(companyName)s, %(versionNumber)s, 'ee')
|
||||
RETURNING tenant_id, api_key
|
||||
),
|
||||
u AS (
|
||||
INSERT INTO public.users (tenant_id, email, role, name, data)
|
||||
VALUES ((SELECT tenant_id FROM t), %(email)s, 'owner', %(fullname)s,%(data)s)
|
||||
RETURNING user_id,email,role,name
|
||||
),
|
||||
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)), FALSE)
|
||||
)
|
||||
INSERT INTO public.projects (tenant_id, name, active)
|
||||
VALUES ((SELECT t.tenant_id FROM t), %(projectName)s, TRUE)
|
||||
RETURNING tenant_id,project_id, (SELECT api_key FROM t) AS api_key;"""
|
||||
),
|
||||
u AS (
|
||||
INSERT INTO public.users (tenant_id, email, role, name, data)
|
||||
VALUES ((SELECT tenant_id FROM t), %(email)s, 'owner', %(fullname)s,%(data)s)
|
||||
RETURNING user_id,email,role,name
|
||||
),
|
||||
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)), FALSE)
|
||||
)
|
||||
INSERT INTO public.projects (tenant_id, name, active)
|
||||
VALUES ((SELECT t.tenant_id FROM t), %(projectName)s, TRUE)
|
||||
RETURNING tenant_id,project_id, (SELECT api_key FROM t) AS api_key;"""
|
||||
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute(cur.mogrify(query, params))
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ def update(tenant_id, user_id, data):
|
|||
return edit_client(tenant_id=tenant_id, changes=changes)
|
||||
|
||||
|
||||
def get_tenants():
|
||||
def tenants_exists():
|
||||
with pg_client.PostgresClient() as cur:
|
||||
cur.execute(f"SELECT name FROM public.tenants")
|
||||
return helper.list_to_camel_case(cur.fetchall())
|
||||
cur.execute(f"SELECT EXISTS(SELECT 1 FROM public.tenants)")
|
||||
return cur.fetchone()["exists"]
|
||||
|
|
|
|||
|
|
@ -440,11 +440,11 @@ 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):
|
||||
def set_password_invitation(tenant_id, 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)
|
||||
user = update(tenant_id=tenant_id, user_id=user_id, changes=changes)
|
||||
r = authenticate(user['email'], new_password)
|
||||
|
||||
tenant_id = r.pop("tenantId")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue