feat(chalice): refactored&cleaned endpoints

feat(chalice): notes slack notification
This commit is contained in:
Taha Yassine Kraiem 2022-10-07 16:04:07 +02:00
parent 2492867e9c
commit e8a288ba8a
8 changed files with 204 additions and 123 deletions

View file

@ -61,10 +61,10 @@ def __get_live_sessions_ws(project_id, data):
return {"total": 0, "sessions": []}
live_peers = results.json().get("data", [])
except requests.exceptions.Timeout:
print("Timeout getting Assist response")
print("!! Timeout getting Assist response")
live_peers = {"total": 0, "sessions": []}
except Exception as e:
print("issue getting Live-Assist response")
print("!! Issue getting Live-Assist response")
print(str(e))
print("expected JSON, received:")
try:
@ -116,7 +116,7 @@ def get_live_session_by_id(project_id, session_id):
print("!! Timeout getting Assist response")
return None
except Exception as e:
print("issue getting Assist response")
print("!! Issue getting Assist response")
print(str(e))
print("expected JSON, received:")
try:
@ -139,10 +139,10 @@ def is_live(project_id, session_id, project_key=None):
return False
results = results.json().get("data")
except requests.exceptions.Timeout:
print("Timeout getting Assist response")
print("!! Timeout getting Assist response")
return False
except Exception as e:
print("issue getting Assist response")
print("!! Issue getting Assist response")
print(str(e))
print("expected JSON, received:")
try:
@ -168,10 +168,10 @@ def autocomplete(project_id, q: str, key: str = None):
return {"errors": [f"Something went wrong wile calling assist:{results.text}"]}
results = results.json().get("data", [])
except requests.exceptions.Timeout:
print("Timeout getting Assist response")
print("!! Timeout getting Assist response")
return {"errors": ["Assist request timeout"]}
except Exception as e:
print("issue getting Assist response")
print("!! Issue getting Assist response")
print(str(e))
print("expected JSON, received:")
try:
@ -250,7 +250,7 @@ def session_exists(project_id, session_id):
print("!! Timeout getting Assist response")
return False
except Exception as e:
print("issue getting Assist response")
print("!! Issue getting Assist response")
print(str(e))
print("expected JSON, received:")
try:

View file

@ -35,24 +35,57 @@ class Slack:
return True
@classmethod
def send_text(cls, tenant_id, webhook_id, text, **args):
def send_text_attachments(cls, tenant_id, webhook_id, text, **args):
integration = cls.__get(tenant_id=tenant_id, integration_id=webhook_id)
if integration is None:
return {"errors": ["slack integration not found"]}
print("====> sending slack notification")
r = requests.post(
url=integration["endpoint"],
json={
"attachments": [
{
"text": text,
"ts": datetime.now().timestamp(),
**args
}
]
})
print(r)
print(r.text)
try:
r = requests.post(
url=integration["endpoint"],
json={
"attachments": [
{
"text": text,
"ts": datetime.now().timestamp(),
**args
}
]
},
timeout=5)
if r.status_code != 200:
print(f"!! issue sending slack text attachments; webhookId:{webhook_id} code:{r.status_code}")
print(r.text)
return None
except requests.exceptions.Timeout:
print(f"!! Timeout sending slack text attachments webhookId:{webhook_id}")
return None
except Exception as e:
print(f"!! Issue sending slack text attachments webhookId:{webhook_id}")
print(str(e))
return None
return {"data": r.text}
@classmethod
def send_raw(cls, tenant_id, webhook_id, body):
integration = cls.__get(tenant_id=tenant_id, integration_id=webhook_id)
if integration is None:
return {"errors": ["slack integration not found"]}
try:
r = requests.post(
url=integration["endpoint"],
json=body,
timeout=5)
if r.status_code != 200:
print(f"!! issue sending slack raw; webhookId:{webhook_id} code:{r.status_code}")
print(r.text)
return None
except requests.exceptions.Timeout:
print(f"!! Timeout sending slack raw webhookId:{webhook_id}")
return None
except Exception as e:
print(f"!! Issue sending slack raw webhookId:{webhook_id}")
print(str(e))
return None
return {"data": r.text}
@classmethod

View file

@ -1,9 +1,34 @@
from urllib.parse import urljoin
from decouple import config
import schemas
from chalicelib.core import sessions
from chalicelib.core.collaboration_slack import Slack
from chalicelib.utils import pg_client, helper
from chalicelib.utils.TimeUTC import TimeUTC
def get_note(tenant_id, project_id, user_id, note_id, share=None):
with pg_client.PostgresClient() as cur:
query = cur.mogrify(f"""SELECT sessions_notes.*, users.name AS creator_name
{",(SELECT name FROM users WHERE user_id=%(share)s AND deleted_at ISNULL) AS share_name" if share else ""}
FROM sessions_notes INNER JOIN users USING (user_id)
WHERE sessions_notes.project_id = %(project_id)s
AND sessions_notes.note_id = %(note_id)s
AND sessions_notes.deleted_at IS NULL
AND (sessions_notes.user_id = %(user_id)s OR sessions_notes.is_public);""",
{"project_id": project_id, "user_id": user_id, "tenant_id": tenant_id,
"note_id": note_id, "share": share})
cur.execute(query=query)
row = cur.fetchone()
row = helper.dict_to_camel_case(row)
if row:
row["createdAt"] = TimeUTC.datetime_to_timestamp(row["createdAt"])
return row
def get_session_notes(tenant_id, project_id, session_id, user_id):
with pg_client.PostgresClient() as cur:
query = cur.mogrify(f"""SELECT sessions_notes.*
@ -80,8 +105,7 @@ def edit(tenant_id, user_id, project_id, note_id, data: schemas.SessionUpdateNot
sub_query.append("timestamp = %(timestamp)s")
with pg_client.PostgresClient() as cur:
cur.execute(
cur.mogrify(f"""\
UPDATE public.sessions_notes
cur.mogrify(f"""UPDATE public.sessions_notes
SET
{" ,".join(sub_query)}
WHERE
@ -101,14 +125,42 @@ def edit(tenant_id, user_id, project_id, note_id, data: schemas.SessionUpdateNot
def delete(tenant_id, user_id, project_id, note_id):
with pg_client.PostgresClient() as cur:
cur.execute(
cur.mogrify("""\
UPDATE public.sessions_notes
cur.mogrify(""" UPDATE public.sessions_notes
SET deleted_at = timezone('utc'::text, now())
WHERE
note_id = %(note_id)s
AND project_id = %(project_id)s\
WHERE note_id = %(note_id)s
AND project_id = %(project_id)s
AND user_id = %(user_id)s
AND deleted_at ISNULL;""",
{"project_id": project_id, "user_id": user_id, "note_id": note_id})
)
return {"data": {"state": "success"}}
def share_to_slack(tenant_id, user_id, project_id, note_id, webhook_id):
note = get_note(tenant_id=tenant_id, project_id=project_id, user_id=user_id, note_id=note_id, share=user_id)
if note is None:
return {"errors": ["Note not found"]}
session_url = urljoin(config('SITE_URL'), f"{note['projectId']}/sessions/{note['sessionId']}")
title = f"<{session_url}|Note for session {note['sessionId']}>"
blocks = [{"type": "section",
"fields": [{"type": "mrkdwn",
"text": title}]},
{"type": "section",
"fields": [{"type": "plain_text",
"text": note["message"]}]}]
if note["tag"]:
blocks.append({"type": "context",
"elements": [{"type": "plain_text",
"text": f"Tag: *{note['tag']}*"}]})
bottom = f"Created by {note['creatorName'].capitalize()}"
if user_id != note["userId"]:
bottom += f"\nSent by {note['shareName']}: "
blocks.append({"type": "context",
"elements": [{"type": "plain_text",
"text": bottom}]})
return Slack.send_raw(
tenant_id=tenant_id,
webhook_id=webhook_id,
body={"blocks": blocks}
)

View file

@ -4,17 +4,6 @@ from decouple import config
from chalicelib.core.collaboration_slack import Slack
def send(notification, destination):
if notification is None:
return
return Slack.send_text(tenant_id=notification["tenantId"],
webhook_id=destination,
text=notification["description"] \
+ f"\n<{config('SITE_URL')}{notification['buttonUrl']}|{notification['buttonText']}>",
title=notification["title"],
title_link=notification["buttonUrl"], )
def send_batch(notifications_list):
if notifications_list is None or len(notifications_list) == 0:
return

View file

@ -1,22 +1,19 @@
from typing import Union
from decouple import config
from fastapi import Depends, Body, BackgroundTasks, HTTPException
from fastapi.responses import FileResponse
from fastapi import Depends, Body, HTTPException
from starlette import status
import schemas
from chalicelib.core import log_tool_rollbar, sourcemaps, events, sessions_assignments, projects, \
alerts, funnels, issues, integrations_manager, metadata, \
log_tool_elasticsearch, log_tool_datadog, \
log_tool_stackdriver, reset_password, sessions_favorite, \
log_tool_cloudwatch, log_tool_sentry, log_tool_sumologic, log_tools, errors, sessions, \
log_tool_stackdriver, reset_password, log_tool_cloudwatch, log_tool_sentry, log_tool_sumologic, log_tools, sessions, \
log_tool_newrelic, announcements, log_tool_bugsnag, weekly_report, integration_jira_cloud, integration_github, \
assist, heatmaps, mobile, signup, tenants, errors_viewed, boarding, notifications, webhook, users, \
custom_metrics, saved_search, integrations_global, sessions_viewed, errors_favorite
assist, mobile, signup, tenants, boarding, notifications, webhook, users, \
custom_metrics, saved_search, integrations_global
from chalicelib.core.collaboration_slack import Slack
from chalicelib.utils import email_helper, helper, captcha
from chalicelib.utils.TimeUTC import TimeUTC
from chalicelib.utils import helper, captcha
from or_dependencies import OR_context
from routers.base import get_routers
@ -52,7 +49,6 @@ def login(data: schemas.UserLoginSchema = Body(...)):
@app.post('/{projectId}/sessions/search', tags=["sessions"])
@app.post('/{projectId}/sessions/search2', tags=["sessions"])
def sessions_search(projectId: int, data: schemas.FlatSessionsSearchPayloadSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
data = sessions.search_sessions(data=data, project_id=projectId, user_id=context.user_id)
@ -100,7 +96,6 @@ def get_integrations_status(projectId: int, context: schemas.CurrentContext = De
@app.post('/{projectId}/integrations/{integration}/notify/{integrationId}/{source}/{sourceId}', tags=["integrations"])
@app.put('/{projectId}/integrations/{integration}/notify/{integrationId}/{source}/{sourceId}', tags=["integrations"])
def integration_notify(projectId: int, integration: str, integrationId: int, source: str, sourceId: str,
data: schemas.IntegrationNotificationSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
@ -129,7 +124,6 @@ def get_sentry(projectId: int, context: schemas.CurrentContext = Depends(OR_cont
@app.post('/{projectId}/integrations/sentry', tags=["integrations"])
@app.put('/{projectId}/integrations/sentry', tags=["integrations"])
def add_edit_sentry(projectId: int, data: schemas.SentrySchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": log_tool_sentry.add_edit(tenant_id=context.tenant_id, project_id=projectId, data=data.dict())}
@ -156,7 +150,6 @@ def get_datadog(projectId: int, context: schemas.CurrentContext = Depends(OR_con
@app.post('/{projectId}/integrations/datadog', tags=["integrations"])
@app.put('/{projectId}/integrations/datadog', tags=["integrations"])
def add_edit_datadog(projectId: int, data: schemas.DatadogSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": log_tool_datadog.add_edit(tenant_id=context.tenant_id, project_id=projectId, data=data.dict())}
@ -178,7 +171,6 @@ def get_stackdriver(projectId: int, context: schemas.CurrentContext = Depends(OR
@app.post('/{projectId}/integrations/stackdriver', tags=["integrations"])
@app.put('/{projectId}/integrations/stackdriver', tags=["integrations"])
def add_edit_stackdriver(projectId: int, data: schemas.StackdriverSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": log_tool_stackdriver.add_edit(tenant_id=context.tenant_id, project_id=projectId, data=data.dict())}
@ -200,7 +192,6 @@ def get_newrelic(projectId: int, context: schemas.CurrentContext = Depends(OR_co
@app.post('/{projectId}/integrations/newrelic', tags=["integrations"])
@app.put('/{projectId}/integrations/newrelic', tags=["integrations"])
def add_edit_newrelic(projectId: int, data: schemas.NewrelicSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": log_tool_newrelic.add_edit(tenant_id=context.tenant_id, project_id=projectId, data=data.dict())}
@ -222,7 +213,6 @@ def get_rollbar(projectId: int, context: schemas.CurrentContext = Depends(OR_con
@app.post('/{projectId}/integrations/rollbar', tags=["integrations"])
@app.put('/{projectId}/integrations/rollbar', tags=["integrations"])
def add_edit_rollbar(projectId: int, data: schemas.RollbarSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": log_tool_rollbar.add_edit(tenant_id=context.tenant_id, project_id=projectId, data=data.dict())}
@ -250,7 +240,6 @@ def get_bugsnag(projectId: int, context: schemas.CurrentContext = Depends(OR_con
@app.post('/{projectId}/integrations/bugsnag', tags=["integrations"])
@app.put('/{projectId}/integrations/bugsnag', tags=["integrations"])
def add_edit_bugsnag(projectId: int, data: schemas.BugsnagSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": log_tool_bugsnag.add_edit(tenant_id=context.tenant_id, project_id=projectId, data=data.dict())}
@ -280,7 +269,6 @@ def get_cloudwatch(projectId: int, context: schemas.CurrentContext = Depends(OR_
@app.post('/{projectId}/integrations/cloudwatch', tags=["integrations"])
@app.put('/{projectId}/integrations/cloudwatch', tags=["integrations"])
def add_edit_cloudwatch(projectId: int, data: schemas.CloudwatchSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": log_tool_cloudwatch.add_edit(tenant_id=context.tenant_id, project_id=projectId, data=data.dict())}
@ -308,7 +296,6 @@ def test_elasticsearch_connection(data: schemas.ElasticsearchBasicSchema = Body(
@app.post('/{projectId}/integrations/elasticsearch', tags=["integrations"])
@app.put('/{projectId}/integrations/elasticsearch', tags=["integrations"])
def add_edit_elasticsearch(projectId: int, data: schemas.ElasticsearchSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {
@ -331,7 +318,6 @@ def get_sumologic(projectId: int, context: schemas.CurrentContext = Depends(OR_c
@app.post('/{projectId}/integrations/sumologic', tags=["integrations"])
@app.put('/{projectId}/integrations/sumologic', tags=["integrations"])
def add_edit_sumologic(projectId: int, data: schemas.SumologicSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": log_tool_sumologic.add_edit(tenant_id=context.tenant_id, project_id=projectId, data=data.dict())}
@ -372,7 +358,6 @@ def get_integration_status_github(context: schemas.CurrentContext = Depends(OR_c
@app.post('/integrations/jira', tags=["integrations"])
@app.put('/integrations/jira', tags=["integrations"])
def add_edit_jira_cloud(data: schemas.JiraSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
if not data.url.endswith('atlassian.net'):
@ -386,7 +371,6 @@ def add_edit_jira_cloud(data: schemas.JiraSchema = Body(...),
@app.post('/integrations/github', tags=["integrations"])
@app.put('/integrations/github', tags=["integrations"])
def add_edit_github(data: schemas.GithubSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
error, integration = integrations_manager.get_integration(tool=integration_github.PROVIDER,
@ -461,7 +445,6 @@ def get_all_assignments(projectId: int, context: schemas.CurrentContext = Depend
@app.post('/{projectId}/sessions2/{sessionId}/assign/projects/{integrationProjectId}', tags=["assignment"])
@app.put('/{projectId}/sessions2/{sessionId}/assign/projects/{integrationProjectId}', tags=["assignment"])
def create_issue_assignment(projectId: int, sessionId: int, integrationProjectId,
data: schemas.AssignmentSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
@ -484,14 +467,12 @@ def get_gdpr(projectId: int, context: schemas.CurrentContext = Depends(OR_contex
@app.post('/{projectId}/gdpr', tags=["projects", "gdpr"])
@app.put('/{projectId}/gdpr', tags=["projects", "gdpr"])
def edit_gdpr(projectId: int, data: schemas.GdprSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": projects.edit_gdpr(project_id=projectId, gdpr=data.dict())}
@public_app.post('/password/reset-link', tags=["reset password"])
@public_app.put('/password/reset-link', tags=["reset password"])
def reset_password_handler(data: schemas.ForgetPasswordPayloadSchema = Body(...)):
if len(data.email) < 5:
return {"errors": ["please provide a valid email address"]}
@ -504,21 +485,18 @@ def get_metadata(projectId: int, context: schemas.CurrentContext = Depends(OR_co
@app.post('/{projectId}/metadata/list', tags=["metadata"])
@app.put('/{projectId}/metadata/list', tags=["metadata"])
def add_edit_delete_metadata(projectId: int, data: schemas.MetadataListSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return metadata.add_edit_delete(tenant_id=context.tenant_id, project_id=projectId, new_metas=data.list)
@app.post('/{projectId}/metadata', tags=["metadata"])
@app.put('/{projectId}/metadata', tags=["metadata"])
def add_metadata(projectId: int, data: schemas.MetadataBasicSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return metadata.add(tenant_id=context.tenant_id, project_id=projectId, new_name=data.key)
@app.post('/{projectId}/metadata/{index}', tags=["metadata"])
@app.put('/{projectId}/metadata/{index}', tags=["metadata"])
def edit_metadata(projectId: int, index: int, data: schemas.MetadataBasicSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return metadata.edit(tenant_id=context.tenant_id, project_id=projectId, index=index,
@ -552,7 +530,6 @@ def get_capture_status(projectId: int, context: schemas.CurrentContext = Depends
@app.post('/{projectId}/sample_rate', tags=["projects"])
@app.put('/{projectId}/sample_rate', tags=["projects"])
def update_capture_status(projectId: int, data: schemas.SampleRateSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": projects.update_capture_status(project_id=projectId, changes=data.dict())}
@ -574,7 +551,6 @@ def errors_merge(context: schemas.CurrentContext = Depends(OR_context)):
@app.post('/{projectId}/alerts', tags=["alerts"])
@app.put('/{projectId}/alerts', tags=["alerts"])
def create_alert(projectId: int, data: schemas.AlertSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return alerts.create(projectId, data)
@ -597,7 +573,6 @@ def get_alert(projectId: int, alertId: int, context: schemas.CurrentContext = De
@app.post('/{projectId}/alerts/{alertId}', tags=["alerts"])
@app.put('/{projectId}/alerts/{alertId}', tags=["alerts"])
def update_alert(projectId: int, alertId: int, data: schemas.AlertSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return alerts.update(alertId, data)
@ -609,7 +584,6 @@ def delete_alert(projectId: int, alertId: int, context: schemas.CurrentContext =
@app.post('/{projectId}/funnels', tags=["funnels"])
@app.put('/{projectId}/funnels', tags=["funnels"])
def add_funnel(projectId: int, data: schemas.FunnelSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return funnels.create(project_id=projectId,
@ -653,7 +627,6 @@ def get_funnel_insights(projectId: int, funnelId: int, rangeValue: str = None, s
@app.post('/{projectId}/funnels/{funnelId}/insights', tags=["funnels"])
@app.put('/{projectId}/funnels/{funnelId}/insights', tags=["funnels"])
def get_funnel_insights_on_the_fly(projectId: int, funnelId: int, data: schemas.FunnelInsightsPayloadSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return funnels.get_top_insights_on_the_fly(funnel_id=funnelId, user_id=context.user_id, project_id=projectId,
@ -668,7 +641,6 @@ def get_funnel_issues(projectId: int, funnelId, rangeValue: str = None, startDat
@app.post('/{projectId}/funnels/{funnelId}/issues', tags=["funnels"])
@app.put('/{projectId}/funnels/{funnelId}/issues', tags=["funnels"])
def get_funnel_issues_on_the_fly(projectId: int, funnelId: int, data: schemas.FunnelSearchPayloadSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": funnels.get_issues_on_the_fly(funnel_id=funnelId, user_id=context.user_id, project_id=projectId,
@ -685,7 +657,6 @@ def get_funnel_sessions(projectId: int, funnelId: int, rangeValue: str = None, s
@app.post('/{projectId}/funnels/{funnelId}/sessions', tags=["funnels"])
@app.put('/{projectId}/funnels/{funnelId}/sessions', tags=["funnels"])
def get_funnel_sessions_on_the_fly(projectId: int, funnelId: int, data: schemas.FunnelSearchPayloadSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": funnels.get_sessions_on_the_fly(funnel_id=funnelId, user_id=context.user_id, project_id=projectId,
@ -705,7 +676,6 @@ def get_funnel_issue_sessions(projectId: int, issueId: str, startDate: int = Non
@app.post('/{projectId}/funnels/{funnelId}/issues/{issueId}/sessions', tags=["funnels"])
@app.put('/{projectId}/funnels/{funnelId}/issues/{issueId}/sessions', tags=["funnels"])
def get_funnel_issue_sessions(projectId: int, funnelId: int, issueId: str,
data: schemas.FunnelSearchPayloadSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
@ -729,7 +699,6 @@ def get_funnel(projectId: int, funnelId: int, context: schemas.CurrentContext =
@app.post('/{projectId}/funnels/{funnelId}', tags=["funnels"])
@app.put('/{projectId}/funnels/{funnelId}', tags=["funnels"])
def edit_funnel(projectId: int, funnelId: int, data: schemas.UpdateFunnelSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return funnels.update(funnel_id=funnelId,
@ -762,7 +731,6 @@ def get_weekly_report_config(context: schemas.CurrentContext = Depends(OR_contex
@app.post('/config/weekly_report', tags=["weekly report config"])
@app.put('/config/weekly_report', tags=["weekly report config"])
def edit_weekly_report_config(data: schemas.WeeklyReportConfigSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": weekly_report.edit_config(user_id=context.user_id, weekly_report=data.weekly_report)}
@ -797,21 +765,19 @@ def mobile_signe(projectId: int, sessionId: int, data: schemas.MobileSignPayload
return {"data": mobile.sign_keys(project_id=projectId, session_id=sessionId, keys=data.keys)}
@public_app.put('/signup', tags=['signup'])
@public_app.post('/signup', tags=['signup'])
@public_app.put('/signup', tags=['signup'])
def signup_handler(data: schemas.UserSignupSchema = Body(...)):
return signup.create_step1(data)
@app.post('/projects', tags=['projects'])
@app.put('/projects', tags=['projects'])
def create_project(data: schemas.CreateProjectSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return projects.create(tenant_id=context.tenant_id, user_id=context.user_id, data=data)
@app.post('/projects/{projectId}', tags=['projects'])
@app.put('/projects/{projectId}', tags=['projects'])
def edit_project(projectId: int, data: schemas.CreateProjectSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return projects.edit(tenant_id=context.tenant_id, user_id=context.user_id, data=data, project_id=projectId)
@ -829,8 +795,8 @@ def generate_new_tenant_token(context: schemas.CurrentContext = Depends(OR_conte
}
@app.put('/client', tags=['client'])
@app.post('/client', tags=['client'])
@app.put('/client', tags=['client'])
def edit_client(data: schemas.UpdateTenantSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return tenants.update(tenant_id=context.tenant_id, user_id=context.user_id, data=data)
@ -852,7 +818,6 @@ def view_notifications(notificationId: int, context: schemas.CurrentContext = De
@app.post('/notifications/view', tags=['notifications'])
@app.put('/notifications/view', tags=['notifications'])
def batch_view_notifications(data: schemas.NotificationsViewSchema,
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": notifications.view_notification(notification_ids=data.ids,
@ -903,7 +868,6 @@ def delete_slack_integration(integrationId: int, context: schemas.CurrentContext
@app.post('/webhooks', tags=["webhooks"])
@app.put('/webhooks', tags=["webhooks"])
def add_edit_webhook(data: schemas.CreateEditWebhookSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": webhook.add_edit(tenant_id=context.tenant_id, data=data.dict(), replace_none=True)}
@ -940,7 +904,6 @@ def generate_new_user_token(context: schemas.CurrentContext = Depends(OR_context
@app.post('/account/password', tags=["account"])
@app.put('/account/password', tags=["account"])
def change_client_password(data: schemas.EditUserPasswordSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return users.change_password(email=context.email, old_password=data.old_password,
@ -949,7 +912,6 @@ def change_client_password(data: schemas.EditUserPasswordSchema = Body(...),
@app.post('/{projectId}/saved_search', tags=["savedSearch"])
@app.put('/{projectId}/saved_search', tags=["savedSearch"])
def add_saved_search(projectId: int, data: schemas.SavedSearchSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return saved_search.create(project_id=projectId, user_id=context.user_id, data=data)
@ -966,7 +928,6 @@ def get_saved_search(projectId: int, search_id: int, context: schemas.CurrentCon
@app.post('/{projectId}/saved_search/{search_id}', tags=["savedSearch"])
@app.put('/{projectId}/saved_search/{search_id}', tags=["savedSearch"])
def update_saved_search(projectId: int, search_id: int, data: schemas.SavedSearchSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": saved_search.update(user_id=context.user_id, search_id=search_id, data=data, project_id=projectId)}

View file

@ -46,7 +46,6 @@ def get_account(context: schemas.CurrentContext = Depends(OR_context)):
@app.post('/account', tags=["account"])
@app.put('/account', tags=["account"])
def edit_account(data: schemas.EditUserSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return users.edit(tenant_id=context.tenant_id, user_id_to_update=context.user_id, changes=data,
@ -70,8 +69,8 @@ def get_project(projectId: int, context: schemas.CurrentContext = Depends(OR_con
return {"data": data}
@app.put('/integrations/slack', tags=['integrations'])
@app.post('/integrations/slack', tags=['integrations'])
@app.put('/integrations/slack', tags=['integrations'])
def add_slack_client(data: schemas.AddSlackSchema, context: schemas.CurrentContext = Depends(OR_context)):
n = Slack.add_channel(tenant_id=context.tenant_id, url=data.url, name=data.name)
if n is None:
@ -81,7 +80,6 @@ def add_slack_client(data: schemas.AddSlackSchema, context: schemas.CurrentConte
return {"data": n}
@app.put('/integrations/slack/{integrationId}', tags=['integrations'])
@app.post('/integrations/slack/{integrationId}', tags=['integrations'])
def edit_slack_integration(integrationId: int, data: schemas.EditSlackSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
@ -98,7 +96,6 @@ def edit_slack_integration(integrationId: int, data: schemas.EditSlackSchema = B
@app.post('/client/members', tags=["client"])
@app.put('/client/members', tags=["client"])
def add_member(background_tasks: BackgroundTasks, data: schemas.CreateMemberSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return users.create_member(tenant_id=context.tenant_id, user_id=context.user_id, data=data.dict(),
@ -123,7 +120,6 @@ def process_invitation_link(token: str):
@public_app.post('/password/reset', tags=["users"])
@public_app.put('/password/reset', tags=["users"])
def change_password_by_invitation(data: schemas.EditPasswordByInvitationSchema = Body(...)):
if data is None or len(data.invitation) < 64 or len(data.passphrase) < 8:
return {"errors": ["please provide a valid invitation & pass"]}
@ -136,7 +132,6 @@ def change_password_by_invitation(data: schemas.EditPasswordByInvitationSchema =
return users.set_password_invitation(new_password=data.password, user_id=user["userId"])
@app.put('/client/members/{memberId}', tags=["client"])
@app.post('/client/members/{memberId}', tags=["client"])
def edit_member(memberId: int, data: schemas.EditMemberSchema,
context: schemas.CurrentContext = Depends(OR_context)):
@ -358,9 +353,7 @@ def assign_session(projectId: int, sessionId: int, issueId: str,
@app.post('/{projectId}/sessions/{sessionId}/assign/{issueId}/comment', tags=["sessions", "issueTracking"])
@app.put('/{projectId}/sessions/{sessionId}/assign/{issueId}/comment', tags=["sessions", "issueTracking"])
@app.post('/{projectId}/sessions2/{sessionId}/assign/{issueId}/comment', tags=["sessions", "issueTracking"])
@app.put('/{projectId}/sessions2/{sessionId}/assign/{issueId}/comment', tags=["sessions", "issueTracking"])
def comment_assignment(projectId: int, sessionId: int, issueId: str, data: schemas.CommentAssignmentSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
data = sessions_assignments.comment(tenant_id=context.tenant_id, project_id=projectId,
@ -374,9 +367,10 @@ def comment_assignment(projectId: int, sessionId: int, issueId: str, data: schem
@app.post('/{projectId}/sessions/{sessionId}/notes', tags=["sessions", "notes"])
@app.put('/{projectId}/sessions/{sessionId}/notes', tags=["sessions", "notes"])
def create_note(projectId: int, sessionId: int, data: schemas.SessionNoteSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
if not sessions.session_exists(project_id=projectId, session_id=sessionId):
return {"errors": ["Session not found"]}
data = sessions_notes.create(tenant_id=context.tenant_id, project_id=projectId,
session_id=sessionId, user_id=context.user_id, data=data)
if "errors" in data.keys():
@ -398,7 +392,6 @@ def get_session_notes(projectId: int, sessionId: int, context: schemas.CurrentCo
@app.post('/{projectId}/notes/{noteId}', tags=["sessions", "notes"])
@app.put('/{projectId}/notes/{noteId}', tags=["sessions", "notes"])
def edit_note(projectId: int, noteId: int, data: schemas.SessionUpdateNoteSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
data = sessions_notes.edit(tenant_id=context.tenant_id, project_id=projectId, user_id=context.user_id,
@ -417,6 +410,13 @@ def delete_note(projectId: int, noteId: int, context: schemas.CurrentContext = D
return data
@app.post('/{projectId}/notes/{noteId}/slack/{webhookId}', tags=["sessions", "notes"])
def share_note_to_slack(projectId: int, noteId: int, webhookId: int,
context: schemas.CurrentContext = Depends(OR_context)):
return sessions_notes.share_to_slack(tenant_id=context.tenant_id, project_id=projectId, user_id=context.user_id,
note_id=noteId, webhook_id=webhookId)
@app.post('/{projectId}/notes', tags=["sessions", "notes"])
def get_all_notes(projectId: int, data: schemas.SearchNoteSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
@ -424,6 +424,4 @@ def get_all_notes(projectId: int, data: schemas.SearchNoteSchema = Body(...),
user_id=context.user_id, data=data)
if "errors" in data:
return data
return {
'data': data
}
return {'data': data}

View file

@ -1,9 +1,35 @@
from urllib.parse import urljoin
from decouple import config
import schemas
from chalicelib.core import sessions
from chalicelib.core.collaboration_slack import Slack
from chalicelib.utils import pg_client, helper
from chalicelib.utils.TimeUTC import TimeUTC
def get_note(tenant_id, project_id, user_id, note_id, share=None):
with pg_client.PostgresClient() as cur:
query = cur.mogrify(f"""SELECT sessions_notes.*, users.name AS creator_name
{",(SELECT name FROM users WHERE tenant_id=%(tenant_id)s AND user_id=%(share)s) AS share_name" if share else ""}
FROM sessions_notes INNER JOIN users USING (user_id)
WHERE sessions_notes.project_id = %(project_id)s
AND sessions_notes.note_id = %(note_id)s
AND sessions_notes.deleted_at IS NULL
AND (sessions_notes.user_id = %(user_id)s
OR sessions_notes.is_public AND users.tenant_id = %(tenant_id)s);""",
{"project_id": project_id, "user_id": user_id, "tenant_id": tenant_id,
"note_id": note_id, "share": share})
cur.execute(query=query)
row = cur.fetchone()
row = helper.dict_to_camel_case(row)
if row:
row["createdAt"] = TimeUTC.datetime_to_timestamp(row["createdAt"])
return row
def get_session_notes(tenant_id, project_id, session_id, user_id):
with pg_client.PostgresClient() as cur:
query = cur.mogrify(f"""SELECT sessions_notes.*
@ -83,8 +109,7 @@ def edit(tenant_id, user_id, project_id, note_id, data: schemas.SessionUpdateNot
sub_query.append("timestamp = %(timestamp)s")
with pg_client.PostgresClient() as cur:
cur.execute(
cur.mogrify(f"""\
UPDATE public.sessions_notes
cur.mogrify(f"""UPDATE public.sessions_notes
SET
{" ,".join(sub_query)}
WHERE
@ -104,14 +129,42 @@ def edit(tenant_id, user_id, project_id, note_id, data: schemas.SessionUpdateNot
def delete(tenant_id, user_id, project_id, note_id):
with pg_client.PostgresClient() as cur:
cur.execute(
cur.mogrify("""\
UPDATE public.sessions_notes
cur.mogrify(""" UPDATE public.sessions_notes
SET deleted_at = timezone('utc'::text, now())
WHERE
note_id = %(note_id)s
AND project_id = %(project_id)s\
WHERE note_id = %(note_id)s
AND project_id = %(project_id)s
AND user_id = %(user_id)s
AND deleted_at ISNULL;""",
{"project_id": project_id, "user_id": user_id, "note_id": note_id})
)
return {"data": {"state": "success"}}
def share_to_slack(tenant_id, user_id, project_id, note_id, webhook_id):
note = get_note(tenant_id=tenant_id, project_id=project_id, user_id=user_id, note_id=note_id, share=user_id)
if note is None:
return {"errors": ["Note not found"]}
session_url = urljoin(config('SITE_URL'), f"{note['projectId']}/sessions/{note['sessionId']}")
title = f"<{session_url}|Note for session {note['sessionId']}>"
blocks = [{"type": "section",
"fields": [{"type": "mrkdwn",
"text": title}]},
{"type": "section",
"fields": [{"type": "plain_text",
"text": note["message"]}]}]
if note["tag"]:
blocks.append({"type": "context",
"elements": [{"type": "plain_text",
"text": f"Tag: *{note['tag']}*"}]})
bottom = f"Created by {note['creatorName'].capitalize()}"
if user_id != note["userId"]:
bottom += f"\nSent by {note['shareName']}: "
blocks.append({"type": "context",
"elements": [{"type": "plain_text",
"text": bottom}]})
return Slack.send_raw(
tenant_id=tenant_id,
webhook_id=webhook_id,
body={"blocks": blocks}
)

View file

@ -50,7 +50,6 @@ def get_account(context: schemas.CurrentContext = Depends(OR_context)):
@app.post('/account', tags=["account"])
@app.put('/account', tags=["account"])
def edit_account(data: schemas_ee.EditUserSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return users.edit(tenant_id=context.tenant_id, user_id_to_update=context.user_id, changes=data,
@ -74,8 +73,8 @@ def get_project(projectId: int, context: schemas.CurrentContext = Depends(OR_con
return {"data": data}
@app.put('/integrations/slack', tags=['integrations'])
@app.post('/integrations/slack', tags=['integrations'])
@app.put('/integrations/slack', tags=['integrations'])
def add_slack_client(data: schemas.AddSlackSchema, context: schemas.CurrentContext = Depends(OR_context)):
n = Slack.add_channel(tenant_id=context.tenant_id, url=data.url, name=data.name)
if n is None:
@ -85,7 +84,6 @@ def add_slack_client(data: schemas.AddSlackSchema, context: schemas.CurrentConte
return {"data": n}
@app.put('/integrations/slack/{integrationId}', tags=['integrations'])
@app.post('/integrations/slack/{integrationId}', tags=['integrations'])
def edit_slack_integration(integrationId: int, data: schemas.EditSlackSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
@ -102,7 +100,6 @@ def edit_slack_integration(integrationId: int, data: schemas.EditSlackSchema = B
@app.post('/client/members', tags=["client"])
@app.put('/client/members', tags=["client"])
def add_member(background_tasks: BackgroundTasks, data: schemas_ee.CreateMemberSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return users.create_member(tenant_id=context.tenant_id, user_id=context.user_id, data=data.dict(),
@ -127,7 +124,6 @@ def process_invitation_link(token: str):
@public_app.post('/password/reset', tags=["users"])
@public_app.put('/password/reset', tags=["users"])
def change_password_by_invitation(data: schemas.EditPasswordByInvitationSchema = Body(...)):
if data is None or len(data.invitation) < 64 or len(data.passphrase) < 8:
return {"errors": ["please provide a valid invitation & pass"]}
@ -140,7 +136,6 @@ def change_password_by_invitation(data: schemas.EditPasswordByInvitationSchema =
return users.set_password_invitation(new_password=data.password, user_id=user["userId"], tenant_id=user["tenantId"])
@app.put('/client/members/{memberId}', tags=["client"])
@app.post('/client/members/{memberId}', tags=["client"])
def edit_member(memberId: int, data: schemas_ee.EditMemberSchema,
context: schemas.CurrentContext = Depends(OR_context)):
@ -375,12 +370,8 @@ def assign_session(projectId: int, sessionId: int, issueId: str,
@app.post('/{projectId}/sessions/{sessionId}/assign/{issueId}/comment', tags=["sessions", "issueTracking"],
dependencies=[OR_scope(Permissions.session_replay)])
@app.put('/{projectId}/sessions/{sessionId}/assign/{issueId}/comment', tags=["sessions", "issueTracking"],
dependencies=[OR_scope(Permissions.session_replay)])
@app.post('/{projectId}/sessions2/{sessionId}/assign/{issueId}/comment', tags=["sessions", "issueTracking"],
dependencies=[OR_scope(Permissions.session_replay)])
@app.put('/{projectId}/sessions2/{sessionId}/assign/{issueId}/comment', tags=["sessions", "issueTracking"],
dependencies=[OR_scope(Permissions.session_replay)])
def comment_assignment(projectId: int, sessionId: int, issueId: str, data: schemas.CommentAssignmentSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
data = sessions_assignments.comment(tenant_id=context.tenant_id, project_id=projectId,
@ -395,10 +386,10 @@ def comment_assignment(projectId: int, sessionId: int, issueId: str, data: schem
@app.post('/{projectId}/sessions/{sessionId}/notes', tags=["sessions", "notes"],
dependencies=[OR_scope(Permissions.session_replay)])
@app.put('/{projectId}/sessions/{sessionId}/notes', tags=["sessions", "notes"],
dependencies=[OR_scope(Permissions.session_replay)])
def create_note(projectId: int, sessionId: int, data: schemas.SessionNoteSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
if not sessions.session_exists(project_id=projectId, session_id=sessionId):
return {"errors": ["Session not found"]}
data = sessions_notes.create(tenant_id=context.tenant_id, project_id=projectId,
session_id=sessionId, user_id=context.user_id, data=data)
if "errors" in data.keys():
@ -422,7 +413,6 @@ def get_session_notes(projectId: int, sessionId: int, context: schemas.CurrentCo
@app.post('/{projectId}/notes/{noteId}', tags=["sessions", "notes"],
dependencies=[OR_scope(Permissions.session_replay)])
@app.put('/{projectId}/notes/{noteId}', tags=["sessions", "notes"], dependencies=[OR_scope(Permissions.session_replay)])
def edit_note(projectId: int, noteId: int, data: schemas.SessionUpdateNoteSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
data = sessions_notes.edit(tenant_id=context.tenant_id, project_id=projectId, user_id=context.user_id,
@ -442,6 +432,13 @@ def delete_note(projectId: int, noteId: int, context: schemas.CurrentContext = D
return data
@app.post('/{projectId}/notes/{noteId}/slack/{webhookId}', tags=["sessions", "notes"])
def share_note_to_slack(projectId: int, noteId: int, webhookId: int,
context: schemas.CurrentContext = Depends(OR_context)):
return sessions_notes.share_to_slack(tenant_id=context.tenant_id, project_id=projectId, user_id=context.user_id,
note_id=noteId, webhook_id=webhookId)
@app.post('/{projectId}/notes', tags=["sessions", "notes"], dependencies=[OR_scope(Permissions.session_replay)])
def get_all_notes(projectId: int, data: schemas.SearchNoteSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
@ -449,6 +446,4 @@ def get_all_notes(projectId: int, data: schemas.SearchNoteSchema = Body(...),
user_id=context.user_id)
if "errors" in data:
return data
return {
'data': data
}
return {'data': data}