mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
Merge branch 'develop' of github.com:makeplane/plane into feat/notifications
This commit is contained in:
commit
8260e2f897
@ -21,10 +21,12 @@ NEXT_PUBLIC_TRACK_EVENTS=0
|
|||||||
NEXT_PUBLIC_SLACK_CLIENT_ID=""
|
NEXT_PUBLIC_SLACK_CLIENT_ID=""
|
||||||
|
|
||||||
# Backend
|
# Backend
|
||||||
|
|
||||||
# Debug value for api server use it as 0 for production use
|
# Debug value for api server use it as 0 for production use
|
||||||
DEBUG=0
|
DEBUG=0
|
||||||
|
|
||||||
|
# Error logs
|
||||||
|
SENTRY_DSN=""
|
||||||
|
|
||||||
# Database Settings
|
# Database Settings
|
||||||
PGUSER="plane"
|
PGUSER="plane"
|
||||||
PGPASSWORD="plane"
|
PGPASSWORD="plane"
|
||||||
|
@ -22,7 +22,7 @@ from plane.db.models import (
|
|||||||
State,
|
State,
|
||||||
IssueLink,
|
IssueLink,
|
||||||
IssueAttachment,
|
IssueAttachment,
|
||||||
IssueActivity,
|
ProjectMember,
|
||||||
)
|
)
|
||||||
from plane.api.serializers import (
|
from plane.api.serializers import (
|
||||||
IssueSerializer,
|
IssueSerializer,
|
||||||
@ -246,13 +246,28 @@ class InboxIssueViewSet(BaseViewSet):
|
|||||||
inbox_issue = InboxIssue.objects.get(
|
inbox_issue = InboxIssue.objects.get(
|
||||||
pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id
|
pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id
|
||||||
)
|
)
|
||||||
|
# Get the project member
|
||||||
|
project_member = ProjectMember.objects.get(workspace__slug=slug, project_id=project_id, member=request.user)
|
||||||
|
# Only project members admins and created_by users can access this endpoint
|
||||||
|
if project_member.role <= 10 and str(inbox_issue.created_by_id) != str(request.user.id):
|
||||||
|
return Response({"error": "You cannot edit inbox issues"}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
# Get issue data
|
||||||
issue_data = request.data.pop("issue", False)
|
issue_data = request.data.pop("issue", False)
|
||||||
|
|
||||||
if bool(issue_data):
|
if bool(issue_data):
|
||||||
issue = Issue.objects.get(
|
issue = Issue.objects.get(
|
||||||
pk=inbox_issue.issue_id, workspace__slug=slug, project_id=project_id
|
pk=inbox_issue.issue_id, workspace__slug=slug, project_id=project_id
|
||||||
)
|
)
|
||||||
|
# Only allow guests and viewers to edit name and description
|
||||||
|
if project_member <= 10:
|
||||||
|
# viewers and guests since only viewers and guests
|
||||||
|
issue_data = {
|
||||||
|
"name": issue_data.get("name", issue.name),
|
||||||
|
"description_html": issue_data.get("description_html", issue.description_html),
|
||||||
|
"description": issue_data.get("description", issue.description)
|
||||||
|
}
|
||||||
|
|
||||||
issue_serializer = IssueCreateSerializer(
|
issue_serializer = IssueCreateSerializer(
|
||||||
issue, data=issue_data, partial=True
|
issue, data=issue_data, partial=True
|
||||||
)
|
)
|
||||||
@ -279,6 +294,8 @@ class InboxIssueViewSet(BaseViewSet):
|
|||||||
issue_serializer.errors, status=status.HTTP_400_BAD_REQUEST
|
issue_serializer.errors, status=status.HTTP_400_BAD_REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Only project admins and members can edit inbox issue attributes
|
||||||
|
if project_member.role > 10:
|
||||||
serializer = InboxIssueSerializer(
|
serializer = InboxIssueSerializer(
|
||||||
inbox_issue, data=request.data, partial=True
|
inbox_issue, data=request.data, partial=True
|
||||||
)
|
)
|
||||||
@ -319,6 +336,8 @@ class InboxIssueViewSet(BaseViewSet):
|
|||||||
|
|
||||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
else:
|
||||||
|
return Response(InboxIssueSerializer(inbox_issue).data, status=status.HTTP_200_OK)
|
||||||
except InboxIssue.DoesNotExist:
|
except InboxIssue.DoesNotExist:
|
||||||
return Response(
|
return Response(
|
||||||
{"error": "Inbox Issue does not exist"},
|
{"error": "Inbox Issue does not exist"},
|
||||||
@ -347,3 +366,25 @@ class InboxIssueViewSet(BaseViewSet):
|
|||||||
{"error": "Something went wrong please try again later"},
|
{"error": "Something went wrong please try again later"},
|
||||||
status=status.HTTP_400_BAD_REQUEST,
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def destroy(self, request, slug, project_id, inbox_id, pk):
|
||||||
|
try:
|
||||||
|
inbox_issue = InboxIssue.objects.get(
|
||||||
|
pk=pk, workspace__slug=slug, project_id=project_id, inbox_id=inbox_id
|
||||||
|
)
|
||||||
|
# Get the project member
|
||||||
|
project_member = ProjectMember.objects.get(workspace__slug=slug, project_id=project_id, member=request.user)
|
||||||
|
|
||||||
|
if project_member.role <= 10 and str(inbox_issue.created_by_id) != str(request.user.id):
|
||||||
|
return Response({"error": "You cannot delete inbox issue"}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
inbox_issue.delete()
|
||||||
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||||
|
except InboxIssue.DoesNotExist:
|
||||||
|
return Response({"error": "Inbox Issue does not exists"}, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
except Exception as e:
|
||||||
|
capture_exception(e)
|
||||||
|
return Response(
|
||||||
|
{"error": "Something went wrong please try again later"},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
|
)
|
@ -592,6 +592,20 @@ class SubIssuesEndpoint(BaseAPIView):
|
|||||||
.annotate(count=Func(F("id"), function="Count"))
|
.annotate(count=Func(F("id"), function="Count"))
|
||||||
.values("count")
|
.values("count")
|
||||||
)
|
)
|
||||||
|
.annotate(
|
||||||
|
link_count=IssueLink.objects.filter(issue=OuterRef("id"))
|
||||||
|
.order_by()
|
||||||
|
.annotate(count=Func(F("id"), function="Count"))
|
||||||
|
.values("count")
|
||||||
|
)
|
||||||
|
.annotate(
|
||||||
|
attachment_count=IssueAttachment.objects.filter(
|
||||||
|
issue=OuterRef("id")
|
||||||
|
)
|
||||||
|
.order_by()
|
||||||
|
.annotate(count=Func(F("id"), function="Count"))
|
||||||
|
.values("count")
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
state_distribution = (
|
state_distribution = (
|
||||||
|
@ -98,20 +98,6 @@ class UpdateUserOnBoardedEndpoint(BaseAPIView):
|
|||||||
user = User.objects.get(pk=request.user.id)
|
user = User.objects.get(pk=request.user.id)
|
||||||
user.is_onboarded = request.data.get("is_onboarded", False)
|
user.is_onboarded = request.data.get("is_onboarded", False)
|
||||||
user.save()
|
user.save()
|
||||||
|
|
||||||
if user.last_workspace_id is not None:
|
|
||||||
user_role = WorkspaceMember.objects.filter(
|
|
||||||
workspace_id=user.last_workspace_id, member=request.user.id
|
|
||||||
).first()
|
|
||||||
return Response(
|
|
||||||
{
|
|
||||||
"message": "Updated successfully",
|
|
||||||
"role": user_role.company_role
|
|
||||||
if user_role is not None
|
|
||||||
else None,
|
|
||||||
},
|
|
||||||
status=status.HTTP_200_OK,
|
|
||||||
)
|
|
||||||
return Response(
|
return Response(
|
||||||
{"message": "Updated successfully"}, status=status.HTTP_200_OK
|
{"message": "Updated successfully"}, status=status.HTTP_200_OK
|
||||||
)
|
)
|
||||||
|
@ -169,6 +169,8 @@ def analytic_export_task(email, data, slug):
|
|||||||
msg.send(fail_silently=False)
|
msg.send(fail_silently=False)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
# Print logs if in DEBUG mode
|
||||||
|
if settings.DEBUG:
|
||||||
print(e)
|
print(e)
|
||||||
capture_exception(e)
|
capture_exception(e)
|
||||||
return
|
return
|
||||||
|
@ -39,5 +39,8 @@ def email_verification(first_name, email, token, current_site):
|
|||||||
msg.send()
|
msg.send()
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
# Print logs if in DEBUG mode
|
||||||
|
if settings.DEBUG:
|
||||||
|
print(e)
|
||||||
capture_exception(e)
|
capture_exception(e)
|
||||||
return
|
return
|
||||||
|
@ -37,5 +37,8 @@ def forgot_password(first_name, email, uidb64, token, current_site):
|
|||||||
msg.send()
|
msg.send()
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
# Print logs if in DEBUG mode
|
||||||
|
if settings.DEBUG:
|
||||||
|
print(e)
|
||||||
capture_exception(e)
|
capture_exception(e)
|
||||||
return
|
return
|
||||||
|
@ -175,5 +175,8 @@ def service_importer(service, importer_id):
|
|||||||
importer = Importer.objects.get(pk=importer_id)
|
importer = Importer.objects.get(pk=importer_id)
|
||||||
importer.status = "failed"
|
importer.status = "failed"
|
||||||
importer.save()
|
importer.save()
|
||||||
|
# Print logs if in DEBUG mode
|
||||||
|
if settings.DEBUG:
|
||||||
|
print(e)
|
||||||
capture_exception(e)
|
capture_exception(e)
|
||||||
return
|
return
|
||||||
|
@ -1047,5 +1047,8 @@ def issue_activity(
|
|||||||
|
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
# Print logs if in DEBUG mode
|
||||||
|
if settings.DEBUG:
|
||||||
|
print(e)
|
||||||
capture_exception(e)
|
capture_exception(e)
|
||||||
return
|
return
|
||||||
|
@ -31,4 +31,7 @@ def magic_link(email, key, token, current_site):
|
|||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
capture_exception(e)
|
capture_exception(e)
|
||||||
|
# Print logs if in DEBUG mode
|
||||||
|
if settings.DEBUG:
|
||||||
|
print(e)
|
||||||
return
|
return
|
||||||
|
@ -50,5 +50,8 @@ def project_invitation(email, project_id, token, current_site):
|
|||||||
except (Project.DoesNotExist, ProjectMemberInvite.DoesNotExist) as e:
|
except (Project.DoesNotExist, ProjectMemberInvite.DoesNotExist) as e:
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
# Print logs if in DEBUG mode
|
||||||
|
if settings.DEBUG:
|
||||||
|
print(e)
|
||||||
capture_exception(e)
|
capture_exception(e)
|
||||||
return
|
return
|
||||||
|
@ -29,5 +29,8 @@ def send_welcome_slack(user_id, created, message):
|
|||||||
print(f"Got an error: {e.response['error']}")
|
print(f"Got an error: {e.response['error']}")
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
# Print logs if in DEBUG mode
|
||||||
|
if settings.DEBUG:
|
||||||
|
print(e)
|
||||||
capture_exception(e)
|
capture_exception(e)
|
||||||
return
|
return
|
||||||
|
@ -66,5 +66,8 @@ def workspace_invitation(email, workspace_id, token, current_site, invitor):
|
|||||||
except (Workspace.DoesNotExist, WorkspaceMemberInvite.DoesNotExist) as e:
|
except (Workspace.DoesNotExist, WorkspaceMemberInvite.DoesNotExist) as e:
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
# Print logs if in DEBUG mode
|
||||||
|
if settings.DEBUG:
|
||||||
|
print(e)
|
||||||
capture_exception(e)
|
capture_exception(e)
|
||||||
return
|
return
|
||||||
|
@ -98,7 +98,7 @@ export const InboxFiltersList = () => {
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setFilters({
|
setFilters({
|
||||||
priority: null,
|
inbox_status: null,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
@ -28,6 +28,8 @@ services:
|
|||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
|
DEBUG: ${DEBUG}
|
||||||
|
SENTRY_DSN: ${SENTRY_DSN}
|
||||||
DJANGO_SETTINGS_MODULE: plane.settings.production
|
DJANGO_SETTINGS_MODULE: plane.settings.production
|
||||||
DATABASE_URL: postgres://${PGUSER}:${PGPASSWORD}@${PGHOST}:5432/${PGDATABASE}
|
DATABASE_URL: postgres://${PGUSER}:${PGPASSWORD}@${PGHOST}:5432/${PGDATABASE}
|
||||||
REDIS_URL: redis://plane-redis:6379/
|
REDIS_URL: redis://plane-redis:6379/
|
||||||
@ -52,7 +54,6 @@ services:
|
|||||||
DEFAULT_EMAIL: ${DEFAULT_EMAIL}
|
DEFAULT_EMAIL: ${DEFAULT_EMAIL}
|
||||||
DEFAULT_PASSWORD: ${DEFAULT_PASSWORD}
|
DEFAULT_PASSWORD: ${DEFAULT_PASSWORD}
|
||||||
USE_MINIO: ${USE_MINIO}
|
USE_MINIO: ${USE_MINIO}
|
||||||
DEBUG: ${DEBUG}
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- plane-db
|
- plane-db
|
||||||
- plane-redis
|
- plane-redis
|
||||||
@ -65,6 +66,8 @@ services:
|
|||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
|
DEBUG: ${DEBUG}
|
||||||
|
SENTRY_DSN: ${SENTRY_DSN}
|
||||||
DJANGO_SETTINGS_MODULE: plane.settings.production
|
DJANGO_SETTINGS_MODULE: plane.settings.production
|
||||||
DATABASE_URL: postgres://${PGUSER}:${PGPASSWORD}@${PGHOST}:5432/${PGDATABASE}
|
DATABASE_URL: postgres://${PGUSER}:${PGPASSWORD}@${PGHOST}:5432/${PGDATABASE}
|
||||||
REDIS_URL: redis://plane-redis:6379/
|
REDIS_URL: redis://plane-redis:6379/
|
||||||
@ -89,7 +92,6 @@ services:
|
|||||||
DEFAULT_EMAIL: ${DEFAULT_EMAIL}
|
DEFAULT_EMAIL: ${DEFAULT_EMAIL}
|
||||||
DEFAULT_PASSWORD: ${DEFAULT_PASSWORD}
|
DEFAULT_PASSWORD: ${DEFAULT_PASSWORD}
|
||||||
USE_MINIO: ${USE_MINIO}
|
USE_MINIO: ${USE_MINIO}
|
||||||
DEBUG: ${DEBUG}
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- plane-api
|
- plane-api
|
||||||
- plane-db
|
- plane-db
|
||||||
|
@ -38,6 +38,7 @@ services:
|
|||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
DEBUG: ${DEBUG}
|
DEBUG: ${DEBUG}
|
||||||
|
SENTRY_DSN: ${SENTRY_DSN}
|
||||||
DJANGO_SETTINGS_MODULE: plane.settings.production
|
DJANGO_SETTINGS_MODULE: plane.settings.production
|
||||||
DATABASE_URL: postgres://${PGUSER}:${PGPASSWORD}@${PGHOST}:5432/${PGDATABASE}
|
DATABASE_URL: postgres://${PGUSER}:${PGPASSWORD}@${PGHOST}:5432/${PGDATABASE}
|
||||||
REDIS_URL: redis://plane-redis:6379/
|
REDIS_URL: redis://plane-redis:6379/
|
||||||
@ -80,6 +81,7 @@ services:
|
|||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
DEBUG: ${DEBUG}
|
DEBUG: ${DEBUG}
|
||||||
|
SENTRY_DSN: ${SENTRY_DSN}
|
||||||
DJANGO_SETTINGS_MODULE: plane.settings.production
|
DJANGO_SETTINGS_MODULE: plane.settings.production
|
||||||
DATABASE_URL: postgres://${PGUSER}:${PGPASSWORD}@${PGHOST}:5432/${PGDATABASE}
|
DATABASE_URL: postgres://${PGUSER}:${PGPASSWORD}@${PGHOST}:5432/${PGDATABASE}
|
||||||
REDIS_URL: redis://plane-redis:6379/
|
REDIS_URL: redis://plane-redis:6379/
|
||||||
|
Loading…
Reference in New Issue
Block a user